summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2020-03-08 14:44:37 +0000
committerSam Thursfield <sam@afuera.me.uk>2020-03-08 14:44:37 +0000
commit911f37ecb546bbfe77d16ba2a006253ad85062cc (patch)
tree80c03108313d600dd02329924acda27741bd3a78
parent5aaf4ec03241a8619335630f620944c7c07e848e (diff)
parentbd01f6c28fe3d5a15753e17f539ff269c854e7b9 (diff)
downloadtracker-911f37ecb546bbfe77d16ba2a006253ad85062cc.tar.gz
Merge branch 'wip/carlosg/fix-minus' into 'master'
Fix MINUS support Closes #190 See merge request GNOME/tracker!195
-rw-r--r--meson.build3
-rw-r--r--src/libtracker-data/tracker-sparql.c100
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-1.out5
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-1.rq7
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-2.out0
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-2.rq7
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-3.out5
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-3.rq7
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-4.out0
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-4.rq7
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-5.out77
-rw-r--r--tests/libtracker-data/subqueries/subqueries-minus-5.rq7
-rw-r--r--tests/libtracker-data/tracker-sparql-test.c5
13 files changed, 211 insertions, 19 deletions
diff --git a/meson.build b/meson.build
index 2226fb930..fbfb88d7a 100644
--- a/meson.build
+++ b/meson.build
@@ -33,7 +33,8 @@ glib_required = '2.52.0'
# 3.7.9 for FTS4 content= support
# 3.7.15 for sqlite3_errstr() support
# 3.8.3 for SQLITE_DETERMINISTIC
-sqlite_required = '3.8.3'
+# 3.15.0 for https://sqlite.org/rowvalue.html
+sqlite_required = '3.15.0'
dbus = dependency('dbus-1', version: '> 1.3.1')
gio = dependency('gio-2.0', version: '>' + glib_required)
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 988e94930..314863169 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -4977,24 +4977,10 @@ translate_DataBlockValue (TrackerSparql *sparql,
return TRUE;
}
-static gboolean
-translate_MinusGraphPattern (TrackerSparql *sparql,
- GError **error)
-{
- /* MinusGraphPattern ::= 'MINUS' GroupGraphPattern
- */
- _expect (sparql, RULE_TYPE_LITERAL, LITERAL_MINUS);
- _prepend_string (sparql, "SELECT * FROM (");
- _append_string (sparql, ") EXCEPT ");
- _call_rule (sparql, NAMED_RULE_GroupGraphPattern, error);
-
- return TRUE;
-}
-
static void
-append_union_select_vars (TrackerSparql *sparql,
- TrackerContext *context,
- GList *vars)
+append_subquery_select_vars (TrackerSparql *sparql,
+ TrackerContext *context,
+ GList *vars)
{
GList *l;
@@ -5019,6 +5005,84 @@ append_union_select_vars (TrackerSparql *sparql,
_append_string (sparql, "FROM (");
}
+static GList *
+intersect_var_set (GHashTable *ht1,
+ GHashTable *ht2)
+{
+ GHashTableIter iter;
+ GList *intersection = NULL;
+ gpointer key;
+
+ g_hash_table_iter_init (&iter, ht1);
+
+ while (g_hash_table_iter_next (&iter, &key, NULL)) {
+ if (g_hash_table_contains (ht2, key))
+ intersection = g_list_prepend (intersection, key);
+ }
+
+ return intersection;
+}
+
+
+static gboolean
+translate_MinusGraphPattern (TrackerSparql *sparql,
+ GError **error)
+{
+ TrackerStringBuilder *pre, *post, *cur;
+ TrackerContext *cur_context, *context;
+ GList *intersection, *l, *vars;
+
+ cur_context = sparql->current_state.context;
+
+ /* MinusGraphPattern ::= 'MINUS' GroupGraphPattern
+ */
+ _expect (sparql, RULE_TYPE_LITERAL, LITERAL_MINUS);
+
+ pre = _prepend_placeholder (sparql);
+ post = _append_placeholder (sparql);
+
+ context = tracker_context_new ();
+ tracker_sparql_push_context (sparql, context);
+ _call_rule (sparql, NAMED_RULE_GroupGraphPattern, error);
+ tracker_sparql_pop_context (sparql, FALSE);
+
+ intersection = intersect_var_set (cur_context->variable_set, context->variable_set);
+
+ vars = g_hash_table_get_keys (cur_context->variable_set);
+ cur = tracker_sparql_swap_builder (sparql, pre);
+ append_subquery_select_vars (sparql, cur_context, vars);
+ tracker_sparql_swap_builder (sparql, cur);
+
+ if (intersection) {
+ cur = tracker_sparql_swap_builder (sparql, post);
+ _append_string (sparql, ") WHERE (");
+ for (l = intersection; l; l = l->next) {
+ if (l != intersection)
+ _append_string (sparql, ", ");
+ _append_string_printf (sparql, "%s ",
+ tracker_variable_get_sql_expression (l->data));
+ }
+
+ _append_string (sparql, ") NOT IN (");
+ append_subquery_select_vars (sparql, context, intersection);
+
+ tracker_sparql_swap_builder (sparql, cur);
+ _append_string (sparql, ")) ");
+ g_list_free (intersection);
+ } else {
+ cur = tracker_sparql_swap_builder (sparql, post);
+ _append_string (sparql, ") EXCEPT ");
+ append_subquery_select_vars (sparql, context, vars);
+
+ tracker_sparql_swap_builder (sparql, cur);
+ _append_string (sparql, ") ");
+ }
+
+ g_list_free (vars);
+
+ return TRUE;
+}
+
static gboolean
translate_GroupOrUnionGraphPattern (TrackerSparql *sparql,
GError **error)
@@ -5072,7 +5136,7 @@ translate_GroupOrUnionGraphPattern (TrackerSparql *sparql,
if (c != context->children)
_append_string (sparql, ") UNION ALL ");
- append_union_select_vars (sparql, c->data, vars);
+ append_subquery_select_vars (sparql, c->data, vars);
tracker_sparql_swap_builder (sparql, old);
idx++;
}
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-1.out b/tests/libtracker-data/subqueries/subqueries-minus-1.out
new file mode 100644
index 000000000..7baa303ae
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-1.out
@@ -0,0 +1,5 @@
+"http://example.org/ns#msg1"
+"http://example.org/ns#msg2"
+"http://example.org/ns#msg3"
+"http://example.org/ns#msg4"
+"http://example.org/ns#msg5"
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-1.rq b/tests/libtracker-data/subqueries/subqueries-minus-1.rq
new file mode 100644
index 000000000..0268be189
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-1.rq
@@ -0,0 +1,7 @@
+SELECT ?s WHERE {
+ {
+ ?s a example:Message
+ } MINUS {
+ ?s a example:Group
+ }
+} ORDER BY ?s
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-2.out b/tests/libtracker-data/subqueries/subqueries-minus-2.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-2.out
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-2.rq b/tests/libtracker-data/subqueries/subqueries-minus-2.rq
new file mode 100644
index 000000000..81dc02fa6
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-2.rq
@@ -0,0 +1,7 @@
+SELECT ?s WHERE {
+ {
+ ?s a example:Message
+ } MINUS {
+ ?s a example:Message
+ }
+} ORDER BY ?s
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-3.out b/tests/libtracker-data/subqueries/subqueries-minus-3.out
new file mode 100644
index 000000000..7baa303ae
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-3.out
@@ -0,0 +1,5 @@
+"http://example.org/ns#msg1"
+"http://example.org/ns#msg2"
+"http://example.org/ns#msg3"
+"http://example.org/ns#msg4"
+"http://example.org/ns#msg5"
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-3.rq b/tests/libtracker-data/subqueries/subqueries-minus-3.rq
new file mode 100644
index 000000000..f61a92f92
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-3.rq
@@ -0,0 +1,7 @@
+SELECT ?one WHERE {
+ {
+ ?one a example:Message
+ } MINUS {
+ ?another a example:Message
+ }
+} ORDER BY ?one
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-4.out b/tests/libtracker-data/subqueries/subqueries-minus-4.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-4.out
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-4.rq b/tests/libtracker-data/subqueries/subqueries-minus-4.rq
new file mode 100644
index 000000000..b8367e2f7
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-4.rq
@@ -0,0 +1,7 @@
+SELECT ?s WHERE {
+ {
+ ?s a example:Message
+ } MINUS {
+ ?s a ?u
+ }
+} ORDER BY ?s
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-5.out b/tests/libtracker-data/subqueries/subqueries-minus-5.out
new file mode 100644
index 000000000..0a978f6ea
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-5.out
@@ -0,0 +1,77 @@
+"http://example.org/ns#"
+"http://example.org/ns#Group"
+"http://example.org/ns#Message"
+"http://example.org/ns#date"
+"http://example.org/ns#group"
+"http://example.org/ns#group1"
+"http://example.org/ns#group2"
+"http://example.org/ns#lastDate"
+"http://purl.org/dc/elements/1.1/"
+"http://purl.org/dc/elements/1.1/contributor"
+"http://purl.org/dc/elements/1.1/coverage"
+"http://purl.org/dc/elements/1.1/creator"
+"http://purl.org/dc/elements/1.1/date"
+"http://purl.org/dc/elements/1.1/description"
+"http://purl.org/dc/elements/1.1/format"
+"http://purl.org/dc/elements/1.1/identifier"
+"http://purl.org/dc/elements/1.1/language"
+"http://purl.org/dc/elements/1.1/publisher"
+"http://purl.org/dc/elements/1.1/relation"
+"http://purl.org/dc/elements/1.1/rights"
+"http://purl.org/dc/elements/1.1/source"
+"http://purl.org/dc/elements/1.1/subject"
+"http://purl.org/dc/elements/1.1/title"
+"http://purl.org/dc/elements/1.1/type"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#Tag"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#deprecated"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#identifier"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isRelated"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#lastModified"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nao#prefLabel"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#InverseFunctionalProperty"
+"http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#maxCardinality"
+"http://www.tracker-project.org/ontologies/tracker#"
+"http://www.tracker-project.org/ontologies/tracker#Namespace"
+"http://www.tracker-project.org/ontologies/tracker#Ontology"
+"http://www.tracker-project.org/ontologies/tracker#damaged"
+"http://www.tracker-project.org/ontologies/tracker#defaultValue"
+"http://www.tracker-project.org/ontologies/tracker#domainIndex"
+"http://www.tracker-project.org/ontologies/tracker#fulltextIndexed"
+"http://www.tracker-project.org/ontologies/tracker#fulltextNoLimit"
+"http://www.tracker-project.org/ontologies/tracker#indexed"
+"http://www.tracker-project.org/ontologies/tracker#notify"
+"http://www.tracker-project.org/ontologies/tracker#prefix"
+"http://www.tracker-project.org/ontologies/tracker#secondaryIndex"
+"http://www.tracker-project.org/ontologies/tracker#weight"
+"http://www.tracker-project.org/ontologies/tracker#writeback"
+"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+"http://www.w3.org/1999/02/22-rdf-syntax-ns#List"
+"http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"
+"http://www.w3.org/1999/02/22-rdf-syntax-ns#first"
+"http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"
+"http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"
+"http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"
+"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
+"http://www.w3.org/2000/01/rdf-schema#"
+"http://www.w3.org/2000/01/rdf-schema#Class"
+"http://www.w3.org/2000/01/rdf-schema#Datatype"
+"http://www.w3.org/2000/01/rdf-schema#Literal"
+"http://www.w3.org/2000/01/rdf-schema#Resource"
+"http://www.w3.org/2000/01/rdf-schema#comment"
+"http://www.w3.org/2000/01/rdf-schema#domain"
+"http://www.w3.org/2000/01/rdf-schema#label"
+"http://www.w3.org/2000/01/rdf-schema#range"
+"http://www.w3.org/2000/01/rdf-schema#subClassOf"
+"http://www.w3.org/2000/01/rdf-schema#subPropertyOf"
+"http://www.w3.org/2001/XMLSchema#"
+"http://www.w3.org/2001/XMLSchema#boolean"
+"http://www.w3.org/2001/XMLSchema#date"
+"http://www.w3.org/2001/XMLSchema#dateTime"
+"http://www.w3.org/2001/XMLSchema#double"
+"http://www.w3.org/2001/XMLSchema#integer"
+"http://www.w3.org/2001/XMLSchema#string"
diff --git a/tests/libtracker-data/subqueries/subqueries-minus-5.rq b/tests/libtracker-data/subqueries/subqueries-minus-5.rq
new file mode 100644
index 000000000..8038da4f0
--- /dev/null
+++ b/tests/libtracker-data/subqueries/subqueries-minus-5.rq
@@ -0,0 +1,7 @@
+SELECT DISTINCT ?s WHERE {
+ {
+ ?s a ?u
+ } MINUS {
+ ?s a example:Message
+ }
+} ORDER BY ?s
diff --git a/tests/libtracker-data/tracker-sparql-test.c b/tests/libtracker-data/tracker-sparql-test.c
index 0e189cb43..acf413823 100644
--- a/tests/libtracker-data/tracker-sparql-test.c
+++ b/tests/libtracker-data/tracker-sparql-test.c
@@ -193,6 +193,11 @@ const TestInfo tests[] = {
{ "subqueries/subqueries-1", "subqueries/data-1", FALSE },
{ "subqueries/subqueries-union-1", "subqueries/data-1", FALSE },
{ "subqueries/subqueries-union-2", "subqueries/data-1", FALSE },
+ { "subqueries/subqueries-minus-1", "subqueries/data-1", FALSE },
+ { "subqueries/subqueries-minus-2", "subqueries/data-1", FALSE },
+ { "subqueries/subqueries-minus-3", "subqueries/data-1", FALSE },
+ { "subqueries/subqueries-minus-4", "subqueries/data-1", FALSE },
+ { "subqueries/subqueries-minus-5", "subqueries/data-1", FALSE },
/* Bracket error after WHERE */
{ "error/query-error-1", "error/query-error-1", TRUE, FALSE },
/* Unknown property */