📄 where2.test
字号:
# 2005 July 28## The author disclaims copyright to this source code. In place of# a legal notice, here is a blessing:## May you do good and not evil.# May you find forgiveness for yourself and forgive others.# May you share freely, never taking more than you give.##***********************************************************************# This file implements regression tests for SQLite library. The# focus of this file is testing the use of indices in WHERE clauses# based on recent changes to the optimizer.## $Id: where2.test,v 1.11 2007/02/23 23:13:34 drh Exp $set testdir [file dirname $argv0]source $testdir/tester.tcl# Build some test data#do_test where2-1.0 { execsql { BEGIN; CREATE TABLE t1(w int, x int, y int, z int); } for {set i 1} {$i<=100} {incr i} { set w $i set x [expr {int(log($i)/log(2))}] set y [expr {$i*$i + 2*$i + 1}] set z [expr {$x+$y}] ifcapable tclvar { execsql {INSERT INTO t1 VALUES($::w,$::x,$::y,$::z)} } else { execsql {INSERT INTO t1 VALUES(:w,:x,:y,:z)} } } execsql { CREATE UNIQUE INDEX i1w ON t1(w); CREATE INDEX i1xy ON t1(x,y); CREATE INDEX i1zyx ON t1(z,y,x); COMMIT; }} {}# Do an SQL statement. Append the search count to the end of the result.#proc count sql { set ::sqlite_search_count 0 return [concat [execsql $sql] $::sqlite_search_count]}# This procedure executes the SQL. Then it checks to see if the OP_Sort# opcode was executed. If an OP_Sort did occur, then "sort" is appended# to the result. If no OP_Sort happened, then "nosort" is appended.## This procedure is used to check to make sure sorting is or is not# occurring as expected.#proc cksort {sql} { set ::sqlite_sort_count 0 set data [execsql $sql] if {$::sqlite_sort_count} {set x sort} {set x nosort} lappend data $x return $data}# This procedure executes the SQL. Then it appends to the result the# "sort" or "nosort" keyword (as in the cksort procedure above) then# it appends the ::sqlite_query_plan variable.#proc queryplan {sql} { set ::sqlite_sort_count 0 set data [execsql $sql] if {$::sqlite_sort_count} {set x sort} {set x nosort} lappend data $x return [concat $data $::sqlite_query_plan]}# Prefer a UNIQUE index over another index.#do_test where2-1.1 { queryplan { SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 }} {85 6 7396 7402 nosort t1 i1w}# Always prefer a rowid== constraint over any other index.#do_test where2-1.3 { queryplan { SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 AND rowid=85 }} {85 6 7396 7402 nosort t1 *}# When constrained by a UNIQUE index, the ORDER BY clause is always ignored.#do_test where2-2.1 { queryplan { SELECT * FROM t1 WHERE w=85 ORDER BY random(5); }} {85 6 7396 7402 nosort t1 i1w}do_test where2-2.2 { queryplan { SELECT * FROM t1 WHERE x=6 AND y=7396 ORDER BY random(5); }} {85 6 7396 7402 sort t1 i1xy}do_test where2-2.3 { queryplan { SELECT * FROM t1 WHERE rowid=85 AND x=6 AND y=7396 ORDER BY random(5); }} {85 6 7396 7402 nosort t1 *}# Efficient handling of forward and reverse table scans.#do_test where2-3.1 { queryplan { SELECT * FROM t1 ORDER BY rowid LIMIT 2 }} {1 0 4 4 2 1 9 10 nosort t1 *}do_test where2-3.2 { queryplan { SELECT * FROM t1 ORDER BY rowid DESC LIMIT 2 }} {100 6 10201 10207 99 6 10000 10006 nosort t1 *}# The IN operator can be used by indices at multiple layers#ifcapable subquery { do_test where2-4.1 { queryplan { SELECT * FROM t1 WHERE z IN (10207,10006) AND y IN (10000,10201) AND x>0 AND x<10 ORDER BY w } } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} do_test where2-4.2 { queryplan { SELECT * FROM t1 WHERE z IN (10207,10006) AND y=10000 AND x>0 AND x<10 ORDER BY w } } {99 6 10000 10006 sort t1 i1zyx} do_test where2-4.3 { queryplan { SELECT * FROM t1 WHERE z=10006 AND y IN (10000,10201) AND x>0 AND x<10 ORDER BY w } } {99 6 10000 10006 sort t1 i1zyx} ifcapable compound { do_test where2-4.4 { queryplan { SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006) AND y IN (10000,10201) AND x>0 AND x<10 ORDER BY w } } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} do_test where2-4.5 { queryplan { SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006) AND y IN (SELECT 10000 UNION SELECT 10201) AND x>0 AND x<10 ORDER BY w } } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} } do_test where2-4.6 { queryplan { SELECT * FROM t1 WHERE x IN (1,2,3,4,5,6,7,8) AND y IN (10000,10001,10002,10003,10004,10005) ORDER BY 2 } } {99 6 10000 10006 sort t1 i1xy} # Duplicate entires on the RHS of an IN operator do not cause duplicate # output rows. # do_test where2-4.6 { queryplan { SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207) ORDER BY w } } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} ifcapable compound { do_test where2-4.7 { queryplan { SELECT * FROM t1 WHERE z IN ( SELECT 10207 UNION ALL SELECT 10006 UNION ALL SELECT 10006 UNION ALL SELECT 10207) ORDER BY w } } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx} }} ;# ifcapable subquery# The use of an IN operator disables the index as a sorter.#do_test where2-5.1 { queryplan { SELECT * FROM t1 WHERE w=99 ORDER BY w }} {99 6 10000 10006 nosort t1 i1w}ifcapable subquery { do_test where2-5.2 { queryplan { SELECT * FROM t1 WHERE w IN (99) ORDER BY w } } {99 6 10000 10006 sort t1 i1w}}# Verify that OR clauses get translated into IN operators.#set ::idx {}ifcapable subquery {set ::idx i1w}do_test where2-6.1.1 { queryplan { SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w }} [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]do_test where2-6.1.2 { queryplan { SELECT * FROM t1 WHERE 99=w OR 100=w ORDER BY +w }} [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]do_test where2-6.2 { queryplan { SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w }} [list 6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]do_test where2-6.3 { queryplan { SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w }} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}do_test where2-6.4 { queryplan { SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w }} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}set ::idx {}ifcapable subquery {set ::idx i1zyx}do_test where2-6.5 { queryplan { SELECT b.* FROM t1 a, t1 b WHERE a.w=1 AND (a.y=b.z OR b.z=10) ORDER BY +b.w }} [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]do_test where2-6.6 { queryplan { SELECT b.* FROM t1 a, t1 b WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10) ORDER BY +b.w }} [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]# Ticket #2249. Make sure the OR optimization is not attempted if# comparisons between columns of different affinities are needed.#do_test where2-6.7 { execsql { CREATE TABLE t2249a(a TEXT UNIQUE); CREATE TABLE t2249b(b INTEGER); INSERT INTO t2249a VALUES('0123'); INSERT INTO t2249b VALUES(123); } queryplan { -- Because a is type TEXT and b is type INTEGER, both a and b -- will attempt to convert to NUMERIC before the comparison. -- They will thus compare equal. -- SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b; }} {123 0123 nosort t2249b {} t2249a {}}do_test where2-6.9 { queryplan { -- The + operator removes affinity from the rhs. No conversions -- occur and the comparison is false. The result is an empty set. -- SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b; }} {nosort t2249b {} {} sqlite_autoindex_t2249a_1}do_test where2-6.9.2 { # The same thing but with the expression flipped around. queryplan { SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a }} {nosort t2249b {} {} sqlite_autoindex_t2249a_1}do_test where2-6.10 { queryplan { -- Use + on both sides of the comparison to disable indices -- completely. Make sure we get the same result. -- SELECT * FROM t2249b CROSS JOIN t2249a WHERE +a=+b; }} {nosort t2249b {} t2249a {}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -