5 #include <QueryCallbacks.h>
7 /* ==================== AssignmentQuery ==================== */
10 * AssignmentQuery represents an assignment of values to names.
15 struct QueryCallbacks *def;
22 // Release any memory.
23 static void AssignmentQuery_reclaim(Query *this) {
24 AssignmentQuery *q = (AssignmentQuery*) this;
29 static int AssignmentQuery_check(int arity,Tuple *a,Tuple *b) {
31 for ( i = 0; i < arity; i++ ) {
32 char *value = a->elements[i];
33 char *current = b->elements[i];
34 if ( value && current && current != value &&
35 strcmp( current, value ) != 0 ) {
42 static void AssignmentQuery_assign(
43 BindingTable *bt,int n,Tuple *names,Tuple *values,int all)
46 for ( i = 0; i < n; i++ ) {
47 if ( all || values->elements[i] ) {
48 BindingTable_set( bt, names->elements[i], values->elements[i] );
53 // Make names have given values and return 1. If any name has a
54 // different value then return 0. Values are strings.
55 static int AssignmentQuery_next(
56 Query *this,BindingTable *bt,enum NextState state) {
57 AssignmentQuery *q = (AssignmentQuery*) this;
60 if ( q->saved == 0 ) {
61 q->saved = Tuple_clone( q->arity, q->names );
63 memcpy( q->saved, q->names, q->arity * sizeof( void* ) );
65 BindingTable_deref( bt, q->arity, q->saved );
66 // Check with new values
67 if ( AssignmentQuery_check( q->arity, q->values, q->saved ) ) {
68 AssignmentQuery_assign( bt, q->arity, q->names, q->values, 0 );
75 AssignmentQuery_assign( bt, q->arity, q->names, q->saved, 1 );
84 static struct QueryCallbacks AssignmentQuery_def = {
85 .reclaim = AssignmentQuery_reclaim,
86 .next = AssignmentQuery_next
90 * Return a Query object representing an assignment of one or more
93 Query *Query_assign(int arity,Tuple *names,Tuple *values) {
94 AssignmentQuery *q = (AssignmentQuery*)
95 malloc( sizeof( AssignmentQuery ) );
96 (*q) = (AssignmentQuery) {
97 .def = &AssignmentQuery_def,
106 /* ==================== conjunction ==================== */
109 * ConjunctionQuery represents a conjunction of sub queries.
114 struct QueryCallbacks *def;
120 static void ConjunctionQuery_reclaim(Query *this) {
121 ConjunctionQuery *q = (ConjunctionQuery*) this;
123 for ( i = 0; i < q->size; i++ ) {
124 q->conjuncts[i]->def->reclaim( q->conjuncts[i] );
126 free( q->conjuncts );
130 static int ConjunctionQuery_next(
131 Query *this,BindingTable *bt,enum NextState state)
133 ConjunctionQuery *q = (ConjunctionQuery*) this;
135 enum NextState s = subsequent;
143 while ( i < q->size ) {
144 if ( q->conjuncts[i]->def->next( q->conjuncts[i], bt, s ) ) {
147 q->conjuncts[i]->def->next( q->conjuncts[i], bt, restore );
149 // The first conjunct now exhausted
158 for ( ; i >= 0; i-- ) {
159 q->conjuncts[i]->def->next( q->conjuncts[i], bt, restore );
168 static struct QueryCallbacks ConjunctionQuery_def = {
169 .reclaim = ConjunctionQuery_reclaim,
170 .next = ConjunctionQuery_next
173 Query *Query_and(int n,...) {
175 ConjunctionQuery *q = (ConjunctionQuery *)
176 malloc( sizeof( ConjunctionQuery ) );
177 (*q) = (ConjunctionQuery) {
178 .def = &ConjunctionQuery_def,
181 .conjuncts = (Query**) malloc( n * sizeof( Query* ) )
185 for ( i = 0; i < n; i++ ) {
186 q->conjuncts[i] = va_arg( args, Query* );
192 /* ==================== disjunction ==================== */
195 * DisjunctionQuery represents a disjunction of sub queries.
200 struct QueryCallbacks *def;
206 static void DisjunctionQuery_reclaim(Query *this) {
207 DisjunctionQuery *q = (DisjunctionQuery*) this;
209 for ( i = 0; i < q->size; i++ ) {
210 q->disjuncts[i]->def->reclaim( q->disjuncts[i] );
212 free( q->disjuncts );
216 static int DisjunctionQuery_next(
217 Query *this,BindingTable *bt,enum NextState state) {
218 DisjunctionQuery *q = (DisjunctionQuery*) this;
220 enum NextState s = subsequent;
226 for ( ; i < q->size; i++ ) {
227 if ( q->disjuncts[i]->def->next( q->disjuncts[i], bt, s ) ) {
231 q->disjuncts[i]->def->next( q->disjuncts[i], bt, restore );
238 q->disjuncts[i]->def->next( q->disjuncts[i], bt, restore );
246 static struct QueryCallbacks DisjunctionQuery_def = {
247 .reclaim = DisjunctionQuery_reclaim,
248 .next = DisjunctionQuery_next,
251 Query *Query_or(int n,...) {
253 DisjunctionQuery *q = (DisjunctionQuery *)
254 malloc( sizeof( DisjunctionQuery ) );
255 (*q) = (DisjunctionQuery) {
256 .def = &DisjunctionQuery_def,
259 .disjuncts = (Query**) malloc( n * sizeof( Query* ) ),
263 for ( i = 0; i < n; i++ ) {
264 q->disjuncts[i] = va_arg( args, Query* );
270 /* ==================== Relation access ==================== */
273 * RelationQuery represents a ground query on a relation.
278 struct QueryCallbacks *def;
286 // Release any memory.
287 static void RelationQuery_reclaim(Query *this) {
288 RelationQuery *q = (RelationQuery*) this;
293 // Make names have given values and return 1. If any name has a
294 // different value then return 0. Values are strings.
295 static int RelationQuery_next(
296 Query *this,BindingTable *bt,enum NextState state) {
297 RelationQuery *q = (RelationQuery*) this;
298 int arity = ((TupleSchema*) q->rel->content.type)->arity;
299 VectorIndex index = q->index + 1;
302 if ( q->saved == 0 ) {
303 q->saved = Tuple_clone( arity, q->names );
305 memcpy( q->saved, q->names, arity * sizeof( void* ) );
307 BindingTable_deref( bt, arity, q->saved );
311 for ( ; index < q->rel->content.table.size; index++ ) {
312 Tuple *values = Relation_next( q->rel, &index, q->values );
315 AssignmentQuery_assign( bt, arity, q->names, values, 1 );
321 AssignmentQuery_assign( bt, arity, q->names, q->saved, 1 );
330 static struct QueryCallbacks RelationQuery_def = {
331 .reclaim = RelationQuery_reclaim,
332 .next = RelationQuery_next
336 * Return a Query object representing an Relation of one or more
339 Query *Query_Relation(Relation *r,Tuple *names,Tuple *values) {
340 RelationQuery *q = (RelationQuery*) malloc( sizeof( RelationQuery ) );
341 (*q) = (RelationQuery) {
342 .def = &RelationQuery_def,
352 Query *q,BindingTable *bt,
353 int (*consequent)(BindingTable *bt,void *data),
356 if ( q->def->next( q, bt, initial ) && consequent( bt, data ) ) {
357 while ( q->def->next( q, bt, subsequent ) && consequent( bt, data ) );
359 (void) q->def->next( q, bt, restore );