summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2017-07-05 10:56:46 +0200
committerCarlos Garnacho <carlosg@gnome.org>2017-08-05 21:52:00 +0200
commitc4444621d2ac363b2147648985048503c4db6c83 (patch)
treec04a513d8b082b114f95976e1e4c2ff5c1c275c1
parentf501b8b414b3fcf3c2e5e79adf270fb8b50b159f (diff)
downloadtracker-c4444621d2ac363b2147648985048503c4db6c83.tar.gz
libtracker-data: Add resource element triggers
Those will control the Refcount column in the Resource table, whenever a resource is added/removed from a resource or multivalued property table, or whenever a single or multivalued property points or stops pointing to a given resource, its refcount will be changed. This adds automatic refcounting on elements, so we can tell those with a refcount=0 are not referenced anywhere so thus can be dropped.
-rw-r--r--src/libtracker-data/tracker-data-manager.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 05d894745..c7bea50a0 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -2901,6 +2901,118 @@ schedule_copy (GPtrArray *schedule,
}
static void
+create_triggers_on_rowid (TrackerDBInterface *iface,
+ TrackerClass *klass,
+ TrackerProperty *property,
+ GError **error)
+{
+ GError *internal_error = NULL;
+ gchar *table_name;
+
+ if (property) {
+ table_name = g_strdup_printf ("%s_%s",
+ tracker_class_get_name (klass),
+ tracker_property_get_name (property));
+ } else {
+ table_name = g_strdup (tracker_class_get_name (klass));
+ }
+
+ tracker_db_interface_execute_query (iface, &internal_error,
+ "CREATE TRIGGER \"trigger_insert_%s\" "
+ "AFTER INSERT ON \"%s\" "
+ "FOR EACH ROW BEGIN "
+ "UPDATE Resource SET Refcount = Refcount + 1 WHERE Resource.rowid = NEW.ID;"
+ "END",
+ table_name, table_name);
+ if (internal_error) {
+ g_propagate_error (error, internal_error);
+ g_free (table_name);
+ return;
+ }
+
+ tracker_db_interface_execute_query (iface, &internal_error,
+ "CREATE TRIGGER \"trigger_delete_%s\" "
+ "AFTER DELETE ON \"%s\" "
+ "FOR EACH ROW BEGIN "
+ "UPDATE Resource SET Refcount = Refcount - 1 WHERE Resource.rowid = OLD.ID;"
+ "END",
+ table_name, table_name);
+ if (internal_error) {
+ g_propagate_error (error, internal_error);
+ g_free (table_name);
+ return;
+ }
+
+ g_free (table_name);
+}
+
+static void
+create_table_triggers (TrackerDataManager *manager,
+ TrackerDBInterface *iface,
+ TrackerClass *klass,
+ GError **error)
+{
+ const gchar *property_name;
+ TrackerProperty **properties, *property;
+ GError *internal_error = NULL;
+ guint i, n_props;
+
+ create_triggers_on_rowid (iface, klass, NULL, &internal_error);
+ if (internal_error) {
+ g_propagate_error (error, internal_error);
+ return;
+ }
+
+ properties = tracker_ontologies_get_properties (manager->ontologies, &n_props);
+
+ for (i = 0; i < n_props; i++) {
+ gboolean multivalued;
+ gchar *table_name;
+
+ property = properties[i];
+
+ if (tracker_property_get_domain (property) != klass ||
+ tracker_property_get_data_type (property) != TRACKER_PROPERTY_TYPE_RESOURCE)
+ continue;
+
+ property_name = tracker_property_get_name (property);
+ multivalued = tracker_property_get_multiple_values (property);
+
+ if (multivalued) {
+ create_triggers_on_rowid (iface, klass, property, &internal_error);
+ if (internal_error) {
+ g_propagate_error (error, internal_error);
+ return;
+ }
+
+ table_name = g_strdup_printf ("%s_%s",
+ tracker_class_get_name (klass),
+ property_name);
+ } else {
+ table_name = g_strdup (tracker_class_get_name (klass));
+ }
+
+ tracker_db_interface_execute_query (iface, &internal_error,
+ "CREATE TRIGGER \"trigger_update_%s_%s\" "
+ "AFTER UPDATE OF \"%s\" ON \"%s\" "
+ "FOR EACH ROW BEGIN "
+ "UPDATE Resource SET Refcount = Refcount + 1 WHERE Resource.rowid = NEW.\"%s\";"
+ "UPDATE Resource SET Refcount = Refcount - 1 WHERE Resource.rowid = OLD.\"%s\";"
+ "END",
+ tracker_class_get_name (klass),
+ property_name,
+ property_name, table_name,
+ property_name, property_name);
+ g_free (table_name);
+
+ if (internal_error) {
+ g_propagate_error (error, internal_error);
+ return;
+ }
+ }
+}
+
+static void
create_decomposed_metadata_tables (TrackerDataManager *manager,
TrackerDBInterface *iface,
TrackerClass *service,
@@ -2912,6 +3024,7 @@ create_decomposed_metadata_tables (TrackerDataManager *manager,
GString *create_sql = NULL;
GString *in_col_sql = NULL;
GString *sel_col_sql = NULL;
+ GString *trigger_sql = NULL;
TrackerProperty **properties, *property, **domain_indexes;
GSList *class_properties = NULL, *field_it;
gboolean main_class;
@@ -3203,6 +3316,9 @@ create_decomposed_metadata_tables (TrackerDataManager *manager,
tracker_db_interface_execute_query (iface, &internal_error,
"%s", create_sql->str);
+ if (!internal_error)
+ create_table_triggers (manager, iface, service, &internal_error);
+
if (internal_error) {
g_propagate_error (error, internal_error);
goto error_out;