sl@0
|
1 |
# 2008 June 24
|
sl@0
|
2 |
#
|
sl@0
|
3 |
# The author disclaims copyright to this source code. In place of
|
sl@0
|
4 |
# a legal notice, here is a blessing:
|
sl@0
|
5 |
#
|
sl@0
|
6 |
# May you do good and not evil.
|
sl@0
|
7 |
# May you find forgiveness for yourself and forgive others.
|
sl@0
|
8 |
# May you share freely, never taking more than you give.
|
sl@0
|
9 |
#
|
sl@0
|
10 |
#***********************************************************************
|
sl@0
|
11 |
# This file implements regression tests for SQLite library.
|
sl@0
|
12 |
#
|
sl@0
|
13 |
# $Id: select9.test,v 1.4 2008/07/01 14:39:35 danielk1977 Exp $
|
sl@0
|
14 |
|
sl@0
|
15 |
# The tests in this file are focused on test compound SELECT statements
|
sl@0
|
16 |
# that have any or all of an ORDER BY, LIMIT or OFFSET clauses. As of
|
sl@0
|
17 |
# version 3.6.0, SQLite contains code to use SQL indexes where possible
|
sl@0
|
18 |
# to optimize such statements.
|
sl@0
|
19 |
#
|
sl@0
|
20 |
|
sl@0
|
21 |
# TODO Points:
|
sl@0
|
22 |
#
|
sl@0
|
23 |
# * Are there any "column affinity" issues to consider?
|
sl@0
|
24 |
|
sl@0
|
25 |
set testdir [file dirname $argv0]
|
sl@0
|
26 |
source $testdir/tester.tcl
|
sl@0
|
27 |
|
sl@0
|
28 |
#set ISQUICK 1
|
sl@0
|
29 |
|
sl@0
|
30 |
#-------------------------------------------------------------------------
|
sl@0
|
31 |
# test_compound_select TESTNAME SELECT RESULT
|
sl@0
|
32 |
#
|
sl@0
|
33 |
# This command is used to run multiple LIMIT/OFFSET test cases based on
|
sl@0
|
34 |
# the single SELECT statement passed as the second argument. The SELECT
|
sl@0
|
35 |
# statement may not contain a LIMIT or OFFSET clause. This proc tests
|
sl@0
|
36 |
# many statements of the form:
|
sl@0
|
37 |
#
|
sl@0
|
38 |
# "$SELECT limit $X offset $Y"
|
sl@0
|
39 |
#
|
sl@0
|
40 |
# for various values of $X and $Y.
|
sl@0
|
41 |
#
|
sl@0
|
42 |
# The third argument, $RESULT, should contain the expected result of
|
sl@0
|
43 |
# the command [execsql $SELECT].
|
sl@0
|
44 |
#
|
sl@0
|
45 |
# The first argument, $TESTNAME, is used as the base test case name to
|
sl@0
|
46 |
# pass to [do_test] for each individual LIMIT OFFSET test case.
|
sl@0
|
47 |
#
|
sl@0
|
48 |
proc test_compound_select {testname sql result} {
|
sl@0
|
49 |
|
sl@0
|
50 |
set nCol 1
|
sl@0
|
51 |
db eval $sql A {
|
sl@0
|
52 |
set nCol [llength $A(*)]
|
sl@0
|
53 |
break
|
sl@0
|
54 |
}
|
sl@0
|
55 |
set nRow [expr {[llength $result] / $nCol}]
|
sl@0
|
56 |
|
sl@0
|
57 |
set ::compound_sql $sql
|
sl@0
|
58 |
do_test $testname {
|
sl@0
|
59 |
execsql $::compound_sql
|
sl@0
|
60 |
} $result
|
sl@0
|
61 |
#return
|
sl@0
|
62 |
|
sl@0
|
63 |
set iLimitIncr 1
|
sl@0
|
64 |
set iOffsetIncr 1
|
sl@0
|
65 |
if {[info exists ::ISQUICK] && $::ISQUICK && $nRow>=5} {
|
sl@0
|
66 |
set iOffsetIncr [expr $nRow / 5]
|
sl@0
|
67 |
set iLimitIncr [expr $nRow / 5]
|
sl@0
|
68 |
}
|
sl@0
|
69 |
|
sl@0
|
70 |
set iLimitEnd [expr $nRow+$iLimitIncr]
|
sl@0
|
71 |
set iOffsetEnd [expr $nRow+$iOffsetIncr]
|
sl@0
|
72 |
|
sl@0
|
73 |
for {set iOffset 0} {$iOffset < $iOffsetEnd} {incr iOffset $iOffsetIncr} {
|
sl@0
|
74 |
for {set iLimit 0} {$iLimit < $iLimitEnd} {incr iLimit} {
|
sl@0
|
75 |
|
sl@0
|
76 |
set ::compound_sql "$sql LIMIT $iLimit"
|
sl@0
|
77 |
if {$iOffset != 0} {
|
sl@0
|
78 |
append ::compound_sql " OFFSET $iOffset"
|
sl@0
|
79 |
}
|
sl@0
|
80 |
|
sl@0
|
81 |
set iStart [expr {$iOffset*$nCol}]
|
sl@0
|
82 |
set iEnd [expr {($iOffset*$nCol) + ($iLimit*$nCol) -1}]
|
sl@0
|
83 |
|
sl@0
|
84 |
do_test $testname.limit=$iLimit.offset=$iOffset {
|
sl@0
|
85 |
execsql $::compound_sql
|
sl@0
|
86 |
} [lrange $result $iStart $iEnd]
|
sl@0
|
87 |
}
|
sl@0
|
88 |
}
|
sl@0
|
89 |
}
|
sl@0
|
90 |
|
sl@0
|
91 |
#-------------------------------------------------------------------------
|
sl@0
|
92 |
# test_compound_select_flippable TESTNAME SELECT RESULT
|
sl@0
|
93 |
#
|
sl@0
|
94 |
# This command is for testing statements of the form:
|
sl@0
|
95 |
#
|
sl@0
|
96 |
# <simple select 1> <compound op> <simple select 2> ORDER BY <order by>
|
sl@0
|
97 |
#
|
sl@0
|
98 |
# where each <simple select> is a simple (non-compound) select statement
|
sl@0
|
99 |
# and <compound op> is one of "INTERSECT", "UNION ALL" or "UNION".
|
sl@0
|
100 |
#
|
sl@0
|
101 |
# This proc calls [test_compound_select] twice, once with the select
|
sl@0
|
102 |
# statement as it is passed to this command, and once with the positions
|
sl@0
|
103 |
# of <select statement 1> and <select statement 2> exchanged.
|
sl@0
|
104 |
#
|
sl@0
|
105 |
proc test_compound_select_flippable {testname sql result} {
|
sl@0
|
106 |
test_compound_select $testname $sql $result
|
sl@0
|
107 |
|
sl@0
|
108 |
set select [string trim $sql]
|
sl@0
|
109 |
set RE {(.*)(UNION ALL|INTERSECT|UNION)(.*)(ORDER BY.*)}
|
sl@0
|
110 |
set rc [regexp $RE $select -> s1 op s2 order_by]
|
sl@0
|
111 |
if {!$rc} {error "Statement is unflippable: $select"}
|
sl@0
|
112 |
|
sl@0
|
113 |
set flipsql "$s2 $op $s1 $order_by"
|
sl@0
|
114 |
test_compound_select $testname.flipped $flipsql $result
|
sl@0
|
115 |
}
|
sl@0
|
116 |
|
sl@0
|
117 |
#############################################################################
|
sl@0
|
118 |
# Begin tests.
|
sl@0
|
119 |
#
|
sl@0
|
120 |
|
sl@0
|
121 |
# Create and populate a sample database.
|
sl@0
|
122 |
#
|
sl@0
|
123 |
do_test select9-1.0 {
|
sl@0
|
124 |
execsql {
|
sl@0
|
125 |
CREATE TABLE t1(a, b, c);
|
sl@0
|
126 |
CREATE TABLE t2(d, e, f);
|
sl@0
|
127 |
BEGIN;
|
sl@0
|
128 |
INSERT INTO t1 VALUES(1, 'one', 'I');
|
sl@0
|
129 |
INSERT INTO t1 VALUES(3, NULL, NULL);
|
sl@0
|
130 |
INSERT INTO t1 VALUES(5, 'five', 'V');
|
sl@0
|
131 |
INSERT INTO t1 VALUES(7, 'seven', 'VII');
|
sl@0
|
132 |
INSERT INTO t1 VALUES(9, NULL, NULL);
|
sl@0
|
133 |
INSERT INTO t1 VALUES(2, 'two', 'II');
|
sl@0
|
134 |
INSERT INTO t1 VALUES(4, 'four', 'IV');
|
sl@0
|
135 |
INSERT INTO t1 VALUES(6, NULL, NULL);
|
sl@0
|
136 |
INSERT INTO t1 VALUES(8, 'eight', 'VIII');
|
sl@0
|
137 |
INSERT INTO t1 VALUES(10, 'ten', 'X');
|
sl@0
|
138 |
|
sl@0
|
139 |
INSERT INTO t2 VALUES(1, 'two', 'IV');
|
sl@0
|
140 |
INSERT INTO t2 VALUES(2, 'four', 'VIII');
|
sl@0
|
141 |
INSERT INTO t2 VALUES(3, NULL, NULL);
|
sl@0
|
142 |
INSERT INTO t2 VALUES(4, 'eight', 'XVI');
|
sl@0
|
143 |
INSERT INTO t2 VALUES(5, 'ten', 'XX');
|
sl@0
|
144 |
INSERT INTO t2 VALUES(6, NULL, NULL);
|
sl@0
|
145 |
INSERT INTO t2 VALUES(7, 'fourteen', 'XXVIII');
|
sl@0
|
146 |
INSERT INTO t2 VALUES(8, 'sixteen', 'XXXII');
|
sl@0
|
147 |
INSERT INTO t2 VALUES(9, NULL, NULL);
|
sl@0
|
148 |
INSERT INTO t2 VALUES(10, 'twenty', 'XL');
|
sl@0
|
149 |
|
sl@0
|
150 |
COMMIT;
|
sl@0
|
151 |
}
|
sl@0
|
152 |
} {}
|
sl@0
|
153 |
|
sl@0
|
154 |
# Each iteration of this loop runs the same tests with a different set
|
sl@0
|
155 |
# of indexes present within the database schema. The data returned by
|
sl@0
|
156 |
# the compound SELECT statements in the test cases should be the same
|
sl@0
|
157 |
# in each case.
|
sl@0
|
158 |
#
|
sl@0
|
159 |
set iOuterLoop 1
|
sl@0
|
160 |
foreach indexes [list {
|
sl@0
|
161 |
/* Do not create any indexes. */
|
sl@0
|
162 |
} {
|
sl@0
|
163 |
CREATE INDEX i1 ON t1(a)
|
sl@0
|
164 |
} {
|
sl@0
|
165 |
CREATE INDEX i2 ON t1(b)
|
sl@0
|
166 |
} {
|
sl@0
|
167 |
CREATE INDEX i3 ON t2(d)
|
sl@0
|
168 |
} {
|
sl@0
|
169 |
CREATE INDEX i4 ON t2(e)
|
sl@0
|
170 |
}] {
|
sl@0
|
171 |
|
sl@0
|
172 |
do_test select9-1.$iOuterLoop.1 {
|
sl@0
|
173 |
execsql $indexes
|
sl@0
|
174 |
} {}
|
sl@0
|
175 |
|
sl@0
|
176 |
# Test some 2-way UNION ALL queries. No WHERE clauses.
|
sl@0
|
177 |
#
|
sl@0
|
178 |
test_compound_select select9-1.$iOuterLoop.2 {
|
sl@0
|
179 |
SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2
|
sl@0
|
180 |
} {1 one 3 {} 5 five 7 seven 9 {} 2 two 4 four 6 {} 8 eight 10 ten 1 two 2 four 3 {} 4 eight 5 ten 6 {} 7 fourteen 8 sixteen 9 {} 10 twenty}
|
sl@0
|
181 |
test_compound_select select9-1.$iOuterLoop.3 {
|
sl@0
|
182 |
SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY 1
|
sl@0
|
183 |
} {1 one 1 two 2 two 2 four 3 {} 3 {} 4 four 4 eight 5 five 5 ten 6 {} 6 {} 7 seven 7 fourteen 8 eight 8 sixteen 9 {} 9 {} 10 ten 10 twenty}
|
sl@0
|
184 |
test_compound_select select9-1.$iOuterLoop.4 {
|
sl@0
|
185 |
SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY 2
|
sl@0
|
186 |
} {3 {} 9 {} 6 {} 3 {} 6 {} 9 {} 8 eight 4 eight 5 five 4 four 2 four 7 fourteen 1 one 7 seven 8 sixteen 10 ten 5 ten 10 twenty 2 two 1 two}
|
sl@0
|
187 |
test_compound_select_flippable select9-1.$iOuterLoop.5 {
|
sl@0
|
188 |
SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY 1, 2
|
sl@0
|
189 |
} {1 one 1 two 2 four 2 two 3 {} 3 {} 4 eight 4 four 5 five 5 ten 6 {} 6 {} 7 fourteen 7 seven 8 eight 8 sixteen 9 {} 9 {} 10 ten 10 twenty}
|
sl@0
|
190 |
test_compound_select_flippable select9-1.$iOuterLoop.6 {
|
sl@0
|
191 |
SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY 2, 1
|
sl@0
|
192 |
} {3 {} 3 {} 6 {} 6 {} 9 {} 9 {} 4 eight 8 eight 5 five 2 four 4 four 7 fourteen 1 one 7 seven 8 sixteen 5 ten 10 ten 10 twenty 1 two 2 two}
|
sl@0
|
193 |
|
sl@0
|
194 |
# Test some 2-way UNION queries.
|
sl@0
|
195 |
#
|
sl@0
|
196 |
test_compound_select select9-1.$iOuterLoop.7 {
|
sl@0
|
197 |
SELECT a, b FROM t1 UNION SELECT d, e FROM t2
|
sl@0
|
198 |
} {1 one 1 two 2 four 2 two 3 {} 4 eight 4 four 5 five 5 ten 6 {} 7 fourteen 7 seven 8 eight 8 sixteen 9 {} 10 ten 10 twenty}
|
sl@0
|
199 |
|
sl@0
|
200 |
test_compound_select select9-1.$iOuterLoop.8 {
|
sl@0
|
201 |
SELECT a, b FROM t1 UNION SELECT d, e FROM t2 ORDER BY 1
|
sl@0
|
202 |
} {1 one 1 two 2 four 2 two 3 {} 4 eight 4 four 5 five 5 ten 6 {} 7 fourteen 7 seven 8 eight 8 sixteen 9 {} 10 ten 10 twenty}
|
sl@0
|
203 |
|
sl@0
|
204 |
test_compound_select select9-1.$iOuterLoop.9 {
|
sl@0
|
205 |
SELECT a, b FROM t1 UNION SELECT d, e FROM t2 ORDER BY 2
|
sl@0
|
206 |
} {3 {} 6 {} 9 {} 4 eight 8 eight 5 five 2 four 4 four 7 fourteen 1 one 7 seven 8 sixteen 5 ten 10 ten 10 twenty 1 two 2 two}
|
sl@0
|
207 |
|
sl@0
|
208 |
test_compound_select_flippable select9-1.$iOuterLoop.10 {
|
sl@0
|
209 |
SELECT a, b FROM t1 UNION SELECT d, e FROM t2 ORDER BY 1, 2
|
sl@0
|
210 |
} {1 one 1 two 2 four 2 two 3 {} 4 eight 4 four 5 five 5 ten 6 {} 7 fourteen 7 seven 8 eight 8 sixteen 9 {} 10 ten 10 twenty}
|
sl@0
|
211 |
|
sl@0
|
212 |
test_compound_select_flippable select9-1.$iOuterLoop.11 {
|
sl@0
|
213 |
SELECT a, b FROM t1 UNION SELECT d, e FROM t2 ORDER BY 2, 1
|
sl@0
|
214 |
} {3 {} 6 {} 9 {} 4 eight 8 eight 5 five 2 four 4 four 7 fourteen 1 one 7 seven 8 sixteen 5 ten 10 ten 10 twenty 1 two 2 two}
|
sl@0
|
215 |
|
sl@0
|
216 |
# Test some 2-way INTERSECT queries.
|
sl@0
|
217 |
#
|
sl@0
|
218 |
test_compound_select select9-1.$iOuterLoop.11 {
|
sl@0
|
219 |
SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2
|
sl@0
|
220 |
} {3 {} 6 {} 9 {}}
|
sl@0
|
221 |
test_compound_select_flippable select9-1.$iOuterLoop.12 {
|
sl@0
|
222 |
SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 ORDER BY 1
|
sl@0
|
223 |
} {3 {} 6 {} 9 {}}
|
sl@0
|
224 |
test_compound_select select9-1.$iOuterLoop.13 {
|
sl@0
|
225 |
SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 ORDER BY 2
|
sl@0
|
226 |
} {3 {} 6 {} 9 {}}
|
sl@0
|
227 |
test_compound_select_flippable select9-1.$iOuterLoop.14 {
|
sl@0
|
228 |
SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 ORDER BY 2, 1
|
sl@0
|
229 |
} {3 {} 6 {} 9 {}}
|
sl@0
|
230 |
test_compound_select_flippable select9-1.$iOuterLoop.15 {
|
sl@0
|
231 |
SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 ORDER BY 1, 2
|
sl@0
|
232 |
} {3 {} 6 {} 9 {}}
|
sl@0
|
233 |
|
sl@0
|
234 |
# Test some 2-way EXCEPT queries.
|
sl@0
|
235 |
#
|
sl@0
|
236 |
test_compound_select select9-1.$iOuterLoop.16 {
|
sl@0
|
237 |
SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2
|
sl@0
|
238 |
} {1 one 2 two 4 four 5 five 7 seven 8 eight 10 ten}
|
sl@0
|
239 |
|
sl@0
|
240 |
test_compound_select select9-1.$iOuterLoop.17 {
|
sl@0
|
241 |
SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 ORDER BY 1
|
sl@0
|
242 |
} {1 one 2 two 4 four 5 five 7 seven 8 eight 10 ten}
|
sl@0
|
243 |
|
sl@0
|
244 |
test_compound_select select9-1.$iOuterLoop.18 {
|
sl@0
|
245 |
SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 ORDER BY 2
|
sl@0
|
246 |
} {8 eight 5 five 4 four 1 one 7 seven 10 ten 2 two}
|
sl@0
|
247 |
|
sl@0
|
248 |
test_compound_select select9-1.$iOuterLoop.19 {
|
sl@0
|
249 |
SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 ORDER BY 1, 2
|
sl@0
|
250 |
} {1 one 2 two 4 four 5 five 7 seven 8 eight 10 ten}
|
sl@0
|
251 |
|
sl@0
|
252 |
test_compound_select select9-1.$iOuterLoop.20 {
|
sl@0
|
253 |
SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 ORDER BY 2, 1
|
sl@0
|
254 |
} {8 eight 5 five 4 four 1 one 7 seven 10 ten 2 two}
|
sl@0
|
255 |
|
sl@0
|
256 |
incr iOuterLoop
|
sl@0
|
257 |
}
|
sl@0
|
258 |
|
sl@0
|
259 |
do_test select9-2.0 {
|
sl@0
|
260 |
execsql {
|
sl@0
|
261 |
DROP INDEX i1;
|
sl@0
|
262 |
DROP INDEX i2;
|
sl@0
|
263 |
DROP INDEX i3;
|
sl@0
|
264 |
DROP INDEX i4;
|
sl@0
|
265 |
}
|
sl@0
|
266 |
} {}
|
sl@0
|
267 |
|
sl@0
|
268 |
proc reverse {lhs rhs} {
|
sl@0
|
269 |
return [string compare $rhs $lhs]
|
sl@0
|
270 |
}
|
sl@0
|
271 |
db collate reverse reverse
|
sl@0
|
272 |
|
sl@0
|
273 |
# This loop is similar to the previous one (test cases select9-1.*)
|
sl@0
|
274 |
# except that the simple select statements have WHERE clauses attached
|
sl@0
|
275 |
# to them. Sometimes the WHERE clause may be satisfied using the same
|
sl@0
|
276 |
# index used for ORDER BY, sometimes not.
|
sl@0
|
277 |
#
|
sl@0
|
278 |
set iOuterLoop 1
|
sl@0
|
279 |
foreach indexes [list {
|
sl@0
|
280 |
/* Do not create any indexes. */
|
sl@0
|
281 |
} {
|
sl@0
|
282 |
CREATE INDEX i1 ON t1(a)
|
sl@0
|
283 |
} {
|
sl@0
|
284 |
DROP INDEX i1;
|
sl@0
|
285 |
CREATE INDEX i1 ON t1(b, a)
|
sl@0
|
286 |
} {
|
sl@0
|
287 |
CREATE INDEX i2 ON t2(d DESC, e COLLATE REVERSE ASC);
|
sl@0
|
288 |
} {
|
sl@0
|
289 |
CREATE INDEX i3 ON t1(a DESC);
|
sl@0
|
290 |
}] {
|
sl@0
|
291 |
do_test select9-2.$iOuterLoop.1 {
|
sl@0
|
292 |
execsql $indexes
|
sl@0
|
293 |
} {}
|
sl@0
|
294 |
|
sl@0
|
295 |
test_compound_select_flippable select9-2.$iOuterLoop.2 {
|
sl@0
|
296 |
SELECT * FROM t1 WHERE a<5 UNION SELECT * FROM t2 WHERE d>=5 ORDER BY 1
|
sl@0
|
297 |
} {1 one I 2 two II 3 {} {} 4 four IV 5 ten XX 6 {} {} 7 fourteen XXVIII 8 sixteen XXXII 9 {} {} 10 twenty XL}
|
sl@0
|
298 |
|
sl@0
|
299 |
test_compound_select_flippable select9-2.$iOuterLoop.2 {
|
sl@0
|
300 |
SELECT * FROM t1 WHERE a<5 UNION SELECT * FROM t2 WHERE d>=5 ORDER BY 2, 1
|
sl@0
|
301 |
} {3 {} {} 6 {} {} 9 {} {} 4 four IV 7 fourteen XXVIII 1 one I 8 sixteen XXXII 5 ten XX 10 twenty XL 2 two II}
|
sl@0
|
302 |
|
sl@0
|
303 |
test_compound_select_flippable select9-2.$iOuterLoop.3 {
|
sl@0
|
304 |
SELECT * FROM t1 WHERE a<5 UNION SELECT * FROM t2 WHERE d>=5
|
sl@0
|
305 |
ORDER BY 2 COLLATE reverse, 1
|
sl@0
|
306 |
} {3 {} {} 6 {} {} 9 {} {} 2 two II 10 twenty XL 5 ten XX 8 sixteen XXXII 1 one I 7 fourteen XXVIII 4 four IV}
|
sl@0
|
307 |
|
sl@0
|
308 |
test_compound_select_flippable select9-2.$iOuterLoop.4 {
|
sl@0
|
309 |
SELECT * FROM t1 WHERE a<5 UNION ALL SELECT * FROM t2 WHERE d>=5 ORDER BY 1
|
sl@0
|
310 |
} {1 one I 2 two II 3 {} {} 4 four IV 5 ten XX 6 {} {} 7 fourteen XXVIII 8 sixteen XXXII 9 {} {} 10 twenty XL}
|
sl@0
|
311 |
|
sl@0
|
312 |
test_compound_select_flippable select9-2.$iOuterLoop.5 {
|
sl@0
|
313 |
SELECT * FROM t1 WHERE a<5 UNION ALL SELECT * FROM t2 WHERE d>=5 ORDER BY 2, 1
|
sl@0
|
314 |
} {3 {} {} 6 {} {} 9 {} {} 4 four IV 7 fourteen XXVIII 1 one I 8 sixteen XXXII 5 ten XX 10 twenty XL 2 two II}
|
sl@0
|
315 |
|
sl@0
|
316 |
test_compound_select_flippable select9-2.$iOuterLoop.6 {
|
sl@0
|
317 |
SELECT * FROM t1 WHERE a<5 UNION ALL SELECT * FROM t2 WHERE d>=5
|
sl@0
|
318 |
ORDER BY 2 COLLATE reverse, 1
|
sl@0
|
319 |
} {3 {} {} 6 {} {} 9 {} {} 2 two II 10 twenty XL 5 ten XX 8 sixteen XXXII 1 one I 7 fourteen XXVIII 4 four IV}
|
sl@0
|
320 |
|
sl@0
|
321 |
test_compound_select select9-2.$iOuterLoop.4 {
|
sl@0
|
322 |
SELECT a FROM t1 WHERE a<8 EXCEPT SELECT d FROM t2 WHERE d<=3 ORDER BY 1
|
sl@0
|
323 |
} {4 5 6 7}
|
sl@0
|
324 |
|
sl@0
|
325 |
test_compound_select select9-2.$iOuterLoop.4 {
|
sl@0
|
326 |
SELECT a FROM t1 WHERE a<8 INTERSECT SELECT d FROM t2 WHERE d<=3 ORDER BY 1
|
sl@0
|
327 |
} {1 2 3}
|
sl@0
|
328 |
|
sl@0
|
329 |
}
|
sl@0
|
330 |
|
sl@0
|
331 |
do_test select9-2.X {
|
sl@0
|
332 |
execsql {
|
sl@0
|
333 |
DROP INDEX i1;
|
sl@0
|
334 |
DROP INDEX i2;
|
sl@0
|
335 |
DROP INDEX i3;
|
sl@0
|
336 |
}
|
sl@0
|
337 |
} {}
|
sl@0
|
338 |
|
sl@0
|
339 |
# This procedure executes the SQL. Then it checks the generated program
|
sl@0
|
340 |
# for the SQL and appends a "nosort" to the result if the program contains the
|
sl@0
|
341 |
# SortCallback opcode. If the program does not contain the SortCallback
|
sl@0
|
342 |
# opcode it appends "sort"
|
sl@0
|
343 |
#
|
sl@0
|
344 |
proc cksort {sql} {
|
sl@0
|
345 |
set ::sqlite_sort_count 0
|
sl@0
|
346 |
set data [execsql $sql]
|
sl@0
|
347 |
if {$::sqlite_sort_count} {set x sort} {set x nosort}
|
sl@0
|
348 |
lappend data $x
|
sl@0
|
349 |
return $data
|
sl@0
|
350 |
}
|
sl@0
|
351 |
|
sl@0
|
352 |
# If the right indexes exist, the following query:
|
sl@0
|
353 |
#
|
sl@0
|
354 |
# SELECT t1.a FROM t1 UNION ALL SELECT t2.d FROM t2 ORDER BY 1
|
sl@0
|
355 |
#
|
sl@0
|
356 |
# can use indexes to run without doing a in-memory sort operation.
|
sl@0
|
357 |
# This block of tests (select9-3.*) is used to check if the same
|
sl@0
|
358 |
# is possible with:
|
sl@0
|
359 |
#
|
sl@0
|
360 |
# CREATE VIEW v1 AS SELECT a FROM t1 UNION ALL SELECT d FROM t2
|
sl@0
|
361 |
# SELECT a FROM v1 ORDER BY 1
|
sl@0
|
362 |
#
|
sl@0
|
363 |
# It turns out that it is.
|
sl@0
|
364 |
#
|
sl@0
|
365 |
do_test select9-3.1 {
|
sl@0
|
366 |
cksort { SELECT a FROM t1 ORDER BY 1 }
|
sl@0
|
367 |
} {1 2 3 4 5 6 7 8 9 10 sort}
|
sl@0
|
368 |
do_test select9-3.2 {
|
sl@0
|
369 |
execsql { CREATE INDEX i1 ON t1(a) }
|
sl@0
|
370 |
cksort { SELECT a FROM t1 ORDER BY 1 }
|
sl@0
|
371 |
} {1 2 3 4 5 6 7 8 9 10 nosort}
|
sl@0
|
372 |
do_test select9-3.3 {
|
sl@0
|
373 |
cksort { SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 5 }
|
sl@0
|
374 |
} {1 1 2 2 3 sort}
|
sl@0
|
375 |
do_test select9-3.4 {
|
sl@0
|
376 |
execsql { CREATE INDEX i2 ON t2(d) }
|
sl@0
|
377 |
cksort { SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 5 }
|
sl@0
|
378 |
} {1 1 2 2 3 nosort}
|
sl@0
|
379 |
do_test select9-3.5 {
|
sl@0
|
380 |
execsql { CREATE VIEW v1 AS SELECT a FROM t1 UNION ALL SELECT d FROM t2 }
|
sl@0
|
381 |
cksort { SELECT a FROM v1 ORDER BY 1 LIMIT 5 }
|
sl@0
|
382 |
} {1 1 2 2 3 nosort}
|
sl@0
|
383 |
do_test select9-3.X {
|
sl@0
|
384 |
execsql {
|
sl@0
|
385 |
DROP INDEX i1;
|
sl@0
|
386 |
DROP INDEX i2;
|
sl@0
|
387 |
DROP VIEW v1;
|
sl@0
|
388 |
}
|
sl@0
|
389 |
} {}
|
sl@0
|
390 |
|
sl@0
|
391 |
# This block of tests is the same as the preceding one, except that
|
sl@0
|
392 |
# "UNION" is tested instead of "UNION ALL".
|
sl@0
|
393 |
#
|
sl@0
|
394 |
do_test select9-4.1 {
|
sl@0
|
395 |
cksort { SELECT a FROM t1 ORDER BY 1 }
|
sl@0
|
396 |
} {1 2 3 4 5 6 7 8 9 10 sort}
|
sl@0
|
397 |
do_test select9-4.2 {
|
sl@0
|
398 |
execsql { CREATE INDEX i1 ON t1(a) }
|
sl@0
|
399 |
cksort { SELECT a FROM t1 ORDER BY 1 }
|
sl@0
|
400 |
} {1 2 3 4 5 6 7 8 9 10 nosort}
|
sl@0
|
401 |
do_test select9-4.3 {
|
sl@0
|
402 |
cksort { SELECT a FROM t1 UNION SELECT d FROM t2 ORDER BY 1 LIMIT 5 }
|
sl@0
|
403 |
} {1 2 3 4 5 sort}
|
sl@0
|
404 |
do_test select9-4.4 {
|
sl@0
|
405 |
execsql { CREATE INDEX i2 ON t2(d) }
|
sl@0
|
406 |
cksort { SELECT a FROM t1 UNION SELECT d FROM t2 ORDER BY 1 LIMIT 5 }
|
sl@0
|
407 |
} {1 2 3 4 5 nosort}
|
sl@0
|
408 |
do_test select9-4.5 {
|
sl@0
|
409 |
execsql { CREATE VIEW v1 AS SELECT a FROM t1 UNION SELECT d FROM t2 }
|
sl@0
|
410 |
cksort { SELECT a FROM v1 ORDER BY 1 LIMIT 5 }
|
sl@0
|
411 |
} {1 2 3 4 5 sort}
|
sl@0
|
412 |
do_test select9-4.X {
|
sl@0
|
413 |
execsql {
|
sl@0
|
414 |
DROP INDEX i1;
|
sl@0
|
415 |
DROP INDEX i2;
|
sl@0
|
416 |
DROP VIEW v1;
|
sl@0
|
417 |
}
|
sl@0
|
418 |
} {}
|
sl@0
|
419 |
|
sl@0
|
420 |
|
sl@0
|
421 |
finish_test
|