[tracker/wip/carlosg/sparql1.1: 95/201] libtracker-data: Handle ADD/MOVE/COPY/CLEAR



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]