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');
52 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
54 } {one-a one-c two-a two-b three-a three-c}
56 # Verify that the ORDER BY clause is optimized out
61 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn
63 } {~/ORDER BY/} ;# ORDER BY optimized out
65 # The same query with ORDER BY clause optimization disabled via + operators
66 # should give exactly the same answer.
70 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
72 } {one-a one-c two-a two-b three-a three-c}
74 # The output is sorted manually in this case.
79 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
81 } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms
83 # The same query with ORDER BY optimizations turned off via built-in test.
86 optimization_control db order-by-idx-join 0
89 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
91 } {one-a one-c two-a two-b three-a three-c}
95 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
97 } {/ORDER BY/} ;# separate sorting pass due to disabled optimization
98 optimization_control db all 1
101 # Reverse order sorts
105 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
107 } {three-a three-c two-a two-b one-a one-c}
110 SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn
112 } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting
116 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
118 } {~/ORDER BY/} ;# ORDER BY suppressed due to uniqueness constraints
122 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
124 } {one-c one-a two-b two-a three-c three-a}
127 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC
129 } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting
133 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
135 } {~/ORDER BY/} ;# ORDER BY suppressed due to uniqueness constraints
139 SELECT name FROM album CROSS JOIN track USING (aid)
140 ORDER BY title DESC, tn DESC
142 } {three-c three-a two-b two-a one-c one-a}
145 SELECT name FROM album CROSS JOIN track USING (aid)
146 ORDER BY +title DESC, +tn DESC
148 } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting
152 SELECT name FROM album CROSS JOIN track USING (aid)
153 ORDER BY title DESC, tn DESC
155 } {~/ORDER BY/} ;# ORDER BY
158 # Reconstruct the test data to use indices rather than integer primary keys.
169 CREATE INDEX album_i1 ON album(title, aid);
171 aid INTEGER NOT NULL REFERENCES album,
176 INSERT INTO album VALUES(1, '1-one'), (20, '2-two'), (3, '3-three');
177 INSERT INTO track VALUES
190 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
192 } {one-a one-c two-a two-b three-a three-c}
194 # Verify that the ORDER BY clause is optimized out
199 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
201 } {/ORDER BY/} ;# ORDER BY required because of missing aid term in ORDER BY
205 SELECT name FROM album JOIN track USING (aid) ORDER BY title, aid, tn
207 } {one-a one-c two-a two-b three-a three-c}
211 SELECT name FROM album JOIN track USING (aid) ORDER BY title, aid, tn
213 } {/ORDER BY/} ;# ORDER BY required in this case
215 # The same query with ORDER BY clause optimization disabled via + operators
216 # should give exactly the same answer.
220 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
222 } {one-a one-c two-a two-b three-a three-c}
224 # The output is sorted manually in this case.
229 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
231 } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms
233 # The same query with ORDER BY optimizations turned off via built-in test.
236 optimization_control db order-by-idx-join 0
239 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
241 } {one-a one-c two-a two-b three-a three-c}
245 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
247 } {/ORDER BY/} ;# separate sorting pass due to disabled optimization
248 optimization_control db all 1
251 # Reverse order sorts
255 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
257 } {three-a three-c two-a two-b one-a one-c}
260 SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn
262 } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting
266 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
268 } {/ORDER BY/} ;# separate sorting pass due to mixed DESC/ASC
273 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
275 } {one-c one-a two-b two-a three-c three-a}
278 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC
280 } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting
284 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
286 } {/ORDER BY/} ;# separate sorting pass due to mixed ASC/DESC
290 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
292 } {three-c three-a two-b two-a one-c one-a}
295 SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn DESC
297 } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting
301 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
303 } {/ORDER BY/} ;# ORDER BY required
306 # Generate another test dataset, but this time using mixed ASC/DESC indices.
314 aid INTEGER PRIMARY KEY,
315 title TEXT UNIQUE NOT NULL
318 tid INTEGER PRIMARY KEY,
319 aid INTEGER NOT NULL REFERENCES album,
322 UNIQUE(aid ASC, tn DESC)
324 INSERT INTO album VALUES(1, '1-one'), (2, '2-two'), (3, '3-three');
325 INSERT INTO track VALUES
326 (NULL, 1, 1, 'one-a'),
327 (NULL, 2, 2, 'two-b'),
328 (NULL, 3, 3, 'three-c'),
329 (NULL, 1, 3, 'one-c'),
330 (NULL, 2, 1, 'two-a'),
331 (NULL, 3, 1, 'three-a');
338 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC
340 } {one-c one-a two-b two-a three-c three-a}
342 # Verify that the ORDER BY clause is optimized out
347 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC
349 } {~/ORDER BY/} ;# ORDER BY optimized out
351 # The same query with ORDER BY clause optimization disabled via + operators
352 # should give exactly the same answer.
356 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC
358 } {one-c one-a two-b two-a three-c three-a}
360 # The output is sorted manually in this case.
365 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn DESC
367 } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms
369 # The same query with ORDER BY optimizations turned off via built-in test.
372 optimization_control db order-by-idx-join 0
375 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
377 } {one-c one-a two-b two-a three-c three-a}
381 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
383 } {/ORDER BY/} ;# separate sorting pass due to disabled optimization
384 optimization_control db all 1
387 # Without the mixed ASC/DESC on ORDER BY
391 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
393 } {one-a one-c two-a two-b three-a three-c}
396 SELECT name FROM album JOIN track USING (aid) ORDER BY +title, +tn
398 } {one-a one-c two-a two-b three-a three-c} ;# verify same order after sorting
402 SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
404 } {~/ORDER BY/} ;# ORDER BY suppressed by uniqueness constraints
408 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
410 } {three-c three-a two-b two-a one-c one-a}
413 SELECT name FROM album JOIN track USING (aid) ORDER BY +title DESC, +tn DESC
415 } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting
419 SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
421 } {~/ORDER BY/} ;# ORDER BY suppressed by uniqueness constraints
426 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn
428 } {three-a three-c two-a two-b one-a one-c}
431 SELECT name FROM album CROSS JOIN track USING (aid)
432 ORDER BY +title DESC, +tn
434 } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting
438 SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn
440 } {~/ORDER BY/} ;# inverted ASC/DESC is optimized out
442 # Ticket 5ed1772895bf3deeab78c5e3519b1da9165c541b (2013-06-04)
443 # Incorrect ORDER BY on an indexed JOIN
447 CREATE TABLE t41(a INT UNIQUE NOT NULL, b INT NOT NULL);
448 CREATE INDEX t41ba ON t41(b,a);
449 CREATE TABLE t42(x INT NOT NULL REFERENCES t41(a), y INT NOT NULL);
450 CREATE UNIQUE INDEX t42xy ON t42(x,y);
451 INSERT INTO t41 VALUES(1,1),(3,1);
452 INSERT INTO t42 VALUES(1,13),(1,15),(3,14),(3,16);
454 SELECT b, y FROM t41 CROSS JOIN t42 ON x=a ORDER BY b, y;
456 } {1 13 1 14 1 15 1 16}
458 # No sorting of queries that omit the FROM clause.
466 do_execsql_test 5.1 {
467 EXPLAIN QUERY PLAN SELECT 5 UNION ALL SELECT 3 ORDER BY 1
469 do_execsql_test 5.2 {
470 SELECT 5 UNION ALL SELECT 3 ORDER BY 1
472 do_execsql_test 5.3 {
473 SELECT 986 AS x GROUP BY X ORDER BY X
476 # The following test (originally derived from a single test within fuzz.test)
477 # verifies that a PseudoTable cursor is not closed prematurely in a deeply
478 # nested query. This test caused a segfault on 3.8.5 beta.
480 do_execsql_test 6.0 {
481 CREATE TABLE abc(a, b, c);
482 INSERT INTO abc VALUES(1, 2, 3);
483 INSERT INTO abc VALUES(4, 5, 6);
484 INSERT INTO abc VALUES(7, 8, 9);
486 SELECT 'hardware' FROM (
487 SELECT 'software' ORDER BY 'firmware' ASC, 'sportswear' DESC
488 ) GROUP BY 1 HAVING length(b)
491 } {hardware hardware hardware}
493 # Here is a test for a query-planner problem reported on the SQLite
494 # mailing list on 2014-09-18 by "Merike". Beginning with version 3.8.0,
495 # a separate sort was being used rather than using the single-column
496 # index. This was due to an oversight in the indexMightHelpWithOrderby()
497 # routine in where.c.
499 do_execsql_test 7.0 {
500 CREATE TABLE t7(a,b);
501 CREATE INDEX t7a ON t7(a);
502 CREATE INDEX t7ab ON t7(a,b);
504 SELECT * FROM t7 WHERE a=?1 ORDER BY rowid;
507 #-------------------------------------------------------------------------
508 # Test a partial sort large enough to cause the sorter to spill data
512 do_execsql_test 8.0 {
513 PRAGMA cache_size = 5;
514 CREATE TABLE t1(a, b);
515 CREATE INDEX i1 ON t1(a);
519 SELECT * FROM t1 ORDER BY a, b;
522 |--SCAN t1 USING INDEX i1
523 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
526 do_execsql_test 8.2 {
528 SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000
530 INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt;
534 db eval { SELECT * FROM t1 ORDER BY a, b } { incr res $a }
538 #---------------------------------------------------------------------------
539 # https://www.sqlite.org/src/tktview/cb3aa0641d9a413841c004293a4fc06cdc122029
541 # Adverse interaction between scalar subqueries and the partial-sorting
544 do_execsql_test 9.0 {
545 DROP TABLE IF EXISTS t1;
546 CREATE TABLE t1(x INTEGER PRIMARY KEY);
547 INSERT INTO t1 VALUES(1),(2);
548 DROP TABLE IF EXISTS t2;
550 INSERT INTO t2 VALUES(9),(8),(3),(4);
551 SELECT (SELECT x||y FROM t2, t1 ORDER BY x, y);
554 # Problem found by OSSFuzz on 2018-05-05. This was caused by a new
555 # optimization that had not been previously released.
557 do_execsql_test 10.0 {
558 CREATE TABLE t10(a,b);
559 INSERT INTO t10 VALUES(1,2),(8,9),(3,4),(5,4),(0,7);
560 CREATE INDEX t10b ON t10(b);
561 SELECT b, rowid, '^' FROM t10 ORDER BY b, a LIMIT 4;
562 } {2 1 ^ 4 3 ^ 4 4 ^ 7 5 ^}
564 do_catchsql_test 11.0 {
565 VALUES(2) EXCEPT SELECT '' ORDER BY abc
566 } {1 {1st ORDER BY term does not match any column in the result set}}