1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rasqal_rowsource_service.c - Rasqal SERVICE rowsource class
4 *
5 * Copyright (C) 2011, David Beckett http://www.dajobe.org/
6 *
7 * This package is Free Software and part of Redland http://librdf.org/
8 *
9 * It is licensed under the following three licenses as alternatives:
10 * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
11 * 2. GNU General Public License (GPL) V2 or any newer version
12 * 3. Apache License, V2.0 or any newer version
13 *
14 * You may not use this file except in compliance with at least one of
15 * the above three licenses.
16 *
17 * See LICENSE.html or LICENSE.txt at the top of this package for the
18 * complete terms and further detail along with the license texts for
19 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
20 *
21 */
22
23
24 #ifdef HAVE_CONFIG_H
25 #include <rasqal_config.h>
26 #endif
27
28 #ifdef WIN32
29 #include <win32_rasqal_config.h>
30 #endif
31
32 #include <stdio.h>
33 #include <string.h>
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37
38 #include <raptor.h>
39
40 #include "rasqal.h"
41 #include "rasqal_internal.h"
42
43
44 #ifndef STANDALONE
45
46 typedef struct
47 {
48 rasqal_service* svc;
49 rasqal_query* query;
50 rasqal_rowsource* rowsource;
51 int count;
52 /* bit flags; currently using RASQAL_ENGINE_BITFLAG_SILENT */
53 unsigned int flags;
54 } rasqal_service_rowsource_context;
55
56
57 static int
rasqal_service_rowsource_init(rasqal_rowsource * rowsource,void * user_data)58 rasqal_service_rowsource_init(rasqal_rowsource* rowsource, void *user_data)
59 {
60 rasqal_service_rowsource_context* con;
61
62 con = (rasqal_service_rowsource_context*)user_data;
63
64 con->rowsource = rasqal_service_execute_as_rowsource(con->svc,
65 con->query->vars_table);
66
67 if(!con->rowsource) {
68 /* Silent errors return an empty rowsource */
69
70 if(con->flags & RASQAL_ENGINE_BITFLAG_SILENT) {
71 con->rowsource = rasqal_new_empty_rowsource(con->query->world,
72 con->query);
73 return 0;
74 }
75
76 return 1;
77 }
78
79 return 0;
80 }
81
82
83 static int
rasqal_service_rowsource_finish(rasqal_rowsource * rowsource,void * user_data)84 rasqal_service_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
85 {
86 rasqal_service_rowsource_context* con;
87
88 con = (rasqal_service_rowsource_context*)user_data;
89
90 if(con->svc)
91 rasqal_free_service(con->svc);
92
93 if(con->rowsource)
94 rasqal_free_rowsource(con->rowsource);
95
96 RASQAL_FREE(rasqal_service_rowsource_context, con);
97
98 return 0;
99 }
100
101 static int
rasqal_service_rowsource_ensure_variables(rasqal_rowsource * rowsource,void * user_data)102 rasqal_service_rowsource_ensure_variables(rasqal_rowsource* rowsource,
103 void *user_data)
104 {
105 rasqal_service_rowsource_context* con;
106 int rc;
107
108 con = (rasqal_service_rowsource_context*)user_data;
109
110 rc = rasqal_rowsource_ensure_variables(con->rowsource);
111 if(rc)
112 return rc;
113 /* copy in variables from format rowsource */
114 rc = rasqal_rowsource_copy_variables(rowsource, con->rowsource);
115
116 return rc;
117 }
118
119 static rasqal_row*
rasqal_service_rowsource_read_row(rasqal_rowsource * rowsource,void * user_data)120 rasqal_service_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data)
121 {
122 rasqal_service_rowsource_context* con;
123
124 con = (rasqal_service_rowsource_context*)user_data;
125
126 return rasqal_rowsource_read_row(con->rowsource);
127 }
128
129 static raptor_sequence*
rasqal_service_rowsource_read_all_rows(rasqal_rowsource * rowsource,void * user_data)130 rasqal_service_rowsource_read_all_rows(rasqal_rowsource* rowsource,
131 void *user_data)
132 {
133 rasqal_service_rowsource_context* con;
134
135 con = (rasqal_service_rowsource_context*)user_data;
136
137 return rasqal_rowsource_read_all_rows(con->rowsource);
138 }
139
140 static const rasqal_rowsource_handler rasqal_service_rowsource_handler = {
141 /* .version = */ 1,
142 "service",
143 /* .init = */ rasqal_service_rowsource_init,
144 /* .finish = */ rasqal_service_rowsource_finish,
145 /* .ensure_variables = */ rasqal_service_rowsource_ensure_variables,
146 /* .read_row = */ rasqal_service_rowsource_read_row,
147 /* .read_all_rows = */ rasqal_service_rowsource_read_all_rows,
148 /* .reset = */ NULL,
149 /* .set_preserve = */ NULL,
150 /* .get_inner_rowsource = */ NULL,
151 /* .set_origin = */ NULL,
152 };
153
154
155 /**
156 * rasqal_new_service_rowsource:
157 * @world: world object
158 * @query: query object
159 * @service_uri: service URI
160 * @query_string: query to send to service
161 * @data_graphs: sequence of data graphs (or NULL)
162 * @rs_flags: service rowsource flags
163 *
164 * INTERNAL - create a new rowsource that takes rows from a service
165 *
166 * All arguments are copied.
167 *
168 * Return value: new rowsource or NULL on failure
169 */
170 rasqal_rowsource*
rasqal_new_service_rowsource(rasqal_world * world,rasqal_query * query,raptor_uri * service_uri,const unsigned char * query_string,raptor_sequence * data_graphs,unsigned int rs_flags)171 rasqal_new_service_rowsource(rasqal_world *world, rasqal_query* query,
172 raptor_uri* service_uri,
173 const unsigned char* query_string,
174 raptor_sequence* data_graphs,
175 unsigned int rs_flags)
176 {
177 rasqal_service_rowsource_context* con = NULL;
178 rasqal_service* svc = NULL;
179 int flags = 0;
180 int silent = (rs_flags & RASQAL_ENGINE_BITFLAG_SILENT);
181
182 if(!world || !query_string)
183 goto fail;
184
185 svc = rasqal_new_service(query->world, service_uri, query_string,
186 data_graphs);
187 if(!svc) {
188 if(!silent)
189 goto fail;
190
191 /* Silent errors so tidy up and return empty rowsource */
192 RASQAL_FREE(cstring, query_string);
193 if(data_graphs)
194 raptor_free_sequence(data_graphs);
195
196 return rasqal_new_empty_rowsource(world, query);
197 }
198
199 con = RASQAL_CALLOC(rasqal_service_rowsource_context*, 1, sizeof(*con));
200 if(!con)
201 goto fail;
202
203 con->svc = svc;
204 con->query = query;
205 con->flags = rs_flags;
206
207 return rasqal_new_rowsource_from_handler(world, query,
208 con,
209 &rasqal_service_rowsource_handler,
210 query->vars_table,
211 flags);
212
213 fail:
214 if(svc)
215 rasqal_free_service(svc);
216 if(con)
217 RASQAL_FREE(rasqal_service_rowsource_context, con);
218 if(query_string)
219 RASQAL_FREE(cstring, query_string);
220 if(data_graphs)
221 raptor_free_sequence(data_graphs);
222
223 return NULL;
224 }
225
226
227 #endif /* not STANDALONE */
228
229
230
231 #ifdef STANDALONE
232
233 /* one more prototype */
234 int main(int argc, char *argv[]);
235
236 int
main(int argc,char * argv[])237 main(int argc, char *argv[])
238 {
239 const char *program = rasqal_basename(argv[0]);
240 rasqal_rowsource *rowsource = NULL;
241 rasqal_world* world = NULL;
242 rasqal_query* query = NULL;
243 rasqal_row* row = NULL;
244 int count;
245 raptor_sequence* seq = NULL;
246 int failures = 0;
247 raptor_uri* service_uri;
248 const unsigned char* query_string;
249 raptor_sequence* data_graphs = NULL;
250 unsigned int rs_flags = 0;
251
252 world = rasqal_new_world();
253 if(!world || rasqal_world_open(world)) {
254 fprintf(stderr, "%s: rasqal_world init failed\n", program);
255 return(1);
256 }
257
258 query = rasqal_new_query(world, "sparql", NULL);
259
260 service_uri = raptor_new_uri(world->raptor_world_ptr,
261 (const unsigned char *)"http://example.org/service");
262 query_string = (const unsigned char*)"SELECT * WHERE { ?s ?p ?o }";
263 rowsource = rasqal_new_service_rowsource(world, query, service_uri,
264 query_string, data_graphs,
265 rs_flags);
266 if(!rowsource) {
267 fprintf(stderr, "%s: failed to create service rowsource\n", program);
268 failures++;
269 goto tidy;
270 }
271
272 row = rasqal_rowsource_read_row(rowsource);
273 if(!row) {
274 fprintf(stderr,
275 "%s: read_row failed to return a row for an service rowsource\n",
276 program);
277 failures++;
278 goto tidy;
279 }
280
281 if(row->size) {
282 fprintf(stderr,
283 "%s: read_row returned an non-service row size %d for a service stream\n",
284 program, row->size);
285 failures++;
286 goto tidy;
287 }
288
289 count = rasqal_rowsource_get_rows_count(rowsource);
290 if(count != 1) {
291 fprintf(stderr, "%s: read_rows returned count %d for a service stream\n",
292 program, count);
293 failures++;
294 goto tidy;
295 }
296
297 rasqal_free_rowsource(rowsource);
298
299 /* re-init rowsource */
300 rowsource = rasqal_new_service_rowsource(world, query, service_uri,
301 query_string, data_graphs,
302 rs_flags);
303
304 seq = rasqal_rowsource_read_all_rows(rowsource);
305 if(!seq) {
306 fprintf(stderr, "%s: read_rows returned a NULL seq for a service stream\n",
307 program);
308 failures++;
309 goto tidy;
310 }
311
312 count = raptor_sequence_size(seq);
313 if(count != 1) {
314 fprintf(stderr, "%s: read_rows returned size %d seq for a service stream\n",
315 program, count);
316 failures++;
317 goto tidy;
318 }
319
320
321 tidy:
322 if(seq)
323 raptor_free_sequence(seq);
324 if(rowsource)
325 rasqal_free_rowsource(rowsource);
326 if(query)
327 rasqal_free_query(query);
328 if(world)
329 rasqal_free_world(world);
330
331 return failures;
332 }
333
334 #endif /* STANDALONE */
335