Volksdata 1.0b7
RDF library
Loading...
Searching...
No Matches
graph.c
Go to the documentation of this file.
1#include "volksdata/graph.h"
2
3/*
4 * Data types.
5 */
6
11
13 const VOLK_Graph * graph;
14 void * data;
15 size_t ct;
21};
22
23
24/*
25 * Static prototypes.
26 */
27
28inline static VOLK_rc
29graph_iter_next_buffer (VOLK_GraphIterator *it);
30
31
32#define ENTRY(a, b) (be) == (VOLK_STORE_##a) ||
33static inline bool
34check_backend (VOLK_StoreType be)
35{ return (BACKEND_TBL false); }
36#undef ENTRY
37
38
39/*
40 * Graph API.
41 */
42
43VOLK_Graph *
44VOLK_graph_new (VOLK_Store *store, const char *uri_str)
45{
46 // Create a HTable graph by default.
47 VOLK_Graph *gr;
48 MALLOC_GUARD (gr, NULL);
49
50 gr->store = (store) ? store : VOLK_store_new (
51 VOLK_STORE_HTABLE, NULL, 0, false);
52
53 gr->uri =
54 uri_str? VOLK_iriref_new (uri_str) :
55 VOLK_iriref_new (NULL);
56
57 log_debug ("Graph created.");
58 return gr;
59}
60
61
62VOLK_Graph *
64 void *txn, VOLK_Store *store, const VOLK_Term *uri, size_t *ct)
65{
67 void *it = store->sif->lookup_fn (
68 store->data, NULL, NULL, NULL, sc, NULL, NULL);
69
70 VOLK_Graph *gr = VOLK_graph_new (NULL, uri->data);
72 void *add_it = VOLK_graph_add_init_txn (txn, gr);
73
74 size_t _ct = 0;
75 while (store->sif->lu_next_fn (it, sspo, NULL) == VOLK_OK) {
76 // This is deserializing a buffer triple that will be re-serialized by
77 // VOLK_graph_add_iter. But it's necessary to relativize URIs.
79 VOLK_graph_add_iter (add_it, spo);
80 VOLK_triple_free (spo);
81 _ct++;
82 }
83 VOLK_graph_iter_free (add_it);
84 store->sif->lu_free_fn(it);
86 VOLK_btriple_free (sspo);
87
88 // Do not create a new graph if no results were found.
89 if (_ct == 0) {
90 VOLK_graph_free (gr);
91 gr = NULL;
92 }
93 if (ct) *ct = _ct;
94
95 return gr;
96}
97
98
101 void *txn, const VOLK_bool_op op,
102 const VOLK_Graph *gr1, const VOLK_Graph *gr2, VOLK_Graph *res)
103{
105 if (UNLIKELY (
106 op != VOLK_BOOL_UNION
107 && op != VOLK_BOOL_SUBTRACTION
109 && op != VOLK_BOOL_XOR)) {
110 log_error ("Invalid boolean operation: %d.", op);
111
112 return VOLK_VALUE_ERR;
113 }
114
115 /* BEGIN union block. */
116
117 if (op == VOLK_BOOL_UNION) {
118 // No need to use a transaction here: the graph is freed on failure.
119 rc = VOLK_graph_copy_contents (gr1, res, NULL, NULL, NULL);
120 PCHECK (rc, fail);
121 rc = VOLK_graph_copy_contents (gr2, res, NULL, NULL, NULL);
122 PCHECK (rc, fail);
123
124 return VOLK_OK;
125 }
126
127 /* END union block. */
128
130 *res_sc = VOLK_term_serialize (res->uri),
131 *gr1_sc = VOLK_term_serialize (gr1->uri),
132 *gr2_sc = VOLK_term_serialize (gr2->uri);
133 void *lu1_it, *lu2_it, *add_it;
135 size_t ct;
136
137 // Handle transactions for graphs possibly in different storage back ends.
138 void
139 *lu1_txn = NULL,
140 *lu2_txn = NULL,
141 *res_txn = NULL;
142 // Whether gr1 or gr2 txn will be open independently from res txn.
143 bool
144 open_txn1 = false,
145 open_txn2 = false;
146
147 add_it = res->store->sif->add_init_fn (res->store->data, res_sc, txn);
148
149 if (res->store->sif->features & VOLK_STORE_TXN)
150 res_txn = res->store->sif->iter_txn_fn (add_it);
151
152 /* If either source graph is in the same store as the destination and has
153 * an open transaction, reuse that transaction. A new reader cannot be
154 * opened in LMDB while a writer is open already.
155 */
156 // Handle gr1 transaction.
157 if (gr1->store->sif->features & VOLK_STORE_TXN) {
158 if (gr1->store == res->store) lu1_txn = res_txn;
159 // FIXME: MDB_RDONLY is implementation-specific and doesn't belong here.
160 else {
161 CHECK (gr1->store->sif->txn_begin_fn (
162 gr1->store->data, MDB_RDONLY, &lu1_txn), fail);
163 open_txn1 = true;
164 }
165 }
166
167 // Handle gr2 transaction.
168 if (gr2->store->sif->features & VOLK_STORE_TXN) {
169 if (gr2->store == res->store) lu2_txn = res_txn;
170 else if (gr2->store == gr1->store) lu2_txn = lu1_txn;
171 // FIXME: see above.
172 else {
173 CHECK (gr2->store->sif->txn_begin_fn (
174 gr2->store->data, MDB_RDONLY, &lu2_txn), fail);
175 open_txn2 = true;
176 }
177 }
178 log_trace (
179 "lu1_txn: %p ; lu2_txn: %p ; res_txn: %p",
180 lu1_txn, lu2_txn, res_txn);
181
182 /* BEGIN XOR block. */
183
184 if (op == VOLK_BOOL_XOR) {
185 // Add triples from gr2 if not found in gr1.
186 lu2_it = gr2->store->sif->lookup_fn (
187 gr2->store->data, NULL, NULL, NULL, gr2_sc, lu2_txn, NULL);
188 while (gr2->store->sif->lu_next_fn (lu2_it, sspo, NULL) == VOLK_OK) {
189 lu1_it = gr1->store->sif->lookup_fn (
190 gr1->store->data, sspo->s, sspo->p, sspo->o, gr1_sc,
191 lu1_txn, &ct);
192 if (ct == 0) {
193 res->store->sif->add_iter_fn (add_it, sspo);
194 rc = VOLK_OK;
195 }
196 gr1->store->sif->lu_free_fn (lu1_it);
197 }
198 gr2->store->sif->lu_free_fn (lu2_it);
199 }
200
201 /* BEGIN subtraction and intersection block. */
202
203 lu1_it = gr1->store->sif->lookup_fn (
204 gr1->store->data, NULL, NULL, NULL, gr1_sc, lu1_txn, NULL);
205 while (gr1->store->sif->lu_next_fn (lu1_it, sspo, NULL) == VOLK_OK) {
206 lu2_it = gr2->store->sif->lookup_fn (
207 gr2->store->data, sspo->s, sspo->p, sspo->o, gr2_sc,
208 lu2_txn, &ct);
209 if (UNLIKELY (!lu2_it)) {
210 rc = VOLK_DB_ERR;
211 gr1->store->sif->lu_free_fn (lu1_it);
212 goto fail;
213 }
214 // For XOR and subtraction, add if not found.
215 // For intersection, add if found.
216 if ((ct == 0) ^ (op == VOLK_BOOL_INTERSECTION)) {
217 res->store->sif->add_iter_fn (add_it, sspo);
218 rc = VOLK_OK;
219 }
220 gr2->store->sif->lu_free_fn (lu2_it);
221 }
222 gr1->store->sif->lu_free_fn (lu1_it);
223
224 if (open_txn1) gr1->store->sif->txn_commit_fn (lu1_txn);
225 if (open_txn2) gr2->store->sif->txn_commit_fn (lu2_txn);
226
227 res->store->sif->add_done_fn (add_it);
228 VOLK_btriple_free (sspo);
229 VOLK_buffer_free (res_sc);
230 VOLK_buffer_free (gr1_sc);
231 VOLK_buffer_free (gr2_sc);
232
233 /* END subtraction, intersection, XOR block. */
234
235 return rc;
236
237fail:
238 if (lu1_txn) gr1->store->sif->txn_abort_fn (lu1_txn);
239 if (lu2_txn) gr2->store->sif->txn_abort_fn (lu2_txn);
240 VOLK_graph_free (res);
241 return rc;
242}
243
244
245void
246VOLK_graph_free (VOLK_Graph *gr)
247{
248 if (UNLIKELY (!gr)) return;
249
250 VOLK_term_free (gr->uri);
251 // If the store is embedded, it goes away with the associated graph.
252 if (gr->store->sif->features & VOLK_STORE_EMBED) {
253 gr->store->sif->free_fn (gr->store->data);
254 free (gr->store->id);
255 free (gr->store);
256 }
257
258 free (gr);
259}
260
261
262const VOLK_Term *
263VOLK_graph_uri (const VOLK_Graph *gr) { return gr->uri; }
264
265
267VOLK_graph_store (const VOLK_Graph *gr)
268{ return gr->store; }
269
270
272VOLK_graph_set_uri (VOLK_Graph *gr, const char *uri_str)
273{
274 VOLK_rc rc = VOLK_OK;
275 VOLK_Buffer *old_sc = NULL, *new_sc = NULL;
276
277 VOLK_Term *uri = VOLK_iriref_new (uri_str);
278 if (UNLIKELY (!uri)) {
279 rc = VOLK_MEM_ERR;
280 goto finally;
281 }
282
283 // Update context for triples in the graph.
284 if (gr->store->sif->features & VOLK_STORE_CTX) {
285 old_sc = VOLK_term_serialize (gr->uri);
286 new_sc = VOLK_term_serialize (uri);
287 if (UNLIKELY (!old_sc || !new_sc)) {
288 rc = VOLK_MEM_ERR;
289 goto finally;
290 }
291
292 PCHECK (rc = gr->store->sif->update_ctx_fn (
293 gr->store->data, old_sc, new_sc, NULL), finally);
294
295 // Overall success even if rc of underlying fn was VOLK_NOACTION.
296 if (rc == VOLK_NOACTION) rc = VOLK_OK;
297 }
298
299 VOLK_term_free (gr->uri);
300 gr->uri = uri;
301
302finally:
303 if (old_sc) VOLK_buffer_free (old_sc);
304 if (new_sc) VOLK_buffer_free (new_sc);
305
306 return rc;
307}
308
309
310size_t
311VOLK_graph_size (const VOLK_Graph *gr)
312{
313 size_t ct = 0;
314 VOLK_Buffer *sc = VOLK_term_serialize (gr->uri);
315 void *it = gr->store->sif->lookup_fn (
316 gr->store->data, NULL, NULL, NULL, sc, NULL, &ct);
317 if (!it) {
318 log_error ("Error initializing lookup.");
319 ct = -1;
320 }
321 gr->store->sif->lu_free_fn (it);
322
323 VOLK_buffer_free (sc);
324
325 return ct;
326}
327
328
329bool
330VOLK_graph_equals (const VOLK_Graph *gr1, const VOLK_Graph *gr2)
331{
332 VOLK_Graph *res = VOLK_graph_new (NULL, NULL);
333 VOLK_graph_bool_op (VOLK_BOOL_XOR, gr1, gr2, res);
334 bool ret = (VOLK_graph_size (res) == 0);
335
336 VOLK_graph_free (res);
337
338 return ret;
339}
340
341
342VOLK_GraphIterator *
343VOLK_graph_add_init_txn (void *txn, VOLK_Graph *gr)
344{
345 VOLK_GraphIterator *it;
346 CALLOC_GUARD (it, NULL);
347
348 VOLK_Buffer *sc = VOLK_term_serialize (gr->uri);
349
350 it->data = gr->store->sif->add_init_fn (gr->store->data, sc, txn);
351 VOLK_buffer_free (sc);
352
353 it->graph = gr;
354
355 return it;
356}
357
358
360VOLK_graph_add_iter (VOLK_GraphIterator *it, const VOLK_Triple *spo)
361{
362 log_trace (
363 "Adding triple {%s, %s, %s} to %s",
364 spo->s->data, spo->p->data, spo->o->data,
365 VOLK_graph_uri(it->graph)->data);
366
367 // Make relative s and o.
368 VOLK_Term *rel_s, *rel_o;
369 if (spo->s->type == VOLK_TERM_IRIREF)
370 rel_s = VOLK_iriref_new_rel (it->graph->uri, spo->s);
371 else rel_s = spo->s;
372 if (spo->o->type == VOLK_TERM_IRIREF)
373 rel_o = VOLK_iriref_new_rel (it->graph->uri, spo->o);
374 else rel_o = spo->o;
375
376 VOLK_Triple *rel_spo = VOLK_triple_new (rel_s, spo->p, rel_o);
377 log_trace (
378 "Adding relative triple: {%s, %s, %s}",
379 rel_s->data, spo->p->data, rel_o->data);
380
381 // Serialize relative triple.
383 NLRCCK (sspo, VOLK_MEM_ERR);
384
385 // Selectively free triple members and structure.
386 if (rel_s != spo->s) VOLK_term_free (rel_s);
387 if (rel_o != spo->o) VOLK_term_free (rel_o);
388 free (rel_spo);
389
390 const VOLK_StoreInt *sif = it->graph->store->sif;
391
392 VOLK_rc rc;
393
394 PCHECK (rc = sif->add_iter_fn (it->data, sspo), finally);
395
396 // Store datatype term permanently.
397 if (rc == VOLK_OK && sif->add_term_fn) {
398 for (int i = 0; i < 3; i++) {
399 VOLK_Term *term = VOLK_triple_pos (spo, i);
400 if (term->type == VOLK_TERM_LITERAL) {
401 VOLK_Buffer *ser_dtype = VOLK_term_serialize (term->datatype);
402 void *txn =
403 sif->features & VOLK_STORE_TXN ?
404 sif->iter_txn_fn (it->data) : NULL;
405 VOLK_rc term_rc = sif->add_term_fn (
406 it->graph->store->data, ser_dtype, txn);
407 PCHECK (term_rc, finally);
408 VOLK_buffer_free (ser_dtype);
409 }
410 }
411 }
412
413
414finally:
415 VOLK_btriple_free (sspo);
416
417 return rc;
418}
419
420
423 void *txn, VOLK_Graph *gr, VOLK_Triple *const *trp, size_t *ct)
424{
426
427 // Initialize iterator.
428 VOLK_GraphIterator *it = VOLK_graph_add_init_txn (txn, gr);
429
430 if (ct) *ct = 0;
431 // Serialize and insert RDF triples.
432 for (size_t i = 0; trp[i] != NULL; i++) {
433 log_trace ("Inserting triple #%lu", i);
434
435 VOLK_rc db_rc = VOLK_graph_add_iter (it, trp[i]);
436
437 if (db_rc == VOLK_OK) {
438 rc = VOLK_OK;
439 if (ct) (*ct)++;
440 // A duplicate will return VOLK_NOACTION and not increment ct.
441 }
442 if (UNLIKELY (db_rc < 0)) {
443 rc = db_rc;
444 goto finally;
445 }
446 }
447
448finally:
450
451 return rc;
452}
453
454
457 void *txn, VOLK_Graph *gr,
458 const VOLK_Term *s, const VOLK_Term *p, const VOLK_Term *o,
459 size_t *ct)
460{
462 *ss = VOLK_term_serialize (s),
463 *sp = VOLK_term_serialize (p),
464 *so = VOLK_term_serialize (o),
465 *sc = VOLK_term_serialize (gr->uri);
466
467 log_debug (
468 "Removing triples by terms: %s %s %s",
469 s ? s->data : "<nil>",
470 p ? p->data : "<nil>",
471 o ? o->data : "<nil>"
472 );
473
474 VOLK_rc rc = gr->store->sif->remove_fn (
475 gr->store->data, ss, sp, so, sc, txn, ct);
476
477 VOLK_buffer_free (ss);
478 VOLK_buffer_free (sp);
479 VOLK_buffer_free (so);
480 VOLK_buffer_free (sc);
481
482 return rc;
483}
484
485
488 void *txn, const VOLK_Graph *src, VOLK_Graph *dest,
489 const VOLK_Term *s, const VOLK_Term *p, const VOLK_Term *o)
490{
492
493 VOLK_GraphIterator *it = VOLK_graph_lookup_txn (txn, src, s, p, o, NULL);
494
495 VOLK_Triple *spo = NULL;
496 VOLK_GraphIterator *add_it = VOLK_graph_add_init_txn (txn, dest);
497 while (VOLK_graph_iter_next (it, &spo) != VOLK_END) {
498 VOLK_rc add_rc = VOLK_graph_add_iter (add_it, spo);
499 VOLK_triple_free (spo);
500 if (LIKELY (add_rc == VOLK_OK)) rc = VOLK_OK;
501 else if (add_rc < 0) {
502 rc = add_rc;
503 break;
504 }
505 }
506
507 VOLK_graph_iter_free (add_it);
509
510 return rc;
511}
512
513
514VOLK_GraphIterator *
516 void *txn, const VOLK_Graph *gr,
517 const VOLK_Term *s, const VOLK_Term *p, const VOLK_Term *o,
518 size_t *ct)
519{
520 VOLK_GraphIterator *it;
521 MALLOC_GUARD (it, NULL);
522
523 // Make relative s and o.
524 VOLK_Term *rel_s, *rel_o;
525 if (s && s->type == VOLK_TERM_IRIREF) {
526 rel_s = VOLK_iriref_new_rel (gr->uri, s);
527 log_debug ("Relative S lookup: %s", rel_s->data);
528 } else rel_s = (VOLK_Term *)s;
529 if (o && o->type == VOLK_TERM_IRIREF) {
530 rel_o = VOLK_iriref_new_rel (gr->uri, o);
531 log_debug ("Relative O lookup: %s", rel_o->data);
532 } else rel_o = (VOLK_Term *)o;
533
535 *ss = VOLK_term_serialize (rel_s),
536 *sp = VOLK_term_serialize (p),
537 *so = VOLK_term_serialize (rel_o),
538 *sc = VOLK_term_serialize (gr->uri);
539
540 // Selectively free triple members and structure.
541 if (rel_s != s) VOLK_term_free (rel_s);
542 if (rel_o != o) VOLK_term_free (rel_o);
543
544 it->data = gr->store->sif->lookup_fn (
545 gr->store->data, ss, sp, so, sc, txn, ct);
546
547 VOLK_buffer_free (ss);
548 VOLK_buffer_free (sp);
549 VOLK_buffer_free (so);
550 VOLK_buffer_free (sc);
551
552 if (UNLIKELY (!it->data)) {
553 free (it);
554 return NULL;
555 }
556
557 it->graph = gr;
558
559 if (it->graph->store->sif->features & VOLK_STORE_COW) {
560 // Copy-on-write store.
561 it->sspo = BTRP_DUMMY;
562 if (UNLIKELY (it->sspo == NULL)) return NULL;
563 it->sspo->s->flags |= VOLK_BUF_BORROWED;
564 it->sspo->p->flags |= VOLK_BUF_BORROWED;
565 it->sspo->o->flags |= VOLK_BUF_BORROWED;
566 } else {
567 // TODO copy-on-retrieval store. No implementations yet.
568 }
569
570 return it;
571}
572
573
575VOLK_graph_iter_next (VOLK_GraphIterator *it, VOLK_Triple **spo_p)
576{
577 VOLK_rc rc = graph_iter_next_buffer (it);
578 PRCCK (rc);
579 if (rc != VOLK_OK) return rc;
580
582 VOLK_term_new_from_buffer (it->sspo->s),
583 VOLK_term_new_from_buffer (it->sspo->p),
584 VOLK_term_new_from_buffer (it->sspo->o)
585 );
586 if (UNLIKELY (!spo)) return VOLK_MEM_ERR;
587
588 *spo_p = spo;
589
590 return VOLK_OK;
591}
592
593
594const VOLK_Graph *
595VOLK_graph_iter_graph (VOLK_GraphIterator *it)
596{ return it->graph; }
597
598
599bool
600VOLK_graph_iter_is_add (VOLK_GraphIterator *it)
601{ return it->sspo == NULL; }
602
603
604void
605VOLK_graph_iter_free (VOLK_GraphIterator *it)
606{
607 if (UNLIKELY (!it)) return;
608
609 if (it->sspo) {
610 // Free lookup iterator.
611 it->graph->store->sif->lu_free_fn (it->data);
612
613 /*
614 * This deallocates resources properly by preserving borrowed pointers
615 * from the store in case of VOLK_STORE_COW stores.
616 */
617 if (it->graph->store->sif->features & VOLK_STORE_COW) {
618 VOLK_btriple_free (it->sspo);
619 log_debug ("Freeing dummy triple @ %p", it->sspo);
620 } else {
621 // TODO copy-on-retrieval stores. None yet.
622 }
623
624 } else {
625 // Add iterator has sspo == NULL. Use add_done_fn for that.
626 it->graph->store->sif->add_done_fn (it->data);
627 }
628
629 free (it);
630}
631
632
635{
636 VOLK_Buffer **tdata = VOLK_store_ctx_list_txn (store, txn);
637 if (UNLIKELY (!tdata)) return NULL;
638
640
641 size_t i = 0;
642 while (tdata[i]) {
643 VOLK_Term *t = VOLK_term_new_from_buffer (tdata[i]);
644 VOLK_rc rc = VOLK_term_set_add (ts, t, NULL);
645 VOLK_buffer_free (tdata[i]);
646 if (UNLIKELY (rc != VOLK_OK)) {
647 VOLK_term_free (t);
649
650 return NULL;
651 }
652 i++;
653 }
654 free (tdata);
655
656 return ts;
657}
658
659
660bool
661VOLK_graph_contains (const VOLK_Graph *gr, const VOLK_Triple *spo)
662{
663 VOLK_GraphIterator *it = VOLK_graph_lookup (
664 gr, spo->s, spo->p, spo->o, NULL);
665 VOLK_Triple *tmp_spo = NULL;
666 bool rc = VOLK_graph_iter_next (it, &tmp_spo) != VOLK_END;
667
668 VOLK_triple_free (tmp_spo);
670
671 return rc;
672}
673
674
675void
676VOLK_graph_print (const VOLK_Graph *gr)
677{
678 size_t ct;
679 VOLK_GraphIterator *it = VOLK_graph_lookup (gr, NULL, NULL, NULL, &ct);
680 if (UNLIKELY (!it)) {
681 log_error ("Could not inspect graph for printing.");
682 return;
683 }
684
685 printf ("*** Graph %s (%zu triples):\n\n", gr->uri->data, ct);
686
687 VOLK_Triple *spo = NULL;
688 ct = 0;
690 while ((rc = VOLK_graph_iter_next (it, &spo)) == VOLK_OK) {
691 printf (
692 "#%-6zu {%s %s %s}\n",
693 ct, spo->s->data, spo->p->data, spo->o->data);
694 ct++;
695 }
696 if (rc != VOLK_END)
697 log_error (
698 "Output truncated due to abnormal return: %s",
699 VOLK_strerror (rc));
700}
701
702
705 const VOLK_Graph *gr, const VOLK_Term *t, const VOLK_LinkType type)
706{
707 const VOLK_Term
708 *s = NULL,
709 *p = NULL,
710 *o = NULL;
711
712 // Position of passed term and link terms, respectively.
713 VOLK_TriplePos pos1, pos2;
714
715 if (type == VOLK_LINK_INBOUND) {
716 o = t;
717 pos1 = TRP_POS_O;
718 pos2 = TRP_POS_P;
719 } else if (type == VOLK_LINK_OUTBOUND) {
720 s = t;
721 pos1 = TRP_POS_S;
722 pos2 = TRP_POS_P;
723 } else if (type == VOLK_LINK_EDGE) {
724 p = t;
725 pos1 = TRP_POS_P;
726 pos2 = TRP_POS_S;
727 } else {
728 log_error ("Invalid connection type: %d", type);
729 return NULL;
730 }
731
732 // Gather all linking terms in a set first.
733 VOLK_GraphIterator *it = VOLK_graph_lookup (gr, s, p, o, NULL);
734 if (!it) return NULL;
735
737 while (graph_iter_next_buffer (it) != VOLK_END) {
739 *ex = NULL,
741 VOLK_btriple_pos (it->sspo, pos2));
742 VOLK_term_set_add (lts, ins, &ex);
743
744 if (ex) VOLK_term_free (ins);
745 }
747
748 VOLK_LinkMap *ret = VOLK_link_map_new (t, type);
749 if (!ret) return NULL;
750 size_t i = 0;
751 VOLK_Term *lt;
752 while (VOLK_term_set_next (lts, &i, &lt) != VOLK_END) {
754 ret, VOLK_term_copy (lt),
755 VOLK_graph_term_set (gr, t, pos1, lt, pos2));
756 }
757 VOLK_term_set_free (lts);
758
759 return ret;
760}
761
762
765 const VOLK_Graph *gr, const VOLK_Term *t1, const VOLK_TriplePos t1_pos,
766 const VOLK_Term *t2, const VOLK_TriplePos t2_pos)
767{
768 if (t1_pos == t2_pos) {
769 log_error ("Term 1 and 2 positions cannot be the same!");
770 return NULL;
771 }
772
773 const VOLK_Term *spo_l[3] = {NULL};
774 spo_l[t1_pos] = t1;
775 spo_l[t2_pos] = t2;
776 VOLK_TriplePos rpos = 0; // Position of term to be added to results.
777 for (unsigned i = 0; i < 3; i++)
778 if (t1_pos != i && t2_pos != i) rpos = i;
779
780 VOLK_GraphIterator *it = VOLK_graph_lookup (
781 gr, spo_l[0], spo_l[1], spo_l[2], NULL);
782
784 while (graph_iter_next_buffer (it) != VOLK_END) {
785 // There cannot be duplicates in a 2-bound lookup.
787 ts,
789 NULL);
790 }
792
793 return ts;
794}
795
796
798VOLK_graph_unique_terms (const VOLK_Graph *gr, VOLK_TriplePos pos)
799{
800 // TODO We should use spo indices for stores that have them...
801 VOLK_GraphIterator *it = VOLK_graph_lookup (gr, NULL, NULL, NULL, NULL);
802
804 while (graph_iter_next_buffer (it) != VOLK_END) {
806 *ex = NULL,
807 *ins = VOLK_term_new_from_buffer (VOLK_btriple_pos (it->sspo, pos));
808 VOLK_term_set_add (ts, ins, &ex);
809
810 if (ex) VOLK_term_free (ins);
811 }
813
814 return ts;
815}
816
817
818size_t
819VOLK_graph_add_link_map (VOLK_GraphIterator *it, VOLK_LinkMap *lm)
820{
821 VOLK_Triple *spo = TRP_DUMMY;
822 size_t ct = 0;
823 VOLK_LinkMapIterator *lmit = VOLK_link_map_iter_new (lm);
824
825 while (VOLK_link_map_triples (lmit, spo) != VOLK_END) {
826 VOLK_rc rc = VOLK_graph_add_iter (it, spo);
827 if (rc >= 0) ct++;
828 PRCCK (rc);
829 }
831 free (spo);
832
833 return ct;
834}
835
836
837VOLK_Term *
838VOLK_bnode_add_collection (VOLK_GraphIterator *it, VOLK_TermSet *ts)
839{
841 *s = VOLK_term_new (VOLK_TERM_BNODE, NULL, NULL),
842 *rdf_first = VOLK_iriref_new ("rdf:first"),
843 *rdf_rest = VOLK_iriref_new ("rdf:rest"),
844 *rdf_nil = VOLK_iriref_new ("rdf:nil"),
845 *link;
846
847 VOLK_Triple *spo = TRP_DUMMY;
848 link = s;
849 size_t i = 0;
850 VOLK_Term *t;
851 while (VOLK_term_set_next (ts, &i, &t) != VOLK_END) {
852 spo->s = link;
853 spo->p = rdf_first;
854 spo->o = t;
855 PRCNL (VOLK_graph_add_iter (it, spo));
856
857 spo->p = rdf_rest;
858 size_t save_i = i; // Save iterator position to restore it after peek.
859 spo->o = (
860 // Peek into the next result.
861 VOLK_term_set_next (ts, &i, NULL) != VOLK_END ?
862 VOLK_term_new (VOLK_TERM_BNODE, NULL, NULL)
863 : rdf_nil);
864 i = save_i; // Restore the iterator that advanced when peeking.
865
866 PRCNL (VOLK_graph_add_iter (it, spo));
867
868 if (link != s) VOLK_term_free (link);
869 // Current object becomes next subject. Irrelevant for last item.
870 link = spo->o;
871 }
872
873 VOLK_term_free (rdf_first);
874 VOLK_term_free (rdf_rest);
875 VOLK_term_free (rdf_nil);
876 free (spo);
877
878 return s;
879}
880
881
882/*
883 * Static functions.
884 */
885
893inline static VOLK_rc
894graph_iter_next_buffer (VOLK_GraphIterator *it)
895{ return it->graph->store->sif->lu_next_fn (it->data, it->sspo, NULL); }
896
897
901
902size_t VOLK_graph_size (const VOLK_Graph *gr);
903VOLK_Graph * VOLK_graph_new_ns (VOLK_Store *store, const char *ns_str);
#define UNLIKELY(x)
Definition core.h:39
#define LIKELY(x)
Definition core.h:38
bool VOLK_graph_iter_is_add(VOLK_GraphIterator *it)
Definition graph.c:600
VOLK_Buffer * VOLK_btriple_pos(const VOLK_BufferTriple *trp, VOLK_TriplePos n)
Get serialized triple by term position.
Definition buffer.h:297
#define BTRP_DUMMY
Dummy buffer triple.
Definition buffer.h:336
void VOLK_btriple_free(VOLK_BufferTriple *sspo)
Free a buffer triple and all its internal pointers.
Definition buffer.c:147
VOLK_TriplePos
Triple position of s, p, o.
Definition buffer.h:19
void VOLK_buffer_free(VOLK_Buffer *buf)
Free a buffer.
Definition buffer.c:97
@ VOLK_BUF_BORROWED
Definition buffer.h:28
@ TRP_POS_O
Definition buffer.h:22
@ TRP_POS_S
Definition buffer.h:20
@ TRP_POS_P
Definition buffer.h:21
#define VOLK_graph_lookup(...)
Non-transactional version of VOLK_graph_lookup_txn.
Definition graph.h:364
VOLK_Graph * VOLK_graph_new_ns(VOLK_Store *store, const char *ns_str)
Create an empty graph using a namespace-prefixed string for its URI.
Definition graph.h:54
const VOLK_Graph * VOLK_graph_iter_graph(VOLK_GraphIterator *it)
Return the graph related to an iterator.
Definition graph.c:595
VOLK_TermSet * VOLK_graph_list_txn(void *txn, VOLK_Store *store)
List all graph URIs in a store.
Definition graph.c:634
void VOLK_graph_print(const VOLK_Graph *gr)
Print graph information and triples to stdout.
Definition graph.c:676
VOLK_LinkMap * VOLK_graph_connections(const VOLK_Graph *gr, const VOLK_Term *t, const VOLK_LinkType type)
Get term pairs connected to a term in a graph.
Definition graph.c:704
VOLK_Graph * VOLK_graph_get_txn(void *txn, VOLK_Store *store, const VOLK_Term *uri, size_t *ct)
Create a temp graph from stored triples.
Definition graph.c:63
size_t VOLK_graph_add_link_map(VOLK_GraphIterator *it, VOLK_LinkMap *lm)
Add triples for a term and related link map to a graph.
Definition graph.c:819
bool VOLK_graph_contains(const VOLK_Graph *gr, const VOLK_Triple *spo)
Whether a graph contains a triple.
Definition graph.c:661
bool VOLK_graph_equals(const VOLK_Graph *gr1, const VOLK_Graph *gr2)
Compare two graphs.
Definition graph.c:330
VOLK_rc VOLK_graph_remove_txn(void *txn, VOLK_Graph *gr, const VOLK_Term *s, const VOLK_Term *p, const VOLK_Term *o, size_t *ct)
Delete triples by a matching pattern.
Definition graph.c:456
VOLK_rc VOLK_graph_copy_contents_txn(void *txn, const VOLK_Graph *src, VOLK_Graph *dest, const VOLK_Term *s, const VOLK_Term *p, const VOLK_Term *o)
Copy triples from a source graph into a destination one.
Definition graph.c:487
void VOLK_graph_free(VOLK_Graph *gr)
Free a graph.
Definition graph.c:246
VOLK_rc VOLK_graph_add_txn(void *txn, VOLK_Graph *gr, VOLK_Triple *const *trp, size_t *ct)
Add triples to a graph.
Definition graph.c:422
VOLK_GraphIterator * VOLK_graph_lookup_txn(void *txn, const VOLK_Graph *gr, const VOLK_Term *s, const VOLK_Term *p, const VOLK_Term *o, size_t *ct)
Look up triples by a matching pattern and yield an iterator.
Definition graph.c:515
#define VOLK_graph_copy_contents(...)
Definition graph.h:134
VOLK_rc VOLK_graph_bool_op_txn(void *txn, const VOLK_bool_op op, const VOLK_Graph *gr1, const VOLK_Graph *gr2, VOLK_Graph *res)
Definition graph.c:100
VOLK_TermSet * VOLK_graph_unique_terms(const VOLK_Graph *gr, VOLK_TriplePos pos)
Get all unique subjcts, predicates, or objects in a graph.
Definition graph.c:798
#define VOLK_graph_bool_op(...)
Non-transactional version of VOLK_graph_bool_op_txn.
Definition graph.h:184
VOLK_Store * VOLK_graph_store(const VOLK_Graph *gr)
Underlying graph store handle.
Definition graph.c:267
VOLK_GraphIterator * VOLK_graph_add_init_txn(void *txn, VOLK_Graph *gr)
Initialize an iterator to add triples.
Definition graph.c:343
VOLK_rc VOLK_graph_iter_next(VOLK_GraphIterator *it, VOLK_Triple **spo_p)
Advance a cursor obtained by a lookup and return a matching triple.
Definition graph.c:575
VOLK_rc VOLK_graph_set_uri(VOLK_Graph *gr, const char *uri_str)
Definition graph.c:272
VOLK_Term * VOLK_bnode_add_collection(VOLK_GraphIterator *it, VOLK_TermSet *ts)
Add triples for an anonymous collection to a graph.
Definition graph.c:838
VOLK_rc VOLK_graph_add_iter(VOLK_GraphIterator *it, const VOLK_Triple *spo)
Add a single triple to the store.
Definition graph.c:360
void VOLK_graph_iter_free(VOLK_GraphIterator *it)
Free a graph iterator.
Definition graph.c:605
VOLK_TermSet * VOLK_graph_term_set(const VOLK_Graph *gr, const VOLK_Term *t1, const VOLK_TriplePos t1_pos, const VOLK_Term *t2, const VOLK_TriplePos t2_pos)
Get a list of terms related to a term pair in a graph.
Definition graph.c:764
VOLK_Graph * VOLK_graph_new(VOLK_Store *store, const char *uri_str)
Create new graph.
Definition graph.c:44
const VOLK_Term * VOLK_graph_uri(const VOLK_Graph *gr)
Read-only graph URI.
Definition graph.c:263
size_t VOLK_graph_size(const VOLK_Graph *gr)
Number of triples in a graph.
Definition graph.c:311
#define MALLOC_GUARD(var, rc)
Allocate one pointer with malloc and return rc if it fails.
Definition core.h:382
#define PCHECK(exp, marker)
Jump to marker if exp returns a negative value (skip warnings).
Definition core.h:302
#define PRCNL(exp)
Return NULL if exp returns a negative value (=error).
Definition core.h:363
#define CHECK(exp, marker)
Jump to marker if exp does not return VOLK_OK.
Definition core.h:290
#define CALLOC_GUARD(var, rc)
Allocate one pointer with calloc and return rc if it fails.
Definition core.h:388
#define log_debug(...)
Definition core.h:273
#define NLRCCK(exp, _rc)
Return rc return code if exp is NULL.
Definition core.h:344
#define PRCCK(exp)
Return exp return value if it is of VOLK_rc type and negative (=error).
Definition core.h:333
#define log_trace(...)
Definition core.h:275
VOLK_bool_op
Boolean operations that can be performed on a graph.
Definition core.h:221
@ VOLK_BOOL_XOR
Boolean XOR.
Definition core.h:225
@ VOLK_BOOL_UNION
Boolean union.
Definition core.h:222
@ VOLK_BOOL_SUBTRACTION
Boolean subtraction.
Definition core.h:223
@ VOLK_BOOL_INTERSECTION
Boolean intersection.
Definition core.h:224
#define VOLK_VALUE_ERR
An invalid input value was provided.
Definition core.h:129
#define VOLK_MEM_ERR
Memory allocation error.
Definition core.h:144
#define VOLK_NORESULT
No result yielded.
Definition core.h:100
#define VOLK_DB_ERR
Low-level database error.
Definition core.h:135
#define VOLK_END
Loop end.
Definition core.h:107
#define VOLK_OK
Generic success return code.
Definition core.h:83
#define VOLK_NOACTION
No action taken.
Definition core.h:93
int VOLK_rc
Definition core.h:79
const char * VOLK_strerror(VOLK_rc rc)
Return an error message for a return code.
Definition core.c:196
@ VOLK_STORE_TXN
Supports transaction handling.
@ VOLK_STORE_EMBED
@ VOLK_STORE_COW
Copy on write.
@ VOLK_STORE_CTX
VOLK_Buffer ** VOLK_store_ctx_list_txn(VOLK_Store *store, void *txn)
get index of all graph (context) URIs in a store.
Definition store.c:226
VOLK_StoreType
Store types. All prefixed with VOLK_STORE_.
Definition store.h:39
VOLK_Store * VOLK_store_new(const VOLK_StoreType store_type, const char *store_id, size_t size, bool clear)
Create a new store.
Definition store.c:28
#define BACKEND_TBL
Definition store.h:32
VOLK_rc VOLK_term_set_add(VOLK_TermSet *ts, VOLK_Term *term, VOLK_Term **existing)
Add term to a term set.
Definition term.c:562
VOLK_Triple * VOLK_triple_new_from_btriple(const VOLK_BufferTriple *sspo)
Definition term.c:471
struct hashmap VOLK_TermSet
a set of unique terms.
Definition term.h:124
VOLK_rc VOLK_term_set_next(VOLK_TermSet *ts, size_t *i, VOLK_Term **term)
Iterate trough a term set.
Definition term.c:592
VOLK_Triple * VOLK_triple_new(VOLK_Term *s, VOLK_Term *p, VOLK_Term *o)
Create a new triple from three terms.
Definition term.c:456
VOLK_Term * VOLK_iriref_new_rel(const VOLK_Term *root, const VOLK_Term *iri)
Create a new relative IRI from an absolute IRI and a web root IRI.
Definition term.c:273
void VOLK_link_map_iter_free(VOLK_LinkMapIterator *it)
Free a link map iterator.
Definition term.c:720
VOLK_LinkType
Link type.
Definition term.h:94
VOLK_Term * VOLK_iriref_new(const char *data)
Create an IRI reference.
Definition term.h:192
VOLK_LinkMapIterator * VOLK_link_map_iter_new(const VOLK_LinkMap *lmap)
Create a new iterator to loop through a link map.
Definition term.c:708
VOLK_LinkMap * VOLK_link_map_new(const VOLK_Term *linked_term, VOLK_LinkType type)
New link map.
Definition term.c:630
VOLK_rc VOLK_link_map_triples(VOLK_LinkMapIterator *it, VOLK_Triple *spo)
Iterate over a link map and generate triples.
Definition term.c:739
VOLK_TermSet * VOLK_term_set_new()
Create a new term set.
Definition term.c:549
void VOLK_term_set_free(VOLK_TermSet *ts)
Free a term set.
Definition term.c:604
#define TRP_DUMMY
Dummy triple with NULL slots. It is not a valid triple.
Definition term.h:442
void VOLK_term_free(VOLK_Term *term)
Definition term.c:387
VOLK_Term * VOLK_triple_pos(const VOLK_Triple *trp, VOLK_TriplePos n)
Get triple by term position.
Definition term.h:499
VOLK_Buffer * VOLK_term_serialize(const VOLK_Term *term)
Serialize a term into a buffer.
Definition term.c:293
VOLK_Term * VOLK_term_new_from_buffer(const VOLK_Buffer *sterm)
See notes in VOLK_term_serialize function body for format info.
Definition term.c:189
VOLK_rc VOLK_link_map_add(VOLK_LinkMap *lmap, VOLK_Term *term, VOLK_TermSet *tset)
Add a term - term set pair to a link map.
Definition term.c:665
VOLK_BufferTriple * VOLK_triple_serialize(const VOLK_Triple *spo)
Definition term.c:485
VOLK_Term * VOLK_term_new(VOLK_TermType type, const char *data, void *metadata)
Create a new term.
Definition term.c:157
void VOLK_triple_free(VOLK_Triple *spo)
Free a triple and all its internal pointers.
Definition term.c:532
VOLK_Term * VOLK_term_copy(const VOLK_Term *src)
Copy a term.
Definition term.c:174
@ VOLK_LINK_EDGE
Edge link (so).
Definition term.h:97
@ VOLK_LINK_INBOUND
Inbound link (sp).
Definition term.h:95
@ VOLK_LINK_OUTBOUND
Outbound link (po).
Definition term.h:96
@ VOLK_TERM_IRIREF
IRI reference.
Definition term.h:35
@ VOLK_TERM_LITERAL
Literal without language tag.
Definition term.h:36
@ VOLK_TERM_BNODE
Blank node.
Definition term.h:38
Triple of byte buffers.
Definition buffer.h:60
VOLK_Buffer * o
Definition buffer.h:63
VOLK_Buffer * s
Definition buffer.h:61
VOLK_Buffer * p
Definition buffer.h:62
General-purpose data buffer.
Definition buffer.h:47
Store interface.
VOLK_StoreFeature features
Feature flags.
iter_free_fn_t lu_free_fn
Free the lookup iterator.
store_add_iter_fn_t add_iter_fn
Add one triple.
store_add_term_fn_t add_term_fn
iter_txn_fn_t iter_txn_fn
Get iterator's transaction.
iter_next_fn_t lu_next_fn
Advance the lookup iterator.
store_lookup_fn_t lookup_fn
Look up triples by pattern. 
Store structure.
Definition store.h:59
void * data
Store back end data.
Definition store.h:67
const VOLK_StoreInt * sif
Store interface.
Definition store.h:66
RDF term.
Definition term.h:62
char * data
URI, literal value, or BNode label.
Definition term.h:63
struct term_t * datatype
Data type IRI for VOLK_TERM_LITERAL.
Definition term.h:65
VOLK_TermType type
Term type.
Definition term.h:70
RDF triple.
Definition term.h:86
VOLK_Term * p
Predicate.
Definition term.h:88
VOLK_Term * s
Subject.
Definition term.h:87
VOLK_Term * o
Object.
Definition term.h:89
Graph iterator.
Definition graph.c:12
const VOLK_Graph * graph
Parent graph.
Definition graph.c:13
size_t ct
Total lookup matches.
Definition graph.c:15
void * data
Iterator state.
Definition graph.c:14
VOLK_BufferTriple * sspo
Definition graph.c:16
Graph object.
Definition graph.c:7
VOLK_Store * store
Store handle.
Definition graph.c:9
VOLK_Term * uri
Graph "name" (URI).
Definition graph.c:8