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_clone( ts->columns );
int i = 0;
va_start( ap, r );
- for ( ; i < ts->arity; i++ ) {
- if ( va_arg( ap, int ) ) {
- (*columns)[i] = ts->columns[i];
+ for ( ; i < columns->size; i++ ) {
+ if ( va_arg( ap, int ) == 0 ) {
+ columns->elements[i] = 0;
}
}
va_end( ap );
- ts = TupleSchema_create( ts->arity, columns );
+ ts = TupleSchema_create( columns );
i = (int) r->constraints.size;
Vector_append(
&r->constraints,
// 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 );
}
}
// 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 = {
// 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 );
// 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
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;
}