1# 2014-04-26 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# 12 13set testdir [file dirname $argv0] 14source $testdir/tester.tcl 15set testprefix cost 16 17 18do_execsql_test 1.1 { 19 CREATE TABLE t3(id INTEGER PRIMARY KEY, b NOT NULL); 20 CREATE TABLE t4(c, d, e); 21 CREATE UNIQUE INDEX i3 ON t3(b); 22 CREATE UNIQUE INDEX i4 ON t4(c, d); 23} 24do_eqp_test 1.2 { 25 SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d; 26} { 27 QUERY PLAN 28 |--SCAN TABLE t3 USING COVERING INDEX i3 29 `--SEARCH TABLE t4 USING INDEX i4 (c=?) 30} 31 32 33do_execsql_test 2.1 { 34 CREATE TABLE t1(a, b); 35 CREATE INDEX i1 ON t1(a); 36} 37 38# It is better to use an index for ORDER BY than sort externally, even 39# if the index is a non-covering index. 40do_eqp_test 2.2 { 41 SELECT * FROM t1 ORDER BY a; 42} {SCAN TABLE t1 USING INDEX i1} 43 44do_execsql_test 3.1 { 45 CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g); 46 CREATE INDEX t5b ON t5(b); 47 CREATE INDEX t5c ON t5(c); 48 CREATE INDEX t5d ON t5(d); 49 CREATE INDEX t5e ON t5(e); 50 CREATE INDEX t5f ON t5(f); 51 CREATE INDEX t5g ON t5(g); 52} 53 54do_eqp_test 3.2 { 55 SELECT a FROM t5 56 WHERE b IS NULL OR c IS NULL OR d IS NULL 57 ORDER BY a; 58} { 59 QUERY PLAN 60 |--MULTI-INDEX OR 61 | |--SEARCH TABLE t5 USING INDEX t5b (b=?) 62 | |--SEARCH TABLE t5 USING INDEX t5c (c=?) 63 | `--SEARCH TABLE t5 USING INDEX t5d (d=?) 64 `--USE TEMP B-TREE FOR ORDER BY 65} 66 67#------------------------------------------------------------------------- 68# If there is no likelihood() or stat3 data, SQLite assumes that a closed 69# range scan (e.g. one constrained by "col BETWEEN ? AND ?" constraint) 70# visits 1/64 of the rows in a table. 71# 72# Note: 1/63 =~ 0.016 73# Note: 1/65 =~ 0.015 74# 75reset_db 76do_execsql_test 4.1 { 77 CREATE TABLE t1(a, b); 78 CREATE INDEX i1 ON t1(a); 79 CREATE INDEX i2 ON t1(b); 80} 81do_eqp_test 4.2 { 82 SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?; 83} {SEARCH TABLE t1 USING INDEX i1 (a=?)} 84 85do_eqp_test 4.3 { 86 SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?; 87} {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)} 88 89 90#------------------------------------------------------------------------- 91# 92reset_db 93do_execsql_test 5.1 { 94 CREATE TABLE t2(x, y); 95 CREATE INDEX t2i1 ON t2(x); 96} 97 98do_eqp_test 5.2 { 99 SELECT * FROM t2 ORDER BY x, y; 100} { 101 QUERY PLAN 102 |--SCAN TABLE t2 USING INDEX t2i1 103 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY 104} 105 106do_eqp_test 5.3 { 107 SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid; 108} { 109 QUERY PLAN 110 |--SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?) 111 `--USE TEMP B-TREE FOR ORDER BY 112} 113 114# where7.test, where8.test: 115# 116do_execsql_test 6.1 { 117 CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c); 118 CREATE INDEX t3i1 ON t3(b); 119 CREATE INDEX t3i2 ON t3(c); 120} 121 122do_eqp_test 6.2 { 123 SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a 124} { 125 QUERY PLAN 126 |--MULTI-INDEX OR 127 | |--SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?) 128 | `--SEARCH TABLE t3 USING INDEX t3i2 (c=?) 129 `--USE TEMP B-TREE FOR ORDER BY 130} 131 132#------------------------------------------------------------------------- 133# 134reset_db 135do_execsql_test 7.1 { 136 CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d,e,f,g); 137 CREATE INDEX t1b ON t1(b); 138 CREATE INDEX t1c ON t1(c); 139 CREATE INDEX t1d ON t1(d); 140 CREATE INDEX t1e ON t1(e); 141 CREATE INDEX t1f ON t1(f); 142 CREATE INDEX t1g ON t1(g); 143} 144 145do_eqp_test 7.2 { 146 SELECT a FROM t1 147 WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL) 148 ORDER BY a 149} { 150 QUERY PLAN 151 |--MULTI-INDEX OR 152 | |--SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?) 153 | `--SEARCH TABLE t1 USING INDEX t1b (b=?) 154 `--USE TEMP B-TREE FOR ORDER BY 155} 156 157do_eqp_test 7.3 { 158 SELECT rowid FROM t1 159 WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL) 160 OR (b NOT NULL AND c IS NULL AND d NOT NULL) 161 OR (b NOT NULL AND c NOT NULL AND d IS NULL) 162} {SCAN TABLE t1} 163 164do_eqp_test 7.4 { 165 SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL 166} {SCAN TABLE t1} 167 168#------------------------------------------------------------------------- 169# 170reset_db 171do_execsql_test 8.1 { 172 CREATE TABLE composer( 173 cid INTEGER PRIMARY KEY, 174 cname TEXT 175 ); 176 CREATE TABLE album( 177 aid INTEGER PRIMARY KEY, 178 aname TEXT 179 ); 180 CREATE TABLE track( 181 tid INTEGER PRIMARY KEY, 182 cid INTEGER REFERENCES composer, 183 aid INTEGER REFERENCES album, 184 title TEXT 185 ); 186 CREATE INDEX track_i1 ON track(cid); 187 CREATE INDEX track_i2 ON track(aid); 188} 189 190do_eqp_test 8.2 { 191 SELECT DISTINCT aname 192 FROM album, composer, track 193 WHERE cname LIKE '%bach%' 194 AND unlikely(composer.cid=track.cid) 195 AND unlikely(album.aid=track.aid); 196} { 197 QUERY PLAN 198 |--SCAN TABLE track 199 |--SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?) 200 |--SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?) 201 `--USE TEMP B-TREE FOR DISTINCT 202} 203 204#------------------------------------------------------------------------- 205# 206do_execsql_test 9.1 { 207 CREATE TABLE t1( 208 a,b,c,d,e, f,g,h,i,j, 209 k,l,m,n,o, p,q,r,s,t 210 ); 211 CREATE INDEX i1 ON t1(k,l,m,n,o,p,q,r,s,t); 212} 213do_test 9.2 { 214 for {set i 0} {$i < 100} {incr i} { 215 execsql { INSERT INTO t1 DEFAULT VALUES } 216 } 217 execsql { 218 ANALYZE; 219 CREATE INDEX i2 ON t1(a,b,c,d,e,f,g,h,i,j); 220 } 221} {} 222 223set L [list a=? b=? c=? d=? e=? f=? g=? h=? i=? j=?] 224foreach {tn nTerm nRow} { 225 1 1 10 226 2 2 9 227 3 3 8 228 4 4 7 229 5 5 6 230 6 6 5 231 7 7 5 232 8 8 5 233 9 9 5 234 10 10 5 235} { 236 set w [join [lrange $L 0 [expr $nTerm-1]] " AND "] 237 set p1 [expr ($nRow-1) / 100.0] 238 set p2 [expr ($nRow+1) / 100.0] 239 240 set sql1 "SELECT * FROM t1 WHERE likelihood(k=?, $p1) AND $w" 241 set sql2 "SELECT * FROM t1 WHERE likelihood(k=?, $p2) AND $w" 242 243 do_eqp_test 9.3.$tn.1 $sql1 {/INDEX i1/} 244 do_eqp_test 9.3.$tn.2 $sql2 {/INDEX i2/} 245} 246 247 248#------------------------------------------------------------------------- 249# 250 251ifcapable stat4 { 252 do_execsql_test 10.1 { 253 CREATE TABLE t6(a, b, c); 254 CREATE INDEX t6i1 ON t6(a, b); 255 CREATE INDEX t6i2 ON t6(c); 256 } 257 258 do_test 10.2 { 259 for {set i 0} {$i < 16} {incr i} { 260 execsql { INSERT INTO t6 VALUES($i%4, 'xyz', $i%8) } 261 } 262 execsql ANALYZE 263 } {} 264 265 do_eqp_test 10.3 { 266 SELECT rowid FROM t6 WHERE a=0 AND c=0 267 } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)} 268 269 do_eqp_test 10.4 { 270 SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0 271 } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)} 272 273 do_eqp_test 10.5 { 274 SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0 275 } {SEARCH TABLE t6 USING INDEX t6i1 (a=?)} 276 277 do_eqp_test 10.6 { 278 SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0 279 } {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)} 280} 281 282finish_test 283