1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rasqal_bindings.c - Rasqal result bindings class
4 *
5 * Copyright (C) 2010-2013, 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 #include <stdarg.h>
38
39 #include "rasqal.h"
40 #include "rasqal_internal.h"
41
42
43 /*
44 * rasqal_new_bindings:
45 * @query: rasqal query
46 * @variables: sequence of variables
47 * @rows: sequence of #rasqal_row (or NULL)
48 *
49 * INTERNAL - Create a new bindings object.
50 *
51 * The @variables and @rows become owned by the bindings object.
52 *
53 * Return value: a new #rasqal_bindings object or NULL on failure
54 **/
55 rasqal_bindings*
rasqal_new_bindings(rasqal_query * query,raptor_sequence * variables,raptor_sequence * rows)56 rasqal_new_bindings(rasqal_query* query,
57 raptor_sequence* variables,
58 raptor_sequence* rows)
59 {
60 rasqal_bindings* bindings;
61
62 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query, rasqal_query, NULL);
63 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(variables, raptor_sequence, NULL);
64
65 bindings = RASQAL_CALLOC(rasqal_bindings*, 1, sizeof(*bindings));
66 if(!bindings)
67 return NULL;
68
69 bindings->usage = 1;
70 bindings->query = query;
71 bindings->variables = variables;
72 bindings->rows = rows;
73
74 return bindings;
75 }
76
77
78
79 /*
80 * rasqal_new_bindings_from_bindings:
81 * @bindings: #rasqal_bindings to copy
82 *
83 * INTERNAL - Copy Constructor - Create a new Rasqal bindings from an existing one
84 *
85 * This adds a new reference to the bindings, it does not do a deep copy
86 *
87 * Return value: a new #rasqal_bindings or NULL on failure.
88 **/
89 rasqal_bindings*
rasqal_new_bindings_from_bindings(rasqal_bindings * bindings)90 rasqal_new_bindings_from_bindings(rasqal_bindings* bindings)
91 {
92 if(!bindings)
93 return NULL;
94
95 bindings->usage++;
96
97 return bindings;
98 }
99
100
101 /*
102 * rasqal_new_bindings_from_var_values:
103 * @query: rasqal query
104 * @var: variable
105 * @values: sequence of #rasqal_value (or NULL)
106 *
107 * INTERNAL - Create a new bindings object for one variable with multiple bindings
108 *
109 * The @var and @values become owned by the bindings object.
110 *
111 * Return value: a new #rasqal_bindings object or NULL on failure
112 **/
113 rasqal_bindings*
rasqal_new_bindings_from_var_values(rasqal_query * query,rasqal_variable * var,raptor_sequence * values)114 rasqal_new_bindings_from_var_values(rasqal_query* query,
115 rasqal_variable* var,
116 raptor_sequence* values)
117 {
118 rasqal_bindings* bindings = NULL;
119 raptor_sequence* varlist = NULL;
120 rasqal_row* row = NULL;
121 raptor_sequence* rowlist = NULL;
122 int size = 0;
123 int i;
124
125
126 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query, rasqal_query, NULL);
127 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(var, rasqal_variable, NULL);
128
129 #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1
130 RASQAL_DEBUG1("binding ");
131 rasqal_variable_print(var, stderr);
132 fputs(" and row values ", stderr);
133 raptor_sequence_print(values, stderr);
134 fputc('\n', stderr);
135 #endif
136
137 varlist = raptor_new_sequence((raptor_data_free_handler)rasqal_free_variable,
138 (raptor_data_print_handler)rasqal_variable_print);
139 if(!varlist) {
140 RASQAL_DEBUG1("Cannot create varlist sequence");
141 goto tidy;
142 }
143
144 if(raptor_sequence_push(varlist, var)) {
145 RASQAL_DEBUG1("varlist sequence push failed");
146 goto tidy;
147 }
148 var = NULL;
149
150 if(values)
151 size = raptor_sequence_size(values);
152
153 row = rasqal_new_row_for_size(query->world, size);
154 if(!row) {
155 RASQAL_DEBUG1("cannot create row");
156 goto tidy;
157 }
158
159 for(i = 0; i < size; i++) {
160 rasqal_literal* value = (rasqal_literal*)raptor_sequence_get_at(values, i);
161 rasqal_row_set_value_at(row, i, value);
162 }
163
164 rowlist = raptor_new_sequence((raptor_data_free_handler)rasqal_free_row,
165 (raptor_data_print_handler)rasqal_row_print);
166 if(!rowlist) {
167 RASQAL_DEBUG1("cannot create rowlist sequence");
168 goto tidy;
169 }
170
171 if(raptor_sequence_push(rowlist, row)) {
172 RASQAL_DEBUG1("rowlist sequence push failed");
173 goto tidy;
174 }
175 row = NULL;
176
177 bindings = rasqal_new_bindings(query, varlist, rowlist);
178 varlist = NULL; rowlist = NULL;
179
180 tidy:
181 if(row)
182 rasqal_free_row(row);
183 if(rowlist)
184 raptor_free_sequence(rowlist);
185 if(varlist)
186 raptor_free_sequence(varlist);
187 if(var)
188 rasqal_free_variable(var);
189 if(values)
190 raptor_free_sequence(values);
191
192 return bindings;
193 }
194
195
196 /*
197 * rasqal_free_bindings:
198 * @bindings: #rasqal_bindings object
199 *
200 * INTERNAL - Free a bindings object.
201 *
202 **/
203 void
rasqal_free_bindings(rasqal_bindings * bindings)204 rasqal_free_bindings(rasqal_bindings* bindings)
205 {
206 if(!bindings)
207 return;
208
209 if(--bindings->usage)
210 return;
211
212 raptor_free_sequence(bindings->variables);
213 if(bindings->rows)
214 raptor_free_sequence(bindings->rows);
215
216 RASQAL_FREE(rasqal_bindings, bindings);
217 }
218
219
220 /*
221 * rasqal_bindings_print:
222 * @bindings: the #rasqal_bindings object
223 * @fh: the FILE* handle to print to
224 *
225 * INTERNAL - Print a #rasqal_bindings in a debug format.
226 *
227 * The print debug format may change in any release.
228 *
229 * Return value: non-0 on failure
230 **/
231 int
rasqal_bindings_print(rasqal_bindings * bindings,FILE * fh)232 rasqal_bindings_print(rasqal_bindings* bindings, FILE* fh)
233 {
234 int i;
235
236 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(bindings, rasqal_bindings, 1);
237 RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(fh, FILE*, 1);
238
239 fputs("\n variables: ", fh);
240 raptor_sequence_print(bindings->variables, fh);
241 fputs("\n rows: [\n ", fh);
242
243 if(bindings->rows) {
244 for(i = 0; i < raptor_sequence_size(bindings->rows); i++) {
245 rasqal_row* row;
246 row = (rasqal_row*)raptor_sequence_get_at(bindings->rows, i);
247 if(i > 0)
248 fputs("\n ", fh);
249 rasqal_row_print(row, fh);
250 }
251 }
252 fputs("\n ]\n", fh);
253
254 return 0;
255 }
256
257 /*
258 * rasqal_bindings_get_row:
259 * @bindings: the #rasqal_bindings object
260 * @offset: row offset into bindings (0+)
261 *
262 * INTERNAL - get a row from a binding at the given offset
263 *
264 * Return value: new row or NULL if out of range
265 */
266 rasqal_row*
rasqal_bindings_get_row(rasqal_bindings * bindings,int offset)267 rasqal_bindings_get_row(rasqal_bindings* bindings, int offset)
268 {
269 rasqal_row* row = NULL;
270
271 if(bindings->rows) {
272 row = (rasqal_row*)raptor_sequence_get_at(bindings->rows, offset);
273 if(row)
274 row = rasqal_new_row_from_row(row);
275 }
276
277 return row;
278 }
279