192e4feb7Sdrh# 2011 March 3 292e4feb7Sdrh# 392e4feb7Sdrh# The author disclaims copyright to this source code. In place of 492e4feb7Sdrh# a legal notice, here is a blessing: 592e4feb7Sdrh# 692e4feb7Sdrh# May you do good and not evil. 792e4feb7Sdrh# May you find forgiveness for yourself and forgive others. 892e4feb7Sdrh# May you share freely, never taking more than you give. 992e4feb7Sdrh# 1092e4feb7Sdrh#*********************************************************************** 1192e4feb7Sdrh# 1292e4feb7Sdrh# This file implements tests for SQLite library. The focus of the tests 1392e4feb7Sdrh# in this file a corner-case query planner optimization involving the 1492e4feb7Sdrh# join order of two tables of different sizes. 1592e4feb7Sdrh# 1692e4feb7Sdrh 1792e4feb7Sdrhset testdir [file dirname $argv0] 1892e4feb7Sdrhsource $testdir/tester.tcl 1992e4feb7Sdrh 20175b8f06Sdrhifcapable !stat4 { 2192e4feb7Sdrh finish_test 2292e4feb7Sdrh return 2392e4feb7Sdrh} 2492e4feb7Sdrh 2592e4feb7Sdrhset testprefix analyze6 2692e4feb7Sdrh 2792e4feb7Sdrhproc eqp {sql {db db}} { 2892e4feb7Sdrh uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db 2992e4feb7Sdrh} 3092e4feb7Sdrh 3192e4feb7Sdrhdo_test analyze6-1.0 { 3292e4feb7Sdrh db eval { 33d9e3cad2Sdrh CREATE TABLE cat(x INT, yz TEXT); 3492e4feb7Sdrh CREATE UNIQUE INDEX catx ON cat(x); 3592e4feb7Sdrh /* Give cat 16 unique integers */ 36d9e3cad2Sdrh INSERT INTO cat(x) VALUES(1); 37d9e3cad2Sdrh INSERT INTO cat(x) VALUES(2); 38d9e3cad2Sdrh INSERT INTO cat(x) SELECT x+2 FROM cat; 39d9e3cad2Sdrh INSERT INTO cat(x) SELECT x+4 FROM cat; 40d9e3cad2Sdrh INSERT INTO cat(x) SELECT x+8 FROM cat; 4192e4feb7Sdrh 4292e4feb7Sdrh CREATE TABLE ev(y INT); 4392e4feb7Sdrh CREATE INDEX evy ON ev(y); 4492e4feb7Sdrh /* ev will hold 32 copies of 16 integers found in cat */ 4592e4feb7Sdrh INSERT INTO ev SELECT x FROM cat; 4692e4feb7Sdrh INSERT INTO ev SELECT x FROM cat; 4792e4feb7Sdrh INSERT INTO ev SELECT y FROM ev; 4892e4feb7Sdrh INSERT INTO ev SELECT y FROM ev; 4992e4feb7Sdrh INSERT INTO ev SELECT y FROM ev; 5092e4feb7Sdrh INSERT INTO ev SELECT y FROM ev; 5192e4feb7Sdrh ANALYZE; 5292e4feb7Sdrh SELECT count(*) FROM cat; 5392e4feb7Sdrh SELECT count(*) FROM ev; 5492e4feb7Sdrh } 5592e4feb7Sdrh} {16 512} 5692e4feb7Sdrh 5792e4feb7Sdrh# The lowest cost plan is to scan CAT and for each integer there, do a single 5892e4feb7Sdrh# lookup of the first corresponding entry in EV then read off the equal values 5992e4feb7Sdrh# in EV. (Prior to the 2011-03-04 enhancement to where.c, this query would 6092e4feb7Sdrh# have used EV for the outer loop instead of CAT - which was about 3x slower.) 6192e4feb7Sdrh# 6292e4feb7Sdrhdo_test analyze6-1.1 { 6392e4feb7Sdrh eqp {SELECT count(*) FROM ev, cat WHERE x=y} 64*8210233cSdrh} {/*SCAN cat USING COVERING INDEX catx*SEARCH ev USING COVERING INDEX evy (y=?)*/} 6592e4feb7Sdrh 6692e4feb7Sdrh# The same plan is chosen regardless of the order of the tables in the 6792e4feb7Sdrh# FROM clause. 6892e4feb7Sdrh# 69cdf88760Sdrhdo_eqp_test analyze6-1.2 { 70cdf88760Sdrh SELECT count(*) FROM cat, ev WHERE x=y 71cdf88760Sdrh} { 72cdf88760Sdrh QUERY PLAN 73*8210233cSdrh |--SCAN cat USING COVERING INDEX catx 74*8210233cSdrh `--SEARCH ev USING COVERING INDEX evy (y=?) 75cdf88760Sdrh} 7692e4feb7Sdrh 7792e4feb7Sdrh 78f6cf1ffbSdrh# Ticket [83ea97620bd3101645138b7b0e71c12c5498fe3d] 2011-03-30 79f6cf1ffbSdrh# If ANALYZE is run on an empty table, make sure indices are used 80f6cf1ffbSdrh# on the table. 81f6cf1ffbSdrh# 82f6cf1ffbSdrhdo_test analyze6-2.1 { 83f6cf1ffbSdrh execsql { 84f6cf1ffbSdrh CREATE TABLE t201(x INTEGER PRIMARY KEY, y UNIQUE, z); 85f6cf1ffbSdrh CREATE INDEX t201z ON t201(z); 86f6cf1ffbSdrh ANALYZE; 87f6cf1ffbSdrh } 88f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE z=5} 89*8210233cSdrh} {/*SEARCH t201 USING INDEX t201z (z=?)*/} 90f6cf1ffbSdrhdo_test analyze6-2.2 { 91f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE y=5} 92*8210233cSdrh} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/} 93f6cf1ffbSdrhdo_test analyze6-2.3 { 94f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE x=5} 95*8210233cSdrh} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/} 96f6cf1ffbSdrhdo_test analyze6-2.4 { 97f6cf1ffbSdrh execsql { 98358406fcSdrh INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5); 99f6cf1ffbSdrh ANALYZE t201; 100f6cf1ffbSdrh } 101f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE z=5} 102*8210233cSdrh} {/*SEARCH t201 USING INDEX t201z (z=?)*/} 103f6cf1ffbSdrhdo_test analyze6-2.5 { 104f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE y=5} 105*8210233cSdrh} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/} 106f6cf1ffbSdrhdo_test analyze6-2.6 { 107f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE x=5} 108*8210233cSdrh} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/} 109f6cf1ffbSdrhdo_test analyze6-2.7 { 110f6cf1ffbSdrh execsql { 111f6cf1ffbSdrh INSERT INTO t201 VALUES(4,5,7); 112f6cf1ffbSdrh INSERT INTO t201 SELECT x+100, y+100, z+100 FROM t201; 113f6cf1ffbSdrh INSERT INTO t201 SELECT x+200, y+200, z+200 FROM t201; 114f6cf1ffbSdrh INSERT INTO t201 SELECT x+400, y+400, z+400 FROM t201; 115f6cf1ffbSdrh ANALYZE t201; 116f6cf1ffbSdrh } 117f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE z=5} 118*8210233cSdrh} {/*SEARCH t201 USING INDEX t201z (z=?)*/} 119f6cf1ffbSdrhdo_test analyze6-2.8 { 120f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE y=5} 121*8210233cSdrh} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/} 122f6cf1ffbSdrhdo_test analyze6-2.9 { 123f6cf1ffbSdrh eqp {SELECT * FROM t201 WHERE x=5} 124*8210233cSdrh} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/} 125f6cf1ffbSdrh 12692e4feb7Sdrhfinish_test 127