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 |