[tracker/wip/carlosg/sparql1.1: 116/201] libtracker-sparql: Implement PathNegatedPropertySet



commit 519e4a1628fce4d55d442bb3f918a543a2c3c04c
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Jun 14 02:50:53 2019 +0200

    libtracker-sparql: Implement PathNegatedPropertySet

 src/libtracker-data/tracker-sparql-types.c |  19 ++++-
 src/libtracker-data/tracker-sparql-types.h |   5 +-
 src/libtracker-data/tracker-sparql.c       | 128 ++++++++++++++++++++++++++++-
 3 files changed, 143 insertions(+), 9 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-types.c b/src/libtracker-data/tracker-sparql-types.c
index 6ac613640..4f100ae03 100644
--- a/src/libtracker-data/tracker-sparql-types.c
+++ b/src/libtracker-data/tracker-sparql-types.c
@@ -523,14 +523,17 @@ tracker_path_element_free (TrackerPathElement *elem)
 }
 
 TrackerPathElement *
-tracker_path_element_property_new (TrackerProperty *prop)
+tracker_path_element_property_new (TrackerPathOperator  op,
+                                   TrackerProperty     *prop)
 {
        TrackerPathElement *elem;
 
        g_return_val_if_fail (TRACKER_IS_PROPERTY (prop), NULL);
+       g_return_val_if_fail (op == TRACKER_PATH_OPERATOR_NONE ||
+                             op == TRACKER_PATH_OPERATOR_NEGATED, NULL);
 
        elem = g_new0 (TrackerPathElement, 1);
-       elem->op = TRACKER_PATH_OPERATOR_NONE;
+       elem->op = op;
        elem->type = tracker_property_get_data_type (prop);
        elem->data.property = prop;
 
@@ -544,11 +547,13 @@ tracker_path_element_operator_new (TrackerPathOperator  op,
 {
        TrackerPathElement *elem;
 
-       g_return_val_if_fail (op != TRACKER_PATH_OPERATOR_NONE, NULL);
+       g_return_val_if_fail (op != TRACKER_PATH_OPERATOR_NONE &&
+                             op != TRACKER_PATH_OPERATOR_NEGATED, NULL);
        g_return_val_if_fail (child1 != NULL, NULL);
        g_return_val_if_fail (child2 == NULL ||
                              op == TRACKER_PATH_OPERATOR_SEQUENCE ||
-                             op == TRACKER_PATH_OPERATOR_ALTERNATIVE, NULL);
+                             op == TRACKER_PATH_OPERATOR_ALTERNATIVE ||
+                             op == TRACKER_PATH_OPERATOR_INTERSECTION, NULL);
 
        elem = g_new0 (TrackerPathElement, 1);
        elem->op = op;
@@ -587,6 +592,12 @@ tracker_path_element_set_unique_name (TrackerPathElement *elem,
        case TRACKER_PATH_OPERATOR_ONEORMORE:
                name = "oneormore";
                break;
+       case TRACKER_PATH_OPERATOR_NEGATED:
+               name = "neg";
+               break;
+       case TRACKER_PATH_OPERATOR_INTERSECTION:
+               name = "intersect";
+               break;
        default:
                g_assert_not_reached ();
        }
diff --git a/src/libtracker-data/tracker-sparql-types.h b/src/libtracker-data/tracker-sparql-types.h
index ac088d473..616405205 100644
--- a/src/libtracker-data/tracker-sparql-types.h
+++ b/src/libtracker-data/tracker-sparql-types.h
@@ -154,6 +154,8 @@ typedef enum {
        TRACKER_PATH_OPERATOR_ZEROORONE,   /* ? */
        TRACKER_PATH_OPERATOR_ONEORMORE,   /* + */
        TRACKER_PATH_OPERATOR_ZEROORMORE,  /* * */
+       TRACKER_PATH_OPERATOR_NEGATED,     /* ! */
+       TRACKER_PATH_OPERATOR_INTERSECTION, /* Used for negated paths */
 } TrackerPathOperator;
 
 struct _TrackerPathElement {
@@ -317,7 +319,8 @@ void              tracker_solution_add_value       (TrackerSolution *solution,
 GHashTable      * tracker_solution_get_bindings    (TrackerSolution *solution);
 
 /* Property path element */
-TrackerPathElement * tracker_path_element_property_new (TrackerProperty *prop);
+TrackerPathElement * tracker_path_element_property_new (TrackerPathOperator  op,
+                                                        TrackerProperty     *prop);
 TrackerPathElement * tracker_path_element_operator_new (TrackerPathOperator  op,
                                                         TrackerPathElement  *child1,
                                                         TrackerPathElement  *child2);
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 3dc4f175c..b933ce1b9 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -640,6 +640,27 @@ _prepend_path_element (TrackerSparql      *sparql,
                                       path_elem->data.composite.child1->name,
                                       path_elem->data.composite.child1->name);
                break;
+       case TRACKER_PATH_OPERATOR_NEGATED:
+               _append_string_printf (sparql,
+                                      "\"%s\" (ID, value, graph) AS "
+                                      "(SELECT subject AS ID, object AS value, graph "
+                                      "FROM \"tracker_triples\" "
+                                      "WHERE predicate != %d",
+                                      path_elem->name,
+                                      tracker_property_get_id (path_elem->data.property));
+               break;
+       case TRACKER_PATH_OPERATOR_INTERSECTION:
+               _append_string_printf (sparql,
+                                      "\"%s\" (ID, value, graph) AS "
+                                      "(SELECT ID, value, graph "
+                                      "FROM \"%s\" "
+                                      "INTERSECT "
+                                      "SELECT ID, value, graph "
+                                      "FROM \"%s\") ",
+                                      path_elem->name,
+                                      path_elem->data.composite.child1->name,
+                                      path_elem->data.composite.child2->name);
+               break;
        }
 
        tracker_sparql_swap_builder (sparql, old);
@@ -4970,7 +4991,7 @@ translate_PathPrimary (TrackerSparql  *sparql,
                                                                                 prop);
 
                if (!path_elem) {
-                       path_elem = tracker_path_element_property_new (prop);
+                       path_elem = tracker_path_element_property_new (TRACKER_PATH_OPERATOR_NONE, prop);
                        tracker_select_context_add_path_element (TRACKER_SELECT_CONTEXT (sparql->context),
                                                                 path_elem);
                        _prepend_path_element (sparql, path_elem);
@@ -4989,19 +5010,118 @@ static gboolean
 translate_PathNegatedPropertySet (TrackerSparql  *sparql,
                                   GError        **error)
 {
+       TrackerPathElement *path_elem;
+
        /* PathNegatedPropertySet ::= PathOneInPropertySet | '(' ( PathOneInPropertySet ( '|' 
PathOneInPropertySet )* )? ')'
         */
-       _unimplemented ("Negated property set in property paths");
-       return FALSE;
+       if (_check_in_rule (sparql, NAMED_RULE_PathOneInPropertySet))
+               _call_rule (sparql, NAMED_RULE_PathOneInPropertySet, error);
+       else if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_OPEN_PARENS)) {
+               GPtrArray *path_elems;
+
+               path_elems = g_ptr_array_new ();
+
+               _call_rule (sparql, NAMED_RULE_PathEltOrInverse, error);
+               g_ptr_array_add (path_elems, sparql->current_state.path);
+
+               while (_check_in_rule (sparql, NAMED_RULE_PathOneInPropertySet)) {
+                       _call_rule (sparql, NAMED_RULE_PathOneInPropertySet, error);
+                       g_ptr_array_add (path_elems, sparql->current_state.path);
+               }
+
+               if (path_elems->len > 1) {
+                       gint i;
+
+                       path_elem = tracker_path_element_operator_new (TRACKER_PATH_OPERATOR_INTERSECTION,
+                                                                      g_ptr_array_index (path_elems, 0),
+                                                                      g_ptr_array_index (path_elems, 1));
+                       tracker_select_context_add_path_element (TRACKER_SELECT_CONTEXT (sparql->context),
+                                                                path_elem);
+                       _prepend_path_element (sparql, path_elem);
+
+                       for (i = 2; i < path_elems->len; i++) {
+                               TrackerPathElement *child;
+
+                               child = g_ptr_array_index (path_elems, i);
+                               path_elem = tracker_path_element_operator_new 
(TRACKER_PATH_OPERATOR_INTERSECTION,
+                                                                              child, path_elem);
+                               tracker_select_context_add_path_element (TRACKER_SELECT_CONTEXT 
(sparql->context),
+                                                                        path_elem);
+                               _prepend_path_element (sparql, path_elem);
+                       }
+
+                       sparql->current_state.path = path_elem;
+               }
+
+               _expect (sparql, RULE_TYPE_LITERAL, LITERAL_CLOSE_PARENS);
+       } else {
+               g_assert_not_reached ();
+       }
+
+       return TRUE;
 }
 
 static gboolean
 translate_PathOneInPropertySet (TrackerSparql  *sparql,
                                 GError        **error)
 {
+       TrackerPathElement *path_elem;
+       gboolean inverse = FALSE;
+
        /* PathOneInPropertySet ::= iri | 'a' | '^' ( iri | 'a' )
         */
-       return FALSE;
+       if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_PATH_INVERSE))
+               inverse = TRUE;
+
+       if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_A) ||
+           _check_in_rule (sparql, NAMED_RULE_iri)) {
+               TrackerOntologies *ontologies;
+               TrackerProperty *prop;
+               gchar *str;
+
+               if (_check_in_rule (sparql, NAMED_RULE_iri))
+                       _call_rule (sparql, NAMED_RULE_iri, error);
+
+               str = _dup_last_string (sparql);
+               ontologies = tracker_data_manager_get_ontologies (sparql->data_manager);
+               prop = tracker_ontologies_get_property_by_uri (ontologies, str);
+
+               if (!prop) {
+                       g_set_error (error, TRACKER_SPARQL_ERROR,
+                                    TRACKER_SPARQL_ERROR_UNKNOWN_PROPERTY,
+                                    "Unknown property '%s'", str);
+                       g_free (str);
+                       return FALSE;
+               }
+
+               path_elem =
+                       tracker_select_context_lookup_path_element_for_property (TRACKER_SELECT_CONTEXT 
(sparql->context),
+                                                                                prop);
+
+               if (!path_elem) {
+                       path_elem = tracker_path_element_property_new (TRACKER_PATH_OPERATOR_NEGATED, prop);
+                       tracker_select_context_add_path_element (TRACKER_SELECT_CONTEXT (sparql->context),
+                                                                path_elem);
+                       _prepend_path_element (sparql, path_elem);
+               }
+
+               sparql->current_state.path = path_elem;
+               g_free (str);
+       } else {
+               g_assert_not_reached ();
+       }
+
+       if (inverse) {
+               path_elem = tracker_path_element_operator_new (TRACKER_PATH_OPERATOR_INVERSE,
+                                                              sparql->current_state.path,
+                                                              NULL);
+               tracker_select_context_add_path_element (TRACKER_SELECT_CONTEXT (sparql->context),
+                                                        path_elem);
+               _prepend_path_element (sparql, path_elem);
+               sparql->current_state.path = path_elem;
+       }
+
+       return TRUE;
 }
 
 static gboolean


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