| Index: third_party/sqlite/src/test/where2.test
|
| diff --git a/third_party/sqlite/src/test/where2.test b/third_party/sqlite/src/test/where2.test
|
| index d61c0897e8dae94764de7aa2b61f590ad2c7753f..367eb0dfeadd2ef196d244abf9e45aa074abe8dc 100644
|
| --- a/third_party/sqlite/src/test/where2.test
|
| +++ b/third_party/sqlite/src/test/where2.test
|
| @@ -66,14 +66,24 @@ proc cksort {sql} {
|
|
|
| # This procedure executes the SQL. Then it appends to the result the
|
| # "sort" or "nosort" keyword (as in the cksort procedure above) then
|
| -# it appends the ::sqlite_query_plan variable.
|
| +# it appends the name of the table and index used.
|
| #
|
| proc queryplan {sql} {
|
| set ::sqlite_sort_count 0
|
| set data [execsql $sql]
|
| if {$::sqlite_sort_count} {set x sort} {set x nosort}
|
| lappend data $x
|
| - return [concat $data $::sqlite_query_plan]
|
| + set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
|
| + # puts eqp=$eqp
|
| + foreach {a b c x} $eqp {
|
| + if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
|
| + $x all as tab idx]} {
|
| + lappend data $tab $idx
|
| + } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
|
| + lappend data $tab *
|
| + }
|
| + }
|
| + return $data
|
| }
|
|
|
|
|
| @@ -111,6 +121,42 @@ do_test where2-2.3 {
|
| }
|
| } {85 6 7396 7402 nosort t1 *}
|
|
|
| +# Ticket [65bdeb9739605cc22966f49208452996ff29a640] 2014-02-26
|
| +# Make sure "ORDER BY random" does not gets optimized out.
|
| +#
|
| +do_test where2-2.4 {
|
| + db eval {
|
| + CREATE TABLE x1(a INTEGER PRIMARY KEY, b DEFAULT 1);
|
| + WITH RECURSIVE
|
| + cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<50)
|
| + INSERT INTO x1 SELECT x, 1 FROM cnt;
|
| + CREATE TABLE x2(x INTEGER PRIMARY KEY);
|
| + INSERT INTO x2 VALUES(1);
|
| + }
|
| + set sql {SELECT * FROM x1, x2 WHERE x=1 ORDER BY random()}
|
| + set out1 [db eval $sql]
|
| + set out2 [db eval $sql]
|
| + set out3 [db eval $sql]
|
| + expr {$out1!=$out2 && $out2!=$out3}
|
| +} {1}
|
| +do_execsql_test where2-2.5 {
|
| + -- random() is not optimized out
|
| + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random();
|
| +} {/ random/}
|
| +do_execsql_test where2-2.5b {
|
| + -- random() is not optimized out
|
| + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random();
|
| +} {/ SorterOpen /}
|
| +do_execsql_test where2-2.6 {
|
| + -- other constant functions are optimized out
|
| + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5);
|
| +} {~/ abs/}
|
| +do_execsql_test where2-2.6b {
|
| + -- other constant functions are optimized out
|
| + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5);
|
| +} {~/ SorterOpen /}
|
| +
|
| +
|
|
|
| # Efficient handling of forward and reverse table scans.
|
| #
|
| @@ -167,24 +213,54 @@ ifcapable subquery {
|
| }
|
| } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
|
| }
|
| - do_test where2-4.6 {
|
| + do_test where2-4.6a {
|
| + queryplan {
|
| + SELECT * FROM t1
|
| + WHERE x IN (1,2,3,4,5,6,7,8)
|
| + AND y IN (10000,10001,10002,10003,10004,10005)
|
| + ORDER BY x
|
| + }
|
| + } {99 6 10000 10006 nosort t1 i1xy}
|
| + do_test where2-4.6b {
|
| + queryplan {
|
| + SELECT * FROM t1
|
| + WHERE x IN (1,2,3,4,5,6,7,8)
|
| + AND y IN (10000,10001,10002,10003,10004,10005)
|
| + ORDER BY x DESC
|
| + }
|
| + } {99 6 10000 10006 nosort t1 i1xy}
|
| + do_test where2-4.6c {
|
| queryplan {
|
| SELECT * FROM t1
|
| WHERE x IN (1,2,3,4,5,6,7,8)
|
| AND y IN (10000,10001,10002,10003,10004,10005)
|
| - ORDER BY 2
|
| + ORDER BY x, y
|
| + }
|
| + } {99 6 10000 10006 nosort t1 i1xy}
|
| + do_test where2-4.6d {
|
| + queryplan {
|
| + SELECT * FROM t1
|
| + WHERE x IN (1,2,3,4,5,6,7,8)
|
| + AND y IN (10000,10001,10002,10003,10004,10005)
|
| + ORDER BY x, y DESC
|
| }
|
| } {99 6 10000 10006 sort t1 i1xy}
|
|
|
| # Duplicate entires on the RHS of an IN operator do not cause duplicate
|
| # output rows.
|
| #
|
| - do_test where2-4.6 {
|
| + do_test where2-4.6x {
|
| queryplan {
|
| SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207)
|
| ORDER BY w
|
| }
|
| } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
|
| + do_test where2-4.6y {
|
| + queryplan {
|
| + SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207)
|
| + ORDER BY w DESC
|
| + }
|
| + } {100 6 10201 10207 99 6 10000 10006 sort t1 i1zyx}
|
| ifcapable compound {
|
| do_test where2-4.7 {
|
| queryplan {
|
| @@ -207,11 +283,16 @@ do_test where2-5.1 {
|
| } {99 6 10000 10006 nosort t1 i1w}
|
|
|
| ifcapable subquery {
|
| - do_test where2-5.2 {
|
| + do_test where2-5.2a {
|
| queryplan {
|
| SELECT * FROM t1 WHERE w IN (99) ORDER BY w
|
| }
|
| - } {99 6 10000 10006 sort t1 i1w}
|
| + } {99 6 10000 10006 nosort t1 i1w}
|
| + do_test where2-5.2b {
|
| + queryplan {
|
| + SELECT * FROM t1 WHERE w IN (99) ORDER BY w DESC
|
| + }
|
| + } {99 6 10000 10006 nosort t1 i1w}
|
| }
|
|
|
| # Verify that OR clauses get translated into IN operators.
|
| @@ -238,12 +319,12 @@ do_test where2-6.3 {
|
| queryplan {
|
| SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w
|
| }
|
| -} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}
|
| +} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 *}
|
| do_test where2-6.4 {
|
| queryplan {
|
| SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w
|
| }
|
| -} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}
|
| +} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 *}
|
|
|
| set ::idx {}
|
| ifcapable subquery {set ::idx i1zyx}
|
| @@ -262,14 +343,16 @@ do_test where2-6.6 {
|
| }
|
| } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]
|
|
|
| +if {[permutation] != "no_optimization"} {
|
| +
|
| # Ticket #2249. Make sure the OR optimization is not attempted if
|
| # comparisons between columns of different affinities are needed.
|
| #
|
| do_test where2-6.7 {
|
| execsql {
|
| - CREATE TABLE t2249a(a TEXT UNIQUE);
|
| + CREATE TABLE t2249a(a TEXT UNIQUE, x CHAR(100));
|
| CREATE TABLE t2249b(b INTEGER);
|
| - INSERT INTO t2249a VALUES('0123');
|
| + INSERT INTO t2249a(a) VALUES('0123');
|
| INSERT INTO t2249b VALUES(123);
|
| }
|
| queryplan {
|
| @@ -277,56 +360,56 @@ do_test where2-6.7 {
|
| -- will attempt to convert to NUMERIC before the comparison.
|
| -- They will thus compare equal.
|
| --
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b;
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b;
|
| }
|
| -} {123 0123 nosort t2249b {} t2249a {}}
|
| +} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.9 {
|
| queryplan {
|
| -- The + operator removes affinity from the rhs. No conversions
|
| -- occur and the comparison is false. The result is an empty set.
|
| --
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b;
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b;
|
| }
|
| -} {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
|
| +} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.9.2 {
|
| # The same thing but with the expression flipped around.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a
|
| }
|
| -} {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
|
| +} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.10 {
|
| queryplan {
|
| -- Use + on both sides of the comparison to disable indices
|
| -- completely. Make sure we get the same result.
|
| --
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE +a=+b;
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +a=+b;
|
| }
|
| -} {nosort t2249b {} t2249a {}}
|
| +} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.11 {
|
| # This will not attempt the OR optimization because of the a=b
|
| # comparison.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello';
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello';
|
| }
|
| -} {123 0123 nosort t2249b {} t2249a {}}
|
| +} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.11.2 {
|
| # Permutations of the expression terms.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello';
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello';
|
| }
|
| -} {123 0123 nosort t2249b {} t2249a {}}
|
| +} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.11.3 {
|
| # Permutations of the expression terms.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a;
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a;
|
| }
|
| -} {123 0123 nosort t2249b {} t2249a {}}
|
| +} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.11.4 {
|
| # Permutations of the expression terms.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a;
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a;
|
| }
|
| -} {123 0123 nosort t2249b {} t2249a {}}
|
| +} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| ifcapable explain&&subquery {
|
| # These tests are not run if subquery support is not included in the
|
| # build. This is because these tests test the "a = 1 OR a = 2" to
|
| @@ -338,41 +421,41 @@ ifcapable explain&&subquery {
|
| # the OR optimization to be used again. The result is now an empty
|
| # set, the same as in where2-6.9.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello';
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello';
|
| }
|
| - } {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
|
| + } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.12.2 {
|
| # In this case, the +b disables the affinity conflict and allows
|
| # the OR optimization to be used again. The result is now an empty
|
| # set, the same as in where2-6.9.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a;
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a;
|
| }
|
| - } {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
|
| + } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.12.3 {
|
| # In this case, the +b disables the affinity conflict and allows
|
| # the OR optimization to be used again. The result is now an empty
|
| # set, the same as in where2-6.9.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello';
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello';
|
| }
|
| - } {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
|
| + } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| do_test where2-6.13 {
|
| # The addition of +a on the second term disabled the OR optimization.
|
| # But we should still get the same empty-set result as in where2-6.9.
|
| queryplan {
|
| - SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello';
|
| + SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello';
|
| }
|
| - } {nosort t2249b {} t2249a {}}
|
| + } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
| }
|
|
|
| # Variations on the order of terms in a WHERE clause in order
|
| # to make sure the OR optimizer can recognize them all.
|
| do_test where2-6.20 {
|
| queryplan {
|
| - SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a
|
| + SELECT x.a, y.a FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a
|
| }
|
| -} {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1}
|
| +} {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
|
| ifcapable explain&&subquery {
|
| # These tests are not run if subquery support is not included in the
|
| # build. This is because these tests test the "a = 1 OR a = 2" to
|
| @@ -381,19 +464,22 @@ ifcapable explain&&subquery {
|
| #
|
| do_test where2-6.21 {
|
| queryplan {
|
| - SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a OR y.a='hello'
|
| + SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
|
| + WHERE x.a=y.a OR y.a='hello'
|
| }
|
| - } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1}
|
| + } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
|
| do_test where2-6.22 {
|
| queryplan {
|
| - SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE y.a=x.a OR y.a='hello'
|
| + SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
|
| + WHERE y.a=x.a OR y.a='hello'
|
| }
|
| - } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1}
|
| + } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
|
| do_test where2-6.23 {
|
| queryplan {
|
| - SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE y.a='hello' OR x.a=y.a
|
| + SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
|
| + WHERE y.a='hello' OR x.a=y.a
|
| }
|
| - } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1}
|
| + } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
|
| }
|
|
|
| # Unique queries (queries that are guaranteed to return only a single
|
| @@ -429,6 +515,8 @@ do_test where2-7.4 {
|
| }
|
| } {1 2 3 2 3 nosort}
|
|
|
| +} ;# if {[permutation] != "no_optimization"}
|
| +
|
| # Ticket #1807. Using IN constrains on multiple columns of
|
| # a multi-column index.
|
| #
|
| @@ -650,5 +738,26 @@ do_test where2-11.4 {
|
| }
|
| } {4 8 10}
|
|
|
| +# Verify that the OR clause is used in an outer loop even when
|
| +# the OR clause scores slightly better on an inner loop.
|
| +if {[permutation] != "no_optimization"} {
|
| +do_execsql_test where2-12.1 {
|
| + CREATE TABLE t12(x INTEGER PRIMARY KEY, y INT, z CHAR(100));
|
| + CREATE INDEX t12y ON t12(y);
|
| + EXPLAIN QUERY PLAN
|
| + SELECT a.x, b.x
|
| + FROM t12 AS a JOIN t12 AS b ON a.y=b.x
|
| + WHERE (b.x=$abc OR b.y=$abc);
|
| +} {/.*SEARCH TABLE t12 AS b .*SEARCH TABLE t12 AS b .*/}
|
| +}
|
| +
|
| +# Verify that all necessary OP_OpenRead opcodes occur in the OR optimization.
|
| +#
|
| +do_execsql_test where2-13.1 {
|
| + CREATE TABLE t13(a,b);
|
| + CREATE INDEX t13a ON t13(a);
|
| + INSERT INTO t13 VALUES(4,5);
|
| + SELECT * FROM t13 WHERE (1=2 AND a=3) OR a=4;
|
| +} {4 5}
|
|
|
| finish_test
|
|
|