[tracker/wip/carlosg/sparql1.1: 74/201] libtracker-data: Handle attaching and management of "graph" databases
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/sparql1.1: 74/201] libtracker-data: Handle attaching and management of "graph" databases
- Date: Mon, 9 Sep 2019 22:25:01 +0000 (UTC)
commit 843a5e87ccc93f9985e352114049cea3e451e78d
Author: Carlos Garnacho <carlosg gnome org>
Date: Fri Mar 15 00:18:51 2019 +0100
libtracker-data: Handle attaching and management of "graph" databases
src/libtracker-data/tracker-data-manager.c | 194 ++++++++++++++++++++++
src/libtracker-data/tracker-data-manager.h | 13 ++
src/libtracker-data/tracker-data-update.c | 60 +++++--
src/libtracker-data/tracker-data-update.h | 7 +
src/libtracker-data/tracker-db-interface-sqlite.c | 50 +++++-
src/libtracker-data/tracker-db-interface-sqlite.h | 8 +
src/libtracker-data/tracker-db-manager.c | 47 ++++++
src/libtracker-data/tracker-db-manager.h | 10 ++
8 files changed, 374 insertions(+), 15 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index ca23b2af1..1753701e3 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -83,6 +83,8 @@ struct _TrackerDataManager {
TrackerOntologies *ontologies;
TrackerData *data_update;
+ GHashTable *graphs;
+
gchar *status;
};
@@ -150,6 +152,65 @@ tracker_data_ontology_error_quark (void)
return g_quark_from_static_string ("tracker-data-ontology-error-quark");
}
+static gboolean
+tracker_data_manager_ensure_graphs (TrackerDataManager *manager,
+ TrackerDBInterface *iface,
+ GError **error)
+{
+ TrackerDBCursor *cursor = NULL;
+ TrackerDBStatement *stmt;
+ GHashTable *graphs;
+
+ if (manager->graphs)
+ return TRUE;
+
+ graphs = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE, error,
+ "SELECT ID, Uri FROM Resource WHERE ID IN (SELECT ID
FROM Graph)");
+ if (!stmt) {
+ g_hash_table_unref (graphs);
+ return FALSE;
+ }
+
+ cursor = tracker_db_statement_start_cursor (stmt, error);
+ g_object_unref (stmt);
+
+ if (!cursor) {
+ g_hash_table_unref (graphs);
+ return FALSE;
+ }
+
+ while (tracker_db_cursor_iter_next (cursor, NULL, NULL)) {
+ const gchar *name;
+ gint id;
+
+ id = tracker_db_cursor_get_int (cursor, 0);
+ name = tracker_db_cursor_get_string (cursor, 1, NULL);
+
+ g_hash_table_insert (graphs, g_strdup (name),
+ GINT_TO_POINTER (id));
+ }
+
+ g_object_unref (cursor);
+ manager->graphs = graphs;
+ return TRUE;
+}
+
+static GHashTable *
+tracker_data_manager_get_graphs (TrackerDataManager *manager,
+ TrackerDBInterface *iface,
+ GError **error)
+{
+ if (!tracker_data_manager_ensure_graphs (manager, iface, error))
+ return NULL;
+
+ return manager->graphs;
+}
+
static void
handle_unsupported_ontology_change (TrackerDataManager *manager,
const gchar *ontology_path,
@@ -3898,9 +3959,32 @@ setup_interface_cb (TrackerDBManager *db_manager,
TrackerDBInterface *iface,
TrackerDataManager *data_manager)
{
+ GHashTable *graphs;
+ GError *error = NULL;
+
#if HAVE_TRACKER_FTS
tracker_data_manager_init_fts (iface, FALSE);
#endif
+ graphs = tracker_data_manager_get_graphs (data_manager, iface, NULL);
+
+ if (graphs) {
+ GHashTableIter iter;
+ gpointer value;
+ GError *error = NULL;
+
+ g_hash_table_iter_init (&iter, graphs);
+
+ while (g_hash_table_iter_next (&iter, &value, NULL)) {
+ if (!tracker_db_manager_attach_database (db_manager,
+ iface, value, FALSE,
+ &error)) {
+ g_critical ("Could not attach database '%s': %s\n",
+ (gchar *) value, error->message);
+ g_clear_error (&error);
+ continue;
+ }
+ }
+ }
}
static gboolean
@@ -3940,6 +4024,7 @@ tracker_data_manager_initable_init (GInitable *initable,
TrackerDBCursor *cursor;
TrackerDBStatement *stmt;
GHashTable *ontos_table;
+ GHashTable *graphs;
GList *sorted = NULL, *l;
gint max_id = 0;
gboolean read_only;
@@ -4415,6 +4500,22 @@ tracker_data_manager_initable_init (GInitable *initable,
tracker_data_ontology_setup_db (manager, iface, "main", TRUE,
&ontology_error);
+ graphs = tracker_data_manager_get_graphs (manager, iface, &ontology_error);
+
+ if (graphs) {
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, graphs);
+
+ while (g_hash_table_iter_next (&iter, &value, NULL)) {
+ tracker_data_ontology_setup_db (manager, iface, value, TRUE,
+ &ontology_error);
+ if (ontology_error)
+ break;
+ }
+ }
+
if (!ontology_error) {
tracker_data_ontology_import_into_db (manager, iface, TRUE,
&ontology_error);
@@ -4646,6 +4747,7 @@ tracker_data_manager_finalize (GObject *object)
g_clear_object (&manager->ontologies);
g_clear_object (&manager->data_update);
+ g_clear_pointer (&manager->graphs, g_hash_table_unref);
g_free (manager->status);
G_OBJECT_CLASS (tracker_data_manager_parent_class)->finalize (object);
@@ -4747,3 +4849,95 @@ tracker_data_manager_get_namespaces (TrackerDataManager *manager)
return ht;
}
+
+gboolean
+tracker_data_manager_create_graph (TrackerDataManager *manager,
+ const gchar *name,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+ gint id;
+
+ iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+
+ if (!tracker_db_manager_attach_database (manager->db_manager, iface,
+ name, TRUE, error))
+ return FALSE;
+
+ if (!tracker_data_ontology_setup_db (manager, iface, name,
+ FALSE, error))
+ goto detach;
+
+ id = tracker_data_ensure_graph (manager->data_update, name, error);
+ if (id == 0)
+ goto detach;
+
+ g_hash_table_insert (manager->graphs, g_strdup (name), GINT_TO_POINTER (id));
+ return TRUE;
+
+detach:
+ tracker_db_manager_detach_database (manager->db_manager, iface, name, NULL);
+ return FALSE;
+}
+
+gboolean
+tracker_data_manager_drop_graph (TrackerDataManager *manager,
+ const gchar *name,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+
+ iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+
+ if (!tracker_db_manager_detach_database (manager->db_manager, iface,
+ name, error))
+ return FALSE;
+
+ if (!tracker_data_delete_graph (manager->data_update, name, error))
+ return FALSE;
+
+ if (manager->graphs)
+ g_hash_table_remove (manager->graphs, name);
+
+ return TRUE;
+}
+
+gint
+tracker_data_manager_find_graph (TrackerDataManager *manager,
+ const gchar *name)
+{
+ TrackerDBInterface *iface;
+ GHashTable *graphs;
+
+ iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+ graphs = tracker_data_manager_get_graphs (manager, iface, NULL);
+
+ if (!graphs)
+ return 0;
+
+ return GPOINTER_TO_UINT (g_hash_table_lookup (graphs, name));
+}
+
+const gchar *
+tracker_data_manager_find_graph_by_id (TrackerDataManager *manager,
+ gint id)
+{
+ TrackerDBInterface *iface;
+ GHashTableIter iter;
+ GHashTable *graphs;
+ gpointer key, value;
+
+ iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+ graphs = tracker_data_manager_get_graphs (manager, iface, NULL);
+
+ if (!graphs)
+ return NULL;
+
+ g_hash_table_iter_init (&iter, graphs);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ if (id == GPOINTER_TO_INT (value))
+ return key;
+ }
+
+ return NULL;
+}
diff --git a/src/libtracker-data/tracker-data-manager.h b/src/libtracker-data/tracker-data-manager.h
index 71795a56a..ebb992753 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -80,6 +80,19 @@ TrackerData * tracker_data_manager_get_data (TrackerDataManage
GHashTable * tracker_data_manager_get_namespaces (TrackerDataManager *manager);
+gboolean tracker_data_manager_create_graph (TrackerDataManager *manager,
+ const gchar *name,
+ GError **error);
+
+gboolean tracker_data_manager_drop_graph (TrackerDataManager *manager,
+ const gchar *name,
+ GError **error);
+
+gint tracker_data_manager_find_graph (TrackerDataManager *manager,
+ const gchar *name);
+const gchar * tracker_data_manager_find_graph_by_id (TrackerDataManager *manager,
+ gint id);
+
G_END_DECLS
#endif /* __LIBTRACKER_DATA_MANAGER_H__ */
diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c
index 25baa6df7..5c97652e8 100644
--- a/src/libtracker-data/tracker-data-update.c
+++ b/src/libtracker-data/tracker-data-update.c
@@ -734,8 +734,6 @@ ensure_graph_id (TrackerData *data,
const gchar *uri,
gboolean *create)
{
- TrackerDBInterface *iface;
- TrackerDBStatement *stmt;
GError *error = NULL;
gint id;
@@ -743,17 +741,7 @@ ensure_graph_id (TrackerData *data,
if (id != 0)
return id;
- id = ensure_resource_id (data, uri, create);
- iface = tracker_data_manager_get_writable_db_interface (data->manager);
- stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, &error,
- "INSERT OR IGNORE INTO Graph (ID) VALUES (?)");
-
- if (stmt) {
- tracker_db_statement_bind_int (stmt, 0, id);
- tracker_db_statement_execute (stmt, &error);
- g_object_unref (stmt);
- }
-
+ id = tracker_data_ensure_graph (data, uri, &error);
if (error) {
g_critical ("Could not ensure graph existence: %s", error->message);
g_error_free (error);
@@ -3412,3 +3400,49 @@ tracker_data_load_turtle_file (TrackerData *data,
tracker_turtle_reader_load (file, data, error);
}
+
+gint
+tracker_data_ensure_graph (TrackerData *data,
+ const gchar *uri,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+ TrackerDBStatement *stmt;
+ gint id;
+
+ id = ensure_resource_id (data, uri, NULL);
+ iface = tracker_data_manager_get_writable_db_interface (data->manager);
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, error,
+ "INSERT OR IGNORE INTO Graph (ID) VALUES (?)");
+ if (!stmt)
+ return 0;
+
+ tracker_db_statement_bind_int (stmt, 0, id);
+ tracker_db_statement_execute (stmt, error);
+ g_object_unref (stmt);
+
+ return id;
+}
+
+gboolean
+tracker_data_delete_graph (TrackerData *data,
+ const gchar *uri,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+ TrackerDBStatement *stmt;
+ gint id;
+
+ id = query_resource_id (data, uri);
+ iface = tracker_data_manager_get_writable_db_interface (data->manager);
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, error,
+ "DELETE FROM Graph WHERE ID = ?");
+ if (!stmt)
+ return FALSE;
+
+ tracker_db_statement_bind_int (stmt, 0, id);
+ tracker_db_statement_execute (stmt, error);
+ g_object_unref (stmt);
+
+ return TRUE;
+}
diff --git a/src/libtracker-data/tracker-data-update.h b/src/libtracker-data/tracker-data-update.h
index 3acb11f27..5241167fb 100644
--- a/src/libtracker-data/tracker-data-update.h
+++ b/src/libtracker-data/tracker-data-update.h
@@ -118,6 +118,13 @@ void tracker_data_load_turtle_file (TrackerData *
void tracker_data_sync (TrackerData *data);
+gint tracker_data_ensure_graph (TrackerData *data,
+ const gchar *name,
+ GError **error);
+gboolean tracker_data_delete_graph (TrackerData *data,
+ const gchar *uri,
+ GError **error);
+
/* Calling back */
void tracker_data_add_insert_statement_callback (TrackerData *data,
TrackerStatementCallback callback,
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.c
b/src/libtracker-data/tracker-db-interface-sqlite.c
index d253df52d..d19eb93d9 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.c
+++ b/src/libtracker-data/tracker-db-interface-sqlite.c
@@ -2382,7 +2382,7 @@ tracker_db_interface_create_statement (TrackerDBInterface *db_interfac
return g_object_ref_sink (stmt);
}
-static void
+static gboolean
execute_stmt (TrackerDBInterface *interface,
sqlite3_stmt *stmt,
GCancellable *cancellable,
@@ -2431,7 +2431,7 @@ execute_stmt (TrackerDBInterface *interface,
g_critical ("SQLite error: %s (errno: %s)",
sqlite3_errmsg (interface->db),
g_strerror (errno));
- return;
+ return FALSE;
}
if (!error) {
@@ -2456,6 +2456,8 @@ execute_stmt (TrackerDBInterface *interface,
}
}
}
+
+ return result == SQLITE_DONE;
}
void
@@ -3171,3 +3173,47 @@ tracker_db_interface_init_vtabs (TrackerDBInterface *db_interface,
tracker_vtab_triples_init (db_interface->db, ontologies);
return TRUE;
}
+
+gboolean
+tracker_db_interface_attach_database (TrackerDBInterface *db_interface,
+ GFile *file,
+ const gchar *name,
+ GError **error)
+{
+ gchar *sql, *path;
+ sqlite3_stmt *stmt;
+ gboolean retval;
+
+ path = g_file_get_path (file);
+ sql = g_strdup_printf ("ATTACH DATABASE \"%s\" AS \"%s\"", path, name);
+ g_free (path);
+
+ stmt = tracker_db_interface_prepare_stmt (db_interface, sql, error);
+ g_free (sql);
+ if (!stmt)
+ return FALSE;
+
+ retval = execute_stmt (db_interface, stmt, NULL, error);
+ sqlite3_finalize (stmt);
+ return retval;
+}
+
+gboolean
+tracker_db_interface_detach_database (TrackerDBInterface *db_interface,
+ const gchar *name,
+ GError **error)
+{
+ sqlite3_stmt *stmt;
+ gboolean retval;
+ gchar *sql;
+
+ sql = g_strdup_printf ("DETACH DATABASE \"%s\"", name);
+
+ stmt = tracker_db_interface_prepare_stmt (db_interface, sql, error);
+ if (!stmt)
+ return FALSE;
+
+ retval = execute_stmt (db_interface, stmt, NULL, error);
+ sqlite3_finalize (stmt);
+ return retval;
+}
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.h
b/src/libtracker-data/tracker-db-interface-sqlite.h
index 4608bac94..1715d30ef 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.h
+++ b/src/libtracker-data/tracker-db-interface-sqlite.h
@@ -83,6 +83,14 @@ void tracker_db_interface_sqlite_fts_update_rollback (TrackerD
void tracker_db_interface_sqlite_fts_rebuild_tokens (TrackerDBInterface *interface);
+gboolean tracker_db_interface_attach_database (TrackerDBInterface
*db_interface,
+ GFile *file,
+ const gchar *name,
+ GError **error);
+gboolean tracker_db_interface_detach_database (TrackerDBInterface
*db_interface,
+ const gchar *name,
+ GError **error);
+
#endif
G_END_DECLS
diff --git a/src/libtracker-data/tracker-db-manager.c b/src/libtracker-data/tracker-db-manager.c
index 333920630..c4def0934 100644
--- a/src/libtracker-data/tracker-db-manager.c
+++ b/src/libtracker-data/tracker-db-manager.c
@@ -1277,3 +1277,50 @@ tracker_db_manager_check_perform_vacuum (TrackerDBManager *db_manager)
iface = tracker_db_manager_get_writable_db_interface (db_manager);
tracker_db_interface_execute_query (iface, NULL, "VACUUM");
}
+
+gboolean
+tracker_db_manager_attach_database (TrackerDBManager *db_manager,
+ TrackerDBInterface *iface,
+ const gchar *name,
+ gboolean create,
+ GError **error)
+{
+ gchar *filename, *escaped;
+ GFile *file;
+
+ filename = g_strdup_printf ("%s.db", name);
+ escaped = g_uri_escape_string (filename, NULL, FALSE);
+ file = g_file_get_child (db_manager->cache_location, escaped);
+ g_free (filename);
+ g_free (escaped);
+
+ if (create) {
+ GError *inner_error = NULL;
+
+ /* Create the database from scratch */
+ if (!g_file_delete (file, NULL, &inner_error)) {
+ if (!g_error_matches (inner_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
+ g_object_unref (file);
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+ }
+ }
+
+ if (!tracker_db_interface_attach_database (iface, file, name, error)) {
+ g_object_unref (file);
+ return FALSE;
+ }
+
+ g_object_unref (file);
+ return TRUE;
+}
+
+gboolean
+tracker_db_manager_detach_database (TrackerDBManager *db_manager,
+ TrackerDBInterface *iface,
+ const gchar *name,
+ GError **error)
+{
+ return tracker_db_interface_detach_database (iface, name, error);
+}
diff --git a/src/libtracker-data/tracker-db-manager.h b/src/libtracker-data/tracker-db-manager.h
index 06dee6ba4..5ce937773 100644
--- a/src/libtracker-data/tracker-db-manager.h
+++ b/src/libtracker-data/tracker-db-manager.h
@@ -99,6 +99,16 @@ void tracker_db_manager_tokenizer_update (TrackerDBManager
void tracker_db_manager_check_perform_vacuum (TrackerDBManager *db_manager);
+gboolean tracker_db_manager_attach_database (TrackerDBManager *db_manager,
+ TrackerDBInterface *iface,
+ const gchar *name,
+ gboolean create,
+ GError **error);
+gboolean tracker_db_manager_detach_database (TrackerDBManager *db_manager,
+ TrackerDBInterface *iface,
+ const gchar *name,
+ GError **error);
+
G_END_DECLS
#endif /* __LIBTRACKER_DB_MANAGER_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]