5 #include <BindingTable.h>
9 * This state tells the "next" function that it should capture the
10 * incoming BindingTable state and provide the initial Binding of
11 * a new sucession of bindings.
15 * This state tells the "next" function that it should update the
16 * bidning table with a subsequent Binding in the current
17 * succession of bindings.
21 * This state tells the "next" function that it should just
22 * restore the Binding table to its incoming state.
27 //enum compound_state { reset, started, ended };
30 * A struct query_callbacks record defines the callbacks for a
31 * specific query type.
33 struct query_callbacks {
35 * \brief Callback function to reclaim the query memory for a
38 * \param this is the specific \ref query concerned.
40 * Ground queries recalim their own state memory. Composite
41 * queries first propagate the reclaim call to its components, and
42 * thereafter reclaim their local state memory.
44 void (*reclaim)(query *this);
45 void (*start)(query *this,BindingTable *bt,enum next_state s);
47 * \brief Callback function to update the Binding table with a
48 * succession of alternative bindings.
50 * \param this is the specific \ref query concerned.
52 * \param bt is the Binding table to set bindings in.
54 * \param s is the call "sub-command" for the function.
56 * \returns 1 if a new Binding is provided and 0 otherwise.
58 * This function is called repeatedly for successively obtaining
59 * the alternative bindings that satisfy the query. The "initial"
60 * state sub-command tells the function to capture the incoming
61 * BindingTable state so that the function can later restore it
62 * upon the "restore" sub-command. Upon the "initial" command, the
63 * function also sets up the Binding table with its first Binding
64 * alternative. This is followed by a series of "subsequent"
65 * sub-command calls for the function to change the BindingTable
66 * for its succession of Binding alternatives. The function should
67 * return 1 after any successful Binding setup, and return 0 when
68 * it cannot setup any (more) Binding.
70 int (*next)(query *this,BindingTable *bt,enum next_state state);
73 /* ==================== AssignmentQuery ==================== */
75 struct query_callbacks *def;
82 // Release any memory.
83 static void AssignmentQuery_reclaim(query *this) {
84 AssignmentQuery *q = (AssignmentQuery*) this;
89 static int AssignmentQuery_check(int arity,tuple *a,tuple *b) {
91 for ( i = 0; i < arity; i++ ) {
92 char *value = (*a)[i];
93 char *current = (*b)[i];
94 if ( value && current && current != value &&
95 strcmp( current, value ) != 0 ) {
102 static void AssignmentQuery_assign(
103 BindingTable *bt,int n,tuple *names,tuple *values,int all)
106 for ( i = 0; i < n; i++ ) {
107 if ( all || (*values)[i] ) {
108 BindingTable_set( bt, (*names)[i], (*values)[i] );
113 // Make names have given values and return 1. If any name has a
114 // different value then return 0. Values are strings.
115 static int AssignmentQuery_next(
116 query *this,BindingTable *bt,enum next_state state) {
117 AssignmentQuery *q = (AssignmentQuery*) this;
120 if ( q->saved == 0 ) {
121 q->saved = (tuple*) malloc( q->arity * sizeof( void* ) );
123 memcpy( q->saved, q->names, q->arity * sizeof( void* ) );
124 BindingTable_deref( bt, q->arity, q->saved );
125 // Check with new values
126 if ( AssignmentQuery_check( q->arity, q->values, q->saved ) ) {
127 AssignmentQuery_assign( bt, q->arity, q->names, q->values, 0 );
134 AssignmentQuery_assign( bt, q->arity, q->names, q->saved, 1 );
143 static struct query_callbacks AssignmentQuery_def = {
144 .reclaim = AssignmentQuery_reclaim,
145 .next = AssignmentQuery_next
149 * Return a query object representing an assignment of one or more
152 query *query_assign(int arity,tuple *names,tuple *values) {
153 AssignmentQuery *q = (AssignmentQuery*)
154 malloc( sizeof( AssignmentQuery ) );
155 (*q) = (AssignmentQuery) {
156 .def = &AssignmentQuery_def,
165 /* ==================== conjunction ==================== */
167 struct query_callbacks *def;
173 static void ConjunctionQuery_reclaim(query *this) {
174 ConjunctionQuery *q = (ConjunctionQuery*) this;
176 for ( i = 0; i < q->size; i++ ) {
177 q->conjuncts[i]->def->reclaim( q->conjuncts[i] );
179 free( q->conjuncts );
183 static int ConjunctionQuery_next(
184 query *this,BindingTable *bt,enum next_state state)
186 ConjunctionQuery *q = (ConjunctionQuery*) this;
188 enum next_state s = subsequent;
196 while ( i < q->size ) {
197 if ( q->conjuncts[i]->def->next( q->conjuncts[i], bt, s ) ) {
200 q->conjuncts[i]->def->next( q->conjuncts[i], bt, restore );
202 // The first conjunct now exhausted
211 for ( ; i >= 0; i-- ) {
212 q->conjuncts[i]->def->next( q->conjuncts[i], bt, restore );
221 static struct query_callbacks ConjunctionQuery_def = {
222 .reclaim = ConjunctionQuery_reclaim,
223 .next = ConjunctionQuery_next
226 query *query_and(int n,...) {
228 ConjunctionQuery *q = (ConjunctionQuery *)
229 malloc( sizeof( ConjunctionQuery ) );
230 (*q) = (ConjunctionQuery) {
231 .def = &ConjunctionQuery_def,
234 .conjuncts = (query**) malloc( n * sizeof( query* ) )
238 for ( i = 0; i < n; i++ ) {
239 q->conjuncts[i] = va_arg( args, query* );
245 /* ==================== disjunction ==================== */
247 struct query_callbacks *def;
253 static void DisjunctionQuery_reclaim(query *this) {
254 DisjunctionQuery *q = (DisjunctionQuery*) this;
256 for ( i = 0; i < q->size; i++ ) {
257 q->disjuncts[i]->def->reclaim( q->disjuncts[i] );
259 free( q->disjuncts );
263 static int DisjunctionQuery_next(
264 query *this,BindingTable *bt,enum next_state state) {
265 DisjunctionQuery *q = (DisjunctionQuery*) this;
267 enum next_state s = subsequent;
273 for ( ; i < q->size; i++ ) {
274 if ( q->disjuncts[i]->def->next( q->disjuncts[i], bt, s ) ) {
278 q->disjuncts[i]->def->next( q->disjuncts[i], bt, restore );
285 q->disjuncts[i]->def->next( q->disjuncts[i], bt, restore );
293 static struct query_callbacks DisjunctionQuery_def = {
294 .reclaim = DisjunctionQuery_reclaim,
295 .next = DisjunctionQuery_next,
298 query *query_or(int n,...) {
300 DisjunctionQuery *q = (DisjunctionQuery *)
301 malloc( sizeof( DisjunctionQuery ) );
302 (*q) = (DisjunctionQuery) {
303 .def = &DisjunctionQuery_def,
306 .disjuncts = (query**) malloc( n * sizeof( query* ) ),
310 for ( i = 0; i < n; i++ ) {
311 q->disjuncts[i] = va_arg( args, query* );
317 /* ==================== Relation access ==================== */
319 struct query_callbacks *def;
327 // Release any memory.
328 static void RelationQuery_reclaim(query *this) {
329 RelationQuery *q = (RelationQuery*) this;
334 // Make names have given values and return 1. If any name has a
335 // different value then return 0. Values are strings.
336 static int RelationQuery_next(
337 query *this,BindingTable *bt,enum next_state state) {
338 RelationQuery *q = (RelationQuery*) this;
339 int arity = ((TupleSchema*) q->rel->content.type)->arity;
340 VectorIndex index = q->index + 1;
343 if ( q->saved == 0 ) {
344 q->saved = (tuple*) malloc( arity * sizeof( void* ) );
346 memcpy( q->saved, q->names, arity * sizeof( void* ) );
347 BindingTable_deref( bt, arity, q->saved );
351 for ( ; index < q->rel->content.table.size; index++ ) {
352 tuple *values = relation_next( q->rel, &index, q->values );
355 AssignmentQuery_assign( bt, arity, q->names, values, 1 );
361 AssignmentQuery_assign( bt, arity, q->names, q->saved, 1 );
370 static struct query_callbacks RelationQuery_def = {
371 .reclaim = RelationQuery_reclaim,
372 .next = RelationQuery_next
376 * Return a query object representing an Relation of one or more
379 query *query_Relation(Relation *r,tuple *names,tuple *values) {
380 RelationQuery *q = (RelationQuery*) malloc( sizeof( RelationQuery ) );
381 (*q) = (RelationQuery) {
382 .def = &RelationQuery_def,