diff --git a/src/libtracker-common/tracker-service.c b/src/libtracker-common/tracker-service.c index 3f28fb4..f4364bc 100644 --- a/src/libtracker-common/tracker-service.c +++ b/src/libtracker-common/tracker-service.c @@ -39,6 +39,7 @@ struct _TrackerServicePriv { gchar *property_prefix; gchar *content_metadata; GSList *key_metadata; + GHashTable *changed_columns; TrackerDBType db_type; @@ -53,6 +54,7 @@ struct _TrackerServicePriv { gboolean show_service_directories; }; + static void service_finalize (GObject *object); static void service_get_property (GObject *object, guint param_id, @@ -251,6 +253,10 @@ service_finalize (GObject *object) priv = GET_PRIV (object); + if (priv->changed_columns) { + g_critical ("We have unfinished column changes, this should never happen"); + } + g_free (priv->name); g_free (priv->parent); g_free (priv->content_metadata); @@ -259,6 +265,7 @@ service_finalize (GObject *object) g_slist_foreach (priv->key_metadata, (GFunc) g_free, NULL); g_slist_free (priv->key_metadata); + (G_OBJECT_CLASS (tracker_service_parent_class)->finalize) (object); } @@ -838,3 +845,52 @@ tracker_service_set_show_service_directories (TrackerService *service, g_object_notify (G_OBJECT (service), "show-service-directories"); } +void +tracker_service_add_column_change (TrackerService *service, + const gchar *column, + const gchar *value) +{ + TrackerServicePriv *priv; + + g_return_if_fail (TRACKER_IS_SERVICE (service)); + + priv = GET_PRIV (service); + + if (!priv->changed_columns) { + priv->changed_columns = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + } + + g_hash_table_replace (priv->changed_columns, + g_strdup (column), + g_strdup (value)); + +} + +GHashTable* +tracker_service_get_column_changes (TrackerService *service) +{ + TrackerServicePriv *priv; + + g_return_val_if_fail (TRACKER_IS_SERVICE (service), NULL); + + priv = GET_PRIV (service); + + return priv->changed_columns; +} + +void +tracker_service_unset_column_changes(TrackerService *service) +{ + TrackerServicePriv *priv; + + g_return_if_fail (TRACKER_IS_SERVICE (service)); + + priv = GET_PRIV (service); + + g_hash_table_unref (priv->changed_columns); + priv->changed_columns = NULL; +} + diff --git a/src/libtracker-common/tracker-service.h b/src/libtracker-common/tracker-service.h index 849a788..a1a8835 100644 --- a/src/libtracker-common/tracker-service.h +++ b/src/libtracker-common/tracker-service.h @@ -65,6 +65,9 @@ struct _TrackerServiceClass { GObjectClass parent_class; }; +typedef void (*TrackerServiceColumnChanger) (guint service_id, + GHashTable *changes); + GType tracker_service_get_type (void) G_GNUC_CONST; TrackerService *tracker_service_new (void); @@ -113,6 +116,12 @@ void tracker_service_set_show_service_files (TrackerService *service, void tracker_service_set_show_service_directories (TrackerService *service, gboolean value); +void tracker_service_add_column_change (TrackerService *service, + const gchar *column, + const gchar *value); +GHashTable* tracker_service_get_column_changes (TrackerService *service); +void tracker_service_unset_column_changes (TrackerService *service); + G_END_DECLS #endif /* __LIBTRACKER_COMMON_SERVICE_H__ */ diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c index e3f1fef..12caa08 100644 --- a/src/libtracker-data/tracker-data-update.c +++ b/src/libtracker-data/tracker-data-update.c @@ -322,6 +322,7 @@ tracker_data_update_delete_all_metadata (TrackerService *service, g_free (service_id_str); } + void tracker_data_update_set_metadata (TrackerService *service, guint32 service_id, @@ -391,38 +392,36 @@ tracker_data_update_set_metadata (TrackerService *service, tracker_field_get_name (field)); if (metadata_key > 0) { gchar *val; + gchar *column = g_strdup_printf ("KeyMetadata%d", metadata_key); val = tracker_escape_string (value); + tracker_service_add_column_change (service, column, val); - tracker_db_interface_execute_query (iface, NULL, - "update Services set KeyMetadata%d = '%s' where id = %d", - metadata_key, - val, - service_id); g_free (val); + g_free (column); + } else if (tracker_field_get_data_type (field) == TRACKER_FIELD_TYPE_DATE && (strcmp (tracker_field_get_name (field), "File:Modified") == 0)) { + gchar *val = tracker_escape_string (value); /* Handle mtime */ - tracker_db_interface_execute_query (iface, NULL, - "update Services set IndexTime = '%s' where ID = %d", - value, - service_id); + tracker_service_add_column_change (service, "IndexTime", val); + g_free (val); } collate_key = tracker_ontology_service_get_key_collate (tracker_service_get_name (service), tracker_field_get_name (field)); if (collate_key > 0) { - gchar *val; - - val = tracker_escape_string (value); - - tracker_db_interface_execute_query (iface, NULL, - "update Services set KeyMetadataCollation%d = CollateKey('%s') where id = %d", - collate_key, - val, - service_id); + gchar *vala, *valb; + gchar *column = g_strdup_printf ("KeyMetadataCollation%d", collate_key); - g_free (val); + vala = tracker_escape_string (value); + valb = g_strdup_printf ("CollateKey('%s')", vala); + + tracker_service_add_column_change (service, column, valb); + + g_free (vala); + g_free (column); + g_free (valb); } g_free (id_str); @@ -872,3 +871,60 @@ tracker_data_update_disable_all_volumes (void) NULL); } + +void +tracker_data_update_change_columns (TrackerService *service, + guint32 service_id, + GHashTable *changes) +{ + GString *update_query; + GHashTableIter iter; + gpointer key, value; + gboolean first = TRUE; + TrackerDBInterface *iface; + GError *error = NULL; + + if (!changes) { + /* This is just a noop, no changes */ + return; + } + + iface = tracker_db_manager_get_db_interface_by_type (tracker_service_get_name (service), + TRACKER_DB_CONTENT_TYPE_METADATA); + + update_query = g_string_new ("UPDATE Services SET "); + + g_hash_table_iter_init (&iter, changes); + + while (g_hash_table_iter_next (&iter, &key, &value)) { + const gchar *column = key; + const gchar *val = value; + + if (first) { + g_string_append_printf (update_query, + "%s = '%s'", + column, + val); + } else { + g_string_append_printf (update_query, + ", %s = '%s'", + column, + val); + } + + first = FALSE; + } + + g_string_append_printf (update_query, " WHERE ID = %d", + service_id); + + /* g_debug ("UPDATE: %s\n", update_query->str); */ + tracker_db_interface_execute_query (iface, &error, "%s", update_query->str); + + if (!error) { + g_warning ("%s", error->message); + g_clear_error (&error); + } + + g_string_free (update_query, TRUE); +} diff --git a/src/libtracker-data/tracker-data-update.h b/src/libtracker-data/tracker-data-update.h index 90cc12a..e45f785 100644 --- a/src/libtracker-data/tracker-data-update.h +++ b/src/libtracker-data/tracker-data-update.h @@ -88,6 +88,9 @@ void tracker_data_update_enable_volume (const gchar *ud void tracker_data_update_disable_volume (const gchar *udi); void tracker_data_update_disable_all_volumes (void); void tracker_data_update_reset_volume (guint32 volume_id); +void tracker_data_update_change_columns (TrackerService *service, + guint32 service_id, + GHashTable *changes); G_END_DECLS diff --git a/src/tracker-indexer/tracker-indexer.c b/src/tracker-indexer/tracker-indexer.c index 0aec6bc..70efb86 100644 --- a/src/tracker-indexer/tracker-indexer.c +++ b/src/tracker-indexer/tracker-indexer.c @@ -1199,6 +1199,8 @@ index_metadata_item (TrackerField *field, } if (data->add) { + /* index_metadata from index_metadata_foreach who called us does + * the required tracker_data_update_change_columns call) */ tracker_data_update_set_metadata (data->service, data->id, field, (gchar *) value, parsed_value); } else { tracker_data_update_delete_metadata (data->service, data->id, field, (gchar *) value); @@ -1249,6 +1251,7 @@ index_metadata (TrackerIndexer *indexer, { MetadataForeachData data; gint service_id; + GHashTable *changes; service_id = tracker_service_get_id (service); @@ -1262,6 +1265,10 @@ index_metadata (TrackerIndexer *indexer, tracker_module_metadata_foreach (metadata, index_metadata_foreach, &data); + changes = tracker_service_get_column_changes (service); + tracker_data_update_change_columns (service, id, changes); + tracker_service_unset_column_changes (service); + schedule_flush (indexer, FALSE); } @@ -2291,6 +2298,7 @@ handle_metadata_add (TrackerIndexer *indexer, gchar **old_contents; gint len; gboolean exists, enabled; + GHashTable *changes; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -2393,6 +2401,10 @@ handle_metadata_add (TrackerIndexer *indexer, set_values [++j] = values[i]; } + changes = tracker_service_get_column_changes (service); + tracker_data_update_change_columns (service, service_id, changes); + tracker_service_unset_column_changes (service); + joined = g_strjoinv (" ", set_values); if (tracker_field_get_filtered (field)) { index_text_no_parsing (indexer,