[tracker/tracker-2.1] libtracker-data: Drop FTS table/view before ontology updates



commit fedb4d58557a5d34ab3fdd7869a05bd87aff7193
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Nov 8 12:40:36 2018 +0100

    libtracker-data: Drop FTS table/view before ontology updates
    
    Sqlite >= 3.25.0 got stricter 'alter table ... rename ...' behavior
    where the renaming affects all references to the table across the
    database. This is at odds with our fts_view view on schema updates
    due to ontology changes, as we first migrate (rename current table,
    create new one, insert previous content, drop old table) all resource
    tables before doing the FTS table/view updates. This causes rename
    failures due to the fts_view referencing the renamed and dropped
    tables.
    
    Change the ontology update code so we delete the FTS table/view
    before changing resource tables in case of FTS updates. This makes
    the behavior correct both before and after the Sqlite change.
    
    https://gitlab.gnome.org/GNOME/tracker/issues/40

 src/libtracker-data/tracker-data-manager.c        | 105 +++++++++++++++-------
 src/libtracker-data/tracker-db-interface-sqlite.c |   8 ++
 src/libtracker-data/tracker-db-interface-sqlite.h |   2 +
 src/libtracker-fts/tracker-fts.c                  |  32 ++++---
 src/libtracker-fts/tracker-fts.h                  |   2 +
 5 files changed, 107 insertions(+), 42 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index a752fcd55..f2addd0df 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -135,6 +135,12 @@ enum {
        N_PROPS
 };
 
+#if HAVE_TRACKER_FTS
+static gboolean tracker_data_manager_fts_changed (TrackerDataManager *manager);
+static void tracker_data_manager_update_fts (TrackerDataManager *manager,
+                                             TrackerDBInterface *iface);
+#endif
+
 static void tracker_data_manager_initable_iface_init (GInitableIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (TrackerDataManager, tracker_data_manager, G_TYPE_OBJECT,
@@ -3681,6 +3687,9 @@ tracker_data_ontology_import_into_db (TrackerDataManager  *manager,
        TrackerProperty **properties;
        guint i, n_props, n_classes;
        gboolean base_tables_altered = FALSE;
+#if HAVE_TRACKER_FTS
+       gboolean update_fts = FALSE;
+#endif
 
        iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
 
@@ -3691,6 +3700,15 @@ tracker_data_ontology_import_into_db (TrackerDataManager  *manager,
                return;
        }
 
+#if HAVE_TRACKER_FTS
+       if (in_update) {
+               update_fts = tracker_data_manager_fts_changed (manager);
+
+               if (update_fts)
+                       tracker_db_interface_sqlite_fts_delete_table (iface);
+       }
+#endif
+
        /* create tables */
        for (i = 0; i < n_classes; i++) {
                GError *internal_error = NULL;
@@ -3740,6 +3758,14 @@ tracker_data_ontology_import_into_db (TrackerDataManager  *manager,
                        }
                }
        }
+
+#if HAVE_TRACKER_FTS
+       if (update_fts) {
+               tracker_data_manager_update_fts (manager, iface);
+       } else {
+               tracker_data_manager_init_fts (iface, !in_update);
+       }
+#endif
 }
 
 static gint
@@ -3942,13 +3968,44 @@ load_ontologies_gvdb (TrackerDataManager  *manager,
 
 #if HAVE_TRACKER_FTS
 static gboolean
+tracker_data_manager_fts_changed (TrackerDataManager *manager)
+{
+       TrackerProperty **properties;
+       gboolean has_changed = FALSE;
+       guint i, len;
+
+       properties = tracker_ontologies_get_properties (manager->ontologies, &len);
+
+       for (i = 0; i < len; i++) {
+               TrackerClass *class;
+
+               if (tracker_property_get_fulltext_indexed (properties[i]) !=
+                   tracker_property_get_orig_fulltext_indexed (properties[i])) {
+                       has_changed |= TRUE;
+               }
+
+               if (!tracker_property_get_fulltext_indexed (properties[i])) {
+                       continue;
+               }
+
+               has_changed |= tracker_property_get_is_new (properties[i]);
+
+               /* We must also regenerate FTS if any table in the view
+                * updated its schema.
+                */
+               class = tracker_property_get_domain (properties[i]);
+               has_changed |= tracker_class_get_db_schema_changed (class);
+       }
+
+       return has_changed;
+}
+
+static void
 ontology_get_fts_properties (TrackerDataManager  *manager,
-                             gboolean             only_new,
                              GHashTable         **fts_properties,
                              GHashTable         **multivalued)
 {
        TrackerProperty **properties;
-       gboolean has_changed = FALSE;
        guint i, len;
 
        properties = tracker_ontologies_get_properties (manager->ontologies, &len);
@@ -3960,16 +4017,10 @@ ontology_get_fts_properties (TrackerDataManager  *manager,
                const gchar *name, *table_name;
                GList *list;
 
-               if (tracker_property_get_fulltext_indexed (properties[i]) !=
-                   tracker_property_get_orig_fulltext_indexed (properties[i])) {
-                       has_changed |= TRUE;
-               }
-
                if (!tracker_property_get_fulltext_indexed (properties[i])) {
                        continue;
                }
 
-               has_changed |= tracker_property_get_is_new (properties[i]);
                table_name = tracker_property_get_table_name (properties[i]);
                name = tracker_property_get_name (properties[i]);
                list = g_hash_table_lookup (*fts_properties, table_name);
@@ -3986,8 +4037,6 @@ ontology_get_fts_properties (TrackerDataManager  *manager,
                        list = g_list_append (list, (gpointer) name);
                }
        }
-
-       return has_changed;
 }
 
 static void
@@ -4001,29 +4050,36 @@ rebuild_fts_tokens (TrackerDataManager *manager,
        /* Update the stamp file */
        tracker_db_manager_tokenizer_update (manager->db_manager);
 }
-#endif
 
 gboolean
 tracker_data_manager_init_fts (TrackerDBInterface *iface,
                                gboolean            create)
 {
-#if HAVE_TRACKER_FTS
        GHashTable *fts_props, *multivalued;
        TrackerDataManager *manager;
 
        manager = tracker_db_interface_get_user_data (iface);
-       ontology_get_fts_properties (manager, FALSE, &fts_props, &multivalued);
+       ontology_get_fts_properties (manager, &fts_props, &multivalued);
        tracker_db_interface_sqlite_fts_init (iface, fts_props,
                                              multivalued, create);
        g_hash_table_unref (fts_props);
        g_hash_table_unref (multivalued);
        return TRUE;
-#else
-       g_info ("FTS support is disabled");
-       return FALSE;
-#endif
 }
 
+static void
+tracker_data_manager_update_fts (TrackerDataManager *manager,
+                                 TrackerDBInterface *iface)
+{
+       GHashTable *fts_properties, *multivalued;
+
+       ontology_get_fts_properties (manager, &fts_properties, &multivalued);
+       tracker_db_interface_sqlite_fts_alter_table (iface, fts_properties, multivalued);
+       g_hash_table_unref (fts_properties);
+       g_hash_table_unref (multivalued);
+}
+#endif
+
 GFile *
 tracker_data_manager_get_cache_location (TrackerDataManager *manager)
 {
@@ -4279,8 +4335,6 @@ tracker_data_manager_initable_init (GInitable     *initable,
                tracker_data_ontology_import_into_db (manager, FALSE,
                                                      &internal_error);
 
-               tracker_data_manager_init_fts (iface, TRUE);
-
                if (internal_error) {
                        g_propagate_error (error, internal_error);
                        return FALSE;
@@ -4371,7 +4425,9 @@ tracker_data_manager_initable_init (GInitable     *initable,
                        }
                }
 
+#if HAVE_TRACKER_FTS
                tracker_data_manager_init_fts (iface, FALSE);
+#endif
        }
 
        if (!read_only) {
@@ -4630,17 +4686,6 @@ tracker_data_manager_initable_init (GInitable     *initable,
                        }
 
                        if (update_nao) {
-#if HAVE_TRACKER_FTS
-                               GHashTable *fts_properties, *multivalued;
-
-                               if (ontology_get_fts_properties (manager, TRUE, &fts_properties, 
&multivalued)) {
-                                       tracker_db_interface_sqlite_fts_alter_table (iface, fts_properties, 
multivalued);
-                               }
-
-                               g_hash_table_unref (fts_properties);
-                               g_hash_table_unref (multivalued);
-#endif
-
                                update_ontology_last_modified (manager, iface, ontology, &n_error);
 
                                if (n_error) {
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.c 
b/src/libtracker-data/tracker-db-interface-sqlite.c
index 079be7a1c..08c83a872 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.c
+++ b/src/libtracker-data/tracker-db-interface-sqlite.c
@@ -1647,6 +1647,14 @@ tracker_db_interface_sqlite_fts_init (TrackerDBInterface  *db_interface,
 
 #if HAVE_TRACKER_FTS
 
+void
+tracker_db_interface_sqlite_fts_delete_table (TrackerDBInterface  *db_interface)
+{
+       if (!tracker_fts_delete_table (db_interface->db, "fts5")) {
+               g_critical ("Failed to delete FTS table");
+       }
+}
+
 void
 tracker_db_interface_sqlite_fts_alter_table (TrackerDBInterface  *db_interface,
                                             GHashTable          *properties,
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.h 
b/src/libtracker-data/tracker-db-interface-sqlite.h
index 49fab3c17..e83acc13b 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.h
+++ b/src/libtracker-data/tracker-db-interface-sqlite.h
@@ -59,6 +59,8 @@ gboolean            tracker_db_interface_sqlite_wal_checkpoint         (TrackerD
 
 
 #if HAVE_TRACKER_FTS
+void                tracker_db_interface_sqlite_fts_delete_table       (TrackerDBInterface       *interface);
+
 void                tracker_db_interface_sqlite_fts_alter_table        (TrackerDBInterface       *interface,
                                                                         GHashTable               *properties,
                                                                         GHashTable               
*multivalued);
diff --git a/src/libtracker-fts/tracker-fts.c b/src/libtracker-fts/tracker-fts.c
index 3c550ca41..49ba4d362 100644
--- a/src/libtracker-fts/tracker-fts.c
+++ b/src/libtracker-fts/tracker-fts.c
@@ -157,6 +157,26 @@ tracker_fts_create_table (sqlite3    *db,
        return (rc == SQLITE_OK);
 }
 
+gboolean
+tracker_fts_delete_table (sqlite3 *db,
+                          gchar   *table_name)
+{
+       gchar *query;
+       int rc;
+
+       query = g_strdup_printf ("DROP VIEW fts_view");
+       rc = sqlite3_exec (db, query, NULL, NULL, NULL);
+       g_free (query);
+
+       if (rc == SQLITE_OK) {
+               query = g_strdup_printf ("DROP TABLE %s", table_name);
+               sqlite3_exec (db, query, NULL, NULL, NULL);
+               g_free (query);
+       }
+
+       return rc == SQLITE_OK;
+}
+
 gboolean
 tracker_fts_alter_table (sqlite3    *db,
                         gchar      *table_name,
@@ -168,18 +188,6 @@ tracker_fts_alter_table (sqlite3    *db,
 
        tmp_name = g_strdup_printf ("%s_TMP", table_name);
 
-       query = g_strdup_printf ("DROP VIEW fts_view");
-       rc = sqlite3_exec (db, query, NULL, NULL, NULL);
-       g_free (query);
-
-       query = g_strdup_printf ("DROP TABLE %s", tmp_name);
-       rc = sqlite3_exec (db, query, NULL, NULL, NULL);
-       g_free (query);
-
-       query = g_strdup_printf ("DROP TABLE %s", table_name);
-       rc = sqlite3_exec (db, query, NULL, NULL, NULL);
-       g_free (query);
-
        if (!tracker_fts_create_table (db, tmp_name, tables, grouped_columns)) {
                g_free (tmp_name);
                return FALSE;
diff --git a/src/libtracker-fts/tracker-fts.h b/src/libtracker-fts/tracker-fts.h
index 751014f38..3bda8cf98 100644
--- a/src/libtracker-fts/tracker-fts.h
+++ b/src/libtracker-fts/tracker-fts.h
@@ -36,6 +36,8 @@ gboolean    tracker_fts_create_table     (sqlite3    *db,
                                           gchar      *table_name,
                                           GHashTable *tables,
                                           GHashTable *grouped_columns);
+gboolean    tracker_fts_delete_table     (sqlite3    *db,
+                                          gchar      *table_name);
 gboolean    tracker_fts_alter_table      (sqlite3    *db,
                                           gchar      *table_name,
                                           GHashTable *tables,


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