X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=vector%2FQuery.c;h=c13ecde73e418e4c399f190fc7ad4f370e46809f;hb=3d4400773c3361961bcb9f8b6898321f2005a093;hp=68efa3fb73f1d568bf1aa58a7fdb9cf5a0bb1f4c;hpb=e938f8c45fd191d96da48f65262e4efcfada7805;p=rrq%2Frrqmisc.git diff --git a/vector/Query.c b/vector/Query.c index 68efa3f..c13ecde 100644 --- a/vector/Query.c +++ b/vector/Query.c @@ -2,79 +2,21 @@ #include #include #include -#include +#include -enum NextState { - /** - * This state tells the "next" function that it should capture the - * incoming BindingTable state and provide the initial Binding of - * a new sucession of bindings. - */ - initial, - /** - * This state tells the "next" function that it should update the - * bidning table with a subsequent Binding in the current - * succession of bindings. - */ - subsequent, - /** - * This state tells the "next" function that it should just - * restore the Binding table to its incoming state. - */ - restore -}; +/* ==================== AssignmentQuery ==================== */ /** - * A struct Query_callbacks record defines the callbacks for a - * specific Query type. + * AssignmentQuery represents an assignment of values to names. + * \extends Query + * \related Query */ -struct QueryCallbacks { - /** - * \brief Callback function to reclaim the Query memory for a - * given Query. - * - * \param this is the specific \ref Query concerned. - * - * Ground queries recalim their own state memory. Composite - * queries first propagate the reclaim call to its components, and - * thereafter reclaim their local state memory. - */ - void (*reclaim)(Query *this); - void (*start)(Query *this,BindingTable *bt,enum NextState s); - /** - * \brief Callback function to update the Binding table with a - * succession of alternative bindings. - * - * \param this is the specific \ref Query concerned. - * - * \param bt is the Binding table to set bindings in. - * - * \param s is the call "sub-command" for the function. - * - * \returns 1 if a new Binding is provided and 0 otherwise. - * - * This function is called repeatedly for successively obtaining - * the alternative bindings that satisfy the Query. The "initial" - * state sub-command tells the function to capture the incoming - * BindingTable state so that the function can later restore it - * upon the "restore" sub-command. Upon the "initial" command, the - * function also sets up the Binding table with its first Binding - * alternative. This is followed by a series of "subsequent" - * sub-command calls for the function to change the BindingTable - * for its succession of Binding alternatives. The function should - * return 1 after any successful Binding setup, and return 0 when - * it cannot setup any (more) Binding. - */ - int (*next)(Query *this,BindingTable *bt,enum NextState state); -}; - -/* ==================== AssignmentQuery ==================== */ typedef struct { struct QueryCallbacks *def; int arity; - tuple *names; - tuple *values; - tuple *saved; + Tuple *names; + Tuple *values; + Tuple *saved; } AssignmentQuery; // Release any memory. @@ -84,11 +26,11 @@ static void AssignmentQuery_reclaim(Query *this) { free( this ); } -static int AssignmentQuery_check(int arity,tuple *a,tuple *b) { +static int AssignmentQuery_check(int arity,Tuple *a,Tuple *b) { int i; for ( i = 0; i < arity; i++ ) { - char *value = (*a)[i]; - char *current = (*b)[i]; + char *value = a->elements[i]; + char *current = b->elements[i]; if ( value && current && current != value && strcmp( current, value ) != 0 ) { return 0; @@ -98,12 +40,12 @@ static int AssignmentQuery_check(int arity,tuple *a,tuple *b) { } static void AssignmentQuery_assign( - BindingTable *bt,int n,tuple *names,tuple *values,int all) + BindingTable *bt,int n,Tuple *names,Tuple *values,int all) { int i; for ( i = 0; i < n; i++ ) { - if ( all || (*values)[i] ) { - BindingTable_set( bt, (*names)[i], (*values)[i] ); + if ( all || values->elements[i] ) { + BindingTable_set( bt, names->elements[i], values->elements[i] ); } } } @@ -116,9 +58,10 @@ static int AssignmentQuery_next( switch ( state ) { case initial: if ( q->saved == 0 ) { - q->saved = (tuple*) malloc( q->arity * sizeof( void* ) ); + q->saved = Tuple_clone( q->arity, q->names ); + } else { + memcpy( q->saved, q->names, q->arity * sizeof( void* ) ); } - memcpy( q->saved, q->names, q->arity * sizeof( void* ) ); BindingTable_deref( bt, q->arity, q->saved ); // Check with new values if ( AssignmentQuery_check( q->arity, q->values, q->saved ) ) { @@ -147,7 +90,7 @@ static struct QueryCallbacks AssignmentQuery_def = { * Return a Query object representing an assignment of one or more * variables. */ -Query *Query_assign(int arity,tuple *names,tuple *values) { +Query *Query_assign(int arity,Tuple *names,Tuple *values) { AssignmentQuery *q = (AssignmentQuery*) malloc( sizeof( AssignmentQuery ) ); (*q) = (AssignmentQuery) { @@ -161,6 +104,12 @@ Query *Query_assign(int arity,tuple *names,tuple *values) { } /* ==================== conjunction ==================== */ + +/** + * ConjunctionQuery represents a conjunction of sub queries. + * \extends Query + * \related Query + */ typedef struct { struct QueryCallbacks *def; int active; @@ -241,6 +190,12 @@ Query *Query_and(int n,...) { } /* ==================== disjunction ==================== */ + +/** + * DisjunctionQuery represents a disjunction of sub queries. + * \extends Query + * \related Query + */ typedef struct { struct QueryCallbacks *def; int index; @@ -313,13 +268,19 @@ Query *Query_or(int n,...) { } /* ==================== Relation access ==================== */ + +/** + * RelationQuery represents a ground query on a relation. + * \extends Query + * \related Query + */ typedef struct { struct QueryCallbacks *def; Relation *rel; VectorIndex index; - tuple *names; - tuple *values; - tuple *saved; + Tuple *names; + Tuple *values; + Tuple *saved; } RelationQuery; // Release any memory. @@ -339,15 +300,16 @@ static int RelationQuery_next( switch ( state ) { case initial: if ( q->saved == 0 ) { - q->saved = (tuple*) malloc( arity * sizeof( void* ) ); + q->saved = Tuple_clone( arity, q->names ); + } else { + memcpy( q->saved, q->names, arity * sizeof( void* ) ); } - memcpy( q->saved, q->names, arity * sizeof( void* ) ); BindingTable_deref( bt, arity, q->saved ); index = 0; // Fall through case subsequent: for ( ; index < q->rel->content.table.size; index++ ) { - tuple *values = Relation_next( q->rel, &index, q->values ); + Tuple *values = Relation_next( q->rel, &index, q->values ); if ( values ) { q->index = index; AssignmentQuery_assign( bt, arity, q->names, values, 1 ); @@ -374,7 +336,7 @@ static struct QueryCallbacks RelationQuery_def = { * Return a Query object representing an Relation of one or more * variables. */ -Query *Query_Relation(Relation *r,tuple *names,tuple *values) { +Query *Query_Relation(Relation *r,Tuple *names,Tuple *values) { RelationQuery *q = (RelationQuery*) malloc( sizeof( RelationQuery ) ); (*q) = (RelationQuery) { .def = &RelationQuery_def, @@ -385,3 +347,14 @@ Query *Query_Relation(Relation *r,tuple *names,tuple *values) { }; return (Query*) q; } + +void Query_rule( + Query *q,BindingTable *bt, + int (*consequent)(BindingTable *bt,void *data), + void *data ) +{ + if ( q->def->next( q, bt, initial ) && consequent( bt, data ) ) { + while ( q->def->next( q, bt, subsequent ) && consequent( bt, data ) ); + } + (void) q->def->next( q, bt, restore ); +}