| OLD | NEW |
| 1 # 2005 July 28 | 1 # 2005 July 28 |
| 2 # | 2 # |
| 3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
| 4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
| 5 # | 5 # |
| 6 # May you do good and not evil. | 6 # May you do good and not evil. |
| 7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
| 8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
| 9 # | 9 # |
| 10 #*********************************************************************** | 10 #*********************************************************************** |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 # | 59 # |
| 60 proc cksort {sql} { | 60 proc cksort {sql} { |
| 61 set data [execsql $sql] | 61 set data [execsql $sql] |
| 62 if {[db status sort]} {set x sort} {set x nosort} | 62 if {[db status sort]} {set x sort} {set x nosort} |
| 63 lappend data $x | 63 lappend data $x |
| 64 return $data | 64 return $data |
| 65 } | 65 } |
| 66 | 66 |
| 67 # This procedure executes the SQL. Then it appends to the result the | 67 # This procedure executes the SQL. Then it appends to the result the |
| 68 # "sort" or "nosort" keyword (as in the cksort procedure above) then | 68 # "sort" or "nosort" keyword (as in the cksort procedure above) then |
| 69 # it appends the ::sqlite_query_plan variable. | 69 # it appends the name of the table and index used. |
| 70 # | 70 # |
| 71 proc queryplan {sql} { | 71 proc queryplan {sql} { |
| 72 set ::sqlite_sort_count 0 | 72 set ::sqlite_sort_count 0 |
| 73 set data [execsql $sql] | 73 set data [execsql $sql] |
| 74 if {$::sqlite_sort_count} {set x sort} {set x nosort} | 74 if {$::sqlite_sort_count} {set x sort} {set x nosort} |
| 75 lappend data $x | 75 lappend data $x |
| 76 return [concat $data $::sqlite_query_plan] | 76 set eqp [execsql "EXPLAIN QUERY PLAN $sql"] |
| 77 # puts eqp=$eqp |
| 78 foreach {a b c x} $eqp { |
| 79 if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \ |
| 80 $x all as tab idx]} { |
| 81 lappend data $tab $idx |
| 82 } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} { |
| 83 lappend data $tab * |
| 84 } |
| 85 } |
| 86 return $data |
| 77 } | 87 } |
| 78 | 88 |
| 79 | 89 |
| 80 # Prefer a UNIQUE index over another index. | 90 # Prefer a UNIQUE index over another index. |
| 81 # | 91 # |
| 82 do_test where2-1.1 { | 92 do_test where2-1.1 { |
| 83 queryplan { | 93 queryplan { |
| 84 SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 | 94 SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 |
| 85 } | 95 } |
| 86 } {85 6 7396 7402 nosort t1 i1w} | 96 } {85 6 7396 7402 nosort t1 i1w} |
| (...skipping 17 matching lines...) Expand all Loading... |
| 104 queryplan { | 114 queryplan { |
| 105 SELECT * FROM t1 WHERE x=6 AND y=7396 ORDER BY random(); | 115 SELECT * FROM t1 WHERE x=6 AND y=7396 ORDER BY random(); |
| 106 } | 116 } |
| 107 } {85 6 7396 7402 sort t1 i1xy} | 117 } {85 6 7396 7402 sort t1 i1xy} |
| 108 do_test where2-2.3 { | 118 do_test where2-2.3 { |
| 109 queryplan { | 119 queryplan { |
| 110 SELECT * FROM t1 WHERE rowid=85 AND x=6 AND y=7396 ORDER BY random(); | 120 SELECT * FROM t1 WHERE rowid=85 AND x=6 AND y=7396 ORDER BY random(); |
| 111 } | 121 } |
| 112 } {85 6 7396 7402 nosort t1 *} | 122 } {85 6 7396 7402 nosort t1 *} |
| 113 | 123 |
| 124 # Ticket [65bdeb9739605cc22966f49208452996ff29a640] 2014-02-26 |
| 125 # Make sure "ORDER BY random" does not gets optimized out. |
| 126 # |
| 127 do_test where2-2.4 { |
| 128 db eval { |
| 129 CREATE TABLE x1(a INTEGER PRIMARY KEY, b DEFAULT 1); |
| 130 WITH RECURSIVE |
| 131 cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<50) |
| 132 INSERT INTO x1 SELECT x, 1 FROM cnt; |
| 133 CREATE TABLE x2(x INTEGER PRIMARY KEY); |
| 134 INSERT INTO x2 VALUES(1); |
| 135 } |
| 136 set sql {SELECT * FROM x1, x2 WHERE x=1 ORDER BY random()} |
| 137 set out1 [db eval $sql] |
| 138 set out2 [db eval $sql] |
| 139 set out3 [db eval $sql] |
| 140 expr {$out1!=$out2 && $out2!=$out3} |
| 141 } {1} |
| 142 do_execsql_test where2-2.5 { |
| 143 -- random() is not optimized out |
| 144 EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random(); |
| 145 } {/ random/} |
| 146 do_execsql_test where2-2.5b { |
| 147 -- random() is not optimized out |
| 148 EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random(); |
| 149 } {/ SorterOpen /} |
| 150 do_execsql_test where2-2.6 { |
| 151 -- other constant functions are optimized out |
| 152 EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5); |
| 153 } {~/ abs/} |
| 154 do_execsql_test where2-2.6b { |
| 155 -- other constant functions are optimized out |
| 156 EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5); |
| 157 } {~/ SorterOpen /} |
| 158 |
| 159 |
| 114 | 160 |
| 115 # Efficient handling of forward and reverse table scans. | 161 # Efficient handling of forward and reverse table scans. |
| 116 # | 162 # |
| 117 do_test where2-3.1 { | 163 do_test where2-3.1 { |
| 118 queryplan { | 164 queryplan { |
| 119 SELECT * FROM t1 ORDER BY rowid LIMIT 2 | 165 SELECT * FROM t1 ORDER BY rowid LIMIT 2 |
| 120 } | 166 } |
| 121 } {1 0 4 4 2 1 9 10 nosort t1 *} | 167 } {1 0 4 4 2 1 9 10 nosort t1 *} |
| 122 do_test where2-3.2 { | 168 do_test where2-3.2 { |
| 123 queryplan { | 169 queryplan { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} | 206 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} |
| 161 do_test where2-4.5 { | 207 do_test where2-4.5 { |
| 162 queryplan { | 208 queryplan { |
| 163 SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006) | 209 SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006) |
| 164 AND y IN (SELECT 10000 UNION SELECT 10201) | 210 AND y IN (SELECT 10000 UNION SELECT 10201) |
| 165 AND x>0 AND x<10 | 211 AND x>0 AND x<10 |
| 166 ORDER BY w | 212 ORDER BY w |
| 167 } | 213 } |
| 168 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} | 214 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} |
| 169 } | 215 } |
| 170 do_test where2-4.6 { | 216 do_test where2-4.6a { |
| 171 queryplan { | 217 queryplan { |
| 172 SELECT * FROM t1 | 218 SELECT * FROM t1 |
| 173 WHERE x IN (1,2,3,4,5,6,7,8) | 219 WHERE x IN (1,2,3,4,5,6,7,8) |
| 174 AND y IN (10000,10001,10002,10003,10004,10005) | 220 AND y IN (10000,10001,10002,10003,10004,10005) |
| 175 ORDER BY 2 | 221 ORDER BY x |
| 222 } |
| 223 } {99 6 10000 10006 nosort t1 i1xy} |
| 224 do_test where2-4.6b { |
| 225 queryplan { |
| 226 SELECT * FROM t1 |
| 227 WHERE x IN (1,2,3,4,5,6,7,8) |
| 228 AND y IN (10000,10001,10002,10003,10004,10005) |
| 229 ORDER BY x DESC |
| 230 } |
| 231 } {99 6 10000 10006 nosort t1 i1xy} |
| 232 do_test where2-4.6c { |
| 233 queryplan { |
| 234 SELECT * FROM t1 |
| 235 WHERE x IN (1,2,3,4,5,6,7,8) |
| 236 AND y IN (10000,10001,10002,10003,10004,10005) |
| 237 ORDER BY x, y |
| 238 } |
| 239 } {99 6 10000 10006 nosort t1 i1xy} |
| 240 do_test where2-4.6d { |
| 241 queryplan { |
| 242 SELECT * FROM t1 |
| 243 WHERE x IN (1,2,3,4,5,6,7,8) |
| 244 AND y IN (10000,10001,10002,10003,10004,10005) |
| 245 ORDER BY x, y DESC |
| 176 } | 246 } |
| 177 } {99 6 10000 10006 sort t1 i1xy} | 247 } {99 6 10000 10006 sort t1 i1xy} |
| 178 | 248 |
| 179 # Duplicate entires on the RHS of an IN operator do not cause duplicate | 249 # Duplicate entires on the RHS of an IN operator do not cause duplicate |
| 180 # output rows. | 250 # output rows. |
| 181 # | 251 # |
| 182 do_test where2-4.6 { | 252 do_test where2-4.6x { |
| 183 queryplan { | 253 queryplan { |
| 184 SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207) | 254 SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207) |
| 185 ORDER BY w | 255 ORDER BY w |
| 186 } | 256 } |
| 187 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} | 257 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} |
| 258 do_test where2-4.6y { |
| 259 queryplan { |
| 260 SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207) |
| 261 ORDER BY w DESC |
| 262 } |
| 263 } {100 6 10201 10207 99 6 10000 10006 sort t1 i1zyx} |
| 188 ifcapable compound { | 264 ifcapable compound { |
| 189 do_test where2-4.7 { | 265 do_test where2-4.7 { |
| 190 queryplan { | 266 queryplan { |
| 191 SELECT * FROM t1 WHERE z IN ( | 267 SELECT * FROM t1 WHERE z IN ( |
| 192 SELECT 10207 UNION ALL SELECT 10006 | 268 SELECT 10207 UNION ALL SELECT 10006 |
| 193 UNION ALL SELECT 10006 UNION ALL SELECT 10207) | 269 UNION ALL SELECT 10006 UNION ALL SELECT 10207) |
| 194 ORDER BY w | 270 ORDER BY w |
| 195 } | 271 } |
| 196 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} | 272 } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} |
| 197 } | 273 } |
| 198 | 274 |
| 199 } ;# ifcapable subquery | 275 } ;# ifcapable subquery |
| 200 | 276 |
| 201 # The use of an IN operator disables the index as a sorter. | 277 # The use of an IN operator disables the index as a sorter. |
| 202 # | 278 # |
| 203 do_test where2-5.1 { | 279 do_test where2-5.1 { |
| 204 queryplan { | 280 queryplan { |
| 205 SELECT * FROM t1 WHERE w=99 ORDER BY w | 281 SELECT * FROM t1 WHERE w=99 ORDER BY w |
| 206 } | 282 } |
| 207 } {99 6 10000 10006 nosort t1 i1w} | 283 } {99 6 10000 10006 nosort t1 i1w} |
| 208 | 284 |
| 209 ifcapable subquery { | 285 ifcapable subquery { |
| 210 do_test where2-5.2 { | 286 do_test where2-5.2a { |
| 211 queryplan { | 287 queryplan { |
| 212 SELECT * FROM t1 WHERE w IN (99) ORDER BY w | 288 SELECT * FROM t1 WHERE w IN (99) ORDER BY w |
| 213 } | 289 } |
| 214 } {99 6 10000 10006 sort t1 i1w} | 290 } {99 6 10000 10006 nosort t1 i1w} |
| 291 do_test where2-5.2b { |
| 292 queryplan { |
| 293 SELECT * FROM t1 WHERE w IN (99) ORDER BY w DESC |
| 294 } |
| 295 } {99 6 10000 10006 nosort t1 i1w} |
| 215 } | 296 } |
| 216 | 297 |
| 217 # Verify that OR clauses get translated into IN operators. | 298 # Verify that OR clauses get translated into IN operators. |
| 218 # | 299 # |
| 219 set ::idx {} | 300 set ::idx {} |
| 220 ifcapable subquery {set ::idx i1w} | 301 ifcapable subquery {set ::idx i1w} |
| 221 do_test where2-6.1.1 { | 302 do_test where2-6.1.1 { |
| 222 queryplan { | 303 queryplan { |
| 223 SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w | 304 SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w |
| 224 } | 305 } |
| 225 } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx] | 306 } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx] |
| 226 do_test where2-6.1.2 { | 307 do_test where2-6.1.2 { |
| 227 queryplan { | 308 queryplan { |
| 228 SELECT * FROM t1 WHERE 99=w OR 100=w ORDER BY +w | 309 SELECT * FROM t1 WHERE 99=w OR 100=w ORDER BY +w |
| 229 } | 310 } |
| 230 } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx] | 311 } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx] |
| 231 do_test where2-6.2 { | 312 do_test where2-6.2 { |
| 232 queryplan { | 313 queryplan { |
| 233 SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w | 314 SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w |
| 234 } | 315 } |
| 235 } [list 6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx] | 316 } [list 6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx] |
| 236 | 317 |
| 237 do_test where2-6.3 { | 318 do_test where2-6.3 { |
| 238 queryplan { | 319 queryplan { |
| 239 SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w | 320 SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w |
| 240 } | 321 } |
| 241 } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}} | 322 } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 *} |
| 242 do_test where2-6.4 { | 323 do_test where2-6.4 { |
| 243 queryplan { | 324 queryplan { |
| 244 SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w | 325 SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w |
| 245 } | 326 } |
| 246 } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}} | 327 } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 *} |
| 247 | 328 |
| 248 set ::idx {} | 329 set ::idx {} |
| 249 ifcapable subquery {set ::idx i1zyx} | 330 ifcapable subquery {set ::idx i1zyx} |
| 250 do_test where2-6.5 { | 331 do_test where2-6.5 { |
| 251 queryplan { | 332 queryplan { |
| 252 SELECT b.* FROM t1 a, t1 b | 333 SELECT b.* FROM t1 a, t1 b |
| 253 WHERE a.w=1 AND (a.y=b.z OR b.z=10) | 334 WHERE a.w=1 AND (a.y=b.z OR b.z=10) |
| 254 ORDER BY +b.w | 335 ORDER BY +b.w |
| 255 } | 336 } |
| 256 } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx] | 337 } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx] |
| 257 do_test where2-6.6 { | 338 do_test where2-6.6 { |
| 258 queryplan { | 339 queryplan { |
| 259 SELECT b.* FROM t1 a, t1 b | 340 SELECT b.* FROM t1 a, t1 b |
| 260 WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10) | 341 WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10) |
| 261 ORDER BY +b.w | 342 ORDER BY +b.w |
| 262 } | 343 } |
| 263 } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx] | 344 } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx] |
| 264 | 345 |
| 346 if {[permutation] != "no_optimization"} { |
| 347 |
| 265 # Ticket #2249. Make sure the OR optimization is not attempted if | 348 # Ticket #2249. Make sure the OR optimization is not attempted if |
| 266 # comparisons between columns of different affinities are needed. | 349 # comparisons between columns of different affinities are needed. |
| 267 # | 350 # |
| 268 do_test where2-6.7 { | 351 do_test where2-6.7 { |
| 269 execsql { | 352 execsql { |
| 270 CREATE TABLE t2249a(a TEXT UNIQUE); | 353 CREATE TABLE t2249a(a TEXT UNIQUE, x CHAR(100)); |
| 271 CREATE TABLE t2249b(b INTEGER); | 354 CREATE TABLE t2249b(b INTEGER); |
| 272 INSERT INTO t2249a VALUES('0123'); | 355 INSERT INTO t2249a(a) VALUES('0123'); |
| 273 INSERT INTO t2249b VALUES(123); | 356 INSERT INTO t2249b VALUES(123); |
| 274 } | 357 } |
| 275 queryplan { | 358 queryplan { |
| 276 -- Because a is type TEXT and b is type INTEGER, both a and b | 359 -- Because a is type TEXT and b is type INTEGER, both a and b |
| 277 -- will attempt to convert to NUMERIC before the comparison. | 360 -- will attempt to convert to NUMERIC before the comparison. |
| 278 -- They will thus compare equal. | 361 -- They will thus compare equal. |
| 279 -- | 362 -- |
| 280 SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b; | 363 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b; |
| 281 } | 364 } |
| 282 } {123 0123 nosort t2249b {} t2249a {}} | 365 } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 283 do_test where2-6.9 { | 366 do_test where2-6.9 { |
| 284 queryplan { | 367 queryplan { |
| 285 -- The + operator removes affinity from the rhs. No conversions | 368 -- The + operator removes affinity from the rhs. No conversions |
| 286 -- occur and the comparison is false. The result is an empty set. | 369 -- occur and the comparison is false. The result is an empty set. |
| 287 -- | 370 -- |
| 288 SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b; | 371 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b; |
| 289 } | 372 } |
| 290 } {nosort t2249b {} {} sqlite_autoindex_t2249a_1} | 373 } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 291 do_test where2-6.9.2 { | 374 do_test where2-6.9.2 { |
| 292 # The same thing but with the expression flipped around. | 375 # The same thing but with the expression flipped around. |
| 293 queryplan { | 376 queryplan { |
| 294 SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a | 377 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a |
| 295 } | 378 } |
| 296 } {nosort t2249b {} {} sqlite_autoindex_t2249a_1} | 379 } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 297 do_test where2-6.10 { | 380 do_test where2-6.10 { |
| 298 queryplan { | 381 queryplan { |
| 299 -- Use + on both sides of the comparison to disable indices | 382 -- Use + on both sides of the comparison to disable indices |
| 300 -- completely. Make sure we get the same result. | 383 -- completely. Make sure we get the same result. |
| 301 -- | 384 -- |
| 302 SELECT * FROM t2249b CROSS JOIN t2249a WHERE +a=+b; | 385 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +a=+b; |
| 303 } | 386 } |
| 304 } {nosort t2249b {} t2249a {}} | 387 } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 305 do_test where2-6.11 { | 388 do_test where2-6.11 { |
| 306 # This will not attempt the OR optimization because of the a=b | 389 # This will not attempt the OR optimization because of the a=b |
| 307 # comparison. | 390 # comparison. |
| 308 queryplan { | 391 queryplan { |
| 309 SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello'; | 392 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello'; |
| 310 } | 393 } |
| 311 } {123 0123 nosort t2249b {} t2249a {}} | 394 } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 312 do_test where2-6.11.2 { | 395 do_test where2-6.11.2 { |
| 313 # Permutations of the expression terms. | 396 # Permutations of the expression terms. |
| 314 queryplan { | 397 queryplan { |
| 315 SELECT * FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello'; | 398 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello'; |
| 316 } | 399 } |
| 317 } {123 0123 nosort t2249b {} t2249a {}} | 400 } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 318 do_test where2-6.11.3 { | 401 do_test where2-6.11.3 { |
| 319 # Permutations of the expression terms. | 402 # Permutations of the expression terms. |
| 320 queryplan { | 403 queryplan { |
| 321 SELECT * FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a; | 404 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a; |
| 322 } | 405 } |
| 323 } {123 0123 nosort t2249b {} t2249a {}} | 406 } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 324 do_test where2-6.11.4 { | 407 do_test where2-6.11.4 { |
| 325 # Permutations of the expression terms. | 408 # Permutations of the expression terms. |
| 326 queryplan { | 409 queryplan { |
| 327 SELECT * FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a; | 410 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a; |
| 328 } | 411 } |
| 329 } {123 0123 nosort t2249b {} t2249a {}} | 412 } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 330 ifcapable explain&&subquery { | 413 ifcapable explain&&subquery { |
| 331 # These tests are not run if subquery support is not included in the | 414 # These tests are not run if subquery support is not included in the |
| 332 # build. This is because these tests test the "a = 1 OR a = 2" to | 415 # build. This is because these tests test the "a = 1 OR a = 2" to |
| 333 # "a IN (1, 2)" optimisation transformation, which is not enabled if | 416 # "a IN (1, 2)" optimisation transformation, which is not enabled if |
| 334 # subqueries and the IN operator is not available. | 417 # subqueries and the IN operator is not available. |
| 335 # | 418 # |
| 336 do_test where2-6.12 { | 419 do_test where2-6.12 { |
| 337 # In this case, the +b disables the affinity conflict and allows | 420 # In this case, the +b disables the affinity conflict and allows |
| 338 # the OR optimization to be used again. The result is now an empty | 421 # the OR optimization to be used again. The result is now an empty |
| 339 # set, the same as in where2-6.9. | 422 # set, the same as in where2-6.9. |
| 340 queryplan { | 423 queryplan { |
| 341 SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello'; | 424 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello'; |
| 342 } | 425 } |
| 343 } {nosort t2249b {} {} sqlite_autoindex_t2249a_1} | 426 } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 344 do_test where2-6.12.2 { | 427 do_test where2-6.12.2 { |
| 345 # In this case, the +b disables the affinity conflict and allows | 428 # In this case, the +b disables the affinity conflict and allows |
| 346 # the OR optimization to be used again. The result is now an empty | 429 # the OR optimization to be used again. The result is now an empty |
| 347 # set, the same as in where2-6.9. | 430 # set, the same as in where2-6.9. |
| 348 queryplan { | 431 queryplan { |
| 349 SELECT * FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a; | 432 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a; |
| 350 } | 433 } |
| 351 } {nosort t2249b {} {} sqlite_autoindex_t2249a_1} | 434 } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 352 do_test where2-6.12.3 { | 435 do_test where2-6.12.3 { |
| 353 # In this case, the +b disables the affinity conflict and allows | 436 # In this case, the +b disables the affinity conflict and allows |
| 354 # the OR optimization to be used again. The result is now an empty | 437 # the OR optimization to be used again. The result is now an empty |
| 355 # set, the same as in where2-6.9. | 438 # set, the same as in where2-6.9. |
| 356 queryplan { | 439 queryplan { |
| 357 SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello'; | 440 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello'; |
| 358 } | 441 } |
| 359 } {nosort t2249b {} {} sqlite_autoindex_t2249a_1} | 442 } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 360 do_test where2-6.13 { | 443 do_test where2-6.13 { |
| 361 # The addition of +a on the second term disabled the OR optimization. | 444 # The addition of +a on the second term disabled the OR optimization. |
| 362 # But we should still get the same empty-set result as in where2-6.9. | 445 # But we should still get the same empty-set result as in where2-6.9. |
| 363 queryplan { | 446 queryplan { |
| 364 SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello'; | 447 SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello'; |
| 365 } | 448 } |
| 366 } {nosort t2249b {} t2249a {}} | 449 } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1} |
| 367 } | 450 } |
| 368 | 451 |
| 369 # Variations on the order of terms in a WHERE clause in order | 452 # Variations on the order of terms in a WHERE clause in order |
| 370 # to make sure the OR optimizer can recognize them all. | 453 # to make sure the OR optimizer can recognize them all. |
| 371 do_test where2-6.20 { | 454 do_test where2-6.20 { |
| 372 queryplan { | 455 queryplan { |
| 373 SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a | 456 SELECT x.a, y.a FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a |
| 374 } | 457 } |
| 375 } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1} | 458 } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1} |
| 376 ifcapable explain&&subquery { | 459 ifcapable explain&&subquery { |
| 377 # These tests are not run if subquery support is not included in the | 460 # These tests are not run if subquery support is not included in the |
| 378 # build. This is because these tests test the "a = 1 OR a = 2" to | 461 # build. This is because these tests test the "a = 1 OR a = 2" to |
| 379 # "a IN (1, 2)" optimisation transformation, which is not enabled if | 462 # "a IN (1, 2)" optimisation transformation, which is not enabled if |
| 380 # subqueries and the IN operator is not available. | 463 # subqueries and the IN operator is not available. |
| 381 # | 464 # |
| 382 do_test where2-6.21 { | 465 do_test where2-6.21 { |
| 383 queryplan { | 466 queryplan { |
| 384 SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a OR y.a='hello' | 467 SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y |
| 468 WHERE x.a=y.a OR y.a='hello' |
| 385 } | 469 } |
| 386 } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1} | 470 } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1} |
| 387 do_test where2-6.22 { | 471 do_test where2-6.22 { |
| 388 queryplan { | 472 queryplan { |
| 389 SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE y.a=x.a OR y.a='hello' | 473 SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y |
| 474 WHERE y.a=x.a OR y.a='hello' |
| 390 } | 475 } |
| 391 } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1} | 476 } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1} |
| 392 do_test where2-6.23 { | 477 do_test where2-6.23 { |
| 393 queryplan { | 478 queryplan { |
| 394 SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE y.a='hello' OR x.a=y.a | 479 SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y |
| 480 WHERE y.a='hello' OR x.a=y.a |
| 395 } | 481 } |
| 396 } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1} | 482 } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1} |
| 397 } | 483 } |
| 398 | 484 |
| 399 # Unique queries (queries that are guaranteed to return only a single | 485 # Unique queries (queries that are guaranteed to return only a single |
| 400 # row of result) do not call the sorter. But all tables must give | 486 # row of result) do not call the sorter. But all tables must give |
| 401 # a unique result. If any one table in the join does not give a unique | 487 # a unique result. If any one table in the join does not give a unique |
| 402 # result then sorting is necessary. | 488 # result then sorting is necessary. |
| 403 # | 489 # |
| 404 do_test where2-7.1 { | 490 do_test where2-7.1 { |
| 405 cksort { | 491 cksort { |
| 406 create table t8(a unique, b, c); | 492 create table t8(a unique, b, c); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 422 select * from t8, t9 where a=1 and y=3 order by b, x | 508 select * from t8, t9 where a=1 and y=3 order by b, x |
| 423 } | 509 } |
| 424 } {1 2 3 2 3 sort} | 510 } {1 2 3 2 3 sort} |
| 425 do_test where2-7.4 { | 511 do_test where2-7.4 { |
| 426 cksort { | 512 cksort { |
| 427 create unique index i9y on t9(y); | 513 create unique index i9y on t9(y); |
| 428 select * from t8, t9 where a=1 and y=3 order by b, x | 514 select * from t8, t9 where a=1 and y=3 order by b, x |
| 429 } | 515 } |
| 430 } {1 2 3 2 3 nosort} | 516 } {1 2 3 2 3 nosort} |
| 431 | 517 |
| 518 } ;# if {[permutation] != "no_optimization"} |
| 519 |
| 432 # Ticket #1807. Using IN constrains on multiple columns of | 520 # Ticket #1807. Using IN constrains on multiple columns of |
| 433 # a multi-column index. | 521 # a multi-column index. |
| 434 # | 522 # |
| 435 ifcapable subquery { | 523 ifcapable subquery { |
| 436 do_test where2-8.1 { | 524 do_test where2-8.1 { |
| 437 execsql { | 525 execsql { |
| 438 SELECT * FROM t1 WHERE x IN (20,21) AND y IN (1,2) | 526 SELECT * FROM t1 WHERE x IN (20,21) AND y IN (1,2) |
| 439 } | 527 } |
| 440 } {} | 528 } {} |
| 441 do_test where2-8.2 { | 529 do_test where2-8.2 { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 execsql { | 731 execsql { |
| 644 SELECT d FROM t11 WHERE c IN (1,2,3,4,5); | 732 SELECT d FROM t11 WHERE c IN (1,2,3,4,5); |
| 645 } | 733 } |
| 646 } {4} | 734 } {4} |
| 647 do_test where2-11.4 { | 735 do_test where2-11.4 { |
| 648 execsql { | 736 execsql { |
| 649 SELECT d FROM t11 WHERE c=7 OR (a=1 AND b=2) ORDER BY d; | 737 SELECT d FROM t11 WHERE c=7 OR (a=1 AND b=2) ORDER BY d; |
| 650 } | 738 } |
| 651 } {4 8 10} | 739 } {4 8 10} |
| 652 | 740 |
| 741 # Verify that the OR clause is used in an outer loop even when |
| 742 # the OR clause scores slightly better on an inner loop. |
| 743 if {[permutation] != "no_optimization"} { |
| 744 do_execsql_test where2-12.1 { |
| 745 CREATE TABLE t12(x INTEGER PRIMARY KEY, y INT, z CHAR(100)); |
| 746 CREATE INDEX t12y ON t12(y); |
| 747 EXPLAIN QUERY PLAN |
| 748 SELECT a.x, b.x |
| 749 FROM t12 AS a JOIN t12 AS b ON a.y=b.x |
| 750 WHERE (b.x=$abc OR b.y=$abc); |
| 751 } {/.*SEARCH TABLE t12 AS b .*SEARCH TABLE t12 AS b .*/} |
| 752 } |
| 753 |
| 754 # Verify that all necessary OP_OpenRead opcodes occur in the OR optimization. |
| 755 # |
| 756 do_execsql_test where2-13.1 { |
| 757 CREATE TABLE t13(a,b); |
| 758 CREATE INDEX t13a ON t13(a); |
| 759 INSERT INTO t13 VALUES(4,5); |
| 760 SELECT * FROM t13 WHERE (1=2 AND a=3) OR a=4; |
| 761 } {4 5} |
| 653 | 762 |
| 654 finish_test | 763 finish_test |
| OLD | NEW |