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