12dd3cdcfSdan# 2014-04-26 22dd3cdcfSdan# 32dd3cdcfSdan# The author disclaims copyright to this source code. In place of 42dd3cdcfSdan# a legal notice, here is a blessing: 52dd3cdcfSdan# 62dd3cdcfSdan# May you do good and not evil. 72dd3cdcfSdan# May you find forgiveness for yourself and forgive others. 82dd3cdcfSdan# May you share freely, never taking more than you give. 92dd3cdcfSdan# 102dd3cdcfSdan#*********************************************************************** 112dd3cdcfSdan# 122dd3cdcfSdan 132dd3cdcfSdanset testdir [file dirname $argv0] 142dd3cdcfSdansource $testdir/tester.tcl 152dd3cdcfSdanset testprefix cost 162dd3cdcfSdan 172dd3cdcfSdan 182dd3cdcfSdando_execsql_test 1.1 { 192dd3cdcfSdan CREATE TABLE t3(id INTEGER PRIMARY KEY, b NOT NULL); 202dd3cdcfSdan CREATE TABLE t4(c, d, e); 212dd3cdcfSdan CREATE UNIQUE INDEX i3 ON t3(b); 222dd3cdcfSdan CREATE UNIQUE INDEX i4 ON t4(c, d); 232dd3cdcfSdan} 242dd3cdcfSdando_eqp_test 1.2 { 252dd3cdcfSdan SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d; 262dd3cdcfSdan} { 27b3f0276bSdrh QUERY PLAN 28*8210233cSdrh |--SCAN t3 USING COVERING INDEX i3 29*8210233cSdrh `--SEARCH t4 USING INDEX i4 (c=?) 302dd3cdcfSdan} 312dd3cdcfSdan 322dd3cdcfSdan 332dd3cdcfSdando_execsql_test 2.1 { 342dd3cdcfSdan CREATE TABLE t1(a, b); 352dd3cdcfSdan CREATE INDEX i1 ON t1(a); 362dd3cdcfSdan} 372dd3cdcfSdan 382dd3cdcfSdan# It is better to use an index for ORDER BY than sort externally, even 392dd3cdcfSdan# if the index is a non-covering index. 402dd3cdcfSdando_eqp_test 2.2 { 412dd3cdcfSdan SELECT * FROM t1 ORDER BY a; 42*8210233cSdrh} {SCAN t1 USING INDEX i1} 432dd3cdcfSdan 442dd3cdcfSdando_execsql_test 3.1 { 452dd3cdcfSdan CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g); 462dd3cdcfSdan CREATE INDEX t5b ON t5(b); 472dd3cdcfSdan CREATE INDEX t5c ON t5(c); 482dd3cdcfSdan CREATE INDEX t5d ON t5(d); 492dd3cdcfSdan CREATE INDEX t5e ON t5(e); 502dd3cdcfSdan CREATE INDEX t5f ON t5(f); 512dd3cdcfSdan CREATE INDEX t5g ON t5(g); 522dd3cdcfSdan} 532dd3cdcfSdan 542dd3cdcfSdando_eqp_test 3.2 { 552dd3cdcfSdan SELECT a FROM t5 562dd3cdcfSdan WHERE b IS NULL OR c IS NULL OR d IS NULL 572dd3cdcfSdan ORDER BY a; 582dd3cdcfSdan} { 59b3f0276bSdrh QUERY PLAN 605d72d924Sdrh |--MULTI-INDEX OR 61bd462bccSdrh | |--INDEX 1 62*8210233cSdrh | | `--SEARCH t5 USING INDEX t5b (b=?) 63bd462bccSdrh | |--INDEX 2 64*8210233cSdrh | | `--SEARCH t5 USING INDEX t5c (c=?) 65bd462bccSdrh | `--INDEX 3 66*8210233cSdrh | `--SEARCH t5 USING INDEX t5d (d=?) 67b3f0276bSdrh `--USE TEMP B-TREE FOR ORDER BY 682dd3cdcfSdan} 692dd3cdcfSdan 70440e6ff3Sdan#------------------------------------------------------------------------- 71440e6ff3Sdan# If there is no likelihood() or stat3 data, SQLite assumes that a closed 72440e6ff3Sdan# range scan (e.g. one constrained by "col BETWEEN ? AND ?" constraint) 7309e1df6cSdan# visits 1/64 of the rows in a table. 74440e6ff3Sdan# 7509e1df6cSdan# Note: 1/63 =~ 0.016 7609e1df6cSdan# Note: 1/65 =~ 0.015 77440e6ff3Sdan# 78440e6ff3Sdanreset_db 79440e6ff3Sdando_execsql_test 4.1 { 80440e6ff3Sdan CREATE TABLE t1(a, b); 81440e6ff3Sdan CREATE INDEX i1 ON t1(a); 82440e6ff3Sdan CREATE INDEX i2 ON t1(b); 83440e6ff3Sdan} 84440e6ff3Sdando_eqp_test 4.2 { 8509e1df6cSdan SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?; 86*8210233cSdrh} {SEARCH t1 USING INDEX i1 (a=?)} 87b3f0276bSdrh 88440e6ff3Sdando_eqp_test 4.3 { 8909e1df6cSdan SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?; 90*8210233cSdrh} {SEARCH t1 USING INDEX i2 (b>? AND b<?)} 912dd3cdcfSdan 922dd3cdcfSdan 937de2a1faSdan#------------------------------------------------------------------------- 947de2a1faSdan# 957de2a1faSdanreset_db 967de2a1faSdando_execsql_test 5.1 { 977de2a1faSdan CREATE TABLE t2(x, y); 987de2a1faSdan CREATE INDEX t2i1 ON t2(x); 997de2a1faSdan} 1007de2a1faSdan 1017de2a1faSdando_eqp_test 5.2 { 1027de2a1faSdan SELECT * FROM t2 ORDER BY x, y; 10375525cbeSdan} { 104b3f0276bSdrh QUERY PLAN 105*8210233cSdrh |--SCAN t2 USING INDEX t2i1 106b3f0276bSdrh `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY 10775525cbeSdan} 1087de2a1faSdan 1097de2a1faSdando_eqp_test 5.3 { 1107de2a1faSdan SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid; 11109e1df6cSdan} { 112b3f0276bSdrh QUERY PLAN 113*8210233cSdrh |--SEARCH t2 USING INDEX t2i1 (x>? AND x<?) 114b3f0276bSdrh `--USE TEMP B-TREE FOR ORDER BY 11509e1df6cSdan} 1167de2a1faSdan 1177de2a1faSdan# where7.test, where8.test: 1187de2a1faSdan# 1197de2a1faSdando_execsql_test 6.1 { 1207de2a1faSdan CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c); 1217de2a1faSdan CREATE INDEX t3i1 ON t3(b); 1227de2a1faSdan CREATE INDEX t3i2 ON t3(c); 1237de2a1faSdan} 1247de2a1faSdan 1257de2a1faSdando_eqp_test 6.2 { 1267de2a1faSdan SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a 1277de2a1faSdan} { 128b3f0276bSdrh QUERY PLAN 1295d72d924Sdrh |--MULTI-INDEX OR 130bd462bccSdrh | |--INDEX 1 131*8210233cSdrh | | `--SEARCH t3 USING INDEX t3i1 (b>? AND b<?) 132bd462bccSdrh | `--INDEX 2 133*8210233cSdrh | `--SEARCH t3 USING INDEX t3i2 (c=?) 134b3f0276bSdrh `--USE TEMP B-TREE FOR ORDER BY 1357de2a1faSdan} 1367de2a1faSdan 1377de2a1faSdan#------------------------------------------------------------------------- 1387de2a1faSdan# 1397de2a1faSdanreset_db 1407de2a1faSdando_execsql_test 7.1 { 1417de2a1faSdan CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d,e,f,g); 1427de2a1faSdan CREATE INDEX t1b ON t1(b); 1437de2a1faSdan CREATE INDEX t1c ON t1(c); 1447de2a1faSdan CREATE INDEX t1d ON t1(d); 1457de2a1faSdan CREATE INDEX t1e ON t1(e); 1467de2a1faSdan CREATE INDEX t1f ON t1(f); 1477de2a1faSdan CREATE INDEX t1g ON t1(g); 1487de2a1faSdan} 1497de2a1faSdan 1507de2a1faSdando_eqp_test 7.2 { 1517de2a1faSdan SELECT a FROM t1 1527de2a1faSdan WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL) 1537de2a1faSdan ORDER BY a 1547de2a1faSdan} { 155b3f0276bSdrh QUERY PLAN 1565d72d924Sdrh |--MULTI-INDEX OR 157bd462bccSdrh | |--INDEX 1 158*8210233cSdrh | | `--SEARCH t1 USING INDEX t1b (b>? AND b<?) 159bd462bccSdrh | `--INDEX 2 160*8210233cSdrh | `--SEARCH t1 USING INDEX t1b (b=?) 161b3f0276bSdrh `--USE TEMP B-TREE FOR ORDER BY 1627de2a1faSdan} 1637de2a1faSdan 1647de2a1faSdando_eqp_test 7.3 { 1657de2a1faSdan SELECT rowid FROM t1 1667de2a1faSdan WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL) 1677de2a1faSdan OR (b NOT NULL AND c IS NULL AND d NOT NULL) 1687de2a1faSdan OR (b NOT NULL AND c NOT NULL AND d IS NULL) 169*8210233cSdrh} {SCAN t1} 1707de2a1faSdan 1715da73e1aSdando_eqp_test 7.4 { 1725da73e1aSdan SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL 173*8210233cSdrh} {SCAN t1} 1745da73e1aSdan 1757de2a1faSdan#------------------------------------------------------------------------- 1767de2a1faSdan# 1777de2a1faSdanreset_db 1787de2a1faSdando_execsql_test 8.1 { 1797de2a1faSdan CREATE TABLE composer( 1807de2a1faSdan cid INTEGER PRIMARY KEY, 1817de2a1faSdan cname TEXT 1827de2a1faSdan ); 1837de2a1faSdan CREATE TABLE album( 1847de2a1faSdan aid INTEGER PRIMARY KEY, 1857de2a1faSdan aname TEXT 1867de2a1faSdan ); 1877de2a1faSdan CREATE TABLE track( 1887de2a1faSdan tid INTEGER PRIMARY KEY, 1897de2a1faSdan cid INTEGER REFERENCES composer, 1907de2a1faSdan aid INTEGER REFERENCES album, 1917de2a1faSdan title TEXT 1927de2a1faSdan ); 1937de2a1faSdan CREATE INDEX track_i1 ON track(cid); 1947de2a1faSdan CREATE INDEX track_i2 ON track(aid); 1957de2a1faSdan} 1967de2a1faSdan 1977de2a1faSdando_eqp_test 8.2 { 1987de2a1faSdan SELECT DISTINCT aname 1997de2a1faSdan FROM album, composer, track 2007de2a1faSdan WHERE cname LIKE '%bach%' 2017de2a1faSdan AND unlikely(composer.cid=track.cid) 2027de2a1faSdan AND unlikely(album.aid=track.aid); 2037de2a1faSdan} { 204b3f0276bSdrh QUERY PLAN 205*8210233cSdrh |--SCAN track 206*8210233cSdrh |--SEARCH album USING INTEGER PRIMARY KEY (rowid=?) 207*8210233cSdrh |--SEARCH composer USING INTEGER PRIMARY KEY (rowid=?) 208b3f0276bSdrh `--USE TEMP B-TREE FOR DISTINCT 2097de2a1faSdan} 2107de2a1faSdan 211264d2b97Sdan#------------------------------------------------------------------------- 212264d2b97Sdan# 213264d2b97Sdando_execsql_test 9.1 { 214264d2b97Sdan CREATE TABLE t1( 215264d2b97Sdan a,b,c,d,e, f,g,h,i,j, 216264d2b97Sdan k,l,m,n,o, p,q,r,s,t 217264d2b97Sdan ); 218264d2b97Sdan CREATE INDEX i1 ON t1(k,l,m,n,o,p,q,r,s,t); 219264d2b97Sdan} 220264d2b97Sdando_test 9.2 { 221264d2b97Sdan for {set i 0} {$i < 100} {incr i} { 222264d2b97Sdan execsql { INSERT INTO t1 DEFAULT VALUES } 223264d2b97Sdan } 224264d2b97Sdan execsql { 225264d2b97Sdan ANALYZE; 226264d2b97Sdan CREATE INDEX i2 ON t1(a,b,c,d,e,f,g,h,i,j); 227264d2b97Sdan } 228264d2b97Sdan} {} 229264d2b97Sdan 230264d2b97Sdanset L [list a=? b=? c=? d=? e=? f=? g=? h=? i=? j=?] 231264d2b97Sdanforeach {tn nTerm nRow} { 232264d2b97Sdan 1 1 10 23356c65c92Sdrh 2 2 10 234264d2b97Sdan 3 3 8 235264d2b97Sdan 4 4 7 23656c65c92Sdrh 5 5 7 237264d2b97Sdan 6 6 5 238264d2b97Sdan 7 7 5 239264d2b97Sdan 8 8 5 240264d2b97Sdan 9 9 5 241264d2b97Sdan 10 10 5 242264d2b97Sdan} { 243264d2b97Sdan set w [join [lrange $L 0 [expr $nTerm-1]] " AND "] 244264d2b97Sdan set p1 [expr ($nRow-1) / 100.0] 245264d2b97Sdan set p2 [expr ($nRow+1) / 100.0] 246264d2b97Sdan 247264d2b97Sdan set sql1 "SELECT * FROM t1 WHERE likelihood(k=?, $p1) AND $w" 248264d2b97Sdan set sql2 "SELECT * FROM t1 WHERE likelihood(k=?, $p2) AND $w" 249264d2b97Sdan 250264d2b97Sdan do_eqp_test 9.3.$tn.1 $sql1 {/INDEX i1/} 251264d2b97Sdan do_eqp_test 9.3.$tn.2 $sql2 {/INDEX i2/} 252264d2b97Sdan} 253264d2b97Sdan 254264d2b97Sdan 2555a0b8b12Sdan#------------------------------------------------------------------------- 2565a0b8b12Sdan# 2575a0b8b12Sdan 2585a0b8b12Sdanifcapable stat4 { 2595a0b8b12Sdan do_execsql_test 10.1 { 2605a0b8b12Sdan CREATE TABLE t6(a, b, c); 2615a0b8b12Sdan CREATE INDEX t6i1 ON t6(a, b); 2625a0b8b12Sdan CREATE INDEX t6i2 ON t6(c); 2635a0b8b12Sdan } 2645a0b8b12Sdan 2655a0b8b12Sdan do_test 10.2 { 2665a0b8b12Sdan for {set i 0} {$i < 16} {incr i} { 2675a0b8b12Sdan execsql { INSERT INTO t6 VALUES($i%4, 'xyz', $i%8) } 2685a0b8b12Sdan } 2695a0b8b12Sdan execsql ANALYZE 2705a0b8b12Sdan } {} 2715a0b8b12Sdan 2725a0b8b12Sdan do_eqp_test 10.3 { 2735a0b8b12Sdan SELECT rowid FROM t6 WHERE a=0 AND c=0 274*8210233cSdrh } {SEARCH t6 USING INDEX t6i2 (c=?)} 2755a0b8b12Sdan 2765a0b8b12Sdan do_eqp_test 10.4 { 2775a0b8b12Sdan SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0 278*8210233cSdrh } {SEARCH t6 USING INDEX t6i2 (c=?)} 2795a0b8b12Sdan 2805a0b8b12Sdan do_eqp_test 10.5 { 2815a0b8b12Sdan SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0 282*8210233cSdrh } {SEARCH t6 USING INDEX t6i1 (a=?)} 2835a0b8b12Sdan 2845a0b8b12Sdan do_eqp_test 10.6 { 2855a0b8b12Sdan SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0 286*8210233cSdrh } {SEARCH t6 USING INDEX t6i1 (a=? AND b=?)} 2875a0b8b12Sdan} 288264d2b97Sdan 2892dd3cdcfSdanfinish_test 290