diff options
author | Sam Thursfield <sam@afuera.me.uk> | 2020-03-08 14:44:37 +0000 |
---|---|---|
committer | Sam Thursfield <sam@afuera.me.uk> | 2020-03-08 14:44:37 +0000 |
commit | 911f37ecb546bbfe77d16ba2a006253ad85062cc (patch) | |
tree | 80c03108313d600dd02329924acda27741bd3a78 | |
parent | 5aaf4ec03241a8619335630f620944c7c07e848e (diff) | |
parent | bd01f6c28fe3d5a15753e17f539ff269c854e7b9 (diff) | |
download | tracker-911f37ecb546bbfe77d16ba2a006253ad85062cc.tar.gz |
Merge branch 'wip/carlosg/fix-minus' into 'master'
Fix MINUS support
Closes #190
See merge request GNOME/tracker!195
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 */ |