[tracker/wip/carlosg/graphs-through-with: 6/15] libtracker-data: Iterate through graphs directly in tracker_triples vtab



commit b34bc3ef675295392cb2ca9f0265a41f3c671c4d
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Oct 27 21:51:06 2019 +0100

    libtracker-data: Iterate through graphs directly in tracker_triples vtab
    
    Using the unionGraph views was merely convenient as it saved us from an
    extra iteration level. As the unionGraph views will be dropped, just add
    such extra level.

 src/libtracker-data/tracker-vtab-triples.c | 100 +++++++++++++++++++++++++----
 1 file changed, 86 insertions(+), 14 deletions(-)
---
diff --git a/src/libtracker-data/tracker-vtab-triples.c b/src/libtracker-data/tracker-vtab-triples.c
index c1f7227f3..a9e868b1d 100644
--- a/src/libtracker-data/tracker-vtab-triples.c
+++ b/src/libtracker-data/tracker-vtab-triples.c
@@ -74,7 +74,9 @@ typedef struct {
                guint idxFlags;
        } match;
 
+       GHashTable *query_graphs;
        GList *properties;
+       GList *graphs;
 
        guint64 rowid;
        guint finished : 1;
@@ -106,6 +108,8 @@ tracker_triples_cursor_reset (TrackerTriplesCursor *cursor)
        g_clear_pointer (&cursor->match.subject, sqlite3_value_free);
        g_clear_pointer (&cursor->match.predicate, sqlite3_value_free);
        g_clear_pointer (&cursor->properties, g_list_free);
+       g_clear_pointer (&cursor->graphs, g_list_free);
+       g_clear_pointer (&cursor->query_graphs, g_hash_table_unref);
        cursor->match.idxFlags = 0;
        cursor->rowid = 0;
        cursor->finished = FALSE;
@@ -281,6 +285,52 @@ collect_properties (TrackerTriplesCursor *cursor)
        }
 }
 
+static int
+collect_graphs (TrackerTriplesCursor *cursor)
+{
+       sqlite3_stmt *stmt;
+       int rc;
+
+       rc = sqlite3_prepare_v2 (cursor->vtab->module->db,
+                                "SELECT 0, \"main\" "
+                                "UNION ALL "
+                                "SELECT ID, "
+                                "       (SELECT Uri from Resource where Resource.ID = Graph.ID) "
+                                "FROM Graph",
+                                -1, &stmt, 0);
+       if (rc != SQLITE_OK)
+               return rc;
+
+       cursor->query_graphs = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+
+       while ((rc = sqlite3_step (stmt)) == SQLITE_ROW) {
+               const gchar *uri;
+               gint id;
+
+               id = sqlite3_column_int (stmt, 0);
+               uri = sqlite3_column_text (stmt, 1);
+
+               if (cursor->match.graph) {
+                       gboolean negated = !!(cursor->match.idxFlags & IDX_MATCH_GRAPH_NEG);
+                       gboolean equals = (sqlite3_value_int64 (cursor->match.graph) == id);
+
+                       if (equals == negated)
+                               continue;
+               }
+
+               g_hash_table_insert (cursor->query_graphs,
+                                    GINT_TO_POINTER (id),
+                                    g_strdup (uri));
+       }
+
+       if (rc == SQLITE_DONE)
+               cursor->graphs = g_hash_table_get_keys (cursor->query_graphs);
+
+       sqlite3_finalize (stmt);
+
+       return rc;
+}
+
 static gchar *
 convert_to_string (const gchar         *table_name,
                   TrackerPropertyType  type)
@@ -348,42 +398,62 @@ bind_arg (sqlite3_stmt  *stmt,
        sqlite3_bind_value (stmt, idx, value);
 }
 
+static gboolean
+iterate_next_stmt (TrackerTriplesCursor  *cursor,
+                   const gchar          **graph,
+                   gint                  *graph_id,
+                   TrackerProperty      **property)
+{
+       while (cursor->properties && !cursor->graphs) {
+               /* Iterate to next property, and redo graph list */
+               cursor->properties = g_list_remove (cursor->properties,
+                                                   cursor->properties->data);
+               cursor->graphs = g_hash_table_get_keys (cursor->query_graphs);
+       }
+
+       if (!cursor->properties)
+               return FALSE;
+
+       *property = cursor->properties->data;
+       *graph_id = GPOINTER_TO_INT (cursor->graphs->data);
+       *graph = g_hash_table_lookup (cursor->query_graphs,
+                                     cursor->graphs->data);
+
+       cursor->graphs = g_list_remove (cursor->graphs, cursor->graphs->data);
+
+       return TRUE;
+}
+
 static int
 init_stmt (TrackerTriplesCursor *cursor)
 {
        TrackerProperty *property;
+       const gchar *graph;
+       gint graph_id;
        GString *sql;
        int rc;
 
-       while (cursor->properties) {
+       while (iterate_next_stmt (cursor, &graph, &graph_id, &property)) {
                gchar *string_expr;
 
-               property = cursor->properties->data;
-               cursor->properties = g_list_remove (cursor->properties, property);
-
                string_expr = convert_to_string (tracker_property_get_name (property),
                                                 tracker_property_get_data_type (property));
 
                sql = g_string_new (NULL);
                g_string_append_printf (sql,
-                                       "SELECT t.graph, t.ID, "
+                                       "SELECT %d, t.ID, "
                                        "       (SELECT ID From Resource WHERE Uri = \"%s\"), "
                                        "       %s, "
                                        "       %d "
-                                       "FROM \"unionGraph_%s\" AS t "
+                                       "FROM \"%s\".\"%s\" AS t "
                                        "WHERE 1 ",
+                                       graph_id,
                                        tracker_property_get_uri (property),
                                        string_expr,
                                        tracker_property_get_data_type (property),
+                                       graph,
                                        tracker_property_get_table_name (property));
 
-               if (cursor->match.graph) {
-                       g_string_append (sql, "AND t.graph ");
-                       add_arg_check (sql, cursor->match.graph,
-                                      !!(cursor->match.idxFlags & IDX_MATCH_GRAPH_NEG),
-                                      "@g");
-               }
-
                if (cursor->match.subject) {
                        g_string_append (sql, "AND t.ID ");
                        add_arg_check (sql, cursor->match.subject,
@@ -443,8 +513,10 @@ triples_filter (sqlite3_vtab_cursor  *vtab_cursor,
 
        cursor->match.idxFlags = idx;
 
-       collect_properties (cursor);
+       if ((rc = collect_graphs (cursor)) != SQLITE_DONE)
+               return rc;
 
+       collect_properties (cursor);
        rc = init_stmt (cursor);
 
        if (rc == SQLITE_DONE)


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