Commit fedb4d58 authored by Carlos Garnacho's avatar Carlos Garnacho

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.

#40
parent 3cbfaa5b
Pipeline #39618 failed with stage
in 8 minutes and 48 seconds
......@@ -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) {
......
......@@ -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,
......
......@@ -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);
......
......@@ -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;
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment