Browse Source

Store relative URIs in graph.

scossu 3 weeks ago
parent
commit
7af3f1c650
5 changed files with 112 additions and 38 deletions
  1. 32 32
      docs/dev/deps.dot
  2. BIN
      docs/dev/deps.pdf
  3. 3 2
      include/graph.h
  4. 39 4
      src/graph.c
  5. 38 0
      test/test_graph.c

+ 32 - 32
docs/dev/deps.dot

@@ -5,45 +5,45 @@ digraph "source tree" {
     fontsize="16";
     fontname="Helvetica";
 	clusterrank="local";
-	"environment" -> "term"
-	"lsup_rdf" -> "codec_ttl"
-	"store_mdb" -> "store_interface"
-	"grammar_nt" -> "codec"
-	"lsup_rdf" -> "codec_nt"
+	"environment" -> "bootstrap"
+	"core" -> "log"
+	"parser_nt" -> "tokens_nt"
+	"store" -> "store_mdb"
+	"parser_ttl" -> "codec"
+	"term" -> "namespace"
+	"store" -> "store_htable"
 	"namespace" -> "hashmap"
-	"py_graph" -> "graph"
-	"codec_nt" -> "parser_nt"
-	"buffer" -> "core"
+	"py_lsup_rdf" -> "py_graph"
+	"lsup_rdf" -> "codec_nt"
+	"graph" -> "store"
 	"term" -> "buffer"
-	"graph" -> "term"
-	"store_htable" -> "store_interface"
-	"py_graph" -> "codec_ttl"
+	"py_term" -> "term"
 	"parser_ttl" -> "tokens_ttl"
+	"py_graph" -> "codec_ttl"
 	"store_htable" -> "hashmap"
-	"py_graph" -> "codec_nt"
-	"py_lsup_rdf" -> "py_graph"
-	"py_graph" -> "py_triple"
-	"store_htable" -> "buffer"
-	"store" -> "store_mdb"
-	"codec_ttl" -> "parser_ttl"
+	"store_mdb" -> "store_interface"
+	"buffer" -> "core"
+	"py_term" -> "py_namespace"
+	"parser_nt" -> "codec"
+	"codec_nt" -> "parser_nt"
+	"graph" -> "term"
+	"profile" -> "lsup_rdf"
+	"grammar_nt" -> "codec"
+	"graph" -> "environment"
+	"lsup_rdf" -> "codec_ttl"
+	"py_graph" -> "graph"
 	"term" -> "tpl"
-	"store_interface" -> "environment"
+	"codec_ttl" -> "parser_ttl"
 	"namespace" -> "core"
-	"store" -> "store_htable"
+	"py_graph" -> "codec_nt"
+	"py_triple" -> "py_term"
+	"store_interface" -> "environment"
+	"py_namespace" -> "namespace"
 	"grammar_ttl" -> "codec"
-	"py_term" -> "py_namespace"
-	"graph" -> "environment"
-	"term" -> "namespace"
+	"store_htable" -> "buffer"
+	"store_htable" -> "store_interface"
+	"py_graph" -> "py_triple"
+	"environment" -> "term"
 	"store_mdb" -> "buffer"
-	"graph" -> "store"
-	"core" -> "log"
-	"parser_ttl" -> "codec"
-	"py_triple" -> "py_term"
-	"parser_nt" -> "codec"
-	"profile" -> "lsup_rdf"
 	"codec" -> "graph"
-	"parser_nt" -> "tokens_nt"
-	"py_namespace" -> "namespace"
-	"environment" -> "bootstrap"
-	"py_term" -> "term"
 }

BIN
docs/dev/deps.pdf


+ 3 - 2
include/graph.h

@@ -239,7 +239,7 @@ LSUP_graph_contains (const LSUP_Graph *gr, const LSUP_Triple *spo);
 /** @brief Initialize an iterator to add triples.
  *
  * @param[in] txn Transaction handle. It may be NULL. If not NULL, its handle
- * will be bound to the iterator handle for its whole lifa cycle.
+ * will be bound to the iterator handle for its whole life cycle.
  *
  * @param[in] gr Graph to add to. It is added to the iterator state.
  *
@@ -258,7 +258,8 @@ LSUP_graph_add_init_txn (void *txn, LSUP_Graph *gr);
  *
  * @param[in] it Iterator obtained with #LSUP_graph_add_init_txn().
  *
- * @param[in] spo Triple to add. Caller retains ownership.
+ * @param[in] spo Triple to add. Caller retains ownership. NOTE: the triple
+ *  subject and object, if IRIRefs, are stored as relative to the graph URI.
  */
 LSUP_rc
 LSUP_graph_add_iter (LSUP_GraphIterator *it, const LSUP_Triple *spo);

+ 39 - 4
src/graph.c

@@ -327,8 +327,30 @@ LSUP_graph_add_iter (LSUP_GraphIterator *it, const LSUP_Triple *spo)
             "Adding triple {%s, %s, %s} to %s",
             spo->s->data, spo->p->data, spo->o->data,
             LSUP_graph_uri(it->graph)->data);
-    LSUP_BufferTriple *sspo = LSUP_triple_serialize (spo);
+
+    // Make relative s and o.
+    LSUP_Term *rel_s, *rel_o;
+    if (LSUP_IS_IRI (spo->s))
+        rel_s = LSUP_iriref_relative (it->graph->uri, spo->s);
+    else rel_s = spo->s;
+    if (LSUP_IS_IRI (spo->o))
+        rel_o = LSUP_iriref_relative (it->graph->uri, spo->o);
+    else rel_o = spo->o;
+
+    LSUP_Triple *rel_spo = LSUP_triple_new (rel_s, spo->p, rel_o);
+    LOG_TRACE (
+            "Relative triple: {%s %s %s}",
+            rel_s->data, spo->p->data, rel_o->data);
+
+    // Serialize relative triple.
+    LSUP_BufferTriple *sspo = LSUP_triple_serialize (rel_spo);
     if (UNLIKELY (!sspo)) return LSUP_MEM_ERR;
+
+    // Selectively free triple members and structure.
+    if (rel_s != spo->s) LSUP_term_free (rel_s);
+    if (rel_o != spo->o) LSUP_term_free (rel_o);
+    free (rel_spo);
+
     const LSUP_StoreInt *sif = it->graph->store->sif;
 
     LSUP_rc rc;
@@ -460,12 +482,25 @@ LSUP_graph_lookup_txn (
     LSUP_GraphIterator *it;
     MALLOC_GUARD (it, NULL);
 
+    // Make relative s and o.
+    LSUP_Term *rel_s, *rel_o;
+    if (s && LSUP_IS_IRI (s))
+        rel_s = LSUP_iriref_relative (gr->uri, s);
+    else rel_s = (LSUP_Term *)s;
+    if (o && LSUP_IS_IRI (o))
+        rel_o = LSUP_iriref_relative (gr->uri, o);
+    else rel_o = (LSUP_Term *)o;
+
     LSUP_Buffer
-        *ss = LSUP_term_serialize (s),
+        *ss = LSUP_term_serialize (rel_s),
         *sp = LSUP_term_serialize (p),
-        *so = LSUP_term_serialize (o),
+        *so = LSUP_term_serialize (rel_o),
         *sc = LSUP_term_serialize (gr->uri);
 
+    // Selectively free triple members and structure.
+    if (rel_s != s) LSUP_term_free (rel_s);
+    if (rel_o != o) LSUP_term_free (rel_o);
+
     it->data = gr->store->sif->lookup_fn (
             gr->store->data, ss, sp, so, sc, txn, ct);
 
@@ -482,7 +517,7 @@ LSUP_graph_lookup_txn (
     it->graph = gr;
 
     if (it->graph->store->sif->features & LSUP_STORE_COW) {
-        // Copy-on-wite store.
+        // Copy-on-write store.
         it->sspo = BTRP_DUMMY;
         if (UNLIKELY (it->sspo == NULL)) return NULL;
         it->sspo->s->flags |= LSUP_BUF_BORROWED;

+ 38 - 0
test/test_graph.c

@@ -589,6 +589,43 @@ static int test_graph_copy()
 }
 
 
+static int test_graph_relative()
+{
+    LSUP_Term
+        *s = LSUP_iriref_new ("http://onto.knowledgetx.net/gr1/s1", NULL),
+        *p = LSUP_iriref_new ("http://onto.knowledgetx.net/vocab/p1", NULL),
+        *o = LSUP_iriref_new ("http://onto.knowledgetx.net/gr1/o1", NULL),
+        *c = LSUP_iriref_new ("http://onto.knowledgetx.net/gr1/", NULL),
+        *rel_s = LSUP_iriref_relative (c, s),
+        *rel_o = LSUP_iriref_relative (c, o);
+    LSUP_Triple *spo[2] = {
+        LSUP_triple_new (s, p, o),
+        NULL
+    };
+    LSUP_Triple *rel_spo = LSUP_triple_new (rel_s, p, rel_o);
+
+    LSUP_Store *store = LSUP_store_new (LSUP_STORE_MDB, NULL, 0);
+    LSUP_Graph *gr = LSUP_graph_new (store, c, NULL);
+
+    size_t ct;
+    LSUP_graph_add (gr, spo, &ct);
+
+    // Both absolute and relative IRIs should be found.
+    ASSERT (LSUP_graph_contains (gr, rel_spo), "Relative triple not found!");
+    ASSERT (LSUP_graph_contains (gr, spo[0]), "Absolute triple not found!");
+
+    LSUP_triple_free (spo[0]);
+    LSUP_term_free (rel_s);
+    LSUP_term_free (rel_o);
+    LSUP_term_free (c);
+    free (rel_spo);
+    LSUP_graph_free (gr);
+    LSUP_store_free (store);
+
+    return 0;
+}
+
+
 int graph_tests()
 {
     RUN (test_environment);
@@ -600,6 +637,7 @@ int graph_tests()
     RUN (test_graph_remove);
     RUN (test_graph_copy);
     RUN (test_graph_txn);
+    RUN (test_graph_relative);
 
     return 0;
 }