125df48d9Sdrh# 2014-07-22 225df48d9Sdrh# 325df48d9Sdrh# The author disclaims copyright to this source code. In place of 425df48d9Sdrh# a legal notice, here is a blessing: 525df48d9Sdrh# 625df48d9Sdrh# May you do good and not evil. 725df48d9Sdrh# May you find forgiveness for yourself and forgive others. 825df48d9Sdrh# May you share freely, never taking more than you give. 925df48d9Sdrh# 1025df48d9Sdrh#*********************************************************************** 1125df48d9Sdrh# 1225df48d9Sdrh# This file contains automated tests used to verify that the text terms 1325df48d9Sdrh# at the end of sqlite_stat1.stat are processed correctly. 1425df48d9Sdrh# 1525df48d9Sdrh# (1) "unordered" means that the index cannot be used for ORDER BY 1625df48d9Sdrh# or for range queries 1725df48d9Sdrh# 1825df48d9Sdrh# (2) "sz=NNN" sets the relative size of the index entries 1925df48d9Sdrh# 2025df48d9Sdrh# (3) All other fields are silently ignored 2125df48d9Sdrh# 2225df48d9Sdrh 2325df48d9Sdrhset testdir [file dirname $argv0] 2425df48d9Sdrhsource $testdir/tester.tcl 2525df48d9Sdrhset testprefix analyzeC 2625df48d9Sdrh 2725df48d9Sdrh# Baseline case. Range queries work OK. Indexes can be used for 2825df48d9Sdrh# ORDER BY. 2925df48d9Sdrh# 3025df48d9Sdrhdo_execsql_test 1.0 { 3125df48d9Sdrh CREATE TABLE t1(a,b,c); 3225df48d9Sdrh INSERT INTO t1(a,b,c) 3325df48d9Sdrh VALUES(1,2,3),(7,8,9),(4,5,6),(10,11,12),(4,8,12),(1,11,111); 3425df48d9Sdrh CREATE INDEX t1a ON t1(a); 3525df48d9Sdrh CREATE INDEX t1b ON t1(b); 3625df48d9Sdrh ANALYZE; 3725df48d9Sdrh DELETE FROM sqlite_stat1; 3825df48d9Sdrh INSERT INTO sqlite_stat1(tbl,idx,stat) 3925df48d9Sdrh VALUES('t1','t1a','12345 2'),('t1','t1b','12345 4'); 4025df48d9Sdrh ANALYZE sqlite_master; 4125df48d9Sdrh SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c; 4225df48d9Sdrh} {4 5 6 # 7 8 9 # 4 8 12 #} 4325df48d9Sdrhdo_execsql_test 1.1 { 4425df48d9Sdrh EXPLAIN QUERY PLAN 4525df48d9Sdrh SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c; 4625df48d9Sdrh} {/.* USING INDEX t1a .a>. AND a<...*/} 4725df48d9Sdrhdo_execsql_test 1.2 { 4825df48d9Sdrh SELECT c FROM t1 ORDER BY a; 4925df48d9Sdrh} {3 111 6 12 9 12} 5025df48d9Sdrhdo_execsql_test 1.3 { 5125df48d9Sdrh EXPLAIN QUERY PLAN 5225df48d9Sdrh SELECT c FROM t1 ORDER BY a; 53*8210233cSdrh} {/.*SCAN t1 USING INDEX t1a.*/} 5425df48d9Sdrhdo_execsql_test 1.3x { 5525df48d9Sdrh EXPLAIN QUERY PLAN 5625df48d9Sdrh SELECT c FROM t1 ORDER BY a; 5725df48d9Sdrh} {~/.*B-TREE FOR ORDER BY.*/} 5825df48d9Sdrh 5925df48d9Sdrh# Now mark the t1a index as "unordered". Range queries and ORDER BY no 6025df48d9Sdrh# longer use the index, but equality queries do. 6125df48d9Sdrh# 6225df48d9Sdrhdo_execsql_test 2.0 { 6325df48d9Sdrh UPDATE sqlite_stat1 SET stat='12345 2 unordered' WHERE idx='t1a'; 6425df48d9Sdrh ANALYZE sqlite_master; 6525df48d9Sdrh SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c; 6625df48d9Sdrh} {4 5 6 # 7 8 9 # 4 8 12 #} 6725df48d9Sdrhdo_execsql_test 2.1 { 6825df48d9Sdrh EXPLAIN QUERY PLAN 6925df48d9Sdrh SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c; 7025df48d9Sdrh} {~/.*USING INDEX.*/} 7125df48d9Sdrhdo_execsql_test 2.2 { 7225df48d9Sdrh SELECT c FROM t1 ORDER BY a; 7325df48d9Sdrh} {3 111 6 12 9 12} 7425df48d9Sdrhdo_execsql_test 2.3 { 7525df48d9Sdrh EXPLAIN QUERY PLAN 7625df48d9Sdrh SELECT c FROM t1 ORDER BY a; 7725df48d9Sdrh} {~/.*USING INDEX.*/} 7825df48d9Sdrhdo_execsql_test 2.3x { 7925df48d9Sdrh EXPLAIN QUERY PLAN 8025df48d9Sdrh SELECT c FROM t1 ORDER BY a; 8125df48d9Sdrh} {/.*B-TREE FOR ORDER BY.*/} 8225df48d9Sdrh 8325df48d9Sdrh# Ignore extraneous text parameters in the sqlite_stat1.stat field. 8425df48d9Sdrh# 8525df48d9Sdrhdo_execsql_test 3.0 { 8625df48d9Sdrh UPDATE sqlite_stat1 SET stat='12345 2 whatever=5 unordered xyzzy=11' 8725df48d9Sdrh WHERE idx='t1a'; 8825df48d9Sdrh ANALYZE sqlite_master; 8925df48d9Sdrh SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c; 9025df48d9Sdrh} {4 5 6 # 7 8 9 # 4 8 12 #} 9125df48d9Sdrhdo_execsql_test 3.1 { 9225df48d9Sdrh EXPLAIN QUERY PLAN 9325df48d9Sdrh SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c; 9425df48d9Sdrh} {~/.*USING INDEX.*/} 9525df48d9Sdrhdo_execsql_test 3.2 { 9625df48d9Sdrh SELECT c FROM t1 ORDER BY a; 9725df48d9Sdrh} {3 111 6 12 9 12} 9825df48d9Sdrhdo_execsql_test 3.3 { 9925df48d9Sdrh EXPLAIN QUERY PLAN 10025df48d9Sdrh SELECT c FROM t1 ORDER BY a; 10125df48d9Sdrh} {~/.*USING INDEX.*/} 10225df48d9Sdrhdo_execsql_test 3.3x { 10325df48d9Sdrh EXPLAIN QUERY PLAN 10425df48d9Sdrh SELECT c FROM t1 ORDER BY a; 10525df48d9Sdrh} {/.*B-TREE FOR ORDER BY.*/} 10625df48d9Sdrh 10725df48d9Sdrh# The sz=NNN parameter determines which index to scan 10825df48d9Sdrh# 10925df48d9Sdrhdo_execsql_test 4.0 { 11025df48d9Sdrh DROP INDEX t1a; 11125df48d9Sdrh CREATE INDEX t1ab ON t1(a,b); 11225df48d9Sdrh CREATE INDEX t1ca ON t1(c,a); 11325df48d9Sdrh DELETE FROM sqlite_stat1; 11425df48d9Sdrh INSERT INTO sqlite_stat1(tbl,idx,stat) 11525df48d9Sdrh VALUES('t1','t1ab','12345 3 2 sz=10'),('t1','t1ca','12345 3 2 sz=20'); 11625df48d9Sdrh ANALYZE sqlite_master; 11725df48d9Sdrh SELECT count(a) FROM t1; 11825df48d9Sdrh} {6} 11925df48d9Sdrhdo_execsql_test 4.1 { 12025df48d9Sdrh EXPLAIN QUERY PLAN 12125df48d9Sdrh SELECT count(a) FROM t1; 12225df48d9Sdrh} {/.*INDEX t1ab.*/} 12325df48d9Sdrhdo_execsql_test 4.2 { 12425df48d9Sdrh DELETE FROM sqlite_stat1; 12525df48d9Sdrh INSERT INTO sqlite_stat1(tbl,idx,stat) 12625df48d9Sdrh VALUES('t1','t1ab','12345 3 2 sz=20'),('t1','t1ca','12345 3 2 sz=10'); 12725df48d9Sdrh ANALYZE sqlite_master; 12825df48d9Sdrh SELECT count(a) FROM t1; 12925df48d9Sdrh} {6} 13025df48d9Sdrhdo_execsql_test 4.3 { 13125df48d9Sdrh EXPLAIN QUERY PLAN 13225df48d9Sdrh SELECT count(a) FROM t1; 13325df48d9Sdrh} {/.*INDEX t1ca.*/} 13425df48d9Sdrh 135725dd724Sdrh# 2019-08-15. 136725dd724Sdrh# Ticket https://www.sqlite.org/src/tktview/e4598ecbdd18bd82945f602901 137725dd724Sdrh# The sz=N parameter in the sqlite_stat1 table needs to have a value of 138725dd724Sdrh# 2 or more to avoid a division by zero in the query planner. 139725dd724Sdrh# 140725dd724Sdrhdo_execsql_test 4.4 { 141725dd724Sdrh DROP TABLE IF EXISTS t44; 142725dd724Sdrh CREATE TABLE t44(a PRIMARY KEY); 143725dd724Sdrh INSERT INTO sqlite_stat1 VALUES('t44',null,'sz=0'); 144725dd724Sdrh ANALYZE sqlite_master; 145725dd724Sdrh SELECT 0 FROM t44 WHERE a IN(1,2,3); 146725dd724Sdrh} {} 147725dd724Sdrh 148725dd724Sdrh 14925df48d9Sdrh 15025df48d9Sdrh# The sz=NNN parameter works even if there is other extraneous text 15125df48d9Sdrh# in the sqlite_stat1.stat column. 15225df48d9Sdrh# 15325df48d9Sdrhdo_execsql_test 5.0 { 15425df48d9Sdrh DELETE FROM sqlite_stat1; 15525df48d9Sdrh INSERT INTO sqlite_stat1(tbl,idx,stat) 15625df48d9Sdrh VALUES('t1','t1ab','12345 3 2 x=5 sz=10 y=10'), 15725df48d9Sdrh ('t1','t1ca','12345 3 2 whatever sz=20 junk'); 15825df48d9Sdrh ANALYZE sqlite_master; 15925df48d9Sdrh SELECT count(a) FROM t1; 16025df48d9Sdrh} {6} 16125df48d9Sdrhdo_execsql_test 5.1 { 16225df48d9Sdrh EXPLAIN QUERY PLAN 16325df48d9Sdrh SELECT count(a) FROM t1; 16425df48d9Sdrh} {/.*INDEX t1ab.*/} 16525df48d9Sdrhdo_execsql_test 5.2 { 16625df48d9Sdrh DELETE FROM sqlite_stat1; 16725df48d9Sdrh INSERT INTO sqlite_stat1(tbl,idx,stat) 16825df48d9Sdrh VALUES('t1','t1ca','12345 3 2 x=5 sz=10 y=10'), 16925df48d9Sdrh ('t1','t1ab','12345 3 2 whatever sz=20 junk'); 17025df48d9Sdrh ANALYZE sqlite_master; 17125df48d9Sdrh SELECT count(a) FROM t1; 17225df48d9Sdrh} {6} 17325df48d9Sdrhdo_execsql_test 5.3 { 17425df48d9Sdrh EXPLAIN QUERY PLAN 17525df48d9Sdrh SELECT count(a) FROM t1; 17625df48d9Sdrh} {/.*INDEX t1ca.*/} 17725df48d9Sdrh 17825df48d9Sdrh 17925df48d9Sdrh 18025df48d9Sdrh 18125df48d9Sdrhfinish_test 182