[tracker/property-changes-for-review: 2/5] libtracker-data: Support for ontology change tracker:notify, tracker:writeback and tracker:indexed



commit 1b365e489ed9275c99ccd458a7cf5fafd9340354
Author: Philip Van Hoof <philip codeminded be>
Date:   Wed Mar 31 11:40:57 2010 +0200

    libtracker-data: Support for ontology change tracker:notify, tracker:writeback and tracker:indexed

 src/libtracker-data/tracker-class.c                |   53 +++
 src/libtracker-data/tracker-class.h                |    8 +-
 src/libtracker-data/tracker-data-manager.c         |  351 +++++++++++++++++---
 src/libtracker-data/tracker-data-manager.h         |    7 +-
 src/libtracker-data/tracker-data-update.c          |   41 ++-
 src/libtracker-data/tracker-property.c             |   52 +++
 src/libtracker-data/tracker-property.h             |    6 +
 .../change/source/99-example.ontology.v2           |    3 +-
 .../change/source/99-example.ontology.v3           |    3 +-
 .../change/source/99-example.ontology.v4           |    7 +
 .../change/updates/99-example.queries.v3           |    2 +-
 11 files changed, 472 insertions(+), 61 deletions(-)
---
diff --git a/src/libtracker-data/tracker-class.c b/src/libtracker-data/tracker-class.c
index b2375e6..0fc2599 100644
--- a/src/libtracker-data/tracker-class.c
+++ b/src/libtracker-data/tracker-class.c
@@ -39,6 +39,8 @@ struct _TrackerClassPriv {
 	gint count;
 	gint id;
 	gboolean is_new;
+	gboolean need_recreate;
+	gboolean notify;
 
 	GArray *super_classes;
 };
@@ -165,6 +167,30 @@ tracker_class_get_is_new (TrackerClass *service)
 	return priv->is_new;
 }
 
+gboolean
+tracker_class_get_notify (TrackerClass *service)
+{
+	TrackerClassPriv *priv;
+
+	g_return_val_if_fail (TRACKER_IS_CLASS (service), FALSE);
+
+	priv = GET_PRIV (service);
+
+	return priv->notify;
+}
+
+gboolean
+tracker_class_get_need_recreate (TrackerClass *service)
+{
+	TrackerClassPriv *priv;
+
+	g_return_val_if_fail (TRACKER_IS_CLASS (service), FALSE);
+
+	priv = GET_PRIV (service);
+
+	return priv->need_recreate;
+}
+
 void
 tracker_class_set_uri (TrackerClass *service,
                        const gchar  *value)
@@ -260,3 +286,30 @@ tracker_class_set_is_new (TrackerClass *service,
 
 	priv->is_new = value;
 }
+
+void
+tracker_class_set_notify (TrackerClass *service,
+                          gboolean         value)
+{
+	TrackerClassPriv *priv;
+
+	g_return_if_fail (TRACKER_IS_CLASS (service));
+
+	priv = GET_PRIV (service);
+
+	priv->notify = value;
+}
+
+void
+tracker_class_set_need_recreate (TrackerClass *service,
+                                 gboolean         value)
+{
+	TrackerClassPriv *priv;
+
+	g_return_if_fail (TRACKER_IS_CLASS (service));
+
+	priv = GET_PRIV (service);
+
+	priv->need_recreate = value;
+}
+
diff --git a/src/libtracker-data/tracker-class.h b/src/libtracker-data/tracker-class.h
index c6c0acd..0b1725b 100644
--- a/src/libtracker-data/tracker-class.h
+++ b/src/libtracker-data/tracker-class.h
@@ -54,8 +54,10 @@ const gchar *   tracker_class_get_name          (TrackerClass  *service);
 gint            tracker_class_get_count         (TrackerClass  *service);
 gint            tracker_class_get_id            (TrackerClass  *service);
 gboolean        tracker_class_get_is_new        (TrackerClass  *service);
-
+gboolean        tracker_class_get_need_recreate (TrackerClass  *service);
+gboolean        tracker_class_get_notify        (TrackerClass  *service);
 TrackerClass  **tracker_class_get_super_classes (TrackerClass  *service);
+
 void            tracker_class_set_uri           (TrackerClass  *service,
                                                  const gchar   *value);
 void            tracker_class_set_count         (TrackerClass  *service,
@@ -66,6 +68,10 @@ void            tracker_class_set_id            (TrackerClass  *service,
                                                  gint           id);
 void            tracker_class_set_is_new        (TrackerClass  *service,
                                                  gboolean       value);
+void            tracker_class_set_need_recreate (TrackerClass  *service,
+                                                 gboolean       value);
+void            tracker_class_set_notify        (TrackerClass  *service,
+                                                 gboolean       value);
 
 G_END_DECLS
 
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index ef29b66..7573b47 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -46,6 +46,7 @@
 #include "tracker-ontology.h"
 #include "tracker-property.h"
 #include "tracker-sparql-query.h"
+#include "tracker-data-query.h"
 
 #define RDF_PREFIX TRACKER_RDF_PREFIX
 #define RDF_PROPERTY RDF_PREFIX "Property"
@@ -69,9 +70,147 @@
 
 #define ZLIBBUFSIZ 8192
 
-static gchar              *ontologies_dir;
-static gboolean            initialized;
-static gboolean            in_journal_replay;
+static gchar    *ontologies_dir;
+static gboolean  initialized;
+static gboolean  in_journal_replay;
+
+static void
+set_index_for_single_value_property (TrackerDBInterface *iface,
+                                     const gchar *service_name,
+                                     const gchar *field_name,
+                                     gboolean enabled)
+{
+	if (enabled) {
+		tracker_db_interface_execute_query (iface, NULL,
+		                                    "CREATE INDEX \"%s_%s\" ON \"%s\" (\"%s\")",
+		                                    service_name,
+		                                    field_name,
+		                                    service_name,
+		                                    field_name);
+	} else {
+		tracker_db_interface_execute_query (iface, NULL,
+		                                    "DROP INDEX IF EXISTS \"%s_%s\"",
+		                                    service_name,
+		                                    field_name);
+	}
+}
+
+static void
+set_index_for_multi_value_property (TrackerDBInterface *iface,
+                                    const gchar *service_name,
+                                    const gchar *field_name,
+                                    gboolean enabled)
+{
+	tracker_db_interface_execute_query (iface, NULL,
+	                                    "DROP INDEX IF EXISTS \"%s_%s_ID_ID\"",
+	                                    service_name,
+	                                    field_name);
+
+	if (enabled) {
+		tracker_db_interface_execute_query (iface, NULL,
+		                                    "CREATE INDEX \"%s_%s_ID\" ON \"%s_%s\" (ID)",
+		                                    service_name,
+		                                    field_name,
+		                                    service_name,
+		                                    field_name);
+		tracker_db_interface_execute_query (iface, NULL,
+		                                    "CREATE UNIQUE INDEX \"%s_%s_ID_ID\" ON \"%s_%s\" (\"%s\", ID)",
+		                                    service_name,
+		                                    field_name,
+		                                    service_name,
+		                                    field_name,
+		                                    field_name);
+	} else {
+		tracker_db_interface_execute_query (iface, NULL,
+		                                    "DROP INDEX IF EXISTS \"%s_%s_ID\"",
+		                                    service_name,
+		                                    field_name);
+		tracker_db_interface_execute_query (iface, NULL,
+		                                    "CREATE UNIQUE INDEX \"%s_%s_ID_ID\" ON \"%s_%s\" (ID, \"%s\")",
+		                                    service_name,
+		                                    field_name,
+		                                    service_name,
+		                                    field_name,
+		                                    field_name);
+	}
+}
+
+static gboolean
+update_property_value (const gchar *kind,
+                       const gchar *subject,
+                       const gchar *predicate,
+                       const gchar *object)
+{
+	GError *error = NULL;
+	TrackerDBResultSet *result_set;
+	gchar *query;
+	gboolean needed = TRUE;
+
+	query = g_strdup_printf ("SELECT ?old_value WHERE { "
+	                           "<%s> %s ?old_value "
+	                         "}", subject, kind);
+
+	result_set = tracker_data_query_sparql (query, &error);
+
+	g_free (query);
+
+	if (!error && result_set) {
+		gchar *str = NULL;
+
+		tracker_db_result_set_get (result_set, 0, &str, -1);
+
+		if (g_strcmp0 (object, str) == 0) {
+			needed = FALSE;
+		} else {
+			tracker_data_delete_statement (NULL, subject, predicate, str, &error);
+			if (!error)
+				tracker_data_update_buffer_flush (&error);
+		}
+
+		g_free (str);
+	}
+
+	if (result_set) {
+		g_object_unref (result_set);
+	}
+
+	if (!error && needed) {
+		tracker_data_insert_statement (NULL, subject,
+		                               predicate, object,
+		                               &error);
+		if (!error)
+			tracker_data_update_buffer_flush (&error);
+	}
+
+	if (error) {
+		g_critical ("Ontology change: %s", error->message);
+		g_clear_error (&error);
+	}
+
+	return needed;
+}
+
+
+static void
+fix_indexed (TrackerProperty *property, gboolean enabled)
+{
+	TrackerDBInterface *iface;
+	TrackerClass *class;
+	const gchar *service_name;
+	const gchar *field_name;
+
+	iface = tracker_db_manager_get_db_interface ();
+
+	class = tracker_property_get_domain (property);
+	field_name = tracker_property_get_name (property);
+	service_name = tracker_class_get_name (class);
+
+	if (tracker_property_get_multiple_values (property)) {
+		set_index_for_multi_value_property (iface, service_name, field_name, enabled);
+	} else {
+		set_index_for_single_value_property (iface, service_name, field_name, enabled);
+	}
+}
 
 void
 tracker_data_ontology_load_statement (const gchar *ontology_path,
@@ -82,15 +221,24 @@ tracker_data_ontology_load_statement (const gchar *ontology_path,
                                       gint        *max_id,
                                       gboolean    in_update,
                                       GHashTable *classes,
-                                      GHashTable *properties)
+                                      GHashTable *properties,
+                                      GPtrArray  *seen_classes,
+                                      GPtrArray  *seen_properties)
 {
 	if (g_strcmp0 (predicate, RDF_TYPE) == 0) {
 		if (g_strcmp0 (object, RDFS_CLASS) == 0) {
 			TrackerClass *class;
+			class = tracker_ontologies_get_class_by_uri (subject);
 
-			if (tracker_ontologies_get_class_by_uri (subject) != NULL) {
-				if (!in_update)
+			if (class != NULL) {
+				if (seen_classes)
+					g_ptr_array_add (seen_classes, g_object_ref (class));
+				if (!in_update) {
 					g_critical ("%s: Duplicate definition of class %s", ontology_path, subject);
+				} else {
+					/* Reset for a correct post-check */
+					tracker_class_set_notify (class, FALSE);
+				}
 				return;
 			}
 
@@ -105,6 +253,9 @@ tracker_data_ontology_load_statement (const gchar *ontology_path,
 			tracker_ontologies_add_class (class);
 			tracker_ontologies_add_id_uri_pair (subject_id, subject);
 
+			if (seen_classes)
+				g_ptr_array_add (seen_classes, g_object_ref (class));
+
 			if (classes) {
 				g_hash_table_insert (classes, GINT_TO_POINTER (subject_id), class);
 			} else {
@@ -114,9 +265,17 @@ tracker_data_ontology_load_statement (const gchar *ontology_path,
 		} else if (g_strcmp0 (object, RDF_PROPERTY) == 0) {
 			TrackerProperty *property;
 
-			if (tracker_ontologies_get_property_by_uri (subject) != NULL) {
-				if (!in_update)
+			property = tracker_ontologies_get_property_by_uri (subject);
+			if (property != NULL) {
+				if (seen_properties)
+					g_ptr_array_add (seen_properties, g_object_ref (property));
+				if (!in_update) {
 					g_critical ("%s: Duplicate definition of property %s", ontology_path, subject);
+				} else {
+					/* Reset for a correct post-check */
+					tracker_property_set_indexed (property, FALSE);
+					tracker_property_set_writeback (property, FALSE);
+				}
 				return;
 			}
 
@@ -131,6 +290,9 @@ tracker_data_ontology_load_statement (const gchar *ontology_path,
 			tracker_ontologies_add_property (property);
 			tracker_ontologies_add_id_uri_pair (subject_id, subject);
 
+			if (seen_properties)
+				g_ptr_array_add (seen_properties, g_object_ref (property));
+
 			if (properties) {
 				g_hash_table_insert (properties, GINT_TO_POINTER (subject_id), property);
 			} else {
@@ -198,6 +360,29 @@ tracker_data_ontology_load_statement (const gchar *ontology_path,
 		}
 
 		tracker_class_add_super_class (class, super_class);
+	} else if (g_strcmp0 (predicate, TRACKER_PREFIX "notify") == 0) {
+		TrackerClass *class;
+
+		class = tracker_ontologies_get_class_by_uri (subject);
+
+		if (class == NULL) {
+			g_critical ("%s: Unknown class %s", ontology_path, subject);
+			return;
+		}
+
+		tracker_class_set_notify (class, (strcmp (object, "true") == 0));
+
+	} else if (g_strcmp0 (predicate, TRACKER_PREFIX "writeback") == 0) {
+		TrackerProperty *property;
+
+		property = tracker_ontologies_get_property_by_uri (subject);
+
+		if (property == NULL) {
+			g_critical ("%s: Unknown property %s", ontology_path, subject);
+			return;
+		}
+
+		tracker_property_set_writeback (property, (strcmp (object, "true") == 0));
 	} else if (g_strcmp0 (predicate, RDFS_SUB_PROPERTY_OF) == 0) {
 		TrackerProperty *property, *super_property;
 
@@ -285,13 +470,7 @@ tracker_data_ontology_load_statement (const gchar *ontology_path,
 			return;
 		}
 
-		if (tracker_property_get_is_new (property) != in_update) {
-			return;
-		}
-
-		if (strcmp (object, "true") == 0) {
-			tracker_property_set_indexed (property, TRUE);
-		}
+		tracker_property_set_indexed (property, (strcmp (object, "true") == 0));
 	} else if (g_strcmp0 (predicate, TRACKER_PREFIX "transient") == 0) {
 		TrackerProperty *property;
 
@@ -349,6 +528,10 @@ tracker_data_ontology_load_statement (const gchar *ontology_path,
 			return;
 		}
 
+		if (tracker_property_get_is_new (property) != in_update) {
+			return;
+		}
+
 		if (strcmp (object, "true") == 0) {
 			tracker_property_set_fulltext_no_limit (property, TRUE);
 		}
@@ -381,13 +564,82 @@ tracker_data_ontology_load_statement (const gchar *ontology_path,
 
 		tracker_ontology_set_last_modified (ontology, tracker_string_to_date (object, NULL, NULL));
 	}
+}
+
+void
+tracker_data_ontology_post_check (GPtrArray *seen_classes,
+                                  GPtrArray *seen_properties)
+{
+	gint i;
+
+	/* This checks for properties of classes being removed from the ontology.
+	 * For example when going from: prefix:A rdfs:Class ; tracker:notify true .
+	 * to prefix:A rdfs:Class . */
+
+	for (i = 0; i < seen_classes->len; i++) {
+		TrackerClass *class = g_ptr_array_index (seen_classes, i);
+		const gchar *subject;
+		subject = tracker_class_get_uri (class);
+		if (tracker_class_get_notify (class)) {
+			update_property_value ("tracker:notify",
+			                       subject,
+			                       TRACKER_PREFIX "notify",
+			                       "true");
+		} else {
+			update_property_value ("tracker:notify",
+			                       subject,
+			                       TRACKER_PREFIX "notify",
+			                       "false");
+		}
+	}
+
+	for (i = 0; i < seen_properties->len; i++) {
+		TrackerProperty *property = g_ptr_array_index (seen_properties, i);
+		const gchar *subject;
+		subject = tracker_property_get_uri (property);
+		if (tracker_property_get_writeback (property)) {
+			update_property_value ("tracker:writeback",
+			                       subject,
+			                       TRACKER_PREFIX "writeback",
+			                       "true");
+		} else {
+			update_property_value ("tracker:writeback",
+			                       subject,
+			                       TRACKER_PREFIX "writeback",
+			                       "false");
+		}
+
+		if (tracker_property_get_indexed (property)) {
+			if (update_property_value ("tracker:indexed",
+			                           subject,
+			                           TRACKER_PREFIX "indexed",
+			                           "true")) {
+				fix_indexed (property, TRUE);
+			}
+		} else {
+			if (update_property_value ("tracker:indexed",
+			                           subject,
+			                           TRACKER_PREFIX "indexed",
+			                           "false")) {
+				fix_indexed (property, FALSE);
+			}
+		}
+	}
+}
 
+void
+tracker_data_ontology_free_seen (GPtrArray *seen)
+{
+	g_ptr_array_foreach (seen, (GFunc) g_object_unref, NULL);
+	g_ptr_array_free (seen, TRUE);
 }
 
 static void
 load_ontology_file_from_path (const gchar        *ontology_path,
                               gint               *max_id,
-                              gboolean            in_update)
+                              gboolean            in_update,
+                              GPtrArray          *seen_classes,
+                              GPtrArray          *seen_properties)
 {
 	TrackerTurtleReader *reader;
 	GError              *error = NULL;
@@ -399,6 +651,9 @@ load_ontology_file_from_path (const gchar        *ontology_path,
 		return;
 	}
 
+	/* Post checks are only needed for ontology updates, not the initial
+	 * ontology */
+
 	while (error == NULL && tracker_turtle_reader_next (reader, &error)) {
 		const gchar *subject, *predicate, *object;
 
@@ -407,7 +662,8 @@ load_ontology_file_from_path (const gchar        *ontology_path,
 		object = tracker_turtle_reader_get_object (reader);
 
 		tracker_data_ontology_load_statement (ontology_path, 0, subject, predicate, object,
-		                                      max_id, in_update, NULL, NULL);
+		                                      max_id, in_update, NULL, NULL,
+		                                      seen_classes, seen_properties);
 	}
 
 	g_object_unref (reader);
@@ -505,7 +761,6 @@ load_ontology_from_journal (GHashTable **classes_out,
 
 	id_uri_map = g_hash_table_new (g_direct_hash, g_direct_equal);
 
-
 	while (tracker_db_journal_reader_next (NULL)) {
 		TrackerDBJournalEntryType type;
 
@@ -535,8 +790,12 @@ load_ontology_from_journal (GHashTable **classes_out,
 			subject = g_hash_table_lookup (id_uri_map, GINT_TO_POINTER (subject_id));
 			predicate = g_hash_table_lookup (id_uri_map, GINT_TO_POINTER (predicate_id));
 
-			tracker_data_ontology_load_statement ("journal", subject_id, subject, predicate, 
-			                                      object, NULL, FALSE, classes, properties);
+			/* Post checks are only needed for ontology updates, not the initial
+			 * ontology */
+
+			tracker_data_ontology_load_statement ("journal", subject_id, subject, predicate,
+			                                      object, NULL, FALSE, classes, properties,
+			                                      NULL, NULL);
 		}
 	}
 
@@ -1094,30 +1353,18 @@ create_decomposed_metadata_property_table (TrackerDBInterface *iface,
 				                        tracker_property_get_name (property));
 			}
 
+			tracker_db_interface_execute_query (iface, NULL,
+			                                    "%s)", sql->str);
+
 			/* multiple values */
 			if (tracker_property_get_indexed (property)) {
 				/* use different UNIQUE index for properties whose
 				 * value should be indexed to minimize index size */
-				tracker_db_interface_execute_query (iface, NULL,
-				                                    "%s, "
-				                                    "UNIQUE (\"%s\", ID))",
-				                                    sql->str,
-				                                    field_name);
-
-				tracker_db_interface_execute_query (iface, NULL,
-				                                    "CREATE INDEX \"%s_%s_ID\" ON \"%s_%s\" (ID)",
-				                                    service_name,
-				                                    field_name,
-				                                    service_name,
-				                                    field_name);
+				set_index_for_multi_value_property (iface, service_name, field_name, TRUE);
 			} else {
+				set_index_for_multi_value_property (iface, service_name, field_name, FALSE);
 				/* we still have to include the property value in
 				 * the unique index for proper constraints */
-				tracker_db_interface_execute_query (iface, NULL,
-				                                    "%s, "
-				                                    "UNIQUE (ID, \"%s\"))",
-				                                    sql->str,
-				                                    field_name);
 			}
 
 			g_string_free (sql, TRUE);
@@ -1271,12 +1518,7 @@ create_decomposed_metadata_tables (TrackerDBInterface *iface,
 		if (!tracker_property_get_multiple_values (field)
 		    && tracker_property_get_indexed (field)) {
 			field_name = tracker_property_get_name (field);
-			tracker_db_interface_execute_query (iface, NULL,
-			                                    "CREATE INDEX \"%s_%s\" ON \"%s\" (\"%s\")",
-			                                    service_name,
-			                                    field_name,
-			                                    service_name,
-			                                    field_name);
+			set_index_for_single_value_property (iface, service_name, field_name, TRUE);
 		}
 	}
 
@@ -1546,7 +1788,7 @@ tracker_data_manager_init (TrackerDBManagerFlags  flags,
 			gchar *ontology_path;
 			g_debug ("Loading ontology %s", (char *) l->data);
 			ontology_path = g_build_filename (ontologies_dir, l->data, NULL);
-			load_ontology_file_from_path (ontology_path, &max_id, FALSE);
+			load_ontology_file_from_path (ontology_path, &max_id, FALSE, NULL, NULL);
 			g_free (ontology_path);
 		}
 
@@ -1558,7 +1800,7 @@ tracker_data_manager_init (TrackerDBManagerFlags  flags,
 
 				g_debug ("Loading ontology:'%s' (TEST ONTOLOGY)", test_schema_path);
 
-				load_ontology_file_from_path (test_schema_path, &max_id, FALSE);
+				load_ontology_file_from_path (test_schema_path, &max_id, FALSE, NULL, NULL);
 				g_free (test_schema_path);
 			}
 		}
@@ -1613,6 +1855,11 @@ tracker_data_manager_init (TrackerDBManagerFlags  flags,
 		GList *to_reload = NULL;
 		GList *ontos = NULL;
 		guint p;
+		GPtrArray *seen_classes;
+		GPtrArray *seen_properties;
+
+		seen_classes = g_ptr_array_new ();
+		seen_properties = g_ptr_array_new ();
 
 		/* Get all the ontology files from ontologies_dir */
 		sorted = get_ontologies (test_schemas != NULL, ontologies_dir);
@@ -1711,9 +1958,10 @@ tracker_data_manager_init (TrackerDBManagerFlags  flags,
 						/* In case of first-time, this wont start at zero */
 						max_id = get_new_service_id (iface);
 					}
-					/* load ontology from files into memory, set all new's 
+					/* load ontology from files into memory, set all new's
 					 * is_new to TRUE */
-					load_ontology_file_from_path (ontology_path, &max_id, TRUE);
+					load_ontology_file_from_path (ontology_path, &max_id, TRUE,
+					                              seen_classes, seen_properties);
 					to_reload = g_list_prepend (to_reload, l->data);
 					update_nao = TRUE;
 				}
@@ -1723,9 +1971,10 @@ tracker_data_manager_init (TrackerDBManagerFlags  flags,
 					/* In case of first-time, this wont start at zero */
 					max_id = get_new_service_id (iface);
 				}
-				/* load ontology from files into memory, set all new's 
+				/* load ontology from files into memory, set all new's
 				 * is_new to TRUE */
-				load_ontology_file_from_path (ontology_path, &max_id, TRUE);
+				load_ontology_file_from_path (ontology_path, &max_id, TRUE,
+				                              seen_classes, seen_properties);
 				to_reload = g_list_prepend (to_reload, l->data);
 				update_nao = TRUE;
 			}
@@ -1760,6 +2009,10 @@ tracker_data_manager_init (TrackerDBManagerFlags  flags,
 			g_list_free (to_reload);
 		}
 
+		tracker_data_ontology_post_check (seen_classes, seen_properties);
+		tracker_data_ontology_free_seen (seen_classes);
+		tracker_data_ontology_free_seen (seen_properties);
+
 		/* Reset the is_new flag for all classes and properties */
 		tracker_data_ontology_import_finished ();
 
diff --git a/src/libtracker-data/tracker-data-manager.h b/src/libtracker-data/tracker-data-manager.h
index cb41391..38a5f2c 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -58,7 +58,9 @@ void     tracker_data_ontology_load_statement     (const gchar           *ontolo
                                                    gint                  *max_id,
                                                    gboolean               in_update,
                                                    GHashTable            *classes,
-                                                   GHashTable            *properties);
+                                                   GHashTable            *properties,
+                                                   GPtrArray             *seen_classes,
+                                                   GPtrArray             *seen_properties);
 void     tracker_data_ontology_import_into_db     (gboolean               is_new);
 void     tracker_data_ontology_process_statement  (const gchar           *graph,
                                                    const gchar           *subject,
@@ -68,6 +70,9 @@ void     tracker_data_ontology_process_statement  (const gchar           *graph,
                                                    gboolean               in_update,
                                                    gboolean               ignore_nao_last_modified);
 void    tracker_data_ontology_import_finished     (void);
+void    tracker_data_ontology_post_check          (GPtrArray             *seen_classes,
+                                                   GPtrArray             *seen_properties);
+void    tracker_data_ontology_free_seen           (GPtrArray             *seen);
 
 G_END_DECLS
 
diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c
index 37bb4b4..0d766cc 100644
--- a/src/libtracker-data/tracker-data-update.c
+++ b/src/libtracker-data/tracker-data-update.c
@@ -2376,11 +2376,13 @@ queue_statement (GList *queue,
 }
 
 static void
-ontology_transaction_end (GList *ontology_queue)
+ontology_transaction_end (GList *ontology_queue, GPtrArray *seen_classes, GPtrArray *seen_properties)
 {
 	GList *l;
 	const gchar *ontology_uri = NULL;
 
+	tracker_data_ontology_post_check (seen_classes, seen_properties);
+
 	/* Perform ALTER-TABLE and CREATE-TABLE calls for all that are is_new */
 	tracker_data_ontology_import_into_db (TRUE);
 
@@ -2444,7 +2446,9 @@ ontology_statement_insert (GList       *ontology_queue,
                            GHashTable  *classes,
                            GHashTable  *properties,
                            GHashTable  *id_uri_map,
-                           gboolean     is_uri)
+                           gboolean     is_uri,
+                           GPtrArray   *seen_classes,
+                           GPtrArray   *seen_properties)
 {
 	const gchar *graph, *subject, *predicate;
 
@@ -2458,8 +2462,9 @@ ontology_statement_insert (GList       *ontology_queue,
 	predicate = g_hash_table_lookup (id_uri_map, GINT_TO_POINTER (predicate_id));
 
 	/* load ontology from journal into memory, set all new's is_new to TRUE */
-	tracker_data_ontology_load_statement ("journal", subject_id, subject, predicate, 
-	                                      object, NULL, TRUE, classes, properties);
+	tracker_data_ontology_load_statement ("journal", subject_id, subject, predicate,
+	                                      object, NULL, TRUE, classes, properties,
+	                                      seen_classes, seen_properties);
 
 	/* Queue the statement for processing after ALTER in ontology_transaction_end */
 	ontology_queue = queue_statement (ontology_queue, graph, subject, predicate, object, is_uri);
@@ -2480,6 +2485,8 @@ tracker_data_replay_journal (GHashTable          *classes,
 	gint last_operation_type = 0;
 	gboolean in_ontology = FALSE;
 	GList *ontology_queue = NULL;
+	GPtrArray *seen_classes = NULL;
+	GPtrArray *seen_properties = NULL;
 
 	tracker_data_begin_db_transaction_for_replay (0);
 
@@ -2538,11 +2545,15 @@ tracker_data_replay_journal (GHashTable          *classes,
 			resource_time = tracker_db_journal_reader_get_time ();
 		} else if (type == TRACKER_DB_JOURNAL_END_TRANSACTION) {
 			if (in_ontology) {
-				ontology_transaction_end (ontology_queue);
+				ontology_transaction_end (ontology_queue, seen_classes, seen_properties);
 				g_list_foreach (ontology_queue, (GFunc) free_queued_statement, NULL);
 				g_list_free (ontology_queue);
 				ontology_queue = NULL;
 				in_ontology = FALSE;
+				tracker_data_ontology_free_seen (seen_classes);
+				seen_classes = NULL;
+				tracker_data_ontology_free_seen (seen_properties);
+				seen_properties = NULL;
 			} else {
 				GError *new_error = NULL;
 				tracker_data_update_buffer_might_flush (&new_error);
@@ -2558,6 +2569,12 @@ tracker_data_replay_journal (GHashTable          *classes,
 			tracker_db_journal_reader_get_statement (&graph_id, &subject_id, &predicate_id, &object);
 
 			if (in_ontology) {
+
+				if (!seen_classes)
+					seen_classes = g_ptr_array_new ();
+				if (!seen_properties)
+					seen_properties = g_ptr_array_new ();
+
 				ontology_queue = ontology_statement_insert (ontology_queue,
 				                                            graph_id,
 				                                            subject_id,
@@ -2566,7 +2583,9 @@ tracker_data_replay_journal (GHashTable          *classes,
 				                                            classes,
 				                                            properties,
 				                                            id_uri_map,
-				                                            FALSE);
+				                                            FALSE,
+				                                            seen_classes,
+				                                            seen_properties);
 				continue;
 			}
 
@@ -2605,6 +2624,12 @@ tracker_data_replay_journal (GHashTable          *classes,
 			if (in_ontology) {
 				const gchar *object_n;
 				object_n = g_hash_table_lookup (id_uri_map, GINT_TO_POINTER (object_id));
+
+				if (!seen_classes)
+					seen_classes = g_ptr_array_new ();
+				if (!seen_properties)
+					seen_properties = g_ptr_array_new ();
+
 				ontology_queue = ontology_statement_insert (ontology_queue,
 				                                            graph_id,
 				                                            subject_id,
@@ -2613,7 +2638,9 @@ tracker_data_replay_journal (GHashTable          *classes,
 				                                            classes,
 				                                            properties,
 				                                            id_uri_map,
-				                                            TRUE);
+				                                            TRUE,
+				                                            seen_classes,
+				                                            seen_properties);
 				continue;
 			}
 
diff --git a/src/libtracker-data/tracker-property.c b/src/libtracker-data/tracker-property.c
index b59d1e6..cbe178e 100644
--- a/src/libtracker-data/tracker-property.c
+++ b/src/libtracker-data/tracker-property.c
@@ -59,6 +59,8 @@ struct _TrackerPropertyPriv {
 	gboolean       transient;
 	gboolean       is_inverse_functional_property;
 	gboolean       is_new;
+	gboolean       need_recreate;
+	gboolean       writeback;
 
 	GArray        *super_properties;
 };
@@ -341,6 +343,30 @@ tracker_property_get_is_new (TrackerProperty *field)
 }
 
 gboolean
+tracker_property_get_writeback (TrackerProperty *field)
+{
+	TrackerPropertyPriv *priv;
+
+	g_return_val_if_fail (TRACKER_IS_PROPERTY (field), FALSE);
+
+	priv = GET_PRIV (field);
+
+	return priv->writeback;
+}
+
+gboolean
+tracker_property_get_need_recreate (TrackerProperty *field)
+{
+	TrackerPropertyPriv *priv;
+
+	g_return_val_if_fail (TRACKER_IS_PROPERTY (field), FALSE);
+
+	priv = GET_PRIV (field);
+
+	return priv->need_recreate;
+}
+
+gboolean
 tracker_property_get_embedded (TrackerProperty *field)
 {
 	TrackerPropertyPriv *priv;
@@ -551,6 +577,32 @@ tracker_property_set_is_new (TrackerProperty *field,
 }
 
 void
+tracker_property_set_writeback (TrackerProperty *field,
+                             gboolean         value)
+{
+	TrackerPropertyPriv *priv;
+
+	g_return_if_fail (TRACKER_IS_PROPERTY (field));
+
+	priv = GET_PRIV (field);
+
+	priv->writeback = value;
+}
+
+void
+tracker_property_set_need_recreate (TrackerProperty *field,
+                                    gboolean         value)
+{
+	TrackerPropertyPriv *priv;
+
+	g_return_if_fail (TRACKER_IS_PROPERTY (field));
+
+	priv = GET_PRIV (field);
+
+	priv->need_recreate = value;
+}
+
+void
 tracker_property_set_fulltext_indexed (TrackerProperty *field,
                                        gboolean                 value)
 {
diff --git a/src/libtracker-data/tracker-property.h b/src/libtracker-data/tracker-property.h
index ab4e532..7eb4baa 100644
--- a/src/libtracker-data/tracker-property.h
+++ b/src/libtracker-data/tracker-property.h
@@ -87,6 +87,8 @@ gboolean            tracker_property_get_embedded         (TrackerProperty
 gboolean            tracker_property_get_multiple_values  (TrackerProperty      *property);
 gboolean            tracker_property_get_transient        (TrackerProperty      *property);
 gboolean            tracker_property_get_is_new           (TrackerProperty      *property);
+gboolean            tracker_property_get_writeback        (TrackerProperty      *property);
+gboolean            tracker_property_get_need_recreate    (TrackerProperty      *property);
 gboolean            tracker_property_get_is_inverse_functional_property
 (TrackerProperty      *property);
 TrackerProperty **  tracker_property_get_super_properties (TrackerProperty      *property);
@@ -114,6 +116,10 @@ void                tracker_property_set_transient        (TrackerProperty
                                                            gboolean              value);
 void                tracker_property_set_is_new           (TrackerProperty      *property,
                                                            gboolean              value);
+void                tracker_property_set_writeback        (TrackerProperty      *property,
+                                                           gboolean              value);
+void                tracker_property_set_need_recreate    (TrackerProperty      *property,
+                                                           gboolean              value);
 void                tracker_property_set_is_inverse_functional_property
 (TrackerProperty      *property,
  gboolean              value);
diff --git a/tests/libtracker-data/change/source/99-example.ontology.v2 b/tests/libtracker-data/change/source/99-example.ontology.v2
index fefb68f..10bdbb2 100644
--- a/tests/libtracker-data/change/source/99-example.ontology.v2
+++ b/tests/libtracker-data/change/source/99-example.ontology.v2
@@ -17,5 +17,6 @@ example:B a rdfs:Class ;
 
 example:b a rdf:Property ;
 	rdfs:domain example:A ;
-	rdfs:range example:B .
+	rdfs:range example:B ;
+	tracker:indexed true .
 
diff --git a/tests/libtracker-data/change/source/99-example.ontology.v3 b/tests/libtracker-data/change/source/99-example.ontology.v3
index 4c626bc..5048df1 100644
--- a/tests/libtracker-data/change/source/99-example.ontology.v3
+++ b/tests/libtracker-data/change/source/99-example.ontology.v3
@@ -31,4 +31,5 @@ example:i2 a rdf:Property ;
 example:single1 a rdf:Property ;
 	rdfs:domain example:A ;
 	rdfs:range xsd:integer ;
-	nrl:maxCardinality 1 .
+	nrl:maxCardinality 1 ;
+	tracker:indexed true .
diff --git a/tests/libtracker-data/change/source/99-example.ontology.v4 b/tests/libtracker-data/change/source/99-example.ontology.v4
index 706d77c..08b0a28 100644
--- a/tests/libtracker-data/change/source/99-example.ontology.v4
+++ b/tests/libtracker-data/change/source/99-example.ontology.v4
@@ -4,6 +4,7 @@
 @prefix tracker: <http://www.tracker-project.org/ontologies/tracker#> .
 @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
 @prefix nao: <http://www.semanticdesktop.org/ontologies/2007/08/15/nao#> .
+ prefix nrl: <http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#> .
 
 example: a tracker:Namespace, tracker:Ontology ;
 	nao:lastModified "2010-03-23T11:00:04Z" ;
@@ -27,6 +28,12 @@ example:i2 a rdf:Property ;
 	rdfs:domain example:A ;
 	rdfs:range xsd:integer .
 
+example:single1 a rdf:Property ;
+	rdfs:domain example:A ;
+	rdfs:range xsd:integer ;
+	nrl:maxCardinality 1 ;
+	tracker:indexed false .
+
 example:ib a rdf:Property ;
 	rdfs:domain example:B ;
 	rdfs:range xsd:integer .
diff --git a/tests/libtracker-data/change/updates/99-example.queries.v3 b/tests/libtracker-data/change/updates/99-example.queries.v3
index 62d1b07..45b4a55 100644
--- a/tests/libtracker-data/change/updates/99-example.queries.v3
+++ b/tests/libtracker-data/change/updates/99-example.queries.v3
@@ -4,6 +4,6 @@ insert { <a01> example:i1 2 }
 insert { <a01> example:i2 1 }
 delete { <a01> example:i2 1 }
 insert { <a01> example:i2 2 }
-insert { <a01> example:single1 1 }
+insert { <a01> example:single1 2 }
 delete { <a01> example:single1 1 }
 insert { <a01> example:single1 2 }



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