diff --git a/data/sqlite-tracker.sql b/data/sqlite-tracker.sql index f49f17e..9c80ce1 100644 --- a/data/sqlite-tracker.sql +++ b/data/sqlite-tracker.sql @@ -1,6 +1,6 @@ CREATE TABLE Options ( - OptionKey Text COLLATE NOCASE not null, + OptionKey Text PRIMARY KEY, OptionValue Text COLLATE NOCASE ); diff --git a/src/trackerd/trackerd.c b/src/trackerd/trackerd.c index d0e24aa..68e89bf 100644 --- a/src/trackerd/trackerd.c +++ b/src/trackerd/trackerd.c @@ -2490,6 +2490,73 @@ create_index (gboolean need_data) } +/* Fix LP: bug #324364 and bug #324300 + On a per-user basis a one-time correction of the current Options table in + ~/.local/share/tracker/data/common.db is required. + */ +static void +tracker_db_fix_table_options(void) +{ + char ***result; + char **row; + char *column; + + const char *szcSQL[] = { + "SELECT sql FROM sqlite_master WHERE type='table' AND tbl_name='Options';", + "CREATE TABLE Options_New (OptionKey PRIMARY KEY, OptionValue Text COLLATE NOCASE);", + "DELETE FROM Options WHERE OptionValue='IntegrityCheck';", + "INSERT INTO Options_New (OptionKey, OptionValue) SELECT OptionKey, OptionValue FROM Options;", + "ALTER TABLE Options RENAME TO Options_Bad;", + "ALTER TABLE Options_New RENAME TO Options;", + "DROP TABLE Options_Bad;" + } + enum sql { + SQL_GET_SCHEMA, + SQL_CREATE_NEW_TABLE, + SQL_DELETE_BAD_ENTRIES, + SQL_COPY_GOOD_ENTRIES, + SQL_RENAME_BAD_TABLE, + SQL_RENAME_NEW_TABLE, + SQL_DELETE_BAD_TABLE + }; + + DBConnection *db_con = tracker_db_connect_common(); + + tracker_log ("Checking Options table for bad schema (see LP: bug #324364 and #324300"); + /* Use these functions to execute raw SQL: + gboolean tracker_db_exec_no_reply(DBConnection *db_con, const char *query) + char ***tracker_exec_sql(DBConnection *db_con, const char *query) + */ + + result = tracker_exec_sql(db_con, szcSQL[SQL_GET_SCHEMA]); + /* Bad table: + CREATE TABLE Options ( + OptionKey Text COLLATE NOCASE not null, + OptionValue Text COLLATE NOCASE + ) + */ + + if (result) { + tracker_log ("Found bad Options table schema"); + row = tracker_db_get_row(result, 0); + /* A bad schema definition will not contain "PRIMARY KEY" */ + if (row && row[0] && !strstr(row[0], "PRIMARY KEY") { + if (tracker_db_exec_no_reply(db_con, szcSQL[SQL_CREATE_NEW_TABLE) && + tracker_db_exec_no_reply(db_con, szcSQL[SQL_DELETE_BAD_ENTRIES] && + tracker_db_exec_no_reply(db_con, szcSQL[SQL_COPY_GOOD_ENTRIES] && + tracker_db_exec_no_reply(db_con, szcSQL[SQL_RENAME_BAD_TABLE])) { + tracker_db_exec_no_reply(db_con, szcSQL[SQL_RENAME_NEW_TABLE]); + tracker_db_exec_no_reply(db_con, szcSQL[SQL_DELETE_BAD_TABLE]); + tracker_log ("Replaced Options table schema and cleaned entries"); + } + } + tracker_db_free_result(result); + } + + tracker_db_close(db_con); + g_free(db_con); +} + gint main (gint argc, gchar *argv[]) { @@ -2827,6 +2894,10 @@ main (gint argc, gchar *argv[]) tracker->first_time_index = FALSE; } + /* LP: bug #324364 */ + if (!tracker->readonly) { + tracker_db_fix_table_options(); + } db_con = tracker_db_connect (); db_con->thread = "main";