1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * rasqal_query_results.c - Rasqal RDF Query Results
4  *
5  * Copyright (C) 2003-2009, David Beckett http://www.dajobe.org/
6  * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
7  *
8  * This package is Free Software and part of Redland http://librdf.org/
9  *
10  * It is licensed under the following three licenses as alternatives:
11  *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
12  *   2. GNU General Public License (GPL) V2 or any newer version
13  *   3. Apache License, V2.0 or any newer version
14  *
15  * You may not use this file except in compliance with at least one of
16  * the above three licenses.
17  *
18  * See LICENSE.html or LICENSE.txt at the top of this package for the
19  * complete terms and further detail along with the license texts for
20  * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
21  *
22  *
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <rasqal_config.h>
27 #endif
28 
29 #ifdef WIN32
30 #include <win32_rasqal_config.h>
31 #endif
32 
33 #include <stdio.h>
34 #include <string.h>
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
38 #include <stdarg.h>
39 
40 #include "rasqal.h"
41 #include "rasqal_internal.h"
42 
43 #ifndef STANDALONE
44 
45 /*
46  *
47  * Query Results Class Internals
48  *
49  * This class provides the abstraction for query results in different
50  * forms.  The forms can be either a sequence of variable bindings,
51  * set of RDF triples, boolean value or a syntax.
52  *
53  * Query results can be created as a result of a #rasqal_query
54  * execution using rasqal_query_execute() or as an independent result
55  * set constructed from a query results syntax such as the SPARQL XML
56  * results format via the #rasqal_query_results_formatter class.
57  *
58  * The query results constructor rasqal_new_query_results() takes
59  * a world to use, an optional query, the type of result as well
60  * as a variable table to operate on.  If the query is given, then
61  * that is used to handle limit, offset and triple construction,
62  * otherwise the result set is standalone and not associated with
63  * a query.
64  *
65  * The variables table is used for the variables that will appear in
66  * the result rows in the result set.  The query results module does
67  * not own any variable information, all API calls are delegated to
68  * the variables table.
69  *
70  * If the rasqal_new_query_results_from_query_execution() is used to
71  * make a query results from a query structure via executing the
72  * query, it initialises a execution engine via the
73  * #rasqal_query_execution_factory 'execute_init' factory method.
74  * This method also determines whether the entire results need to be
75  * (or a requested to be) obtained in one go, and if so, they are
76  * done during construction.
77  *
78  * The user API to getting query results is primarily to get variable
79  * bindings - a sequence of variable:value (also called #rasqal_row
80  * internally), RDF triples, a boolean value or a syntax.
81  *
82  * The variable bindings are generated from the execution engine by
83  * retrieving #rasqal_row either one-by-one using the get_row method
84  * or getting the entire result at once with the get_all_rows method.
85  *
86  * In the case of getting the entire result the rows are stored as a
87  * sqeuence inside the #rasqal_query_results and returned one-by-one
88  * from there, respecting any limit and offset.
89  *
90  * The RDF triples and boolean value results are generated from the
91  * variable bindings (#rasqal_row) inside this class.  The underlying
92  * execution engine only knows about rows.
93  *
94  * The class also handles several other results-specific methods such
95  * as getting variable binding names, values by name, counts of
96  * number of results, writing a query results as a syntax (in a
97  * simple fashion), read a query results from a syntax.
98  */
99 
100 static int rasqal_query_results_execute_and_store_results(rasqal_query_results* query_results);
101 static void rasqal_query_results_update_query_bindings(rasqal_query_results* query_results, rasqal_query *query);
102 
103 
104 /*
105  * A query result for some query
106  */
107 struct rasqal_query_results_s {
108   rasqal_world* world;
109 
110   /* type of query result (bindings, boolean, graph or syntax) */
111   rasqal_query_results_type type;
112 
113   /* non-0 if have read all (variable binding) results */
114   int finished;
115 
116   /* non-0 if query has been executed */
117   int executed;
118 
119   /* non 0 if query had fatal error and cannot return results */
120   int failed;
121 
122   /* query that this was executed over */
123   rasqal_query* query;
124 
125   /* how many (variable bindings) results found so far */
126   int result_count;
127 
128   /* execution data for execution engine. owned by this object */
129   void* execution_data;
130 
131   /* current row of results */
132   rasqal_row* row;
133 
134   /* boolean ASK result >0 true, 0 false or -1 uninitialised */
135   int ask_result;
136 
137   /* boolean: non-0 to store query results rather than lazy eval */
138   int store_results;
139 
140   /* current triple in the sequence of triples 'constructs' or -1 */
141   int current_triple_result;
142 
143   /* constructed triple result - shared and updated for each triple */
144   raptor_statement result_triple;
145 
146   /* sequence of stored results */
147   raptor_sequence* results_sequence;
148 
149   /* size of result row fields:
150    * row->results, row->values
151    */
152   int size;
153 
154   /* Execution engine used here */
155   const rasqal_query_execution_factory* execution_factory;
156 
157   /* Variables table for variables in result rows */
158   rasqal_variables_table* vars_table;
159 
160   /* non-0 if @vars_table has been initialized from first row */
161   int vars_table_init;
162 };
163 
164 
165 int
rasqal_init_query_results(void)166 rasqal_init_query_results(void)
167 {
168   return 0;
169 }
170 
171 
172 void
rasqal_finish_query_results(void)173 rasqal_finish_query_results(void)
174 {
175 }
176 
177 
178 /**
179  * rasqal_new_query_results2:
180  * @world: rasqal world object
181  * @query: query object (or NULL)
182  * @type: query results (expected) type
183  *
184  * Constructor - create a new query results set
185  *
186  * The @query may be NULL for result set objects that are standalone
187  * and not attached to any particular query
188  *
189  * Return value: a new query result object or NULL on failure
190  **/
191 rasqal_query_results*
rasqal_new_query_results2(rasqal_world * world,rasqal_query * query,rasqal_query_results_type type)192 rasqal_new_query_results2(rasqal_world* world,
193                           rasqal_query* query,
194                           rasqal_query_results_type type)
195 {
196   rasqal_query_results* query_results;
197 
198   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
199 
200   query_results = RASQAL_CALLOC(rasqal_query_results*, 1, sizeof(*query_results));
201   if(!query_results)
202     return NULL;
203 
204   query_results->vars_table = rasqal_new_variables_table(world);
205   if(!query_results->vars_table) {
206     RASQAL_FREE(rasqal_query_results, query_results);
207     return NULL;
208   }
209 
210   query_results->world = world;
211   query_results->type = type;
212   query_results->finished = 0;
213   query_results->executed = 0;
214   query_results->failed = 0;
215   query_results->query = query;
216   query_results->result_count = 0;
217   query_results->execution_data = NULL;
218   query_results->row = NULL;
219   query_results->ask_result = -1;
220   query_results->store_results = 0;
221   query_results->current_triple_result = -1;
222 
223   /* initialize static query_results->result_triple */
224   raptor_statement_init(&query_results->result_triple, world->raptor_world_ptr);
225 
226   query_results->results_sequence = NULL;
227   query_results->size = 0;
228 
229   return query_results;
230 }
231 
232 
233 /**
234  * rasqal_new_query_results:
235  * @world: rasqal world object
236  * @query: query object (or NULL)
237  * @type: query results (expected) type
238  * @vars_table: This parameter is *IGNORED*
239  *
240  * Constructor - create a new query results set
241  *
242  * @Deprecated for rasqal_new_query_results2() that loses the unused argument.
243  *
244  * The @query may be NULL for result set objects that are standalone
245  * and not attached to any particular query
246  *
247  * Return value: a new query result object or NULL on failure
248  **/
249 rasqal_query_results*
rasqal_new_query_results(rasqal_world * world,rasqal_query * query,rasqal_query_results_type type,rasqal_variables_table * vars_table)250 rasqal_new_query_results(rasqal_world* world,
251                          rasqal_query* query,
252                          rasqal_query_results_type type,
253                          rasqal_variables_table* vars_table)
254 {
255   return rasqal_new_query_results2(world, query, type);
256 }
257 
258 
259 /**
260  * rasqal_new_query_results_from_string:
261  * @world: rasqal world object
262  * @type: query results (expected) type; typically #RASQAL_QUERY_RESULTS_BINDINGS
263  * @base_uri: base URI of query results format (or NULL)
264  * @string: query results string
265  * @string_len: length of @string (or 0 to calculate it here)
266  *
267  * Constructor - create a new query results set from a results format string
268  *
269  * Return value: a new query result object or NULL on failure
270  **/
271 rasqal_query_results*
rasqal_new_query_results_from_string(rasqal_world * world,rasqal_query_results_type type,raptor_uri * base_uri,const char * string,size_t string_len)272 rasqal_new_query_results_from_string(rasqal_world* world,
273                                      rasqal_query_results_type type,
274                                      raptor_uri* base_uri,
275                                      const char* string,
276                                      size_t string_len)
277 {
278   int rc;
279   raptor_iostream* iostr = NULL;
280   rasqal_query_results_formatter* formatter = NULL;
281   rasqal_query_results* results = NULL;
282   raptor_world *raptor_world_ptr;
283   const char* formatter_name;
284   const unsigned char* id = NULL;
285 
286   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, rasqal_world, NULL);
287   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(string, const char*, NULL);
288 
289   if(!string_len)
290     string_len = strlen(string);
291 
292   raptor_world_ptr = rasqal_world_get_raptor(world);
293 
294   results = rasqal_new_query_results2(world, NULL, type);
295   if(!results)
296     goto failed;
297 
298   iostr = raptor_new_iostream_from_string(raptor_world_ptr,
299                                           RASQAL_GOOD_CAST(void*, string),
300                                           string_len);
301   if(!iostr)
302     goto failed;
303 
304   if(base_uri)
305     id = raptor_uri_as_string(base_uri);
306 
307   formatter_name =
308     rasqal_world_guess_query_results_format_name(world,
309                                                  base_uri,
310                                                  NULL /* mime_type */,
311                                                  RASQAL_GOOD_CAST(const unsigned char*, string),
312                                                  string_len,
313                                                  id);
314 
315   formatter = rasqal_new_query_results_formatter(world,
316                                                  formatter_name,
317                                                  NULL /* mime type */,
318                                                  NULL /* uri */);
319   if(!formatter)
320     goto failed;
321 
322   rc = rasqal_query_results_formatter_read(world, iostr, formatter,
323                                            results, base_uri);
324   if(rc)
325     goto failed;
326 
327   /* success */
328   goto tidy;
329 
330   failed:
331   if(results) {
332     rasqal_free_query_results(results);
333     results = NULL;
334   }
335 
336   tidy:
337   if(formatter)
338     rasqal_free_query_results_formatter(formatter);
339 
340   if(iostr)
341     raptor_free_iostream(iostr);
342 
343   return results;
344 }
345 
346 
347 /**
348  * rasqal_query_results_execute_with_engine:
349  * @query_results: the #rasqal_query_results object
350  * @engine: execution factory
351  * @store_results: non-0 to store query results
352  *
353  * INTERNAL - Create a new query results set executing a prepared query with the given execution engine
354  *
355  * return value: non-0 on failure
356  **/
357 int
rasqal_query_results_execute_with_engine(rasqal_query_results * query_results,const rasqal_query_execution_factory * engine,int store_results)358 rasqal_query_results_execute_with_engine(rasqal_query_results* query_results,
359                                          const rasqal_query_execution_factory* engine,
360                                          int store_results)
361 {
362   int rc = 0;
363   size_t ex_data_size;
364   rasqal_query* query;
365 
366 
367   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 1);
368 
369   query = query_results->query;
370 
371   if(query->failed)
372     return 1;
373 
374   query_results->execution_factory = engine;
375 
376   /* set executed flag early to enable cleanup on error */
377   query_results->executed = 1;
378 
379   /* ensure stored results are present if ordering or distincting are being done */
380   query_results->store_results = (store_results ||
381                                   rasqal_query_get_order_conditions_sequence(query) ||
382                                   rasqal_query_get_distinct(query));
383 
384   ex_data_size = query_results->execution_factory->execution_data_size;
385   if(ex_data_size > 0) {
386     query_results->execution_data = RASQAL_CALLOC(void*, 1, ex_data_size);
387 
388     if(!query_results->execution_data)
389       return 1;
390   } else
391     query_results->execution_data = NULL;
392 
393   /* Update the current datetime once per query execution */
394   rasqal_world_reset_now(query->world);
395 
396   if(query_results->execution_factory->execute_init) {
397     rasqal_engine_error execution_error = RASQAL_ENGINE_OK;
398     int execution_flags = 0;
399 
400     if(query_results->store_results)
401       execution_flags |= 1;
402 
403     rc = query_results->execution_factory->execute_init(query_results->execution_data, query, query_results, execution_flags, &execution_error);
404 
405     if(rc || execution_error != RASQAL_ENGINE_OK) {
406       query_results->failed = 1;
407       return 1;
408     }
409   }
410 
411 #ifdef RASQAL_DEBUG
412   RASQAL_DEBUG1("After execute_init, query is now:\n");
413   rasqal_query_print(query, stderr);
414 #endif
415 
416   /* Choose either to execute all now and store OR do it on demand (lazy) */
417   if(query_results->store_results)
418     rc = rasqal_query_results_execute_and_store_results(query_results);
419 
420   return rc;
421 }
422 
423 
424 /**
425  * rasqal_free_query_results:
426  * @query_results: #rasqal_query_results object
427  *
428  * Destructor - destroy a rasqal_query_results.
429  *
430  **/
431 void
rasqal_free_query_results(rasqal_query_results * query_results)432 rasqal_free_query_results(rasqal_query_results* query_results)
433 {
434   rasqal_query* query;
435 
436   if(!query_results)
437     return;
438 
439   query = query_results->query;
440 
441   if(query_results->executed) {
442     if(query_results->execution_factory->execute_finish) {
443       rasqal_engine_error execution_error = RASQAL_ENGINE_OK;
444 
445       query_results->execution_factory->execute_finish(query_results->execution_data, &execution_error);
446       /* ignoring failure of execute_finish */
447     }
448   }
449 
450   if(query_results->execution_data)
451     RASQAL_FREE(rasqal_engine_execution_data, query_results->execution_data);
452 
453   if(query_results->row)
454     rasqal_free_row(query_results->row);
455 
456   if(query_results->results_sequence)
457     raptor_free_sequence(query_results->results_sequence);
458 
459   /* free terms owned by static query_results->result_triple */
460   raptor_free_statement(&query_results->result_triple);
461 
462   if(query_results->vars_table)
463     rasqal_free_variables_table(query_results->vars_table);
464 
465   if(query)
466     rasqal_query_remove_query_result(query, query_results);
467 
468   RASQAL_FREE(rasqal_query_results, query_results);
469 }
470 
471 
472 /**
473  * rasqal_query_results_get_query:
474  * @query_results: #rasqal_query_results object
475  *
476  * Get thq query associated with this query result
477  *
478  * Return value: shared pointer to query object
479  **/
480 rasqal_query*
rasqal_query_results_get_query(rasqal_query_results * query_results)481 rasqal_query_results_get_query(rasqal_query_results* query_results)
482 {
483   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);
484 
485   return query_results->query;
486 }
487 
488 
489 /**
490  * rasqal_query_results_get_type:
491  * @query_results: #rasqal_query_results object
492  *
493  * Get query results type
494  *
495  * Return value: non-0 if true
496  **/
497 rasqal_query_results_type
rasqal_query_results_get_type(rasqal_query_results * query_results)498 rasqal_query_results_get_type(rasqal_query_results* query_results)
499 {
500   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, (rasqal_query_results_type)0);
501 
502   return query_results->type;
503 }
504 
505 
506 static const char* const rasqal_query_results_type_labels[RASQAL_QUERY_RESULTS_LAST + 1] = {
507   "Bindings",
508   "Boolean",
509   "Graph",
510   "Syntax",
511   "Unknown"
512 };
513 
514 
515 
516 /**
517  * rasqal_query_results_type_label:
518  * @type: #rasqal_query_results_type type
519  *
520  * Get a label for a query results type
521  *
522  * Return value: label or NULL on failure (invalid type)
523  **/
524 const char*
rasqal_query_results_type_label(rasqal_query_results_type type)525 rasqal_query_results_type_label(rasqal_query_results_type type)
526 {
527   if(type > RASQAL_QUERY_RESULTS_LAST)
528     type = RASQAL_QUERY_RESULTS_UNKNOWN;
529 
530   return rasqal_query_results_type_labels[RASQAL_GOOD_CAST(int, type)];
531 }
532 
533 
534 /**
535  * rasqal_query_results_is_bindings:
536  * @query_results: #rasqal_query_results object
537  *
538  * Test if rasqal_query_results is variable bindings format.
539  *
540  * Return value: non-0 if true
541  **/
542 int
rasqal_query_results_is_bindings(rasqal_query_results * query_results)543 rasqal_query_results_is_bindings(rasqal_query_results* query_results)
544 {
545   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 0);
546 
547   return (query_results->type == RASQAL_QUERY_RESULTS_BINDINGS);
548 }
549 
550 
551 /**
552  * rasqal_query_results_is_boolean:
553  * @query_results: #rasqal_query_results object
554  *
555  * Test if rasqal_query_results is boolean format.
556  *
557  * Return value: non-0 if true
558  **/
559 int
rasqal_query_results_is_boolean(rasqal_query_results * query_results)560 rasqal_query_results_is_boolean(rasqal_query_results* query_results)
561 {
562   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 0);
563 
564   return (query_results->type == RASQAL_QUERY_RESULTS_BOOLEAN);
565 }
566 
567 
568 /**
569  * rasqal_query_results_is_graph:
570  * @query_results: #rasqal_query_results object
571  *
572  * Test if rasqal_query_results is RDF graph format.
573  *
574  * Return value: non-0 if true
575  **/
576 int
rasqal_query_results_is_graph(rasqal_query_results * query_results)577 rasqal_query_results_is_graph(rasqal_query_results* query_results)
578 {
579   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 0);
580 
581   return (query_results->type == RASQAL_QUERY_RESULTS_GRAPH);
582 }
583 
584 
585 /**
586  * rasqal_query_results_is_syntax:
587  * @query_results: #rasqal_query_results object
588  *
589  * Test if the rasqal_query_results is a syntax.
590  *
591  * Many of the query results may be formatted as a syntax using the
592  * #rasqal_query_formatter class however this function returns true
593  * if a syntax result was specifically requested.
594  *
595  * Return value: non-0 if true
596  **/
597 int
rasqal_query_results_is_syntax(rasqal_query_results * query_results)598 rasqal_query_results_is_syntax(rasqal_query_results* query_results)
599 {
600   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 0);
601 
602   return (query_results->type == RASQAL_QUERY_RESULTS_SYNTAX);
603 }
604 
605 
606 /**
607  * rasqal_query_check_limit_offset_core:
608  * @result_offset: offset to check
609  * @limit: limit
610  * @offset: offset
611  *
612  * INTERNAL - Check the result_offset is in the limit and offset range if any.
613  *
614  * Return value: before range -1, in range 0, after range 1
615  */
616 int
rasqal_query_check_limit_offset_core(int result_offset,int limit,int offset)617 rasqal_query_check_limit_offset_core(int result_offset,
618                                      int limit,
619                                      int offset)
620 {
621   if(result_offset < 0)
622     return -1;
623 
624   if(offset > 0) {
625     /* offset */
626     if(result_offset <= offset)
627       return -1;
628 
629     if(limit >= 0) {
630       /* offset and limit */
631       if(result_offset > (offset + limit)) {
632         return 1;
633       }
634     }
635 
636   } else if(limit >= 0) {
637     /* limit */
638     if(result_offset > limit) {
639       return 1;
640     }
641   }
642 
643   return 0;
644 }
645 
646 
647 /**
648  * rasqal_query_check_limit_offset:
649  * @query_results: query results object
650  * @result_offset: offset to check
651  *
652  * INTERNAL - Check the query result count is in the limit and offset range if any.
653  *
654  * Return value: before range -1, in range 0, after range 1
655  */
656 int
rasqal_query_check_limit_offset(rasqal_query * query,int result_offset)657 rasqal_query_check_limit_offset(rasqal_query* query,
658                                 int result_offset)
659 {
660   int limit;
661   int offset;
662 
663   if(!query)
664     return 0;
665 
666   if(result_offset < 0)
667     return -1;
668 
669   limit = rasqal_query_get_limit(query);
670 
671   /* Ensure ASK queries never do more than one result */
672   if(query->verb == RASQAL_QUERY_VERB_ASK)
673     limit = 1;
674 
675   offset = rasqal_query_get_offset(query);
676 
677   return rasqal_query_check_limit_offset_core(result_offset, limit, offset);
678 }
679 
680 
681 /**
682  * rasqal_query_results_get_row_from_saved:
683  * @query_results: Query results to execute
684  *
685  * INTERNAL - Get next result row from a stored query result sequence
686  *
687  * Return value: result row or NULL if finished or failed
688  */
689 static rasqal_row*
rasqal_query_results_get_row_from_saved(rasqal_query_results * query_results)690 rasqal_query_results_get_row_from_saved(rasqal_query_results* query_results)
691 {
692   rasqal_query* query = query_results->query;
693   int size;
694   rasqal_row* row = NULL;
695 
696   size = raptor_sequence_size(query_results->results_sequence);
697 
698   while(1) {
699     int check;
700 
701     if(query_results->result_count >= size) {
702       query_results->finished = 1;
703       break;
704     }
705 
706     query_results->result_count++;
707 
708     check = rasqal_query_check_limit_offset(query, query_results->result_count);
709 
710     /* finished if beyond result range */
711     if(check > 0) {
712       query_results->finished = 1;
713       query_results->result_count--;
714       break;
715     }
716 
717     /* continue if before start of result range */
718     if(check < 0)
719       continue;
720 
721     /* else got result */
722     row = (rasqal_row*)raptor_sequence_get_at(query_results->results_sequence,
723                                               query_results->result_count - 1);
724 
725     if(row) {
726       row = rasqal_new_row_from_row(row);
727 
728       /* stored results may not be canonicalized yet - do it lazily */
729       rasqal_row_to_nodes(row);
730 
731       query_results->row = row;
732 
733       if(query && query->constructs)
734         rasqal_query_results_update_query_bindings(query_results, query);
735     }
736     break;
737   }
738 
739   return row;
740 }
741 
742 
743 /**
744  * rasqal_query_results_ensure_have_row_internal:
745  * @query_results: #rasqal_query_results query_results
746  *
747  * INTERNAL - Ensure there is a row in the query results by getting it from the generator/stored list
748  *
749  * If one already is held, nothing is done.  It is assumed
750  * that @query_results is not NULL and the query is neither finished
751  * nor failed.
752  *
753  * Return value: non-0 if failed or results exhausted
754  **/
755 static int
rasqal_query_results_ensure_have_row_internal(rasqal_query_results * query_results)756 rasqal_query_results_ensure_have_row_internal(rasqal_query_results* query_results)
757 {
758   /* already have row */
759   if(query_results->row)
760     return 0;
761 
762   if(query_results->results_sequence) {
763     query_results->row = rasqal_query_results_get_row_from_saved(query_results);
764   } else if(query_results->execution_factory &&
765             query_results->execution_factory->get_row) {
766     rasqal_engine_error execution_error = RASQAL_ENGINE_OK;
767 
768     /* handle limit/offset for incremental get_row() */
769     while(1) {
770       int check;
771 
772       query_results->row = query_results->execution_factory->get_row(query_results->execution_data, &execution_error);
773       if(execution_error == RASQAL_ENGINE_FAILED) {
774         query_results->failed = 1;
775         break;
776       }
777 
778       if(execution_error != RASQAL_ENGINE_OK)
779         break;
780 
781       query_results->result_count++;
782 
783       check = rasqal_query_check_limit_offset(query_results->query,
784                                               query_results->result_count);
785 
786       /* finished if beyond result range */
787       if(check > 0) {
788         query_results->finished = 1;
789         query_results->result_count--;
790 
791         /* empty row to trigger finished */
792         rasqal_free_row(query_results->row); query_results->row = NULL;
793         break;
794       }
795 
796       /* continue if before start of result range */
797       if(check < 0) {
798         /* empty row because continuing */
799         rasqal_free_row(query_results->row); query_results->row = NULL;
800         continue;
801       }
802 
803       /* got a row */
804       break;
805 
806     } /* end while */
807 
808   }
809 
810   if(query_results->row) {
811     rasqal_row_to_nodes(query_results->row);
812     query_results->size = query_results->row->size;
813   } else
814     query_results->finished = 1;
815 
816   if(query_results->row && !query_results->vars_table_init) {
817     /* build variables table once from first row seen */
818     int i;
819 
820     query_results->vars_table_init = 1;
821 
822     for(i = 0; 1; i++) {
823       rasqal_variable* v;
824 
825       v = rasqal_row_get_variable_by_offset(query_results->row, i);
826       if(!v)
827         break;
828 
829       v = rasqal_variables_table_add2(query_results->vars_table,
830                                       v->type,
831                                       v->name, /* name len */ 0,
832                                       /* value */ NULL);
833       rasqal_free_variable(v);
834     }
835   }
836 
837   return (query_results->row == NULL);
838 }
839 
840 
841 /**
842  * rasqal_query_results_get_current_row:
843  * @query_results: query results object
844  *
845  * INTERNAL - Get the current query result as a row of values
846  *
847  * The returned row is shared and owned by query_results
848  *
849  * Return value: result row or NULL on failure
850  */
851 rasqal_row*
rasqal_query_results_get_current_row(rasqal_query_results * query_results)852 rasqal_query_results_get_current_row(rasqal_query_results* query_results)
853 {
854   if(!query_results || query_results->failed || query_results->finished)
855     return NULL;
856 
857   if(!rasqal_query_results_is_bindings(query_results))
858     return NULL;
859 
860   /* ensure we have a row */
861   rasqal_query_results_ensure_have_row_internal(query_results);
862 
863   return query_results->row;
864 }
865 
866 
867 /**
868  * rasqal_query_results_get_count:
869  * @query_results: #rasqal_query_results query_results
870  *
871  * Get number of bindings so far.
872  *
873  * Return value: number of bindings found so far or < 0 on failure
874  **/
875 int
rasqal_query_results_get_count(rasqal_query_results * query_results)876 rasqal_query_results_get_count(rasqal_query_results* query_results)
877 {
878   rasqal_query* query;
879   int offset = -1;
880 
881   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, -1);
882 
883   if(query_results->failed)
884     return -1;
885 
886   if(!rasqal_query_results_is_bindings(query_results))
887     return -1;
888 
889   query = query_results->query;
890 
891   if(query)
892     offset = rasqal_query_get_offset(query);
893 
894   if(query && offset > 0)
895     return query_results->result_count - offset;
896   else
897     return query_results->result_count;
898 }
899 
900 
901 /*
902  * rasqal_query_results_next_internal:
903  * @query_results: #rasqal_query_results query_results
904  *
905  * INTERNAL - Move to the next result without query verb type checking
906  *
907  * Return value: non-0 if failed or results exhausted
908  **/
909 static int
rasqal_query_results_next_internal(rasqal_query_results * query_results)910 rasqal_query_results_next_internal(rasqal_query_results* query_results)
911 {
912   if(query_results->failed || query_results->finished)
913     return 1;
914 
915   /* Remove any current row */
916   if(query_results->row) {
917     rasqal_free_row(query_results->row);
918     query_results->row = NULL;
919   }
920 
921   /* Now try to get a new one */
922   return rasqal_query_results_ensure_have_row_internal(query_results);
923 }
924 
925 
926 /**
927  * rasqal_query_results_next:
928  * @query_results: #rasqal_query_results query_results
929  *
930  * Move to the next result.
931  *
932  * Return value: non-0 if failed or results exhausted
933  **/
934 int
rasqal_query_results_next(rasqal_query_results * query_results)935 rasqal_query_results_next(rasqal_query_results* query_results)
936 {
937   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 1);
938 
939   if(!rasqal_query_results_is_bindings(query_results))
940     return 1;
941 
942   return rasqal_query_results_next_internal(query_results);
943 }
944 
945 
946 /**
947  * rasqal_query_results_finished:
948  * @query_results: #rasqal_query_results query_results
949  *
950  * Find out if binding results are exhausted.
951  *
952  * Return value: non-0 if results are finished or query failed
953  **/
954 int
rasqal_query_results_finished(rasqal_query_results * query_results)955 rasqal_query_results_finished(rasqal_query_results* query_results)
956 {
957   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 1);
958 
959   if(query_results->failed || query_results->finished)
960     return 1;
961 
962   if(!rasqal_query_results_is_bindings(query_results))
963     return 1;
964 
965   /* need to have at least tried to get a row once */
966   if(!query_results->failed && !query_results->finished)
967     rasqal_query_results_ensure_have_row_internal(query_results);
968 
969   return (query_results->failed || query_results->finished);
970 }
971 
972 
973 /**
974  * rasqal_query_results_rewind:
975  * @query_results: #rasqal_query_results query_results
976  *
977  * Rewind stored query results to start
978  *
979  * This requires rasqal_query_set_store_results() to be called before
980  * query execution.
981  *
982  * Return value: non-0 if rewinding is not available when results are not stored
983  **/
984 int
rasqal_query_results_rewind(rasqal_query_results * query_results)985 rasqal_query_results_rewind(rasqal_query_results* query_results)
986 {
987   int size;
988   int limit = -1;
989   int offset = -1;
990   rasqal_query* query;
991 
992   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 1);
993 
994   if(!query_results->results_sequence)
995     return 1;
996 
997   size = raptor_sequence_size(query_results->results_sequence);
998 
999   /* This may be NULL for a static query result */
1000   query = query_results->query;
1001 
1002   if(query) {
1003     /* If the query failed, it remains failed */
1004     if(query->failed)
1005       return 1;
1006 
1007     limit = rasqal_query_get_limit(query);
1008     offset = rasqal_query_get_offset(query);
1009   }
1010 
1011   /* reset to first result */
1012   query_results->finished = (size == 0);
1013 
1014   if(query && !limit)
1015     query_results->finished = 1;
1016 
1017   if(!query_results->finished) {
1018     /* Reset to first result, index-1 into sequence of results */
1019     query_results->result_count = 0;
1020 
1021     /* skip past any OFFSET */
1022     if(query && offset > 0) {
1023       query_results->result_count += offset;
1024 
1025       if(query_results->result_count >= size)
1026         query_results->finished = 1;
1027     }
1028 
1029   }
1030 
1031 
1032   if(query_results->finished)
1033     query_results->result_count = 0;
1034   else {
1035     if(query && query->constructs)
1036       rasqal_query_results_update_query_bindings(query_results, query);
1037   }
1038 
1039   return 0;
1040 }
1041 
1042 
1043 /**
1044  * rasqal_query_results_get_bindings:
1045  * @query_results: #rasqal_query_results query_results
1046  * @names: pointer to an array of binding names (or NULL)
1047  * @values: pointer to an array of binding value #rasqal_literal (or NULL)
1048  *
1049  * Get all binding names, values for current result.
1050  *
1051  * If names is not NULL, it is set to the address of a shared array
1052  * of names of the bindings (an output parameter).  These names
1053  * are shared and must not be freed by the caller
1054  *
1055  * If values is not NULL, it is set to the address of a shared array
1056  * of #rasqal_literal* binding values.  These values are shaerd
1057  * and must not be freed by the caller.
1058  *
1059  * Return value: non-0 if the assignment failed
1060  **/
1061 int
rasqal_query_results_get_bindings(rasqal_query_results * query_results,const unsigned char *** names,rasqal_literal *** values)1062 rasqal_query_results_get_bindings(rasqal_query_results* query_results,
1063                                   const unsigned char ***names,
1064                                   rasqal_literal ***values)
1065 {
1066   rasqal_row* row;
1067 
1068   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 1);
1069 
1070   if(!rasqal_query_results_is_bindings(query_results))
1071     return 1;
1072 
1073   row = rasqal_query_results_get_current_row(query_results);
1074 
1075   if(!row) {
1076       query_results->finished = 1;
1077       return 0;
1078   }
1079 
1080   if(names)
1081     *names = rasqal_variables_table_get_names(query_results->vars_table);
1082 
1083   if(values)
1084     *values = row->values;
1085 
1086   return 0;
1087 }
1088 
1089 
1090 /**
1091  * rasqal_query_results_get_binding_value:
1092  * @query_results: #rasqal_query_results query_results
1093  * @offset: offset of binding name into array of known names
1094  *
1095  * Get one binding value for the current result.
1096  *
1097  * Return value: a pointer to a shared #rasqal_literal binding value or NULL on failure
1098  **/
1099 rasqal_literal*
rasqal_query_results_get_binding_value(rasqal_query_results * query_results,int offset)1100 rasqal_query_results_get_binding_value(rasqal_query_results* query_results,
1101                                        int offset)
1102 {
1103   rasqal_row* row;
1104 
1105   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);
1106 
1107   if(!rasqal_query_results_is_bindings(query_results))
1108     return NULL;
1109 
1110   if(offset < 0 || offset > query_results->size-1)
1111     return NULL;
1112 
1113   row = rasqal_query_results_get_current_row(query_results);
1114   if(row)
1115     return row->values[offset];
1116 
1117   query_results->finished = 1;
1118   return NULL;
1119 }
1120 
1121 
1122 /**
1123  * rasqal_query_results_get_binding_name:
1124  * @query_results: #rasqal_query_results query_results
1125  * @offset: offset of binding name into array of known names
1126  *
1127  * Get binding name for the current result.
1128  *
1129  * Return value: a pointer to a shared copy of the binding name or NULL on failure
1130  **/
1131 const unsigned char*
rasqal_query_results_get_binding_name(rasqal_query_results * query_results,int offset)1132 rasqal_query_results_get_binding_name(rasqal_query_results* query_results,
1133                                       int offset)
1134 {
1135   rasqal_row* row;
1136   rasqal_variable* v;
1137 
1138   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);
1139 
1140   if(!rasqal_query_results_is_bindings(query_results))
1141     return NULL;
1142 
1143   row = rasqal_query_results_get_current_row(query_results);
1144   if(!row)
1145     return NULL;
1146 
1147   v = rasqal_variables_table_get(query_results->vars_table, offset);
1148   if(!v)
1149     return NULL;
1150 
1151   return v->name;
1152 }
1153 
1154 
1155 /**
1156  * rasqal_query_results_get_binding_value_by_name:
1157  * @query_results: #rasqal_query_results query_results
1158  * @name: variable name
1159  *
1160  * Get one binding value for a given name in the current result.
1161  *
1162  * Return value: a pointer to a shared #rasqal_literal binding value or NULL on failure
1163  **/
1164 rasqal_literal*
rasqal_query_results_get_binding_value_by_name(rasqal_query_results * query_results,const unsigned char * name)1165 rasqal_query_results_get_binding_value_by_name(rasqal_query_results* query_results,
1166                                                const unsigned char *name)
1167 {
1168   rasqal_row* row;
1169   rasqal_variable* v;
1170 
1171   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);
1172   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(name, char*, NULL);
1173 
1174   if(!rasqal_query_results_is_bindings(query_results))
1175     return NULL;
1176 
1177   row = rasqal_query_results_get_current_row(query_results);
1178   if(!row)
1179     return NULL;
1180 
1181   v = rasqal_variables_table_get_by_name(query_results->vars_table,
1182                                          RASQAL_VARIABLE_TYPE_NORMAL, name);
1183   if(!v)
1184     return NULL;
1185 
1186   return row->values[v->offset];
1187 }
1188 
1189 
1190 /**
1191  * rasqal_query_results_get_bindings_count:
1192  * @query_results: #rasqal_query_results query_results
1193  *
1194  * Get the number of bound variables in the result.
1195  *
1196  * Return value: <0 if failed or results exhausted
1197  **/
1198 int
rasqal_query_results_get_bindings_count(rasqal_query_results * query_results)1199 rasqal_query_results_get_bindings_count(rasqal_query_results* query_results)
1200 {
1201   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, -1);
1202 
1203   if(query_results->failed)
1204     return -1;
1205 
1206   if(!rasqal_query_results_is_bindings(query_results))
1207     return -1;
1208 
1209   /* ensures an attempt is made to get at least 1 row */
1210   rasqal_query_results_ensure_have_row_internal(query_results);
1211 
1212   return query_results->size;
1213 }
1214 
1215 
1216 static unsigned char*
rasqal_prefix_id(int prefix_id,const unsigned char * string)1217 rasqal_prefix_id(int prefix_id, const unsigned char *string)
1218 {
1219   int tmpid = prefix_id;
1220   unsigned char* buffer;
1221   size_t length = strlen(RASQAL_GOOD_CAST(const char*, string)) + 4;  /* "r" +... + "q" +... \0 */
1222 
1223   while(tmpid /= 10)
1224     length++;
1225 
1226   buffer = RASQAL_MALLOC(unsigned char*, length);
1227   if(!buffer)
1228     return NULL;
1229 
1230   sprintf(RASQAL_GOOD_CAST(char*, buffer), "r%dq%s", prefix_id, string);
1231 
1232   return buffer;
1233 }
1234 
1235 
1236 static raptor_term*
rasqal_literal_to_result_term(rasqal_query_results * query_results,rasqal_literal * l)1237 rasqal_literal_to_result_term(rasqal_query_results* query_results,
1238                               rasqal_literal* l)
1239 {
1240   rasqal_literal* nodel;
1241   raptor_term* t = NULL;
1242   unsigned char *nodeid;
1243 
1244   nodel = rasqal_literal_as_node(l);
1245   if(!nodel)
1246     return NULL;
1247 
1248   switch(nodel->type) {
1249     case RASQAL_LITERAL_URI:
1250       t = raptor_new_term_from_uri(query_results->world->raptor_world_ptr,
1251                                    nodel->value.uri);
1252       break;
1253 
1254     case RASQAL_LITERAL_BLANK:
1255       if(l->type == RASQAL_LITERAL_BLANK) {
1256         /* original was a genuine blank node not a variable with a
1257          * blank node value so make a new one every result, not every triple
1258          */
1259         nodeid = rasqal_prefix_id(query_results->result_count,
1260                                   nodel->string);
1261       } else {
1262         nodeid = RASQAL_MALLOC(unsigned char*, nodel->string_len + 1);
1263         if(nodeid)
1264           memcpy(nodeid, nodel->string, nodel->string_len + 1);
1265       }
1266 
1267       if(nodeid)
1268         l = rasqal_new_simple_literal(query_results->world,
1269                                       RASQAL_LITERAL_BLANK,
1270                                       nodeid);
1271 
1272       if(!nodeid || !l)
1273         goto done;
1274 
1275       t = raptor_new_term_from_blank(query_results->world->raptor_world_ptr,
1276                                      nodeid);
1277       rasqal_free_literal(l);
1278       break;
1279 
1280     case RASQAL_LITERAL_STRING:
1281       t = raptor_new_term_from_literal(query_results->world->raptor_world_ptr,
1282                                        nodel->string,
1283                                        nodel->datatype,
1284                                        RASQAL_GOOD_CAST(const unsigned char*, nodel->language));
1285       break;
1286 
1287     case RASQAL_LITERAL_QNAME:
1288     case RASQAL_LITERAL_PATTERN:
1289     case RASQAL_LITERAL_XSD_STRING:
1290     case RASQAL_LITERAL_BOOLEAN:
1291     case RASQAL_LITERAL_INTEGER:
1292     case RASQAL_LITERAL_DOUBLE:
1293     case RASQAL_LITERAL_FLOAT:
1294     case RASQAL_LITERAL_VARIABLE:
1295     case RASQAL_LITERAL_DECIMAL:
1296     case RASQAL_LITERAL_DATE:
1297     case RASQAL_LITERAL_DATETIME:
1298     case RASQAL_LITERAL_UDT:
1299     case RASQAL_LITERAL_INTEGER_SUBTYPE:
1300       /* QNames should be gone by the time expression eval happens
1301        * Everything else is removed by rasqal_literal_as_node() above.
1302        */
1303 
1304     case RASQAL_LITERAL_UNKNOWN:
1305     default:
1306       break;
1307   }
1308 
1309 
1310   done:
1311   if(nodel)
1312     rasqal_free_literal(nodel);
1313 
1314   return t;
1315 }
1316 
1317 
1318 /**
1319  * rasqal_query_results_get_triple:
1320  * @query_results: #rasqal_query_results query_results
1321  *
1322  * Get the current triple in the result.
1323  *
1324  * The return value is a shared #raptor_statement.
1325  *
1326  * Return value: #raptor_statement or NULL if failed or results exhausted
1327  **/
1328 raptor_statement*
rasqal_query_results_get_triple(rasqal_query_results * query_results)1329 rasqal_query_results_get_triple(rasqal_query_results* query_results)
1330 {
1331   rasqal_query* query;
1332   rasqal_triple *t;
1333   raptor_statement *rs = NULL;
1334 
1335   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);
1336 
1337  if(query_results->failed || query_results->finished)
1338     return NULL;
1339 
1340   if(!rasqal_query_results_is_graph(query_results))
1341     return NULL;
1342 
1343   query = query_results->query;
1344   if(!query)
1345     return NULL;
1346 
1347   if(query->verb == RASQAL_QUERY_VERB_DESCRIBE)
1348     return NULL;
1349 
1350 
1351   /* ensure we have a row to work on */
1352   if(rasqal_query_results_ensure_have_row_internal(query_results))
1353     return NULL;
1354 
1355   while(1) {
1356     int skip = 0;
1357 
1358     if(query_results->current_triple_result < 0)
1359       query_results->current_triple_result = 0;
1360 
1361     t = (rasqal_triple*)raptor_sequence_get_at(query->constructs,
1362                                                query_results->current_triple_result);
1363 
1364     rs = &query_results->result_triple;
1365 
1366     raptor_statement_clear(rs);
1367 
1368     rs->subject = rasqal_literal_to_result_term(query_results, t->subject);
1369     if(!rs->subject || rs->subject->type == RAPTOR_TERM_TYPE_LITERAL) {
1370       rasqal_log_warning_simple(query_results->world,
1371                                 RASQAL_WARNING_LEVEL_BAD_TRIPLE,
1372                                 &query->locator,
1373                                 "Triple with non-RDF subject term skipped");
1374       skip = 1;
1375     } else {
1376       rs->predicate = rasqal_literal_to_result_term(query_results, t->predicate);
1377       if(!rs->predicate || rs->predicate->type != RAPTOR_TERM_TYPE_URI) {
1378         rasqal_log_warning_simple(query_results->world,
1379                                   RASQAL_WARNING_LEVEL_BAD_TRIPLE,
1380                                   &query->locator,
1381                                   "Triple with non-RDF predicate term skipped");
1382         skip = 1;
1383       } else {
1384         rs->object = rasqal_literal_to_result_term(query_results, t->object);
1385         if(!rs->object) {
1386           rasqal_log_warning_simple(query_results->world,
1387                                     RASQAL_WARNING_LEVEL_BAD_TRIPLE,
1388                                     &query->locator,
1389                                     "Triple with non-RDF object term skipped");
1390           skip = 1;
1391         }
1392       }
1393     }
1394 
1395     if(!skip)
1396       /* got triple, return it */
1397       break;
1398 
1399     /* Have to move to next triple internally */
1400     if(rasqal_query_results_next_triple(query_results)) {
1401       /* end of results or failed */
1402       rs = NULL;
1403       break;
1404     }
1405   }
1406 
1407   return rs;
1408 }
1409 
1410 
1411 /**
1412  * rasqal_query_results_next_triple:
1413  * @query_results: #rasqal_query_results query_results
1414  *
1415  * Move to the next triple result.
1416  *
1417  * Return value: non-0 if failed or results exhausted
1418  **/
1419 int
rasqal_query_results_next_triple(rasqal_query_results * query_results)1420 rasqal_query_results_next_triple(rasqal_query_results* query_results)
1421 {
1422   rasqal_query* query;
1423   int rc = 0;
1424 
1425   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 1);
1426 
1427   if(query_results->failed || query_results->finished)
1428     return 1;
1429 
1430   if(!rasqal_query_results_is_graph(query_results))
1431     return 1;
1432 
1433   query = query_results->query;
1434   if(!query)
1435     return 1;
1436 
1437   if(query->verb == RASQAL_QUERY_VERB_DESCRIBE)
1438     return 1;
1439 
1440   if(++query_results->current_triple_result >= raptor_sequence_size(query->constructs)) {
1441     if(rasqal_query_results_next_internal(query_results))
1442       return 1;
1443 
1444     query_results->current_triple_result = -1;
1445   }
1446 
1447   return rc;
1448 }
1449 
1450 
1451 /**
1452  * rasqal_query_results_get_boolean:
1453  * @query_results: #rasqal_query_results query_results
1454  *
1455  * Get boolean query result.
1456  *
1457  * The return value is only meaningful if this is a boolean
1458  * query result - see rasqal_query_results_is_boolean()
1459  *
1460  * Return value: boolean query result - >0 is true, 0 is false, <0 on error
1461  */
1462 int
rasqal_query_results_get_boolean(rasqal_query_results * query_results)1463 rasqal_query_results_get_boolean(rasqal_query_results* query_results)
1464 {
1465   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, -1);
1466 
1467   if(query_results->failed)
1468     return -1;
1469 
1470   if(!rasqal_query_results_is_boolean(query_results))
1471     return -1;
1472 
1473   if(query_results->ask_result >= 0)
1474     return query_results->ask_result;
1475 
1476   rasqal_query_results_ensure_have_row_internal(query_results);
1477 
1478   query_results->ask_result = (query_results->result_count > 0) ? 1 : 0;
1479   query_results->finished = 1;
1480 
1481   return query_results->ask_result;
1482 }
1483 
1484 
1485 /**
1486  * rasqal_query_results_set_boolean:
1487  * @query_results: #rasqal_query_results query_results
1488  * @value: boolean value
1489  *
1490  * INTERNAL - Set boolean query result value.
1491  *
1492  * Return value: boolean query result - >0 is true, 0 is false, <0 on error
1493  */
1494 int
rasqal_query_results_set_boolean(rasqal_query_results * query_results,int value)1495 rasqal_query_results_set_boolean(rasqal_query_results* query_results, int value)
1496 {
1497   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, -1);
1498 
1499   if(query_results->failed)
1500     return -1;
1501 
1502   if(!rasqal_query_results_is_boolean(query_results))
1503     return -1;
1504 
1505   query_results->finished = 1;
1506   query_results->ask_result = value;
1507   return 0;
1508 }
1509 
1510 
1511 /**
1512  * rasqal_query_results_write:
1513  * @iostr: #raptor_iostream to write the query to
1514  * @results: #rasqal_query_results query results format
1515  * @name: format name (or NULL)
1516  * @mime_type: format mime type (or NULL)
1517  * @format_uri: #raptor_uri describing the format to write (or NULL for default)
1518  * @base_uri: #raptor_uri base URI of the output format
1519  *
1520  * Write the query results to an iostream in a format.
1521  *
1522  * This uses the #rasqal_query_results_formatter class and the
1523  * rasqal_query_results_formatter_write() method to perform the
1524  * formatting.
1525  *
1526  * Note that after calling this method, the query results will be
1527  * empty and rasqal_query_results_finished() will return true (non-0)
1528  *
1529  * See rasqal_world_get_query_results_format_description() for obtaining the
1530  * supported format names, mime_types and URIs at run time.
1531  *
1532  * Return value: non-0 on failure
1533  **/
1534 int
rasqal_query_results_write(raptor_iostream * iostr,rasqal_query_results * results,const char * name,const char * mime_type,raptor_uri * format_uri,raptor_uri * base_uri)1535 rasqal_query_results_write(raptor_iostream *iostr,
1536                            rasqal_query_results* results,
1537                            const char *name,
1538                            const char *mime_type,
1539                            raptor_uri *format_uri,
1540                            raptor_uri *base_uri)
1541 {
1542   rasqal_query_results_formatter *formatter;
1543   int status;
1544 
1545   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(iostr, raptor_iostream, 1);
1546   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(results, rasqal_query_results, 1);
1547 
1548   if(results->failed)
1549     return 1;
1550 
1551   formatter = rasqal_new_query_results_formatter(results->world,
1552                                                  name, mime_type,
1553                                                  format_uri);
1554   if(!formatter)
1555     return 1;
1556 
1557   status = rasqal_query_results_formatter_write(iostr, formatter,
1558                                                 results, base_uri);
1559 
1560   rasqal_free_query_results_formatter(formatter);
1561   return status;
1562 }
1563 
1564 
1565 /**
1566  * rasqal_query_results_read:
1567  * @iostr: #raptor_iostream to read the query from
1568  * @results: #rasqal_query_results query results format
1569  * @name: format name (or NULL)
1570  * @mime_type: format mime type (or NULL)
1571  * @format_uri: #raptor_uri describing the format to read (or NULL for default)
1572  * @base_uri: #raptor_uri base URI of the input format
1573  *
1574  * Read the query results from an iostream in a format.
1575  *
1576  * This uses the #rasqal_query_results_formatter class
1577  * and the rasqal_query_results_formatter_read() method
1578  * to perform the formatting.
1579  *
1580  * See rasqal_world_get_query_results_format_description() for
1581  * obtaining the supported format URIs at run time.
1582  *
1583  * Return value: non-0 on failure
1584  **/
1585 int
rasqal_query_results_read(raptor_iostream * iostr,rasqal_query_results * results,const char * name,const char * mime_type,raptor_uri * format_uri,raptor_uri * base_uri)1586 rasqal_query_results_read(raptor_iostream *iostr,
1587                           rasqal_query_results* results,
1588                           const char *name,
1589                           const char *mime_type,
1590                           raptor_uri *format_uri,
1591                           raptor_uri *base_uri)
1592 {
1593   rasqal_query_results_formatter *formatter;
1594   int status;
1595 
1596   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(iostr, raptor_iostream, 1);
1597   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(results, rasqal_query_results, 1);
1598 
1599   if(results->failed)
1600     return 1;
1601 
1602   formatter = rasqal_new_query_results_formatter(results->world,
1603                                                  name, mime_type,
1604                                                  format_uri);
1605   if(!formatter)
1606     return 1;
1607 
1608   status = rasqal_query_results_formatter_read(results->world, iostr, formatter,
1609                                                results, base_uri);
1610 
1611   rasqal_free_query_results_formatter(formatter);
1612   return status;
1613 }
1614 
1615 
1616 /**
1617  * rasqal_query_results_add_row:
1618  * @query_results: query results object
1619  * @row: query result row
1620  *
1621  * Add a query result row to the sequence of result rows
1622  *
1623  * Return value: non-0 on failure
1624  */
1625 int
rasqal_query_results_add_row(rasqal_query_results * query_results,rasqal_row * row)1626 rasqal_query_results_add_row(rasqal_query_results* query_results,
1627                              rasqal_row* row)
1628 {
1629   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 1);
1630   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(row, rasqal_row, 1);
1631 
1632   if(!query_results->results_sequence) {
1633     query_results->results_sequence = raptor_new_sequence((raptor_data_free_handler)rasqal_free_row, (raptor_data_print_handler)rasqal_row_print);
1634     if(!query_results->results_sequence)
1635       return 1;
1636 
1637     query_results->result_count = 0;
1638   }
1639 
1640   row->offset = raptor_sequence_size(query_results->results_sequence);
1641 
1642   return raptor_sequence_push(query_results->results_sequence, row);
1643 }
1644 
1645 
1646 /**
1647  * rasqal_query_results_execute_and_store_results:
1648  * @query_results: query results object
1649  *
1650  * INTERNAL - Store all query result (rows) immediately
1651  *
1652  * Return value: non-0 on failure
1653  */
1654 static int
rasqal_query_results_execute_and_store_results(rasqal_query_results * query_results)1655 rasqal_query_results_execute_and_store_results(rasqal_query_results* query_results)
1656 {
1657   raptor_sequence* seq = NULL;
1658 
1659   if(query_results->results_sequence)
1660      raptor_free_sequence(query_results->results_sequence);
1661 
1662   if(query_results->execution_factory->get_all_rows) {
1663     rasqal_engine_error execution_error = RASQAL_ENGINE_OK;
1664 
1665     seq = query_results->execution_factory->get_all_rows(query_results->execution_data, &execution_error);
1666     if(execution_error == RASQAL_ENGINE_FAILED)
1667       query_results->failed = 1;
1668   }
1669 
1670   query_results->results_sequence = seq;
1671 
1672   if(!seq) {
1673     query_results->finished = 1;
1674   } else
1675     rasqal_query_results_rewind(query_results);
1676 
1677   return query_results->failed;
1678 }
1679 
1680 
1681 /*
1682  * rasqal_query_results_update_query_bindings:
1683  * @query_results: query results to read from
1684  * @query: query to set bindings to
1685  *
1686  * INTERNAL - bind the query variables to the values from the current query results row
1687  *
1688  * Used to handle query CONSTRUCT
1689  */
1690 static void
rasqal_query_results_update_query_bindings(rasqal_query_results * query_results,rasqal_query * query)1691 rasqal_query_results_update_query_bindings(rasqal_query_results* query_results, rasqal_query* query)
1692 {
1693   int i;
1694   int size;
1695   rasqal_row* row;
1696 
1697   RASQAL_ASSERT_OBJECT_POINTER_RETURN(query_results, rasqal_query_results);
1698 
1699   rasqal_query_results_ensure_have_row_internal(query_results);
1700 
1701   row = query_results->row;
1702   if(!row) {
1703     query_results->finished = 1;
1704     return;
1705   }
1706 
1707   size = rasqal_variables_table_get_named_variables_count(query_results->vars_table);
1708   for(i = 0; i < size; i++) {
1709     rasqal_variable* srcv;
1710     rasqal_variable* v;
1711     /* source value is in row */
1712     rasqal_literal* value = row->values[i];
1713 
1714     /* source variable is in query results */
1715     srcv = rasqal_variables_table_get(query_results->vars_table, i);
1716 
1717     /* destination variable is in query */
1718     v = rasqal_variables_table_get_by_name(query->vars_table, srcv->type, srcv->name);
1719     if(v)
1720       rasqal_variable_set_value(v, rasqal_new_literal_from_literal(value));
1721     else {
1722       RASQAL_DEBUG2("Cannot bind query results variable %s into query", srcv->name);
1723     }
1724   }
1725 }
1726 
1727 
1728 void
rasqal_query_results_remove_query_reference(rasqal_query_results * query_results)1729 rasqal_query_results_remove_query_reference(rasqal_query_results* query_results)
1730 {
1731   rasqal_query* query;
1732 
1733   RASQAL_ASSERT_OBJECT_POINTER_RETURN(query_results, rasqal_query_results);
1734 
1735   query = query_results->query;
1736   query_results->query = NULL;
1737 
1738   rasqal_free_query(query);
1739 }
1740 
1741 
1742 rasqal_variables_table*
rasqal_query_results_get_variables_table(rasqal_query_results * query_results)1743 rasqal_query_results_get_variables_table(rasqal_query_results* query_results)
1744 {
1745   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);
1746 
1747   return query_results->vars_table;
1748 }
1749 
1750 
1751 
1752 rasqal_world*
rasqal_query_results_get_world(rasqal_query_results * query_results)1753 rasqal_query_results_get_world(rasqal_query_results* query_results)
1754 {
1755   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);
1756 
1757   return query_results->world;
1758 }
1759 
1760 
1761 /**
1762  * rasqal_query_results_get_row_by_offset:
1763  * @query_results: query result
1764  * @result_offset: index into result rows
1765  *
1766  * Get stored result row by an offset
1767  *
1768  * The result_offset index is 0-indexed into the subset of results
1769  * constrained by any query limit and offset.
1770  *
1771  * Return value: row or NULL if @result_offset is out of range
1772  */
1773 rasqal_row*
rasqal_query_results_get_row_by_offset(rasqal_query_results * query_results,int result_offset)1774 rasqal_query_results_get_row_by_offset(rasqal_query_results* query_results,
1775                                        int result_offset)
1776 {
1777   rasqal_query* query;
1778   int check;
1779   rasqal_row* row;
1780   int offset = 0;
1781 
1782   RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);
1783 
1784   if(!query_results->results_sequence)
1785     return NULL;
1786 
1787   if(result_offset < 0)
1788     return NULL;
1789 
1790   query = query_results->query;
1791   if(query)
1792     offset = rasqal_query_get_offset(query);
1793 
1794   /* Adjust 0-indexed to query results 1-indexed + query result offset */
1795   result_offset += 1 + offset;
1796 
1797   check = rasqal_query_check_limit_offset(query_results->query,
1798                                           result_offset);
1799   /* outside limit/offset range in some way */
1800   if(check < 0 || check > 0)
1801     return NULL;
1802 
1803   row = (rasqal_row*)raptor_sequence_get_at(query_results->results_sequence,
1804                                             result_offset - 1);
1805   if(row) {
1806     row = rasqal_new_row_from_row(row);
1807 
1808     /* stored results may not be canonicalized yet - do it lazily */
1809     rasqal_row_to_nodes(row);
1810   }
1811 
1812   return row;
1813 }
1814 
1815 
1816 struct rqr_context
1817 {
1818   rasqal_query_results* results;
1819 
1820   /* size of @order - number of values */
1821   int size;
1822 
1823   /* Sequence of offsets to variables in lexical order  */
1824   int* order;
1825 };
1826 
1827 
1828 /**
1829  * rasqal_query_results_sort_compare_row:
1830  * @a: pointer to address of first #row
1831  * @b: pointer to address of second #row
1832  * @arg: query results pointer
1833  *
1834  * INTERNAL - compare two pointers to #row objects with user data arg
1835  *
1836  * Suitable for use as a compare function with raptor_sort_r() or
1837  * compatible.  Used by rasqal_query_results_sort().
1838  *
1839  * Return value: <0, 0 or >0 comparison
1840  */
1841 static int
rasqal_query_results_sort_compare_row(const void * a,const void * b,void * arg)1842 rasqal_query_results_sort_compare_row(const void *a, const void *b, void *arg)
1843 {
1844   rasqal_row* row_a;
1845   rasqal_row* row_b;
1846   struct rqr_context* rqr;
1847   int result = 0;
1848 
1849   row_a = *(rasqal_row**)a;
1850   row_b = *(rasqal_row**)b;
1851   rqr = (struct rqr_context*)arg;
1852 
1853   result = rasqal_literal_array_compare_by_order(row_a->values, row_b->values,
1854                                                  rqr->order, row_a->size, 0);
1855 
1856   /* still equal?  make sort stable by using the original order */
1857   if(!result) {
1858     result = row_a->offset - row_b->offset;
1859 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
1860     RASQAL_DEBUG2("Got equality result so using offsets, returning %d\n",
1861                   result);
1862 #endif
1863   }
1864 
1865   return result;
1866 }
1867 
1868 
1869 int
rasqal_query_results_sort(rasqal_query_results * query_results)1870 rasqal_query_results_sort(rasqal_query_results* query_results)
1871 {
1872   struct rqr_context rqr;
1873 
1874   if(query_results->execution_factory && !query_results->results_sequence) {
1875     int rc;
1876 
1877     rc = rasqal_query_results_execute_and_store_results(query_results);
1878     if(rc)
1879       return rc;
1880   }
1881 
1882   rqr.results = query_results;
1883   rqr.size = query_results->size;
1884   rqr.order = rasqal_variables_table_get_order(query_results->vars_table);
1885   if(!rqr.order)
1886     return 1;
1887 
1888   if(query_results->results_sequence) {
1889     int size = raptor_sequence_size(query_results->results_sequence);
1890     if(size > 1) {
1891 #if RAPTOR_VERSION < 20015
1892       raptor_sequence *seq;
1893       void** array;
1894       size_t i;
1895 
1896       seq = raptor_new_sequence((raptor_data_free_handler)rasqal_free_row, (raptor_data_print_handler)rasqal_row_print);
1897       if(!seq) {
1898         RASQAL_FREE(int*, rqr.order);
1899         return 1;
1900       }
1901 
1902       array = rasqal_sequence_as_sorted(seq,
1903                                         rasqal_query_results_sort_compare_row,
1904                                         &rqr);
1905       if(!array) {
1906         raptor_free_sequence(seq);
1907         RASQAL_FREE(int*, rqr.order);
1908         return 1;
1909       }
1910 
1911       for(i = 0; i < RASQAL_GOOD_CAST(size_t, size); i++) {
1912         rasqal_row* row = rasqal_new_row_from_row(RASQAL_GOOD_CAST(rasqal_row*, array[i]));
1913         raptor_sequence_push(seq, row);
1914       }
1915       raptor_free_sequence(query_results->results_sequence);
1916       query_results->results_sequence = seq;
1917       RASQAL_FREE(void*, array);
1918 #else
1919       raptor_sequence_sort_r(query_results->results_sequence,
1920                              rasqal_query_results_sort_compare_row,
1921                              &rqr);
1922 #endif
1923     }
1924   }
1925 
1926   RASQAL_FREE(int*, rqr.order);
1927   return 0;
1928 }
1929 
1930 #endif /* not STANDALONE */
1931 
1932 
1933 
1934 #ifdef STANDALONE
1935 
1936 /* one more prototype */
1937 int main(int argc, char *argv[]);
1938 
1939 #define NTESTS 2
1940 
1941 const struct {
1942   const char* qr_string;
1943   int expected_vars_count;
1944   int expected_rows_count;
1945   int expected_equality;
1946 } expected_data[NTESTS] = {
1947   {
1948     "a\tb\tc\td\n\"a\"\t\"b\"\t\"c\"\t\"d\"\n",
1949     4, 1, 1
1950   },
1951   {
1952     "a,b,c,d,e,f\n\"a\",\"b\",\"c\",\"d\",\"e\",\"f\"\n",
1953     6, 1, 1
1954   }
1955 };
1956 
1957 
1958 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
1959 static void
print_bindings_results_simple(rasqal_query_results * results,FILE * output)1960 print_bindings_results_simple(rasqal_query_results *results, FILE* output)
1961 {
1962   while(!rasqal_query_results_finished(results)) {
1963     int i;
1964 
1965     fputs("row: [", output);
1966     for(i = 0; i < rasqal_query_results_get_bindings_count(results); i++) {
1967       const unsigned char *name;
1968       rasqal_literal *value;
1969 
1970       name = rasqal_query_results_get_binding_name(results, i);
1971       value = rasqal_query_results_get_binding_value(results, i);
1972 
1973       if(i > 0)
1974         fputs(", ", output);
1975 
1976       fprintf(output, "%s=", name);
1977       rasqal_literal_print(value, output);
1978     }
1979     fputs("]\n", output);
1980 
1981     rasqal_query_results_next(results);
1982   }
1983 }
1984 #endif
1985 
1986 int
main(int argc,char * argv[])1987 main(int argc, char *argv[])
1988 {
1989   const char *program = rasqal_basename(argv[0]);
1990   rasqal_world* world = NULL;
1991   raptor_world* raptor_world_ptr;
1992   int failures = 0;
1993   int i;
1994   rasqal_query_results_type type = RASQAL_QUERY_RESULTS_BINDINGS;
1995 
1996   world = rasqal_new_world(); rasqal_world_open(world);
1997 
1998   raptor_world_ptr = rasqal_world_get_raptor(world);
1999 
2000   for(i = 0; i < NTESTS; i++) {
2001     raptor_uri* base_uri = raptor_new_uri(raptor_world_ptr,
2002                                           (const unsigned char*)"http://example.org/");
2003     rasqal_query_results *qr;
2004     int expected_vars_count = expected_data[i].expected_vars_count;
2005     int vars_count;
2006 
2007     qr = rasqal_new_query_results_from_string(world,
2008                                               type,
2009                                               base_uri,
2010                                               expected_data[i].qr_string,
2011                                               0);
2012 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
2013     RASQAL_DEBUG1("Query result from string:");
2014     print_bindings_results_simple(first_qr, stderr);
2015     rasqal_query_results_rewind(first_qr);
2016 #endif
2017 
2018     raptor_free_uri(base_uri);
2019 
2020     if(!qr) {
2021       fprintf(stderr, "%s: failed to create query results\n", program);
2022       failures++;
2023     } else {
2024       rasqal_variables_table* vt;
2025 
2026       vt = rasqal_query_results_get_variables_table(qr);
2027       vars_count = rasqal_variables_table_get_named_variables_count(vt);
2028       RASQAL_DEBUG4("%s: query results test %d returned %d vars\n", program, i,
2029                     vars_count);
2030       if(vars_count != expected_vars_count) {
2031         fprintf(stderr,
2032                 "%s: FAILED query results test %d returned %d vars  expected %d vars\n",
2033                 program, i, vars_count, expected_vars_count);
2034         failures++;
2035       }
2036     }
2037 
2038     if(qr)
2039       rasqal_free_query_results(qr);
2040   }
2041 
2042   if(world)
2043     rasqal_free_world(world);
2044 
2045   return failures;
2046 }
2047 
2048 #endif /* STANDALONE */
2049