X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;ds=sidebyside;f=vector%2FRelation.c;h=0f671abce2d09c475f8092e22ff760825211250c;hb=3d4400773c3361961bcb9f8b6898321f2005a093;hp=f72f19888d8ab531ac6fe47e7944baed178b2fd3;hpb=6fcd4ffc18696dbf4c11be32837a2035ea5ee92f;p=rrq%2Frrqmisc.git diff --git a/vector/Relation.c b/vector/Relation.c index f72f198..0f671ab 100644 --- a/vector/Relation.c +++ b/vector/Relation.c @@ -2,7 +2,7 @@ #include #include -Relation *relation_create(TupleSchema *schema) { +Relation *Relation_create(TupleSchema *schema) { Relation *r = (Relation *) malloc( sizeof( Relation ) ); (*r) = (Relation) { .content = (HashVector) { @@ -27,15 +27,16 @@ Relation *relation_create(TupleSchema *schema) { // Add an indexing HashVector to the Relation using the given column // flags with 1 indicating key column and 0 indicating value column. -int relation_add_constraint(Relation *r,...) { +int Relation_add_constraint(Relation *r,...) { va_list ap; TupleSchema *ts = (TupleSchema *) r->content.type; - tuple *columns = (tuple*) calloc( ts->arity, sizeof( void* ) ); + Tuple *columns = (Tuple*) malloc( + sizeof( Tuple ) + ts->arity * sizeof( void* ) ); int i = 0; va_start( ap, r ); for ( ; i < ts->arity; i++ ) { if ( va_arg( ap, int ) ) { - (*columns)[i] = ts->columns[i]; + columns->elements[i] = ts->columns->elements[i]; } } va_end( ap ); @@ -48,7 +49,7 @@ int relation_add_constraint(Relation *r,...) { } //============== Adding an item ============= -// Iteration context for adding or querying a Relation +// Iteration context for adding or Querying a Relation typedef struct { Relation *rel; HashVector knockouts; @@ -60,10 +61,16 @@ typedef struct { // for ignoring full matches to the key tuple. static int knockout_check(VectorIndex index,void *item,void *data) { Knockout *kod = (Knockout*) data; + void *key = kod->item; + HashVector *hv = (HashVector*) item; + TupleSchema *type = (TupleSchema *)hv->type; VectorIndex i = 0; - for ( ; i < ((HashVector*) item)->table.size; i++ ) { - void *old = HashVector_next( (HashVector*) item, &i, kod->item ); + for ( ; i < hv->table.size; i++ ) { + void *old = HashVector_next( hv, &i ); if ( old ) { + if ( key && type->base.haskey( type, old, key ) == 0 ) { + continue; + } HashVector_add( &kod->knockouts, old ); } } @@ -82,10 +89,10 @@ static int knockout_add(VectorIndex index,void *item,void *data) { return 0; } -// Find and remove all collisions for a query, unless "add" is +// Find and remove all collisions for a Query, unless "add" is // non-zero in which case the function aborts if there is any match in // the main content. -static int knockout_clear(Knockout *this,Relation *r,tuple *item,int add) { +static int knockout_clear(Knockout *this,Relation *r,Tuple *item,int add) { (*this) = (Knockout) { .rel = r, .knockouts = { @@ -108,7 +115,7 @@ static int knockout_clear(Knockout *this,Relation *r,tuple *item,int add) { // Delete them from all tables VectorIndex i; for ( i = 0; i < this->knockouts.table.size; i++ ) { - void *t = HashVector_next( &this->knockouts, &i, 0 ); + void *t = HashVector_next( &this->knockouts, &i ); if ( t ) { HashVector_delete( &r->content, t ); Vector_iterate( &r->constraints, 0, knockout_delete, t ); @@ -120,7 +127,7 @@ static int knockout_clear(Knockout *this,Relation *r,tuple *item,int add) { // add a tuple to a Relation and return a Vector of knocked out // tuples, if any, or 0 otherwise. -Vector *relation_add(Relation *r,tuple *item) { +Vector *Relation_add(Relation *r,Tuple *item) { Knockout data; if ( knockout_clear( &data, r, item, 1 ) ) { // Add the new tuple @@ -131,13 +138,26 @@ Vector *relation_add(Relation *r,tuple *item) { return 0; } -Vector *relation_delete(Relation *r,tuple *item) { +Vector *Relation_delete(Relation *r,Tuple *item) { Knockout data; (void) knockout_clear( &data, r, item, 0 ); return HashVector_contents( &data.knockouts, single_index_level, 0 ); } -void *relation_next(Relation *r,VectorIndex *index,tuple *query) { - return HashVector_next( &r->content, index, query ); +void *Relation_next(Relation *r,VectorIndex *index,Tuple *query) { + HashVector *hv = &r->content; + void *key = query; + TupleSchema *type = (TupleSchema *) hv->type; + for ( ; (*index) < hv->table.size; (*index)++ ) { + void *old = HashVector_next( hv, index ); + if ( old ) { + if ( key && type->base.haskey( type, old, key ) == 0 ) { + continue; + } + return old; + } + } + (*index) = hv->table.size; + return 0; }