[tracker/wip/carlosg/vars-in-service: 1/2] libtracker-data: Handle variables for SERVICE clauses correctly




commit 9c84dce97b085949dc895b60d3fdc9419eb45edf
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Jan 26 10:07:32 2021 +0100

    libtracker-data: Handle variables for SERVICE clauses correctly
    
    The sparql1.1 spec allows the use of variables in SERVICE clauses,
    e.g.:
    
      ... SERVICE ?s { ... } ...
    
    Where ?s is a variable resolved in other parts of the graph pattern.
    https://www.w3.org/TR/2013/REC-sparql11-federated-query-20130321/#variableService
    precisely advocates that query execution order should resolve the
    possible values for the queried services before attempting to access
    those.
    
    Let Tracker do this somersault, if the service is a variable instead
    of a literal propagate it up as a variable in the subselect so it is
    matched together with all other variables when JOINed with the other
    bits of the graph pattern, and let the services virtual table enforce
    the execution order that resolves the service variable by returning
    SQLITE_CONSTRAINT if the service column is missing. This makes SQLite
    try the alternative execution orders, and eventually find one that
    resolves the service variable when executing the remote service(s).
    
    This allows delegating service queries to a variable, which may be
    useful if e.g. we want to propagate a same query to multiple services:
    
      SELECT ?u {
        SERVICE ?s {
          ?u a nfo:Document
        }
      }
      VALUES ?s { 'dbus:...', 'dbus:...' }

 src/libtracker-data/tracker-sparql.c       | 17 +++++++++++++++--
 src/libtracker-data/tracker-vtab-service.c |  7 +++++++
 2 files changed, 22 insertions(+), 2 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 2a3e8c17b..9b0f5701f 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -5214,6 +5214,15 @@ translate_ServiceGraphPattern (TrackerSparql  *sparql,
                i++;
        }
 
+       if (tracker_token_get_variable (&service)) {
+               if (variable_rules != NULL)
+                       _append_string (sparql, ", ");
+
+               _append_string_printf (sparql, "service AS %s ",
+                                      tracker_token_get_idstring (&service));
+               join_vars = g_list_prepend (join_vars, tracker_token_get_variable (&service));
+       }
+
        tracker_parser_node_get_extents (pattern, &pattern_start, &pattern_end);
        pattern_str = g_strndup (&sparql->sparql[pattern_start], pattern_end - pattern_start);
        escaped_str = _escape_sql_string (pattern_str, '"');
@@ -5222,11 +5231,15 @@ translate_ServiceGraphPattern (TrackerSparql  *sparql,
        g_free (pattern_str);
        g_free (escaped_str);
 
-       _append_string_printf (sparql, "FROM tracker_service WHERE service=\"%s\" AND query=\"%s\" AND 
silent=%d ",
-                              tracker_token_get_idstring (&service),
+       _append_string_printf (sparql, "FROM tracker_service WHERE query=\"%s\" AND silent=%d ",
                               service_sparql->str,
                               silent);
 
+       if (!tracker_token_get_variable (&service)) {
+               _append_string_printf (sparql, "AND service=\"%s\" ",
+                                      tracker_token_get_idstring (&service));
+       }
+
        i = 0;
 
        /* Proxy parameters to the virtual table */
diff --git a/src/libtracker-data/tracker-vtab-service.c b/src/libtracker-data/tracker-vtab-service.c
index a14d50509..628ecada1 100644
--- a/src/libtracker-data/tracker-vtab-service.c
+++ b/src/libtracker-data/tracker-vtab-service.c
@@ -158,6 +158,7 @@ service_best_index (sqlite3_vtab       *vtab,
 {
        int i, argv_idx = 1;
        ConstraintData *data;
+       gboolean has_service = FALSE;
 
        data = sqlite3_malloc (sizeof (ConstraintData) * info->nConstraint);
        bzero (data, sizeof (ConstraintData) * info->nConstraint);
@@ -174,6 +175,9 @@ service_best_index (sqlite3_vtab       *vtab,
                if (info->aConstraint[i].op != SQLITE_INDEX_CONSTRAINT_EQ)
                        goto error;
 
+               if (info->aConstraint[i].iColumn == COL_SERVICE)
+                       has_service = TRUE;
+
                data[i].column = info->aConstraint[i].iColumn;
                data[i].op = info->aConstraint[i].op;
 
@@ -186,6 +190,9 @@ service_best_index (sqlite3_vtab       *vtab,
        info->idxStr = (char *) data;
        info->needToFreeIdxStr = TRUE;
 
+       if (!has_service)
+               return SQLITE_CONSTRAINT;
+
        return SQLITE_OK;
 
 error:


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