From: Ralph Ronnquist Date: Fri, 8 Jul 2022 13:35:59 +0000 (+1000) Subject: revised relation_add_constraint ABI and added convenience macros X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=03eba52ca6e59fb0b3e239588bb619fedafc341b;p=rrq%2Frrqmisc.git revised relation_add_constraint ABI and added convenience macros --- diff --git a/vector/relation.c b/vector/relation.c index e7469de..6777d9a 100644 --- a/vector/relation.c +++ b/vector/relation.c @@ -1,3 +1,4 @@ +#include #include #include @@ -24,24 +25,25 @@ relation *relation_create(tupleschema *schema) { #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_add_constraint(relation *r,tupleschema *key) { - tupleschema *primary = (tupleschema *) r->content.type; - if ( primary->arity != key->arity ) { - return -1; // no good - } +// 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,...) { + va_list ap; + tupleschema *ts = (tupleschema *) r->content.type; + tuple *columns = (tuple*) calloc( ts->arity, sizeof( void* ) ); int i = 0; - for ( ; i < primary->arity; i++ ) { - if ( key->columns[i] && primary->columns[i] != key->columns[i] ) { - return -1; + va_start( ap, r ); + for ( ; i < ts->arity; i++ ) { + if ( va_arg( ap, int ) ) { + (*columns)[i] = ts->columns[i]; } } + va_end( ap ); + ts = tupleschema_create( ts->arity, columns ); i = (int) r->constraints.size; vector_append( &r->constraints, - hashvector_create( nibble_index_levels, &key->base ) ); + hashvector_create( nibble_index_levels, (itemkeyfun*) ts ) ); return i; } @@ -138,3 +140,4 @@ vector *relation_delete(relation *r,tuple *item) { void *relation_next(relation *r,vector_index *index,tuple *query) { return hashvector_next( &r->content, index, query ); } + diff --git a/vector/relation.h b/vector/relation.h index f76f1bb..c2e5293 100644 --- a/vector/relation.h +++ b/vector/relation.h @@ -50,29 +50,28 @@ extern relation *relation_create(tupleschema *schema); * * \param r is the relation concerned. * - * \param key is the constraint \ref tupleschema. + * \param ... are the column flags indicating key (1) or value (0) + * column for all columns. * * \returns the index into the constraints \ref vector for the added * constraint. * - * This function adds a \ref hashvector with the provided \ref - * tupleschema as its item type. The \b key \ref tupleschema must be a - * clone of the \ref relation column schema with some (or all) value - * columns marked as \b 0. Such a \ref tupleschema may be obtained via - * the function \ref tupleschema_mask to clone the \ref relation - * content type (casted as \ref tupleschema*) and clear columns by - * their index. - * - * The constraint \ref hashvectors are used when tuples are added to - * the \ref relation so as to identify the already contained tuples - * that contradict the addition by means of having the same constraint - * key. The already contained tuples are then "knocked out" from the - * relation by the new addition. - * - * \see tupleschema_mask, relation_add + * This function adds a \ref hashvector with a \ref tupleschema as its + * item type cloned from the content type and then modified to + * represent the constraint. Namely that the key columns have their + * "column type" set while value columsn are reset. + * + * The \b constraint \ref hashvectors are used when \ref tuple + * "tuples" are added to the \ref relation so as to identify the + * already contained \ref tuple "tuples" that contradict the addition + * by means of having the same constraint key. The already contained + * \ref tuple "tuples" are then "knocked out" from the relation by the + * new addition. + * + * \see relation_add * \related relation */ -extern int relation_add_constraint(relation *r,tupleschema *key); +extern int relation_add_constraint(relation *r,...); /** * \brief Add the tuple to the relation. @@ -129,4 +128,37 @@ extern vector *relation_delete(relation *r,tuple *query); */ extern void *relation_next(relation *r,vector_index *index,tuple *query); +/** + * \brief Lay out a dynamic \ref relation initializer for a relation + * wth the given column "types". + * + * This defines a \ref relation intializer that creates the \ref + * tupleschema for the given columns. + * + * \note The initializer cannot be used statically. + * + * The \b content \ref hashvector is a \ref nibble_index_level variant + * with an initial size of 16 slots. + * + * The constraints \ref vector is a \ref bitpair_index_level variant + * with initial size 0. + * + * The \b content \ref hashvector \b type is set up with an allocated + * \ref tupleschema that has an allocated \ref tuple that declares the + * column "types" view the given \ref itemkeyfun pointers. Any add + * constraints will need to clone that \ref tupleschema and then clear + * the column slots for the constraint value columns, typically by + * using \ref tupleschema_mask for this. + * + * \related relation + */ +#define RELATION(...) (relation) { \ + .content = { \ + .table = { .variant = nibble_index_levels, .size=16, .entries=0 }, \ + .fill = 0, .holes = 0, \ + .type = (itemkeyfun*) TUPLESCHEMA( __VA_ARGS__ ) \ + }, \ + .constraints = { .variant = bitpair_index_levels, .size=0, .entries=0 } \ +} + #endif