mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Overhaul of EXPLAIN QUERY PLAN. The output is now in the form of a tree.
More details of the query plan are shown, and what is shown is truer to what actually happens. FossilOrigin-Name: ff01bbdabc4b9db3db8b928979442c91b32d72082158e4f5fe62ae51a73649d2
This commit is contained in:
@@ -118,10 +118,10 @@ do_execsql_test analyze3-1.1.x {
|
||||
#
|
||||
do_eqp_test analyze3-1.1.2 {
|
||||
SELECT sum(y) FROM t1 WHERE x>200 AND x<300
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
|
||||
do_eqp_test analyze3-1.1.3 {
|
||||
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
# 2017-06-26: Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables
|
||||
# the use of bound parameters by STAT4
|
||||
@@ -131,27 +131,27 @@ unset -nocomplain l
|
||||
unset -nocomplain u
|
||||
do_eqp_test analyze3-1.1.3.100 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
|
||||
set l 200
|
||||
set u 300
|
||||
do_eqp_test analyze3-1.1.3.101 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
|
||||
set l 0
|
||||
set u 1100
|
||||
do_eqp_test analyze3-1.1.3.102 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
db cache flush
|
||||
sqlite3_db_config db ENABLE_QPSG 1
|
||||
do_eqp_test analyze3-1.1.3.103 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
|
||||
db cache flush
|
||||
sqlite3_db_config db ENABLE_QPSG 0
|
||||
do_eqp_test analyze3-1.1.3.104 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
do_test analyze3-1.1.4 {
|
||||
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
|
||||
@@ -201,10 +201,10 @@ do_execsql_test analyze3-2.1.x {
|
||||
} {200 990}
|
||||
do_eqp_test analyze3-1.2.2 {
|
||||
SELECT sum(y) FROM t2 WHERE x>1 AND x<2
|
||||
} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}
|
||||
do_eqp_test analyze3-1.2.3 {
|
||||
SELECT sum(y) FROM t2 WHERE x>0 AND x<99
|
||||
} {0 0 0 {SCAN TABLE t2}}
|
||||
} {SCAN TABLE t2}
|
||||
|
||||
do_test analyze3-1.2.4 {
|
||||
sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
|
||||
@@ -253,10 +253,10 @@ do_execsql_test analyze3-1.3.x {
|
||||
} {99 1000}
|
||||
do_eqp_test analyze3-1.3.2 {
|
||||
SELECT sum(y) FROM t3 WHERE x>200 AND x<300
|
||||
} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}
|
||||
do_eqp_test analyze3-1.3.3 {
|
||||
SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
|
||||
} {0 0 0 {SCAN TABLE t3}}
|
||||
} {SCAN TABLE t3}
|
||||
|
||||
do_test analyze3-1.3.4 {
|
||||
sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
|
||||
@@ -308,10 +308,10 @@ do_test analyze3-2.1 {
|
||||
} {}
|
||||
do_eqp_test analyze3-2.2 {
|
||||
SELECT count(a) FROM t1 WHERE b LIKE 'a%'
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}
|
||||
do_eqp_test analyze3-2.3 {
|
||||
SELECT count(a) FROM t1 WHERE b LIKE '%a'
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
# Return the first argument if like_match_blobs is true (the default)
|
||||
# or the second argument if not
|
||||
@@ -698,11 +698,11 @@ do_test analyze3-6.1 {
|
||||
|
||||
do_eqp_test analyze3-6-3 {
|
||||
SELECT * FROM t1 WHERE a = 5 AND c = 13;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
|
||||
|
||||
do_eqp_test analyze3-6-2 {
|
||||
SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# 2015-04-20.
|
||||
|
||||
@@ -38,7 +38,7 @@ do_test analyze4-1.0 {
|
||||
|
||||
# Should choose the t1a index since it is more specific than t1b.
|
||||
db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
|
||||
# Verify that the t1b index shows that it does not narrow down the
|
||||
# search any at all.
|
||||
|
||||
@@ -61,14 +61,18 @@ do_test analyze6-1.0 {
|
||||
#
|
||||
do_test analyze6-1.1 {
|
||||
eqp {SELECT count(*) FROM ev, cat WHERE x=y}
|
||||
} {0 0 1 {SCAN TABLE cat USING COVERING INDEX catx} 0 1 0 {SEARCH TABLE ev USING COVERING INDEX evy (y=?)}}
|
||||
} {/*SCAN TABLE cat USING COVERING INDEX catx*SEARCH TABLE ev USING COVERING INDEX evy (y=?)*/}
|
||||
|
||||
# The same plan is chosen regardless of the order of the tables in the
|
||||
# FROM clause.
|
||||
#
|
||||
do_test analyze6-1.2 {
|
||||
eqp {SELECT count(*) FROM cat, ev WHERE x=y}
|
||||
} {0 0 0 {SCAN TABLE cat USING COVERING INDEX catx} 0 1 1 {SEARCH TABLE ev USING COVERING INDEX evy (y=?)}}
|
||||
do_eqp_test analyze6-1.2 {
|
||||
SELECT count(*) FROM cat, ev WHERE x=y
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE cat USING COVERING INDEX catx
|
||||
`--SEARCH TABLE ev USING COVERING INDEX evy (y=?)
|
||||
}
|
||||
|
||||
|
||||
# Ticket [83ea97620bd3101645138b7b0e71c12c5498fe3d] 2011-03-30
|
||||
@@ -82,26 +86,26 @@ do_test analyze6-2.1 {
|
||||
ANALYZE;
|
||||
}
|
||||
eqp {SELECT * FROM t201 WHERE z=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
|
||||
do_test analyze6-2.2 {
|
||||
eqp {SELECT * FROM t201 WHERE y=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
|
||||
do_test analyze6-2.3 {
|
||||
eqp {SELECT * FROM t201 WHERE x=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
|
||||
do_test analyze6-2.4 {
|
||||
execsql {
|
||||
INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5);
|
||||
ANALYZE t201;
|
||||
}
|
||||
eqp {SELECT * FROM t201 WHERE z=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
|
||||
do_test analyze6-2.5 {
|
||||
eqp {SELECT * FROM t201 WHERE y=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
|
||||
do_test analyze6-2.6 {
|
||||
eqp {SELECT * FROM t201 WHERE x=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
|
||||
do_test analyze6-2.7 {
|
||||
execsql {
|
||||
INSERT INTO t201 VALUES(4,5,7);
|
||||
@@ -111,12 +115,12 @@ do_test analyze6-2.7 {
|
||||
ANALYZE t201;
|
||||
}
|
||||
eqp {SELECT * FROM t201 WHERE z=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
|
||||
do_test analyze6-2.8 {
|
||||
eqp {SELECT * FROM t201 WHERE y=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
|
||||
do_test analyze6-2.9 {
|
||||
eqp {SELECT * FROM t201 WHERE x=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -37,13 +37,13 @@ do_test analyze7-1.0 {
|
||||
WHERE value BETWEEN 1 AND 256;
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;
|
||||
}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test analyze7-1.1 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test analyze7-1.2 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
|
||||
# Run an analyze on one of the three indices. Verify that this
|
||||
# effects the row-count estimate on the one query that uses that
|
||||
@@ -53,20 +53,20 @@ do_test analyze7-2.0 {
|
||||
execsql {ANALYZE t1a;}
|
||||
db cache flush
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test analyze7-2.1 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test analyze7-2.2 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
|
||||
# Verify that since the query planner now things that t1a is more
|
||||
# selective than t1b, it prefers to use t1a.
|
||||
#
|
||||
do_test analyze7-2.3 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
|
||||
# Run an analysis on another of the three indices. Verify that this
|
||||
# new analysis works and does not disrupt the previous analysis.
|
||||
@@ -75,40 +75,40 @@ do_test analyze7-3.0 {
|
||||
execsql {ANALYZE t1cd;}
|
||||
db cache flush;
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test analyze7-3.1 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test analyze7-3.2.1 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
ifcapable stat4||stat3 {
|
||||
# If ENABLE_STAT4 is defined, SQLite comes up with a different estimated
|
||||
# row count for (c=2) than it does for (c=?).
|
||||
do_test analyze7-3.2.2 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
} else {
|
||||
# If ENABLE_STAT4 is not defined, the expected row count for (c=2) is the
|
||||
# same as that for (c=?).
|
||||
do_test analyze7-3.2.3 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
}
|
||||
do_test analyze7-3.3 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
|
||||
ifcapable {!stat4 && !stat3} {
|
||||
do_test analyze7-3.4 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test analyze7-3.5 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
}
|
||||
do_test analyze7-3.6 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)*/}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -61,25 +61,25 @@ do_test 1.0 {
|
||||
#
|
||||
do_test 1.1 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND b=55}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test 1.2 {
|
||||
eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 1.3 {
|
||||
eqp {SELECT * FROM t1 WHERE a=101 AND b=55}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 1.4 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test 1.5 {
|
||||
eqp {SELECT * FROM t1 WHERE a=99 AND b=56}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 1.6 {
|
||||
eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 2.1 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)*/}
|
||||
|
||||
# There are many more values of c between 0 and 100000 than there are
|
||||
# between 800000 and 900000. So t1c is more selective for the latter
|
||||
@@ -99,17 +99,17 @@ do_execsql_test 3.0 {
|
||||
} {50 376 32}
|
||||
do_test 3.1 {
|
||||
eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 0 AND 100000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)*/}
|
||||
do_test 3.2 {
|
||||
eqp {SELECT * FROM t1
|
||||
WHERE b BETWEEN 30 AND 34 AND c BETWEEN 800000 AND 900000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)*/}
|
||||
do_test 3.3 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 3.4 {
|
||||
eqp {SELECT * FROM t1
|
||||
WHERE a=100 AND c BETWEEN 800000 AND 900000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)*/}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -987,7 +987,8 @@ do_eqp_test 21.3 {
|
||||
reset_db
|
||||
do_execsql_test 22.0 {
|
||||
CREATE TABLE t3(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID;
|
||||
}
|
||||
SELECT * FROM t3;
|
||||
} {}
|
||||
do_execsql_test 22.1 {
|
||||
WITH r(x) AS (
|
||||
SELECT 1
|
||||
@@ -1055,15 +1056,11 @@ do_eqp_test 23.1 {
|
||||
-- Formerly used index i41. But i41 is not a covering index whereas
|
||||
-- the PRIMARY KEY is a covering index, and so as of 2017-10-15, the
|
||||
-- PRIMARY KEY is preferred.
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a<?)}
|
||||
}
|
||||
} {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a<?)}
|
||||
do_eqp_test 23.2 {
|
||||
SELECT * FROM t4 WHERE
|
||||
(e=1 AND b='xyz' AND c='zyx' AND a<'JJJ') AND f<300
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t4 USING INDEX i42 (f<?)}
|
||||
}
|
||||
} {SEARCH TABLE t4 USING INDEX i42 (f<?)}
|
||||
|
||||
do_execsql_test 24.0 {
|
||||
CREATE TABLE t5(c, d, b, e, a, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
|
||||
@@ -1108,33 +1105,26 @@ ifcapable stat4&&cte {
|
||||
|
||||
# Term (b<?) is estimated at 25%. Better than (a<30) but not as
|
||||
# good as (a<20).
|
||||
do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b<?)}
|
||||
}
|
||||
do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
}
|
||||
do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } \
|
||||
{SEARCH TABLE t6 USING INDEX bb (b<?)}
|
||||
do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } \
|
||||
{SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
|
||||
# Term (b BETWEEN ? AND ?) is estimated at 1/64.
|
||||
do_eqp_test 25.3.1 {
|
||||
SELECT * FROM t6 WHERE a BETWEEN 5 AND 10 AND b BETWEEN ? AND ?
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
|
||||
# Term (b BETWEEN ? AND 60) is estimated to return roughly 15 rows -
|
||||
# 60 from (b<=60) multiplied by 0.25 for the b>=? term. Better than
|
||||
# (a<20) but not as good as (a<10).
|
||||
do_eqp_test 25.4.1 {
|
||||
SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
|
||||
do_eqp_test 25.4.2 {
|
||||
SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -1190,9 +1180,7 @@ do_execsql_test 26.1.3 {
|
||||
#
|
||||
do_eqp_test 26.1.4 {
|
||||
SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1z (z=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1z (z=?)}
|
||||
|
||||
|
||||
# This test - 26.2.* - tests that another manifestation of the same problem
|
||||
@@ -1241,9 +1229,7 @@ do_execsql_test 26.2.1 {
|
||||
|
||||
do_eqp_test 26.2.2 {
|
||||
SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -136,10 +136,10 @@ foreach {tn analyze_cmd} {
|
||||
|
||||
do_eqp_test 1.$tn.2.5 {
|
||||
SELECT * FROM t1 WHERE b = 31 AND c = 0;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b=?)}
|
||||
do_eqp_test 1.$tn.2.6 {
|
||||
SELECT * FROM t1 WHERE b = 125 AND c = 16;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1c (c=?)}
|
||||
|
||||
do_execsql_test 1.$tn.3.1 {
|
||||
SELECT count(*) FROM t1 WHERE b BETWEEN 0 AND 50
|
||||
@@ -156,31 +156,31 @@ foreach {tn analyze_cmd} {
|
||||
|
||||
do_eqp_test 1.$tn.3.5 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN 0 AND 50 AND c BETWEEN 0 AND 50
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.6 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN 75 AND 125 AND c BETWEEN 75 AND 125
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.7 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN +0 AND +50 AND c BETWEEN +0 AND +50
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.8 {
|
||||
SELECT * FROM t1
|
||||
WHERE b BETWEEN cast('0' AS int) AND cast('50.0' AS real)
|
||||
AND c BETWEEN cast('0' AS numeric) AND cast('50.0' AS real)
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.9 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN +75 AND +125 AND c BETWEEN +75 AND +125
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.10 {
|
||||
SELECT * FROM t1
|
||||
WHERE b BETWEEN cast('75' AS int) AND cast('125.0' AS real)
|
||||
AND c BETWEEN cast('75' AS numeric) AND cast('125.0' AS real)
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -63,9 +63,7 @@ do_test 1.1 {
|
||||
#
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t1 WHERE a=3001 AND c=150;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
|
||||
do_test 1.3 {
|
||||
execsql { DELETE FROM sqlite_stat1 }
|
||||
@@ -80,9 +78,7 @@ do_test 1.3 {
|
||||
#
|
||||
do_eqp_test 1.4 {
|
||||
SELECT * FROM t1 WHERE a=3001 AND c=150;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
|
||||
|
||||
do_test 1.5 {
|
||||
execsql {
|
||||
@@ -93,9 +89,7 @@ do_test 1.5 {
|
||||
|
||||
do_eqp_test 1.6 {
|
||||
SELECT * FROM t1 WHERE a=13 AND c=150;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
|
||||
do_test 1.7 {
|
||||
execsql { DELETE FROM sqlite_stat1 }
|
||||
@@ -108,8 +102,6 @@ do_test 1.7 {
|
||||
# gets this right, even without stat1 data.
|
||||
do_eqp_test 1.8 {
|
||||
SELECT * FROM t1 WHERE a=13 AND c=150;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -62,7 +62,7 @@ foreach {tn where idx} {
|
||||
11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
|
||||
12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
|
||||
} {
|
||||
set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
|
||||
set res "SEARCH TABLE t1 USING INDEX $idx"
|
||||
do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ foreach {tn where idx} {
|
||||
3 "x = nondet4() AND y = nondet19()" {t1y (y=?)}
|
||||
4 "x = nondet19() AND y = nondet4()" {t1y (y=?)}
|
||||
} {
|
||||
set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
|
||||
set res "SEARCH TABLE t1 USING INDEX $idx"
|
||||
do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
|
||||
}
|
||||
|
||||
|
||||
@@ -177,35 +177,36 @@ do_execsql_test autoindex1-500 {
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t501',null,'1000000');
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t502',null,'1000');
|
||||
ANALYZE sqlite_master;
|
||||
EXPLAIN QUERY PLAN
|
||||
}
|
||||
do_eqp_test autoindex1-500.1 {
|
||||
SELECT b FROM t501
|
||||
WHERE t501.a IN (SELECT x FROM t502 WHERE y=?);
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t502}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--LIST SUBQUERY
|
||||
`--SCAN TABLE t502
|
||||
}
|
||||
do_execsql_test autoindex1-501 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test autoindex1-501 {
|
||||
SELECT b FROM t501
|
||||
WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t501}
|
||||
0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1}
|
||||
1 0 0 {SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t501
|
||||
`--CORRELATED LIST SUBQUERY
|
||||
`--SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)
|
||||
}
|
||||
do_execsql_test autoindex1-502 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test autoindex1-502 {
|
||||
SELECT b FROM t501
|
||||
WHERE t501.a=123
|
||||
AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t502}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--CORRELATED LIST SUBQUERY
|
||||
`--SCAN TABLE t502
|
||||
}
|
||||
|
||||
|
||||
# The following code checks a performance regression reported on the
|
||||
# mailing list on 2010-10-19. The problem is that the nRowEst field
|
||||
# of ephermeral tables was not being initialized correctly and so no
|
||||
@@ -257,7 +258,8 @@ do_execsql_test autoindex1-600 {
|
||||
ON sheep (originating_flock);
|
||||
CREATE INDEX sheep_reg_flock_index
|
||||
ON sheep (registering_flock);
|
||||
EXPLAIN QUERY PLAN
|
||||
}
|
||||
do_eqp_test autoindex1-600a {
|
||||
SELECT x.sheep_no, x.registering_flock, x.date_of_registration
|
||||
FROM sheep x LEFT JOIN
|
||||
(SELECT s.sheep_no, prev.flock_no, prev.owner_person_id,
|
||||
@@ -274,21 +276,26 @@ do_execsql_test autoindex1-600 {
|
||||
WHERE y.sheep_no IS NULL
|
||||
ORDER BY x.registering_flock;
|
||||
} {
|
||||
1 0 0 {SCAN TABLE sheep AS s}
|
||||
1 1 1 {SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)}
|
||||
1 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
|
||||
2 0 0 {SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)}
|
||||
0 0 0 {SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index}
|
||||
0 1 1 {SEARCH SUBQUERY 1 AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| |--SCAN TABLE sheep AS s
|
||||
| |--SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)
|
||||
| `--CORRELATED SCALAR SUBQUERY
|
||||
| `--SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)
|
||||
|--SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index
|
||||
`--SEARCH SUBQUERY xxxxxx AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)
|
||||
}
|
||||
|
||||
|
||||
do_execsql_test autoindex1-700 {
|
||||
CREATE TABLE t5(a, b, c);
|
||||
EXPLAIN QUERY PLAN SELECT a FROM t5 WHERE b=10 ORDER BY c;
|
||||
}
|
||||
do_eqp_test autoindex1-700a {
|
||||
SELECT a FROM t5 WHERE b=10 ORDER BY c;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t5}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t5
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
# The following checks a performance issue reported on the sqlite-dev
|
||||
|
||||
@@ -84,8 +84,9 @@ do_execsql_test 210 {
|
||||
do_eqp_test 220 {
|
||||
select count(*) from u, v where u.b = v.b and v.e > 34;
|
||||
} {
|
||||
0 0 1 {SEARCH TABLE v USING INDEX ve (e>?)}
|
||||
0 1 0 {SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE v USING INDEX ve (e>?)
|
||||
`--SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -84,8 +84,7 @@ do_execsql_test autoindex5-1.0 {
|
||||
# The following query should use an automatic index for the view
|
||||
# in FROM clause of the subquery of the second result column.
|
||||
#
|
||||
do_execsql_test autoindex5-1.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test autoindex5-1.1 {
|
||||
SELECT
|
||||
st.bug_name,
|
||||
(SELECT ALL debian_cve.bug FROM debian_cve
|
||||
@@ -103,7 +102,7 @@ do_execsql_test autoindex5-1.1 {
|
||||
AND ( sp.release = 'sid' OR sp.release = 'stretch' OR sp.release = 'jessie'
|
||||
OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
|
||||
ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
|
||||
} {/SEARCH SUBQUERY 2 USING AUTOMATIC COVERING INDEX .bug_name=/}
|
||||
} {SEARCH SUBQUERY * USING AUTOMATIC COVERING INDEX (bug_name=?)}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that ticket [8a2adec1] has been fixed.
|
||||
|
||||
@@ -51,15 +51,11 @@ do_execsql_test 1.0 {
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT * FROM x1 WHERE a = 'abc'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
|
||||
}
|
||||
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM x1 WHERE a IN ('abc', 'def');
|
||||
} {
|
||||
0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
|
||||
}
|
||||
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -144,21 +140,24 @@ foreach {tn mode} {
|
||||
} {1 4}
|
||||
|
||||
set plan(use) {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
set plan(omit) {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
set plan(use2) {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 2.2.$mode.6 {
|
||||
SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
|
||||
} $plan($mode)
|
||||
} [string map {"\n " "\n"} $plan($mode)]
|
||||
}
|
||||
|
||||
# 2016-04-09.
|
||||
|
||||
@@ -89,40 +89,40 @@ do_execsql_test 1.0 {
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT * FROM t1 WHERE a='abc'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t1 WHERE a='abc' AND b='def'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM t1 WHERE a='abc' AND a='def'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
|
||||
|
||||
do_eqp_test 1.4 {
|
||||
SELECT * FROM t1,t2 WHERE c=a
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
|
||||
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
|
||||
`--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
|
||||
}
|
||||
|
||||
do_eqp_test 1.5 {
|
||||
SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
|
||||
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
|
||||
0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
|
||||
|--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
|
||||
`--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
|
||||
}
|
||||
|
||||
do_eqp_test 1.6 {
|
||||
SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
|
||||
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
|
||||
0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
|
||||
|--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
|
||||
`--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
|
||||
}
|
||||
|
||||
do_execsql_test 1.7.1 {
|
||||
@@ -132,10 +132,11 @@ do_eqp_test 1.7.2 {
|
||||
SELECT * FROM x1 CROSS JOIN t1, t2, t3
|
||||
WHERE t1.a = t2.c AND t1.b = t3.e
|
||||
} {
|
||||
0 0 0 {SCAN TABLE x1}
|
||||
0 1 1 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
|
||||
0 2 2 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
|
||||
0 3 3 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE x1
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
|
||||
|--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
|
||||
`--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -79,28 +79,26 @@ do_execsql_test 1.0 {
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT * FROM t1 WHERE a LIKE 'abc';
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t1 WHERE a = 'abc';
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM t1 WHERE a = 'abc' OR b = 'def';
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?
|
||||
`--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
|
||||
}
|
||||
|
||||
do_eqp_test 1.4 {
|
||||
SELECT * FROM t1 WHERE a LIKE 'abc%' OR b = 'def';
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?
|
||||
`--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
|
||||
}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
@@ -147,10 +145,11 @@ ifcapable !icu {
|
||||
|
||||
do_eqp_test 2.2 {
|
||||
SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)}
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?)}
|
||||
}
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)
|
||||
`--SEARCH TABLE t2 USING INDEX t2y (y=?)
|
||||
}]
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -92,13 +92,13 @@ for {set i 0} {$i < 9} {incr i} {
|
||||
SELECT * FROM t$t AS o WHERE
|
||||
NOT EXISTS( SELECT * FROM t$t AS i WHERE a=o.a AND +b=o.b AND +c=o.c )
|
||||
ORDER BY b, c;
|
||||
" "
|
||||
0 0 0 {SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1}
|
||||
0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 1}
|
||||
1 0 0 {SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
"
|
||||
" [string map {"\n " "\n"} "
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1
|
||||
`--CORRELATED SCALAR SUBQUERY
|
||||
`--SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)
|
||||
"]
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ do_execsql_test 1.1 {
|
||||
do_eqp_test 1.2 {
|
||||
SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t3 USING COVERING INDEX i3}
|
||||
0 1 1 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t3 USING COVERING INDEX i3
|
||||
`--SEARCH TABLE t4 USING INDEX i4 (c=?)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +39,7 @@ do_execsql_test 2.1 {
|
||||
# if the index is a non-covering index.
|
||||
do_eqp_test 2.2 {
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING INDEX i1}
|
||||
}
|
||||
} {SCAN TABLE t1 USING INDEX i1}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
|
||||
@@ -57,10 +56,11 @@ do_eqp_test 3.2 {
|
||||
WHERE b IS NULL OR c IS NULL OR d IS NULL
|
||||
ORDER BY a;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t5 USING INDEX t5b (b=?)}
|
||||
0 0 0 {SEARCH TABLE t5 USING INDEX t5c (c=?)}
|
||||
0 0 0 {SEARCH TABLE t5 USING INDEX t5d (d=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t5 USING INDEX t5b (b=?)
|
||||
|--SEARCH TABLE t5 USING INDEX t5c (c=?)
|
||||
|--SEARCH TABLE t5 USING INDEX t5d (d=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -79,14 +79,11 @@ do_execsql_test 4.1 {
|
||||
}
|
||||
do_eqp_test 4.2 {
|
||||
SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
|
||||
do_eqp_test 4.3 {
|
||||
SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -100,15 +97,17 @@ do_execsql_test 5.1 {
|
||||
do_eqp_test 5.2 {
|
||||
SELECT * FROM t2 ORDER BY x, y;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t2 USING INDEX t2i1}
|
||||
0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t2 USING INDEX t2i1
|
||||
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 5.3 {
|
||||
SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
# where7.test, where8.test:
|
||||
@@ -122,9 +121,10 @@ do_execsql_test 6.1 {
|
||||
do_eqp_test 6.2 {
|
||||
SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)}
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX t3i2 (c=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)
|
||||
|--SEARCH TABLE t3 USING INDEX t3i2 (c=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -145,9 +145,10 @@ do_eqp_test 7.2 {
|
||||
WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
|
||||
ORDER BY a
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)
|
||||
|--SEARCH TABLE t1 USING INDEX t1b (b=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 7.3 {
|
||||
@@ -155,15 +156,11 @@ do_eqp_test 7.3 {
|
||||
WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
|
||||
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
|
||||
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
do_eqp_test 7.4 {
|
||||
SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -194,10 +191,11 @@ do_eqp_test 8.2 {
|
||||
AND unlikely(composer.cid=track.cid)
|
||||
AND unlikely(album.aid=track.aid);
|
||||
} {
|
||||
0 0 2 {SCAN TABLE track}
|
||||
0 1 0 {SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 2 1 {SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE track
|
||||
|--SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--USE TEMP B-TREE FOR DISTINCT
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -263,27 +261,19 @@ ifcapable stat4 {
|
||||
|
||||
do_eqp_test 10.3 {
|
||||
SELECT rowid FROM t6 WHERE a=0 AND c=0
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
|
||||
|
||||
do_eqp_test 10.4 {
|
||||
SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
|
||||
|
||||
do_eqp_test 10.5 {
|
||||
SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
|
||||
|
||||
do_eqp_test 10.6 {
|
||||
SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -109,16 +109,11 @@ do_execsql_test 5.1.0 "
|
||||
|
||||
do_eqp_test 5.1.1 {
|
||||
SELECT * FROM t1 ORDER BY c1, c2;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
}
|
||||
} {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
|
||||
do_eqp_test 5.1.2 {
|
||||
SELECT * FROM t2 ORDER BY c1, c2;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX i2}
|
||||
}
|
||||
|
||||
} {SCAN TABLE t2 USING COVERING INDEX i2}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1385,13 +1385,13 @@ do_execsql_test 4.10.0 {
|
||||
}
|
||||
do_createtable_tests 4.10 {
|
||||
1 "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5"
|
||||
{0 0 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (b=?)}}
|
||||
{/*SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}
|
||||
|
||||
2 "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c"
|
||||
{0 0 0 {SCAN TABLE t2 USING INDEX sqlite_autoindex_t2_1}}
|
||||
{/*SCAN TABLE t2 USING INDEX sqlite_autoindex_t2_1*/}
|
||||
|
||||
3 "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE b=10 AND c>10"
|
||||
{0 0 0 {SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)}}
|
||||
{/*SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a
|
||||
|
||||
434
test/eqp.test
434
test/eqp.test
@@ -43,78 +43,108 @@ do_execsql_test 1.1 {
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t2, t1 WHERE t1.a=1 OR t1.b=2;
|
||||
} {
|
||||
0 0 1 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
0 0 1 {SEARCH TABLE t1 USING INDEX i2 (b=?)}
|
||||
0 1 0 {SCAN TABLE t2}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t1 USING INDEX i1 (a=?)
|
||||
|--SEARCH TABLE t1 USING INDEX i2 (b=?)
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t2}
|
||||
0 1 1 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
0 1 1 {SEARCH TABLE t1 USING INDEX i2 (b=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t2
|
||||
|--SEARCH TABLE t1 USING INDEX i1 (a=?)
|
||||
`--SEARCH TABLE t1 USING INDEX i2 (b=?)
|
||||
}
|
||||
do_eqp_test 1.3 {
|
||||
SELECT a FROM t1 ORDER BY a
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t1 USING COVERING INDEX i1
|
||||
}
|
||||
do_eqp_test 1.4 {
|
||||
SELECT a FROM t1 ORDER BY +a
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 USING COVERING INDEX i1
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
do_eqp_test 1.5 {
|
||||
SELECT a FROM t1 WHERE a=4
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)
|
||||
}
|
||||
do_eqp_test 1.6 {
|
||||
SELECT DISTINCT count(*) FROM t3 GROUP BY a;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t3}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t3
|
||||
|--USE TEMP B-TREE FOR GROUP BY
|
||||
`--USE TEMP B-TREE FOR DISTINCT
|
||||
}
|
||||
|
||||
do_eqp_test 1.7 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1)
|
||||
} {
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| `--SCAN CONSTANT ROW
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
`--SCAN TABLE t3
|
||||
}
|
||||
do_eqp_test 1.8 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
|
||||
} {
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| `--COMPOUND QUERY
|
||||
| |--LEFT-MOST SUBQUERY
|
||||
| | `--SCAN CONSTANT ROW
|
||||
| `--UNION USING TEMP B-TREE
|
||||
| `--SCAN CONSTANT ROW
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
`--SCAN TABLE t3
|
||||
}
|
||||
do_eqp_test 1.9 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
|
||||
} {
|
||||
3 0 0 {SCAN TABLE t3}
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| `--COMPOUND QUERY
|
||||
| |--LEFT-MOST SUBQUERY
|
||||
| | `--SCAN CONSTANT ROW
|
||||
| `--EXCEPT USING TEMP B-TREE
|
||||
| `--SCAN TABLE t3
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
`--SCAN TABLE t3
|
||||
}
|
||||
do_eqp_test 1.10 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
|
||||
} {
|
||||
3 0 0 {SCAN TABLE t3}
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| `--COMPOUND QUERY
|
||||
| |--LEFT-MOST SUBQUERY
|
||||
| | `--SCAN CONSTANT ROW
|
||||
| `--INTERSECT USING TEMP B-TREE
|
||||
| `--SCAN TABLE t3
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
`--SCAN TABLE t3
|
||||
}
|
||||
|
||||
do_eqp_test 1.11 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
|
||||
} {
|
||||
3 0 0 {SCAN TABLE t3}
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| `--COMPOUND QUERY
|
||||
| |--LEFT-MOST SUBQUERY
|
||||
| | `--SCAN CONSTANT ROW
|
||||
| `--UNION ALL
|
||||
| `--SCAN TABLE t3
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
`--SCAN TABLE t3
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -129,48 +159,58 @@ do_execsql_test 2.1 {
|
||||
}
|
||||
|
||||
det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
|--USE TEMP B-TREE FOR GROUP BY
|
||||
|--USE TEMP B-TREE FOR DISTINCT
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t2 USING COVERING INDEX t2i1
|
||||
|--USE TEMP B-TREE FOR DISTINCT
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
det 2.2.3 "SELECT DISTINCT * FROM t1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--USE TEMP B-TREE FOR DISTINCT
|
||||
}
|
||||
det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE t2}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
|--SCAN TABLE t2
|
||||
`--USE TEMP B-TREE FOR DISTINCT
|
||||
}
|
||||
det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE t2}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
|--SCAN TABLE t2
|
||||
|--USE TEMP B-TREE FOR DISTINCT
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" {
|
||||
0 0 1 {SCAN TABLE t2 USING COVERING INDEX t2i1}
|
||||
0 1 0 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t2 USING COVERING INDEX t2i1
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
det 2.3.1 "SELECT max(x) FROM t2" {
|
||||
0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1}
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE t2 USING COVERING INDEX t2i1
|
||||
}
|
||||
det 2.3.2 "SELECT min(x) FROM t2" {
|
||||
0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1}
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE t2 USING COVERING INDEX t2i1
|
||||
}
|
||||
det 2.3.3 "SELECT min(x), max(x) FROM t2" {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t2 USING COVERING INDEX t2i1
|
||||
}
|
||||
|
||||
det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
|
||||
0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
|
||||
@@ -181,40 +221,46 @@ det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
|
||||
do_eqp_test 3.1.1 {
|
||||
SELECT (SELECT x FROM t1 AS sub) FROM t1;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t1 AS sub}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCALAR SUBQUERY
|
||||
`--SCAN TABLE t1 AS sub
|
||||
}
|
||||
do_eqp_test 3.1.2 {
|
||||
SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t1 AS sub}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCALAR SUBQUERY
|
||||
`--SCAN TABLE t1 AS sub
|
||||
}
|
||||
do_eqp_test 3.1.3 {
|
||||
SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t1 AS sub}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCALAR SUBQUERY
|
||||
|--SCAN TABLE t1 AS sub
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
do_eqp_test 3.1.4 {
|
||||
SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCALAR SUBQUERY
|
||||
`--SCAN TABLE t2 USING COVERING INDEX t2i1
|
||||
}
|
||||
|
||||
det 3.2.1 {
|
||||
SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
0 0 0 {SCAN SUBQUERY 1}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--CO-ROUTINE xxxxxx
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
det 3.2.2 {
|
||||
SELECT * FROM
|
||||
@@ -222,34 +268,40 @@ det 3.2.2 {
|
||||
(SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2
|
||||
ORDER BY x2.y LIMIT 5
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
|
||||
0 0 0 {SCAN SUBQUERY 1 AS x1}
|
||||
0 1 1 {SCAN SUBQUERY 2 AS x2}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
|--MATERIALIZE xxxxxx
|
||||
| `--SCAN TABLE t2 USING INDEX t2i1
|
||||
|--SCAN SUBQUERY xxxxxx AS x1
|
||||
|--SCAN SUBQUERY xxxxxx AS x2
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
det 3.3.1 {
|
||||
SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t2}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--LIST SUBQUERY
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
det 3.3.2 {
|
||||
SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t2}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--CORRELATED LIST SUBQUERY
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
det 3.3.3 {
|
||||
SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t2}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--CORRELATED SCALAR SUBQUERY
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -258,119 +310,158 @@ det 3.3.3 {
|
||||
do_eqp_test 4.1.1 {
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
2 0 0 {SCAN TABLE t2}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
|
||||
QUERY PLAN
|
||||
`--COMPOUND QUERY
|
||||
|--LEFT-MOST SUBQUERY
|
||||
| `--SCAN TABLE t1
|
||||
`--UNION ALL
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
do_eqp_test 4.1.2 {
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2}
|
||||
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
|
||||
QUERY PLAN
|
||||
`--MERGE (UNION ALL)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t2
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
do_eqp_test 4.1.3 {
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 2
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2}
|
||||
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)}
|
||||
QUERY PLAN
|
||||
`--MERGE (UNION)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t2
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
do_eqp_test 4.1.4 {
|
||||
SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 2
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2}
|
||||
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)}
|
||||
QUERY PLAN
|
||||
`--MERGE (INTERSECT)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t2
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
do_eqp_test 4.1.5 {
|
||||
SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 2
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2}
|
||||
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
|
||||
QUERY PLAN
|
||||
`--MERGE (EXCEPT)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t2
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 4.2.2 {
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 1
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
|
||||
QUERY PLAN
|
||||
`--MERGE (UNION ALL)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
`--RIGHT
|
||||
`--SCAN TABLE t2 USING INDEX t2i1
|
||||
}
|
||||
do_eqp_test 4.2.3 {
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
|
||||
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)}
|
||||
QUERY PLAN
|
||||
`--MERGE (UNION)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t2 USING INDEX t2i1
|
||||
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
}
|
||||
do_eqp_test 4.2.4 {
|
||||
SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
|
||||
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)}
|
||||
QUERY PLAN
|
||||
`--MERGE (INTERSECT)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t2 USING INDEX t2i1
|
||||
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
}
|
||||
do_eqp_test 4.2.5 {
|
||||
SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
|
||||
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
|
||||
QUERY PLAN
|
||||
`--MERGE (EXCEPT)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t1
|
||||
| `--USE TEMP B-TREE FOR ORDER BY
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t2 USING INDEX t2i1
|
||||
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 4.3.1 {
|
||||
SELECT x FROM t1 UNION SELECT x FROM t2
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t1}
|
||||
2 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
|
||||
QUERY PLAN
|
||||
`--COMPOUND QUERY
|
||||
|--LEFT-MOST SUBQUERY
|
||||
| `--SCAN TABLE t1
|
||||
`--UNION USING TEMP B-TREE
|
||||
`--SCAN TABLE t2 USING COVERING INDEX t2i1
|
||||
}
|
||||
|
||||
do_eqp_test 4.3.2 {
|
||||
SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1
|
||||
} {
|
||||
2 0 0 {SCAN TABLE t1}
|
||||
3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
|
||||
4 0 0 {SCAN TABLE t1}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 4 USING TEMP B-TREE (UNION)}
|
||||
QUERY PLAN
|
||||
`--COMPOUND QUERY
|
||||
|--LEFT-MOST SUBQUERY
|
||||
| `--SCAN TABLE t1
|
||||
|--UNION USING TEMP B-TREE
|
||||
| `--SCAN TABLE t2 USING COVERING INDEX t2i1
|
||||
`--UNION USING TEMP B-TREE
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
do_eqp_test 4.3.3 {
|
||||
SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1
|
||||
} {
|
||||
2 0 0 {SCAN TABLE t1}
|
||||
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION)}
|
||||
4 0 0 {SCAN TABLE t1}
|
||||
4 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 4 (UNION)}
|
||||
QUERY PLAN
|
||||
`--MERGE (UNION)
|
||||
|--LEFT
|
||||
| `--MERGE (UNION)
|
||||
| |--LEFT
|
||||
| | |--SCAN TABLE t1
|
||||
| | `--USE TEMP B-TREE FOR ORDER BY
|
||||
| `--RIGHT
|
||||
| `--SCAN TABLE t2 USING COVERING INDEX t2i1
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t1
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
if 0 {
|
||||
#-------------------------------------------------------------------------
|
||||
# This next block of tests verifies that the examples on the
|
||||
# lang_explain.html page are correct.
|
||||
#
|
||||
drop_all_tables
|
||||
|
||||
# EVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b
|
||||
# XVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b
|
||||
# FROM t1 WHERE a=1;
|
||||
# 0|0|0|SCAN TABLE t1
|
||||
#
|
||||
@@ -379,7 +470,7 @@ det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);
|
||||
# XVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);
|
||||
# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
|
||||
# 0|0|0|SEARCH TABLE t1 USING INDEX i1
|
||||
#
|
||||
@@ -388,7 +479,7 @@ det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);
|
||||
# XVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);
|
||||
# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
|
||||
# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
|
||||
#
|
||||
@@ -397,7 +488,7 @@ det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {
|
||||
0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN
|
||||
# XVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN
|
||||
# SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2;
|
||||
# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
|
||||
# 0|1|1|SCAN TABLE t2
|
||||
@@ -408,7 +499,7 @@ det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
|
||||
0 1 1 {SCAN TABLE t2}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN
|
||||
# XVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN
|
||||
# SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2;
|
||||
# 0|0|1|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
|
||||
# 0|1|0|SCAN TABLE t2
|
||||
@@ -418,7 +509,7 @@ det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
|
||||
0 1 0 {SCAN TABLE t2}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);
|
||||
# XVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);
|
||||
# sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;
|
||||
# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
|
||||
# 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
|
||||
@@ -429,7 +520,7 @@ det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN
|
||||
# XVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN
|
||||
# SELECT c, d FROM t2 ORDER BY c;
|
||||
# 0|0|0|SCAN TABLE t2
|
||||
# 0|0|0|USE TEMP B-TREE FOR ORDER BY
|
||||
@@ -439,7 +530,7 @@ det 5.7 "SELECT c, d FROM t2 ORDER BY c" {
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);
|
||||
# XVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);
|
||||
# sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;
|
||||
# 0|0|0|SCAN TABLE t2 USING INDEX i4
|
||||
#
|
||||
@@ -448,7 +539,7 @@ det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" {
|
||||
0 0 0 {SCAN TABLE t2 USING INDEX i4}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT
|
||||
# XVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT
|
||||
# (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
|
||||
# 0|0|0|SCAN TABLE t2
|
||||
# 0|0|0|EXECUTE SCALAR SUBQUERY 1
|
||||
@@ -466,7 +557,7 @@ det 5.9 {
|
||||
2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN
|
||||
# XVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN
|
||||
# SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
|
||||
# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
|
||||
# 0|0|0|SCAN SUBQUERY 1
|
||||
@@ -480,7 +571,7 @@ det 5.10 {
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN
|
||||
# XVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN
|
||||
# SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1;
|
||||
# 0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?)
|
||||
# 0|1|1|SCAN TABLE t1
|
||||
@@ -490,7 +581,7 @@ det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" {
|
||||
0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN
|
||||
# XVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN
|
||||
# SELECT a FROM t1 UNION SELECT c FROM t2;
|
||||
# 1|0|0|SCAN TABLE t1
|
||||
# 2|0|0|SCAN TABLE t2
|
||||
@@ -502,7 +593,7 @@ det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" {
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN
|
||||
# XVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN
|
||||
# SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1;
|
||||
# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
|
||||
# 2|0|0|SCAN TABLE t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
|
||||
@@ -515,7 +606,6 @@ det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
|
||||
}
|
||||
|
||||
|
||||
if {![nonzero_reserved_bytes]} {
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests - eqp-6.* - test that the example C code on
|
||||
@@ -557,6 +647,7 @@ if {![nonzero_reserved_bytes]} {
|
||||
0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests - eqp-7.* - test that queries that use the OP_Count
|
||||
@@ -571,11 +662,13 @@ do_execsql_test 7.0 {
|
||||
}
|
||||
|
||||
det 7.1 "SELECT count(*) FROM t1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
det 7.2 "SELECT count(*) FROM t2" {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t2 USING COVERING INDEX i1
|
||||
}
|
||||
|
||||
do_execsql_test 7.3 {
|
||||
@@ -593,11 +686,13 @@ db close
|
||||
sqlite3 db test.db
|
||||
|
||||
det 7.4 "SELECT count(*) FROM t1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
det 7.5 "SELECT count(*) FROM t2" {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t2 USING COVERING INDEX i1
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -612,31 +707,38 @@ do_execsql_test 8.0 {
|
||||
}
|
||||
|
||||
det 8.1.1 "SELECT * FROM t2" {
|
||||
0 0 0 {SCAN TABLE t2}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
|
||||
det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
|
||||
0 0 0 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
det 8.1.3 "SELECT count(*) FROM t2" {
|
||||
0 0 0 {SCAN TABLE t2}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
|
||||
det 8.2.1 "SELECT * FROM t1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
|
||||
0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)}
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE t1 USING PRIMARY KEY (b=?)
|
||||
}
|
||||
|
||||
det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
|
||||
0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)}
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)
|
||||
}
|
||||
|
||||
det 8.2.4 "SELECT count(*) FROM t1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -105,10 +105,10 @@ db func rec rec
|
||||
#
|
||||
do_execsql_test 2.1.1.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term='braid'
|
||||
} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:} }
|
||||
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 1:*/}
|
||||
do_execsql_test 2.1.1.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid'
|
||||
} {0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}}
|
||||
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
|
||||
|
||||
# Now show that using "term='braid'" means the virtual table returns
|
||||
# only 1 row to SQLite, but "+term='braid'" means all 19 are returned.
|
||||
@@ -154,24 +154,24 @@ do_execsql_test 2.1.5 { SELECT * FROM terms WHERE term=NULL } {}
|
||||
|
||||
do_execsql_test 2.2.1.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term>'brain'
|
||||
} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 2:} }
|
||||
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 2:*/}
|
||||
do_execsql_test 2.2.1.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain'
|
||||
} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} }
|
||||
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
|
||||
|
||||
do_execsql_test 2.2.1.3 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term<'brain'
|
||||
} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 4:} }
|
||||
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 4:*/}
|
||||
do_execsql_test 2.2.1.4 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain'
|
||||
} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} }
|
||||
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
|
||||
|
||||
do_execsql_test 2.2.1.5 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term BETWEEN 'brags' AND 'brain'
|
||||
} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 6:} }
|
||||
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 6:*/}
|
||||
do_execsql_test 2.2.1.6 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term BETWEEN 'brags' AND 'brain'
|
||||
} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} }
|
||||
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
|
||||
|
||||
do_test 2.2.2.1 {
|
||||
set cnt 0
|
||||
@@ -335,8 +335,9 @@ foreach {tn sort orderby} {
|
||||
9 1 "ORDER BY occurrences DESC"
|
||||
} {
|
||||
|
||||
set res [list 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}]
|
||||
if {$sort} { lappend res 0 0 0 {USE TEMP B-TREE FOR ORDER BY} }
|
||||
set res {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}
|
||||
if {$sort} { append res {*USE TEMP B-TREE FOR ORDER BY} }
|
||||
set res "/*$res*/"
|
||||
|
||||
set sql "SELECT * FROM terms $orderby"
|
||||
do_execsql_test 2.3.1.$tn "EXPLAIN QUERY PLAN $sql" $res
|
||||
@@ -403,39 +404,48 @@ do_execsql_test 4.1 {
|
||||
INSERT INTO x3 SELECT term FROM terms WHERE col = '*';
|
||||
}
|
||||
|
||||
proc do_plansql_test {tn sql r} {
|
||||
uplevel do_execsql_test $tn [list "EXPLAIN QUERY PLAN $sql ; $sql"] [list $r]
|
||||
proc do_plansql_test {tn sql r1 r2} {
|
||||
do_eqp_test $tn.eqp $sql $r1
|
||||
do_execsql_test $tn $sql $r2
|
||||
}
|
||||
|
||||
do_plansql_test 4.2 {
|
||||
SELECT y FROM x2, terms WHERE y = term AND col = '*'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE x2}
|
||||
0 1 1 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE x2
|
||||
`--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
|
||||
} {
|
||||
a b c d e f g h i j k l
|
||||
}
|
||||
|
||||
do_plansql_test 4.3 {
|
||||
SELECT y FROM terms, x2 WHERE y = term AND col = '*'
|
||||
} {
|
||||
0 0 1 {SCAN TABLE x2}
|
||||
0 1 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE x2
|
||||
`--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
|
||||
} {
|
||||
a b c d e f g h i j k l
|
||||
}
|
||||
|
||||
do_plansql_test 4.4 {
|
||||
SELECT y FROM x3, terms WHERE y = term AND col = '*'
|
||||
} {
|
||||
0 0 1 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}
|
||||
0 1 0 {SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
|
||||
`--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
|
||||
} {
|
||||
a b c d e f g h i j k l
|
||||
}
|
||||
|
||||
do_plansql_test 4.5 {
|
||||
SELECT y FROM terms, x3 WHERE y = term AND occurrences>1 AND col = '*'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}
|
||||
0 1 1 {SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
|
||||
`--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
|
||||
} {
|
||||
a k l
|
||||
}
|
||||
|
||||
|
||||
@@ -96,9 +96,11 @@ do_eqp_test 4.2 {
|
||||
) AS rr ON t4.rowid=rr.docid
|
||||
WHERE t4.y = ?;
|
||||
} {
|
||||
1 0 0 {SCAN TABLE ft4 VIRTUAL TABLE INDEX 3:}
|
||||
0 0 0 {SCAN TABLE t4}
|
||||
0 1 1 {SEARCH SUBQUERY 1 AS rr USING AUTOMATIC COVERING INDEX (docid=?)}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| `--SCAN TABLE ft4 VIRTUAL TABLE INDEX 3:
|
||||
|--SCAN TABLE t4
|
||||
`--SEARCH SUBQUERY xxxxxx AS rr USING AUTOMATIC COVERING INDEX (docid=?)
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -118,26 +118,30 @@ do_test fts3query-4.1 {
|
||||
do_eqp_test fts3query-4.2 {
|
||||
SELECT t1.number FROM t1, ft WHERE t1.number=ft.rowid ORDER BY t1.date
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
0 1 1 {SCAN TABLE ft VIRTUAL TABLE INDEX 1:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 USING COVERING INDEX i1
|
||||
`--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
|
||||
}
|
||||
do_eqp_test fts3query-4.3 {
|
||||
SELECT t1.number FROM ft, t1 WHERE t1.number=ft.rowid ORDER BY t1.date
|
||||
} {
|
||||
0 0 1 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
0 1 0 {SCAN TABLE ft VIRTUAL TABLE INDEX 1:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 USING COVERING INDEX i1
|
||||
`--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
|
||||
}
|
||||
do_eqp_test fts3query-4.4 {
|
||||
SELECT t1.number FROM t1, bt WHERE t1.number=bt.rowid ORDER BY t1.date
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
0 1 1 {SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 USING COVERING INDEX i1
|
||||
`--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
do_eqp_test fts3query-4.5 {
|
||||
SELECT t1.number FROM bt, t1 WHERE t1.number=bt.rowid ORDER BY t1.date
|
||||
} {
|
||||
0 0 1 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
0 1 0 {SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 USING COVERING INDEX i1
|
||||
`--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -318,8 +318,9 @@ do_execsql_test index6-8.0 {
|
||||
do_eqp_test index6-8.1 {
|
||||
SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t8a}
|
||||
0 1 1 {SEARCH TABLE t8b USING INDEX i8c (y=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t8a
|
||||
`--SEARCH TABLE t8b USING INDEX i8c (y=?)
|
||||
}
|
||||
|
||||
do_execsql_test index6-8.2 {
|
||||
|
||||
@@ -321,9 +321,8 @@ do_execsql_test index7-6.3 {
|
||||
}
|
||||
do_eqp_test index7-6.4 {
|
||||
SELECT * FROM v4 WHERE d='xyz' AND c='def'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t4 USING INDEX i4 (c=?)}
|
||||
|
||||
do_catchsql_test index7-6.5 {
|
||||
CREATE INDEX t5a ON t5(a) WHERE a=#1;
|
||||
} {1 {near "#1": syntax error}}
|
||||
|
||||
@@ -40,17 +40,18 @@ proc EQP {sql} {
|
||||
|
||||
# These tests are to check that "EXPLAIN QUERY PLAN" is working as expected.
|
||||
#
|
||||
do_execsql_test indexedby-1.2 {
|
||||
EXPLAIN QUERY PLAN select * from t1 WHERE a = 10;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
do_execsql_test indexedby-1.3 {
|
||||
EXPLAIN QUERY PLAN select * from t1 ;
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
do_execsql_test indexedby-1.4 {
|
||||
EXPLAIN QUERY PLAN select * from t1, t2 WHERE c = 10;
|
||||
do_eqp_test indexedby-1.2 {
|
||||
select * from t1 WHERE a = 10;
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
do_eqp_test indexedby-1.3 {
|
||||
select * from t1 ;
|
||||
} {SCAN TABLE t1}
|
||||
do_eqp_test indexedby-1.4 {
|
||||
select * from t1, t2 WHERE c = 10;
|
||||
} {
|
||||
0 0 1 {SEARCH TABLE t2 USING INDEX i3 (c=?)}
|
||||
0 1 0 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t2 USING INDEX i3 (c=?)
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
# Parser tests. Test that an INDEXED BY or NOT INDEX clause can be
|
||||
@@ -115,25 +116,23 @@ do_test indexedby-2.7 {
|
||||
# the rowid can still be used to look up entries even when "NOT INDEXED"
|
||||
# is specified.
|
||||
#
|
||||
do_execsql_test indexedby-3.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
|
||||
do_eqp_test indexedby-3.1 {
|
||||
SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
|
||||
} {/SEARCH TABLE t1 USING INDEX/}
|
||||
do_execsql_test indexedby-3.1.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
do_execsql_test indexedby-3.1.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE rowid=1
|
||||
do_eqp_test indexedby-3.1.1 {
|
||||
SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
|
||||
} {SCAN TABLE t1}
|
||||
do_eqp_test indexedby-3.1.2 {
|
||||
SELECT * FROM t1 NOT INDEXED WHERE rowid=1
|
||||
} {/SEARCH TABLE t1 USING INTEGER PRIMARY KEY .rowid=/}
|
||||
|
||||
|
||||
do_execsql_test indexedby-3.2 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test indexedby-3.2 {
|
||||
SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
do_execsql_test indexedby-3.3 {
|
||||
EXPLAIN QUERY PLAN
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
do_eqp_test indexedby-3.3 {
|
||||
SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
|
||||
do_test indexedby-3.4 {
|
||||
catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' }
|
||||
} {1 {no query solution}}
|
||||
@@ -147,14 +146,12 @@ do_test indexedby-3.7 {
|
||||
catchsql { SELECT * FROM t1 INDEXED BY i1 ORDER BY a }
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test indexedby-3.8 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test indexedby-3.8 {
|
||||
SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e
|
||||
} {0 0 0 {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1}}
|
||||
do_execsql_test indexedby-3.9 {
|
||||
EXPLAIN QUERY PLAN
|
||||
} {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1}
|
||||
do_eqp_test indexedby-3.9 {
|
||||
SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE e = 10
|
||||
} {0 0 0 {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}}
|
||||
} {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}
|
||||
do_test indexedby-3.10 {
|
||||
catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 }
|
||||
} {1 {no query solution}}
|
||||
@@ -164,17 +161,19 @@ do_test indexedby-3.11 {
|
||||
|
||||
# Tests for multiple table cases.
|
||||
#
|
||||
do_execsql_test indexedby-4.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1, t2 WHERE a = c
|
||||
do_eqp_test indexedby-4.1 {
|
||||
SELECT * FROM t1, t2 WHERE a = c
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SEARCH TABLE t2 USING INDEX i3 (c=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SEARCH TABLE t2 USING INDEX i3 (c=?)
|
||||
}
|
||||
do_execsql_test indexedby-4.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c
|
||||
do_eqp_test indexedby-4.2 {
|
||||
SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c
|
||||
} {
|
||||
0 0 1 {SCAN TABLE t2}
|
||||
0 1 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t2
|
||||
`--SEARCH TABLE t1 USING INDEX i1 (a=?)
|
||||
}
|
||||
do_test indexedby-4.3 {
|
||||
catchsql {
|
||||
@@ -194,10 +193,10 @@ do_test indexedby-4.4 {
|
||||
do_execsql_test indexedby-5.1 {
|
||||
CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5;
|
||||
EXPLAIN QUERY PLAN SELECT * FROM v2
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
|
||||
do_execsql_test indexedby-5.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
|
||||
do_test indexedby-5.3 {
|
||||
execsql { DROP INDEX i1 }
|
||||
catchsql { SELECT * FROM v2 }
|
||||
@@ -216,12 +215,12 @@ do_test indexedby-5.5 {
|
||||
|
||||
# Test that "NOT INDEXED" may use the rowid index, but not others.
|
||||
#
|
||||
do_execsql_test indexedby-6.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 10 ORDER BY rowid
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}}
|
||||
do_execsql_test indexedby-6.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
do_eqp_test indexedby-6.1 {
|
||||
SELECT * FROM t1 WHERE b = 10 ORDER BY rowid
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
|
||||
do_eqp_test indexedby-6.2 {
|
||||
SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
# EVIDENCE-OF: R-40297-14464 The INDEXED BY phrase forces the SQLite
|
||||
# query planner to use a particular named index on a DELETE, SELECT, or
|
||||
@@ -229,44 +228,42 @@ do_execsql_test indexedby-6.2 {
|
||||
#
|
||||
# Test that "INDEXED BY" can be used in a DELETE statement.
|
||||
#
|
||||
do_execsql_test indexedby-7.1 {
|
||||
EXPLAIN QUERY PLAN DELETE FROM t1 WHERE a = 5
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
do_execsql_test indexedby-7.2 {
|
||||
EXPLAIN QUERY PLAN DELETE FROM t1 NOT INDEXED WHERE a = 5
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
do_execsql_test indexedby-7.3 {
|
||||
EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
do_execsql_test indexedby-7.4 {
|
||||
EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
do_execsql_test indexedby-7.5 {
|
||||
EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}}
|
||||
do_eqp_test indexedby-7.1 {
|
||||
DELETE FROM t1 WHERE a = 5
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
do_eqp_test indexedby-7.2 {
|
||||
DELETE FROM t1 NOT INDEXED WHERE a = 5
|
||||
} {SCAN TABLE t1}
|
||||
do_eqp_test indexedby-7.3 {
|
||||
DELETE FROM t1 INDEXED BY i1 WHERE a = 5
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
do_eqp_test indexedby-7.4 {
|
||||
DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
do_eqp_test indexedby-7.5 {
|
||||
DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
|
||||
do_test indexedby-7.6 {
|
||||
catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
|
||||
} {1 {no query solution}}
|
||||
|
||||
# Test that "INDEXED BY" can be used in an UPDATE statement.
|
||||
#
|
||||
do_execsql_test indexedby-8.1 {
|
||||
EXPLAIN QUERY PLAN UPDATE t1 SET rowid=rowid+1 WHERE a = 5
|
||||
} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}}
|
||||
do_execsql_test indexedby-8.2 {
|
||||
EXPLAIN QUERY PLAN UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
do_execsql_test indexedby-8.3 {
|
||||
EXPLAIN QUERY PLAN UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5
|
||||
} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}}
|
||||
do_execsql_test indexedby-8.4 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test indexedby-8.1 {
|
||||
UPDATE t1 SET rowid=rowid+1 WHERE a = 5
|
||||
} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
|
||||
do_eqp_test indexedby-8.2 {
|
||||
UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5
|
||||
} {SCAN TABLE t1}
|
||||
do_eqp_test indexedby-8.3 {
|
||||
UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5
|
||||
} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
|
||||
do_eqp_test indexedby-8.4 {
|
||||
UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
do_execsql_test indexedby-8.5 {
|
||||
EXPLAIN QUERY PLAN
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
do_eqp_test indexedby-8.5 {
|
||||
UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
|
||||
do_test indexedby-8.6 {
|
||||
catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
|
||||
} {1 {no query solution}}
|
||||
@@ -341,7 +338,7 @@ do_execsql_test 11.4 {
|
||||
} {1 1 3}
|
||||
do_eqp_test 11.5 {
|
||||
SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3.0';
|
||||
} {0 0 0 {SEARCH TABLE x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}}
|
||||
} {SEARCH TABLE x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}
|
||||
|
||||
do_execsql_test 11.6 {
|
||||
CREATE TABLE x2(c INTEGER PRIMARY KEY, a, b TEXT);
|
||||
@@ -362,7 +359,7 @@ do_execsql_test 11.9 {
|
||||
} {1 1 3}
|
||||
do_eqp_test 11.10 {
|
||||
SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0';
|
||||
} {0 0 0 {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}}
|
||||
} {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check INDEXED BY works (throws an exception) with partial indexes that
|
||||
|
||||
@@ -91,10 +91,11 @@ ifcapable json1 {
|
||||
WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL
|
||||
GROUP BY json_extract(x, '$.b') COLLATE nocase
|
||||
ORDER BY json_extract(x, '$.b') COLLATE nocase;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t2}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
}
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t2
|
||||
`--USE TEMP B-TREE FOR GROUP BY
|
||||
}]
|
||||
|
||||
do_execsql_test 3.3.2 {
|
||||
CREATE INDEX i3 ON t3(json_extract(x, '$.a'), json_extract(x, '$.b'));
|
||||
@@ -105,10 +106,11 @@ ifcapable json1 {
|
||||
WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL
|
||||
GROUP BY json_extract(x, '$.b') COLLATE nocase
|
||||
ORDER BY json_extract(x, '$.b') COLLATE nocase;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX i3 (<expr>=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
|
||||
}
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t3 USING INDEX i3 (<expr>=?)
|
||||
`--USE TEMP B-TREE FOR GROUP BY
|
||||
}]
|
||||
}
|
||||
|
||||
do_execsql_test 3.4.0 {
|
||||
|
||||
@@ -112,15 +112,17 @@ do_execsql_test 3.0 {
|
||||
do_eqp_test 3.1 {
|
||||
SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_1 USING (k3);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_eqp_test 3.2 {
|
||||
SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_2 USING (k3);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -158,15 +160,17 @@ do_execsql_test 4.1.4 {
|
||||
do_eqp_test 4.1.5 {
|
||||
SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE c1}
|
||||
0 1 1 {SEARCH TABLE c2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 2 2 {SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE c1
|
||||
|--SEARCH TABLE c2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
do_eqp_test 4.1.6 {
|
||||
SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE c1}
|
||||
0 1 2 {SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE c1
|
||||
`--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_execsql_test 4.2.0 {
|
||||
@@ -203,15 +207,17 @@ do_execsql_test 4.2.4 {
|
||||
do_eqp_test 4.2.5 {
|
||||
SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE c1}
|
||||
0 1 1 {SEARCH TABLE c2 USING INDEX sqlite_autoindex_c2_1 (k=?)}
|
||||
0 2 2 {SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE c1
|
||||
|--SEARCH TABLE c2 USING INDEX sqlite_autoindex_c2_1 (k=?)
|
||||
`--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
|
||||
}
|
||||
do_eqp_test 4.2.6 {
|
||||
SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE c1}
|
||||
0 1 2 {SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE c1
|
||||
`--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
|
||||
}
|
||||
|
||||
# 2017-11-23 (Thanksgiving day)
|
||||
@@ -245,14 +251,11 @@ do_execsql_test 5.0 {
|
||||
}
|
||||
do_eqp_test 5.1 {
|
||||
SELECT s1.a FROM s1 left join s2 using (a);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE s1}
|
||||
}
|
||||
} {SCAN TABLE s1}
|
||||
|
||||
do_eqp_test 5.2 {
|
||||
SELECT s1.a FROM s1 left join s3 using (a);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE s1}
|
||||
}
|
||||
} {SCAN TABLE s1}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE u1(a INTEGER PRIMARY KEY, b, c);
|
||||
@@ -261,9 +264,7 @@ do_execsql_test 6.0 {
|
||||
}
|
||||
do_eqp_test 6.1 {
|
||||
SELECT u2.* FROM u2 LEFT JOIN u1 ON( u1.a=u2.a AND u1.b=u2.b AND u1.c=u2.c );
|
||||
} {
|
||||
0 0 0 {SCAN TABLE u2}
|
||||
}
|
||||
} {SCAN TABLE u2}
|
||||
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
|
||||
@@ -264,9 +264,10 @@ do_eqp_test 7.2 {
|
||||
t2.x = t1.x AND (t2.y=? OR (t2.y=? AND t2.z IS NOT NULL))
|
||||
);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)}
|
||||
0 1 1 {SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
|--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
|
||||
`--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
|
||||
}
|
||||
|
||||
do_execsql_test 7.3 {
|
||||
@@ -285,9 +286,9 @@ do_execsql_test 7.3 {
|
||||
do_eqp_test 7.4 {
|
||||
SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t3}
|
||||
0 1 1 {SEARCH TABLE t4 USING INDEX t4xz (x=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t3
|
||||
`--SEARCH TABLE t4 USING INDEX t4xz (x=?)
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -121,10 +121,11 @@ do_execsql_test 6.0 {
|
||||
ifcapable stat4 {
|
||||
do_eqp_test 6.1 {
|
||||
SELECT DISTINCT c FROM t3 WHERE b BETWEEN '.xx..' AND '.xxxx';
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX i3 (ANY(a) AND b>? AND b<?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
}
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t3 USING INDEX i3 (ANY(a) AND b>? AND b<?)
|
||||
`--USE TEMP B-TREE FOR DISTINCT
|
||||
}]
|
||||
}
|
||||
|
||||
do_faultsim_test 6 -faults oom* -body {
|
||||
|
||||
@@ -454,9 +454,12 @@ do_test 4.0 {
|
||||
|
||||
# No sorting of queries that omit the FROM clause.
|
||||
#
|
||||
do_execsql_test 5.0 {
|
||||
EXPLAIN QUERY PLAN SELECT 5 ORDER BY 1
|
||||
} {}
|
||||
do_eqp_test 5.0 {
|
||||
SELECT 5 ORDER BY 1
|
||||
} {
|
||||
QUERY PLAN
|
||||
`--SCAN CONSTANT ROW
|
||||
}
|
||||
do_execsql_test 5.1 {
|
||||
EXPLAIN QUERY PLAN SELECT 5 UNION ALL SELECT 3 ORDER BY 1
|
||||
} {~/B-TREE/}
|
||||
@@ -512,8 +515,9 @@ do_execsql_test 8.0 {
|
||||
do_eqp_test 8.1 {
|
||||
SELECT * FROM t1 ORDER BY a, b;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING INDEX i1}
|
||||
0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 USING INDEX i1
|
||||
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
}
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
|
||||
@@ -101,7 +101,7 @@ do_rollback_test 2.2 -setup {
|
||||
#
|
||||
do_eqp_test 3.1 {
|
||||
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
|
||||
} {0 0 0 {SCAN TABLE t1 USING INDEX i1}}
|
||||
} {SCAN TABLE t1 USING INDEX i1}
|
||||
do_rollback_test 3.2 -setup {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE (i%2)==1;
|
||||
@@ -131,7 +131,7 @@ do_execsql_test 4.1 { UPDATE t1 SET h = $leader || h; }
|
||||
|
||||
do_eqp_test 4.2 {
|
||||
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
|
||||
} {0 0 0 {SCAN TABLE t1 USING INDEX i1}}
|
||||
} {SCAN TABLE t1 USING INDEX i1}
|
||||
do_rollback_test 4.3 -setup {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE (i%2)==1;
|
||||
|
||||
@@ -175,19 +175,19 @@ do_execsql_test 7.0 {
|
||||
|
||||
foreach {tn sql res eqp} {
|
||||
1 "SELECT * FROM xy WHERE (i, j) IS (2, 2)" {2 2 2}
|
||||
"0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid=?)}"
|
||||
"SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid=?)"
|
||||
|
||||
2 "SELECT * FROM xy WHERE (k, j) < (2, 3)" {1 1 1 2 2 2}
|
||||
"0 0 0 {SCAN TABLE xy}"
|
||||
"SCAN TABLE xy"
|
||||
|
||||
3 "SELECT * FROM xy WHERE (i, j) < (2, 3)" {1 1 1 2 2 2}
|
||||
"0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid<?)}"
|
||||
"SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid<?)"
|
||||
|
||||
4 "SELECT * FROM xy WHERE (i, j) > (2, 1)" {2 2 2 3 3 3 4 4 4}
|
||||
"0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)}"
|
||||
"SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)"
|
||||
|
||||
5 "SELECT * FROM xy WHERE (i, j) > ('2', 1)" {2 2 2 3 3 3 4 4 4}
|
||||
"0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)}"
|
||||
"SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)"
|
||||
|
||||
} {
|
||||
do_eqp_test 7.$tn.1 $sql $eqp
|
||||
|
||||
@@ -184,34 +184,33 @@ ifcapable stat4 {
|
||||
ANALYZE;
|
||||
}
|
||||
|
||||
do_eqp_test 3.1.1 { SELECT * FROM c1 WHERE a=1 AND c=2 } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
|
||||
}
|
||||
do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
|
||||
}
|
||||
do_eqp_test 3.1.3 { SELECT * FROM c1 WHERE a=1 AND b>'l' AND c=2 } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=? AND b>?)}
|
||||
}
|
||||
do_eqp_test 3.1.1 { SELECT * FROM c1 WHERE a=1 AND c=2 } \
|
||||
{SEARCH TABLE c1 USING INDEX c1cd (c=?)}
|
||||
|
||||
do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } \
|
||||
{SEARCH TABLE c1 USING INDEX c1cd (c=?)}
|
||||
|
||||
do_eqp_test 3.1.3 { SELECT * FROM c1 WHERE a=1 AND b>'l' AND c=2 } \
|
||||
{SEARCH TABLE c1 USING INDEX c1ab (a=? AND b>?)}
|
||||
|
||||
do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } \
|
||||
{SEARCH TABLE c1 USING INDEX c1cd (c>?)}
|
||||
|
||||
do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } \
|
||||
{SEARCH TABLE c1 USING INDEX c1ab (a=?)}
|
||||
|
||||
do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } \
|
||||
{SEARCH TABLE c1 USING INDEX c1ab (a=?)}
|
||||
|
||||
do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } \
|
||||
{SEARCH TABLE c1 USING INDEX c1ab (a=?)}
|
||||
|
||||
do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } \
|
||||
{SEARCH TABLE c1 USING INDEX c1cd ((c,d)>(?,?))}
|
||||
|
||||
do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } \
|
||||
{SEARCH TABLE c1 USING INDEX c1ab (a=?)}
|
||||
|
||||
do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c>?)}
|
||||
}
|
||||
do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
|
||||
}
|
||||
do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
|
||||
}
|
||||
do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
|
||||
}
|
||||
do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1cd ((c,d)>(?,?))}
|
||||
}
|
||||
do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } {
|
||||
0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
@@ -234,11 +233,12 @@ do_eqp_test 5.1 {
|
||||
(a, b) IN (SELECT x, y FROM d1) AND
|
||||
(c) IN (SELECT y FROM d1)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?)}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE d1}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 2}
|
||||
2 0 0 {SCAN TABLE d1}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?)
|
||||
|--LIST SUBQUERY
|
||||
| `--SCAN TABLE d1
|
||||
`--LIST SUBQUERY
|
||||
`--SCAN TABLE d1
|
||||
}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
@@ -249,31 +249,23 @@ do_execsql_test 6.0 {
|
||||
|
||||
do_eqp_test 6.1 {
|
||||
SELECT * FROM e1 WHERE (a, b) > (?, ?)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE e1 USING INDEX e1ab ((a,b)>(?,?))}
|
||||
}
|
||||
} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)>(?,?))}
|
||||
|
||||
do_eqp_test 6.2 {
|
||||
SELECT * FROM e1 WHERE (a, b) < (?, ?)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE e1 USING INDEX e1ab ((a,b)<(?,?))}
|
||||
}
|
||||
} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)<(?,?))}
|
||||
|
||||
do_eqp_test 6.3 {
|
||||
SELECT * FROM e1 WHERE c = ? AND (d, e) > (?, ?)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))}
|
||||
}
|
||||
} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))}
|
||||
|
||||
do_eqp_test 6.4 {
|
||||
SELECT * FROM e1 WHERE c = ? AND (d, e) < (?, ?)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}
|
||||
}
|
||||
} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}
|
||||
|
||||
do_eqp_test 6.5 {
|
||||
SELECT * FROM e1 WHERE (d, e) BETWEEN (?, ?) AND (?, ?) AND c = ?
|
||||
} {
|
||||
0 0 0
|
||||
{SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}
|
||||
}
|
||||
} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@ do_scanstatus_test 5.2.2 {
|
||||
|
||||
do_eqp_test 5.3.1 {
|
||||
SELECT count(*) FROM t2 WHERE y = 'j';
|
||||
} {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}}
|
||||
} {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
|
||||
do_execsql_test 5.3.2 {
|
||||
SELECT count(*) FROM t2 WHERE y = 'j';
|
||||
} {19}
|
||||
@@ -340,8 +340,9 @@ do_scanstatus_test 5.3.3 {
|
||||
do_eqp_test 5.4.1 {
|
||||
SELECT count(*) FROM t1, t2 WHERE y = c;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING COVERING INDEX t1bc}
|
||||
0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 USING COVERING INDEX t1bc
|
||||
`--SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
|
||||
}
|
||||
do_execsql_test 5.4.2 {
|
||||
SELECT count(*) FROM t1, t2 WHERE y = c;
|
||||
@@ -356,8 +357,9 @@ do_scanstatus_test 5.4.3 {
|
||||
do_eqp_test 5.5.1 {
|
||||
SELECT count(*) FROM t1, t3 WHERE y = c;
|
||||
} {
|
||||
0 0 1 {SCAN TABLE t3}
|
||||
0 1 0 {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t3
|
||||
`--SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)
|
||||
}
|
||||
do_execsql_test 5.5.2 {
|
||||
SELECT count(*) FROM t1, t3 WHERE y = c;
|
||||
|
||||
@@ -1336,11 +1336,14 @@ do_eqp_test 4.1.2 {
|
||||
SELECT a, b FROM t4 WHERE f()==f()
|
||||
ORDER BY 1,2
|
||||
} {
|
||||
1 0 0 {SCAN TABLE t5 USING INDEX i2}
|
||||
1 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
2 0 0 {SCAN TABLE t4 USING INDEX i1}
|
||||
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
|
||||
QUERY PLAN
|
||||
`--MERGE (UNION ALL)
|
||||
|--LEFT
|
||||
| |--SCAN TABLE t5 USING INDEX i2
|
||||
| `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
`--RIGHT
|
||||
|--SCAN TABLE t4 USING INDEX i1
|
||||
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
}
|
||||
|
||||
do_execsql_test 4.1.3 {
|
||||
|
||||
@@ -169,6 +169,6 @@ do_execsql_test selectD-4.1 {
|
||||
WHERE x1.d>5
|
||||
GROUP BY x1.d) AS x2
|
||||
ON t41.b=x2.d;
|
||||
} {/.*SEARCH SUBQUERY 1 AS x2 USING AUTOMATIC.*/}
|
||||
} {/*SEARCH SUBQUERY 0x* AS x2 USING AUTOMATIC*/}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -199,7 +199,7 @@ do_test skipscan2-3.2 {
|
||||
} {}
|
||||
do_eqp_test skipscan2-3.3eqp {
|
||||
SELECT * FROM t3 WHERE b=42;
|
||||
} {0 0 0 {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}}
|
||||
} {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -179,22 +179,13 @@ do_execsql_test 3.0 {
|
||||
#
|
||||
do_eqp_test 3.1 {
|
||||
SELECT * FROM t3 WHERE a = ? AND c = ?
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX t3_a (a=?)}
|
||||
}
|
||||
} {SEARCH TABLE t3 USING INDEX t3_a (a=?)}
|
||||
|
||||
# The same query on table t2. This should use index "t2_a", for the
|
||||
# same reason. At one point though, it was mistakenly using a skip-scan.
|
||||
#
|
||||
do_eqp_test 3.2 {
|
||||
SELECT * FROM t2 WHERE a = ? AND c = ?
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2_a (a=?)}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
} {SEARCH TABLE t2 USING INDEX t2_a (a=?)}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -959,10 +959,81 @@ proc do_timed_execsql_test {testname sql {result {}}} {
|
||||
uplevel do_test [list $testname] [list "execsql_timed {$sql}"]\
|
||||
[list [list {*}$result]]
|
||||
}
|
||||
proc do_eqp_test {name sql res} {
|
||||
uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
|
||||
|
||||
# Run an EXPLAIN QUERY PLAN $sql in database "db". Then rewrite the output
|
||||
# as an ASCII-art graph and return a string that is that graph.
|
||||
#
|
||||
# Hexadecimal literals in the output text are converted into "xxxxxx" since those
|
||||
# literals are pointer values that might very from one run of the test to the
|
||||
# next, yet we want the output to be consistent.
|
||||
#
|
||||
proc query_plan_graph {sql} {
|
||||
db eval "EXPLAIN QUERY PLAN $sql" {
|
||||
set dx($id) $detail
|
||||
lappend cx($parent) $id
|
||||
}
|
||||
set a "\n QUERY PLAN\n"
|
||||
append a [append_graph " " dx cx 0]
|
||||
return [regsub -all { 0x[A-F0-9]+\y} $a { xxxxxx}]
|
||||
}
|
||||
|
||||
# Helper routine for [query_plan_graph SQL]:
|
||||
#
|
||||
# Output rows of the graph that are children of $level.
|
||||
#
|
||||
# prefix: Prepend to every output line
|
||||
#
|
||||
# dxname: Name of an array variable that stores text describe
|
||||
# The description for $id is $dx($id)
|
||||
#
|
||||
# cxname: Name of an array variable holding children of item.
|
||||
# Children of $id are $cx($id)
|
||||
#
|
||||
# level: Render all lines that are children of $level
|
||||
#
|
||||
proc append_graph {prefix dxname cxname level} {
|
||||
upvar $dxname dx $cxname cx
|
||||
set a ""
|
||||
set x $cx($level)
|
||||
set n [llength $x]
|
||||
for {set i 0} {$i<$n} {incr i} {
|
||||
set id [lindex $x $i]
|
||||
if {$i==$n-1} {
|
||||
set p1 "`--"
|
||||
set p2 " "
|
||||
} else {
|
||||
set p1 "|--"
|
||||
set p2 "| "
|
||||
}
|
||||
append a $prefix$p1$dx($id)\n
|
||||
if {[info exists cx($id)]} {
|
||||
append a [append_graph "$prefix$p2" dx cx $id]
|
||||
}
|
||||
}
|
||||
return $a
|
||||
}
|
||||
|
||||
# Do an EXPLAIN QUERY PLAN test on input $sql with expected results $res
|
||||
#
|
||||
# If $res begins with a "\s+QUERY PLAN\n" then it is assumed to be the
|
||||
# complete graph which must match the output of [query_plan_graph $sql]
|
||||
# exactly.
|
||||
#
|
||||
# If $res does not begin with "\s+QUERY PLAN\n" then take it is a string
|
||||
# that must be found somewhere in the query plan output.
|
||||
#
|
||||
proc do_eqp_test {name sql res} {
|
||||
if {[regexp {^\s+QUERY PLAN\n} $res]} {
|
||||
uplevel do_test $name [list [list query_plan_graph $sql]] [list $res]
|
||||
} else {
|
||||
if {[string index $res 0]!="/"} {
|
||||
set res "/*$res*/"
|
||||
}
|
||||
uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Usage: do_select_tests PREFIX ?SWITCHES? TESTLIST
|
||||
#
|
||||
|
||||
@@ -34,20 +34,17 @@ do_execsql_test 2.0 {
|
||||
CREATE UNIQUE INDEX t2y ON t2(y);
|
||||
}
|
||||
|
||||
do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2x}
|
||||
}
|
||||
do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } \
|
||||
{SCAN TABLE t2 USING COVERING INDEX t2x}
|
||||
|
||||
do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2y}
|
||||
}
|
||||
do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } \
|
||||
{SCAN TABLE t2 USING COVERING INDEX t2y}
|
||||
|
||||
do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?)}
|
||||
}
|
||||
do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } \
|
||||
{SEARCH TABLE t2 USING INDEX t2y (y=?)}
|
||||
|
||||
do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } \
|
||||
{SEARCH TABLE t2 USING INDEX t2x (x=?)}
|
||||
|
||||
do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x=?)}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -41,10 +41,8 @@ do_test tkt-78e04-1.3 {
|
||||
}
|
||||
} {}
|
||||
do_test tkt-78e04-1.4 {
|
||||
execsql {
|
||||
EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1abc%';
|
||||
}
|
||||
} {0 0 0 {SCAN TABLE USING COVERING INDEX i1}}
|
||||
db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1abc%';}
|
||||
} {/*SCAN TABLE USING COVERING INDEX i1*/}
|
||||
do_test tkt-78e04-1.5 {
|
||||
execsql {
|
||||
DROP TABLE "";
|
||||
@@ -57,12 +55,12 @@ do_test tkt-78e04-2.1 {
|
||||
CREATE INDEX "" ON t2(x);
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=5;
|
||||
}
|
||||
} {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX (x=?)}}
|
||||
} {/*SEARCH TABLE t2 USING COVERING INDEX (x=?)*/}
|
||||
do_test tkt-78e04-2.2 {
|
||||
execsql {
|
||||
DROP INDEX "";
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=2;
|
||||
}
|
||||
} {0 0 0 {SCAN TABLE t2}}
|
||||
} {/*SCAN TABLE t2*/}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -32,41 +32,41 @@ do_execsql_test 1.1 {
|
||||
CREATE INDEX i1 ON t1(x, y);
|
||||
}
|
||||
|
||||
set idxscan {0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}}
|
||||
set tblscan {0 0 0 {SCAN TABLE t1}}
|
||||
set grpsort {0 0 0 {USE TEMP B-TREE FOR GROUP BY}}
|
||||
set sort {0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
|
||||
set idxscan {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
set tblscan {SCAN TABLE t1}
|
||||
set grpsort {USE TEMP B-TREE FOR GROUP BY}
|
||||
set sort {USE TEMP B-TREE FOR ORDER BY}
|
||||
|
||||
foreach {tn q res eqp} [subst -nocommands {
|
||||
1 "SELECT * FROM t1 GROUP BY x, y ORDER BY x,y"
|
||||
{1 3 2 2 3 1} {$idxscan}
|
||||
|
||||
2 "SELECT * FROM t1 GROUP BY x, y ORDER BY x"
|
||||
{1 3 2 2 3 1} {$idxscan $sort}
|
||||
{1 3 2 2 3 1} {$idxscan*$sort}
|
||||
|
||||
3 "SELECT * FROM t1 GROUP BY y, x ORDER BY y, x"
|
||||
{3 1 2 2 1 3} {$idxscan $sort}
|
||||
{3 1 2 2 1 3} {$idxscan*$sort}
|
||||
|
||||
4 "SELECT * FROM t1 GROUP BY x ORDER BY x"
|
||||
{1 3 2 2 3 1} {$idxscan}
|
||||
|
||||
5 "SELECT * FROM t1 GROUP BY y ORDER BY y"
|
||||
{3 1 2 2 1 3} {$tblscan $grpsort}
|
||||
{3 1 2 2 1 3} {$tblscan*$grpsort}
|
||||
|
||||
6 "SELECT * FROM t1 GROUP BY y ORDER BY x"
|
||||
{1 3 2 2 3 1} {$tblscan $grpsort $sort}
|
||||
{1 3 2 2 3 1} {$tblscan*$grpsort*$sort}
|
||||
|
||||
7 "SELECT * FROM t1 GROUP BY x, y ORDER BY x, y DESC"
|
||||
{1 3 2 2 3 1} {$idxscan $sort}
|
||||
{1 3 2 2 3 1} {$idxscan*$sort}
|
||||
|
||||
8 "SELECT * FROM t1 GROUP BY x, y ORDER BY x DESC, y DESC"
|
||||
{3 1 2 2 1 3} {$idxscan $sort}
|
||||
{3 1 2 2 1 3} {$idxscan*$sort}
|
||||
|
||||
9 "SELECT * FROM t1 GROUP BY x, y ORDER BY x ASC, y ASC"
|
||||
{1 3 2 2 3 1} {$idxscan}
|
||||
|
||||
10 "SELECT * FROM t1 GROUP BY x, y ORDER BY x COLLATE nocase, y"
|
||||
{1 3 2 2 3 1} {$idxscan $sort}
|
||||
{1 3 2 2 3 1} {$idxscan*$sort}
|
||||
|
||||
}] {
|
||||
do_execsql_test 1.$tn.1 $q $res
|
||||
|
||||
@@ -34,35 +34,24 @@ do_test tkt3442-1.1 {
|
||||
}
|
||||
} {}
|
||||
|
||||
|
||||
# Explain Query Plan
|
||||
#
|
||||
proc EQP {sql} {
|
||||
uplevel "execsql {EXPLAIN QUERY PLAN $sql}"
|
||||
}
|
||||
|
||||
|
||||
# These tests perform an EXPLAIN QUERY PLAN on both versions of the
|
||||
# SELECT referenced in ticket #3442 (both '5000' and "5000")
|
||||
# and verify that the query plan is the same.
|
||||
#
|
||||
ifcapable explain {
|
||||
do_test tkt3442-1.2 {
|
||||
EQP { SELECT node FROM listhash WHERE id='5000' LIMIT 1; }
|
||||
} {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}}
|
||||
do_test tkt3442-1.3 {
|
||||
EQP { SELECT node FROM listhash WHERE id="5000" LIMIT 1; }
|
||||
} {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}}
|
||||
}
|
||||
do_eqp_test tkt3442-1.2 {
|
||||
SELECT node FROM listhash WHERE id='5000' LIMIT 1;
|
||||
} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
|
||||
do_eqp_test tkt3442-1.3 {
|
||||
SELECT node FROM listhash WHERE id="5000" LIMIT 1;
|
||||
} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
|
||||
|
||||
|
||||
# Some extra tests testing other permutations of 5000.
|
||||
#
|
||||
ifcapable explain {
|
||||
do_test tkt3442-1.4 {
|
||||
EQP { SELECT node FROM listhash WHERE id=5000 LIMIT 1; }
|
||||
} {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}}
|
||||
}
|
||||
do_eqp_test tkt3442-1.4 {
|
||||
SELECT node FROM listhash WHERE id=5000 LIMIT 1;
|
||||
} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
|
||||
|
||||
do_test tkt3442-1.5 {
|
||||
catchsql {
|
||||
SELECT node FROM listhash WHERE id=[5000] LIMIT 1;
|
||||
|
||||
@@ -165,7 +165,7 @@ do_test tpch01-1.1 {
|
||||
order by
|
||||
o_year;}]
|
||||
set ::eqpres
|
||||
} {/0 0 0 {SEARCH TABLE part USING INDEX bootleg_pti .P_TYPE=..} 0 1 2 {SEARCH TABLE lineitem USING INDEX lpki2 .L_PARTKEY=..}.*/}
|
||||
} {/*SEARCH TABLE part USING INDEX bootleg_pti *SEARCH TABLE lineitem USING INDEX lpki2*/}
|
||||
do_test tpch01-1.1b {
|
||||
set ::eqpres
|
||||
} {/.* customer .* nation AS n1 .*/}
|
||||
@@ -187,6 +187,14 @@ group by
|
||||
c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment
|
||||
order by
|
||||
revenue desc;
|
||||
} {0 0 1 {SEARCH TABLE orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE<?)} 0 1 0 {SEARCH TABLE customer USING INDEX cpki (C_CUSTKEY=?)} 0 2 3 {SEARCH TABLE nation USING INDEX npki (N_NATIONKEY=?)} 0 3 2 {SEARCH TABLE lineitem USING INDEX lpki (L_ORDERKEY=?)} 0 0 0 {USE TEMP B-TREE FOR GROUP BY} 0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE<?)
|
||||
|--SEARCH TABLE customer USING INDEX cpki (C_CUSTKEY=?)
|
||||
|--SEARCH TABLE nation USING INDEX npki (N_NATIONKEY=?)
|
||||
|--SEARCH TABLE lineitem USING INDEX lpki (L_ORDERKEY=?)
|
||||
|--USE TEMP B-TREE FOR GROUP BY
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -40,28 +40,27 @@ foreach idxmode {ordered unordered} {
|
||||
sqlite3 db test.db
|
||||
foreach {tn sql r(ordered) r(unordered)} {
|
||||
1 "SELECT * FROM t1 ORDER BY a"
|
||||
{0 0 0 {SCAN TABLE t1 USING INDEX i1}}
|
||||
{0 0 0 {SCAN TABLE t1} 0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
|
||||
{SCAN TABLE t1 USING INDEX i1}
|
||||
{SCAN TABLE t1*USE TEMP B-TREE FOR ORDER BY}
|
||||
2 "SELECT * FROM t1 WHERE a > 100"
|
||||
{0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}}
|
||||
{0 0 0 {SCAN TABLE t1}}
|
||||
{SEARCH TABLE t1 USING INDEX i1 (a>?)}
|
||||
{SCAN TABLE t1}
|
||||
3 "SELECT * FROM t1 WHERE a = ? ORDER BY rowid"
|
||||
{0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
{0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
|
||||
{SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
{SEARCH TABLE t1 USING INDEX i1 (a=?)*USE TEMP B-TREE FOR ORDER BY}
|
||||
4 "SELECT max(a) FROM t1"
|
||||
{0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1}}
|
||||
{0 0 0 {SEARCH TABLE t1}}
|
||||
{SEARCH TABLE t1 USING COVERING INDEX i1}
|
||||
{SEARCH TABLE t1}
|
||||
5 "SELECT group_concat(b) FROM t1 GROUP BY a"
|
||||
{0 0 0 {SCAN TABLE t1 USING INDEX i1}}
|
||||
{0 0 0 {SCAN TABLE t1} 0 0 0 {USE TEMP B-TREE FOR GROUP BY}}
|
||||
{SCAN TABLE t1 USING INDEX i1}
|
||||
{SCAN TABLE t1*USE TEMP B-TREE FOR GROUP BY}
|
||||
|
||||
6 "SELECT * FROM t1 WHERE a = ?"
|
||||
{0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
{0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
{SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
{SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
7 "SELECT count(*) FROM t1"
|
||||
{0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}}
|
||||
{0 0 0 {SCAN TABLE t1}}
|
||||
{SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
{SCAN TABLE t1}
|
||||
} {
|
||||
do_eqp_test 1.$idxmode.$tn $sql $r($idxmode)
|
||||
}
|
||||
|
||||
@@ -235,17 +235,20 @@ do_execsql_test where3-3.0 {
|
||||
CREATE TABLE t302(x, y);
|
||||
INSERT INTO t302 VALUES(4,5);
|
||||
ANALYZE;
|
||||
explain query plan SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t302}
|
||||
0 1 1 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
}
|
||||
do_execsql_test where3-3.1 {
|
||||
explain query plan
|
||||
do_eqp_test where3-3.0a {
|
||||
SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t302
|
||||
`--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
do_eqp_test where3-3.1 {
|
||||
SELECT * FROM t301, t302 WHERE t302.x=5 AND t301.a=t302.y;
|
||||
} {
|
||||
0 0 1 {SCAN TABLE t302}
|
||||
0 1 0 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t302
|
||||
`--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
do_execsql_test where3-3.2 {
|
||||
SELECT * FROM t301 WHERE c=3 AND a IS NULL;
|
||||
@@ -308,8 +311,8 @@ do_execsql_test where3-5.0 {
|
||||
CREATE INDEX bbb_111 ON bbb (fk, type);
|
||||
CREATE INDEX bbb_222 ON bbb (parent, position);
|
||||
CREATE INDEX bbb_333 ON bbb (fk, lastModified);
|
||||
|
||||
EXPLAIN QUERY PLAN
|
||||
}
|
||||
do_eqp_test where3-5.0a {
|
||||
SELECT bbb.title AS tag_title
|
||||
FROM aaa JOIN bbb ON bbb.id = aaa.parent
|
||||
WHERE aaa.fk = 'constant'
|
||||
@@ -317,12 +320,12 @@ do_execsql_test where3-5.0 {
|
||||
AND bbb.parent = 4
|
||||
ORDER BY bbb.title COLLATE NOCASE ASC;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)}
|
||||
0 1 1 {SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
|
||||
|--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
do_execsql_test where3-5.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test where3-5.1 {
|
||||
SELECT bbb.title AS tag_title
|
||||
FROM aaa JOIN aaa AS bbb ON bbb.id = aaa.parent
|
||||
WHERE aaa.fk = 'constant'
|
||||
@@ -330,12 +333,12 @@ do_execsql_test where3-5.1 {
|
||||
AND bbb.parent = 4
|
||||
ORDER BY bbb.title COLLATE NOCASE ASC;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)}
|
||||
0 1 1 {SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
|
||||
|--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
do_execsql_test where3-5.2 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test where3-5.2 {
|
||||
SELECT bbb.title AS tag_title
|
||||
FROM bbb JOIN aaa ON bbb.id = aaa.parent
|
||||
WHERE aaa.fk = 'constant'
|
||||
@@ -343,12 +346,12 @@ do_execsql_test where3-5.2 {
|
||||
AND bbb.parent = 4
|
||||
ORDER BY bbb.title COLLATE NOCASE ASC;
|
||||
} {
|
||||
0 0 1 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)}
|
||||
0 1 0 {SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
|
||||
|--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
do_execsql_test where3-5.3 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test where3-5.3 {
|
||||
SELECT bbb.title AS tag_title
|
||||
FROM aaa AS bbb JOIN aaa ON bbb.id = aaa.parent
|
||||
WHERE aaa.fk = 'constant'
|
||||
@@ -356,9 +359,10 @@ do_execsql_test where3-5.3 {
|
||||
AND bbb.parent = 4
|
||||
ORDER BY bbb.title COLLATE NOCASE ASC;
|
||||
} {
|
||||
0 0 1 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)}
|
||||
0 1 0 {SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
|
||||
|--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
# Name resolution with NATURAL JOIN and USING
|
||||
|
||||
@@ -23341,8 +23341,8 @@ do_execsql_test where7-3.1 {
|
||||
CREATE INDEX t302_c3 on t302(c3);
|
||||
CREATE INDEX t302_c8_c3 on t302(c8, c3);
|
||||
CREATE INDEX t302_c5 on t302(c5);
|
||||
|
||||
EXPLAIN QUERY PLAN
|
||||
}
|
||||
do_eqp_test where7-3.2 {
|
||||
SELECT t302.c1
|
||||
FROM t302 JOIN t301 ON t302.c8 = +t301.c8
|
||||
WHERE t302.c2 = 19571
|
||||
@@ -23351,10 +23351,11 @@ do_execsql_test where7-3.1 {
|
||||
OR t301.c8 = 1407424651264000)
|
||||
ORDER BY t302.c5 LIMIT 200;
|
||||
} {
|
||||
0 0 1 {SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?)}
|
||||
0 0 1 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 1 0 {SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?)
|
||||
|--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -357,25 +357,25 @@ do_test where9-2.8 {
|
||||
|
||||
|
||||
ifcapable explain {
|
||||
do_execsql_test where9-3.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test where9-3.1 {
|
||||
SELECT t2.a FROM t1, t2
|
||||
WHERE t1.a=80 AND ((t1.c=t2.c AND t1.d=t2.d) OR t1.f=t2.f)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 1 1 {SEARCH TABLE t2 USING INDEX t2d (d=?)}
|
||||
0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)}
|
||||
}
|
||||
do_execsql_test where9-3.2 {
|
||||
EXPLAIN QUERY PLAN
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SEARCH TABLE t2 USING INDEX t2d (d=?)
|
||||
`--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
|
||||
}]
|
||||
do_eqp_test where9-3.2 {
|
||||
SELECT coalesce(t2.a,9999)
|
||||
FROM t1 LEFT JOIN t2 ON (t1.c+1=t2.c AND t1.d=t2.d) OR (t1.f||'x')=t2.f
|
||||
WHERE t1.a=80
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 1 1 {SEARCH TABLE t2 USING INDEX t2d (d=?)}
|
||||
0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)}
|
||||
}
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SEARCH TABLE t2 USING INDEX t2d (d=?)
|
||||
`--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
|
||||
}]
|
||||
}
|
||||
|
||||
# Make sure that INDEXED BY and multi-index OR clauses play well with
|
||||
@@ -446,35 +446,30 @@ do_test where9-4.8 {
|
||||
}
|
||||
} {1 {no query solution}}
|
||||
|
||||
ifcapable explain {
|
||||
# The (c=31031 OR d IS NULL) clause is preferred over b>1000 because
|
||||
# the former is an equality test which is expected to return fewer rows.
|
||||
#
|
||||
do_execsql_test where9-5.1 {
|
||||
EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?)}
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1d (d=?)}
|
||||
}
|
||||
|
||||
# In contrast, b=1000 is preferred over any OR-clause.
|
||||
#
|
||||
do_execsql_test where9-5.2 {
|
||||
EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b=1000 AND (c=31031 OR d IS NULL)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}
|
||||
}
|
||||
|
||||
# Likewise, inequalities in an AND are preferred over inequalities in
|
||||
# an OR.
|
||||
#
|
||||
do_execsql_test where9-5.3 {
|
||||
EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>1000 AND (c>=31031 OR d IS NULL)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>?)}
|
||||
}
|
||||
# The (c=31031 OR d IS NULL) clause is preferred over b>1000 because
|
||||
# the former is an equality test which is expected to return fewer rows.
|
||||
#
|
||||
do_eqp_test where9-5.1 {
|
||||
SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL)
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t1 USING INDEX t1c (c=?)
|
||||
`--SEARCH TABLE t1 USING INDEX t1d (d=?)
|
||||
}
|
||||
|
||||
# In contrast, b=1000 is preferred over any OR-clause.
|
||||
#
|
||||
do_eqp_test where9-5.2 {
|
||||
SELECT a FROM t1 WHERE b=1000 AND (c=31031 OR d IS NULL)
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b=?)}
|
||||
|
||||
# Likewise, inequalities in an AND are preferred over inequalities in
|
||||
# an OR.
|
||||
#
|
||||
do_eqp_test where9-5.3 {
|
||||
SELECT a FROM t1 WHERE b>1000 AND (c>=31031 OR d IS NULL)
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b>?)}
|
||||
|
||||
############################################################################
|
||||
# Make sure OR-clauses work correctly on UPDATE and DELETE statements.
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ do_eqp_test whereG-1.1 {
|
||||
WHERE unlikely(cname LIKE '%bach%')
|
||||
AND composer.cid=track.cid
|
||||
AND album.aid=track.aid;
|
||||
} {/.*composer.*track.*album.*/}
|
||||
} {composer*track*album}
|
||||
do_execsql_test whereG-1.2 {
|
||||
SELECT DISTINCT aname
|
||||
FROM album, composer, track
|
||||
@@ -195,13 +195,13 @@ do_execsql_test 5.1 {
|
||||
}
|
||||
do_eqp_test 5.1.2 {
|
||||
SELECT * FROM t1 WHERE a>?
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a>?)}
|
||||
do_eqp_test 5.1.3 {
|
||||
SELECT * FROM t1 WHERE likelihood(a>?, 0.9)
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
do_eqp_test 5.1.4 {
|
||||
SELECT * FROM t1 WHERE likely(a>?)
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
do_test 5.2 {
|
||||
for {set i 0} {$i < 100} {incr i} {
|
||||
@@ -212,23 +212,23 @@ do_test 5.2 {
|
||||
} {}
|
||||
do_eqp_test 5.2.2 {
|
||||
SELECT * FROM t1 WHERE likelihood(b>?, 0.01)
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (ANY(a) AND b>?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (ANY(a) AND b>?)}
|
||||
do_eqp_test 5.2.3 {
|
||||
SELECT * FROM t1 WHERE likelihood(b>?, 0.9)
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
do_eqp_test 5.2.4 {
|
||||
SELECT * FROM t1 WHERE likely(b>?)
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
do_eqp_test 5.3.1 {
|
||||
SELECT * FROM t1 WHERE a=?
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
do_eqp_test 5.3.2 {
|
||||
SELECT * FROM t1 WHERE likelihood(a=?, 0.9)
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
do_eqp_test 5.3.3 {
|
||||
SELECT * FROM t1 WHERE likely(a=?)
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
# 2015-06-18
|
||||
# Ticket [https://www.sqlite.org/see/tktview/472f0742a1868fb58862bc588ed70]
|
||||
|
||||
@@ -29,8 +29,9 @@ do_execsql_test 1.0 {
|
||||
do_eqp_test 1.1 {
|
||||
SELECT a FROM t1 WHERE b='b' OR c='x'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b=?)}
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t1 USING INDEX i1 (b=?)
|
||||
`--SEARCH TABLE t1 USING INDEX i2 (c=?)
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
@@ -57,8 +58,9 @@ do_execsql_test 2.0 {
|
||||
do_eqp_test 2.1 {
|
||||
SELECT a FROM t2 WHERE b='b' OR c='x'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX i3 (b=?)}
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t2 USING INDEX i3 (b=?)
|
||||
`--SEARCH TABLE t2 USING INDEX i4 (c=?)
|
||||
}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
|
||||
@@ -402,9 +402,7 @@ do_eqp_test 3.4 {
|
||||
a = 4 AND b BETWEEN 20 AND 80 -- Matches 80 rows
|
||||
AND
|
||||
c BETWEEN 150 AND 160 -- Matches 10 rows
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c<?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c<?)}
|
||||
|
||||
# This one should use index "idx_ab".
|
||||
do_eqp_test 3.5 {
|
||||
@@ -412,9 +410,7 @@ do_eqp_test 3.5 {
|
||||
a = 5 AND b BETWEEN 20 AND 80 -- Matches 1 row
|
||||
AND
|
||||
c BETWEEN 150 AND 160 -- Matches 10 rows
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX idx_ab (a=? AND b>? AND b<?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX idx_ab (a=? AND b>? AND b<?)}
|
||||
|
||||
###########################################################################################
|
||||
|
||||
|
||||
@@ -992,16 +992,23 @@ do_execsql_test 18.2 {
|
||||
|
||||
# EXPLAIN QUERY PLAN on a self-join of a CTE
|
||||
#
|
||||
do_execsql_test 19.1 {
|
||||
do_execsql_test 19.1a {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
EXPLAIN QUERY PLAN
|
||||
}
|
||||
do_eqp_test 19.1b {
|
||||
WITH
|
||||
x1(a) AS (values(100))
|
||||
INSERT INTO t1(x)
|
||||
SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
|
||||
SELECT * FROM t1;
|
||||
} {0 0 0 {SCAN SUBQUERY 1} 0 1 1 {SCAN SUBQUERY 1}}
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| `--SCAN CONSTANT ROW
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
`--SCAN SUBQUERY xxxxxx
|
||||
}
|
||||
|
||||
# 2017-10-28.
|
||||
# See check-in https://sqlite.org/src/info/0926df095faf72c2
|
||||
|
||||
@@ -79,22 +79,30 @@ ifcapable analyze {
|
||||
do_eqp_test 3.1.2 {
|
||||
WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1)
|
||||
SELECT * FROM cnt, y1 WHERE i=a
|
||||
} {
|
||||
3 0 0 {SCAN TABLE cnt}
|
||||
1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
|
||||
0 0 0 {SCAN SUBQUERY 1}
|
||||
0 1 1 {SEARCH TABLE y1 USING INDEX y1a (a=?)}
|
||||
}
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| |--SETUP
|
||||
| | `--SCAN CONSTANT ROW
|
||||
| `--RECURSIVE STEP
|
||||
| `--SCAN TABLE cnt
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
`--SEARCH TABLE y1 USING INDEX y1a (a=?)
|
||||
}]
|
||||
|
||||
do_eqp_test 3.1.3 {
|
||||
WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000000)
|
||||
SELECT * FROM cnt, y1 WHERE i=a
|
||||
} {
|
||||
3 0 0 {SCAN TABLE cnt}
|
||||
1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
|
||||
0 0 1 {SCAN TABLE y1}
|
||||
0 1 0 {SEARCH SUBQUERY 1 USING AUTOMATIC COVERING INDEX (i=?)}
|
||||
}
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| |--SETUP
|
||||
| | `--SCAN CONSTANT ROW
|
||||
| `--RECURSIVE STEP
|
||||
| `--SCAN TABLE cnt
|
||||
|--SCAN TABLE y1
|
||||
`--SEARCH SUBQUERY xxxxxx USING AUTOMATIC COVERING INDEX (i=?)
|
||||
}]
|
||||
}
|
||||
|
||||
do_execsql_test 3.2.1 {
|
||||
@@ -108,13 +116,18 @@ do_eqp_test 3.2.2 {
|
||||
SELECT * FROM c, w2, w1
|
||||
WHERE c.id=w2.pk AND c.id=w1.pk;
|
||||
} {
|
||||
2 0 0 {EXECUTE SCALAR SUBQUERY 3}
|
||||
3 0 0 {SCAN TABLE w2}
|
||||
4 0 0 {SCAN TABLE w1}
|
||||
4 1 1 {SCAN TABLE c}
|
||||
1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)} 0 0 0 {SCAN SUBQUERY 1}
|
||||
0 1 1 {SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 2 2 {SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| |--SETUP
|
||||
| | |--SCAN CONSTANT ROW
|
||||
| | `--SCALAR SUBQUERY
|
||||
| | `--SCAN TABLE w2
|
||||
| `--RECURSIVE STEP
|
||||
| |--SCAN TABLE w1
|
||||
| `--SCAN TABLE c
|
||||
|--SCAN SUBQUERY xxxxxx
|
||||
|--SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -238,7 +238,7 @@ do_execsql_test 5.0 {
|
||||
|
||||
do_eqp_test 5.1 {
|
||||
SELECT * FROM t45 WHERE b=? AND a>?
|
||||
} {/*USING INDEX i45 (b=? AND a>?)*/}
|
||||
} {USING INDEX i45 (b=? AND a>?)}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
SELECT * FROM t45 WHERE b='two' AND a>4
|
||||
@@ -257,11 +257,11 @@ do_execsql_test 5.4 {
|
||||
}
|
||||
|
||||
set queries {
|
||||
1 2 "c = 5 AND a = 1" {/*i46 (c=? AND a=?)*/}
|
||||
2 6 "c = 4 AND a < 3" {/*i46 (c=? AND a<?)*/}
|
||||
3 4 "c = 2 AND a >= 3" {/*i46 (c=? AND a>?)*/}
|
||||
4 1 "c = 2 AND a = 1 AND b<10" {/*i46 (c=? AND a=? AND b<?)*/}
|
||||
5 1 "c = 0 AND a = 0 AND b>5" {/*i46 (c=? AND a=? AND b>?)*/}
|
||||
1 2 "c = 5 AND a = 1" {i46 (c=? AND a=?)}
|
||||
2 6 "c = 4 AND a < 3" {i46 (c=? AND a<?)}
|
||||
3 4 "c = 2 AND a >= 3" {i46 (c=? AND a>?)}
|
||||
4 1 "c = 2 AND a = 1 AND b<10" {i46 (c=? AND a=? AND b<?)}
|
||||
5 1 "c = 0 AND a = 0 AND b>5" {i46 (c=? AND a=? AND b>?)}
|
||||
}
|
||||
|
||||
foreach {tn cnt where eqp} $queries {
|
||||
|
||||
Reference in New Issue
Block a user