3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
11 # This file implements regression tests for SQLite library. The
12 # focus of this file is testing that the optimizations that disable
13 # ORDER BY clauses when the natural order of a query is correct.
17 set testdir [file dirname $argv0]
18 source $testdir/tester.tcl
19 set ::testprefix orderby1
21 # Generate test data for a join. Verify that the join gets the
28 aid INTEGER PRIMARY KEY,
29 title TEXT UNIQUE NOT NULL
32 tid INTEGER PRIMARY KEY,
33 aid INTEGER NOT NULL REFERENCES album,
38 INSERT INTO album VALUES(1, '1-one'), (2, '2-two'), (3, '3-three');
39 INSERT INTO track VALUES
40 (NULL, 1, 1, 'one-a'),
41 (NULL, 2, 2, 'two-b'),
42 (NULL, 3, 3, 'three-c'),
43 (NULL, 1, 3, 'one-c'),
44 (NULL, 2, 1, 'two-a'),
45 (NULL, 3, 1, 'three-a');
51 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
53 } {one-a one-c two-a two-b three-a three-c}
55 # Verify that the ORDER BY clause is optimized out
60 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn
62 } {~/ORDER BY/} ;# ORDER BY optimized out
64 # The same query with ORDER BY clause optimization disabled via + operators
65 # should give exactly the same answer.
69 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
71 } {one-a one-c two-a two-b three-a three-c}
73 # The output is sorted manually in this case.
78 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
80 } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms
82 # The same query with ORDER BY optimizations turned off via built-in test.
85 optimization_control db order-by-idx-join 0
88 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
90 } {one-a one-c two-a two-b three-a three-c}
94 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
96 } {/ORDER BY/} ;# separate sorting pass due to disabled optimization
97 optimization_control db all 1
100 # Reverse order sorts
104 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
106 } {three-a three-c two-a two-b one-a one-c}
109 SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn
111 } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting
115 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
117 } {~/ORDER BY/} ;# ORDER BY suppressed due to uniqueness constraints
121 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
123 } {one-c one-a two-b two-a three-c three-a}
126 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC
128 } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting
132 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
134 } {~/ORDER BY/} ;# ORDER BY suppressed due to uniqueness constraints
138 SELECT name FROM album CROSS JOIN track USING (aid)
139 ORDER BY title DESC, tn DESC
141 } {three-c three-a two-b two-a one-c one-a}
144 SELECT name FROM album CROSS JOIN track USING (aid)
145 ORDER BY +title DESC, +tn DESC
147 } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting
151 SELECT name FROM album CROSS JOIN track USING (aid)
152 ORDER BY title DESC, tn DESC
154 } {~/ORDER BY/} ;# ORDER BY
157 # Reconstruct the test data to use indices rather than integer primary keys.
168 CREATE INDEX album_i1 ON album(title, aid);
170 aid INTEGER NOT NULL REFERENCES album,
175 INSERT INTO album VALUES(1, '1-one'), (20, '2-two'), (3, '3-three');
176 INSERT INTO track VALUES
188 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
190 } {one-a one-c two-a two-b three-a three-c}
192 # Verify that the ORDER BY clause is optimized out
197 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
199 } {/ORDER BY/} ;# ORDER BY required because of missing aid term in ORDER BY
203 SELECT name FROM album JOIN track USING (aid) ORDER BY title, aid, tn
205 } {one-a one-c two-a two-b three-a three-c}
209 SELECT name FROM album JOIN track USING (aid) ORDER BY title, aid, tn
211 } {/ORDER BY/} ;# ORDER BY required in this case
213 # The same query with ORDER BY clause optimization disabled via + operators
214 # should give exactly the same answer.
218 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
220 } {one-a one-c two-a two-b three-a three-c}
222 # The output is sorted manually in this case.
227 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
229 } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms
231 # The same query with ORDER BY optimizations turned off via built-in test.
234 optimization_control db order-by-idx-join 0
237 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
239 } {one-a one-c two-a two-b three-a three-c}
243 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
245 } {/ORDER BY/} ;# separate sorting pass due to disabled optimization
246 optimization_control db all 1
249 # Reverse order sorts
253 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
255 } {three-a three-c two-a two-b one-a one-c}
258 SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn
260 } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting
264 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
266 } {/ORDER BY/} ;# separate sorting pass due to mixed DESC/ASC
271 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
273 } {one-c one-a two-b two-a three-c three-a}
276 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC
278 } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting
282 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
284 } {/ORDER BY/} ;# separate sorting pass due to mixed ASC/DESC
288 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
290 } {three-c three-a two-b two-a one-c one-a}
293 SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn DESC
295 } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting
299 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
301 } {/ORDER BY/} ;# ORDER BY required
304 # Generate another test dataset, but this time using mixed ASC/DESC indices.
312 aid INTEGER PRIMARY KEY,
313 title TEXT UNIQUE NOT NULL
316 tid INTEGER PRIMARY KEY,
317 aid INTEGER NOT NULL REFERENCES album,
320 UNIQUE(aid ASC, tn DESC)
322 INSERT INTO album VALUES(1, '1-one'), (2, '2-two'), (3, '3-three');
323 INSERT INTO track VALUES
324 (NULL, 1, 1, 'one-a'),
325 (NULL, 2, 2, 'two-b'),
326 (NULL, 3, 3, 'three-c'),
327 (NULL, 1, 3, 'one-c'),
328 (NULL, 2, 1, 'two-a'),
329 (NULL, 3, 1, 'three-a');
335 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC
337 } {one-c one-a two-b two-a three-c three-a}
339 # Verify that the ORDER BY clause is optimized out
344 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC
346 } {~/ORDER BY/} ;# ORDER BY optimized out
348 # The same query with ORDER BY clause optimization disabled via + operators
349 # should give exactly the same answer.
353 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC
355 } {one-c one-a two-b two-a three-c three-a}
357 # The output is sorted manually in this case.
362 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC
364 } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms
366 # The same query with ORDER BY optimizations turned off via built-in test.
369 optimization_control db order-by-idx-join 0
372 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
374 } {one-c one-a two-b two-a three-c three-a}
378 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
380 } {/ORDER BY/} ;# separate sorting pass due to disabled optimization
381 optimization_control db all 1
384 # Without the mixed ASC/DESC on ORDER BY
388 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
390 } {one-a one-c two-a two-b three-a three-c}
393 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
395 } {one-a one-c two-a two-b three-a three-c} ;# verify same order after sorting
399 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
401 } {~/ORDER BY/} ;# ORDER BY suppressed by uniqueness constraints
405 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
407 } {three-c three-a two-b two-a one-c one-a}
410 SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn DESC
412 } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting
416 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
418 } {~/ORDER BY/} ;# ORDER BY suppressed by uniqueness constraints
423 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn
425 } {three-a three-c two-a two-b one-a one-c}
428 SELECT name FROM album CROSS JOIN track USING (aid)
429 ORDER BY +title DESC, +tn
431 } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting
435 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn
437 } {~/ORDER BY/} ;# inverted ASC/DESC is optimized out
439 # Ticket 5ed1772895bf3deeab78c5e3519b1da9165c541b (2013-06-04)
440 # Incorrect ORDER BY on an indexed JOIN
444 CREATE TABLE t41(a INT UNIQUE NOT NULL, b INT NOT NULL);
445 CREATE INDEX t41ba ON t41(b,a);
446 CREATE TABLE t42(x INT NOT NULL REFERENCES t41(a), y INT NOT NULL);
447 CREATE UNIQUE INDEX t42xy ON t42(x,y);
448 INSERT INTO t41 VALUES(1,1),(3,1);
449 INSERT INTO t42 VALUES(1,13),(1,15),(3,14),(3,16);
451 SELECT b, y FROM t41 CROSS JOIN t42 ON x=a ORDER BY b, y;
453 } {1 13 1 14 1 15 1 16}
455 # No sorting of queries that omit the FROM clause.
463 do_execsql_test 5.1 {
464 EXPLAIN QUERY PLAN SELECT 5 UNION ALL SELECT 3 ORDER BY 1
466 do_execsql_test 5.2 {
467 SELECT 5 UNION ALL SELECT 3 ORDER BY 1
469 do_execsql_test 5.3 {
470 SELECT 986 AS x GROUP BY X ORDER BY X
473 # The following test (originally derived from a single test within fuzz.test)
474 # verifies that a PseudoTable cursor is not closed prematurely in a deeply
475 # nested query. This test caused a segfault on 3.8.5 beta.
477 do_execsql_test 6.0 {
478 CREATE TABLE abc(a, b, c);
479 INSERT INTO abc VALUES(1, 2, 3);
480 INSERT INTO abc VALUES(4, 5, 6);
481 INSERT INTO abc VALUES(7, 8, 9);
483 SELECT 'hardware' FROM (
484 SELECT 'software' ORDER BY 'firmware' ASC, 'sportswear' DESC
485 ) GROUP BY 1 HAVING length(b)
488 } {hardware hardware hardware}
490 # Here is a test for a query-planner problem reported on the SQLite
491 # mailing list on 2014-09-18 by "Merike". Beginning with version 3.8.0,
492 # a separate sort was being used rather than using the single-column
493 # index. This was due to an oversight in the indexMightHelpWithOrderby()
494 # routine in where.c.
496 do_execsql_test 7.0 {
497 CREATE TABLE t7(a,b);
498 CREATE INDEX t7a ON t7(a);
499 CREATE INDEX t7ab ON t7(a,b);
501 SELECT * FROM t7 WHERE a=?1 ORDER BY rowid;
504 #-------------------------------------------------------------------------
505 # Test a partial sort large enough to cause the sorter to spill data
509 do_execsql_test 8.0 {
510 PRAGMA cache_size = 5;
511 CREATE TABLE t1(a, b);
512 CREATE INDEX i1 ON t1(a);
516 SELECT * FROM t1 ORDER BY a, b;
519 |--SCAN TABLE t1 USING INDEX i1
520 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
523 do_execsql_test 8.2 {
525 SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000
527 INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt;
531 db eval { SELECT * FROM t1 ORDER BY a, b } { incr res $a }
535 #---------------------------------------------------------------------------
536 # https://www.sqlite.org/src/tktview/cb3aa0641d9a413841c004293a4fc06cdc122029
538 # Adverse interaction between scalar subqueries and the partial-sorting
541 do_execsql_test 9.0 {
542 DROP TABLE IF EXISTS t1;
543 CREATE TABLE t1(x INTEGER PRIMARY KEY);
544 INSERT INTO t1 VALUES(1),(2);
545 DROP TABLE IF EXISTS t2;
547 INSERT INTO t2 VALUES(9),(8),(3),(4);
548 SELECT (SELECT x||y FROM t2, t1 ORDER BY x, y);
551 # Problem found by OSSFuzz on 2018-05-05. This was caused by a new
552 # optimization that had not been previously released.
554 do_execsql_test 10.0 {
555 CREATE TABLE t10(a,b);
556 INSERT INTO t10 VALUES(1,2),(8,9),(3,4),(5,4),(0,7);
557 CREATE INDEX t10b ON t10(b);
558 SELECT b, rowid, '^' FROM t10 ORDER BY b, a LIMIT 4;
559 } {2 1 ^ 4 3 ^ 4 4 ^ 7 5 ^}