1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rdf_storage.c - RDF Storage (Triple store) interface
4 *
5 * Copyright (C) 2000-2008, David Beckett http://www.dajobe.org/
6 * Copyright (C) 2000-2005, University of Bristol, UK http://www.bristol.ac.uk/
7 *
8 * This package is Free Software and part of Redland http://librdf.org/
9 *
10 * It is licensed under the following three licenses as alternatives:
11 * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
12 * 2. GNU General Public License (GPL) V2 or any newer version
13 * 3. Apache License, V2.0 or any newer version
14 *
15 * You may not use this file except in compliance with at least one of
16 * the above three licenses.
17 *
18 * See LICENSE.html or LICENSE.txt at the top of this package for the
19 * complete terms and further detail along with the license texts for
20 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
21 *
22 *
23 */
24
25
26 #ifdef HAVE_CONFIG_H
27 #include <rdf_config.h>
28 #endif
29
30 #ifdef WIN32
31 #include <win32_rdf_config.h>
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <sys/types.h>
38 #ifdef HAVE_STDLIB_H
39 #include <stdlib.h>
40 #endif
41
42 #ifdef MODULAR_LIBRDF
43 #include <ltdl.h>
44 #endif
45
46 #include <redland.h>
47 #include <rdf_storage.h>
48
49
50 #ifndef STANDALONE
51
52 /* prototypes for functions implementing get_sources, arcs, targets
53 * librdf_iterator via conversion from a librdf_stream of librdf_statement
54 */
55 static int librdf_storage_stream_to_node_iterator_is_end(void* iterator);
56 static int librdf_storage_stream_to_node_iterator_next_method(void* iterator);
57 static void* librdf_storage_stream_to_node_iterator_get_method(void* iterator, int flags);
58 static void librdf_storage_stream_to_node_iterator_finished(void* iterator);
59
60 /* helper function for creating iterators for get sources, targets, arcs */
61 static librdf_iterator* librdf_storage_node_stream_to_node_create(librdf_storage* storage, librdf_node* node1, librdf_node *node2, librdf_statement_part want);
62
63 /* helper functions for dynamically loading storage modules */
64 #ifdef MODULAR_LIBRDF
65 void
66 librdf_storage_load_all_modules(librdf_world *world);
67
68 static lt_dlhandle
69 librdf_storage_load_module(librdf_world *world,
70 const char* lib_name,
71 const char* init_func_name);
72 #endif
73
74
75 /**
76 * librdf_init_storage:
77 * @world: redland world object
78 *
79 * INTERNAL - Initialise the storage module.
80 *
81 * Initialises and registers all
82 * compiled storage modules. Must be called before using any of the storage
83 * factory functions such as librdf_get_storage_factory()
84 **/
85 void
librdf_init_storage(librdf_world * world)86 librdf_init_storage(librdf_world *world)
87 {
88 /* built-in storages */
89
90 #ifdef STORAGE_HASHES
91 librdf_init_storage_hashes(world);
92 #endif
93 #ifdef STORAGE_TREES
94 librdf_init_storage_trees(world);
95 #endif
96 #ifdef STORAGE_MEMORY
97 librdf_init_storage_list(world);
98 #endif
99 #ifdef STORAGE_FILE
100 librdf_init_storage_file(world);
101 #endif
102
103 #ifdef MODULAR_LIBRDF
104
105 if (!world->storage_modules)
106 world->storage_modules = raptor_new_sequence(
107 (raptor_data_free_handler)lt_dlclose, NULL);
108
109 librdf_storage_load_all_modules(world);
110
111 #else /* monolithic */
112
113 #ifdef STORAGE_MYSQL
114 librdf_init_storage_mysql(world);
115 #endif
116 #ifdef STORAGE_VIRTUOSO
117 librdf_init_storage_virtuoso(world);
118 #endif
119 #ifdef STORAGE_POSTGRESQL
120 librdf_init_storage_postgresql(world);
121 #endif
122 #ifdef STORAGE_TSTORE
123 librdf_init_storage_tstore(world);
124 #endif
125 #ifdef STORAGE_SQLITE
126 librdf_init_storage_sqlite(world);
127 #endif
128
129 #endif
130 }
131
132
133 /**
134 * librdf_finish_storage:
135 * @world: redland world object
136 *
137 * INTERNAL - Terminate the storage module.
138 *
139 **/
140 void
librdf_finish_storage(librdf_world * world)141 librdf_finish_storage(librdf_world *world)
142 {
143 if(world->storages) {
144 raptor_free_sequence(world->storages);
145 world->storages=NULL;
146 }
147
148 #ifdef MODULAR_LIBRDF
149 if(world->storage_modules) {
150 raptor_free_sequence(world->storage_modules);
151 world->storage_modules=NULL;
152 }
153 #endif
154
155 }
156
157
158
159 /* helper functions */
160
161
162 static void
librdf_free_storage_factory(librdf_storage_factory * factory)163 librdf_free_storage_factory(librdf_storage_factory* factory)
164 {
165 if(factory->name)
166 LIBRDF_FREE(librdf_storage_factory, factory->name);
167 if(factory->label)
168 LIBRDF_FREE(librdf_storage_factory, factory->label);
169 LIBRDF_FREE(librdf_storage_factory, factory);
170 }
171
172
173 #ifdef MODULAR_LIBRDF
174
175 static int
ltdl_module_callback(const char * filename,void * data)176 ltdl_module_callback(const char* filename, void* data)
177 {
178 librdf_world* world = (librdf_world*)data;
179 const char* name = librdf_basename(filename);
180 size_t name_len = strlen(name);
181 lt_dlhandle module;
182
183 /* Currently require that storage module files to be loaded start
184 * with the string "librdf_storage_".
185 */
186
187 if(name_len < 15 || strncmp(name, "librdf_storage_", 15)) {
188 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 2
189 LIBRDF_DEBUG3("not storage module file %s (%s)\n", name, filename);
190 #endif
191 return 0;
192 }
193
194 /*
195 * When compiling and testing against uninstalled modules, not all
196 * files in .libs that contain librdf_storage are storage modules.
197 * (Relevant when running "make check" locally before installing
198 * the modules.)
199 *
200 * This check when debugging LIBRDF_DEBUG attempts to load .so
201 * files when running in the source tree. This is likely very
202 * libtool and unix specific.
203 *
204 * Rules:
205 * - Must end in '.so' or have no suffix (no . in last 3 chars)
206 * - Must not include "-" (libtool intermediate file such as
207 * librdf_storage_mysql_la-rdf_storage_mysql)
208 */
209 #ifdef LIBRDF_DEBUG
210 if(!(
211 strncmp(&name[name_len-3], ".so", 3) ||
212 (name[name_len-3]!='.' && name[name_len-2]!='.' && name[name_len-1]!='.')
213 )
214 || strchr(name, '-')
215 ) {
216 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 2
217 LIBRDF_DEBUG3("not storage module file %s (%s)\n", name, filename);
218 #endif
219 return 0;
220 }
221
222 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
223 LIBRDF_DEBUG3("LOADING storage module file %s (%s)\n", name, filename);
224 #endif
225
226 #endif
227
228 module = librdf_storage_load_module(world, filename,
229 "librdf_storage_module_register_factory");
230 if(module)
231 raptor_sequence_push(world->storage_modules, module);
232
233 return 0;
234 }
235
236
237 /**
238 * librdf_storage_load_all_modules:
239 * @world: redland world object
240 *
241 * INTERNAL - Load and initialize/register all installed storage modules
242 **/
243 void
librdf_storage_load_all_modules(librdf_world * world)244 librdf_storage_load_all_modules(librdf_world *world)
245 {
246 char const *path;
247
248 /* Figure out a path to load modules from */
249
250 /* Try environment variable first - required e.g. for local "make check" tests before install */
251 path = getenv("REDLAND_MODULE_PATH");
252
253 /* If path defined in env but empty, use libtool default paths (e.g. DYLD_LIBRARY_PATH) */
254 if (path && !*path)
255 path = NULL;
256
257 /* If path not defined in env, use libtool user-specified paths (install dir) */
258 else if (!path)
259 path = lt_dlgetsearchpath();
260
261 lt_dlforeachfile(path, ltdl_module_callback, world);
262 }
263
264
265 /**
266 * librdf_storage_load_module:
267 * @world: redland world object
268 * @lib_name: base name of shared library file
269 * @init_func_name: name of initialization function in library
270 *
271 * INTERNAL - Load and initialize/register a storage module
272 **/
273 static lt_dlhandle
librdf_storage_load_module(librdf_world * world,const char * lib_name,const char * init_func_name)274 librdf_storage_load_module(librdf_world *world,
275 const char* lib_name,
276 const char* init_func_name)
277 {
278 typedef void init_func_t(librdf_world*);
279 init_func_t* init;
280
281 lt_dlhandle module = lt_dlopenext(lib_name);
282
283 if(module) {
284 const lt_dlinfo* info = lt_dlgetinfo(module);
285
286 if(info->ref_count > 1) {
287 /* Already loaded so ignore */
288 lt_dlclose(module);
289 module = NULL;
290 return module;
291 }
292
293 init = (init_func_t*)lt_dlsym(module, init_func_name);
294 if(init) {
295 init(world);
296 } else {
297 LIBRDF_DEBUG2("Failed to initialize storage module %s\n", lib_name);
298 lt_dlclose(module);
299 module = NULL;
300 }
301 } else {
302 LIBRDF_DEBUG2("Failed to load storage module %s\n", lib_name);
303 }
304
305 return module;
306 }
307 #endif
308
309
310 /* class methods */
311
312 /**
313 * librdf_storage_register_factory:
314 * @world: redland world object
315 * @name: the storage factory name
316 * @label: the storage factory label
317 * @factory: pointer to function to call to register the factory
318 *
319 * Register a storage factory.
320 *
321 * Registration will fail if any of the parameters or NULL, if the factory
322 * API version is out of the known range or if out of memory.
323 *
324 * Return value: non-0 on failure
325 **/
326 REDLAND_EXTERN_C
327 int
librdf_storage_register_factory(librdf_world * world,const char * name,const char * label,void (* factory)(librdf_storage_factory *))328 librdf_storage_register_factory(librdf_world* world,
329 const char *name, const char *label,
330 void (*factory) (librdf_storage_factory*))
331 {
332 librdf_storage_factory *storage;
333 int i;
334
335 if(!world)
336 return 1;
337
338 if(!name || !label || !factory){
339 librdf_log(world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
340 "failed to register storage with missing parameters to librdf_storage_register_factory()");
341 return 1;
342 }
343
344 librdf_world_open(world);
345
346 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
347 LIBRDF_DEBUG2("Received registration for storage %s\n", name);
348 #endif
349
350 if(!world->storages) {
351 world->storages = raptor_new_sequence((raptor_data_free_handler)librdf_free_storage_factory, NULL);
352
353 if(!world->storages)
354 goto failed;
355 }
356
357 for(i=0;
358 (storage=(librdf_storage_factory*)raptor_sequence_get_at(world->storages, i));
359 i++) {
360 if(!strcmp(storage->name, name)) {
361 #if 1
362 /* Choosing to ignore this error since it probably is caused by
363 * scanning a directory of storage modules and finding a .la
364 * file (libtool) as well as the .so (module) and trying to
365 * load the same module twice.
366 *
367 * See bug http://bugs.librdf.org/mantis/view.php?id=460 for
368 * context
369 */
370 return 0;
371 #else
372 librdf_log(world,
373 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
374 "storage %s already registered", storage->name);
375 return 1;
376 #endif
377 }
378 }
379
380 storage = LIBRDF_CALLOC(librdf_storage_factory*, 1, sizeof(*storage));
381 if(!storage)
382 goto failed;
383
384 storage->name = LIBRDF_MALLOC(char*, strlen(name) + 1);
385 if(!storage->name)
386 goto tidy;
387 strcpy(storage->name, name);
388
389 storage->label = LIBRDF_MALLOC(char*, strlen(label) + 1);
390 if(!storage->label)
391 goto tidy;
392 strcpy(storage->label, label);
393
394 /* Call the storage registration function on the new object */
395 (*factory)(storage);
396
397 if(storage->version < LIBRDF_STORAGE_MIN_INTERFACE_VERSION ||
398 storage->version > LIBRDF_STORAGE_MAX_INTERFACE_VERSION) {
399 librdf_log(world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
400 "storage %s interface version %d is not in supported range %d-%d",
401 name, storage->version,
402 LIBRDF_STORAGE_MIN_INTERFACE_VERSION,
403 LIBRDF_STORAGE_MAX_INTERFACE_VERSION);
404 goto tidy;
405 }
406
407 if(raptor_sequence_push(world->storages, storage))
408 goto failed;
409
410 return 0;
411
412 tidy:
413 librdf_free_storage_factory(storage);
414
415 failed:
416 LIBRDF_FATAL1(world, LIBRDF_FROM_STORAGE, "Registering storage failed");
417 return 1;
418 }
419
420
421 /**
422 * librdf_get_storage_factory:
423 * @world: redland world object
424 * @name: the factory name or NULL for the default factory
425 *
426 * Get a storage factory by name.
427 *
428 * Return value: the factory object or NULL if there is no such factory
429 **/
430 librdf_storage_factory*
librdf_get_storage_factory(librdf_world * world,const char * name)431 librdf_get_storage_factory(librdf_world* world, const char *name)
432 {
433 int i;
434
435 librdf_storage_factory *factory;
436
437 librdf_world_open(world);
438
439 /* use "memory" if nothing is specified (FIXME: probably not the best choice) */
440 if (!name)
441 name = "memory";
442
443 /* search for factory */
444 for(i=0;
445 (factory=(librdf_storage_factory*)raptor_sequence_get_at(world->storages, i));
446 i++) {
447 if(!strcmp(factory->name, name))
448 break;
449 }
450
451 if(!factory) {
452 LIBRDF_DEBUG2("No storage with name %s found\n", name);
453 return NULL;
454 }
455
456 return factory;
457 }
458
459
460 /**
461 * librdf_storage_enumerate:
462 * @world: redland world object
463 * @counter: index into the list of storages
464 * @name: pointer to store the name of the storage (or NULL)
465 * @label: pointer to store syntax readable label (or NULL)
466 *
467 * Get information on storages.
468 *
469 * Return value: non 0 on failure of if counter is out of range
470 **/
471 int
librdf_storage_enumerate(librdf_world * world,const unsigned int counter,const char ** name,const char ** label)472 librdf_storage_enumerate(librdf_world* world,
473 const unsigned int counter,
474 const char **name, const char **label)
475 {
476 librdf_storage_factory *factory;
477 int ioffset = LIBRDF_GOOD_CAST(int, counter);
478
479 librdf_world_open(world);
480
481 factory = (librdf_storage_factory*)raptor_sequence_get_at(world->storages,
482 ioffset);
483 if(!factory)
484 return 1;
485
486 if(name)
487 *name = factory->name;
488
489 if(label)
490 *label = factory->label;
491
492 return 0;
493 }
494
495
496 /**
497 * librdf_new_storage:
498 * @world: redland world object
499 * @storage_name: the storage factory name
500 * @name: an identifier for the storage
501 * @options_string: options to initialise storage
502 *
503 * Constructor - create a new #librdf_storage object.
504 *
505 * The options are encoded as described in librdf_hash_from_string()
506 * and can be NULL if none are required.
507 *
508 * Return value: a new #librdf_storage object or NULL on failure
509 *
510 */
511 librdf_storage*
librdf_new_storage(librdf_world * world,const char * storage_name,const char * name,const char * options_string)512 librdf_new_storage(librdf_world *world,
513 const char *storage_name, const char *name,
514 const char *options_string)
515 {
516 librdf_storage_factory* factory;
517 librdf_hash* options_hash;
518
519 librdf_world_open(world);
520
521 factory = librdf_get_storage_factory(world, storage_name);
522 if(!factory) {
523 librdf_log(world,
524 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
525 "storage '%s' not found", storage_name);
526 return NULL;
527 }
528
529 options_hash=librdf_new_hash(world, NULL);
530 if(!options_hash)
531 return NULL;
532
533 if(librdf_hash_open(options_hash, NULL, 0, 1, 1, NULL)) {
534 librdf_free_hash(options_hash);
535 return NULL;
536 }
537
538 if(librdf_hash_from_string(options_hash, options_string)) {
539 librdf_free_hash(options_hash);
540 return NULL;
541 }
542
543 return librdf_new_storage_from_factory(world, factory, name, options_hash);
544 }
545
546
547 /**
548 * librdf_new_storage_with_options:
549 * @world: redland world object
550 * @storage_name: the storage factory name
551 * @name: an identifier for the storage
552 * @options: #librdf_hash of options to use
553 *
554 * Constructor - create a new #librdf_storage object.
555 *
556 * The options can be NULL if none are required.
557 *
558 * Return value: a new #librdf_storage object or NULL on failure
559 *
560 */
561 librdf_storage*
librdf_new_storage_with_options(librdf_world * world,const char * storage_name,const char * name,librdf_hash * options)562 librdf_new_storage_with_options(librdf_world *world,
563 const char *storage_name, const char *name,
564 librdf_hash *options)
565 {
566 librdf_storage_factory* factory;
567 librdf_hash* options_hash;
568
569 librdf_world_open(world);
570
571 factory = librdf_get_storage_factory(world, storage_name);
572 if(!factory) {
573 librdf_log(world,
574 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
575 "storage '%s' not found", name);
576 return NULL;
577 }
578
579 options_hash=librdf_new_hash_from_hash(options);
580 if(!options_hash)
581 return NULL;
582
583 if(librdf_hash_open(options_hash, NULL, 0, 1, 1, NULL)) {
584 librdf_free_hash(options_hash);
585 return NULL;
586 }
587
588 return librdf_new_storage_from_factory(world, factory, name, options_hash);
589 }
590
591
592 /**
593 * librdf_new_storage_from_storage:
594 * @old_storage: the existing storage #librdf_storage to use
595 *
596 * Copy constructor - create a new librdf_storage object from an existing one
597 *
598 * Should create a new storage in the same context as the existing one
599 * as appropriate for the storage. For example, in a RDBMS storage
600 * it would be a new database, or in on disk it would be a new
601 * set of files. This will mean automatically generating
602 * a new identifier for the storage, maybe based on the existing
603 * storage identifier.
604 *
605 * Return value: a new #librdf_storage object or NULL on failure
606 *
607 */
608 librdf_storage*
librdf_new_storage_from_storage(librdf_storage * old_storage)609 librdf_new_storage_from_storage(librdf_storage* old_storage)
610 {
611 librdf_storage* new_storage;
612
613 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(old_storage, librdf_storage, NULL);
614
615 if(!old_storage->factory->clone) {
616 librdf_log(old_storage->world,
617 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
618 "clone method not implemented for storage factory %s",
619 old_storage->factory->name);
620 return NULL;
621 }
622
623 new_storage = LIBRDF_CALLOC(librdf_storage*, 1, sizeof(*new_storage));
624 if(!new_storage)
625 return NULL;
626
627 /* set usage to 1 early to allow cleanup with librdf_free_storage() */
628 new_storage->usage=1;
629
630 new_storage->instance=NULL;
631
632 new_storage->world=old_storage->world;
633
634 /* do this now so librdf_free_storage won't call new factory on
635 * partially copied storage
636 */
637 new_storage->factory=old_storage->factory;
638
639 /* clone is assumed to do leave the new storage in the same state
640 * after an init() method on an existing storage - i.e ready to
641 * use but closed.
642 */
643 if(old_storage->factory->clone(new_storage, old_storage)) {
644 librdf_free_storage(new_storage);
645 return NULL;
646 }
647
648 return new_storage;
649 }
650
651
652 /**
653 * librdf_new_storage_from_factory:
654 * @world: redland world object
655 * @factory: the factory to use to construct the storage
656 * @name: name to use for storage
657 * @options: #librdf_hash of options to initialise storage
658 *
659 * Constructor - create a new #librdf_storage object.
660 *
661 * If the options are present, they become owned by the storage
662 * and should no longer be used.
663 *
664 * Return value: a new #librdf_storage object or NULL on failure
665 *
666 */
667 librdf_storage*
librdf_new_storage_from_factory(librdf_world * world,librdf_storage_factory * factory,const char * name,librdf_hash * options)668 librdf_new_storage_from_factory(librdf_world *world,
669 librdf_storage_factory* factory,
670 const char *name,
671 librdf_hash* options)
672 {
673 librdf_storage* storage;
674
675 librdf_world_open(world);
676
677 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(factory, librdf_storage_factory, NULL);
678
679 if(!factory) {
680 librdf_free_hash(options);
681 return NULL;
682 }
683
684 storage = LIBRDF_CALLOC(librdf_storage*, 1, sizeof(*storage));
685 if(!storage) {
686 librdf_free_hash(options);
687 return NULL;
688 }
689
690 storage->world=world;
691
692 /* set usage to 1 early to allow cleanup with librdf_free_storage() */
693 storage->usage=1;
694
695 storage->instance=NULL;
696 storage->factory=factory;
697
698 if(factory->init(storage, name, options)) {
699 librdf_free_storage(storage);
700 return NULL;
701 }
702
703 return storage;
704 }
705
706
707 /**
708 * librdf_free_storage:
709 * @storage: #librdf_storage object
710 *
711 * Destructor - destroy a #librdf_storage object.
712 **/
713 void
librdf_free_storage(librdf_storage * storage)714 librdf_free_storage(librdf_storage* storage)
715 {
716 if(!storage)
717 return;
718
719 if(--storage->usage)
720 return;
721
722 if(storage->factory)
723 storage->factory->terminate(storage);
724
725 LIBRDF_FREE(librdf_storage, storage);
726 }
727
728
729 /**
730 * librdf_storage_add_reference:
731 * @storage: #librdf_storage object
732 *
733 * Increment storage reference count by one.
734 *
735 * This function is intended to be internal to librdf storage modules.
736 **/
737 void
librdf_storage_add_reference(librdf_storage * storage)738 librdf_storage_add_reference(librdf_storage *storage)
739 {
740 storage->usage++;
741 }
742
743
744 /**
745 * librdf_storage_remove_reference:
746 * @storage: #librdf_storage object
747 *
748 * Decrement storage reference count by one and free the storage if reference count becomes zero.
749 *
750 * This function is intended to be internal to librdf storage modules.
751 **/
752 void
librdf_storage_remove_reference(librdf_storage * storage)753 librdf_storage_remove_reference(librdf_storage *storage)
754 {
755 librdf_free_storage(storage);
756 }
757
758
759 /**
760 * librdf_storage_set_instance:
761 * @storage: #librdf_storage object
762 * @instance: Opaque instance pointer
763 *
764 * Set the instance data for this storage.
765 *
766 * This function is intended for use by the 'init' method of storage
767 * implementations to set instance data which can be retrived with
768 * librdf_storage_get_instance() and used in other methods of that
769 * storage.
770 *
771 * The instance is completely opaque to librdf, including allocation
772 * and deallocation.
773 **/
774 void
librdf_storage_set_instance(librdf_storage * storage,librdf_storage_instance instance)775 librdf_storage_set_instance(librdf_storage *storage,
776 librdf_storage_instance instance)
777 {
778 storage->instance = instance;
779 }
780
781
782 /**
783 * librdf_storage_get_instance:
784 * @storage: #librdf_storage object
785 *
786 * Get instance data for this storage
787 *
788 * Return value: opaque instance data for this storage
789 **/
790 librdf_storage_instance
librdf_storage_get_instance(librdf_storage * storage)791 librdf_storage_get_instance(librdf_storage *storage)
792 {
793 return storage->instance;
794 }
795
796
797 /**
798 * librdf_storage_get_world:
799 * @storage: #librdf_storage object
800 *
801 * Get the #librdf_world object associated with this storage.
802 *
803 * Return value: world object for this storage
804 **/
805 librdf_world*
librdf_storage_get_world(librdf_storage * storage)806 librdf_storage_get_world(librdf_storage *storage)
807 {
808 return storage->world;
809 }
810
811
812 /* methods */
813
814 /**
815 * librdf_storage_open:
816 * @storage: #librdf_storage object
817 * @model: model stored
818 *
819 * Start a model / storage association.
820 *
821 * This is ended with librdf_storage_close()
822 *
823 * Return value: non 0 on failure
824 **/
825 int
librdf_storage_open(librdf_storage * storage,librdf_model * model)826 librdf_storage_open(librdf_storage* storage, librdf_model* model)
827 {
828 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
829
830 return storage->factory->open(storage, model);
831 }
832
833
834 /**
835 * librdf_storage_close:
836 * @storage: #librdf_storage object
837 *
838 * End a model / storage association.
839 *
840 * Return value: non 0 on failure
841 **/
842 int
librdf_storage_close(librdf_storage * storage)843 librdf_storage_close(librdf_storage* storage)
844 {
845 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
846
847 return storage->factory->close(storage);
848 }
849
850
851 /**
852 * librdf_storage_size:
853 * @storage: #librdf_storage object
854 *
855 * Get the number of statements stored.
856 *
857 * Return value: The number of statements or < 0 if cannot be determined
858 **/
859 int
librdf_storage_size(librdf_storage * storage)860 librdf_storage_size(librdf_storage* storage)
861 {
862 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, -1);
863
864 return storage->factory->size(storage);
865 }
866
867
868 /**
869 * librdf_storage_add_statement:
870 * @storage: #librdf_storage object
871 * @statement: #librdf_statement statement to add
872 *
873 * Add a statement to a storage.
874 *
875 * The passed-in statement is copied when added to the store, not
876 * shared with the store.
877 *
878 * If the statement already exists in the store, it is not added
879 * unless Redland contexts are being used.
880 *
881 * Enforces that the statement is legal for RDF - URI or blank subject,
882 * URI predicate and URI or blank or literal object (i.e. anything).
883 *
884 * Return value: non 0 on failure, <0 on error, >0 if statement was illegal
885 **/
886 int
librdf_storage_add_statement(librdf_storage * storage,librdf_statement * statement)887 librdf_storage_add_statement(librdf_storage* storage,
888 librdf_statement* statement)
889 {
890 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
891 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
892
893 /* subject can be a URI or blank node */
894 if(!librdf_node_is_resource(statement->subject) &&
895 !librdf_node_is_blank(statement->subject))
896 return 1;
897
898 /* predicate can only be a URI */
899 if(!librdf_node_is_resource(statement->predicate))
900 return 1;
901
902 /* object can be any node - no check needed */
903
904 if(storage->factory->add_statement)
905 return storage->factory->add_statement(storage, statement);
906
907 return -1;
908 }
909
910
911 /**
912 * librdf_storage_add_statements:
913 * @storage: #librdf_storage object
914 * @statement_stream: #librdf_stream of statements
915 *
916 * Add a stream of statements to the storage.
917 *
918 * If any of the statements already exists in the store, they are not
919 * added unless Redland contexts are being used.
920 *
921 * Return value: non 0 on failure
922 **/
923 int
librdf_storage_add_statements(librdf_storage * storage,librdf_stream * statement_stream)924 librdf_storage_add_statements(librdf_storage* storage,
925 librdf_stream* statement_stream)
926 {
927 int status=0;
928
929 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
930 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement_stream, librdf_stream, 1);
931
932 if(storage->factory->add_statements)
933 return storage->factory->add_statements(storage, statement_stream);
934
935 while(!librdf_stream_end(statement_stream)) {
936 librdf_statement* statement=librdf_stream_get_object(statement_stream);
937
938 if(statement) {
939 status=librdf_storage_add_statement(storage, statement);
940 if(status > 0)
941 /* just skip illegal statements */
942 status=0;
943 }
944 else
945 status=1;
946
947 if(status)
948 break;
949
950 librdf_stream_next(statement_stream);
951 }
952
953 return status;
954 }
955
956
957 /**
958 * librdf_storage_remove_statement:
959 * @storage: #librdf_storage object
960 * @statement: #librdf_statement statement to remove
961 *
962 * Remove a statement from the storage.
963 *
964 * Return value: non 0 on failure
965 **/
966 int
librdf_storage_remove_statement(librdf_storage * storage,librdf_statement * statement)967 librdf_storage_remove_statement(librdf_storage* storage,
968 librdf_statement* statement)
969 {
970 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
971 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
972
973 if(storage->factory->remove_statement)
974 return storage->factory->remove_statement(storage, statement);
975 return 1;
976 }
977
978
979 /**
980 * librdf_storage_contains_statement:
981 * @storage: #librdf_storage object
982 * @statement: #librdf_statement statement to check
983 *
984 * Test if a given statement is present in the storage.
985 *
986 * Return value: non 0 if the storage contains the statement (>0 if illegal statement)
987 **/
988 int
librdf_storage_contains_statement(librdf_storage * storage,librdf_statement * statement)989 librdf_storage_contains_statement(librdf_storage* storage,
990 librdf_statement* statement)
991 {
992 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 0);
993 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
994
995 if(!librdf_statement_is_complete(statement))
996 return 1;
997
998 return storage->factory->contains_statement(storage, statement) ? -1 : 0;
999 }
1000
1001
1002 /**
1003 * librdf_storage_serialise:
1004 * @storage: #librdf_storage object
1005 *
1006 * Serialise the storage as a librdf_stream of statemetns.
1007 *
1008 * Return value: #librdf_stream of statements or NULL on failure
1009 **/
1010 librdf_stream*
librdf_storage_serialise(librdf_storage * storage)1011 librdf_storage_serialise(librdf_storage* storage)
1012 {
1013 return storage->factory->serialise(storage);
1014 }
1015
1016
1017 /**
1018 * librdf_storage_find_statements:
1019 * @storage: #librdf_storage object
1020 * @statement: #librdf_statement partial statement to find
1021 *
1022 * Search the storage for matching statements.
1023 *
1024 * Searches the storage for a (partial) statement as described in
1025 * librdf_statement_match() and returns a #librdf_stream of
1026 * matching #librdf_statement objects.
1027 *
1028 * Return value: #librdf_stream of matching statements (may be empty) or NULL on failure
1029 **/
1030 librdf_stream*
librdf_storage_find_statements(librdf_storage * storage,librdf_statement * statement)1031 librdf_storage_find_statements(librdf_storage* storage,
1032 librdf_statement* statement)
1033 {
1034 librdf_node *subject, *predicate, *object;
1035 librdf_iterator *iterator;
1036
1037 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1038 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
1039
1040 subject=librdf_statement_get_subject(statement);
1041 predicate=librdf_statement_get_predicate(statement);
1042 object=librdf_statement_get_object(statement);
1043
1044 /* try to pick the most efficient storage back end */
1045
1046 /* only subject/source field blank -> use find_sources */
1047 if(storage->factory->find_sources && !subject && predicate && object) {
1048 iterator=storage->factory->find_sources(storage, predicate, object);
1049 if(iterator)
1050 return librdf_new_stream_from_node_iterator(iterator, statement,
1051 LIBRDF_STATEMENT_SUBJECT);
1052 return NULL;
1053 }
1054
1055 /* only predicate/arc field blank -> use find_arcs */
1056 if(storage->factory->find_arcs && subject && !predicate && object) {
1057 iterator=storage->factory->find_arcs(storage, subject, object);
1058 if(iterator)
1059 return librdf_new_stream_from_node_iterator(iterator, statement,
1060 LIBRDF_STATEMENT_PREDICATE);
1061 return NULL;
1062 }
1063
1064 /* only object/target field blank -> use find_targets */
1065 if(storage->factory->find_targets && subject && predicate && !object) {
1066 iterator=storage->factory->find_targets(storage, subject, predicate);
1067 if(iterator)
1068 return librdf_new_stream_from_node_iterator(iterator, statement,
1069 LIBRDF_STATEMENT_OBJECT);
1070 return NULL;
1071 }
1072
1073 return storage->factory->find_statements(storage, statement);
1074 }
1075
1076
1077 typedef struct {
1078 librdf_storage *storage;
1079 librdf_stream *stream;
1080 librdf_statement *partial_statement;
1081 librdf_statement_part want;
1082 librdf_node *object_node;
1083 librdf_node *context_node;
1084 } librdf_storage_stream_to_node_iterator_context;
1085
1086
1087 static int
librdf_storage_stream_to_node_iterator_is_end(void * iterator)1088 librdf_storage_stream_to_node_iterator_is_end(void* iterator)
1089 {
1090 librdf_storage_stream_to_node_iterator_context* context=(librdf_storage_stream_to_node_iterator_context*)iterator;
1091
1092 return librdf_stream_end(context->stream);
1093 }
1094
1095
1096 static int
librdf_storage_stream_to_node_iterator_next_method(void * iterator)1097 librdf_storage_stream_to_node_iterator_next_method(void* iterator)
1098 {
1099 librdf_storage_stream_to_node_iterator_context* context=(librdf_storage_stream_to_node_iterator_context*)iterator;
1100
1101 if(context->object_node) {
1102 librdf_free_node(context->object_node);
1103 context->object_node=NULL;
1104 }
1105 if(context->context_node) {
1106 librdf_free_node(context->context_node);
1107 context->context_node=NULL;
1108 }
1109
1110 return librdf_stream_next(context->stream);
1111 }
1112
1113
1114 static void*
librdf_storage_stream_to_node_iterator_get_method(void * iterator,int flags)1115 librdf_storage_stream_to_node_iterator_get_method(void* iterator, int flags)
1116 {
1117 librdf_storage_stream_to_node_iterator_context* context=(librdf_storage_stream_to_node_iterator_context*)iterator;
1118 librdf_node* node;
1119 librdf_statement* statement=librdf_stream_get_object(context->stream);
1120
1121 if(!statement)
1122 return NULL;
1123
1124 switch(flags) {
1125 case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
1126
1127 if(!context->object_node) {
1128 switch(context->want) {
1129 case LIBRDF_STATEMENT_SUBJECT: /* SOURCES (subjects) */
1130 node=librdf_statement_get_subject(statement);
1131 break;
1132
1133 case LIBRDF_STATEMENT_PREDICATE: /* ARCS (predicates) */
1134 node=librdf_statement_get_predicate(statement);
1135 break;
1136
1137 case LIBRDF_STATEMENT_OBJECT: /* TARGETS (objects) */
1138 node=librdf_statement_get_object(statement);
1139 break;
1140
1141 case LIBRDF_STATEMENT_ALL:
1142 default: /* error */
1143 librdf_log(context->storage->world,
1144 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
1145 "Unknown statement part %d", context->want);
1146 node=NULL;
1147 }
1148 context->object_node=librdf_new_node_from_node(node);
1149 }
1150 node=context->object_node;
1151 break;
1152
1153 case LIBRDF_ITERATOR_GET_METHOD_GET_CONTEXT:
1154 if(!context->context_node) {
1155 node = librdf_stream_get_context2(context->stream);
1156 context->context_node=node ? librdf_new_node_from_node(node) : NULL;
1157 }
1158 node=context->context_node;
1159 break;
1160
1161 default:
1162 librdf_log(context->storage->world,
1163 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
1164 "Unknown iterator method flag %d", flags);
1165 node=NULL;
1166 }
1167
1168 return (void*)node;
1169 }
1170
1171
1172 static void
librdf_storage_stream_to_node_iterator_finished(void * iterator)1173 librdf_storage_stream_to_node_iterator_finished(void* iterator)
1174 {
1175 librdf_storage_stream_to_node_iterator_context* context=(librdf_storage_stream_to_node_iterator_context*)iterator;
1176 librdf_statement *partial_statement=context->partial_statement;
1177
1178 if(partial_statement)
1179 librdf_free_statement(partial_statement);
1180
1181 if(context->stream)
1182 librdf_free_stream(context->stream);
1183
1184 if(context->storage)
1185 librdf_storage_remove_reference(context->storage);
1186
1187 if(context->object_node)
1188 librdf_free_node(context->object_node);
1189
1190 if(context->context_node)
1191 librdf_free_node(context->context_node);
1192
1193 LIBRDF_FREE(librdf_storage_stream_to_node_iterator_context, context);
1194 }
1195
1196
1197 /*
1198 * librdf_storage_node_stream_to_node_create:
1199 * @storage: the storage object to use
1200 * @node1: the first node to encode in the key (or NULL if not needed)
1201 * @node2: the second node to encode in the key (or NULL if not needed)
1202 * @want: the field required from the statement
1203 *
1204 * INTERNAL - Create a stream for get sources, targets or arcs methods using find_statements method
1205 *
1206 * node1 and node2 cannot both be NULL
1207 *
1208 * Return value: a new #librdf_iterator or NULL on failure
1209 **/
1210 static librdf_iterator*
librdf_storage_node_stream_to_node_create(librdf_storage * storage,librdf_node * node1,librdf_node * node2,librdf_statement_part want)1211 librdf_storage_node_stream_to_node_create(librdf_storage* storage,
1212 librdf_node *node1,
1213 librdf_node *node2,
1214 librdf_statement_part want)
1215 {
1216 librdf_statement *partial_statement;
1217 librdf_stream *stream;
1218 librdf_storage_stream_to_node_iterator_context* context;
1219 librdf_iterator* iterator;
1220
1221 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1222 LIBRDF_ASSERT_RETURN(node1 == NULL && node2 == NULL, "both node objects are NULL", NULL);
1223
1224 partial_statement=librdf_new_statement(storage->world);
1225 if(!partial_statement)
1226 return NULL;
1227
1228 context = LIBRDF_CALLOC(librdf_storage_stream_to_node_iterator_context*, 1,
1229 sizeof(*context));
1230 if(!context) {
1231 librdf_free_statement(partial_statement);
1232 return NULL;
1233 }
1234
1235
1236 if(node1)
1237 node1=librdf_new_node_from_node(node1);
1238 if(node2)
1239 node2=librdf_new_node_from_node(node2);
1240
1241 switch(want) {
1242 case LIBRDF_STATEMENT_SUBJECT:
1243 librdf_statement_set_predicate(partial_statement, node1);
1244 librdf_statement_set_object(partial_statement, node2);
1245 break;
1246 case LIBRDF_STATEMENT_PREDICATE:
1247 librdf_statement_set_subject(partial_statement, node1);
1248 librdf_statement_set_object(partial_statement, node2);
1249 break;
1250 case LIBRDF_STATEMENT_OBJECT:
1251 librdf_statement_set_subject(partial_statement, node1);
1252 librdf_statement_set_predicate(partial_statement, node2);
1253 break;
1254
1255 case LIBRDF_STATEMENT_ALL:
1256 default:
1257 librdf_free_node(node1);
1258 librdf_free_node(node2);
1259 librdf_free_statement(partial_statement);
1260 librdf_log(storage->world,
1261 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
1262 "Illegal statement part %d seen", want);
1263 return NULL;
1264 }
1265
1266 stream=storage->factory->find_statements(storage, partial_statement);
1267 if(!stream) {
1268 librdf_storage_stream_to_node_iterator_finished(context);
1269 return librdf_new_empty_iterator(storage->world);
1270 }
1271
1272 /* initialise context */
1273 context->partial_statement=partial_statement;
1274 context->stream=stream;
1275 context->want=want;
1276
1277 context->storage=storage;
1278 librdf_storage_add_reference(context->storage);
1279
1280 iterator=librdf_new_iterator(storage->world,
1281 (void*)context,
1282 librdf_storage_stream_to_node_iterator_is_end,
1283 librdf_storage_stream_to_node_iterator_next_method,
1284 librdf_storage_stream_to_node_iterator_get_method,
1285 librdf_storage_stream_to_node_iterator_finished);
1286 if(!iterator)
1287 librdf_storage_stream_to_node_iterator_finished(context);
1288 return iterator;
1289 }
1290
1291
1292 /**
1293 * librdf_storage_get_sources:
1294 * @storage: #librdf_storage object
1295 * @arc: #librdf_node arc
1296 * @target: #librdf_node target
1297 *
1298 * Return the sources (subjects) of arc in an RDF graph given arc (predicate) and target (object).
1299 *
1300 * Searches the storage for arcs matching the given arc and target
1301 * and returns a list of the source #librdf_node objects as an iterator
1302 *
1303 * Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
1304 **/
1305 librdf_iterator*
librdf_storage_get_sources(librdf_storage * storage,librdf_node * arc,librdf_node * target)1306 librdf_storage_get_sources(librdf_storage *storage,
1307 librdf_node *arc, librdf_node *target)
1308 {
1309 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1310 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(arc, librdf_node, NULL);
1311 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(target, librdf_node, NULL);
1312
1313 if (storage->factory->find_sources)
1314 return storage->factory->find_sources(storage, arc, target);
1315
1316 return librdf_storage_node_stream_to_node_create(storage, arc, target,
1317 LIBRDF_STATEMENT_SUBJECT);
1318 }
1319
1320
1321 /**
1322 * librdf_storage_get_arcs:
1323 * @storage: #librdf_storage object
1324 * @source: #librdf_node source
1325 * @target: #librdf_node target
1326 *
1327 * Return the arcs (predicates) of an arc in an RDF graph given source (subject) and target (object).
1328 *
1329 * Searches the storage for arcs matching the given source and target
1330 * and returns a list of the arc #librdf_node objects as an iterator
1331 *
1332 * Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
1333 **/
1334 librdf_iterator*
librdf_storage_get_arcs(librdf_storage * storage,librdf_node * source,librdf_node * target)1335 librdf_storage_get_arcs(librdf_storage *storage,
1336 librdf_node *source, librdf_node *target)
1337 {
1338 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1339 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(source, librdf_node, NULL);
1340 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(target, librdf_node, NULL);
1341
1342 if (storage->factory->find_arcs)
1343 return storage->factory->find_arcs(storage, source, target);
1344
1345 return librdf_storage_node_stream_to_node_create(storage, source, target,
1346 LIBRDF_STATEMENT_PREDICATE);
1347 }
1348
1349
1350 /**
1351 * librdf_storage_get_targets:
1352 * @storage: #librdf_storage object
1353 * @source: #librdf_node source
1354 * @arc: #librdf_node arc
1355 *
1356 * Return the targets (objects) of an arc in an RDF graph given source (subject) and arc (predicate).
1357 *
1358 * Searches the storage for targets matching the given source and arc
1359 * and returns a list of the source #librdf_node objects as an iterator
1360 *
1361 * Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
1362 **/
1363 librdf_iterator*
librdf_storage_get_targets(librdf_storage * storage,librdf_node * source,librdf_node * arc)1364 librdf_storage_get_targets(librdf_storage *storage,
1365 librdf_node *source, librdf_node *arc)
1366 {
1367 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1368 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(source, librdf_node, NULL);
1369 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(arc, librdf_node, NULL);
1370
1371 if (storage->factory->find_targets)
1372 return storage->factory->find_targets(storage, source, arc);
1373
1374 return librdf_storage_node_stream_to_node_create(storage, source, arc,
1375 LIBRDF_STATEMENT_OBJECT);
1376 }
1377
1378
1379 /**
1380 * librdf_storage_get_arcs_in:
1381 * @storage: #librdf_storage object
1382 * @node: #librdf_node resource node
1383 *
1384 * Return the properties pointing to the given resource.
1385 *
1386 * Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
1387 **/
1388 librdf_iterator*
librdf_storage_get_arcs_in(librdf_storage * storage,librdf_node * node)1389 librdf_storage_get_arcs_in(librdf_storage *storage, librdf_node *node)
1390 {
1391 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1392 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
1393
1394 if (storage->factory->get_arcs_in)
1395 return storage->factory->get_arcs_in(storage, node);
1396
1397 return librdf_storage_node_stream_to_node_create(storage, NULL, node,
1398 LIBRDF_STATEMENT_PREDICATE);
1399 }
1400
1401
1402 /**
1403 * librdf_storage_get_arcs_out:
1404 * @storage: #librdf_storage object
1405 * @node: #librdf_node resource node
1406 *
1407 * Return the properties pointing from the given resource.
1408 *
1409 * Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
1410 **/
1411 librdf_iterator*
librdf_storage_get_arcs_out(librdf_storage * storage,librdf_node * node)1412 librdf_storage_get_arcs_out(librdf_storage *storage, librdf_node *node)
1413 {
1414 if (storage->factory->get_arcs_out)
1415 return storage->factory->get_arcs_out(storage, node);
1416 return librdf_storage_node_stream_to_node_create(storage, node, NULL,
1417 LIBRDF_STATEMENT_PREDICATE);
1418 }
1419
1420
1421 /**
1422 * librdf_storage_has_arc_in:
1423 * @storage: #librdf_storage object
1424 * @node: #librdf_node resource node
1425 * @property: #librdf_node property node
1426 *
1427 * Check if a node has a given property pointing to it.
1428 *
1429 * Return value: non 0 if arc property does point to the resource node
1430 **/
1431 int
librdf_storage_has_arc_in(librdf_storage * storage,librdf_node * node,librdf_node * property)1432 librdf_storage_has_arc_in(librdf_storage *storage, librdf_node *node,
1433 librdf_node *property)
1434 {
1435 librdf_iterator *iterator;
1436 int status;
1437
1438 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 0);
1439 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
1440 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(property, librdf_node, 0);
1441
1442 if (storage->factory->has_arc_in)
1443 return storage->factory->has_arc_in(storage, node, property);
1444
1445 iterator=librdf_storage_get_sources(storage, property, node);
1446 if(!iterator)
1447 return 0;
1448
1449 /* a non-empty list of sources is success */
1450 status=!librdf_iterator_end(iterator);
1451 librdf_free_iterator(iterator);
1452
1453 return status;
1454 }
1455
1456
1457 /**
1458 * librdf_storage_has_arc_out:
1459 * @storage: #librdf_storage object
1460 * @node: #librdf_node resource node
1461 * @property: #librdf_node property node
1462 *
1463 * Check if a node has a given property pointing from it.
1464 *
1465 * Return value: non 0 if arc property does point from the resource node
1466 **/
1467 int
librdf_storage_has_arc_out(librdf_storage * storage,librdf_node * node,librdf_node * property)1468 librdf_storage_has_arc_out(librdf_storage *storage, librdf_node *node,
1469 librdf_node *property)
1470 {
1471 librdf_iterator *iterator;
1472 int status;
1473
1474 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 0);
1475 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
1476 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(property, librdf_node, 0);
1477
1478 if (storage->factory->has_arc_out)
1479 return storage->factory->has_arc_out(storage, node, property);
1480
1481 iterator=librdf_storage_get_targets(storage, node, property);
1482 if(!iterator)
1483 return 0;
1484
1485 /* a non-empty list of targets is success */
1486 status=!librdf_iterator_end(iterator);
1487 librdf_free_iterator(iterator);
1488
1489 return status;
1490 }
1491
1492
1493
1494 /**
1495 * librdf_storage_context_add_statement:
1496 * @storage: #librdf_storage object
1497 * @context: #librdf_node context node
1498 * @statement: #librdf_statement statement to add
1499 *
1500 * Add a statement to a storage in a context.
1501 *
1502 * If @context is NULL, this is equivalent to librdf_storage_add_statement
1503 *
1504 * Return value: non 0 on failure
1505 **/
1506 int
librdf_storage_context_add_statement(librdf_storage * storage,librdf_node * context,librdf_statement * statement)1507 librdf_storage_context_add_statement(librdf_storage* storage,
1508 librdf_node* context,
1509 librdf_statement* statement)
1510 {
1511 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
1512 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
1513
1514 if(!context)
1515 return librdf_storage_add_statement(storage, statement);
1516
1517 if(storage->factory->context_add_statement)
1518 return storage->factory->context_add_statement(storage, context, statement);
1519 return 1;
1520 }
1521
1522
1523 /**
1524 * librdf_storage_context_add_statements:
1525 * @storage: #librdf_storage object
1526 * @context: #librdf_node context
1527 * @stream: #librdf_stream stream object
1528 *
1529 * Add statements to a storage with a context.
1530 *
1531 * If @context is NULL, this is equivalent to librdf_storage_add_statements
1532 *
1533 * Return value: Non 0 on failure
1534 **/
1535 int
librdf_storage_context_add_statements(librdf_storage * storage,librdf_node * context,librdf_stream * stream)1536 librdf_storage_context_add_statements(librdf_storage* storage,
1537 librdf_node* context,
1538 librdf_stream* stream)
1539 {
1540 int status=0;
1541
1542 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
1543 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(stream, librdf_stream, 1);
1544
1545 if(!context)
1546 return librdf_storage_add_statements(storage, stream);
1547
1548 if(storage->factory->context_add_statements)
1549 return storage->factory->context_add_statements(storage, context, stream);
1550
1551 if(!storage->factory->context_add_statement)
1552 return 1;
1553
1554 if(!stream)
1555 return 1;
1556
1557 while(!librdf_stream_end(stream)) {
1558 librdf_statement* statement=librdf_stream_get_object(stream);
1559 if(!statement)
1560 break;
1561 status=librdf_storage_context_add_statement(storage, context, statement);
1562 if(status)
1563 break;
1564 librdf_stream_next(stream);
1565 }
1566
1567 return status;
1568 }
1569
1570
1571
1572 /**
1573 * librdf_storage_context_remove_statement:
1574 * @storage: #librdf_storage object
1575 * @context: #librdf_node context node
1576 * @statement: #librdf_statement statement to remove
1577 *
1578 * Remove a statement from a storage in a context.
1579 *
1580 * If @context is NULL, this is equivalent to librdf_storage_remove_statement
1581 *
1582 * Return value: non 0 on failure
1583 **/
1584 int
librdf_storage_context_remove_statement(librdf_storage * storage,librdf_node * context,librdf_statement * statement)1585 librdf_storage_context_remove_statement(librdf_storage* storage,
1586 librdf_node* context,
1587 librdf_statement* statement)
1588 {
1589 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
1590 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
1591
1592 if(!storage->factory->context_remove_statement)
1593 return 1;
1594
1595 return storage->factory->context_remove_statement(storage, context, statement);
1596 }
1597
1598
1599 /**
1600 * librdf_storage_context_remove_statements:
1601 * @storage: #librdf_storage object
1602 * @context: #librdf_uri context
1603 *
1604 * Remove statements from a storage with the given context.
1605 *
1606 * Return value: Non 0 on failure
1607 **/
1608 int
librdf_storage_context_remove_statements(librdf_storage * storage,librdf_node * context)1609 librdf_storage_context_remove_statements(librdf_storage* storage,
1610 librdf_node* context)
1611 {
1612 librdf_stream *stream;
1613
1614 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
1615
1616 if(storage->factory->context_remove_statements)
1617 return storage->factory->context_remove_statements(storage, context);
1618
1619 if(!storage->factory->context_remove_statement)
1620 return 1;
1621
1622 stream=librdf_storage_context_as_stream(storage, context);
1623 if(!stream)
1624 return 1;
1625
1626 while(!librdf_stream_end(stream)) {
1627 librdf_statement *statement=librdf_stream_get_object(stream);
1628 if(!statement)
1629 break;
1630 librdf_storage_context_remove_statement(storage, context, statement);
1631 librdf_stream_next(stream);
1632 }
1633 librdf_free_stream(stream);
1634 return 0;
1635 }
1636
1637
1638 /**
1639 * librdf_storage_context_as_stream:
1640 * @storage: #librdf_storage object
1641 * @context: #librdf_node context node
1642 *
1643 * List all statements in a storage context.
1644 *
1645 * Return value: #librdf_stream of statements or NULL on failure or context is empty
1646 **/
1647 librdf_stream*
librdf_storage_context_as_stream(librdf_storage * storage,librdf_node * context)1648 librdf_storage_context_as_stream(librdf_storage* storage, librdf_node* context)
1649 {
1650 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1651
1652 return storage->factory->context_serialise(storage, context);
1653 }
1654
1655
1656 #ifndef REDLAND_DISABLE_DEPRECATED
1657 /**
1658 * librdf_storage_context_serialise:
1659 * @storage: #librdf_storage object
1660 * @context: #librdf_node context node
1661 *
1662 * List all statements in a storage context (DEPRECATED).
1663 *
1664 * DEPRECATED to reduce confusion with the librdf_serializer class.
1665 * Please use librdf_storage_context_as_stream.
1666 *
1667 * Return value: #librdf_stream of statements or NULL on failure or context is empty
1668 **/
1669 librdf_stream*
librdf_storage_context_serialise(librdf_storage * storage,librdf_node * context)1670 librdf_storage_context_serialise(librdf_storage* storage,
1671 librdf_node* context)
1672 {
1673 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1674
1675 return librdf_storage_context_as_stream(storage, context);
1676 }
1677 #endif
1678
1679
1680 /**
1681 * librdf_storage_supports_query:
1682 * @storage: #librdf_storage object
1683 * @query: #librdf_query query object
1684 *
1685 * Check if a storage system supports a query language.
1686 *
1687 * Return value: non-0 if the query is supported.
1688 **/
1689 int
librdf_storage_supports_query(librdf_storage * storage,librdf_query * query)1690 librdf_storage_supports_query(librdf_storage* storage, librdf_query *query)
1691 {
1692 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 0);
1693 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(query, librdf_query, 0);
1694
1695 if(storage->factory->supports_query)
1696 return storage->factory->supports_query(storage, query);
1697 else
1698 return 0;
1699 }
1700
1701
1702 /**
1703 * librdf_storage_query_execute:
1704 * @storage: #librdf_storage object
1705 * @query: #librdf_query query object
1706 *
1707 * Run the given query against the storage.
1708 *
1709 * Return value: #librdf_query_results or NULL on failure
1710 **/
1711 librdf_query_results*
librdf_storage_query_execute(librdf_storage * storage,librdf_query * query)1712 librdf_storage_query_execute(librdf_storage* storage, librdf_query *query)
1713 {
1714 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1715 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(query, librdf_query, NULL);
1716
1717 if(storage->factory->supports_query)
1718 return storage->factory->query_execute(storage, query);
1719 else
1720 return NULL;
1721 }
1722
1723
1724 /**
1725 * librdf_storage_sync:
1726 * @storage: #librdf_storage object
1727 *
1728 * Synchronise the storage to the storage implementation.
1729 *
1730 * Return value: non-0 on failure
1731 **/
1732 int
librdf_storage_sync(librdf_storage * storage)1733 librdf_storage_sync(librdf_storage* storage)
1734 {
1735 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
1736
1737 if(storage->factory->sync)
1738 return storage->factory->sync(storage);
1739 return 0;
1740 }
1741
1742
1743 /**
1744 * librdf_storage_find_statements_in_context:
1745 * @storage: #librdf_storage object
1746 * @statement: #librdf_statement partial statement to find
1747 * @context_node: context #librdf_node (or NULL)
1748 *
1749 * Search the storage for matching statements in a given context.
1750 *
1751 * Searches the storage for a (partial) statement as described in
1752 * librdf_statement_match() in the given context and returns a
1753 * #librdf_stream of matching #librdf_statement objects. If
1754 * context is NULL, this is equivalent to librdf_storage_find_statements.
1755 *
1756 * Return value: #librdf_stream of matching statements (may be empty) or NULL on failure
1757 **/
1758 librdf_stream*
librdf_storage_find_statements_in_context(librdf_storage * storage,librdf_statement * statement,librdf_node * context_node)1759 librdf_storage_find_statements_in_context(librdf_storage* storage, librdf_statement* statement, librdf_node* context_node)
1760 {
1761 librdf_stream *stream;
1762
1763 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1764 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
1765
1766 if(storage->factory->find_statements_in_context)
1767 return storage->factory->find_statements_in_context(storage, statement, context_node);
1768
1769 statement=librdf_new_statement_from_statement(statement);
1770 if(!statement)
1771 return NULL;
1772
1773 stream=librdf_storage_context_as_stream(storage, context_node);
1774 if(!stream) {
1775 librdf_free_statement(statement);
1776 return NULL;
1777 }
1778
1779 librdf_stream_add_map(stream,
1780 &librdf_stream_statement_find_map,
1781 (librdf_stream_map_free_context_handler)&librdf_free_statement, (void*)statement);
1782
1783 return stream;
1784 }
1785
1786
1787 /**
1788 * librdf_storage_get_contexts:
1789 * @storage: #librdf_storage object
1790 *
1791 * Return the list of contexts in the store.
1792 *
1793 * Returns an iterator of #librdf_node context nodes for each
1794 * context in the store.
1795 *
1796 * Return value: #librdf_iterator of context nodes or NULL on failure or if contexts are not supported
1797 **/
1798 librdf_iterator*
librdf_storage_get_contexts(librdf_storage * storage)1799 librdf_storage_get_contexts(librdf_storage* storage)
1800 {
1801 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1802
1803 if(storage->factory->get_contexts)
1804 return storage->factory->get_contexts(storage);
1805 else
1806 return NULL;
1807 }
1808
1809
1810
1811 /**
1812 * librdf_storage_get_feature:
1813 * @storage: #librdf_storage object
1814 * @feature: #librdf_uri feature property
1815 *
1816 * Get the value of a storage feature.
1817 *
1818 * Return value: new #librdf_node feature value or NULL if no such feature
1819 * exists or the value is empty.
1820 **/
1821 librdf_node*
librdf_storage_get_feature(librdf_storage * storage,librdf_uri * feature)1822 librdf_storage_get_feature(librdf_storage* storage, librdf_uri* feature)
1823 {
1824 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
1825 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(feature, librdf_uri, NULL);
1826
1827 if(storage->factory->get_feature)
1828 return storage->factory->get_feature(storage, feature);
1829 return NULL;
1830 }
1831
1832
1833 /**
1834 * librdf_storage_set_feature:
1835 * @storage: #librdf_storage object
1836 * @feature: #librdf_uri feature property
1837 * @value: #librdf_node feature property value
1838 *
1839 * Set the value of a storage feature.
1840 *
1841 * Return value: non 0 on failure (negative if no such feature)
1842 **/
1843 int
librdf_storage_set_feature(librdf_storage * storage,librdf_uri * feature,librdf_node * value)1844 librdf_storage_set_feature(librdf_storage* storage, librdf_uri* feature,
1845 librdf_node* value)
1846 {
1847 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, -1);
1848 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(feature, librdf_uri, -1);
1849 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(value, librdf_node, -1);
1850
1851 if(storage->factory->set_feature)
1852 return storage->factory->set_feature(storage, feature, value);
1853 return -1;
1854 }
1855
1856
1857 /**
1858 * librdf_storage_find_statements_with_options:
1859 * @storage: #librdf_storage object
1860 * @statement: #librdf_statement partial statement to find
1861 * @context_node: #librdf_node context node or NULL.
1862 * @options: #librdf_hash of matching options or NULL
1863 *
1864 * Search the storage for matching statements with match options.
1865 *
1866 * Searches the storage for a (partial) statement as described in
1867 * librdf_statement_match() and returns a #librdf_stream of
1868 * matching #librdf_statement objects.
1869 *
1870 * If options is given then the match is made according to
1871 * the given options. If options is NULL, this is equivalent
1872 * to librdf_storage_find_statements_in_context.
1873 *
1874 * Return value: #librdf_stream of matching statements (may be empty) or NULL on failure
1875 **/
1876 librdf_stream*
librdf_storage_find_statements_with_options(librdf_storage * storage,librdf_statement * statement,librdf_node * context_node,librdf_hash * options)1877 librdf_storage_find_statements_with_options(librdf_storage* storage,
1878 librdf_statement* statement,
1879 librdf_node* context_node,
1880 librdf_hash* options)
1881 {
1882 if(storage->factory->find_statements_with_options)
1883 return storage->factory->find_statements_with_options(storage, statement, context_node, options);
1884 else
1885 return librdf_storage_find_statements_in_context(storage, statement, context_node);
1886 }
1887
1888
1889
1890 /**
1891 * librdf_storage_transaction_start:
1892 * @storage: the storage object
1893 *
1894 * Start a transaction
1895 *
1896 * Return value: non-0 on failure
1897 **/
1898 int
librdf_storage_transaction_start(librdf_storage * storage)1899 librdf_storage_transaction_start(librdf_storage* storage)
1900 {
1901 if(storage->factory->transaction_start)
1902 return storage->factory->transaction_start(storage);
1903 else
1904 return 1;
1905 }
1906
1907
1908 /**
1909 * librdf_storage_transaction_start_with_handle:
1910 * @storage: the storage object
1911 * @handle: the transaction object
1912 *
1913 * Start a transaction using an existing external transaction object.
1914 *
1915 * Return value: non-0 on failure
1916 **/
1917 int
librdf_storage_transaction_start_with_handle(librdf_storage * storage,void * handle)1918 librdf_storage_transaction_start_with_handle(librdf_storage* storage, void* handle)
1919 {
1920 if(storage->factory->transaction_start_with_handle)
1921 return storage->factory->transaction_start_with_handle(storage, handle);
1922 else
1923 return 1;
1924 }
1925
1926
1927 /**
1928 * librdf_storage_transaction_commit:
1929 * @storage: the storage object
1930 *
1931 * Commit a transaction.
1932 *
1933 * Return value: non-0 on failure
1934 **/
1935 int
librdf_storage_transaction_commit(librdf_storage * storage)1936 librdf_storage_transaction_commit(librdf_storage* storage)
1937 {
1938 if(storage->factory->transaction_commit)
1939 return storage->factory->transaction_commit(storage);
1940 else
1941 return 1;
1942 }
1943
1944
1945 /**
1946 * librdf_storage_transaction_rollback:
1947 * @storage: the storage object
1948 *
1949 * Rollback a transaction.
1950 *
1951 * Return value: non-0 on failure
1952 **/
1953 int
librdf_storage_transaction_rollback(librdf_storage * storage)1954 librdf_storage_transaction_rollback(librdf_storage* storage)
1955 {
1956 if(storage->factory->transaction_rollback)
1957 return storage->factory->transaction_rollback(storage);
1958 else
1959 return 1;
1960 }
1961
1962
1963 /**
1964 * librdf_storage_transaction_get_handle:
1965 * @storage: the storage object
1966 *
1967 * Get the current transaction handle.
1968 *
1969 * Return value: non-0 on failure
1970 **/
1971 void*
librdf_storage_transaction_get_handle(librdf_storage * storage)1972 librdf_storage_transaction_get_handle(librdf_storage* storage)
1973 {
1974 if(storage->factory->transaction_get_handle)
1975 return storage->factory->transaction_get_handle(storage);
1976 else
1977 return NULL;
1978 }
1979
1980
1981 #endif
1982
1983
1984 /* TEST CODE */
1985
1986
1987 #ifdef STANDALONE
1988
1989 /* one more prototype */
1990 int main(int argc, char *argv[]);
1991
1992
1993 int
main(int argc,char * argv[])1994 main(int argc, char *argv[])
1995 {
1996 librdf_storage* storage;
1997 const char *program=librdf_basename((const char*)argv[0]);
1998 librdf_world *world;
1999
2000 /* triples of arguments to librdf_new_storage */
2001 const char* const storages[] = {
2002 "memory", NULL, "contexts='yes'",
2003 #ifdef HAVE_BDB_HASH
2004 "hashes", "test", "hash-type='bdb',dir='.',write='yes',new='yes',contexts='yes'",
2005 #else
2006 "hashes", "test", "hash-type='memory',write='yes',new='yes',contexts='yes'",
2007 #endif
2008 #ifdef STORAGE_TREES
2009 "trees", "test", "contexts='yes'",
2010 #endif
2011 #ifdef STORAGE_FILE
2012 "file", "file://../redland.rdf", NULL,
2013 "uri", "http://librdf.org/redland.rdf", NULL,
2014 #endif
2015 #ifdef STORAGE_MYSQL
2016 "mysql", "test", "host='localhost',database='test'",
2017 #endif
2018 #ifdef STORAGE_POSTGRESQL
2019 "postgresql", "test", "host='localhost',database='test'",
2020 #endif
2021 #ifdef STORAGE_TSTORE
2022 "tstore", "test", "host='localhost',database='test'",
2023 #endif
2024 #ifdef STORAGE_SQLITE
2025 "sqlite", "test", "new='yes'",
2026 #endif
2027 NULL, NULL, NULL
2028 };
2029
2030 int test = 0;
2031 int ret = 0;
2032
2033 world=librdf_new_world();
2034 librdf_world_open(world);
2035
2036 for ( ; storages[test] != NULL; test += 3) {
2037
2038 fprintf(stdout, "%s: Creating storage %s\n", program, storages[test]);
2039 storage=librdf_new_storage(world,
2040 storages[test], /* type */
2041 storages[test+1], /* name */
2042 storages[test+2]); /* options */
2043 if(!storage) {
2044 fprintf(stderr, "%s: WARNING: Failed to create new storage %s\n",
2045 program, storages[test]);
2046 continue;
2047 }
2048
2049
2050 fprintf(stdout, "%s: Opening storage\n", program);
2051 if(librdf_storage_open(storage, NULL)) {
2052 fprintf(stderr, "%s: Failed to open storage type %s\n",
2053 program, storages[test]);
2054 ret++;
2055 continue;
2056 }
2057
2058
2059 /* Can do nothing here since need model and storage working */
2060
2061 fprintf(stdout, "%s: Closing storage\n", program);
2062 librdf_storage_close(storage);
2063
2064 fprintf(stdout, "%s: Freeing storage\n", program);
2065 librdf_free_storage(storage);
2066
2067 }
2068
2069
2070 librdf_free_world(world);
2071
2072 return ret;
2073 }
2074
2075 #endif
2076