revised relation_add_constraint ABI and added convenience macros
authorRalph Ronnquist <ralph.ronnquist@gmail.com>
Fri, 8 Jul 2022 13:35:59 +0000 (23:35 +1000)
committerRalph Ronnquist <ralph.ronnquist@gmail.com>
Fri, 8 Jul 2022 13:35:59 +0000 (23:35 +1000)
vector/relation.c
vector/relation.h

index e7469de74b203b3b56ef8f6d45a2f9329bfa6f91..6777d9a5ae19dc9bdea0587ca9f844a93d80bf76 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdarg.h>
 #include <stdlib.h>
 #include <relation.h>
 
@@ -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 );
 }
+
index f76f1bb4fa3976bba435477c13871e6e34be13d8..c2e5293b8141425aeea418f93cf3286b7cbf20c7 100644 (file)
@@ -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