[tracker/wip/carlosg/portal: 7/34] libtracker-data: Add support for CONSTRAINT query prologues



commit 45909ac68135859ddf8747601f10828426d21c7f
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Jan 23 15:49:59 2020 +0100

    libtracker-data: Add support for CONSTRAINT query prologues
    
    This prologue declaration is a Tracker extension, in order to
    constraint access to graphs and services within the query.
    Successive CONSTRAINT calls will intersect with previous ones,
    meaning that the dataset can only be shrunk and no clause will
    be violated.
    
    We allow 2 types of CONSTRAINT clauses, for graphs (CONSTRAINT
    GRAPH) and services (CONSTRAINT SERVICE). These take a list of
    comma-separated IRIREFs. An empty list is also accepted, resulting
    in the most restrictive (empty) set. No clauses will mean access
    to graphs and services is undeterred.

 src/libtracker-data/tracker-sparql-grammar.h | 20 ++++++-
 src/libtracker-data/tracker-sparql.c         | 81 +++++++++++++++++++++++++++-
 2 files changed, 97 insertions(+), 4 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-grammar.h b/src/libtracker-data/tracker-sparql-grammar.h
index 0372a890f..997c0f0f4 100644
--- a/src/libtracker-data/tracker-sparql-grammar.h
+++ b/src/libtracker-data/tracker-sparql-grammar.h
@@ -31,6 +31,7 @@ typedef enum {
        NAMED_RULE_Prologue,
        NAMED_RULE_BaseDecl,
        NAMED_RULE_PrefixDecl,
+       NAMED_RULE_ConstraintDecl,
        NAMED_RULE_SelectQuery,
        NAMED_RULE_SubSelect,
        NAMED_RULE_ConstructQuery,
@@ -191,6 +192,7 @@ typedef enum {
        LITERAL_COLON,
        LITERAL_CONCAT,
        LITERAL_CONTAINS,
+       LITERAL_CONSTRAINT,
        LITERAL_COMMA,
        LITERAL_CONSTRUCT,
        LITERAL_COPY,
@@ -341,6 +343,7 @@ static const gchar literals[][N_LITERALS] = {
        ":", /* LITERAL_COLON */
        "concat", /* LITERAL_CONCAT */
        "contains", /* LITERAL_CONTAINS */
+       "constraint", /* LITERAL_CONSTRAINT */
        ",", /* LITERAL_COMMA */
        "construct", /* LITERAL_CONSTRUCT */
        "copy", /* LITERAL_COPY */
@@ -1498,14 +1501,26 @@ static const TrackerGrammarRule rule_SelectQuery[] = { R(SelectClause), GTE0(hel
  */
 static const TrackerGrammarRule rule_PrefixDecl[] = { L(PREFIX), T(PNAME_NS), T(IRIREF), NIL };
 
+/* ConstraintDecl ::= 'CONSTRAINT' ( 'GRAPH' | 'SERVICE' ) ( IRIREF (',' IRIREF)* )?
+ *
+ * TRACKER EXTENSION
+ */
+static const TrackerGrammarRule helper_ConstraintDecl_or_1[] = { L(GRAPH), L(SERVICE), NIL };
+static const TrackerGrammarRule helper_ConstraintDecl_seq_1[] = { L(COMMA), T(IRIREF), NIL };
+static const TrackerGrammarRule helper_ConstraintDecl_gte0_1[] = { S(helper_ConstraintDecl_seq_1), NIL };
+static const TrackerGrammarRule helper_ConstraintDecl_opt_1[] = { T(IRIREF), 
GTE0(helper_ConstraintDecl_gte0_1), NIL };
+static const TrackerGrammarRule rule_ConstraintDecl[] = { L(CONSTRAINT), OR(helper_ConstraintDecl_or_1), 
OPT(helper_ConstraintDecl_opt_1), NIL };
 
 /* BaseDecl ::= 'BASE' IRIREF
  */
 static const TrackerGrammarRule rule_BaseDecl[] = { L(BASE), T(IRIREF), NIL };
 
-/* Prologue ::= ( BaseDecl | PrefixDecl )*
+/* Prologue ::= ( BaseDecl | PrefixDecl | ConstraintDecl )*
+ *
+ * TRACKER EXTENSION:
+ * ConstraintDecl entirely.
  */
-static const TrackerGrammarRule helper_Prologue_or[] = { R(BaseDecl), R(PrefixDecl), NIL };
+static const TrackerGrammarRule helper_Prologue_or[] = { R(BaseDecl), R(PrefixDecl), R(ConstraintDecl), NIL 
};
 static const TrackerGrammarRule helper_Prologue_gte0[] = { OR(helper_Prologue_or), NIL };
 static const TrackerGrammarRule rule_Prologue[] = { GTE0 (helper_Prologue_gte0), NIL };
 
@@ -2144,6 +2159,7 @@ static const TrackerGrammarRule *named_rules[N_NAMED_RULES] = {
        rule_Prologue,
        rule_BaseDecl,
        rule_PrefixDecl,
+       rule_ConstraintDecl,
        rule_SelectQuery,
        rule_SubSelect,
        rule_ConstructQuery,
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 1f3563ddc..5b3032870 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -2524,11 +2524,16 @@ translate_Prologue (TrackerSparql  *sparql,
 {
        TrackerGrammarNamedRule rule;
 
-       /* Prologue ::= ( BaseDecl | PrefixDecl )*
+       /* Prologue ::= ( BaseDecl | PrefixDecl | ConstraintDecl )*
+        *
+        * TRACKER EXTENSION:
+        * ConstraintDecl entirely.
         */
        rule = _current_rule (sparql);
 
-       while (rule == NAMED_RULE_BaseDecl || rule == NAMED_RULE_PrefixDecl) {
+       while (rule == NAMED_RULE_BaseDecl ||
+              rule == NAMED_RULE_PrefixDecl ||
+              rule == NAMED_RULE_ConstraintDecl) {
                _call_rule (sparql, rule, error);
                rule = _current_rule (sparql);
        }
@@ -2576,6 +2581,77 @@ translate_PrefixDecl (TrackerSparql  *sparql,
        return TRUE;
 }
 
+static void
+intersect_set (GPtrArray *array,
+               GPtrArray *set)
+{
+       const gchar *set_graph, *graph;
+       gint i = 0, j;
+       gboolean found;
+
+       while (i < array->len) {
+               graph = g_ptr_array_index (array, i);
+               found = FALSE;
+
+               for (j = 0; j < set->len; j++) {
+                       set_graph = g_ptr_array_index (set, j);
+
+                       if (g_strcmp0 (set_graph, graph) == 0) {
+                               found = TRUE;
+                               break;
+                       }
+               }
+
+               if (found) {
+                       i++;
+               } else {
+                       g_ptr_array_remove_index_fast (array, i);
+               }
+       }
+}
+
+static gboolean
+translate_ConstraintDecl (TrackerSparql  *sparql,
+                          GError        **error)
+{
+       GPtrArray **previous_set, *set;
+
+       /* ConstraintDecl ::= 'CONSTRAINT' ( 'GRAPH' | 'SERVICE' ) ( IRIREF (',' IRIREF)* )?
+        *
+        * TRACKER EXTENSION
+        */
+       _expect (sparql, RULE_TYPE_LITERAL, LITERAL_CONSTRAINT);
+
+       if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_GRAPH)) {
+               previous_set = &sparql->policy.graphs;
+       } else if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_SERVICE)) {
+               previous_set = &sparql->policy.services;
+       } else {
+               g_assert_not_reached ();
+       }
+
+       set = g_ptr_array_new_with_free_func (g_free);
+
+       while (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_IRIREF)) {
+               gchar *elem;
+
+               elem = _dup_last_string (sparql);
+               g_ptr_array_add (set, elem);
+
+               if (!_accept (sparql, RULE_TYPE_LITERAL, LITERAL_COMMA))
+                       break;
+       }
+
+       if (*previous_set) {
+               intersect_set (*previous_set, set);
+               g_ptr_array_unref (set);
+       } else {
+               *previous_set = set;
+       }
+
+       return TRUE;
+}
+
 static gboolean
 _check_undefined_variables (TrackerSparql         *sparql,
                             TrackerSelectContext  *context,
@@ -8415,6 +8491,7 @@ const RuleTranslationFunc rule_translation_funcs[N_NAMED_RULES] = {
        translate_Prologue,
        translate_BaseDecl,
        translate_PrefixDecl,
+       translate_ConstraintDecl,
        translate_SelectQuery,
        translate_SubSelect,
        translate_ConstructQuery,


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