xref: /sqlite-3.40.0/test/where2.test (revision ff890793)
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