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



commit 801a35b0b48e706fe5dfc3be3ba2416461fb7033
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 5f9fa4a52..1073d2fdd 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 */
@@ -1506,14 +1509,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 };
 
@@ -2152,6 +2167,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 f84b1b6c9..7ecfbc649 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -2607,11 +2607,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);
        }
@@ -2659,6 +2664,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,
@@ -8665,6 +8741,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]