From 4c024b53e6f64213284dc8cf7bb94df51859bd21 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sun, 21 Mar 2021 17:38:48 +0100 Subject: libtracker-data: Workaround SQLite 3.35.x bug The optimization for UNION ALLs inside JOINs had another unexpected victim: SELECT * { GRAPH ?g { ?a ... OPTIONAL { ?a ... } } } Does now break when matching the graph between both sides of the LEFT JOIN caused by OPTIONAL, making all other values coming from the right hand side come back empty. Make it sure this specific case is ineligible for query flattening optimizations by adding a LIMIT clause on the right hand side of the LEFT JOIN. This brings back correct over fast. This workaround should be revisited when a SQLite fix is available. --- src/libtracker-data/tracker-sparql.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c index c4aaaaaa9..28c73bf6c 100644 --- a/src/libtracker-data/tracker-sparql.c +++ b/src/libtracker-data/tracker-sparql.c @@ -5085,8 +5085,28 @@ translate_OptionalGraphPattern (TrackerSparql *sparql, _call_rule (sparql, NAMED_RULE_GroupGraphPattern, error); - if (do_join) + if (do_join) { + /* FIXME: This is a workaround for SQLite 3.35.x, where + * the optimization on UNION ALLs inside JOINs (Point 8c in + * the 3.35.0 release notes) break in this very specific + * case: + * + * SELECT * { GRAPH ?g { ?a ... OPTIONAL { ?a ... } } } + * + * This is a workaround to make this one case ineligible + * for query flattening optimizations, specifically make + * it fall through case 8 in the list at + * https://sqlite.org/optoverview.html#flattening, + * "The subquery does not use LIMIT or the outer query is not + * a join.", we will now meet both here. + * + * This should be evaluated again in future SQLite versions. + */ + if (tracker_token_get_variable (&sparql->current_state->graph)) + _append_string (sparql, "LIMIT -1 "); + _append_string (sparql, ") "); + } return TRUE; } -- cgit v1.2.1 From 8a28feb1bff52bf518a4728cbebf2317ffc7b4bd Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sun, 21 Mar 2021 17:55:22 +0100 Subject: tests: Add test for OPTIONAL inside GRAPH ?g {} This broke in recent SQLite releases, and only caught by one tracker-miners test. Make it sure we have a test here for this. --- tests/libtracker-data/graph/graph-7.out | 2 ++ tests/libtracker-data/graph/graph-7.rq | 7 +++++++ tests/libtracker-data/tracker-sparql-test.c | 1 + 3 files changed, 10 insertions(+) create mode 100644 tests/libtracker-data/graph/graph-7.out create mode 100644 tests/libtracker-data/graph/graph-7.rq diff --git a/tests/libtracker-data/graph/graph-7.out b/tests/libtracker-data/graph/graph-7.out new file mode 100644 index 000000000..b87869c39 --- /dev/null +++ b/tests/libtracker-data/graph/graph-7.out @@ -0,0 +1,2 @@ +"http://example/graphA" "http://example/resource" "73" +"http://example/graphB" "http://example/resource" "42" diff --git a/tests/libtracker-data/graph/graph-7.rq b/tests/libtracker-data/graph/graph-7.rq new file mode 100644 index 000000000..a72b4366e --- /dev/null +++ b/tests/libtracker-data/graph/graph-7.rq @@ -0,0 +1,7 @@ +SELECT ?g ?s ?v WHERE { + GRAPH ?g { + ?s a rdfs:Resource . + OPTIONAL { ?s example:p ?v } . + } +} +ORDER BY ?g ?s ?v \ No newline at end of file diff --git a/tests/libtracker-data/tracker-sparql-test.c b/tests/libtracker-data/tracker-sparql-test.c index 9552d0aa4..60475720b 100644 --- a/tests/libtracker-data/tracker-sparql-test.c +++ b/tests/libtracker-data/tracker-sparql-test.c @@ -162,6 +162,7 @@ const TestInfo tests[] = { { "graph/graph-4", "graph/data-3", FALSE }, { "graph/graph-5", "graph/data-4", FALSE }, { "graph/graph-6", "graph/data-5", FALSE }, + { "graph/graph-7", "graph/data-5", FALSE }, { "graph/non-existent-1", "graph/data-1", FALSE }, { "graph/non-existent-2", "graph/data-1", FALSE }, { "graph/non-existent-3", "graph/data-1", FALSE }, -- cgit v1.2.1