[tracker/wip/carlosg/service-fixes: 4/8] libtracker-data: Rebuild TrackerSparql SQL string on graph changes



commit af97cede7cedaff9d34370605363c383fd430d42
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Jun 8 16:30:02 2020 +0200

    libtracker-data: Rebuild TrackerSparql SQL string on graph changes
    
    If graphs are added or removed, the resulting SQL may be either
    optimized better, or be broken as per the current database schema
    (eg. if graph being removed was specified somewhere in the query).
    
    Use the data manager "generation" number (increased on every graph
    change) to find out whether the statement needs rebuilding before
    execution, and do so. This will generate again a SQL string that
    is up-to-date with the current graphs.

 src/libtracker-data/tracker-data-manager.c |  6 +++++
 src/libtracker-data/tracker-data-manager.h |  2 ++
 src/libtracker-data/tracker-sparql.c       | 43 ++++++++++++++++++++++++++++--
 3 files changed, 49 insertions(+), 2 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 316fe3465..89c25e280 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -5119,3 +5119,9 @@ tracker_data_manager_copy_graph (TrackerDataManager  *manager,
 
        return TRUE;
 }
+
+guint
+tracker_data_manager_get_generation (TrackerDataManager *manager)
+{
+       return manager->generation;
+}
diff --git a/src/libtracker-data/tracker-data-manager.h b/src/libtracker-data/tracker-data-manager.h
index af558789c..cc0afc2e8 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -101,6 +101,8 @@ gint                 tracker_data_manager_find_graph       (TrackerDataManager *
 const gchar *        tracker_data_manager_find_graph_by_id (TrackerDataManager *manager,
                                                             gint                id);
 
+guint                tracker_data_manager_get_generation   (TrackerDataManager *manager);
+
 G_END_DECLS
 
 #endif /* __LIBTRACKER_DATA_MANAGER_H__ */
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index df9b0c62b..937b475cb 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -129,6 +129,7 @@ struct _TrackerSparql
 
        gboolean silent;
        gboolean cacheable;
+       guint generation;
 
        GHashTable *parameters;
 
@@ -8796,6 +8797,21 @@ tracker_sparql_init (TrackerSparql *sparql)
        sparql->cacheable = TRUE;
 }
 
+static gboolean
+tracker_sparql_needs_update (TrackerSparql *sparql)
+{
+       guint generation;
+
+       generation = tracker_data_manager_get_generation (sparql->data_manager);
+
+       if (sparql->generation != generation) {
+               sparql->generation = generation;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
 TrackerSparql*
 tracker_sparql_new (TrackerDataManager *manager,
                     const gchar        *query)
@@ -8819,6 +8835,9 @@ tracker_sparql_new (TrackerDataManager *manager,
                sparql->tree = tree;
                sparql->current_state.node = tracker_node_tree_get_root (sparql->tree);
                tracker_sparql_init_string_builder (sparql);
+
+               if (tracker_sparql_needs_update (sparql))
+                       _call_rule_func (sparql, NAMED_RULE_Query, &sparql->parser_error);
        }
 
        return sparql;
@@ -8925,6 +8944,22 @@ prepare_query (TrackerSparql         *sparql,
        return stmt;
 }
 
+static void
+tracker_sparql_reset_state (TrackerSparql *sparql)
+{
+       sparql->current_state.node = tracker_node_tree_get_root (sparql->tree);
+       tracker_sparql_init_string_builder (sparql);
+       g_clear_object (&sparql->context);
+       g_list_free (sparql->filter_clauses);
+       sparql->filter_clauses = NULL;
+       g_ptr_array_set_size (sparql->var_names, 0);
+       g_array_set_size (sparql->var_types, 0);
+       g_hash_table_remove_all (sparql->cached_bindings);
+       g_hash_table_remove_all (sparql->parameters);
+       g_ptr_array_set_size (sparql->anon_graphs, 0);
+       g_ptr_array_set_size (sparql->named_graphs, 0);
+}
+
 TrackerSparqlCursor *
 tracker_sparql_execute_cursor (TrackerSparql  *sparql,
                                GHashTable     *parameters,
@@ -8953,8 +8988,12 @@ tracker_sparql_execute_cursor (TrackerSparql  *sparql,
                return NULL;
        }
 
-       if (!_call_rule_func (sparql, NAMED_RULE_Query, error))
-               return NULL;
+       if (tracker_sparql_needs_update (sparql)) {
+               tracker_sparql_reset_state (sparql);
+
+               if (!_call_rule_func (sparql, NAMED_RULE_Query, error))
+                       return NULL;
+       }
 
        iface = tracker_data_manager_get_db_interface (sparql->data_manager);
        stmt = prepare_query (sparql, iface, sparql->sql,


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