mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 16:49:41 +02:00
1919 lines
53 KiB
C
1919 lines
53 KiB
C
/* -*- Mode: c; c-basic-offset: 2 -*-
|
|
*
|
|
* rdf_storage.c - RDF Storage (Triple store) interface
|
|
*
|
|
* Copyright (C) 2000-2008, David Beckett http://www.dajobe.org/
|
|
* Copyright (C) 2000-2005, University of Bristol, UK http://www.bristol.ac.uk/
|
|
*
|
|
* This package is Free Software and part of Redland http://librdf.org/
|
|
*
|
|
* It is licensed under the following three licenses as alternatives:
|
|
* 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
|
|
* 2. GNU General Public License (GPL) V2 or any newer version
|
|
* 3. Apache License, V2.0 or any newer version
|
|
*
|
|
* You may not use this file except in compliance with at least one of
|
|
* the above three licenses.
|
|
*
|
|
* See LICENSE.html or LICENSE.txt at the top of this package for the
|
|
* complete terms and further detail along with the license texts for
|
|
* the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <rdf_config.h>
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
#include <win32_rdf_config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <sys/types.h>
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h> /* for abort() as used in errors */
|
|
#endif
|
|
|
|
#ifdef MODULAR_LIBRDF
|
|
#include <ltdl.h>
|
|
#endif
|
|
|
|
#include <redland.h>
|
|
#include <rdf_storage.h>
|
|
|
|
|
|
#ifndef STANDALONE
|
|
|
|
/* prototypes for functions implementing get_sources, arcs, targets
|
|
* librdf_iterator via conversion from a librdf_stream of librdf_statement
|
|
*/
|
|
static int librdf_storage_stream_to_node_iterator_is_end(void* iterator);
|
|
static int librdf_storage_stream_to_node_iterator_next_method(void* iterator);
|
|
static void* librdf_storage_stream_to_node_iterator_get_method(void* iterator, int flags);
|
|
static void librdf_storage_stream_to_node_iterator_finished(void* iterator);
|
|
|
|
/* helper function for creating iterators for get sources, targets, arcs */
|
|
static librdf_iterator* librdf_storage_node_stream_to_node_create(librdf_storage* storage, librdf_node* node1, librdf_node *node2, librdf_statement_part want);
|
|
|
|
#ifdef MODULAR_LIBRDF
|
|
/* helper function for dynamically loading storage modules */
|
|
static lt_dlhandle
|
|
librdf_storage_load_module(librdf_world *world,
|
|
const char* lib_name,
|
|
const char* init_func_name);
|
|
#endif
|
|
|
|
|
|
/**
|
|
* librdf_init_storage:
|
|
* @world: redland world object
|
|
*
|
|
* INTERNAL - Initialise the storage module.
|
|
*
|
|
* Initialises and registers all
|
|
* compiled storage modules. Must be called before using any of the storage
|
|
* factory functions such as librdf_get_storage_factory()
|
|
**/
|
|
void
|
|
librdf_init_storage(librdf_world *world)
|
|
{
|
|
#ifdef MODULAR_LIBRDF
|
|
lt_dlhandle module = NULL;
|
|
|
|
if (!world->storage_modules)
|
|
world->storage_modules = raptor_new_sequence(
|
|
(raptor_sequence_free_handler *)lt_dlclose, NULL);
|
|
#endif
|
|
|
|
/* Always have storage memory - must always be the default storage */
|
|
librdf_init_storage_list(world);
|
|
|
|
/* Always have storage list, hashes, file implementations available */
|
|
librdf_init_storage_hashes(world);
|
|
|
|
#ifdef STORAGE_TREES
|
|
librdf_init_storage_trees(world);
|
|
#endif
|
|
|
|
#ifdef MODULAR_LIBRDF
|
|
|
|
#ifdef STORAGE_FILE
|
|
module = librdf_storage_load_module(world, "librdf_storage_file",
|
|
"librdf_init_storage_file");
|
|
if (module)
|
|
raptor_sequence_push(world->storage_modules, module);
|
|
#endif
|
|
|
|
#ifdef STORAGE_MYSQL
|
|
module = librdf_storage_load_module(world, "librdf_storage_mysql",
|
|
"librdf_init_storage_mysql");
|
|
if (module)
|
|
raptor_sequence_push(world->storage_modules, module);
|
|
#endif
|
|
|
|
#ifdef STORAGE_POSTGRESQL
|
|
module = librdf_storage_load_module(world, "librdf_storage_postgresql",
|
|
"librdf_init_storage_postgresql");
|
|
if (module)
|
|
raptor_sequence_push(world->storage_modules, module);
|
|
#endif
|
|
|
|
#ifdef STORAGE_TSTORE
|
|
module = librdf_storage_load_module(world, "librdf_storage_tstore",
|
|
"librdf_init_storage_tstore");
|
|
if (module)
|
|
raptor_sequence_push(world->storage_modules, module);
|
|
#endif
|
|
|
|
#ifdef STORAGE_SQLITE
|
|
module = librdf_storage_load_module(world, "librdf_storage_sqlite",
|
|
"librdf_init_storage_sqlite");
|
|
if (module)
|
|
raptor_sequence_push(world->storage_modules, module);
|
|
#endif
|
|
|
|
#else /* if !MODULAR_LIBRDF */
|
|
|
|
#ifdef STORAGE_FILE
|
|
librdf_init_storage_file(world);
|
|
#endif
|
|
#ifdef STORAGE_MYSQL
|
|
librdf_init_storage_mysql(world);
|
|
#endif
|
|
#ifdef STORAGE_POSTGRESQL
|
|
librdf_init_storage_postgresql(world);
|
|
#endif
|
|
#ifdef STORAGE_TSTORE
|
|
librdf_init_storage_tstore(world);
|
|
#endif
|
|
#ifdef STORAGE_SQLITE
|
|
librdf_init_storage_sqlite(world);
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_finish_storage:
|
|
* @world: redland world object
|
|
*
|
|
* INTERNAL - Terminate the storage module.
|
|
*
|
|
**/
|
|
void
|
|
librdf_finish_storage(librdf_world *world)
|
|
{
|
|
#ifdef MODULAR_LIBRDF
|
|
if(world->storage_modules) {
|
|
raptor_free_sequence(world->storage_modules);
|
|
world->storage_modules=NULL;
|
|
}
|
|
#endif
|
|
|
|
if(world->storages) {
|
|
raptor_free_sequence(world->storages);
|
|
world->storages=NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* helper functions */
|
|
|
|
|
|
static void
|
|
librdf_free_storage_factory(librdf_storage_factory* factory)
|
|
{
|
|
if(factory->name)
|
|
LIBRDF_FREE(librdf_storage_factory, factory->name);
|
|
if(factory->label)
|
|
LIBRDF_FREE(librdf_storage_factory, factory->label);
|
|
LIBRDF_FREE(librdf_storage_factory, factory);
|
|
}
|
|
|
|
|
|
#ifdef MODULAR_LIBRDF
|
|
/**
|
|
* librdf_storage_load_module:
|
|
* @world: redland world object
|
|
* @lib_name: base name of shared library file
|
|
* @init_func_name: name of initialization function in library
|
|
*
|
|
* INTERNAL - Load and initialize/register a storage module
|
|
**/
|
|
static lt_dlhandle
|
|
librdf_storage_load_module(librdf_world *world,
|
|
const char* lib_name,
|
|
const char* init_func_name)
|
|
{
|
|
typedef void init_func_t(librdf_world* world);
|
|
init_func_t* init;
|
|
|
|
lt_dlhandle module = lt_dlopenext(lib_name);
|
|
if (module) {
|
|
init = (init_func_t*)lt_dlsym(module, init_func_name);
|
|
if (init) {
|
|
init(world);
|
|
} else {
|
|
LIBRDF_DEBUG2("Failed to initialize storage module %s\n", lib_name);
|
|
lt_dlclose(module);
|
|
module = NULL;
|
|
}
|
|
} else {
|
|
LIBRDF_DEBUG2("Failed to load storage module %s\n", lib_name);
|
|
}
|
|
|
|
return module;
|
|
}
|
|
#endif
|
|
|
|
|
|
/* class methods */
|
|
|
|
/**
|
|
* librdf_storage_register_factory:
|
|
* @world: redland world object
|
|
* @name: the storage factory name
|
|
* @label: the storage factory label
|
|
* @factory: pointer to function to call to register the factory
|
|
*
|
|
* Register a storage factory.
|
|
**/
|
|
void
|
|
librdf_storage_register_factory(librdf_world* world,
|
|
const char *name, const char *label,
|
|
void (*factory) (librdf_storage_factory*))
|
|
{
|
|
librdf_storage_factory *storage;
|
|
int i;
|
|
|
|
librdf_world_open(world);
|
|
|
|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
|
|
LIBRDF_DEBUG2("Received registration for storage %s\n", name);
|
|
#endif
|
|
|
|
if(!world->storages) {
|
|
world->storages=raptor_new_sequence((raptor_sequence_free_handler *)librdf_free_storage_factory, NULL);
|
|
if(!world->storages)
|
|
goto oom;
|
|
}
|
|
|
|
for(i=0;
|
|
(storage=(librdf_storage_factory*)raptor_sequence_get_at(world->storages, i));
|
|
i++) {
|
|
if(!strcmp(storage->name, name)) {
|
|
librdf_log(world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
|
"storage %s already registered", storage->name);
|
|
return;
|
|
}
|
|
}
|
|
|
|
storage=(librdf_storage_factory*)LIBRDF_CALLOC(librdf_storage_factory, 1,
|
|
sizeof(librdf_storage_factory));
|
|
if(!storage)
|
|
goto oom;
|
|
|
|
storage->name=(char*)LIBRDF_MALLOC(cstring, strlen(name)+1);
|
|
if(!storage->name)
|
|
goto oom_tidy;
|
|
strcpy(storage->name, name);
|
|
|
|
storage->label=(char*)LIBRDF_MALLOC(cstring, strlen(label)+1);
|
|
if(!storage->label)
|
|
goto oom_tidy;
|
|
strcpy(storage->label, label);
|
|
|
|
if(raptor_sequence_push(world->storages, storage))
|
|
goto oom;
|
|
|
|
/* Call the storage registration function on the new object */
|
|
(*factory)(storage);
|
|
|
|
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
|
|
LIBRDF_DEBUG3("%s has context size %d\n", name, storage->context_length);
|
|
#endif
|
|
|
|
return;
|
|
|
|
oom_tidy:
|
|
librdf_free_storage_factory(storage);
|
|
oom:
|
|
LIBRDF_FATAL1(world, LIBRDF_FROM_STORAGE, "Out of memory");
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_get_storage_factory:
|
|
* @world: redland world object
|
|
* @name: the factory name or NULL for the default factory
|
|
*
|
|
* Get a storage factory by name.
|
|
*
|
|
* Return value: the factory object or NULL if there is no such factory
|
|
**/
|
|
librdf_storage_factory*
|
|
librdf_get_storage_factory(librdf_world* world, const char *name)
|
|
{
|
|
librdf_storage_factory *factory;
|
|
|
|
librdf_world_open(world);
|
|
|
|
/* return 1st storage if no particular one wanted - why? */
|
|
if(!name) {
|
|
factory=(librdf_storage_factory *)raptor_sequence_get_at(world->storages, 0);
|
|
if(!factory) {
|
|
LIBRDF_DEBUG1("No (default) storages registered\n");
|
|
return NULL;
|
|
}
|
|
} else {
|
|
int i;
|
|
|
|
for(i=0;
|
|
(factory=(librdf_storage_factory*)raptor_sequence_get_at(world->storages, i));
|
|
i++) {
|
|
if(!strcmp(factory->name, name))
|
|
break;
|
|
}
|
|
/* else FACTORY name not found */
|
|
if(!factory) {
|
|
LIBRDF_DEBUG2("No storage with name %s found\n", name);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return factory;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_enumerate:
|
|
* @world: redland world object
|
|
* @counter: index into the list of storages
|
|
* @name: pointer to store the name of the storage (or NULL)
|
|
* @label: pointer to store syntax readable label (or NULL)
|
|
*
|
|
* Get information on storages.
|
|
*
|
|
* Return value: non 0 on failure of if counter is out of range
|
|
**/
|
|
int
|
|
librdf_storage_enumerate(librdf_world* world,
|
|
const unsigned int counter,
|
|
const char **name, const char **label)
|
|
{
|
|
librdf_storage_factory *factory;
|
|
|
|
librdf_world_open(world);
|
|
|
|
factory=(librdf_storage_factory*)raptor_sequence_get_at(world->storages,
|
|
counter);
|
|
if(!factory)
|
|
return 1;
|
|
|
|
if(name)
|
|
*name=factory->name;
|
|
if(label)
|
|
*label=factory->label;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_new_storage:
|
|
* @world: redland world object
|
|
* @storage_name: the storage factory name
|
|
* @name: an identifier for the storage
|
|
* @options_string: options to initialise storage
|
|
*
|
|
* Constructor - create a new #librdf_storage object.
|
|
*
|
|
* The options are encoded as described in librdf_hash_from_string()
|
|
* and can be NULL if none are required.
|
|
*
|
|
* Return value: a new #librdf_storage object or NULL on failure
|
|
*
|
|
*/
|
|
librdf_storage*
|
|
librdf_new_storage(librdf_world *world,
|
|
const char *storage_name, const char *name,
|
|
const char *options_string)
|
|
{
|
|
librdf_storage_factory* factory;
|
|
librdf_hash* options_hash;
|
|
|
|
librdf_world_open(world);
|
|
|
|
factory=librdf_get_storage_factory(world, storage_name);
|
|
if(!factory)
|
|
return NULL;
|
|
|
|
options_hash=librdf_new_hash(world, NULL);
|
|
if(!options_hash)
|
|
return NULL;
|
|
|
|
if(librdf_hash_open(options_hash, NULL, 0, 1, 1, NULL)) {
|
|
librdf_free_hash(options_hash);
|
|
return NULL;
|
|
}
|
|
|
|
if(librdf_hash_from_string(options_hash, options_string)) {
|
|
librdf_free_hash(options_hash);
|
|
return NULL;
|
|
}
|
|
|
|
return librdf_new_storage_from_factory(world, factory, name, options_hash);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_new_storage_with_options:
|
|
* @world: redland world object
|
|
* @storage_name: the storage factory name
|
|
* @name: an identifier for the storage
|
|
* @options: #librdf_hash of options to use
|
|
*
|
|
* Constructor - create a new #librdf_storage object.
|
|
*
|
|
* The options can be NULL if none are required.
|
|
*
|
|
* Return value: a new #librdf_storage object or NULL on failure
|
|
*
|
|
*/
|
|
librdf_storage*
|
|
librdf_new_storage_with_options(librdf_world *world,
|
|
const char *storage_name, const char *name,
|
|
librdf_hash *options)
|
|
{
|
|
librdf_storage_factory* factory;
|
|
librdf_hash* options_hash;
|
|
|
|
librdf_world_open(world);
|
|
|
|
factory=librdf_get_storage_factory(world, storage_name);
|
|
if(!factory)
|
|
return NULL;
|
|
|
|
options_hash=librdf_new_hash_from_hash(options);
|
|
if(!options_hash)
|
|
return NULL;
|
|
|
|
if(librdf_hash_open(options_hash, NULL, 0, 1, 1, NULL)) {
|
|
librdf_free_hash(options_hash);
|
|
return NULL;
|
|
}
|
|
|
|
return librdf_new_storage_from_factory(world, factory, name, options_hash);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_new_storage_from_storage - Copy constructor - create a new librdf_storage object from an existing one
|
|
* @old_storage: the existing storage #librdf_storage to use
|
|
*
|
|
* Should create a new storage in the same context as the existing one
|
|
* as appropriate for the storage. For example, in a RDBMS storage
|
|
* it would be a new database, or in on disk it would be a new
|
|
* set of files. This will mean automatically generating
|
|
* a new identifier for the storage, maybe based on the existing
|
|
* storage identifier.
|
|
*
|
|
* Return value: a new #librdf_storage object or NULL on failure
|
|
*
|
|
*/
|
|
librdf_storage*
|
|
librdf_new_storage_from_storage(librdf_storage* old_storage)
|
|
{
|
|
librdf_storage* new_storage;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(old_storage, librdf_storage, NULL);
|
|
|
|
if(!old_storage->factory->clone) {
|
|
librdf_log(old_storage->world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
|
"clone method not implemented for storage factory %s",
|
|
old_storage->factory->name);
|
|
return NULL;
|
|
}
|
|
|
|
new_storage=(librdf_storage*)LIBRDF_CALLOC(librdf_storage, 1,
|
|
sizeof(librdf_storage));
|
|
if(!new_storage)
|
|
return NULL;
|
|
|
|
/* set usage to 1 early to allow cleanup with librdf_free_storage() */
|
|
new_storage->usage=1;
|
|
|
|
new_storage->context=(char*)LIBRDF_CALLOC(librdf_storage_context, 1,
|
|
old_storage->factory->context_length);
|
|
if(!new_storage->context) {
|
|
librdf_free_storage(new_storage);
|
|
return NULL;
|
|
}
|
|
|
|
new_storage->world=old_storage->world;
|
|
|
|
/* do this now so librdf_free_storage won't call new factory on
|
|
* partially copied storage
|
|
*/
|
|
new_storage->factory=old_storage->factory;
|
|
|
|
/* clone is assumed to do leave the new storage in the same state
|
|
* after an init() method on an existing storage - i.e ready to
|
|
* use but closed.
|
|
*/
|
|
if(old_storage->factory->clone(new_storage, old_storage)) {
|
|
librdf_free_storage(new_storage);
|
|
return NULL;
|
|
}
|
|
|
|
return new_storage;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_new_storage_from_factory:
|
|
* @world: redland world object
|
|
* @factory: the factory to use to construct the storage
|
|
* @name: name to use for storage
|
|
* @options: #librdf_hash of options to initialise storage
|
|
*
|
|
* Constructor - create a new #librdf_storage object.
|
|
*
|
|
* If the options are present, they become owned by the storage
|
|
* and should no longer be used.
|
|
*
|
|
* Return value: a new #librdf_storage object or NULL on failure
|
|
*
|
|
*/
|
|
librdf_storage*
|
|
librdf_new_storage_from_factory(librdf_world *world,
|
|
librdf_storage_factory* factory,
|
|
const char *name,
|
|
librdf_hash* options)
|
|
{
|
|
librdf_storage* storage;
|
|
|
|
librdf_world_open(world);
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(factory, librdf_storage_factory, NULL);
|
|
|
|
if(!factory) {
|
|
librdf_free_hash(options);
|
|
return NULL;
|
|
}
|
|
|
|
storage=(librdf_storage*)LIBRDF_CALLOC(librdf_storage, 1,
|
|
sizeof(librdf_storage));
|
|
if(!storage) {
|
|
librdf_free_hash(options);
|
|
return NULL;
|
|
}
|
|
|
|
storage->world=world;
|
|
|
|
/* set usage to 1 early to allow cleanup with librdf_free_storage() */
|
|
storage->usage=1;
|
|
|
|
storage->context=(char*)LIBRDF_CALLOC(librdf_storage_context, 1,
|
|
factory->context_length);
|
|
if(!storage->context) {
|
|
librdf_free_hash(options);
|
|
librdf_free_storage(storage);
|
|
return NULL;
|
|
}
|
|
|
|
storage->factory=factory;
|
|
|
|
if(factory->init(storage, name, options)) {
|
|
librdf_free_storage(storage);
|
|
return NULL;
|
|
}
|
|
|
|
return storage;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_free_storage:
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* Destructor - destroy a #librdf_storage object.
|
|
**/
|
|
void
|
|
librdf_free_storage(librdf_storage* storage)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN(storage, librdf_storage);
|
|
|
|
if(--storage->usage)
|
|
return;
|
|
|
|
if(storage->factory)
|
|
storage->factory->terminate(storage);
|
|
|
|
if(storage->context)
|
|
LIBRDF_FREE(librdf_storage_context, storage->context);
|
|
LIBRDF_FREE(librdf_storage, storage);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_add_reference:
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* Increment storage reference count by one.
|
|
* This function is intended to be internal to librdf storage modules.
|
|
**/
|
|
void
|
|
librdf_storage_add_reference(librdf_storage *storage)
|
|
{
|
|
storage->usage++;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_remove_reference(libdf_storage *storage)
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* Decrement storage reference count by one.
|
|
* Free the storage if reference count becomes zero.
|
|
* This function is intended to be internal to librdf storage modules.
|
|
**/
|
|
void
|
|
librdf_storage_remove_reference(librdf_storage *storage)
|
|
{
|
|
librdf_free_storage(storage);
|
|
}
|
|
|
|
|
|
/* methods */
|
|
|
|
/**
|
|
* librdf_storage_open:
|
|
* @storage: #librdf_storage object
|
|
* @model: model stored
|
|
*
|
|
* Start a model / storage association.
|
|
*
|
|
* This is ended with librdf_storage_close()
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_open(librdf_storage* storage, librdf_model* model)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
|
|
return storage->factory->open(storage, model);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_close:
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* End a model / storage association.
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_close(librdf_storage* storage)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
|
|
return storage->factory->close(storage);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_size:
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* Get the number of statements stored.
|
|
*
|
|
* Return value: The number of statements or < 0 if cannot be determined
|
|
**/
|
|
int
|
|
librdf_storage_size(librdf_storage* storage)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, -1);
|
|
|
|
return storage->factory->size(storage);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_add_statement:
|
|
* @storage: #librdf_storage object
|
|
* @statement: #librdf_statement statement to add
|
|
*
|
|
* Add a statement to a storage.
|
|
*
|
|
* The passed-in statement is copied when added to the store, not
|
|
* shared with the store.
|
|
*
|
|
* If the statement already exists in the store, it is not added
|
|
* unless Redland contexts are being used.
|
|
*
|
|
* Enforces that the statement is legal for RDF - URI or blank subject,
|
|
* URI predicate and URI or blank or literal object (i.e. anything).
|
|
*
|
|
* Return value: non 0 on failure, <0 on error, >0 if statement was illegal
|
|
**/
|
|
int
|
|
librdf_storage_add_statement(librdf_storage* storage,
|
|
librdf_statement* statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
|
|
|
|
/* subject can be a URI or blank node */
|
|
if(!librdf_node_is_resource(statement->subject) &&
|
|
!librdf_node_is_blank(statement->subject))
|
|
return 1;
|
|
|
|
/* predicate can only be a URI */
|
|
if(!librdf_node_is_resource(statement->predicate))
|
|
return 1;
|
|
|
|
/* object can be any node - no check needed */
|
|
|
|
if(storage->factory->add_statement)
|
|
return storage->factory->add_statement(storage, statement);
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_add_statements:
|
|
* @storage: #librdf_storage object
|
|
* @statement_stream: #librdf_stream of statements
|
|
*
|
|
* Add a stream of statements to the storage.
|
|
*
|
|
* If any of the statements already exists in the store, they are not
|
|
* added unless Redland contexts are being used.
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_add_statements(librdf_storage* storage,
|
|
librdf_stream* statement_stream)
|
|
{
|
|
int status=0;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement_stream, librdf_stream, 1);
|
|
|
|
if(storage->factory->add_statements)
|
|
return storage->factory->add_statements(storage, statement_stream);
|
|
|
|
while(!librdf_stream_end(statement_stream)) {
|
|
librdf_statement* statement=librdf_stream_get_object(statement_stream);
|
|
|
|
if(statement) {
|
|
status=librdf_storage_add_statement(storage, statement);
|
|
if(status > 0)
|
|
/* just skip illegal statements */
|
|
status=0;
|
|
}
|
|
else
|
|
status=1;
|
|
|
|
if(status)
|
|
break;
|
|
|
|
librdf_stream_next(statement_stream);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_remove_statement:
|
|
* @storage: #librdf_storage object
|
|
* @statement: #librdf_statement statement to remove
|
|
*
|
|
* Remove a statement from the storage.
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_remove_statement(librdf_storage* storage,
|
|
librdf_statement* statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
|
|
|
|
if(storage->factory->remove_statement)
|
|
return storage->factory->remove_statement(storage, statement);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_contains_statement:
|
|
* @storage: #librdf_storage object
|
|
* @statement: #librdf_statement statement to check
|
|
*
|
|
* Test if a given statement is present in the storage.
|
|
*
|
|
* Return value: non 0 if the storage contains the statement (>0 if illegal statement)
|
|
**/
|
|
int
|
|
librdf_storage_contains_statement(librdf_storage* storage,
|
|
librdf_statement* statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
|
|
|
|
/* subject can be a URI or blank node */
|
|
if(!statement->subject ||
|
|
(!librdf_node_is_resource(statement->subject) &&
|
|
!librdf_node_is_blank(statement->subject)))
|
|
return 1;
|
|
|
|
/* predicate can only be a URI */
|
|
if(!statement->predicate || !librdf_node_is_resource(statement->predicate))
|
|
return 1;
|
|
|
|
if(!statement->object)
|
|
return 1;
|
|
|
|
return storage->factory->contains_statement(storage, statement);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_serialise:
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* Serialise the storage as a librdf_stream of statemetns.
|
|
*
|
|
* Return value: #librdf_stream of statements or NULL on failure
|
|
**/
|
|
librdf_stream*
|
|
librdf_storage_serialise(librdf_storage* storage)
|
|
{
|
|
return storage->factory->serialise(storage);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_find_statements:
|
|
* @storage: #librdf_storage object
|
|
* @statement: #librdf_statement partial statement to find
|
|
*
|
|
* Search the storage for matching statements.
|
|
*
|
|
* Searches the storage for a (partial) statement as described in
|
|
* librdf_statement_match() and returns a #librdf_stream of
|
|
* matching #librdf_statement objects.
|
|
*
|
|
* Return value: #librdf_stream of matching statements (may be empty) or NULL on failure
|
|
**/
|
|
librdf_stream*
|
|
librdf_storage_find_statements(librdf_storage* storage,
|
|
librdf_statement* statement)
|
|
{
|
|
librdf_node *subject, *predicate, *object;
|
|
librdf_iterator *iterator;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
|
|
|
|
subject=librdf_statement_get_subject(statement);
|
|
predicate=librdf_statement_get_predicate(statement);
|
|
object=librdf_statement_get_object(statement);
|
|
|
|
/* try to pick the most efficient storage back end */
|
|
|
|
/* only subject/source field blank -> use find_sources */
|
|
if(storage->factory->find_sources && !subject && predicate && object) {
|
|
iterator=storage->factory->find_sources(storage, predicate, object);
|
|
if(iterator)
|
|
return librdf_new_stream_from_node_iterator(iterator, statement,
|
|
LIBRDF_STATEMENT_SUBJECT);
|
|
return NULL;
|
|
}
|
|
|
|
/* only predicate/arc field blank -> use find_arcs */
|
|
if(storage->factory->find_arcs && subject && !predicate && object) {
|
|
iterator=storage->factory->find_arcs(storage, subject, object);
|
|
if(iterator)
|
|
return librdf_new_stream_from_node_iterator(iterator, statement,
|
|
LIBRDF_STATEMENT_PREDICATE);
|
|
return NULL;
|
|
}
|
|
|
|
/* only object/target field blank -> use find_targets */
|
|
if(storage->factory->find_targets && subject && predicate && !object) {
|
|
iterator=storage->factory->find_targets(storage, subject, predicate);
|
|
if(iterator)
|
|
return librdf_new_stream_from_node_iterator(iterator, statement,
|
|
LIBRDF_STATEMENT_OBJECT);
|
|
return NULL;
|
|
}
|
|
|
|
return storage->factory->find_statements(storage, statement);
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
librdf_storage *storage;
|
|
librdf_stream *stream;
|
|
librdf_statement *partial_statement;
|
|
librdf_statement_part want;
|
|
librdf_node *object_node;
|
|
librdf_node *context_node;
|
|
} librdf_storage_stream_to_node_iterator_context;
|
|
|
|
|
|
static int
|
|
librdf_storage_stream_to_node_iterator_is_end(void* iterator)
|
|
{
|
|
librdf_storage_stream_to_node_iterator_context* context=(librdf_storage_stream_to_node_iterator_context*)iterator;
|
|
|
|
return librdf_stream_end(context->stream);
|
|
}
|
|
|
|
|
|
static int
|
|
librdf_storage_stream_to_node_iterator_next_method(void* iterator)
|
|
{
|
|
librdf_storage_stream_to_node_iterator_context* context=(librdf_storage_stream_to_node_iterator_context*)iterator;
|
|
|
|
if(context->object_node) {
|
|
librdf_free_node(context->object_node);
|
|
context->object_node=NULL;
|
|
}
|
|
if(context->context_node) {
|
|
librdf_free_node(context->context_node);
|
|
context->context_node=NULL;
|
|
}
|
|
|
|
return librdf_stream_next(context->stream);
|
|
}
|
|
|
|
|
|
static void*
|
|
librdf_storage_stream_to_node_iterator_get_method(void* iterator, int flags)
|
|
{
|
|
librdf_storage_stream_to_node_iterator_context* context=(librdf_storage_stream_to_node_iterator_context*)iterator;
|
|
librdf_node* node;
|
|
librdf_statement* statement=librdf_stream_get_object(context->stream);
|
|
|
|
if(!statement)
|
|
return NULL;
|
|
|
|
switch(flags) {
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
|
|
|
|
if(!context->object_node) {
|
|
switch(context->want) {
|
|
case LIBRDF_STATEMENT_SUBJECT: /* SOURCES (subjects) */
|
|
node=librdf_statement_get_subject(statement);
|
|
break;
|
|
|
|
case LIBRDF_STATEMENT_PREDICATE: /* ARCS (predicates) */
|
|
node=librdf_statement_get_predicate(statement);
|
|
break;
|
|
|
|
case LIBRDF_STATEMENT_OBJECT: /* TARGETS (objects) */
|
|
node=librdf_statement_get_object(statement);
|
|
break;
|
|
|
|
case LIBRDF_STATEMENT_ALL:
|
|
default: /* error */
|
|
librdf_log(statement->world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
|
"Unknown statement part %d", context->want);
|
|
node=NULL;
|
|
}
|
|
context->object_node=librdf_new_node_from_node(node);
|
|
}
|
|
node=context->object_node;
|
|
break;
|
|
|
|
case LIBRDF_ITERATOR_GET_METHOD_GET_CONTEXT:
|
|
if(!context->context_node) {
|
|
node=(librdf_node*)librdf_stream_get_context(context->stream);
|
|
context->context_node=node ? librdf_new_node_from_node(node) : NULL;
|
|
}
|
|
node=context->context_node;
|
|
break;
|
|
|
|
default:
|
|
librdf_log(statement->world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
|
"Unknown iterator method flag %d", flags);
|
|
node=NULL;
|
|
}
|
|
|
|
return (void*)node;
|
|
}
|
|
|
|
|
|
static void
|
|
librdf_storage_stream_to_node_iterator_finished(void* iterator)
|
|
{
|
|
librdf_storage_stream_to_node_iterator_context* context=(librdf_storage_stream_to_node_iterator_context*)iterator;
|
|
librdf_statement *partial_statement=context->partial_statement;
|
|
|
|
if(partial_statement)
|
|
librdf_free_statement(partial_statement);
|
|
|
|
if(context->stream)
|
|
librdf_free_stream(context->stream);
|
|
|
|
if(context->storage)
|
|
librdf_storage_remove_reference(context->storage);
|
|
|
|
if(context->object_node)
|
|
librdf_free_node(context->object_node);
|
|
|
|
if(context->context_node)
|
|
librdf_free_node(context->context_node);
|
|
|
|
LIBRDF_FREE(librdf_storage_stream_to_node_iterator_context, context);
|
|
}
|
|
|
|
|
|
/*
|
|
* librdf_storage_node_stream_to_node_create - Create a stream for get sources, targets or arcs methods using find_statements method
|
|
* @storage: the storage object to use
|
|
* @node1: the first node to encode in the key (or NULL if not needed)
|
|
* @node2: the second node to encode in the key (or NULL if not needed)
|
|
* @want: the field required from the statement
|
|
*
|
|
* node1 and node2 cannot both be NULL
|
|
*
|
|
* Return value: a new #librdf_iterator or NULL on failure
|
|
**/
|
|
static librdf_iterator*
|
|
librdf_storage_node_stream_to_node_create(librdf_storage* storage,
|
|
librdf_node *node1,
|
|
librdf_node *node2,
|
|
librdf_statement_part want)
|
|
{
|
|
librdf_statement *partial_statement;
|
|
librdf_stream *stream;
|
|
librdf_storage_stream_to_node_iterator_context* context;
|
|
librdf_iterator* iterator;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_RETURN(node1 == NULL && node2 == NULL, "both node objects are NULL", NULL);
|
|
|
|
partial_statement=librdf_new_statement(storage->world);
|
|
if(!partial_statement)
|
|
return NULL;
|
|
|
|
context=(librdf_storage_stream_to_node_iterator_context*)LIBRDF_CALLOC(librdf_storage_stream_to_node_iterator_context, 1, sizeof(librdf_storage_stream_to_node_iterator_context));
|
|
if(!context) {
|
|
librdf_free_statement(partial_statement);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
if(node1)
|
|
node1=librdf_new_node_from_node(node1);
|
|
if(node2)
|
|
node2=librdf_new_node_from_node(node2);
|
|
|
|
switch(want) {
|
|
case LIBRDF_STATEMENT_SUBJECT:
|
|
librdf_statement_set_predicate(partial_statement, node1);
|
|
librdf_statement_set_object(partial_statement, node2);
|
|
break;
|
|
case LIBRDF_STATEMENT_PREDICATE:
|
|
librdf_statement_set_subject(partial_statement, node1);
|
|
librdf_statement_set_object(partial_statement, node2);
|
|
break;
|
|
case LIBRDF_STATEMENT_OBJECT:
|
|
librdf_statement_set_subject(partial_statement, node1);
|
|
librdf_statement_set_predicate(partial_statement, node2);
|
|
break;
|
|
|
|
case LIBRDF_STATEMENT_ALL:
|
|
default:
|
|
librdf_free_node(node1);
|
|
librdf_free_node(node2);
|
|
librdf_free_statement(partial_statement);
|
|
librdf_log(storage->world,
|
|
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
|
"Illegal statement part %d seen", want);
|
|
return NULL;
|
|
}
|
|
|
|
stream=storage->factory->find_statements(storage, partial_statement);
|
|
if(!stream) {
|
|
librdf_storage_stream_to_node_iterator_finished(context);
|
|
return librdf_new_empty_iterator(storage->world);
|
|
}
|
|
|
|
/* initialise context */
|
|
context->partial_statement=partial_statement;
|
|
context->stream=stream;
|
|
context->want=want;
|
|
|
|
context->storage=storage;
|
|
librdf_storage_add_reference(context->storage);
|
|
|
|
iterator=librdf_new_iterator(storage->world,
|
|
(void*)context,
|
|
librdf_storage_stream_to_node_iterator_is_end,
|
|
librdf_storage_stream_to_node_iterator_next_method,
|
|
librdf_storage_stream_to_node_iterator_get_method,
|
|
librdf_storage_stream_to_node_iterator_finished);
|
|
if(!iterator)
|
|
librdf_storage_stream_to_node_iterator_finished(context);
|
|
return iterator;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_get_sources:
|
|
* @storage: #librdf_storage object
|
|
* @arc: #librdf_node arc
|
|
* @target: #librdf_node target
|
|
*
|
|
* Return the sources (subjects) of arc in an RDF graph given arc (predicate) and target (object).
|
|
*
|
|
* Searches the storage for arcs matching the given arc and target
|
|
* and returns a list of the source #librdf_node objects as an iterator
|
|
*
|
|
* Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
|
|
**/
|
|
librdf_iterator*
|
|
librdf_storage_get_sources(librdf_storage *storage,
|
|
librdf_node *arc, librdf_node *target)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(arc, librdf_node, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(target, librdf_node, NULL);
|
|
|
|
if (storage->factory->find_sources)
|
|
return storage->factory->find_sources(storage, arc, target);
|
|
|
|
return librdf_storage_node_stream_to_node_create(storage, arc, target,
|
|
LIBRDF_STATEMENT_SUBJECT);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_get_arcs:
|
|
* @storage: #librdf_storage object
|
|
* @source: #librdf_node source
|
|
* @target: #librdf_node target
|
|
*
|
|
* Return the arcs (predicates) of an arc in an RDF graph given source (subject) and target (object).
|
|
*
|
|
* Searches the storage for arcs matching the given source and target
|
|
* and returns a list of the arc #librdf_node objects as an iterator
|
|
*
|
|
* Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
|
|
**/
|
|
librdf_iterator*
|
|
librdf_storage_get_arcs(librdf_storage *storage,
|
|
librdf_node *source, librdf_node *target)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(source, librdf_node, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(target, librdf_node, NULL);
|
|
|
|
if (storage->factory->find_arcs)
|
|
return storage->factory->find_arcs(storage, source, target);
|
|
|
|
return librdf_storage_node_stream_to_node_create(storage, source, target,
|
|
LIBRDF_STATEMENT_PREDICATE);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_get_targets:
|
|
* @storage: #librdf_storage object
|
|
* @source: #librdf_node source
|
|
* @arc: #librdf_node arc
|
|
*
|
|
* Return the targets (objects) of an arc in an RDF graph given source (subject) and arc (predicate).
|
|
*
|
|
* Searches the storage for targets matching the given source and arc
|
|
* and returns a list of the source #librdf_node objects as an iterator
|
|
*
|
|
* Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
|
|
**/
|
|
librdf_iterator*
|
|
librdf_storage_get_targets(librdf_storage *storage,
|
|
librdf_node *source, librdf_node *arc)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(source, librdf_node, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(arc, librdf_node, NULL);
|
|
|
|
if (storage->factory->find_targets)
|
|
return storage->factory->find_targets(storage, source, arc);
|
|
|
|
return librdf_storage_node_stream_to_node_create(storage, source, arc,
|
|
LIBRDF_STATEMENT_OBJECT);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_get_arcs_in:
|
|
* @storage: #librdf_storage object
|
|
* @node: #librdf_node resource node
|
|
*
|
|
* Return the properties pointing to the given resource.
|
|
*
|
|
* Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
|
|
**/
|
|
librdf_iterator*
|
|
librdf_storage_get_arcs_in(librdf_storage *storage, librdf_node *node)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, NULL);
|
|
|
|
if (storage->factory->get_arcs_in)
|
|
return storage->factory->get_arcs_in(storage, node);
|
|
|
|
return librdf_storage_node_stream_to_node_create(storage, NULL, node,
|
|
LIBRDF_STATEMENT_PREDICATE);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_get_arcs_out:
|
|
* @storage: #librdf_storage object
|
|
* @node: #librdf_node resource node
|
|
*
|
|
* Return the properties pointing from the given resource.
|
|
*
|
|
* Return value: #librdf_iterator of #librdf_node objects (may be empty) or NULL on failure
|
|
**/
|
|
librdf_iterator*
|
|
librdf_storage_get_arcs_out(librdf_storage *storage, librdf_node *node)
|
|
{
|
|
if (storage->factory->get_arcs_out)
|
|
return storage->factory->get_arcs_out(storage, node);
|
|
return librdf_storage_node_stream_to_node_create(storage, node, NULL,
|
|
LIBRDF_STATEMENT_PREDICATE);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_has_arc_in:
|
|
* @storage: #librdf_storage object
|
|
* @node: #librdf_node resource node
|
|
* @property: #librdf_node property node
|
|
*
|
|
* Check if a node has a given property pointing to it.
|
|
*
|
|
* Return value: non 0 if arc property does point to the resource node
|
|
**/
|
|
int
|
|
librdf_storage_has_arc_in(librdf_storage *storage, librdf_node *node,
|
|
librdf_node *property)
|
|
{
|
|
librdf_iterator *iterator;
|
|
int status;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 0);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(property, librdf_node, 0);
|
|
|
|
if (storage->factory->has_arc_in)
|
|
return storage->factory->has_arc_in(storage, node, property);
|
|
|
|
iterator=librdf_storage_get_sources(storage, property, node);
|
|
if(!iterator)
|
|
return 0;
|
|
|
|
/* a non-empty list of sources is success */
|
|
status=!librdf_iterator_end(iterator);
|
|
librdf_free_iterator(iterator);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_has_arc_out:
|
|
* @storage: #librdf_storage object
|
|
* @node: #librdf_node resource node
|
|
* @property: #librdf_node property node
|
|
*
|
|
* Check if a node has a given property pointing from it.
|
|
*
|
|
* Return value: non 0 if arc property does point from the resource node
|
|
**/
|
|
int
|
|
librdf_storage_has_arc_out(librdf_storage *storage, librdf_node *node,
|
|
librdf_node *property)
|
|
{
|
|
librdf_iterator *iterator;
|
|
int status;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 0);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(node, librdf_node, 0);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(property, librdf_node, 0);
|
|
|
|
if (storage->factory->has_arc_out)
|
|
return storage->factory->has_arc_out(storage, node, property);
|
|
|
|
iterator=librdf_storage_get_targets(storage, node, property);
|
|
if(!iterator)
|
|
return 0;
|
|
|
|
/* a non-empty list of targets is success */
|
|
status=!librdf_iterator_end(iterator);
|
|
librdf_free_iterator(iterator);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* librdf_storage_context_add_statement:
|
|
* @storage: #librdf_storage object
|
|
* @context: #librdf_node context node
|
|
* @statement: #librdf_statement statement to add
|
|
*
|
|
* Add a statement to a storage in a context.
|
|
*
|
|
* If @context is NULL, this is equivalent to librdf_storage_add_statement
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_context_add_statement(librdf_storage* storage,
|
|
librdf_node* context,
|
|
librdf_statement* statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, 1);
|
|
|
|
if(!context)
|
|
return librdf_storage_add_statement(storage, statement);
|
|
|
|
if(storage->factory->context_add_statement)
|
|
return storage->factory->context_add_statement(storage, context, statement);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_context_add_statements:
|
|
* @storage: #librdf_storage object
|
|
* @context: #librdf_node context
|
|
* @stream: #librdf_stream stream object
|
|
*
|
|
* Add statements to a storage with a context.
|
|
*
|
|
* If @context is NULL, this is equivalent to librdf_storage_add_statements
|
|
*
|
|
* Return value: Non 0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_context_add_statements(librdf_storage* storage,
|
|
librdf_node* context,
|
|
librdf_stream* stream)
|
|
{
|
|
int status=0;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(stream, librdf_stream, 1);
|
|
|
|
if(!context)
|
|
return librdf_storage_add_statements(storage, stream);
|
|
|
|
if(storage->factory->context_add_statements)
|
|
return storage->factory->context_add_statements(storage, context, stream);
|
|
|
|
if(!storage->factory->context_add_statement)
|
|
return 1;
|
|
|
|
if(!stream)
|
|
return 1;
|
|
|
|
while(!librdf_stream_end(stream)) {
|
|
librdf_statement* statement=librdf_stream_get_object(stream);
|
|
if(!statement)
|
|
break;
|
|
status=librdf_storage_context_add_statement(storage, context, statement);
|
|
if(status)
|
|
break;
|
|
librdf_stream_next(stream);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* librdf_storage_context_remove_statement:
|
|
* @storage: #librdf_storage object
|
|
* @context: #librdf_node context node
|
|
* @statement: #librdf_statement statement to remove
|
|
*
|
|
* Remove a statement from a storage in a context.
|
|
*
|
|
* If @context is NULL, this is equivalent to librdf_storage_remove_statement
|
|
*
|
|
* Return value: non 0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_context_remove_statement(librdf_storage* storage,
|
|
librdf_node* context,
|
|
librdf_statement* statement)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(context, librdf_statement, 1);
|
|
|
|
if(!storage->factory->context_remove_statement)
|
|
return 1;
|
|
|
|
return storage->factory->context_remove_statement(storage, context, statement);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_context_remove_statements:
|
|
* @storage: #librdf_storage object
|
|
* @context: #librdf_uri context
|
|
*
|
|
* Remove statements from a storage with the given context.
|
|
*
|
|
* Return value: Non 0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_context_remove_statements(librdf_storage* storage,
|
|
librdf_node* context)
|
|
{
|
|
librdf_stream *stream;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
|
|
if(storage->factory->context_remove_statements)
|
|
return storage->factory->context_remove_statements(storage, context);
|
|
|
|
if(!storage->factory->context_remove_statement)
|
|
return 1;
|
|
|
|
stream=librdf_storage_context_as_stream(storage, context);
|
|
if(!stream)
|
|
return 1;
|
|
|
|
while(!librdf_stream_end(stream)) {
|
|
librdf_statement *statement=librdf_stream_get_object(stream);
|
|
if(!statement)
|
|
break;
|
|
librdf_storage_context_remove_statement(storage, context, statement);
|
|
librdf_stream_next(stream);
|
|
}
|
|
librdf_free_stream(stream);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_context_as_stream:
|
|
* @storage: #librdf_storage object
|
|
* @context: #librdf_node context node
|
|
*
|
|
* List all statements in a storage context.
|
|
*
|
|
* Return value: #librdf_stream of statements or NULL on failure or context is empty
|
|
**/
|
|
librdf_stream*
|
|
librdf_storage_context_as_stream(librdf_storage* storage, librdf_node* context)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
|
|
return storage->factory->context_serialise(storage, context);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_context_serialise:
|
|
* @storage: #librdf_storage object
|
|
* @context: #librdf_node context node
|
|
*
|
|
* List all statements in a storage context (DEPRECATED).
|
|
*
|
|
* DEPRECATED to reduce confusion with the librdf_serializer class.
|
|
* Please use librdf_storage_context_as_stream.
|
|
*
|
|
* Return value: #librdf_stream of statements or NULL on failure or context is empty
|
|
**/
|
|
librdf_stream*
|
|
librdf_storage_context_serialise(librdf_storage* storage,
|
|
librdf_node* context)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
|
|
return librdf_storage_context_as_stream(storage, context);
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_supports_query:
|
|
* @storage: #librdf_storage object
|
|
* @query: #librdf_query query object
|
|
*
|
|
* Check if a storage system supports a query language.
|
|
*
|
|
* Not implemented.
|
|
*
|
|
* Return value: non-0 if the query is supported.
|
|
**/
|
|
int
|
|
librdf_storage_supports_query(librdf_storage* storage, librdf_query *query)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 0);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(query, librdf_query, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_query_execute:
|
|
* @storage: #librdf_storage object
|
|
* @query: #librdf_query query object
|
|
*
|
|
* Run the given query against the storage.
|
|
*
|
|
* Not implemented.
|
|
*
|
|
* Return value: #librdf_query_results or NULL on failure
|
|
**/
|
|
librdf_query_results*
|
|
librdf_storage_query_execute(librdf_storage* storage, librdf_query *query)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(query, librdf_query, NULL);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_sync:
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* Synchronise the storage to the storage implementation.
|
|
*
|
|
* Return value: non-0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_sync(librdf_storage* storage)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, 1);
|
|
|
|
if(storage->factory->sync)
|
|
return storage->factory->sync(storage);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_find_statements_in_context:
|
|
* @storage: #librdf_storage object
|
|
* @statement: #librdf_statement partial statement to find
|
|
* @context_node: context #librdf_node (or NULL)
|
|
*
|
|
* Search the storage for matching statements in a given context.
|
|
*
|
|
* Searches the storage for a (partial) statement as described in
|
|
* librdf_statement_match() in the given context and returns a
|
|
* #librdf_stream of matching #librdf_statement objects. If
|
|
* context is NULL, this is equivalent to librdf_storage_find_statements.
|
|
*
|
|
* Return value: #librdf_stream of matching statements (may be empty) or NULL on failure
|
|
**/
|
|
librdf_stream*
|
|
librdf_storage_find_statements_in_context(librdf_storage* storage, librdf_statement* statement, librdf_node* context_node)
|
|
{
|
|
librdf_stream *stream;
|
|
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(statement, librdf_statement, NULL);
|
|
|
|
if(storage->factory->find_statements_in_context)
|
|
return storage->factory->find_statements_in_context(storage, statement, context_node);
|
|
|
|
statement=librdf_new_statement_from_statement(statement);
|
|
if(!statement)
|
|
return NULL;
|
|
|
|
stream=librdf_storage_context_as_stream(storage, context_node);
|
|
if(!stream) {
|
|
librdf_free_statement(statement);
|
|
return NULL;
|
|
}
|
|
|
|
librdf_stream_add_map(stream,
|
|
&librdf_stream_statement_find_map,
|
|
(librdf_stream_map_free_context_handler)&librdf_free_statement, (void*)statement);
|
|
|
|
return stream;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_get_contexts:
|
|
* @storage: #librdf_storage object
|
|
*
|
|
* Return the list of contexts in the store.
|
|
*
|
|
* Returns an iterator of #librdf_node context nodes for each
|
|
* context in the store.
|
|
*
|
|
* Return value: #librdf_iterator of context nodes or NULL on failure or if contexts are not supported
|
|
**/
|
|
librdf_iterator*
|
|
librdf_storage_get_contexts(librdf_storage* storage)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
|
|
if(storage->factory->get_contexts)
|
|
return storage->factory->get_contexts(storage);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* librdf_storage_get_feature:
|
|
* @storage: #librdf_storage object
|
|
* @feature: #librdf_uri feature property
|
|
*
|
|
* Get the value of a storage feature.
|
|
*
|
|
* Return value: new #librdf_node feature value or NULL if no such feature
|
|
* exists or the value is empty.
|
|
**/
|
|
librdf_node*
|
|
librdf_storage_get_feature(librdf_storage* storage, librdf_uri* feature)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, NULL);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(feature, librdf_uri, NULL);
|
|
|
|
if(storage->factory->get_feature)
|
|
return storage->factory->get_feature(storage, feature);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_set_feature:
|
|
* @storage: #librdf_storage object
|
|
* @feature: #librdf_uri feature property
|
|
* @value: #librdf_node feature property value
|
|
*
|
|
* Set the value of a storage feature.
|
|
*
|
|
* Return value: non 0 on failure (negative if no such feature)
|
|
**/
|
|
int
|
|
librdf_storage_set_feature(librdf_storage* storage, librdf_uri* feature,
|
|
librdf_node* value)
|
|
{
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(storage, librdf_storage, -1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(feature, librdf_uri, -1);
|
|
LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(value, librdf_node, -1);
|
|
|
|
if(storage->factory->set_feature)
|
|
return storage->factory->set_feature(storage, feature, value);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_find_statements_with_options:
|
|
* @storage: #librdf_storage object
|
|
* @statement: #librdf_statement partial statement to find
|
|
* @context_node: #librdf_node context node or NULL.
|
|
* @options: #librdf_hash of matching options or NULL
|
|
*
|
|
* Search the storage for matching statements with match options.
|
|
*
|
|
* Searches the storage for a (partial) statement as described in
|
|
* librdf_statement_match() and returns a #librdf_stream of
|
|
* matching #librdf_statement objects.
|
|
*
|
|
* If options is given then the match is made according to
|
|
* the given options. If options is NULL, this is equivalent
|
|
* to librdf_storage_find_statements_in_context.
|
|
*
|
|
* Return value: #librdf_stream of matching statements (may be empty) or NULL on failure
|
|
**/
|
|
librdf_stream*
|
|
librdf_storage_find_statements_with_options(librdf_storage* storage,
|
|
librdf_statement* statement,
|
|
librdf_node* context_node,
|
|
librdf_hash* options)
|
|
{
|
|
if(storage->factory->find_statements_with_options)
|
|
return storage->factory->find_statements_with_options(storage, statement, context_node, options);
|
|
else
|
|
return librdf_storage_find_statements_in_context(storage, statement, context_node);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* librdf_storage_transaction_start:
|
|
* @storage: the storage object
|
|
*
|
|
* Start a transaction
|
|
*
|
|
* Return value: non-0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_transaction_start(librdf_storage* storage)
|
|
{
|
|
if(storage->factory->transaction_start)
|
|
return storage->factory->transaction_start(storage);
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_transaction_start_with_handle:
|
|
* @storage: the storage object
|
|
* @handle: the transaction object
|
|
*
|
|
* Start a transaction using an existing external transaction object.
|
|
*
|
|
* Return value: non-0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_transaction_start_with_handle(librdf_storage* storage, void* handle)
|
|
{
|
|
if(storage->factory->transaction_start_with_handle)
|
|
return storage->factory->transaction_start_with_handle(storage, handle);
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_transaction_commit:
|
|
* @storage: the storage object
|
|
*
|
|
* Commit a transaction.
|
|
*
|
|
* Return value: non-0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_transaction_commit(librdf_storage* storage)
|
|
{
|
|
if(storage->factory->transaction_commit)
|
|
return storage->factory->transaction_commit(storage);
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_transaction_rollback:
|
|
* @storage: the storage object
|
|
*
|
|
* Rollback a transaction.
|
|
*
|
|
* Return value: non-0 on failure
|
|
**/
|
|
int
|
|
librdf_storage_transaction_rollback(librdf_storage* storage)
|
|
{
|
|
if(storage->factory->transaction_rollback)
|
|
return storage->factory->transaction_rollback(storage);
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* librdf_storage_transaction_get_handle:
|
|
* @storage: the storage object
|
|
*
|
|
* Get the current transaction handle.
|
|
*
|
|
* Return value: non-0 on failure
|
|
**/
|
|
void*
|
|
librdf_storage_transaction_get_handle(librdf_storage* storage)
|
|
{
|
|
if(storage->factory->transaction_get_handle)
|
|
return storage->factory->transaction_get_handle(storage);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
/* TEST CODE */
|
|
|
|
|
|
#ifdef STANDALONE
|
|
|
|
/* one more prototype */
|
|
int main(int argc, char *argv[]);
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
librdf_storage* storage;
|
|
const char *program=librdf_basename((const char*)argv[0]);
|
|
librdf_world *world;
|
|
|
|
/* triples of arguments to librdf_new_storage */
|
|
const char* const storages[] = {
|
|
"memory", NULL, "contexts='yes'",
|
|
"hashes", "test", "hash-type='bdb',dir='.',write='yes',new='yes',contexts='yes'",
|
|
#ifdef STORAGE_TREES
|
|
"trees", "test", "contexts='yes'",
|
|
#endif
|
|
#ifdef STORAGE_FILE
|
|
"file", "file://../redland.rdf", NULL,
|
|
"uri", "http://librdf.org/redland.rdf", NULL,
|
|
#endif
|
|
#ifdef STORAGE_MYSQL
|
|
"mysql", "test", "host='localhost',database='test'",
|
|
#endif
|
|
#ifdef STORAGE_POSTGRESQL
|
|
"postgresql", "test", "host='localhost',database='test'",
|
|
#endif
|
|
#ifdef STORAGE_TSTORE
|
|
"tstore", "test", "host='localhost',database='test'",
|
|
#endif
|
|
#ifdef STORAGE_SQLITE
|
|
"sqlite", "test", "new='yes'",
|
|
#endif
|
|
NULL, NULL, NULL
|
|
};
|
|
|
|
int test = 0;
|
|
int ret = 0;
|
|
|
|
world=librdf_new_world();
|
|
librdf_world_open(world);
|
|
|
|
for ( ; storages[test] != NULL; test += 3) {
|
|
|
|
fprintf(stdout, "%s: Creating storage %s\n", program, storages[test]);
|
|
storage=librdf_new_storage(world,
|
|
storages[test], /* type */
|
|
storages[test+1], /* name */
|
|
storages[test+2]); /* options */
|
|
if(!storage) {
|
|
fprintf(stderr, "%s: WARNING: Failed to create new storage %s\n",
|
|
program, storages[test]);
|
|
continue;
|
|
}
|
|
|
|
|
|
fprintf(stdout, "%s: Opening storage\n", program);
|
|
if(librdf_storage_open(storage, NULL)) {
|
|
fprintf(stderr, "%s: Failed to open storage type %s\n",
|
|
program, storages[test]);
|
|
ret++;
|
|
continue;
|
|
}
|
|
|
|
|
|
/* Can do nothing here since need model and storage working */
|
|
|
|
fprintf(stdout, "%s: Closing storage\n", program);
|
|
librdf_storage_close(storage);
|
|
|
|
fprintf(stdout, "%s: Freeing storage\n", program);
|
|
librdf_free_storage(storage);
|
|
|
|
}
|
|
|
|
|
|
librdf_free_world(world);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif
|