so, it seems that librdf_storage_FOO_context_add_statement functions do
not check for duplicates; methinks they should.
how about the following patch for "memory" and "hashes" storages?
(currently i don't care about others; maybe someone else wants to fix
those, or check if they actually don't have the same problem?)
also, attached a test case to reproduce the problem.
michael
--
"The use of four-letter words like goto can occasionally be justified
even in the best of company." -- Donald E. Knuth
diff -ru redland-1.0.7/librdf/rdf_storage_hashes.c redland-1.0.7-contextdup/librdf/rdf_storage_hashes.c
--- redland-1.0.7/librdf/rdf_storage_hashes.c Thu Dec 20 22:39:42 2007
+++ redland-1.0.7-contextdup/librdf/rdf_storage_hashes.c Mon Apr 28 13:13:18 2008
@@ -1389,6 +1389,66 @@
LIBRDF_STATEMENT_OBJECT);
}
+
+/* return -1 on failure, 1 if context contains stmt, 0 if not */
+static int
+librdf_storage_hashes_context_contains_statement(librdf_storage* storage,
+ librdf_node* context_node,
+ librdf_statement* statement)
+{
+ librdf_storage_hashes_context* context=(librdf_storage_hashes_context*)storage->context;
+ librdf_hash_datum key, value; /* on stack - not allocated */
+ size_t size;
+ int status;
+
+ if(context->contexts_index < 0) {
+ librdf_log(storage->world, 0, LIBRDF_LOG_WARN, LIBRDF_FROM_STORAGE, NULL,
+ "Storage was created without context support");
+ return -1;
+ }
+
+ /* ENCODE KEY */
+ size=librdf_node_encode(context_node, NULL, 0);
+ if (!size)
+ return -1;
+ key.data=(char*)LIBRDF_MALLOC(cstring, size);
+ if (!key.data)
+ return -1;
+ key.size=librdf_node_encode(context_node,
+ (unsigned char*)key.data, size);
+ if (!key.size) {
+ LIBRDF_FREE(data, key.data);
+ return -1;
+ }
+
+ /* ENCODE VALUE */
+ size=librdf_statement_encode(statement, NULL, 0);
+ if (!size) {
+ LIBRDF_FREE(data, key.data);
+ return -1;
+ }
+ value.data=(char*)LIBRDF_MALLOC(cstring, size);
+ if (!value.data) {
+ LIBRDF_FREE(data, key.data);
+ return -1;
+ }
+ value.size=librdf_statement_encode(statement, (unsigned char*)value.data, size);
+ if (!value.size) {
+ LIBRDF_FREE(data, value.data);
+ LIBRDF_FREE(data, key.data);
+ return -1;
+ }
+
+ status=librdf_hash_exists(context->hashes[context->contexts_index], &key, &value);
+ LIBRDF_FREE(data, value.data);
+ LIBRDF_FREE(data, key.data);
+
+ /* DO NOT free statement, ownership was not passed in */
+ return status;
+}
+
+
+
/**
* librdf_storage_hashes_context_add_statement:
* @storage: #librdf_storage object
@@ -1414,7 +1474,15 @@
"Storage was created without context support");
return 1;
}
-
+
+ /* Do not add duplicate statements */
+ status=librdf_storage_hashes_context_contains_statement(storage, context_node, statement);
+ if(status)
+ if(status < 0)
+ return 1;
+ else
+ return 0;
+
if(librdf_storage_hashes_add_remove_statement(storage,
statement, context_node, 1))
return 1;
diff -ru redland-1.0.7/librdf/rdf_storage_list.c redland-1.0.7-contextdup/librdf/rdf_storage_list.c
--- redland-1.0.7/librdf/rdf_storage_list.c Thu Dec 20 22:39:42 2007
+++ redland-1.0.7-contextdup/librdf/rdf_storage_list.c Mon Apr 28 13:13:10 2008
@@ -459,6 +459,64 @@
}
+/* return -1 on failure, 1 if context contains stmt, 0 if not */
+static int
+librdf_storage_list_context_contains_statement(librdf_storage* storage,
+ librdf_node* context_node,
+ librdf_statement* statement)
+{
+ librdf_storage_list_context* context=(librdf_storage_list_context*)storage->context;
+ librdf_hash_datum key, value; /* on stack - not allocated */
+ size_t size;
+ int status;
+
+ if(!context->index_contexts) {
+ librdf_log(storage->world, 0, LIBRDF_LOG_WARN, LIBRDF_FROM_STORAGE, NULL,
+ "Storage was created without context support");
+ return -1;
+ }
+
+ /* ENCODE KEY */
+ size=librdf_node_encode(context_node, NULL, 0);
+ if (!size)
+ return -1;
+ key.data=(char*)LIBRDF_MALLOC(cstring, size);
+ if (!key.data)
+ return -1;
+ key.size=librdf_node_encode(context_node,
+ (unsigned char*)key.data, size);
+ if (!key.size) {
+ LIBRDF_FREE(data, key.data);
+ return -1;
+ }
+
+ /* ENCODE VALUE */
+ size=librdf_statement_encode(statement, NULL, 0);
+ if (!size) {
+ LIBRDF_FREE(data, key.data);
+ return -1;
+ }
+ value.data=(char*)LIBRDF_MALLOC(cstring, size);
+ if (!value.data) {
+ LIBRDF_FREE(data, key.data);
+ return -1;
+ }
+ value.size=librdf_statement_encode(statement, (unsigned char*)value.data, size);
+ if (!value.size) {
+ LIBRDF_FREE(data, value.data);
+ LIBRDF_FREE(data, key.data);
+ return -1;
+ }
+
+ status=librdf_hash_exists(context->contexts, &key, &value);
+ LIBRDF_FREE(data, value.data);
+ LIBRDF_FREE(data, key.data);
+
+ /* DO NOT free statement, ownership was not passed in */
+ return status;
+}
+
+
/**
* librdf_storage_list_context_add_statement:
* @storage: #librdf_storage object
@@ -485,7 +543,15 @@
"Storage was created without context support");
return 1;
}
-
+
+ /* Do not add duplicate statements */
+ status=librdf_storage_list_context_contains_statement(storage, context_node, statement);
+ if(status)
+ if(status < 0)
+ return 1;
+ else
+ return 0;
+
/* Store statement + node in the storage_list */
sln=(librdf_storage_list_node*)LIBRDF_MALLOC(librdf_storage_list_node, sizeof(librdf_storage_list_node));
if(!sln)
#include <librdf.h>
int main()
{
librdf_world *pWorld = librdf_new_world();
librdf_world_open(pWorld);
librdf_storage *pStorage = librdf_new_storage(pWorld,
// "memory", NULL, "contexts='yes'");
"hashes", NULL, "contexts='yes',hash-type='memory'");
librdf_model *pModel = librdf_new_model(pWorld, pStorage, NULL);
librdf_node *pContext = librdf_new_node_from_uri_string(pWorld,
(const unsigned char*) ("uri:context"));
librdf_node *pFoo = librdf_new_node_from_uri_string(pWorld,
(const unsigned char*) ("uri:foo"));
librdf_node *pBar = librdf_new_node_from_uri_string(pWorld,
(const unsigned char*) ("uri:bar"));
librdf_node *pBaz = librdf_new_node_from_uri_string(pWorld,
(const unsigned char*) ("uri:baz"));
librdf_statement *pStatement =
librdf_new_statement_from_nodes(pWorld, pFoo, pBar, pBaz);
librdf_model_context_add_statement(pModel, pContext, pStatement);
librdf_model_context_add_statement(pModel, pContext, pStatement);
librdf_model_context_add_statement(pModel, pContext, pStatement);
librdf_stream *pStream = librdf_model_context_as_stream(pModel, pContext);
librdf_serializer *pSerializer =
librdf_new_serializer(pWorld, "rdfxml", NULL, NULL);
librdf_serializer_serialize_stream_to_file_handle(pSerializer,
stdout, NULL, pStream);
return 0;
}
_______________________________________________
redland-dev mailing list
[email protected]
http://lists.librdf.org/mailman/listinfo/redland-dev