X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=vector%2Frelation.c;h=8ab343f6cb739104768bd02116a5472f9ce8dfee;hb=d9858ce46cb09b9127c7246f628e65982aa43a15;hp=330b3def071f70feec70438e4aa6fa95f212628d;hpb=e47e7f1e366224e9e514e28f172afa65c732db21;p=rrq%2Frrqmisc.git diff --git a/vector/relation.c b/vector/relation.c index 330b3de..8ab343f 100644 --- a/vector/relation.c +++ b/vector/relation.c @@ -1,16 +1,36 @@ #include #include +relation *relation_create(tupleschema *schema) { + relation *r = (relation *) malloc( sizeof( relation ) ); + (*r) = (relation) { + .content = (hashvector) { + .table = (vector) { + .variant = nibble_index_levels, + .size = 16, + .entries = 0 + }, + .fill = 0, .holes = 0, .type = (itemkeyfun*) schema + }, + .constraints = (vector) { + .variant = single_index_level, + .size = 0, + .entries = 0 + }, + }; + return r; +} + #define COPYA(T,P,N) (T*) memcpy( malloc( N * sizeof(T) ), P, N * sizeof( T ) ) #define COPY(T,P) COPYA(T,P,1) // Add an indexing hashvector to the relation using the nominated // column indexes being the value part. the key must be a clone of the // relation columns but with some columns reset. -int relation_addindex(relation *r,tupleschema *key) { - tupleschema *primary = r->columns; +int relation_add_contraint(relation *r,tupleschema *key) { + tupleschema *primary = (tupleschema *) r->content.type; if ( primary->arity != key->arity ) { - return -1; + return -1; // no good } int i = 0; for ( ; i < primary->arity; i++ ) { @@ -18,44 +38,29 @@ int relation_addindex(relation *r,tupleschema *key) { return -1; } } - i = (int) r->indexes.size; - vector_append( &r->indexes, hashvector_create( 1, (itemkeyfun*) key ) ); + i = (int) r->constraints.size; + vector_append( + &r->constraints, + hashvector_create( nibble_index_levels, &key->base ) ); return i; } -relation *relation_create(int arity,tupleschema *schema) { - relation *r = (relation *) malloc( sizeof( relation ) ); - (*r) = (relation) { - .indexes = { - .variant = 2, - .size = 0, - .entries = 0 - }, - .columns = schema - }; - return r; -} - +//============== Adding an item ============= // Iteration context for adding or querying a relation typedef struct { - itemkeyfun *columns; + relation *rel; vector knockouts; - void *key; -} knockoutdata; + void *item; +} knockout; -// Determine matches to ((knockoutdata*)data)->key in -// (hashvector*)item, optionally using ((knockoutdata*)data)->columns +// Determine matches to ((knockout*)data)->key in +// (hashvector*)item, optionally using ((knockout*)data)->columns // for ignoring full matches to the key tuple. static int knockout_check(vector_index index,void *item,void *data) { - knockoutdata *kod = (knockoutdata*) data; - void *old = 0; - if ( hashvector_find( (hashvector*) item, kod->key, &old ) ) { - if ( kod->columns == 0 || - kod->columns->haskey( kod->columns, old, kod->key ) == 0 ) { - if ( vector_find( &kod->knockouts, old ) >= kod->knockouts.size ) { - vector_append( &kod->knockouts, old ); - } - } + knockout *kod = (knockout*) data; + void *old = hashvector_next( (hashvector*) item, 0, kod->item ); + if ( old ) { + vector_append( &kod->knockouts, old ); } return 0; } @@ -78,23 +83,58 @@ static int knockout_add(vector_index index,void *item,void *data) { return 0; } -// 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 *x) { - knockoutdata data = { - .columns = &(r->columns->functions), - .knockouts = { .variant = 2, .size = 0, .entries = 0 }, - .key = x +// 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) { + (*this) = (knockout) { + .rel = r, + .knockouts = { + .variant = bitpair_index_levels, + .size = 0, .entries = 0 + }, + .item = item }; - // Find all knockouts - vector_iterate( &r->indexes, 0, knockout_check, &data ); - // Delete them - vector_iterate( &r->indexes, 0, knockout_delete, &data.knockouts ); - // Add the new tuple - vector_iterate( &r->indexes, 0, knockout_add, x ); - if ( data.knockouts.size == 0 ) { + knockout_check( 0, &r->content, this ); + if ( add && this->knockouts.size > 0 ) { return 0; } - return vector_clone( 3, &data.knockouts ); + // Find all constraint knockouts + vector_iterate( &r->constraints, 0, knockout_check, this ); + if ( this->knockouts.size > 0 ) { + // Delete them from all tables + vector_iterate( + &this->knockouts, 0, knockout_delete_item, &r->content ); + vector_iterate( + &r->constraints, 0, knockout_delete, &this->knockouts ); + } + return 1; +} + +// 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) { + knockout data; + if ( knockout_clear( &data, r, item, 1 ) ) { + // Add the new tuple + hashvector_add( &r->content, item ); + vector_iterate( &r->constraints, 0, knockout_add, item ); + if ( data.knockouts.size > 0 ) { + return vector_clone( single_index_level, &data.knockouts ); + } + } + return 0; +} + +vector *relation_delete(relation *r,tuple *item) { + knockout data; + (void) knockout_clear( &data, r, item, 0 ); + if ( data.knockouts.size > 0 ) { + return vector_clone( single_index_level, &data.knockouts ); + } + return 0; } +void *relation_next(relation *r,vector_index *index,tuple *query) { + return hashvector_next( &r->content, index, query ); +}