[tracker/wip/carlosg/sparql1.1: 95/201] libtracker-data: Handle ADD/MOVE/COPY/CLEAR
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/sparql1.1: 95/201] libtracker-data: Handle ADD/MOVE/COPY/CLEAR
- Date: Mon, 9 Sep 2019 22:26:47 +0000 (UTC)
commit 468d39a3dace8b47344c7701561f361f05bd89e9
Author: Carlos Garnacho <carlosg gnome org>
Date: Mon Jun 3 23:48:41 2019 +0200
libtracker-data: Handle ADD/MOVE/COPY/CLEAR
This allows management of graphs
src/libtracker-data/tracker-data-manager.c | 137 ++++++++++++++
src/libtracker-data/tracker-data-manager.h | 8 +
src/libtracker-data/tracker-sparql.c | 279 ++++++++++++++++++++++++++---
3 files changed, 401 insertions(+), 23 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 47aaf51aa..8068d5ed7 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -5140,3 +5140,140 @@ tracker_data_manager_find_graph_by_id (TrackerDataManager *manager,
return NULL;
}
+
+gboolean
+tracker_data_manager_clear_graph (TrackerDataManager *manager,
+ const gchar *graph,
+ GError **error)
+{
+ TrackerOntologies *ontologies = manager->ontologies;
+ TrackerClass **classes;
+ TrackerProperty **properties;
+ TrackerDBStatement *stmt;
+ guint i, n_classes, n_properties;
+ GError *inner_error = NULL;
+ TrackerDBInterface *iface;
+
+ if (!graph)
+ graph = "main";
+
+ iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+ classes = tracker_ontologies_get_classes (ontologies, &n_classes);
+ properties = tracker_ontologies_get_properties (ontologies, &n_properties);
+
+ for (i = 0; !inner_error && i < n_classes; i++) {
+ if (g_str_has_prefix (tracker_class_get_name (classes[i]), "xsd:"))
+ continue;
+
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
&inner_error,
+ "DELETE FROM \"%s\".\"%s\" WHERE ID > 100000",
+ graph,
+ tracker_class_get_name (classes[i]));
+ if (!stmt)
+ break;
+
+ tracker_db_statement_execute (stmt, &inner_error);
+ g_object_unref (stmt);
+ }
+
+ for (i = 0; !inner_error && i < n_properties; i++) {
+ TrackerClass *service;
+
+ if (!tracker_property_get_multiple_values (properties[i]))
+ continue;
+
+ service = tracker_property_get_domain (properties[i]);
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
&inner_error,
+ "DELETE FROM \"%s\".\"%s_%s\" WHERE ID >
100000",
+ graph,
+ tracker_class_get_name (service),
+ tracker_property_get_name (properties[i]));
+ if (!stmt)
+ break;
+
+ tracker_db_statement_execute (stmt, &inner_error);
+ g_object_unref (stmt);
+ }
+
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+tracker_data_manager_copy_graph (TrackerDataManager *manager,
+ const gchar *source,
+ const gchar *destination,
+ GError **error)
+{
+ TrackerOntologies *ontologies = manager->ontologies;
+ TrackerClass **classes;
+ TrackerProperty **properties;
+ TrackerDBStatement *stmt;
+ guint i, n_classes, n_properties;
+ GError *inner_error = NULL;
+ TrackerDBInterface *iface;
+
+ if (!source)
+ source = "main";
+ if (!destination)
+ destination = "main";
+
+ if (strcmp (source, destination) == 0)
+ return TRUE;
+
+ iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+ classes = tracker_ontologies_get_classes (ontologies, &n_classes);
+ properties = tracker_ontologies_get_properties (ontologies, &n_properties);
+
+ for (i = 0; !inner_error && i < n_classes; i++) {
+ if (g_str_has_prefix (tracker_class_get_name (classes[i]), "xsd:"))
+ continue;
+
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
&inner_error,
+ "INSERT OR REPLACE INTO \"%s\".\"%s\" "
+ "SELECT * from \"%s\".\"%s\" WHERE ID > 100000",
+ destination,
+ tracker_class_get_name (classes[i]),
+ source,
+ tracker_class_get_name (classes[i]));
+ if (!stmt)
+ break;
+
+ tracker_db_statement_execute (stmt, &inner_error);
+ g_object_unref (stmt);
+ }
+
+ for (i = 0; !inner_error && i < n_properties; i++) {
+ TrackerClass *service;
+
+ if (!tracker_property_get_multiple_values (properties[i]))
+ continue;
+
+ service = tracker_property_get_domain (properties[i]);
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
&inner_error,
+ "INSERT OR REPLACE INTO \"%s\".\"%s_%s\" "
+ "SELECT * from \"%s\".\"%s_%s\" WHERE ID >
100000",
+ destination,
+ tracker_class_get_name (service),
+ tracker_property_get_name (properties[i]),
+ source,
+ tracker_class_get_name (service),
+ tracker_property_get_name (properties[i]));
+ if (!stmt)
+ break;
+
+ tracker_db_statement_execute (stmt, &inner_error);
+ g_object_unref (stmt);
+ }
+
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/src/libtracker-data/tracker-data-manager.h b/src/libtracker-data/tracker-data-manager.h
index ebb992753..d703b0ea6 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -88,6 +88,14 @@ gboolean tracker_data_manager_drop_graph (TrackerDataManager *manag
const gchar *name,
GError **error);
+gboolean tracker_data_manager_clear_graph (TrackerDataManager *manager,
+ const gchar *graph,
+ GError **error);
+gboolean tracker_data_manager_copy_graph (TrackerDataManager *manager,
+ const gchar *source,
+ const gchar *destination,
+ GError **error);
+
gint tracker_data_manager_find_graph (TrackerDataManager *manager,
const gchar *name);
const gchar * tracker_data_manager_find_graph_by_id (TrackerDataManager *manager,
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 64bc84815..b0665bff3 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -2433,11 +2433,73 @@ translate_Load (TrackerSparql *sparql,
return TRUE;
}
+static gboolean
+handle_silent (gboolean silent,
+ GError *error_in,
+ GError **error)
+{
+ if (silent) {
+ g_error_free (error_in);
+ return TRUE;
+ } else {
+ g_propagate_error (error, error_in);
+ return FALSE;
+ }
+}
+
static gboolean
translate_Clear (TrackerSparql *sparql,
GError **error)
{
- _unimplemented ("CLEAR");
+ gboolean silent = FALSE;
+ GError *inner_error = NULL;
+ GList *graphs = NULL, *l;
+ const gchar *graph;
+
+ /* Clear ::= 'CLEAR' 'SILENT'? GraphRefAll
+ */
+ _expect (sparql, RULE_TYPE_LITERAL, LITERAL_CLEAR);
+
+ if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_SILENT))
+ silent = TRUE;
+
+ _call_rule (sparql, NAMED_RULE_GraphRefAll, error);
+
+ if (tracker_token_is_empty (&sparql->current_state.graph)) {
+ if (sparql->current_state.graph_op == GRAPH_OP_DEFAULT ||
+ sparql->current_state.graph_op == GRAPH_OP_ALL) {
+ graphs = g_list_prepend (graphs, "main");
+ }
+
+ if (sparql->current_state.graph_op == GRAPH_OP_ALL ||
+ sparql->current_state.graph_op == GRAPH_OP_NAMED) {
+ GHashTable *ht;
+ GHashTableIter iter;
+
+ ht = tracker_data_manager_get_graphs (sparql->data_manager);
+ g_hash_table_iter_init (&iter, ht);
+
+ while (g_hash_table_iter_next (&iter, (gpointer *) &graph, NULL))
+ graphs = g_list_prepend (graphs, (gpointer) graph);
+ }
+ } else {
+ graph = tracker_token_get_idstring (&sparql->current_state.graph);
+
+ if (tracker_data_manager_find_graph (sparql->data_manager, graph) == 0)
+ _raise (UNKNOWN_GRAPH, "Unknown graph", graph);
+
+ graphs = g_list_prepend (graphs, (gpointer) graph);
+ }
+
+ for (l = graphs; l; l = l->next) {
+ if (!tracker_data_manager_clear_graph (sparql->data_manager,
+ l->data, &inner_error))
+ break;
+ }
+
+ g_list_free (graphs);
+
+ return handle_silent (silent, inner_error, error);
}
static gboolean
@@ -2455,19 +2517,13 @@ translate_Drop (TrackerSparql *sparql,
_call_rule (sparql, NAMED_RULE_GraphRefAll, error);
if (!tracker_token_is_empty (&sparql->current_state.graph)) {
- const gchar *graph_name;
+ const gchar *graph;
+
+ graph = tracker_token_get_idstring (&sparql->current_state.graph);
- graph_name = tracker_token_get_idstring (&sparql->current_state.graph);
if (!tracker_data_manager_drop_graph (sparql->data_manager,
- graph_name,
- &inner_error)) {
- if (silent) {
- g_error_free (inner_error);
- return TRUE;
- } else {
- g_propagate_error (error, inner_error);
- return FALSE;
- }
+ graph, &inner_error)) {
+ return handle_silent (silent, inner_error, error);
}
}
@@ -2508,34 +2564,208 @@ translate_Create (TrackerSparql *sparql,
return TRUE;
error:
- if (silent) {
- g_error_free (inner_error);
- return TRUE;
- } else {
- g_propagate_error (error, inner_error);
- return FALSE;
- }
+ return handle_silent (silent, inner_error, error);
}
static gboolean
translate_Add (TrackerSparql *sparql,
GError **error)
{
- _unimplemented ("ADD");
+ gboolean silent = FALSE;
+ gchar *source, *destination;
+ GError *inner_error = NULL;
+
+ /* Add ::= 'ADD' 'SILENT'? GraphOrDefault 'TO' GraphOrDefault
+ */
+ _expect (sparql, RULE_TYPE_LITERAL, LITERAL_ADD);
+
+ if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_SILENT))
+ silent = TRUE;
+
+ _call_rule (sparql, NAMED_RULE_GraphOrDefault, error);
+ source = g_strdup (tracker_token_get_idstring (&sparql->current_state.graph));
+
+ _expect (sparql, RULE_TYPE_LITERAL, LITERAL_TO);
+
+ _call_rule (sparql, NAMED_RULE_GraphOrDefault, error);
+ destination = g_strdup (tracker_token_get_idstring (&sparql->current_state.graph));
+
+ if (g_strcmp0 (source, destination) == 0) {
+ g_free (source);
+ g_free (destination);
+ return TRUE;
+ }
+
+ if (source &&
+ !tracker_data_manager_find_graph (sparql->data_manager, source)) {
+ g_set_error (&inner_error, TRACKER_SPARQL_ERROR,
+ TRACKER_SPARQL_ERROR_UNKNOWN_GRAPH,
+ "Unknown graph '%s'", source);
+ goto error;
+ }
+
+ if (destination &&
+ !tracker_data_manager_find_graph (sparql->data_manager, destination)) {
+ if (!tracker_data_manager_create_graph (sparql->data_manager,
+ destination, &inner_error))
+ goto error;
+ }
+
+ if (!tracker_data_manager_copy_graph (sparql->data_manager,
+ source, destination,
+ &inner_error))
+ goto error;
+
+ g_free (source);
+ g_free (destination);
+
+ return TRUE;
+
+error:
+
+ g_free (source);
+ g_free (destination);
+
+ return handle_silent (silent, inner_error, error);
}
static gboolean
translate_Move (TrackerSparql *sparql,
GError **error)
{
- _unimplemented ("MOVE");
+ gboolean silent = FALSE;
+ gchar *source, *destination;
+ GError *inner_error = NULL;
+
+ /* Move ::= 'MOVE' 'SILENT'? GraphOrDefault 'TO' GraphOrDefault
+ */
+ _expect (sparql, RULE_TYPE_LITERAL, LITERAL_MOVE);
+
+ if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_SILENT))
+ silent = TRUE;
+
+ _call_rule (sparql, NAMED_RULE_GraphOrDefault, error);
+ source = g_strdup (tracker_token_get_idstring (&sparql->current_state.graph));
+
+ _expect (sparql, RULE_TYPE_LITERAL, LITERAL_TO);
+
+ _call_rule (sparql, NAMED_RULE_GraphOrDefault, error);
+ destination = g_strdup (tracker_token_get_idstring (&sparql->current_state.graph));
+
+ if (g_strcmp0 (source, destination) == 0) {
+ g_free (source);
+ g_free (destination);
+ return TRUE;
+ }
+
+ if (source &&
+ !tracker_data_manager_find_graph (sparql->data_manager, source)) {
+ g_set_error (&inner_error, TRACKER_SPARQL_ERROR,
+ TRACKER_SPARQL_ERROR_UNKNOWN_GRAPH,
+ "Unknown graph '%s'", source);
+ goto error;
+ }
+
+ if (destination &&
+ !tracker_data_manager_find_graph (sparql->data_manager, destination)) {
+ if (!tracker_data_manager_create_graph (sparql->data_manager,
+ destination, &inner_error))
+ goto error;
+ } else {
+ if (!tracker_data_manager_clear_graph (sparql->data_manager,
+ destination, &inner_error))
+ goto error;
+ }
+
+ if (!tracker_data_manager_copy_graph (sparql->data_manager,
+ source, destination,
+ &inner_error))
+ goto error;
+
+ if (!tracker_data_manager_drop_graph (sparql->data_manager,
+ source,
+ &inner_error))
+ goto error;
+
+ g_free (source);
+ g_free (destination);
+
+ return TRUE;
+
+error:
+ g_free (source);
+ g_free (destination);
+
+ return handle_silent (silent, inner_error, error);
}
static gboolean
translate_Copy (TrackerSparql *sparql,
GError **error)
{
- _unimplemented ("COPY");
+ gboolean silent = FALSE;
+ gchar *source, *destination;
+ GError *inner_error = NULL;
+
+ /* Copy ::= 'COPY' 'SILENT'? GraphOrDefault 'TO' GraphOrDefault
+ */
+ _expect (sparql, RULE_TYPE_LITERAL, LITERAL_COPY);
+
+ if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_SILENT))
+ silent = TRUE;
+
+ _call_rule (sparql, NAMED_RULE_GraphOrDefault, error);
+ g_assert (!tracker_token_is_empty (&sparql->current_state.graph) ||
+ sparql->current_state.graph_op == GRAPH_OP_DEFAULT);
+ source = g_strdup (tracker_token_get_idstring (&sparql->current_state.graph));
+
+ _expect (sparql, RULE_TYPE_LITERAL, LITERAL_TO);
+
+ _call_rule (sparql, NAMED_RULE_GraphOrDefault, error);
+ g_assert (!tracker_token_is_empty (&sparql->current_state.graph) ||
+ sparql->current_state.graph_op == GRAPH_OP_DEFAULT);
+ destination = g_strdup (tracker_token_get_idstring (&sparql->current_state.graph));
+
+ if (g_strcmp0 (source, destination) == 0) {
+ g_free (source);
+ g_free (destination);
+ return TRUE;
+ }
+
+ if (source &&
+ !tracker_data_manager_find_graph (sparql->data_manager, source)) {
+ g_set_error (&inner_error, TRACKER_SPARQL_ERROR,
+ TRACKER_SPARQL_ERROR_UNKNOWN_GRAPH,
+ "Unknown graph '%s'", source);
+ goto error;
+ }
+
+ if (destination &&
+ !tracker_data_manager_find_graph (sparql->data_manager, destination)) {
+ if (!tracker_data_manager_create_graph (sparql->data_manager,
+ destination, &inner_error))
+ goto error;
+ } else {
+ if (!tracker_data_manager_clear_graph (sparql->data_manager,
+ destination, &inner_error))
+ goto error;
+ }
+
+ if (!tracker_data_manager_copy_graph (sparql->data_manager,
+ source, destination,
+ &inner_error))
+ goto error;
+
+ g_free (source);
+ g_free (destination);
+
+ return TRUE;
+
+error:
+ g_free (source);
+ g_free (destination);
+
+ return handle_silent (silent, inner_error, error);
}
static gboolean
@@ -2951,10 +3181,13 @@ translate_GraphOrDefault (TrackerSparql *sparql,
/* GraphOrDefault ::= 'DEFAULT' | 'GRAPH'? iri
*/
if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_DEFAULT)) {
-
+ tracker_token_unset (&sparql->current_state.graph);
+ sparql->current_state.graph_op = GRAPH_OP_DEFAULT;
} else {
_accept (sparql, RULE_TYPE_LITERAL, LITERAL_GRAPH);
_call_rule (sparql, NAMED_RULE_iri, error);
+ _init_token (&sparql->current_state.graph,
+ sparql->current_state.prev_node, sparql);
}
return TRUE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]