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.
28 * A struct Query_callbacks record defines the callbacks for a
29 * specific Query type.
31 struct QueryCallbacks {
33 * \brief Callback function to reclaim the Query memory for a
36 * \param this is the specific \ref Query concerned.
38 * Ground queries recalim their own state memory. Composite
39 * queries first propagate the reclaim call to its components, and
40 * thereafter reclaim their local state memory.
42 void (*reclaim)(Query *this);
43 void (*start)(Query *this,BindingTable *bt,enum NextState s);
45 * \brief Callback function to update the Binding table with a
46 * succession of alternative bindings.
48 * \param this is the specific \ref Query concerned.
50 * \param bt is the Binding table to set bindings in.
52 * \param s is the call "sub-command" for the function.
54 * \returns 1 if a new Binding is provided and 0 otherwise.
56 * This function is called repeatedly for successively obtaining
57 * the alternative bindings that satisfy the Query. The "initial"
58 * state sub-command tells the function to capture the incoming
59 * BindingTable state so that the function can later restore it
60 * upon the "restore" sub-command. Upon the "initial" command, the
61 * function also sets up the Binding table with its first Binding
62 * alternative. This is followed by a series of "subsequent"
63 * sub-command calls for the function to change the BindingTable
64 * for its succession of Binding alternatives. The function should
65 * return 1 after any successful Binding setup, and return 0 when
66 * it cannot setup any (more) Binding.
68 int (*next)(Query *this,BindingTable *bt,enum NextState state);
71 /* ==================== AssignmentQuery ==================== */
73 struct QueryCallbacks *def;
80 // Release any memory.
81 static void AssignmentQuery_reclaim(Query *this) {
82 AssignmentQuery *q = (AssignmentQuery*) this;
87 static int AssignmentQuery_check(int arity,tuple *a,tuple *b) {
89 for ( i = 0; i < arity; i++ ) {
90 char *value = (*a)[i];
91 char *current = (*b)[i];
92 if ( value && current && current != value &&
93 strcmp( current, value ) != 0 ) {
100 static void AssignmentQuery_assign(
101 BindingTable *bt,int n,tuple *names,tuple *values,int all)
104 for ( i = 0; i < n; i++ ) {
105 if ( all || (*values)[i] ) {
106 BindingTable_set( bt, (*names)[i], (*values)[i] );
111 // Make names have given values and return 1. If any name has a
112 // different value then return 0. Values are strings.
113 static int AssignmentQuery_next(
114 Query *this,BindingTable *bt,enum NextState state) {
115 AssignmentQuery *q = (AssignmentQuery*) this;
118 if ( q->saved == 0 ) {
119 q->saved = (tuple*) malloc( q->arity * sizeof( void* ) );
121 memcpy( q->saved, q->names, q->arity * sizeof( void* ) );
122 BindingTable_deref( bt, q->arity, q->saved );
123 // Check with new values
124 if ( AssignmentQuery_check( q->arity, q->values, q->saved ) ) {
125 AssignmentQuery_assign( bt, q->arity, q->names, q->values, 0 );
132 AssignmentQuery_assign( bt, q->arity, q->names, q->saved, 1 );
141 static struct QueryCallbacks AssignmentQuery_def = {
142 .reclaim = AssignmentQuery_reclaim,
143 .next = AssignmentQuery_next
147 * Return a Query object representing an assignment of one or more
150 Query *Query_assign(int arity,tuple *names,tuple *values) {
151 AssignmentQuery *q = (AssignmentQuery*)
152 malloc( sizeof( AssignmentQuery ) );
153 (*q) = (AssignmentQuery) {
154 .def = &AssignmentQuery_def,
163 /* ==================== conjunction ==================== */
165 struct QueryCallbacks *def;
171 static void ConjunctionQuery_reclaim(Query *this) {
172 ConjunctionQuery *q = (ConjunctionQuery*) this;
174 for ( i = 0; i < q->size; i++ ) {
175 q->conjuncts[i]->def->reclaim( q->conjuncts[i] );
177 free( q->conjuncts );
181 static int ConjunctionQuery_next(
182 Query *this,BindingTable *bt,enum NextState state)
184 ConjunctionQuery *q = (ConjunctionQuery*) this;
186 enum NextState s = subsequent;
194 while ( i < q->size ) {
195 if ( q->conjuncts[i]->def->next( q->conjuncts[i], bt, s ) ) {
198 q->conjuncts[i]->def->next( q->conjuncts[i], bt, restore );
200 // The first conjunct now exhausted
209 for ( ; i >= 0; i-- ) {
210 q->conjuncts[i]->def->next( q->conjuncts[i], bt, restore );
219 static struct QueryCallbacks ConjunctionQuery_def = {
220 .reclaim = ConjunctionQuery_reclaim,
221 .next = ConjunctionQuery_next
224 Query *Query_and(int n,...) {
226 ConjunctionQuery *q = (ConjunctionQuery *)
227 malloc( sizeof( ConjunctionQuery ) );
228 (*q) = (ConjunctionQuery) {
229 .def = &ConjunctionQuery_def,
232 .conjuncts = (Query**) malloc( n * sizeof( Query* ) )
236 for ( i = 0; i < n; i++ ) {
237 q->conjuncts[i] = va_arg( args, Query* );
243 /* ==================== disjunction ==================== */
245 struct QueryCallbacks *def;
251 static void DisjunctionQuery_reclaim(Query *this) {
252 DisjunctionQuery *q = (DisjunctionQuery*) this;
254 for ( i = 0; i < q->size; i++ ) {
255 q->disjuncts[i]->def->reclaim( q->disjuncts[i] );
257 free( q->disjuncts );
261 static int DisjunctionQuery_next(
262 Query *this,BindingTable *bt,enum NextState state) {
263 DisjunctionQuery *q = (DisjunctionQuery*) this;
265 enum NextState s = subsequent;
271 for ( ; i < q->size; i++ ) {
272 if ( q->disjuncts[i]->def->next( q->disjuncts[i], bt, s ) ) {
276 q->disjuncts[i]->def->next( q->disjuncts[i], bt, restore );
283 q->disjuncts[i]->def->next( q->disjuncts[i], bt, restore );
291 static struct QueryCallbacks DisjunctionQuery_def = {
292 .reclaim = DisjunctionQuery_reclaim,
293 .next = DisjunctionQuery_next,
296 Query *Query_or(int n,...) {
298 DisjunctionQuery *q = (DisjunctionQuery *)
299 malloc( sizeof( DisjunctionQuery ) );
300 (*q) = (DisjunctionQuery) {
301 .def = &DisjunctionQuery_def,
304 .disjuncts = (Query**) malloc( n * sizeof( Query* ) ),
308 for ( i = 0; i < n; i++ ) {
309 q->disjuncts[i] = va_arg( args, Query* );
315 /* ==================== Relation access ==================== */
317 struct QueryCallbacks *def;
325 // Release any memory.
326 static void RelationQuery_reclaim(Query *this) {
327 RelationQuery *q = (RelationQuery*) this;
332 // Make names have given values and return 1. If any name has a
333 // different value then return 0. Values are strings.
334 static int RelationQuery_next(
335 Query *this,BindingTable *bt,enum NextState state) {
336 RelationQuery *q = (RelationQuery*) this;
337 int arity = ((TupleSchema*) q->rel->content.type)->arity;
338 VectorIndex index = q->index + 1;
341 if ( q->saved == 0 ) {
342 q->saved = (tuple*) malloc( arity * sizeof( void* ) );
344 memcpy( q->saved, q->names, arity * sizeof( void* ) );
345 BindingTable_deref( bt, arity, q->saved );
349 for ( ; index < q->rel->content.table.size; index++ ) {
350 tuple *values = Relation_next( q->rel, &index, q->values );
353 AssignmentQuery_assign( bt, arity, q->names, values, 1 );
359 AssignmentQuery_assign( bt, arity, q->names, q->saved, 1 );
368 static struct QueryCallbacks RelationQuery_def = {
369 .reclaim = RelationQuery_reclaim,
370 .next = RelationQuery_next
374 * Return a Query object representing an Relation of one or more
377 Query *Query_Relation(Relation *r,tuple *names,tuple *values) {
378 RelationQuery *q = (RelationQuery*) malloc( sizeof( RelationQuery ) );
379 (*q) = (RelationQuery) {
380 .def = &RelationQuery_def,