[tracker/fts4: 19/26] Use fts4 external content tables on Tracker FTS



commit 6460779dc792878807cb7921cfc9d946868429e0
Author: Carlos Garnacho <carlos lanedo com>
Date:   Mon Jan 28 17:20:05 2013 +0100

    Use fts4 external content tables on Tracker FTS
    
    FTS support on Tracker is now implemented using external content
    support available in sqlite >= 3.7.9 FTS4.
    
    FTS tables created this way fetch data from a single table/view,
    for this purpose an intermediate view has been created to
    interface with the FTS table. As this view is mainly queried by
    ID (both when populating the FTS contents, and when querying
    throught the FTS table), queries are fast enough on it.
    
    As FTS indirectly points to the data on the real tables where tracker
    data is stored, strings themselves are stored only once in the database,
    so there is no impact in database size when compared to the previous
    custom FTS code. Performance had little changes too from testing.

 src/libtracker-data/tracker-data-manager.c        |  109 +++++++------
 src/libtracker-data/tracker-data-manager.h        |    3 +
 src/libtracker-data/tracker-db-interface-sqlite.c |  128 ++++++++++------
 src/libtracker-data/tracker-db-interface-sqlite.h |    7 +-
 src/libtracker-data/tracker-db-manager.c          |    3 +-
 src/libtracker-fts/tracker-fts.c                  |  174 ++++++++------------
 src/libtracker-fts/tracker-fts.h                  |   13 +-
 7 files changed, 229 insertions(+), 208 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index c8b2f9e..4ff890e 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -3583,54 +3583,76 @@ load_ontologies_gvdb (GError **error)
 }
 
 #if HAVE_TRACKER_FTS
-static gint
-compare_fts_property_ids (gconstpointer a,
-                          gconstpointer b)
-{
-	TrackerProperty *pa, *pb;
-
-	pa = (TrackerProperty *) a;
-	pb = (TrackerProperty *) b;
-
-	return tracker_property_get_id (pa) - tracker_property_get_id (pb);
-}
-
-static const gchar **
-ontology_get_fts_properties (gboolean only_new)
+static gboolean
+ontology_get_fts_properties (gboolean     only_new,
+			     GHashTable **fts_properties,
+			     GHashTable **multivalued)
 {
 	TrackerProperty **properties;
-	GList *fts_props = NULL, *l;
-	const gchar **prop_names;
+	gboolean has_new = FALSE;
+	GHashTable *hashtable;
 	guint i, len;
 
 	properties = tracker_ontologies_get_properties (&len);
+	hashtable = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+					   (GDestroyNotify) g_list_free);
+
+	if (multivalued) {
+		*multivalued = g_hash_table_new (g_str_hash, g_str_equal);
+	}
 
 	for (i = 0; i < len; i++) {
-		if (only_new && !tracker_property_get_is_new (properties[i])) {
+		const gchar *name, *table_name;
+		GList *list;
+
+		if (!tracker_property_get_fulltext_indexed (properties[i])) {
 			continue;
 		}
 
-		if (tracker_property_get_fulltext_indexed (properties[i])) {
-			/* Sort them by ID */
-			fts_props =
-				g_list_insert_sorted (fts_props, properties[i],
-						      (GCompareFunc) compare_fts_property_ids);
+		has_new |= tracker_property_get_is_new (properties[i]);
+
+		if (multivalued &&
+		    tracker_property_get_multiple_values (properties[i])) {
+			g_hash_table_insert (*multivalued, (gpointer) table_name,
+					     GUINT_TO_POINTER (TRUE));
 		}
-	}
 
-	prop_names = g_new0 (const gchar *, g_list_length (fts_props) + 1);
+		table_name = tracker_property_get_table_name (properties[i]);
+		name = tracker_property_get_name (properties[i]);
+		list = g_hash_table_lookup (hashtable, table_name);
 
-	for (l = fts_props, i = 0; l; l = l->next, i++) {
-		prop_names[i] = tracker_property_get_name (l->data);
+		if (!list) {
+			list = g_list_prepend (NULL, (gpointer) name);
+			g_hash_table_insert (hashtable, (gpointer) table_name, list);
+		} else {
+			list = g_list_append (list, (gpointer) name);
+		}
 	}
 
-	g_list_free (fts_props);
+	if (fts_properties) {
+		*fts_properties = hashtable;
+	}
 
-	return prop_names;
+	return has_new;
 }
 #endif
 
 gboolean
+tracker_data_manager_init_fts (TrackerDBInterface *iface,
+                               gboolean            create)
+{
+#if HAVE_TRACKER_FTS
+	GHashTable *fts_props, *multivalued;
+
+	ontology_get_fts_properties (FALSE, &fts_props, &multivalued);
+	tracker_db_interface_sqlite_fts_init (iface, fts_props,
+	                                      multivalued, create);
+	g_hash_table_destroy (fts_props);
+	g_hash_table_destroy (multivalued);
+#endif
+}
+
+gboolean
 tracker_data_manager_init (TrackerDBManagerFlags   flags,
                            const gchar           **test_schemas,
                            gboolean               *first_time,
@@ -3807,10 +3829,6 @@ tracker_data_manager_init (TrackerDBManagerFlags   flags,
 #endif /* DISABLE_JOURNAL */
 
 	if (is_first_time_index && !read_only) {
-#if HAVE_TRACKER_FTS
-		const gchar **fts_props;
-#endif
-
 		sorted = get_ontologies (test_schemas != NULL, ontologies_dir);
 
 #ifndef DISABLE_JOURNAL
@@ -3899,15 +3917,13 @@ tracker_data_manager_init (TrackerDBManagerFlags   flags,
 			return FALSE;
 		}
 
-#if HAVE_TRACKER_FTS
-		fts_props = ontology_get_fts_properties (FALSE);
-		tracker_db_interface_sqlite_fts_init (iface, fts_props, TRUE);
-		g_free (fts_props);
-#endif
-
 		tracker_data_ontology_import_into_db (FALSE,
 		                                      &internal_error);
 
+#if HAVE_TRACKER_FTS
+		tracker_data_manager_init_fts (iface, TRUE);
+#endif
+
 		if (internal_error) {
 			g_propagate_error (error, internal_error);
 
@@ -4050,10 +4066,7 @@ tracker_data_manager_init (TrackerDBManagerFlags   flags,
 			}
 		}
 
-#if HAVE_TRACKER_FTS
-		/* This is a no-op when FTS is disabled */
-		tracker_db_interface_sqlite_fts_init (iface, NULL, FALSE);
-#endif
+		tracker_data_manager_init_fts (iface, FALSE);
 	}
 
 	if (check_ontology) {
@@ -4345,14 +4358,14 @@ tracker_data_manager_init (TrackerDBManagerFlags   flags,
 
 			if (update_nao) {
 #if HAVE_TRACKER_FTS
-				const gchar **new_fts_properties;
+				GHashTable *fts_properties, *multivalued;
 
-				new_fts_properties = ontology_get_fts_properties (TRUE);
-
-				if (new_fts_properties) {
-					tracker_db_interface_sqlite_fts_alter_table (iface, new_fts_properties, NULL);
-					g_free (new_fts_properties);
+				if (ontology_get_fts_properties (TRUE, &fts_properties, &multivalued)) {
+					tracker_db_interface_sqlite_fts_alter_table (iface, fts_properties, multivalued);
 				}
+
+				g_hash_table_destroy (fts_properties);
+				g_hash_table_destroy (multivalued);
 #endif
 
 				/* Update the nao:lastModified in the database */
diff --git a/src/libtracker-data/tracker-data-manager.h b/src/libtracker-data/tracker-data-manager.h
index 6aa21ea..bd82feb 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -63,6 +63,9 @@ gboolean tracker_data_manager_reload                 (TrackerBusyCallback     bu
                                                       const gchar            *busy_operation,
                                                       GError                **error);
 
+gboolean tracker_data_manager_init_fts               (TrackerDBInterface     *interface,
+						      gboolean                create);
+
 G_END_DECLS
 
 #endif /* __LIBTRACKER_DATA_MANAGER_H__ */
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.c b/src/libtracker-data/tracker-db-interface-sqlite.c
index ed27b55..a094669 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.c
+++ b/src/libtracker-data/tracker-db-interface-sqlite.c
@@ -94,6 +94,8 @@ struct TrackerDBInterface {
 	TrackerBusyCallback busy_callback;
 	gpointer busy_user_data;
 	gchar *busy_status;
+
+	gchar *fts_insert_str;
 };
 
 struct TrackerDBInterfaceClass {
@@ -991,28 +993,89 @@ close_database (TrackerDBInterface *db_interface)
 	}
 }
 
+static gchar **
+_fts_create_properties (GHashTable *properties)
+{
+	GHashTableIter iter;
+	GPtrArray *cols;
+	GList *columns;
+	gchar *table;
+
+	if (g_hash_table_size (properties) == 0) {
+		return NULL;
+	}
+
+	g_hash_table_iter_init (&iter, properties);
+	cols = g_ptr_array_new ();
+
+	while (g_hash_table_iter_next (&iter, (gpointer *) &table,
+				       (gpointer *) &columns)) {
+		while (columns) {
+			g_ptr_array_add (cols, g_strdup (columns->data));
+			columns = columns->next;
+		}
+	}
+
+	g_ptr_array_add (cols, NULL);
+
+	return (gchar **) g_ptr_array_free (cols, FALSE);
+}
+
 void
 tracker_db_interface_sqlite_fts_init (TrackerDBInterface  *db_interface,
-                                      const gchar        **columns,
+                                      GHashTable          *properties,
+                                      GHashTable          *multivalued,
                                       gboolean             create)
 {
 #if HAVE_TRACKER_FTS
+	GStrv fts_columns = NULL;
+
 	tracker_fts_init_db (db_interface->db);
 
+	if (properties) {
+		fts_columns = _fts_create_properties (properties);
+	}
+
 	if (create &&
-	    !tracker_fts_create_table (db_interface->db, "fts", columns)) {
+	    !tracker_fts_create_table (db_interface->db, "fts",
+				       properties, multivalued)) {
 		g_warning ("FTS tables creation failed");
 	}
+
+	if (fts_columns) {
+		GString *insert, *select;
+		gint i = 0;
+
+		insert = g_string_new ("INSERT INTO fts (docid");
+		select = g_string_new ("SELECT rowid");
+
+		while (fts_columns[i]) {
+			g_string_append_printf (insert, ", \"%s\"",
+						fts_columns[i]);
+			g_string_append_printf (select, ", \"%s\"",
+						fts_columns[i]);
+			i++;
+		}
+
+		g_string_append (select, " FROM fts_view WHERE rowid=?");
+		g_string_append (insert, ") ");
+		g_string_append (insert, select->str);
+
+		g_string_free (select, TRUE);
+		db_interface->fts_insert_str = g_string_free (insert, FALSE);
+
+		g_strfreev (fts_columns);
+	}
 #endif
 }
 
 #if HAVE_TRACKER_FTS
 void
 tracker_db_interface_sqlite_fts_alter_table (TrackerDBInterface  *db_interface,
-					     const gchar        **added_columns,
-					     const gchar        **removed_columns)
+					     GHashTable          *properties,
+					     GHashTable          *multivalued)
 {
-	if (!tracker_fts_alter_table (db_interface->db, "fts", added_columns, removed_columns)) {
+	if (!tracker_fts_alter_table (db_interface->db, "fts", properties, multivalued)) {
 		g_critical ("Failed to update FTS columns");
 	}
 }
@@ -1026,40 +1089,27 @@ tracker_db_interface_sqlite_fts_update_text (TrackerDBInterface  *db_interface,
 {
 	TrackerDBStatement *stmt;
 	GError *error = NULL;
-	GString *query;
-	gint i;
-
-	if (create) {
-		query = g_string_new ("INSERT INTO fts (docid");
-
-		for (i = 0; properties[i] != NULL; i++) {
-			g_string_append_printf (query, ", \"%s\"", properties[i]);
-		}
-
-		g_string_append (query, ") VALUES (?");
 
-		for (i = 0; properties[i] != NULL; i++) {
-			g_string_append (query, ", ?");
-		}
+	if (!create) {
+		stmt = tracker_db_interface_create_statement (db_interface,
+							      TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE,
+							      &error,
+							      "DELETE FROM fts WHERE docid=?");
+		tracker_db_statement_bind_int (stmt, 0, id);
 
-		g_string_append_c (query, ')');
-	} else {
-		query = g_string_new ("UPDATE fts SET ");
+		tracker_db_statement_execute (stmt, &error);
+		g_object_unref (stmt);
 
-		for (i = 0; properties[i] != NULL; i++) {
-			if (i != 0) {
-				g_string_append_c (query, ',');
-			}
-			g_string_append_printf (query, "\"%s\" = ?", properties[i]);
+		if (error) {
+			g_warning ("Could not update FTS text: %s", error->message);
+			g_error_free (error);
+			return FALSE;
 		}
-
-		g_string_append (query, " WHERE docid = ?");
 	}
 
 	stmt = tracker_db_interface_create_statement (db_interface,
 	                                              TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE,
-	                                              &error, query->str);
-	g_string_free (query, TRUE);
+	                                              &error, db_interface->fts_insert_str);
 
 	if (!stmt || error) {
 		if (error) {
@@ -1070,20 +1120,7 @@ tracker_db_interface_sqlite_fts_update_text (TrackerDBInterface  *db_interface,
 		return FALSE;
 	}
 
-	if (create) {
-		tracker_db_statement_bind_int (stmt, 0, id);
-
-		for (i = 0; properties[i] != NULL; i++) {
-			tracker_db_statement_bind_text (stmt, i + 1, text[i]);
-		}
-	} else {
-		for (i = 0; properties[i] != NULL; i++) {
-			tracker_db_statement_bind_text (stmt, i, text[i]);
-		}
-
-		tracker_db_statement_bind_int (stmt, i, id);
-	}
-
+	tracker_db_statement_bind_int (stmt, 0, id);
 	tracker_db_statement_execute (stmt, &error);
 	g_object_unref (stmt);
 
@@ -1184,6 +1221,7 @@ tracker_db_interface_sqlite_finalize (GObject *object)
 	db_interface = TRACKER_DB_INTERFACE (object);
 
 	close_database (db_interface);
+	g_free (db_interface->fts_insert_str);
 
 	g_message ("Closed sqlite3 database:'%s'", db_interface->filename);
 
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.h b/src/libtracker-data/tracker-db-interface-sqlite.h
index f0e2d90..548814a 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.h
+++ b/src/libtracker-data/tracker-db-interface-sqlite.h
@@ -41,7 +41,8 @@ TrackerDBInterface *tracker_db_interface_sqlite_new_ro                 (const gc
 gint64              tracker_db_interface_sqlite_get_last_insert_id     (TrackerDBInterface       *interface);
 void                tracker_db_interface_sqlite_enable_shared_cache    (void);
 void                tracker_db_interface_sqlite_fts_init               (TrackerDBInterface       *interface,
-                                                                        const gchar             **columns,
+                                                                        GHashTable               *properties,
+                                                                        GHashTable               *multivalued,
                                                                         gboolean                  create);
 void                tracker_db_interface_sqlite_reset_collator         (TrackerDBInterface       *interface);
 void                tracker_db_interface_sqlite_wal_hook               (TrackerDBInterface       *interface,
@@ -49,8 +50,8 @@ void                tracker_db_interface_sqlite_wal_hook               (TrackerD
 
 #if HAVE_TRACKER_FTS
 void                tracker_db_interface_sqlite_fts_alter_table        (TrackerDBInterface       *interface,
-                                                                        const gchar             **added_columns,
-                                                                        const gchar             **removed_columns);
+                                                                        GHashTable               *properties,
+                                                                        GHashTable               *multivalued);
 int                 tracker_db_interface_sqlite_fts_update_text        (TrackerDBInterface       *interface,
                                                                         int                       id,
                                                                         const gchar             **properties,
diff --git a/src/libtracker-data/tracker-db-manager.c b/src/libtracker-data/tracker-db-manager.c
index ab59148..67cabc4 100644
--- a/src/libtracker-data/tracker-db-manager.c
+++ b/src/libtracker-data/tracker-db-manager.c
@@ -1522,8 +1522,7 @@ tracker_db_manager_get_db_interface (void)
 			return NULL;
 		}
 
-		tracker_db_interface_sqlite_fts_init (interface, NULL, FALSE);
-
+		tracker_data_manager_init_fts (interface, FALSE);
 
 		tracker_db_interface_set_max_stmt_cache_size (interface,
 		                                              TRACKER_DB_STATEMENT_CACHE_TYPE_SELECT,
diff --git a/src/libtracker-fts/tracker-fts.c b/src/libtracker-fts/tracker-fts.c
index 6c8afa7..18c4876 100644
--- a/src/libtracker-fts/tracker-fts.c
+++ b/src/libtracker-fts/tracker-fts.c
@@ -236,154 +236,120 @@ tracker_fts_init_db (sqlite3 *db) {
 }
 
 gboolean
-tracker_fts_create_table (sqlite3  *db,
-			  gchar    *table_name,
-			  gchar   **column_names)
+tracker_fts_create_table (sqlite3    *db,
+                          gchar      *table_name,
+                          GHashTable *tables,
+                          GHashTable *grouped_columns)
 {
-	GString *str;
-	gint i, rc;
+	GString *str, *from, *fts;
+	GHashTableIter iter;
+	gchar *index_table;
+	GList *columns;
+	gint rc;
+
+	/* Create view on tables/columns marked as FTS-indexed */
+	g_hash_table_iter_init (&iter, tables);
+	str = g_string_new ("CREATE VIEW fts_view AS SELECT Resource.ID as rowid ");
+	from = g_string_new ("FROM Resource ");
+
+	fts = g_string_new ("CREATE VIRTUAL TABLE ");
+	g_string_append_printf (fts, "%s USING fts4(content=\"fts_view\", ",
+				table_name);
+
+	while (g_hash_table_iter_next (&iter, (gpointer *) &index_table,
+				       (gpointer *) &columns)) {
+		while (columns) {
+			if (grouped_columns &&
+			    g_hash_table_lookup (grouped_columns, columns->data)) {
+				g_string_append_printf (str, ", group_concat(\"%s\".\"%s\")",
+							index_table,
+							(gchar *) columns->data);
+			} else {
+				g_string_append_printf (str, ", \"%s\".\"%s\"",
+							index_table,
+							(gchar *) columns->data);
+			}
+
+			g_string_append_printf (str, " AS \"%s\" ",
+						(gchar *) columns->data);
+			g_string_append_printf (fts, "\"%s\", ",
+						(gchar *) columns->data);
 
-	str = g_string_new ("CREATE VIRTUAL TABLE ");
-	g_string_append_printf (str, "%s USING fts4(", table_name);
+			columns = columns->next;
+		}
 
-	for (i = 0; column_names[i]; i++) {
-		g_string_append_printf (str, "\"%s\", ", column_names[i]);
+		g_string_append_printf (from, "LEFT OUTER JOIN \"%s\" ON "
+					" Resource.ID = \"%s\".ID ",
+					index_table, index_table);
 	}
 
-	g_string_append (str, " tokenize=TrackerTokenizer)");
+	g_string_append (str, from->str);
+	g_string_free (from, TRUE);
 
 	rc = sqlite3_exec(db, str->str, NULL, 0, NULL);
 	g_string_free (str, TRUE);
 
-	return (rc == SQLITE_OK);
-}
-
-gboolean
-tracker_fts_alter_table (sqlite3  *db,
-			 gchar    *table_name,
-			 gchar   **added_columns,
-			 gchar   **removed_columns)
-{
-	GString *columns_str = NULL;
-	GPtrArray *columns;
-	sqlite3_stmt *stmt;
-	gchar *query, *tmp_name;
-	int rc, i;
-
-	if (!added_columns && !removed_columns) {
-		return TRUE;
-	}
-
-	query = g_strdup_printf ("PRAGMA table_info(%s)", table_name);
-	rc = sqlite3_prepare_v2 (db, query, -1, &stmt, NULL);
-	g_free (query);
-
 	if (rc != SQLITE_OK) {
 		return FALSE;
 	}
 
-	columns = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
-
-	/* Fetch the old columns, don't add stuff in removed_columns */
-	while ((rc = sqlite3_step (stmt)) != SQLITE_DONE) {
-		if (rc == SQLITE_ROW) {
-			const gchar *name;
-
-			name = sqlite3_column_text (stmt, 1);
+	g_string_append (fts, "tokenize=TrackerTokenizer)");
+	rc = sqlite3_exec(db, fts->str, NULL, 0, NULL);
+	g_string_free (fts, TRUE);
 
-			for (i = 0; removed_columns && removed_columns[i]; i++) {
-				if (g_strcmp0 (name, removed_columns[i]) == 0) {
-					continue;
-				}
-			}
-
-			g_ptr_array_add (columns, g_strdup (name));
-		}
-	}
-
-	if (rc == SQLITE_DONE) {
-		rc = sqlite3_finalize (stmt);
-	}
-
-	if (rc != SQLITE_OK) {
-		g_ptr_array_free (columns, TRUE);
-		return FALSE;
-	}
-
-	/* In columns we have the current columns, minus the removed columns,
-	 * create the update we'll execute later on to dump data from one
-	 * table to another.
-	 */
-	for (i = 0; i < columns->len; i++) {
-		if (!columns_str) {
-			columns_str = g_string_new ("");
-		} else {
-			g_string_append_c (columns_str, ',');
-		}
-
-		g_string_append_printf (columns_str, "\"%s\"",
-					(gchar *) g_ptr_array_index (columns, i));
-	}
+	return (rc == SQLITE_OK);
+}
 
-	if (!columns_str) {
-		g_ptr_array_free (columns, TRUE);
-		return FALSE;
-	}
+gboolean
+tracker_fts_alter_table (sqlite3    *db,
+			 gchar      *table_name,
+			 GHashTable *tables,
+			 GHashTable *grouped_columns)
+{
+	gchar *query, *tmp_name;
+	sqlite3_stmt *stmt;
+	int rc;
 
 	tmp_name = g_strdup_printf ("%s_TMP", table_name);
 
-	query = g_strdup_printf ("INSERT INTO %s (%s) SELECT %s FROM %s",
-				 tmp_name, columns_str->str,
-				 columns_str->str, table_name);
-	g_string_free (columns_str, TRUE);
-
-	/* Now append stuff in added_columns and create the temporary table */
-	for (i = 0; added_columns && added_columns[i]; i++) {
-		g_ptr_array_add (columns, g_strdup (added_columns[i]));
-	}
+	query = g_strdup_printf ("DROP VIEW fts_view", table_name);
+	rc = sqlite3_prepare_v2 (db, query, -1, NULL, NULL);
 
-	/* Add trailing NULL */
-	g_ptr_array_add (columns, NULL);
-
-	if (!tracker_fts_create_table (db, tmp_name, (gchar **) columns->pdata)) {
-		g_ptr_array_free (columns, TRUE);
+	if (!tracker_fts_create_table (db, tmp_name, tables, grouped_columns)) {
 		g_free (tmp_name);
 		g_free (query);
 		return FALSE;
 	}
 
-	/* Dump all content from one table to another */
-	g_ptr_array_free (columns, TRUE);
-	rc = sqlite3_exec(db, query, NULL, 0, NULL);
+	query = g_strdup_printf ("INSERT INTO %s (docid) SELECT docid FROM %s",
+				 tmp_name, table_name);
+	rc = sqlite3_prepare_v2 (db, query, -1, NULL, NULL);
 	g_free (query);
 
 	if (rc != SQLITE_OK) {
-		query = g_strdup_printf ("DROP TABLE %s", tmp_name);
-		rc = sqlite3_exec(db, query, NULL, 0, NULL);
-		g_free (query);
 		g_free (tmp_name);
 		return FALSE;
 	}
 
-	/* Drop the old table */
-	query = g_strdup_printf ("DROP TABLE %s", table_name);
-	rc = sqlite3_exec(db, query, NULL, 0, NULL);
+	query = g_strdup_printf ("INSERT INTO %s(%s) VALUES('rebuild')",
+				 tmp_name, tmp_name);
+	rc = sqlite3_prepare_v2 (db, query, -1, NULL, NULL);
 	g_free (query);
 
 	if (rc != SQLITE_OK) {
-		/* FIXME: How can we leave such state? this is rather fatal */
 		g_free (tmp_name);
 		return FALSE;
 	}
 
-	/* And rename the previous one */
 	query = g_strdup_printf ("ALTER TABLE %s RENAME TO %s",
 				 tmp_name, table_name);
-	rc = sqlite3_exec(db, query, NULL, 0, NULL);
+	rc = sqlite3_prepare_v2 (db, query, -1, NULL, NULL);
 	g_free (query);
 	g_free (tmp_name);
 
+
 	if (rc != SQLITE_OK) {
+		g_free (tmp_name);
 		return FALSE;
 	}
 
diff --git a/src/libtracker-fts/tracker-fts.h b/src/libtracker-fts/tracker-fts.h
index 487a6ff..c020af2 100644
--- a/src/libtracker-fts/tracker-fts.h
+++ b/src/libtracker-fts/tracker-fts.h
@@ -23,19 +23,20 @@
 #define __TRACKER_FTS_H__
 
 #include <sqlite3.h>
-#include <glib.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
 gboolean    tracker_fts_init             (void);
 gboolean    tracker_fts_init_db          (sqlite3    *db);
 gboolean    tracker_fts_create_table     (sqlite3    *db,
-					  gchar      *table_name,
-					  gchar     **column_names);
+                                          gchar      *table_name,
+                                          GHashTable *tables,
+                                          GHashTable *grouped_columns);
 gboolean    tracker_fts_alter_table      (sqlite3    *db,
-					  gchar      *table_name,
-					  gchar     **added_columns,
-					  gchar     **removed_columns);
+                                          gchar      *table_name,
+                                          GHashTable *tables,
+                                          GHashTable *grouped_columns);
 
 
 G_END_DECLS



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