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