Ver código fonte

Add LSUP_graph_get(); fix LSUP_graph_size().

scossu 9 meses atrás
pai
commit
98f1d9f46f
3 arquivos alterados com 146 adições e 11 exclusões
  1. 27 3
      include/graph.h
  2. 51 8
      src/graph.c
  3. 68 0
      test/test_graph.c

+ 27 - 3
include/graph.h

@@ -40,6 +40,30 @@ LSUP_Graph *
 LSUP_graph_new (LSUP_Store *store, LSUP_Term *uri, LSUP_NSMap *nsm);
 
 
+/** @brief Create a temp graph from stored triples.
+ *
+ * The new graph is stored in a hash map and is made up of all the triples
+ * found in the store with the given context URI. The new graph URI is the
+ * same as the given context.
+ *
+ * @param[in] store Back end store handle. The store must exist.
+ *
+ * @param[in] uri URI of the graph to retrieve.
+ *
+ * @param[out] ct If not NULL, it will be populated with the number of triples
+ * found.
+ *
+ * @return New graph handle. It must be freed by the caller. If no matching
+ * context URI was found, NULL is returned.
+ */
+LSUP_Graph *
+LSUP_graph_get_txn (void *txn, LSUP_Store *store, LSUP_Term *uri, size_t *ct);
+
+
+/// Non-transactional version of #LSUP_graph_get_txn().
+#define LSUP_graph_get(...) LSUP_graph_get_txn (NULL, __VA_ARGS__)
+
+
 /** @brief Copy triples from a source graph into a destination one.
  *
  * The destination graph is not initialized here, so the copy is cumulative.
@@ -244,11 +268,11 @@ LSUP_graph_add_txn (
  *
  * @param[in] txn Transaction handle. It may be NULL.
  *
- * @param gr[in] Graph to delete triples from.
+ * @param[in] gr[in] Graph to delete triples from.
  *
- * @param ptn[in] Matching pattern. Any and all of s, p, o can be NULL.
+ * @param[in] s, p, o Matching pattern. Any and all of s, p, o can be NULL.
  *
- * @param ct[out] If not NULL it is populated with the number of triples
+ * @param[out] ct If not NULL it is populated with the number of triples
  *  deleted.
  */
 LSUP_rc

+ 51 - 8
src/graph.c

@@ -64,6 +64,42 @@ LSUP_graph_new (LSUP_Store *store, LSUP_Term *uri, LSUP_NSMap *nsm)
 }
 
 
+LSUP_Graph *
+LSUP_graph_get_txn (void *txn, LSUP_Store *store, LSUP_Term *uri, size_t *ct)
+{
+    LSUP_Buffer *sc = LSUP_term_serialize (uri);
+    void *it = store->sif->lookup_fn (
+            store->data, NULL, NULL, NULL, sc, NULL, NULL);
+
+    LSUP_Graph *gr = LSUP_graph_new (NULL, uri, NULL);
+    LSUP_BufferTriple *sspo = BTRP_DUMMY;
+    void *add_it = LSUP_graph_add_init_txn (txn, gr);
+
+    size_t _ct = 0;
+    while (store->sif->lu_next_fn (it, sspo, NULL) == LSUP_OK) {
+        // TODO This is inefficient, it's deserializing a buffer triple that
+        // will be re-serialized by LSUP_graph_add_iter.
+        LSUP_Triple *spo = LSUP_triple_new_from_btriple (sspo);
+        LSUP_graph_add_iter (add_it, spo);
+        LSUP_triple_free (spo);
+        _ct++;
+    }
+    LSUP_graph_add_done (add_it);
+    store->sif->lu_free_fn(it);
+    LSUP_buffer_free (sc);
+    LSUP_btriple_free_shallow (sspo);
+
+    // Do not create a new graph if no results were found.
+    if (_ct == 0) {
+        LSUP_graph_free (gr);
+        gr = NULL;
+    }
+    if (ct) *ct = _ct;
+
+    return gr;
+}
+
+
 LSUP_rc
 LSUP_graph_bool_op_txn (
         void *txn, const LSUP_bool_op op,
@@ -212,7 +248,17 @@ LSUP_graph_set_namespace (LSUP_Graph *gr, LSUP_NSMap *nsm)
 
 size_t
 LSUP_graph_size (const LSUP_Graph *gr)
-{ return gr->store->sif->size_fn (gr->store->data); }
+{
+    size_t ct = 0;
+    LSUP_Buffer *sc = LSUP_term_serialize (gr->uri);
+    void *it = gr->store->sif->lookup_fn (
+        gr->store->data, NULL, NULL, NULL, sc, NULL, &ct);
+    gr->store->sif->lu_free_fn (it);
+
+    LSUP_buffer_free (sc);
+
+    return ct;
+}
 
 
 bool
@@ -330,15 +376,13 @@ LSUP_graph_remove_txn (
         const LSUP_Term *s, const LSUP_Term *p, const LSUP_Term *o,
         size_t *ct)
 {
-    LSUP_rc rc;
-
     LSUP_Buffer
         *ss = LSUP_term_serialize (s),
         *sp = LSUP_term_serialize (p),
         *so = LSUP_term_serialize (o),
         *sc = LSUP_term_serialize (gr->uri);
 
-    rc = gr->store->sif->remove_fn (
+    LSUP_rc rc = gr->store->sif->remove_fn (
             gr->store->data, ss, sp, so, sc, txn, ct);
 
     LSUP_buffer_free (ss);
@@ -677,12 +721,11 @@ inline LSUP_rc
 graph_iter_alloc_buffers (LSUP_GraphIterator *it)
 {
     if (it->graph->store->sif->features & LSUP_STORE_COW) {
+        // Copy-on-wite store.
         it->sspo = BTRP_DUMMY;
-        CALLOC_GUARD (it->sspo->s, LSUP_MEM_ERR);
-        CALLOC_GUARD (it->sspo->p, LSUP_MEM_ERR);
-        CALLOC_GUARD (it->sspo->o, LSUP_MEM_ERR);
+        if (it->sspo == NULL) return LSUP_MEM_ERR;
     } else {
-        // TODO copy-on-retrieval stores. None yet.
+        // TODO copy-on-retrieval store. No implementations yet.
     }
 
     return LSUP_OK;

+ 68 - 0
test/test_graph.c

@@ -82,6 +82,63 @@ _graph_add (LSUP_StoreType type)
 }
 
 
+static int
+_graph_get (LSUP_StoreType type)
+{
+    const LSUP_StoreInt *sif = LSUP_store_int (type);
+    // Skip if the store doesn't support contexts.
+    if (!(sif->features & LSUP_STORE_CTX)) return 0;
+
+    if (sif->setup_fn) sif->setup_fn (NULL, true);
+
+    LSUP_Triple **trp = create_triples();
+
+    LSUP_Store *store = LSUP_store_new (type, NULL, 0);
+    LSUP_Graph
+        *gr1 = LSUP_graph_new (store, NULL, NULL),
+        *gr2 = LSUP_graph_new (store, NULL, NULL);
+
+    ASSERT (gr1 != NULL, "Error creating graph!");
+    ASSERT (gr2 != NULL, "Error creating graph!");
+
+
+    // Add 2 groups of triples to different graphs.
+    void *it1 = LSUP_graph_add_init (gr1);
+    for (size_t i = 0; i < 5; i++) {
+        LSUP_graph_add_iter(it1, trp[i]);
+    }
+    LSUP_graph_add_done (it1);
+
+    void *it2 = LSUP_graph_add_init (gr2);
+    for (size_t i = 5; i < NUM_TRP; i++) {
+        LSUP_graph_add_iter(it2, trp[i]);
+    }
+    LSUP_graph_add_done (it2);
+
+    EXPECT_INT_EQ (LSUP_graph_size (gr1), 5);
+    EXPECT_INT_EQ (LSUP_graph_size (gr2), 3);
+
+    size_t ct3, ct4;
+    LSUP_Graph
+        *gr3 = LSUP_graph_get (store, LSUP_graph_uri (gr1), &ct3),
+        *gr4 = LSUP_graph_get (store, LSUP_graph_uri (gr2), &ct4);
+
+    EXPECT_INT_EQ (LSUP_graph_size (gr3), LSUP_graph_size (gr1));
+    EXPECT_INT_EQ (LSUP_graph_size (gr4), LSUP_graph_size (gr2));
+
+    ASSERT (LSUP_graph_equals (gr1, gr3), "Graphs 1 and 3 are not equal!");
+    ASSERT (LSUP_graph_equals (gr2, gr4), "Graphs 2 and 4 are not equal!");
+
+    LSUP_graph_free (gr1);
+    LSUP_graph_free (gr2);
+    LSUP_graph_free (gr3);
+    LSUP_graph_free (gr4);
+    free_triples (trp);
+
+    return 0;
+}
+
+
 static int
 _graph_lookup (LSUP_StoreType type)
 {
@@ -330,6 +387,16 @@ BACKEND_TBL
 }
 
 
+static int test_graph_get() {
+#define ENTRY(a, b) \
+    if (_graph_get (LSUP_STORE_##a) != 0) return -1;
+BACKEND_TBL
+#undef ENTRY
+
+    return 0;
+}
+
+
 static int test_graph_lookup() {
 #define ENTRY(a, b) \
     if (_graph_lookup (LSUP_STORE_##a) != 0) return -1;
@@ -411,6 +478,7 @@ int graph_tests()
     RUN (test_environment);
     RUN (test_graph_new);
     RUN (test_graph_add);
+    RUN (test_graph_get);
     RUN (test_graph_lookup);
     RUN (test_graph_remove);
     RUN (test_graph_copy);