|
@@ -117,6 +117,7 @@ LSUP_graph_bool_op_txn (
|
|
/* BEGIN union block. */
|
|
/* BEGIN union block. */
|
|
|
|
|
|
if (op == LSUP_BOOL_UNION) {
|
|
if (op == LSUP_BOOL_UNION) {
|
|
|
|
+ // No need to use a transaction here: the graph is freed on failure.
|
|
rc = LSUP_graph_copy_contents (gr1, res);
|
|
rc = LSUP_graph_copy_contents (gr1, res);
|
|
PCHECK (rc, fail);
|
|
PCHECK (rc, fail);
|
|
rc = LSUP_graph_copy_contents (gr2, res);
|
|
rc = LSUP_graph_copy_contents (gr2, res);
|
|
@@ -127,8 +128,6 @@ LSUP_graph_bool_op_txn (
|
|
|
|
|
|
/* END union block. */
|
|
/* END union block. */
|
|
|
|
|
|
- /* BEGIN subtraction, intersection, XOR block. */
|
|
|
|
-
|
|
|
|
LSUP_Buffer
|
|
LSUP_Buffer
|
|
*res_sc = LSUP_term_serialize (res->uri),
|
|
*res_sc = LSUP_term_serialize (res->uri),
|
|
*gr1_sc = LSUP_term_serialize (gr1->uri),
|
|
*gr1_sc = LSUP_term_serialize (gr1->uri),
|
|
@@ -137,33 +136,65 @@ LSUP_graph_bool_op_txn (
|
|
LSUP_BufferTriple *sspo = BTRP_DUMMY;
|
|
LSUP_BufferTriple *sspo = BTRP_DUMMY;
|
|
size_t ct;
|
|
size_t ct;
|
|
|
|
|
|
|
|
+ // Handle transactions for graphs possibly in different storage back ends.
|
|
|
|
+ void
|
|
|
|
+ *lu1_txn = NULL,
|
|
|
|
+ *lu2_txn = NULL;
|
|
|
|
+
|
|
add_it = res->store->sif->add_init_fn (res->store->data, res_sc, txn);
|
|
add_it = res->store->sif->add_init_fn (res->store->data, res_sc, txn);
|
|
|
|
|
|
|
|
+ // If either source graph is in the same store as the destination and has
|
|
|
|
+ // an open transaction, reuse that transaction. A new reader cannot be
|
|
|
|
+ // opened in LMDB while a writer is open already.
|
|
|
|
+ if (
|
|
|
|
+ gr1->store->sif->features & LSUP_STORE_TXN
|
|
|
|
+ && gr1->store == res->store)
|
|
|
|
+ lu1_txn = res->store->sif->iter_txn_fn (add_it);
|
|
|
|
+ if (gr1->store->sif->features & LSUP_STORE_TXN) {
|
|
|
|
+ if (gr1->store == res->store)
|
|
|
|
+ lu2_txn = res->store->sif->iter_txn_fn (add_it);
|
|
|
|
+ else if (gr2->store == gr1->store)
|
|
|
|
+ lu2_txn = lu1_txn;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* BEGIN XOR block. */
|
|
|
|
+
|
|
if (op == LSUP_BOOL_XOR) {
|
|
if (op == LSUP_BOOL_XOR) {
|
|
// Add triples from gr2 if not found in gr1.
|
|
// Add triples from gr2 if not found in gr1.
|
|
lu2_it = gr2->store->sif->lookup_fn (
|
|
lu2_it = gr2->store->sif->lookup_fn (
|
|
- gr2->store->data, NULL, NULL, NULL, gr2_sc, NULL, txn);
|
|
|
|
|
|
+ gr2->store->data, NULL, NULL, NULL, gr2_sc, lu2_txn, NULL);
|
|
while (gr2->store->sif->lu_next_fn (lu2_it, sspo, NULL) == LSUP_OK) {
|
|
while (gr2->store->sif->lu_next_fn (lu2_it, sspo, NULL) == LSUP_OK) {
|
|
lu1_it = gr1->store->sif->lookup_fn (
|
|
lu1_it = gr1->store->sif->lookup_fn (
|
|
gr1->store->data, sspo->s, sspo->p, sspo->o, gr1_sc,
|
|
gr1->store->data, sspo->s, sspo->p, sspo->o, gr1_sc,
|
|
- txn, &ct);
|
|
|
|
- if (ct == 0)
|
|
|
|
|
|
+ lu1_txn, &ct);
|
|
|
|
+ if (ct == 0) {
|
|
res->store->sif->add_iter_fn (add_it, sspo);
|
|
res->store->sif->add_iter_fn (add_it, sspo);
|
|
|
|
+ rc = LSUP_OK;
|
|
|
|
+ }
|
|
gr1->store->sif->lu_free_fn (lu1_it);
|
|
gr1->store->sif->lu_free_fn (lu1_it);
|
|
}
|
|
}
|
|
gr2->store->sif->lu_free_fn (lu2_it);
|
|
gr2->store->sif->lu_free_fn (lu2_it);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* BEGIN subtraction and intersection block. */
|
|
|
|
+
|
|
lu1_it = gr1->store->sif->lookup_fn (
|
|
lu1_it = gr1->store->sif->lookup_fn (
|
|
- gr1->store->data, NULL, NULL, NULL, gr1_sc, txn, NULL);
|
|
|
|
|
|
+ gr1->store->data, NULL, NULL, NULL, gr1_sc, lu1_txn, NULL);
|
|
while (gr1->store->sif->lu_next_fn (lu1_it, sspo, NULL) == LSUP_OK) {
|
|
while (gr1->store->sif->lu_next_fn (lu1_it, sspo, NULL) == LSUP_OK) {
|
|
lu2_it = gr2->store->sif->lookup_fn (
|
|
lu2_it = gr2->store->sif->lookup_fn (
|
|
gr2->store->data, sspo->s, sspo->p, sspo->o, gr2_sc,
|
|
gr2->store->data, sspo->s, sspo->p, sspo->o, gr2_sc,
|
|
- txn, &ct);
|
|
|
|
|
|
+ lu2_txn, &ct);
|
|
|
|
+ if (UNLIKELY (!lu2_it)) {
|
|
|
|
+ rc = LSUP_DB_ERR;
|
|
|
|
+ gr1->store->sif->lu_free_fn (lu1_it);
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
// For XOR and subtraction, add if not found.
|
|
// For XOR and subtraction, add if not found.
|
|
// For intersection, add if found.
|
|
// For intersection, add if found.
|
|
- if ((ct == 0) ^ (op == LSUP_BOOL_INTERSECTION))
|
|
|
|
|
|
+ if ((ct == 0) ^ (op == LSUP_BOOL_INTERSECTION)) {
|
|
res->store->sif->add_iter_fn (add_it, sspo);
|
|
res->store->sif->add_iter_fn (add_it, sspo);
|
|
|
|
+ rc = LSUP_OK;
|
|
|
|
+ }
|
|
gr2->store->sif->lu_free_fn (lu2_it);
|
|
gr2->store->sif->lu_free_fn (lu2_it);
|
|
}
|
|
}
|
|
gr1->store->sif->lu_free_fn (lu1_it);
|
|
gr1->store->sif->lu_free_fn (lu1_it);
|
|
@@ -392,11 +423,6 @@ LSUP_graph_remove_txn (
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-/**
|
|
|
|
- * Copy triples from a source graph into a destination one.
|
|
|
|
- *
|
|
|
|
- * The destination graph is not initialized here, so the copy is cumulative.
|
|
|
|
- */
|
|
|
|
LSUP_rc
|
|
LSUP_rc
|
|
LSUP_graph_copy_contents_txn (
|
|
LSUP_graph_copy_contents_txn (
|
|
void *txn, const LSUP_Graph *src, LSUP_Graph *dest)
|
|
void *txn, const LSUP_Graph *src, LSUP_Graph *dest)
|