[tracker/IorR-null-support] libtracker-data: Experimental commit, insert or replace null support
- From: Philip Van Hoof <pvanhoof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/IorR-null-support] libtracker-data: Experimental commit, insert or replace null support
- Date: Tue, 9 Aug 2011 13:29:00 +0000 (UTC)
commit ea00af9ece5e09c6cb312ef683694605f1283604
Author: Philip Van Hoof <philip codeminded be>
Date: Fri Jul 29 16:36:55 2011 +0200
libtracker-data: Experimental commit, insert or replace null support
For deleting a resource-property's objects during insert or replace
using null
src/libtracker-data/libtracker-data.vapi | 2 +-
src/libtracker-data/tracker-data-update.c | 137 ++++++++++++++++++++++-
src/libtracker-data/tracker-data-update.h | 1 +
src/libtracker-data/tracker-sparql-query.vala | 26 ++++-
src/libtracker-data/tracker-sparql-scanner.vala | 5 +
5 files changed, 160 insertions(+), 11 deletions(-)
---
diff --git a/src/libtracker-data/libtracker-data.vapi b/src/libtracker-data/libtracker-data.vapi
index 491cf9e..acec2eb 100644
--- a/src/libtracker-data/libtracker-data.vapi
+++ b/src/libtracker-data/libtracker-data.vapi
@@ -200,7 +200,7 @@ namespace Tracker {
public void load_turtle_file (GLib.File file) throws Sparql.Error;
public void notify_transaction (CommitType commit_type);
public void delete_statement (string? graph, string subject, string predicate, string object) throws Sparql.Error, DateError;
- public void update_statement (string? graph, string subject, string predicate, string object) throws Sparql.Error, DateError;
+ public void update_statement (string? graph, string subject, string predicate, string object, bool object_is_null) throws Sparql.Error, DateError;
public void insert_statement (string? graph, string subject, string predicate, string object) throws Sparql.Error, DateError;
public void insert_statement_with_uri (string? graph, string subject, string predicate, string object) throws Sparql.Error;
public void insert_statement_with_string (string? graph, string subject, string predicate, string object) throws Sparql.Error, DateError;
diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c
index dbf1043..3e6bd70 100644
--- a/src/libtracker-data/tracker-data-update.c
+++ b/src/libtracker-data/tracker-data-update.c
@@ -2247,6 +2247,130 @@ tracker_data_delete_statement (const gchar *graph,
}
}
+static void
+delete_all_objects (const gchar *graph,
+ const gchar *subject,
+ const gchar *predicate,
+ GError **error)
+{
+ gint subject_id = 0;
+ gboolean change = FALSE;
+ guint i;
+ GError *new_error = NULL;
+ TrackerProperty *field;
+
+ g_return_if_fail (subject != NULL);
+ g_return_if_fail (predicate != NULL);
+ g_return_if_fail (in_transaction);
+
+ subject_id = query_resource_id (subject);
+
+ if (subject_id == 0) {
+ /* subject not in database */
+ return;
+ }
+
+ resource_buffer_switch (graph, 0, subject, subject_id);
+
+ field = tracker_ontologies_get_property_by_uri (predicate);
+ if (field != NULL) {
+ GValueArray *old_values;
+
+ if (!tracker_property_get_transient (field)) {
+ has_persistent = TRUE;
+ }
+
+ old_values = get_old_property_values (field, &new_error);
+ if (new_error) {
+ g_propagate_error (error, new_error);
+ return;
+ }
+
+ for (i = 0; i < old_values->n_values; i++) {
+ gint pred_id = 0, graph_id = 0;
+ gboolean tried = FALSE;
+ const gchar *object = NULL;
+ gint object_id = 0;
+
+ if (tracker_property_get_data_type (field) == TRACKER_PROPERTY_TYPE_RESOURCE) {
+
+ graph_id = (graph != NULL ? query_resource_id (graph) : 0);
+ pred_id = tracker_property_get_id (field);
+ object_id = (gint) g_value_get_int64 (g_value_array_get_nth (old_values, i));
+ tried = TRUE;
+
+ change = delete_metadata_decomposed (field, NULL, object_id, error);
+
+#ifndef DISABLE_JOURNAL
+ if (!in_journal_replay && change && !tracker_property_get_transient (field)) {
+ tracker_db_journal_append_delete_statement_id (graph_id,
+ resource_buffer->id,
+ pred_id,
+ object_id);
+ }
+#endif /* DISABLE_JOURNAL */
+ } else {
+ object = g_value_get_string (g_value_array_get_nth (old_values, i));
+ pred_id = tracker_property_get_id (field);
+ graph_id = (graph != NULL ? query_resource_id (graph) : 0);
+ object_id = 0;
+ tried = TRUE;
+
+ change = delete_metadata_decomposed (field, object, 0, error);
+
+#ifndef DISABLE_JOURNAL
+ if (!in_journal_replay && change && !tracker_property_get_transient (field)) {
+ if (!tracker_property_get_force_journal (field) &&
+ g_strcmp0 (graph, TRACKER_MINER_FS_GRAPH_URN) == 0) {
+ /* do not journal this statement extracted from filesystem */
+ TrackerProperty *damaged;
+
+ damaged = tracker_ontologies_get_property_by_uri (TRACKER_TRACKER_PREFIX "damaged");
+
+ tracker_db_journal_append_insert_statement (graph_id,
+ resource_buffer->id,
+ tracker_property_get_id (damaged),
+ "true");
+ } else {
+ tracker_db_journal_append_delete_statement (graph_id,
+ resource_buffer->id,
+ pred_id,
+ object);
+ }
+ }
+#endif /* DISABLE_JOURNAL */
+
+ if (!tried) {
+ graph_id = (graph != NULL ? query_resource_id (graph) : 0);
+ if (field == NULL) {
+ pred_id = tracker_data_query_resource_id (predicate);
+ } else {
+ pred_id = tracker_property_get_id (field);
+ }
+ }
+
+ if (delete_callbacks && change) {
+ guint n;
+ for (n = 0; n < delete_callbacks->len; n++) {
+ TrackerStatementDelegate *delegate;
+
+ delegate = g_ptr_array_index (delete_callbacks, n);
+ delegate->callback (graph_id, graph, subject_id, subject,
+ pred_id, object_id,
+ object,
+ resource_buffer->types,
+ delegate->user_data);
+ }
+ }
+ }
+ }
+ } else {
+ /* I wonder why in case of error the delete_callbacks are still executed */
+ g_set_error (error, TRACKER_SPARQL_ERROR, TRACKER_SPARQL_ERROR_UNKNOWN_PROPERTY,
+ "Property '%s' not found in the ontology", predicate);
+ }
+}
+
static gboolean
tracker_data_insert_statement_common (const gchar *graph,
const gchar *subject,
@@ -2352,7 +2476,7 @@ handle_blank_node (const gchar *subject,
if (blank_uri != NULL) {
/* now insert statement referring to blank node */
- tracker_data_update_statement (graph, subject, predicate, blank_uri, &actual_error);
+ tracker_data_update_statement (graph, subject, predicate, blank_uri, FALSE, &actual_error);
g_hash_table_remove (blank_buffer.table, object);
@@ -2937,6 +3061,7 @@ tracker_data_update_statement (const gchar *graph,
const gchar *subject,
const gchar *predicate,
const gchar *object,
+ gboolean object_is_null,
GError **error)
{
TrackerProperty *property;
@@ -2948,10 +3073,14 @@ tracker_data_update_statement (const gchar *graph,
property = tracker_ontologies_get_property_by_uri (predicate);
if (property != NULL) {
- if (tracker_property_get_data_type (property) == TRACKER_PROPERTY_TYPE_RESOURCE) {
- tracker_data_update_statement_with_uri (graph, subject, predicate, object, error);
+ if (object_is_null) {
+ delete_all_objects (graph, subject, predicate, error);
} else {
- tracker_data_update_statement_with_string (graph, subject, predicate, object, error);
+ if (tracker_property_get_data_type (property) == TRACKER_PROPERTY_TYPE_RESOURCE) {
+ tracker_data_update_statement_with_uri (graph, subject, predicate, object, error);
+ } else {
+ tracker_data_update_statement_with_string (graph, subject, predicate, object, error);
+ }
}
} else {
g_set_error (error, TRACKER_SPARQL_ERROR, TRACKER_SPARQL_ERROR_UNKNOWN_PROPERTY,
diff --git a/src/libtracker-data/tracker-data-update.h b/src/libtracker-data/tracker-data-update.h
index 9921333..245e894 100644
--- a/src/libtracker-data/tracker-data-update.h
+++ b/src/libtracker-data/tracker-data-update.h
@@ -79,6 +79,7 @@ void tracker_data_update_statement (const gchar *
const gchar *subject,
const gchar *predicate,
const gchar *object,
+ gboolean object_is_null,
GError **error);
void tracker_data_begin_transaction (GError **error);
void tracker_data_begin_ontology_transaction (GError **error);
diff --git a/src/libtracker-data/tracker-sparql-query.vala b/src/libtracker-data/tracker-sparql-query.vala
index 0c9f453..79b6e24 100644
--- a/src/libtracker-data/tracker-sparql-query.vala
+++ b/src/libtracker-data/tracker-sparql-query.vala
@@ -755,14 +755,16 @@ public class Tracker.Sparql.Query : Object {
expect (SparqlTokenType.OPEN_BRACE);
while (current () != SparqlTokenType.CLOSE_BRACE) {
+ bool is_null; // ignored
+
if (accept (SparqlTokenType.GRAPH)) {
var old_graph = current_graph;
- current_graph = parse_construct_var_or_term (var_value_map);
+ current_graph = parse_construct_var_or_term (var_value_map, out is_null);
expect (SparqlTokenType.OPEN_BRACE);
while (current () != SparqlTokenType.CLOSE_BRACE) {
- current_subject = parse_construct_var_or_term (var_value_map);
+ current_subject = parse_construct_var_or_term (var_value_map, out is_null);
parse_construct_property_list_not_empty (var_value_map);
if (!accept (SparqlTokenType.DOT)) {
// no triples following
@@ -776,7 +778,7 @@ public class Tracker.Sparql.Query : Object {
accept (SparqlTokenType.DOT);
} else {
- current_subject = parse_construct_var_or_term (var_value_map);
+ current_subject = parse_construct_var_or_term (var_value_map, out is_null);
parse_construct_property_list_not_empty (var_value_map);
if (!accept (SparqlTokenType.DOT) && current () != SparqlTokenType.GRAPH) {
// neither GRAPH nor triples following
@@ -790,8 +792,9 @@ public class Tracker.Sparql.Query : Object {
bool anon_blank_node_open = false;
- string? parse_construct_var_or_term (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
+ string? parse_construct_var_or_term (HashTable<string,string> var_value_map, out bool is_null) throws Sparql.Error, DateError {
string result = "";
+ is_null = false;
if (current () == SparqlTokenType.VAR) {
next ();
result = var_value_map.lookup (get_last_string ().substring (1));
@@ -825,6 +828,10 @@ public class Tracker.Sparql.Query : Object {
} else if (current () == SparqlTokenType.INTEGER) {
next ();
result = get_last_string ();
+ } else if (current () == SparqlTokenType.NULL) {
+ next ();
+ result = "null";
+ is_null = true;
} else if (current () == SparqlTokenType.DECIMAL) {
next ();
result = get_last_string ();
@@ -920,7 +927,8 @@ public class Tracker.Sparql.Query : Object {
}
void parse_construct_object (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
- string object = parse_construct_var_or_term (var_value_map);
+ bool is_null = false;
+ string object = parse_construct_var_or_term (var_value_map, out is_null);
if (current_subject == null || current_predicate == null || object == null) {
// the SPARQL specification says that triples containing unbound variables
// should be excluded from the output RDF graph of CONSTRUCT
@@ -929,12 +937,18 @@ public class Tracker.Sparql.Query : Object {
try {
if (update_statements) {
// update triple in database
- Data.update_statement (current_graph, current_subject, current_predicate, object);
+ Data.update_statement (current_graph, current_subject, current_predicate, object, is_null);
} else if (delete_statements) {
// delete triple from database
+ if (is_null) {
+ throw get_error ("'null' not supported in this mode");
+ }
Data.delete_statement (current_graph, current_subject, current_predicate, object);
} else {
// insert triple into database
+ if (is_null) {
+ throw get_error ("'null' not supported in this mode");
+ }
Data.insert_statement (current_graph, current_subject, current_predicate, object);
}
} catch (Sparql.Error e) {
diff --git a/src/libtracker-data/tracker-sparql-scanner.vala b/src/libtracker-data/tracker-sparql-scanner.vala
index dda1343..aed826d 100644
--- a/src/libtracker-data/tracker-sparql-scanner.vala
+++ b/src/libtracker-data/tracker-sparql-scanner.vala
@@ -169,6 +169,10 @@ public class Tracker.SparqlScanner : Object {
case 'l':
if (matches (begin, "LANG")) return SparqlTokenType.LANG;
break;
+ case 'N':
+ case 'n':
+ if (matches (begin, "NULL")) return SparqlTokenType.NULL;
+ break;
case 'T':
case 't':
if (matches (begin, "TRUE")) return SparqlTokenType.TRUE;
@@ -907,6 +911,7 @@ public enum Tracker.SparqlTokenType {
MINUS,
NAMED,
NOT,
+ NULL, /* Non-standard in SPARQL spec */
OFFSET,
OP_AND,
OP_EQ,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]