1# 2005 July 28 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# This file implements regression tests for SQLite library. The 12# focus of this file is testing the use of indices in WHERE clauses 13# based on recent changes to the optimizer. 14# 15# $Id: where2.test,v 1.7 2006/01/16 16:24:25 danielk1977 Exp $ 16 17set testdir [file dirname $argv0] 18source $testdir/tester.tcl 19 20# Build some test data 21# 22do_test where2-1.0 { 23 execsql { 24 BEGIN; 25 CREATE TABLE t1(w int, x int, y int, z int); 26 } 27 for {set i 1} {$i<=100} {incr i} { 28 set w $i 29 set x [expr {int(log($i)/log(2))}] 30 set y [expr {$i*$i + 2*$i + 1}] 31 set z [expr {$x+$y}] 32 execsql {INSERT INTO t1 VALUES($::w,$::x,$::y,$::z)} 33 } 34 execsql { 35 CREATE UNIQUE INDEX i1w ON t1(w); 36 CREATE INDEX i1xy ON t1(x,y); 37 CREATE INDEX i1zyx ON t1(z,y,x); 38 COMMIT; 39 } 40} {} 41 42# Do an SQL statement. Append the search count to the end of the result. 43# 44proc count sql { 45 set ::sqlite_search_count 0 46 return [concat [execsql $sql] $::sqlite_search_count] 47} 48 49# This procedure executes the SQL. Then it checks to see if the OP_Sort 50# opcode was executed. If an OP_Sort did occur, then "sort" is appended 51# to the result. If no OP_Sort happened, then "nosort" is appended. 52# 53# This procedure is used to check to make sure sorting is or is not 54# occurring as expected. 55# 56proc cksort {sql} { 57 set ::sqlite_sort_count 0 58 set data [execsql $sql] 59 if {$::sqlite_sort_count} {set x sort} {set x nosort} 60 lappend data $x 61 return $data 62} 63 64# This procedure executes the SQL. Then it appends to the result the 65# "sort" or "nosort" keyword (as in the cksort procedure above) then 66# it appends the ::sqlite_query_plan variable. 67# 68proc queryplan {sql} { 69 set ::sqlite_sort_count 0 70 set data [execsql $sql] 71 if {$::sqlite_sort_count} {set x sort} {set x nosort} 72 lappend data $x 73 return [concat $data $::sqlite_query_plan] 74} 75 76 77# Prefer a UNIQUE index over another index. 78# 79do_test where2-1.1 { 80 queryplan { 81 SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 82 } 83} {85 6 7396 7402 nosort t1 i1w} 84 85# Always prefer a rowid== constraint over any other index. 86# 87do_test where2-1.3 { 88 queryplan { 89 SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 AND rowid=85 90 } 91} {85 6 7396 7402 nosort t1 *} 92 93# When constrained by a UNIQUE index, the ORDER BY clause is always ignored. 94# 95do_test where2-2.1 { 96 queryplan { 97 SELECT * FROM t1 WHERE w=85 ORDER BY random(5); 98 } 99} {85 6 7396 7402 nosort t1 i1w} 100do_test where2-2.2 { 101 queryplan { 102 SELECT * FROM t1 WHERE x=6 AND y=7396 ORDER BY random(5); 103 } 104} {85 6 7396 7402 sort t1 i1xy} 105do_test where2-2.3 { 106 queryplan { 107 SELECT * FROM t1 WHERE rowid=85 AND x=6 AND y=7396 ORDER BY random(5); 108 } 109} {85 6 7396 7402 nosort t1 *} 110 111 112# Efficient handling of forward and reverse table scans. 113# 114do_test where2-3.1 { 115 queryplan { 116 SELECT * FROM t1 ORDER BY rowid LIMIT 2 117 } 118} {1 0 4 4 2 1 9 10 nosort t1 *} 119do_test where2-3.2 { 120 queryplan { 121 SELECT * FROM t1 ORDER BY rowid DESC LIMIT 2 122 } 123} {100 6 10201 10207 99 6 10000 10006 nosort t1 *} 124 125# The IN operator can be used by indices at multiple layers 126# 127ifcapable subquery { 128 do_test where2-4.1 { 129 queryplan { 130 SELECT * FROM t1 WHERE z IN (10207,10006) AND y IN (10000,10201) 131 AND x>0 AND x<10 132 ORDER BY w 133 } 134 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} 135 do_test where2-4.2 { 136 queryplan { 137 SELECT * FROM t1 WHERE z IN (10207,10006) AND y=10000 138 AND x>0 AND x<10 139 ORDER BY w 140 } 141 } {99 6 10000 10006 sort t1 i1zyx} 142 do_test where2-4.3 { 143 queryplan { 144 SELECT * FROM t1 WHERE z=10006 AND y IN (10000,10201) 145 AND x>0 AND x<10 146 ORDER BY w 147 } 148 } {99 6 10000 10006 sort t1 i1zyx} 149 ifcapable compound { 150 do_test where2-4.4 { 151 queryplan { 152 SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006) 153 AND y IN (10000,10201) 154 AND x>0 AND x<10 155 ORDER BY w 156 } 157 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} 158 do_test where2-4.5 { 159 queryplan { 160 SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006) 161 AND y IN (SELECT 10000 UNION SELECT 10201) 162 AND x>0 AND x<10 163 ORDER BY w 164 } 165 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} 166 } 167 do_test where2-4.6 { 168 queryplan { 169 SELECT * FROM t1 170 WHERE x IN (1,2,3,4,5,6,7,8) 171 AND y IN (10000,10001,10002,10003,10004,10005) 172 ORDER BY 2 173 } 174 } {99 6 10000 10006 sort t1 i1xy} 175 176 # Duplicate entires on the RHS of an IN operator do not cause duplicate 177 # output rows. 178 # 179 do_test where2-4.6 { 180 queryplan { 181 SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207) 182 ORDER BY w 183 } 184 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} 185 ifcapable compound { 186 do_test where2-4.7 { 187 queryplan { 188 SELECT * FROM t1 WHERE z IN ( 189 SELECT 10207 UNION ALL SELECT 10006 190 UNION ALL SELECT 10006 UNION ALL SELECT 10207) 191 ORDER BY w 192 } 193 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} 194 } 195 196} ;# ifcapable subquery 197 198# The use of an IN operator disables the index as a sorter. 199# 200do_test where2-5.1 { 201 queryplan { 202 SELECT * FROM t1 WHERE w=99 ORDER BY w 203 } 204} {99 6 10000 10006 nosort t1 i1w} 205 206ifcapable subquery { 207 do_test where2-5.2 { 208 queryplan { 209 SELECT * FROM t1 WHERE w IN (99) ORDER BY w 210 } 211 } {99 6 10000 10006 sort t1 i1w} 212} 213 214# Verify that OR clauses get translated into IN operators. 215# 216set ::idx {} 217ifcapable subquery {set ::idx i1w} 218do_test where2-6.1 { 219 queryplan { 220 SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w 221 } 222} [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx] 223do_test where2-6.2 { 224 queryplan { 225 SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w 226 } 227} [list 6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx] 228 229do_test where2-6.3 { 230 queryplan { 231 SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w 232 } 233} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}} 234do_test where2-6.4 { 235 queryplan { 236 SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w 237 } 238} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}} 239 240set ::idx {} 241ifcapable subquery {set ::idx i1zyx} 242do_test where2-6.5 { 243 queryplan { 244 SELECT b.* FROM t1 a, t1 b 245 WHERE a.w=1 AND (a.y=b.z OR b.z=10) 246 ORDER BY +b.w 247 } 248} [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx] 249do_test where2-6.6 { 250 queryplan { 251 SELECT b.* FROM t1 a, t1 b 252 WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10) 253 ORDER BY +b.w 254 } 255} [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx] 256 257# Unique queries (queries that are guaranteed to return only a single 258# row of result) do not call the sorter. But all tables must give 259# a unique result. If any one table in the join does not give a unique 260# result then sorting is necessary. 261# 262do_test where2-7.1 { 263 cksort { 264 create table t8(a unique, b, c); 265 insert into t8 values(1,2,3); 266 insert into t8 values(2,3,4); 267 create table t9(x,y); 268 insert into t9 values(2,4); 269 insert into t9 values(2,3); 270 select y from t8, t9 where a=1 order by a, y; 271 } 272} {3 4 sort} 273do_test where2-7.2 { 274 cksort { 275 select * from t8 where a=1 order by b, c 276 } 277} {1 2 3 nosort} 278do_test where2-7.3 { 279 cksort { 280 select * from t8, t9 where a=1 and y=3 order by b, x 281 } 282} {1 2 3 2 3 sort} 283do_test where2-7.4 { 284 cksort { 285 create unique index i9y on t9(y); 286 select * from t8, t9 where a=1 and y=3 order by b, x 287 } 288} {1 2 3 2 3 nosort} 289 290finish_test 291