1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rasqal_rowsource_bindings.c - Rasqal bindings rows rowsource class
4 *
5 * Copyright (C) 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
38 #include <raptor.h>
39
40 #include "rasqal.h"
41 #include "rasqal_internal.h"
42
43
44 typedef struct
45 {
46 /* bindings object */
47 rasqal_bindings* bindings;
48
49 /* bindings row offset */
50 int offset;
51 } rasqal_bindings_rowsource_context;
52
53
54
55 static int
rasqal_bindings_rowsource_init(rasqal_rowsource * rowsource,void * user_data)56 rasqal_bindings_rowsource_init(rasqal_rowsource* rowsource, void *user_data)
57 {
58 rasqal_bindings_rowsource_context *con;
59
60 con = (rasqal_bindings_rowsource_context*)user_data;
61
62 con->offset = 0;
63
64 return 0;
65 }
66
67
68 static int
rasqal_bindings_rowsource_ensure_variables(rasqal_rowsource * rowsource,void * user_data)69 rasqal_bindings_rowsource_ensure_variables(rasqal_rowsource* rowsource,
70 void *user_data)
71 {
72 rasqal_bindings_rowsource_context* con;
73 raptor_sequence* vars_seq;
74 int i;
75
76 con = (rasqal_bindings_rowsource_context*)user_data;
77
78 rowsource->size = 0;
79
80 vars_seq = con->bindings->variables;
81 if(!vars_seq)
82 return 0;
83
84 for(i = 0; 1; i++) {
85 rasqal_variable* v;
86 v = (rasqal_variable*)raptor_sequence_get_at(vars_seq, i);
87 if(!v)
88 break;
89
90 if(rasqal_rowsource_add_variable(rowsource, v) < 0)
91 return 1;
92 }
93
94 return 0;
95 }
96
97
98 static int
rasqal_bindings_rowsource_finish(rasqal_rowsource * rowsource,void * user_data)99 rasqal_bindings_rowsource_finish(rasqal_rowsource* rowsource, void *user_data)
100 {
101 rasqal_bindings_rowsource_context *con;
102
103 con = (rasqal_bindings_rowsource_context*)user_data;
104
105 if(con->bindings)
106 rasqal_free_bindings(con->bindings);
107
108 RASQAL_FREE(rasqal_bindings_rowsource_context, con);
109
110 return 0;
111 }
112
113
114 static rasqal_row*
rasqal_bindings_rowsource_read_row(rasqal_rowsource * rowsource,void * user_data)115 rasqal_bindings_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data)
116 {
117 rasqal_bindings_rowsource_context *con;
118 rasqal_row *row;
119
120 con = (rasqal_bindings_rowsource_context*)user_data;
121
122 row = rasqal_bindings_get_row(con->bindings, con->offset++);
123
124 return row;
125 }
126
127
128 static int
rasqal_bindings_rowsource_reset(rasqal_rowsource * rowsource,void * user_data)129 rasqal_bindings_rowsource_reset(rasqal_rowsource* rowsource, void *user_data)
130 {
131 rasqal_bindings_rowsource_context *con;
132
133 con = (rasqal_bindings_rowsource_context*)user_data;
134
135 con->offset = 0;
136
137 return 0;
138 }
139
140
141 static const rasqal_rowsource_handler rasqal_bindings_rowsource_handler = {
142 /* .version = */ 1,
143 "bindings",
144 /* .init = */ rasqal_bindings_rowsource_init,
145 /* .finish = */ rasqal_bindings_rowsource_finish,
146 /* .ensure_variables = */ rasqal_bindings_rowsource_ensure_variables,
147 /* .read_row = */ rasqal_bindings_rowsource_read_row,
148 /* .read_all_rows = */ NULL,
149 /* .reset = */ rasqal_bindings_rowsource_reset,
150 /* .set_requirements = */ NULL,
151 /* .get_inner_rowsource = */ NULL,
152 /* .set_origin = */ NULL,
153 };
154
155
156 /**
157 * rasqal_new_bindings_rowsource:
158 * @world: world object
159 * @query: query object
160 * @rowsource: input rowsource
161 * @limit: max rows limit (or <0 for no limit)
162 * @offset: start row offset (or <0 for no offset)
163 *
164 * INTERNAL - create a new bindings (LIMIT, OFFSET) rowsource
165 *
166 * The @rowsource becomes owned by the new rowsource
167 *
168 * Return value: new rowsource or NULL on failure
169 */
170 rasqal_rowsource*
rasqal_new_bindings_rowsource(rasqal_world * world,rasqal_query * query,rasqal_bindings * bindings)171 rasqal_new_bindings_rowsource(rasqal_world *world,
172 rasqal_query *query,
173 rasqal_bindings* bindings)
174 {
175 rasqal_bindings_rowsource_context *con;
176 int flags = 0;
177
178 if(!world || !query || !bindings)
179 goto fail;
180
181 con = RASQAL_CALLOC(rasqal_bindings_rowsource_context*, 1, sizeof(*con));
182 if(!con)
183 goto fail;
184
185 con->bindings = bindings;
186 con->offset = 0;
187
188 return rasqal_new_rowsource_from_handler(world, query,
189 con,
190 &rasqal_bindings_rowsource_handler,
191 query->vars_table,
192 flags);
193
194 fail:
195 if(bindings)
196 rasqal_free_bindings(bindings);
197
198 return NULL;
199 }
200