revised relation_add_constraint ABI and added convenience macros
[rrq/rrqmisc.git] / vector / relation.h
index c589176d3387601fae18fc29ad57ba954740ba26..c2e5293b8141425aeea418f93cf3286b7cbf20c7 100644 (file)
@@ -5,11 +5,14 @@
 #include <tupleitem.h>
 
 /**
- * A relation is an implementation of a tuple set with (optinal) key
- * constraints. The store is a hashvector whose "type" is a
+ * A relation is an implementation of a tuple set with (optional) key
+ * constraints. The store is a \ref hashvector whose \b type is a \ref
  * tupleschema that defines the columns. The key constraints are
- * represented as additional hashvectors whose tupleschemas are clones
- * of the column schema with some columns excluded.
+ * represented as additional \ref hashvector "hashvectors" whose \ref
+ * tupleschema "tupleschemas" are clones of the column schema with
+ * some columns excluded.
+ *
+ * \extends hashvector
  */
 typedef struct {
     /**
@@ -28,36 +31,134 @@ typedef struct {
 } relation;
 
 /**
- * Create a relation for the given tupleschema.
+ * \brief Create a relation for the given tupleschema.
+ *
+ * \param schema is the column schema
+ *
+ * \returns the allocated relation record.
+ *
+ * The given tupleschema is set up as the type of the content
+ * hashvector, which also is initialised as a nibble_index_levels
+ * variant vector.
+ *
+ * \related relation
  */
 extern relation *relation_create(tupleschema *schema);
 
 /**
- * Add a a key index to the relation by identifying the value part for
- * this index.
+ * \brief Add a key constraint to a \ref relation.
+ *
+ * \param r is the relation concerned.
+ *
+ * \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 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_addindex(relation *r,tupleschema *ts);
-
+extern int relation_add_constraint(relation *r,...);
 
 /**
- * \brief Add a tuple to a relation.
- * \param r is th relation concerned.
- * \param t is the tuple to add.
+ * \brief Add the tuple to the relation.
+ *
+ * \param r is the \ref relation concerned.
+ *
+ * \param t is the \ref tuple to add.
  *
  * \returns a vector of all knocked out tuples.
+ *
+ * This function adds the \ref tuple \b t to the \ref relation \b r,
+ * and it returns a \ref vector (single_index_level variant) of all
+ * same-key constraint tuples. The returned vector is malloc-ed and it
+ * must be free-ed by the caller. If the tuple is already contained or
+ * there are no other same-key tuples knocked out, then \b 0 is
+ * returned.
+ *
+ * \related relation
  */
 extern vector *relation_add(relation *r,tuple *t);
 
 /**
- * \brief Delete all tuples matching to the query.
- * \returns all deleted tuples.
+ * \brief Delete all tuples matching to the query \ref tuple fromt the
+ * \ref relation.
+ *
+ * \param r is the \ref relation concerned.
+ *
+ * \param t is the \ref tuple to delete.
+ *
+ * \returns a \vector vector of all knocked out tuples, i.e. the
+ * same-key tuples, if any, contained in the relation
+ *
+ * Note that deletion uses a "query" tuple, which means that some
+ * columns may be null to mark that them match to any value.
+ *
+ * \related relation
  */
 extern vector *relation_delete(relation *r,tuple *query);
 
 /**
- * \brief Return next tuple matching the query at or after the index.
- * \returns any such matching tuple and updates *index to its index.
+ * \brief Return the next \ref tuple in the \ref relation that matches
+ * to the query \ref tuple, at or after the index.
+ *
+ * \param r is the \ref relation concerned.
+ *
+ * \param index is a pointer to the \ref vector index to update.
+ *
+ * \param query is a query \tuple tuple for selection of certain
+ * column values.
+ *
+ * \returns any such matching \tuple tuple and an updateed *index.
+ *
+ * \related relation
  */
 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