[tracker/wip/carlosg/sparql1.1: 116/201] libtracker-sparql: Implement PathNegatedPropertySet
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/sparql1.1: 116/201] libtracker-sparql: Implement PathNegatedPropertySet
- Date: Mon, 9 Sep 2019 22:28:33 +0000 (UTC)
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]