[tracker/sparql-update-multival] I think this is insane, but ill commit it somewhere anyway



commit 562a8351641e76e77e0f40a6d3832483dd567077
Author: Philip Van Hoof <philip codeminded be>
Date:   Wed Mar 9 13:51:26 2011 +0100

    I think this is insane, but ill commit it somewhere anyway

 src/libtracker-data/libtracker-data.vapi      |    2 +-
 src/libtracker-data/tracker-data-update.c     |   77 ++++++++++++++-----------
 src/libtracker-data/tracker-data-update.h     |    1 +
 src/libtracker-data/tracker-db-journal.c      |   17 ++++--
 src/libtracker-data/tracker-db-journal.h      |    6 +-
 src/libtracker-data/tracker-sparql-query.vala |   40 +++++++++++--
 tests/libtracker-data/tracker-db-journal.c    |    2 +-
 7 files changed, 97 insertions(+), 48 deletions(-)
---
diff --git a/src/libtracker-data/libtracker-data.vapi b/src/libtracker-data/libtracker-data.vapi
index ab2e4db..f779859 100644
--- a/src/libtracker-data/libtracker-data.vapi
+++ b/src/libtracker-data/libtracker-data.vapi
@@ -171,7 +171,7 @@ namespace Tracker {
 		public void load_turtle_file (GLib.File file) throws Sparql.Error;
 		public void notify_transaction (bool start_timer);
 		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, GLib.ValueArray? objects) 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 98309aa..3305915 100644
--- a/src/libtracker-data/tracker-data-update.c
+++ b/src/libtracker-data/tracker-data-update.c
@@ -762,7 +762,7 @@ tracker_data_resource_buffer_flush (GError **error)
 	TrackerDataUpdateBufferProperty *property;
 	GHashTableIter                  iter;
 	const gchar                    *table_name;
-	gint                            i, y, param;
+	gint                            i, param;
 	GError                         *actual_error = NULL;
 
 	iface = tracker_db_manager_get_db_interface ();
@@ -774,10 +774,11 @@ tracker_data_resource_buffer_flush (GError **error)
 				property = &g_array_index (table->properties, TrackerDataUpdateBufferProperty, i);
 
 				if (table->update_value) {
+					GValueArray *array;
+					guint y;
 
-					g_critical ("Unimplemented feature, SPARQL REPLACE for multi-value");
-
-					return;
+					/* For multi-value sets are stored in the value as GValueArray */
+					array = g_value_get_boxed (&property->value);
 
 					stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, &actual_error,
 					                                              "DELETE FROM \"%s\" WHERE ID = ?",
@@ -794,8 +795,9 @@ tracker_data_resource_buffer_flush (GError **error)
 						return;
 					}
 
-					/* TODO: loop over set */
-					for (y = 0; y < 0; y++) {
+					for (y = 0; y < array->n_values; y++) {
+						GValue *value = g_value_array_get_nth (array, y);
+
 						if (property->date_time) {
 							stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, &actual_error,
 							                                              "INSERT OR IGNORE INTO \"%s\" (ID, \"%s\", \"%s:localDate\", \"%s:localTime\", \"%s:graph\") VALUES (?, ?, ?, ?, ?)",
@@ -815,8 +817,7 @@ tracker_data_resource_buffer_flush (GError **error)
 						param = 0;
 
 						tracker_db_statement_bind_int (stmt, param++, resource_buffer->id);
-						/* TODO: add values[i]
-						 statement_bind_gvalue (stmt, &param, &property->values[i]); */
+						 statement_bind_gvalue (stmt, &param, value);
 
 						if (property->graph != 0) {
 							tracker_db_statement_bind_int (stmt, param++, property->graph);
@@ -1757,6 +1758,7 @@ cache_update_metadata_decomposed (TrackerProperty  *property,
                                   gint              value_id,
                                   const gchar      *graph,
                                   gint              graph_id,
+                                  GValueArray      *objects,
                                   GError          **error)
 {
 	gboolean            multiple_values;
@@ -1771,7 +1773,7 @@ cache_update_metadata_decomposed (TrackerProperty  *property,
 	super_properties = tracker_property_get_super_properties (property);
 	while (*super_properties) {
 		change |= cache_update_metadata_decomposed (*super_properties, value, value_id,
-		                                            graph, graph_id, &new_error);
+		                                            graph, graph_id, objects, &new_error);
 		if (new_error) {
 			g_propagate_error (error, new_error);
 			return FALSE;
@@ -1783,15 +1785,19 @@ cache_update_metadata_decomposed (TrackerProperty  *property,
 	table_name = tracker_property_get_table_name (property);
 	field_name = tracker_property_get_name (property);
 
-	if (value) {
-		string_to_gvalue (value, tracker_property_get_data_type (property), &gvalue, &new_error);
-		if (new_error) {
-			g_propagate_error (error, new_error);
-			return FALSE;
-		}
+	if (objects != NULL) {
+		g_value_set_boxed_take_ownership (&gvalue, objects);
 	} else {
-		g_value_init (&gvalue, G_TYPE_INT64);
-		g_value_set_int64 (&gvalue, value_id);
+		if (value) {
+			string_to_gvalue (value, tracker_property_get_data_type (property), &gvalue, &new_error);
+			if (new_error) {
+				g_propagate_error (error, new_error);
+				return FALSE;
+			}
+		} else {
+			g_value_init (&gvalue, G_TYPE_INT64);
+			g_value_set_int64 (&gvalue, value_id);
+		}
 	}
 
 	cache_update_value (table_name, field_name,
@@ -2618,6 +2624,7 @@ tracker_data_update_statement_with_uri (const gchar            *graph,
                                         const gchar            *subject,
                                         const gchar            *predicate,
                                         const gchar            *object,
+                                        GValueArray            *objects,
                                         GError                **error)
 {
 	GError          *actual_error = NULL;
@@ -2671,7 +2678,7 @@ tracker_data_update_statement_with_uri (const gchar            *graph,
 
 		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, objects, &actual_error);
 
 			g_hash_table_remove (blank_buffer.table, object);
 
@@ -2718,7 +2725,7 @@ tracker_data_update_statement_with_uri (const gchar            *graph,
 		change = TRUE;
 	} else {
 		/* update or add value to metadata database */
-		change = cache_update_metadata_decomposed (property, object, 0, graph, 0, &actual_error);
+		change = cache_update_metadata_decomposed (property, object, 0, graph, 0, objects, &actual_error);
 		if (actual_error) {
 			g_propagate_error (error, actual_error);
 			return;
@@ -2727,6 +2734,8 @@ tracker_data_update_statement_with_uri (const gchar            *graph,
 		if (change) {
 			graph_id = (graph != NULL ? query_resource_id (graph) : 0);
 			final_prop_id = (prop_id != 0) ? prop_id : tracker_data_query_resource_id (predicate);
+
+			/* todo get objects_ids here */
 			object_id = query_resource_id (object);
 
 			if (insert_callbacks) {
@@ -2757,6 +2766,8 @@ tracker_data_update_statement_with_uri (const gchar            *graph,
 	}
 
 	if (!in_journal_replay && change && !tracker_property_get_transient (property)) {
+
+		/* todo pass objects_ids here */
 		tracker_db_journal_append_update_statement_id (
 			(graph != NULL ? query_resource_id (graph) : 0),
 			resource_buffer->id,
@@ -2770,6 +2781,7 @@ tracker_data_update_statement_with_string (const gchar            *graph,
                                            const gchar            *subject,
                                            const gchar            *predicate,
                                            const gchar            *object,
+                                           GValueArray            *objects,
                                            GError                **error)
 {
 	GError          *actual_error = NULL;
@@ -2780,7 +2792,6 @@ tracker_data_update_statement_with_string (const gchar            *graph,
 
 	g_return_if_fail (subject != NULL);
 	g_return_if_fail (predicate != NULL);
-	g_return_if_fail (object != NULL);
 	g_return_if_fail (in_transaction);
 
 	property = tracker_ontologies_get_property_by_uri (predicate);
@@ -2812,7 +2823,7 @@ tracker_data_update_statement_with_string (const gchar            *graph,
 	}
 
 	/* add or update value to metadata database */
-	change = cache_update_metadata_decomposed (property, object, 0, graph, 0, &actual_error);
+	change = cache_update_metadata_decomposed (property, object, 0, graph, 0, objects, &actual_error);
 	if (actual_error) {
 		g_propagate_error (error, actual_error);
 		return;
@@ -2863,12 +2874,13 @@ tracker_data_update_statement_with_string (const gchar            *graph,
 			tracker_db_journal_append_update_statement (graph_id,
 				                                        resource_buffer->id,
 				                                        tracker_property_get_id (damaged),
-				                                        "true");
+				                                        "true", NULL);
 		} else {
 			tracker_db_journal_append_update_statement (graph_id,
 				                                        resource_buffer->id,
 				                                        pred_id,
-				                                        object);
+				                                        object,
+			                                            objects);
 		}
 	}
 }
@@ -2878,21 +2890,21 @@ tracker_data_update_statement (const gchar            *graph,
                                const gchar            *subject,
                                const gchar            *predicate,
                                const gchar            *object,
+                               GValueArray            *objects,
                                GError                **error)
 {
 	TrackerProperty *property;
 
 	g_return_if_fail (subject != NULL);
 	g_return_if_fail (predicate != NULL);
-	g_return_if_fail (object != NULL);
 	g_return_if_fail (in_transaction);
 
 	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);
+			tracker_data_update_statement_with_uri (graph, subject, predicate, object, objects, error);
 		} else {
-			tracker_data_update_statement_with_string (graph, subject, predicate, object, error);
+			tracker_data_update_statement_with_string (graph, subject, predicate, object, objects, error);
 		}
 	} else {
 		g_set_error (error, TRACKER_SPARQL_ERROR, TRACKER_SPARQL_ERROR_UNKNOWN_PROPERTY,
@@ -2900,9 +2912,6 @@ tracker_data_update_statement (const gchar            *graph,
 	}
 }
 
-/* --------------- */
-
-
 void
 tracker_data_begin_transaction (GError **error)
 {
@@ -3221,8 +3230,9 @@ tracker_data_replay_journal (TrackerBusyCallback   busy_callback,
 		           type == TRACKER_DB_JOURNAL_UPDATE_STATEMENT) {
 			GError *new_error = NULL;
 			TrackerProperty *property = NULL;
+			GValueArray *objects;
 
-			tracker_db_journal_reader_get_statement (&graph_id, &subject_id, &predicate_id, &object);
+			tracker_db_journal_reader_get_statement (&graph_id, &subject_id, &predicate_id, &object, &objects);
 
 			if (last_operation_type == -1) {
 				tracker_data_update_buffer_flush (&new_error);
@@ -3242,7 +3252,7 @@ tracker_data_replay_journal (TrackerBusyCallback   busy_callback,
 				resource_buffer_switch (NULL, graph_id, NULL, subject_id);
 
 				if (type == TRACKER_DB_JOURNAL_UPDATE_STATEMENT) {
-					cache_update_metadata_decomposed (property, object, 0, NULL, graph_id, &new_error);
+					cache_update_metadata_decomposed (property, object, 0, NULL, graph_id, objects, &new_error);
 				} else {
 					cache_insert_metadata_decomposed (property, object, 0, NULL, graph_id, &new_error);
 				}
@@ -3298,7 +3308,8 @@ tracker_data_replay_journal (TrackerBusyCallback   busy_callback,
 
 						/* add value to metadata database */
 						if (type == TRACKER_DB_JOURNAL_UPDATE_STATEMENT_ID) {
-							cache_update_metadata_decomposed (property, NULL, object_id, NULL, graph_id, &new_error);
+							/* TODO: check if passing NULL for objects is OK here */
+							cache_update_metadata_decomposed (property, NULL, object_id, NULL, graph_id, NULL, &new_error);
 						} else {
 							cache_insert_metadata_decomposed (property, NULL, object_id, NULL, graph_id, &new_error);
 						}
@@ -3317,7 +3328,7 @@ tracker_data_replay_journal (TrackerBusyCallback   busy_callback,
 			GError *new_error = NULL;
 			TrackerProperty *property = NULL;
 
-			tracker_db_journal_reader_get_statement (&graph_id, &subject_id, &predicate_id, &object);
+			tracker_db_journal_reader_get_statement (&graph_id, &subject_id, &predicate_id, &object, NULL);
 
 			if (last_operation_type == 1) {
 				tracker_data_update_buffer_flush (&new_error);
diff --git a/src/libtracker-data/tracker-data-update.h b/src/libtracker-data/tracker-data-update.h
index 1bed0d9..5c392d5 100644
--- a/src/libtracker-data/tracker-data-update.h
+++ b/src/libtracker-data/tracker-data-update.h
@@ -73,6 +73,7 @@ void     tracker_data_update_statement              (const gchar               *
                                                      const gchar               *subject,
                                                      const gchar               *predicate,
                                                      const gchar               *object,
+                                                     GValueArray               *objects,
                                                      GError                   **error);
 void     tracker_data_begin_transaction             (GError                   **error);
 void     tracker_data_begin_ontology_transaction    (GError                   **error);
diff --git a/src/libtracker-data/tracker-db-journal.c b/src/libtracker-data/tracker-db-journal.c
index caf6e3b..de1779e 100644
--- a/src/libtracker-data/tracker-db-journal.c
+++ b/src/libtracker-data/tracker-db-journal.c
@@ -899,7 +899,8 @@ db_journal_writer_append_update_statement (JournalWriter *jwriter,
                                            gint           g_id,
                                            gint           s_id,
                                            gint           p_id,
-                                           const gchar   *object)
+                                           const gchar   *object,
+                                           GValueArray   *objects)
 {
 	gint o_len;
 	DataFormat df;
@@ -909,7 +910,6 @@ db_journal_writer_append_update_statement (JournalWriter *jwriter,
 	g_return_val_if_fail (g_id >= 0, FALSE);
 	g_return_val_if_fail (s_id > 0, FALSE);
 	g_return_val_if_fail (p_id > 0, FALSE);
-	g_return_val_if_fail (object != NULL, FALSE);
 
 	o_len = strlen (object);
 	if (g_id == 0) {
@@ -933,6 +933,8 @@ db_journal_writer_append_update_statement (JournalWriter *jwriter,
 	jwriter->cur_entry_amount++;
 	jwriter->cur_block_len += size;
 
+	/* TODO: Write objects in case of a set */
+
 	return TRUE;
 }
 
@@ -940,14 +942,16 @@ gboolean
 tracker_db_journal_append_update_statement (gint         g_id,
                                             gint         s_id,
                                             gint         p_id,
-                                            const gchar *object)
+                                            const gchar *object,
+                                            GValueArray *objects)
 {
 	if (current_transaction_format == TRANSACTION_FORMAT_ONTOLOGY) {
 		return TRUE;
 	}
 
 	return db_journal_writer_append_update_statement (&writer,
-	                                                  g_id, s_id, p_id, object);
+	                                                  g_id, s_id, p_id,
+	                                                  object, objects);
 }
 
 static gboolean
@@ -1818,7 +1822,8 @@ gboolean
 tracker_db_journal_reader_get_statement (gint         *g_id,
                                          gint         *s_id,
                                          gint         *p_id,
-                                         const gchar **object)
+                                         const gchar **object,
+                                         GValueArray **objects)
 {
 	g_return_val_if_fail (reader.file != NULL || reader.stream != NULL, FALSE);
 	g_return_val_if_fail (reader.type == TRACKER_DB_JOURNAL_INSERT_STATEMENT ||
@@ -1833,6 +1838,8 @@ tracker_db_journal_reader_get_statement (gint         *g_id,
 	*p_id = reader.p_id;
 	*object = reader.object;
 
+	/* TODO: Read objects in case of TRACKER_DB_JOURNAL_UPDATE_STATEMENT of a set */
+
 	return TRUE;
 }
 
diff --git a/src/libtracker-data/tracker-db-journal.h b/src/libtracker-data/tracker-db-journal.h
index 7f3e1a5..8fc8289 100644
--- a/src/libtracker-data/tracker-db-journal.h
+++ b/src/libtracker-data/tracker-db-journal.h
@@ -88,7 +88,8 @@ gboolean     tracker_db_journal_append_insert_statement_id   (gint         g_id,
 gboolean     tracker_db_journal_append_update_statement      (gint         g_id,
                                                               gint         s_id,
                                                               gint         p_id,
-                                                              const gchar *object);
+                                                              const gchar *object,
+                                                              GValueArray *objects);
 gboolean     tracker_db_journal_append_update_statement_id   (gint         g_id,
                                                               gint         s_id,
                                                               gint         p_id,
@@ -118,7 +119,8 @@ gboolean     tracker_db_journal_reader_get_resource          (gint         *id,
 gboolean     tracker_db_journal_reader_get_statement         (gint         *g_id,
                                                               gint         *s_id,
                                                               gint         *p_id,
-                                                              const gchar **object);
+                                                              const gchar **object,
+                                                              GValueArray **objects);
 gboolean     tracker_db_journal_reader_get_statement_id      (gint         *g_id,
                                                               gint         *s_id,
                                                               gint         *p_id,
diff --git a/src/libtracker-data/tracker-sparql-query.vala b/src/libtracker-data/tracker-sparql-query.vala
index f101dd8..07238ca 100644
--- a/src/libtracker-data/tracker-sparql-query.vala
+++ b/src/libtracker-data/tracker-sparql-query.vala
@@ -212,7 +212,7 @@ public class Tracker.Sparql.Query : Object {
 	internal Context context;
 
 	bool delete_statements;
-	bool update_statements;
+	public bool update_statements;
 
 	int bnodeid = 0;
 	// base UUID used for blank nodes
@@ -590,7 +590,6 @@ public class Tracker.Sparql.Query : Object {
 		}
 
 		bool delete_statements;
-		bool update_statements;
 
 		if (accept (SparqlTokenType.INSERT)) {
 			delete_statements = false;
@@ -684,7 +683,6 @@ public class Tracker.Sparql.Query : Object {
 		var cursor = exec_sql_cursor (sql.str, null, null, false);
 
 		this.delete_statements = delete_statements;
-		this.update_statements = update_statements;
 
 		// iterate over all solutions
 		while (cursor.next ()) {
@@ -786,6 +784,27 @@ public class Tracker.Sparql.Query : Object {
 
 	bool anon_blank_node_open = false;
 
+	ValueArray? parse_construct_graph_node (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
+		ValueArray result = null;
+
+		expect (SparqlTokenType.OPEN_PARENS);
+
+		while (true) {
+			Value chunk = Value (typeof (string));
+			if (accept (SparqlTokenType.CLOSE_PARENS)) {
+				break;
+			}
+			next();
+			chunk.take_string (get_last_string ());
+			if (result == null) {
+				result = new ValueArray (5);
+			}
+			result.append (chunk);
+		}
+
+		return result;
+	}
+
 	string? parse_construct_var_or_term (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
 		string result = "";
 		if (current () == SparqlTokenType.VAR) {
@@ -916,8 +935,16 @@ 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);
-		if (current_subject == null || current_predicate == null || object == null) {
+		string object = null;
+		ValueArray objects = null;
+
+		if (update_statements && current() == SparqlTokenType.OPEN_PARENS) {
+			objects = parse_construct_graph_node (var_value_map);
+		} else {
+			object = parse_construct_var_or_term (var_value_map);
+		}
+
+		if (current_subject == null || current_predicate == null || (!update_statements && object == null)) {
 			// the SPARQL specification says that triples containing unbound variables
 			// should be excluded from the output RDF graph of CONSTRUCT
 			return;
@@ -925,7 +952,8 @@ public class Tracker.Sparql.Query : Object {
 		try {
 			if (update_statements) {
 				// update triple in database
-				Data.update_statement (current_graph, current_subject, current_predicate, object);
+				// TODO: last argument is for collections
+				Data.update_statement (current_graph, current_subject, current_predicate, object, objects);
 			} else if (delete_statements) {
 				// delete triple from database
 				Data.delete_statement (current_graph, current_subject, current_predicate, object);
diff --git a/tests/libtracker-data/tracker-db-journal.c b/tests/libtracker-data/tracker-db-journal.c
index 02ef306..d7a22c0 100644
--- a/tests/libtracker-data/tracker-db-journal.c
+++ b/tests/libtracker-data/tracker-db-journal.c
@@ -256,7 +256,7 @@ test_read_functions (void)
 	type = tracker_db_journal_reader_get_type ();
 	g_assert_cmpint (type, ==, TRACKER_DB_JOURNAL_INSERT_STATEMENT);
 
-	result = tracker_db_journal_reader_get_statement (NULL, &s_id, &p_id, &str);
+	result = tracker_db_journal_reader_get_statement (NULL, &s_id, &p_id, &str, NULL);
 	g_assert_cmpint (result, ==, TRUE);
 	g_assert_cmpint (s_id, ==, 15);
 	g_assert_cmpint (p_id, ==, 16);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]