diff --git a/testing/sqlite3/all.test b/testing/sqlite3/all.test new file mode 100755 index 000000000..6783d102d --- /dev/null +++ b/testing/sqlite3/all.test @@ -0,0 +1,21 @@ +#!/usr/bin/env tclsh + +set testdir [file dirname $argv0] + +source $testdir/select1.test +source $testdir/select2.test +source $testdir/select3.test +source $testdir/select4.test +source $testdir/select5.test +source $testdir/select6.test +source $testdir/select7.test +source $testdir/select8.test +source $testdir/select9.test +source $testdir/selectA.test +source $testdir/selectB.test +source $testdir/selectC.test +source $testdir/selectD.test +source $testdir/selectE.test +source $testdir/selectF.test +source $testdir/selectG.test +source $testdir/selectH.test diff --git a/testing/sqlite3/select1.test b/testing/sqlite3/select1.test new file mode 100644 index 000000000..44e63d252 --- /dev/null +++ b/testing/sqlite3/select1.test @@ -0,0 +1,1213 @@ +# 2001 September 15 +# +# 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 SELECT statement. +# +# $Id: select1.test,v 1.70 2009/05/28 01:00:56 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Try to select on a non-existant table. +# +do_test select1-1.1 { + set v [catch {execsql {SELECT * FROM test1}} msg] + lappend v $msg +} {1 {no such table: test1}} + + +execsql {CREATE TABLE test1(f1 int, f2 int)} + +do_test select1-1.2 { + set v [catch {execsql {SELECT * FROM test1, test2}} msg] + lappend v $msg +} {1 {no such table: test2}} +do_test select1-1.3 { + set v [catch {execsql {SELECT * FROM test2, test1}} msg] + lappend v $msg +} {1 {no such table: test2}} + +execsql {INSERT INTO test1(f1,f2) VALUES(11,22)} + + +# Make sure the columns are extracted correctly. +# +do_test select1-1.4 { + execsql {SELECT f1 FROM test1} +} {11} +do_test select1-1.5 { + execsql {SELECT f2 FROM test1} +} {22} +do_test select1-1.6 { + execsql {SELECT f2, f1 FROM test1} +} {22 11} +do_test select1-1.7 { + execsql {SELECT f1, f2 FROM test1} +} {11 22} +do_test select1-1.8 { + execsql {SELECT * FROM test1} +} {11 22} +do_test select1-1.8.1 { + execsql {SELECT *, * FROM test1} +} {11 22 11 22} +do_test select1-1.8.2 { + execsql {SELECT *, min(f1,f2), max(f1,f2) FROM test1} +} {11 22 11 22} +do_test select1-1.8.3 { + execsql {SELECT 'one', *, 'two', * FROM test1} +} {one 11 22 two 11 22} + +execsql {CREATE TABLE test2(r1 real, r2 real)} +execsql {INSERT INTO test2(r1,r2) VALUES(1.1,2.2)} + +do_test select1-1.9 { + execsql {SELECT * FROM test1, test2} +} {11 22 1.1 2.2} +do_test select1-1.9.1 { + execsql {SELECT *, 'hi' FROM test1, test2} +} {11 22 1.1 2.2 hi} +do_test select1-1.9.2 { + execsql {SELECT 'one', *, 'two', * FROM test1, test2} +} {one 11 22 1.1 2.2 two 11 22 1.1 2.2} +do_test select1-1.10 { + execsql {SELECT test1.f1, test2.r1 FROM test1, test2} +} {11 1.1} +do_test select1-1.11 { + execsql {SELECT test1.f1, test2.r1 FROM test2, test1} +} {11 1.1} +do_test select1-1.11.1 { + execsql {SELECT * FROM test2, test1} +} {1.1 2.2 11 22} +do_test select1-1.11.2 { + execsql {SELECT * FROM test1 AS a, test1 AS b} +} {11 22 11 22} +do_test select1-1.12 { + execsql {SELECT max(test1.f1,test2.r1), min(test1.f2,test2.r2) + FROM test2, test1} +} {11 2.2} +do_test select1-1.13 { + execsql {SELECT min(test1.f1,test2.r1), max(test1.f2,test2.r2) + FROM test1, test2} +} {1.1 22} + +set long {This is a string that is too big to fit inside a NBFS buffer} +do_test select1-2.0 { + execsql " + DROP TABLE test2; + DELETE FROM test1; + INSERT INTO test1 VALUES(11,22); + INSERT INTO test1 VALUES(33,44); + CREATE TABLE t3(a,b); + INSERT INTO t3 VALUES('abc',NULL); + INSERT INTO t3 VALUES(NULL,'xyz'); + INSERT INTO t3 SELECT * FROM test1; + CREATE TABLE t4(a,b); + INSERT INTO t4 VALUES(NULL,'$long'); + SELECT * FROM t3; + " +} {abc {} {} xyz 11 22 33 44} + +# Error messges from sqliteExprCheck +# +do_test select1-2.1 { + set v [catch {execsql {SELECT count(f1,f2) FROM test1}} msg] + lappend v $msg +} {1 {wrong number of arguments to function count()}} +do_test select1-2.2 { + set v [catch {execsql {SELECT count(f1) FROM test1}} msg] + lappend v $msg +} {0 2} +do_test select1-2.3 { + set v [catch {execsql {SELECT Count() FROM test1}} msg] + lappend v $msg +} {0 2} +do_test select1-2.4 { + set v [catch {execsql {SELECT COUNT(*) FROM test1}} msg] + lappend v $msg +} {0 2} +do_test select1-2.5 { + set v [catch {execsql {SELECT COUNT(*)+1 FROM test1}} msg] + lappend v $msg +} {0 3} +do_test select1-2.5.1 { + execsql {SELECT count(*),count(a),count(b) FROM t3} +} {4 3 3} +do_test select1-2.5.2 { + execsql {SELECT count(*),count(a),count(b) FROM t4} +} {1 0 1} +do_test select1-2.5.3 { + execsql {SELECT count(*),count(a),count(b) FROM t4 WHERE b=5} +} {0 0 0} +do_test select1-2.6 { + set v [catch {execsql {SELECT min(*) FROM test1}} msg] + lappend v $msg +} {1 {wrong number of arguments to function min()}} +do_test select1-2.7 { + set v [catch {execsql {SELECT Min(f1) FROM test1}} msg] + lappend v $msg +} {0 11} +do_test select1-2.8 { + set v [catch {execsql {SELECT MIN(f1,f2) FROM test1}} msg] + lappend v [lsort $msg] +} {0 {11 33}} +do_test select1-2.8.1 { + execsql {SELECT coalesce(min(a),'xyzzy') FROM t3} +} {11} +do_test select1-2.8.2 { + execsql {SELECT min(coalesce(a,'xyzzy')) FROM t3} +} {11} +do_test select1-2.8.3 { + execsql {SELECT min(b), min(b) FROM t4} +} [list $long $long] +do_test select1-2.9 { + set v [catch {execsql {SELECT MAX(*) FROM test1}} msg] + lappend v $msg +} {1 {wrong number of arguments to function MAX()}} +do_test select1-2.10 { + set v [catch {execsql {SELECT Max(f1) FROM test1}} msg] + lappend v $msg +} {0 33} +do_test select1-2.11 { + set v [catch {execsql {SELECT max(f1,f2) FROM test1}} msg] + lappend v [lsort $msg] +} {0 {22 44}} +do_test select1-2.12 { + set v [catch {execsql {SELECT MAX(f1,f2)+1 FROM test1}} msg] + lappend v [lsort $msg] +} {0 {23 45}} +do_test select1-2.13 { + set v [catch {execsql {SELECT MAX(f1)+1 FROM test1}} msg] + lappend v $msg +} {0 34} +do_test select1-2.13.1 { + execsql {SELECT coalesce(max(a),'xyzzy') FROM t3} +} {abc} +do_test select1-2.13.2 { + execsql {SELECT max(coalesce(a,'xyzzy')) FROM t3} +} {xyzzy} +do_test select1-2.14 { + set v [catch {execsql {SELECT SUM(*) FROM test1}} msg] + lappend v $msg +} {1 {wrong number of arguments to function SUM()}} +do_test select1-2.15 { + set v [catch {execsql {SELECT Sum(f1) FROM test1}} msg] + lappend v $msg +} {0 44} +do_test select1-2.16 { + set v [catch {execsql {SELECT sum(f1,f2) FROM test1}} msg] + lappend v $msg +} {1 {wrong number of arguments to function sum()}} +do_test select1-2.17 { + set v [catch {execsql {SELECT SUM(f1)+1 FROM test1}} msg] + lappend v $msg +} {0 45} +do_test select1-2.17.1 { + execsql {SELECT sum(a) FROM t3} +} {44.0} +do_test select1-2.18 { + set v [catch {execsql {SELECT XYZZY(f1) FROM test1}} msg] + lappend v $msg +} {1 {no such function: XYZZY}} +do_test select1-2.19 { + set v [catch {execsql {SELECT SUM(min(f1,f2)) FROM test1}} msg] + lappend v $msg +} {0 44} +do_test select1-2.20 { + set v [catch {execsql {SELECT SUM(min(f1)) FROM test1}} msg] + lappend v $msg +} {1 {misuse of aggregate function min()}} + +# Ticket #2526 +# +do_test select1-2.21 { + catchsql { + SELECT min(f1) AS m FROM test1 GROUP BY f1 HAVING max(m+5)<10 + } +} {1 {misuse of aliased aggregate m}} +do_test select1-2.22 { + catchsql { + SELECT coalesce(min(f1)+5,11) AS m FROM test1 + GROUP BY f1 + HAVING max(m+5)<10 + } +} {1 {misuse of aliased aggregate m}} +do_test select1-2.23 { + execsql { + CREATE TABLE tkt2526(a,b,c PRIMARY KEY); + INSERT INTO tkt2526 VALUES('x','y',NULL); + INSERT INTO tkt2526 VALUES('x','z',NULL); + } + catchsql { + SELECT count(a) AS cn FROM tkt2526 GROUP BY a HAVING cn=11}} msg] + lappend v [lsort $msg] +} {0 {11 33}} +do_test select1-3.5 { + set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>11}} msg] + lappend v [lsort $msg] +} {0 33} +do_test select1-3.6 { + set v [catch {execsql {SELECT f1 FROM test1 WHERE f1!=11}} msg] + lappend v [lsort $msg] +} {0 33} +do_test select1-3.7 { + set v [catch {execsql {SELECT f1 FROM test1 WHERE min(f1,f2)!=11}} msg] + lappend v [lsort $msg] +} {0 33} +do_test select1-3.8 { + set v [catch {execsql {SELECT f1 FROM test1 WHERE max(f1,f2)!=11}} msg] + lappend v [lsort $msg] +} {0 {11 33}} +do_test select1-3.9 { + set v [catch {execsql {SELECT f1 FROM test1 WHERE count(f1,f2)!=11}} msg] + lappend v $msg +} {1 {wrong number of arguments to function count()}} + +# ORDER BY expressions +# +do_test select1-4.1 { + set v [catch {execsql {SELECT f1 FROM test1 ORDER BY f1}} msg] + lappend v $msg +} {0 {11 33}} +do_test select1-4.2 { + set v [catch {execsql {SELECT f1 FROM test1 ORDER BY -f1}} msg] + lappend v $msg +} {0 {33 11}} +do_test select1-4.3 { + set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1,f2)}} msg] + lappend v $msg +} {0 {11 33}} +do_test select1-4.4 { + set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg] + lappend v $msg +} {1 {misuse of aggregate: min()}} +do_catchsql_test select1-4.5 { + INSERT INTO test1(f1) SELECT f1 FROM test1 ORDER BY min(f1); +} {1 {misuse of aggregate: min()}} + +# The restriction not allowing constants in the ORDER BY clause +# has been removed. See ticket #1768 +#do_test select1-4.5 { +# catchsql { +# SELECT f1 FROM test1 ORDER BY 8.4; +# } +#} {1 {ORDER BY terms must not be non-integer constants}} +#do_test select1-4.6 { +# catchsql { +# SELECT f1 FROM test1 ORDER BY '8.4'; +# } +#} {1 {ORDER BY terms must not be non-integer constants}} +#do_test select1-4.7.1 { +# catchsql { +# SELECT f1 FROM test1 ORDER BY 'xyz'; +# } +#} {1 {ORDER BY terms must not be non-integer constants}} +#do_test select1-4.7.2 { +# catchsql { +# SELECT f1 FROM test1 ORDER BY -8.4; +# } +#} {1 {ORDER BY terms must not be non-integer constants}} +#do_test select1-4.7.3 { +# catchsql { +# SELECT f1 FROM test1 ORDER BY +8.4; +# } +#} {1 {ORDER BY terms must not be non-integer constants}} +#do_test select1-4.7.4 { +# catchsql { +# SELECT f1 FROM test1 ORDER BY 4294967296; -- constant larger than 32 bits +# } +#} {1 {ORDER BY terms must not be non-integer constants}} + +do_test select1-4.5 { + execsql { + SELECT f1 FROM test1 ORDER BY 8.4 + } +} {11 33} +do_test select1-4.6 { + execsql { + SELECT f1 FROM test1 ORDER BY '8.4' + } +} {11 33} + +do_test select1-4.8 { + execsql { + CREATE TABLE t5(a,b); + INSERT INTO t5 VALUES(1,10); + INSERT INTO t5 VALUES(2,9); + SELECT * FROM t5 ORDER BY 1; + } +} {1 10 2 9} +do_test select1-4.9.1 { + execsql { + SELECT * FROM t5 ORDER BY 2; + } +} {2 9 1 10} +do_test select1-4.9.2 { + execsql { + SELECT * FROM t5 ORDER BY +2; + } +} {2 9 1 10} +do_test select1-4.10.1 { + catchsql { + SELECT * FROM t5 ORDER BY 3; + } +} {1 {1st ORDER BY term out of range - should be between 1 and 2}} +do_test select1-4.10.2 { + catchsql { + SELECT * FROM t5 ORDER BY -1; + } +} {1 {1st ORDER BY term out of range - should be between 1 and 2}} +do_test select1-4.11 { + execsql { + INSERT INTO t5 VALUES(3,10); + SELECT * FROM t5 ORDER BY 2, 1 DESC; + } +} {2 9 3 10 1 10} +do_test select1-4.12 { + execsql { + SELECT * FROM t5 ORDER BY 1 DESC, b; + } +} {3 10 2 9 1 10} +do_test select1-4.13 { + execsql { + SELECT * FROM t5 ORDER BY b DESC, 1; + } +} {1 10 3 10 2 9} + + +# ORDER BY ignored on an aggregate query +# +do_test select1-5.1 { + set v [catch {execsql {SELECT max(f1) FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 33} + +execsql {CREATE TABLE test2(t1 text, t2 text)} +execsql {INSERT INTO test2 VALUES('abc','xyz')} + +# Check for column naming +# +do_test select1-6.1 { + set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {f1 11 f1 33}} +do_test select1-6.1.1 { + db eval {PRAGMA full_column_names=on} + set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {test1.f1 11 test1.f1 33}} +do_test select1-6.1.2 { + set v [catch {execsql2 {SELECT f1 as 'f1' FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {f1 11 f1 33}} +do_test select1-6.1.3 { + set v [catch {execsql2 {SELECT * FROM test1 WHERE f1==11}} msg] + lappend v $msg +} {0 {f1 11 f2 22}} +do_test select1-6.1.4 { + set v [catch {execsql2 {SELECT DISTINCT * FROM test1 WHERE f1==11}} msg] + db eval {PRAGMA full_column_names=off} + lappend v $msg +} {0 {f1 11 f2 22}} +do_test select1-6.1.5 { + set v [catch {execsql2 {SELECT * FROM test1 WHERE f1==11}} msg] + lappend v $msg +} {0 {f1 11 f2 22}} +do_test select1-6.1.6 { + set v [catch {execsql2 {SELECT DISTINCT * FROM test1 WHERE f1==11}} msg] + lappend v $msg +} {0 {f1 11 f2 22}} +do_test select1-6.2 { + set v [catch {execsql2 {SELECT f1 as xyzzy FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {xyzzy 11 xyzzy 33}} +do_test select1-6.3 { + set v [catch {execsql2 {SELECT f1 as "xyzzy" FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {xyzzy 11 xyzzy 33}} +do_test select1-6.3.1 { + set v [catch {execsql2 {SELECT f1 as 'xyzzy ' FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {{xyzzy } 11 {xyzzy } 33}} +do_test select1-6.4 { + set v [catch {execsql2 {SELECT f1+F2 as xyzzy FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {xyzzy 33 xyzzy 77}} +do_test select1-6.4a { + set v [catch {execsql2 {SELECT f1+F2 FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {f1+F2 33 f1+F2 77}} +do_test select1-6.5 { + set v [catch {execsql2 {SELECT test1.f1+F2 FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {test1.f1+F2 33 test1.f1+F2 77}} +do_test select1-6.5.1 { + execsql2 {PRAGMA full_column_names=on} + set v [catch {execsql2 {SELECT test1.f1+F2 FROM test1 ORDER BY f2}} msg] + execsql2 {PRAGMA full_column_names=off} + lappend v $msg +} {0 {test1.f1+F2 33 test1.f1+F2 77}} +do_test select1-6.6 { + set v [catch {execsql2 {SELECT test1.f1+F2, t1 FROM test1, test2 + ORDER BY f2}} msg] + lappend v $msg +} {0 {test1.f1+F2 33 t1 abc test1.f1+F2 77 t1 abc}} +do_test select1-6.7 { + set v [catch {execsql2 {SELECT A.f1, t1 FROM test1 as A, test2 + ORDER BY f2}} msg] + lappend v $msg +} {0 {f1 11 t1 abc f1 33 t1 abc}} +do_test select1-6.8 { + set v [catch {execsql2 {SELECT A.f1, f1 FROM test1 as A, test1 as B + ORDER BY f2}} msg] + lappend v $msg +} {1 {ambiguous column name: f1}} +do_test select1-6.8b { + set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B + ORDER BY f2}} msg] + lappend v $msg +} {1 {ambiguous column name: f2}} +do_test select1-6.8c { + set v [catch {execsql2 {SELECT A.f1, f1 FROM test1 as A, test1 as A + ORDER BY f2}} msg] + lappend v $msg +} {1 {ambiguous column name: A.f1}} +do_test select1-6.9.1 { + set v [catch {execsql {SELECT A.f1, B.f1 FROM test1 as A, test1 as B + ORDER BY A.f1, B.f1}} msg] + lappend v $msg +} {0 {11 11 11 33 33 11 33 33}} +do_test select1-6.9.2 { + set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B + ORDER BY A.f1, B.f1}} msg] + lappend v $msg +} {0 {f1 11 f1 11 f1 33 f1 33 f1 11 f1 11 f1 33 f1 33}} + +do_test select1-6.9.3 { + db eval { + PRAGMA short_column_names=OFF; + PRAGMA full_column_names=OFF; + } + execsql2 { + SELECT test1 . f1, test1 . f2 FROM test1 LIMIT 1 + } +} {{test1 . f1} 11 {test1 . f2} 22} +do_test select1-6.9.4 { + db eval { + PRAGMA short_column_names=OFF; + PRAGMA full_column_names=ON; + } + execsql2 { + SELECT test1 . f1, test1 . f2 FROM test1 LIMIT 1 + } +} {test1.f1 11 test1.f2 22} +do_test select1-6.9.5 { + db eval { + PRAGMA short_column_names=OFF; + PRAGMA full_column_names=ON; + } + execsql2 { + SELECT 123.45; + } +} {123.45 123.45} +do_test select1-6.9.6 { + execsql2 { + SELECT * FROM test1 a, test1 b LIMIT 1 + } +} {a.f1 11 a.f2 22 b.f1 11 b.f2 22} +do_test select1-6.9.7 { + set x [execsql2 { + SELECT * FROM test1 a, (select 5, 6) LIMIT 1 + }] + regsub -all {subquery-\d+} $x {subquery-0} x + set x +} {a.f1 11 a.f2 22 (subquery-0).5 5 (subquery-0).6 6} +do_test select1-6.9.8 { + set x [execsql2 { + SELECT * FROM test1 a, (select 5 AS x, 6 AS y) AS b LIMIT 1 + }] + regsub -all {subquery-\d+} $x {subquery-0} x + set x +} {a.f1 11 a.f2 22 b.x 5 b.y 6} +do_test select1-6.9.9 { + execsql2 { + SELECT a.f1, b.f2 FROM test1 a, test1 b LIMIT 1 + } +} {test1.f1 11 test1.f2 22} +do_test select1-6.9.10 { + execsql2 { + SELECT f1, t1 FROM test1, test2 LIMIT 1 + } +} {test1.f1 11 test2.t1 abc} +do_test select1-6.9.11 { + db eval { + PRAGMA short_column_names=ON; + PRAGMA full_column_names=ON; + } + execsql2 { + SELECT a.f1, b.f2 FROM test1 a, test1 b LIMIT 1 + } +} {test1.f1 11 test1.f2 22} +do_test select1-6.9.12 { + execsql2 { + SELECT f1, t1 FROM test1, test2 LIMIT 1 + } +} {test1.f1 11 test2.t1 abc} +do_test select1-6.9.13 { + db eval { + PRAGMA short_column_names=ON; + PRAGMA full_column_names=OFF; + } + execsql2 { + SELECT a.f1, b.f1 FROM test1 a, test1 b LIMIT 1 + } +} {f1 11 f1 11} +do_test select1-6.9.14 { + execsql2 { + SELECT f1, t1 FROM test1, test2 LIMIT 1 + } +} {f1 11 t1 abc} +do_test select1-6.9.15 { + db eval { + PRAGMA short_column_names=OFF; + PRAGMA full_column_names=ON; + } + execsql2 { + SELECT a.f1, b.f1 FROM test1 a, test1 b LIMIT 1 + } +} {test1.f1 11 test1.f1 11} +do_test select1-6.9.16 { + execsql2 { + SELECT f1, t1 FROM test1, test2 LIMIT 1 + } +} {test1.f1 11 test2.t1 abc} + + +db eval { + PRAGMA short_column_names=ON; + PRAGMA full_column_names=OFF; +} + +ifcapable compound { +do_test select1-6.10 { + set v [catch {execsql2 { + SELECT f1 FROM test1 UNION SELECT f2 FROM test1 + ORDER BY f2; + }} msg] + lappend v $msg +} {0 {f1 11 f1 22 f1 33 f1 44}} +do_test select1-6.11 { + set v [catch {execsql2 { + SELECT f1 FROM test1 UNION SELECT f2+100 FROM test1 + ORDER BY f2+101; + }} msg] + lappend v $msg +} {1 {1st ORDER BY term does not match any column in the result set}} + +# Ticket #2296 +ifcapable subquery&&compound { +do_test select1-6.20 { + execsql { + CREATE TABLE t6(a TEXT, b TEXT); + INSERT INTO t6 VALUES('a','0'); + INSERT INTO t6 VALUES('b','1'); + INSERT INTO t6 VALUES('c','2'); + INSERT INTO t6 VALUES('d','3'); + SELECT a FROM t6 WHERE b IN + (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x + ORDER BY 1 LIMIT 1) + } +} {a} +do_test select1-6.21 { + execsql { + SELECT a FROM t6 WHERE b IN + (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x + ORDER BY 1 DESC LIMIT 1) + } +} {d} +do_test select1-6.22 { + execsql { + SELECT a FROM t6 WHERE b IN + (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x + ORDER BY b LIMIT 2) + ORDER BY a; + } +} {a b} +do_test select1-6.23 { + execsql { + SELECT a FROM t6 WHERE b IN + (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x + ORDER BY x DESC LIMIT 2) + ORDER BY a; + } +} {b d} +} + +} ;#ifcapable compound + +do_test select1-7.1 { + set v [catch {execsql { + SELECT f1 FROM test1 WHERE f2=; + }} msg] + lappend v $msg +} {1 {near ";": syntax error}} +ifcapable compound { +do_test select1-7.2 { + set v [catch {execsql { + SELECT f1 FROM test1 UNION SELECT WHERE; + }} msg] + lappend v $msg +} {1 {near "WHERE": syntax error}} +} ;# ifcapable compound +do_test select1-7.3 { + set v [catch {execsql {SELECT f1 FROM test1 as 'hi', test2 as}} msg] + lappend v $msg +} {1 {incomplete input}} +do_test select1-7.4 { + set v [catch {execsql { + SELECT f1 FROM test1 ORDER BY; + }} msg] + lappend v $msg +} {1 {near ";": syntax error}} +do_test select1-7.5 { + set v [catch {execsql { + SELECT f1 FROM test1 ORDER BY f1 desc, f2 where; + }} msg] + lappend v $msg +} {1 {near "where": syntax error}} +do_test select1-7.6 { + set v [catch {execsql { + SELECT count(f1,f2 FROM test1; + }} msg] + lappend v $msg +} {1 {near "FROM": syntax error}} +do_test select1-7.7 { + set v [catch {execsql { + SELECT count(f1,f2+) FROM test1; + }} msg] + lappend v $msg +} {1 {near ")": syntax error}} +do_test select1-7.8 { + set v [catch {execsql { + SELECT f1 FROM test1 ORDER BY f2, f1+; + }} msg] + lappend v $msg +} {1 {near ";": syntax error}} +do_test select1-7.9 { + catchsql { + SELECT f1 FROM test1 LIMIT 5+3 OFFSET 11 ORDER BY f2; + } +} {1 {near "ORDER": syntax error}} + +do_test select1-8.1 { + execsql {SELECT f1 FROM test1 WHERE 4.3+2.4 OR 1 ORDER BY f1} +} {11 33} +do_test select1-8.2 { + execsql { + SELECT f1 FROM test1 WHERE ('x' || f1) BETWEEN 'x10' AND 'x20' + ORDER BY f1 + } +} {11} +do_test select1-8.3 { + execsql { + SELECT f1 FROM test1 WHERE 5-3==2 + ORDER BY f1 + } +} {11 33} + +# TODO: This test is failing because f1 is now being loaded off the +# disk as a vdbe integer, not a string. Hence the value of f1/(f1-11) +# changes because of rounding. Disable the test for now. +if 0 { +do_test select1-8.4 { + execsql { + SELECT coalesce(f1/(f1-11),'x'), + coalesce(min(f1/(f1-11),5),'y'), + coalesce(max(f1/(f1-33),6),'z') + FROM test1 ORDER BY f1 + } +} {x y 6 1.5 1.5 z} +} +do_test select1-8.5 { + execsql { + SELECT min(1,2,3), -max(1,2,3) + FROM test1 ORDER BY f1 + } +} {1 -3 1 -3} + + +# Check the behavior when the result set is empty +# +# SQLite v3 always sets r(*). +# +# do_test select1-9.1 { +# catch {unset r} +# set r(*) {} +# db eval {SELECT * FROM test1 WHERE f1<0} r {} +# set r(*) +# } {} +do_test select1-9.2 { + execsql {PRAGMA empty_result_callbacks=on} + catch {unset r} + set r(*) {} + db eval {SELECT * FROM test1 WHERE f1<0} r {} + set r(*) +} {f1 f2} +ifcapable subquery { + do_test select1-9.3 { + set r(*) {} + db eval {SELECT * FROM test1 WHERE f1<(select count(*) from test2)} r {} + set r(*) + } {f1 f2} +} +do_test select1-9.4 { + set r(*) {} + db eval {SELECT * FROM test1 ORDER BY f1} r {} + set r(*) +} {f1 f2} +do_test select1-9.5 { + set r(*) {} + db eval {SELECT * FROM test1 WHERE f1<0 ORDER BY f1} r {} + set r(*) +} {f1 f2} +unset r + +# Check for ORDER BY clauses that refer to an AS name in the column list +# +do_test select1-10.1 { + execsql { + SELECT f1 AS x FROM test1 ORDER BY x + } +} {11 33} +do_test select1-10.2 { + execsql { + SELECT f1 AS x FROM test1 ORDER BY -x + } +} {33 11} +do_test select1-10.3 { + execsql { + SELECT f1-23 AS x FROM test1 ORDER BY abs(x) + } +} {10 -12} +do_test select1-10.4 { + execsql { + SELECT f1-23 AS x FROM test1 ORDER BY -abs(x) + } +} {-12 10} +do_test select1-10.5 { + execsql { + SELECT f1-22 AS x, f2-22 as y FROM test1 + } +} {-11 0 11 22} +do_test select1-10.6 { + execsql { + SELECT f1-22 AS x, f2-22 as y FROM test1 WHERE x>0 AND y<50 + } +} {11 22} +do_test select1-10.7 { + execsql { + SELECT f1 COLLATE nocase AS x FROM test1 ORDER BY x + } +} {11 33} + +# Check the ability to specify "TABLE.*" in the result set of a SELECT +# +do_test select1-11.1 { + execsql { + DELETE FROM t3; + DELETE FROM t4; + INSERT INTO t3 VALUES(1,2); + INSERT INTO t4 VALUES(3,4); + SELECT * FROM t3, t4; + } +} {1 2 3 4} +do_test select1-11.2.1 { + execsql { + SELECT * FROM t3, t4; + } +} {1 2 3 4} +do_test select1-11.2.2 { + execsql2 { + SELECT * FROM t3, t4; + } +} {a 3 b 4 a 3 b 4} +do_test select1-11.4.1 { + execsql { + SELECT t3.*, t4.b FROM t3, t4; + } +} {1 2 4} +do_test select1-11.4.2 { + execsql { + SELECT "t3".*, t4.b FROM t3, t4; + } +} {1 2 4} +do_test select1-11.5.1 { + execsql2 { + SELECT t3.*, t4.b FROM t3, t4; + } +} {a 1 b 4 b 4} +do_test select1-11.6 { + execsql2 { + SELECT x.*, y.b FROM t3 AS x, t4 AS y; + } +} {a 1 b 4 b 4} +do_test select1-11.7 { + execsql { + SELECT t3.b, t4.* FROM t3, t4; + } +} {2 3 4} +do_test select1-11.8 { + execsql2 { + SELECT t3.b, t4.* FROM t3, t4; + } +} {b 4 a 3 b 4} +do_test select1-11.9 { + execsql2 { + SELECT x.b, y.* FROM t3 AS x, t4 AS y; + } +} {b 4 a 3 b 4} +do_test select1-11.10 { + catchsql { + SELECT t5.* FROM t3, t4; + } +} {1 {no such table: t5}} +do_test select1-11.11 { + catchsql { + SELECT t3.* FROM t3 AS x, t4; + } +} {1 {no such table: t3}} +ifcapable subquery { + do_test select1-11.12 { + execsql2 { + SELECT t3.* FROM t3, (SELECT max(a), max(b) FROM t4) + } + } {a 1 b 2} + do_test select1-11.13 { + execsql2 { + SELECT t3.* FROM (SELECT max(a), max(b) FROM t4), t3 + } + } {a 1 b 2} + do_test select1-11.14 { + execsql2 { + SELECT * FROM t3, (SELECT max(a), max(b) FROM t4) AS 'tx' + } + } {a 1 b 2 max(a) 3 max(b) 4} + do_test select1-11.15 { + execsql2 { + SELECT y.*, t3.* FROM t3, (SELECT max(a), max(b) FROM t4) AS y + } + } {max(a) 3 max(b) 4 a 1 b 2} +} +do_test select1-11.16 { + execsql2 { + SELECT y.* FROM t3 as y, t4 as z + } +} {a 1 b 2} + +# Tests of SELECT statements without a FROM clause. +# +do_test select1-12.1 { + execsql2 { + SELECT 1+2+3 + } +} {1+2+3 6} +do_test select1-12.2 { + execsql2 { + SELECT 1,'hello',2 + } +} {1 1 'hello' hello 2 2} +do_test select1-12.3 { + execsql2 { + SELECT 1 AS 'a','hello' AS 'b',2 AS 'c' + } +} {a 1 b hello c 2} +do_test select1-12.4 { + execsql { + DELETE FROM t3; + INSERT INTO t3 VALUES(1,2); + } +} {} + +ifcapable compound { +do_test select1-12.5 { + execsql { + SELECT * FROM t3 UNION SELECT 3 AS 'a', 4 ORDER BY a; + } +} {1 2 3 4} + +do_test select1-12.6 { + execsql { + SELECT 3, 4 UNION SELECT * FROM t3; + } +} {1 2 3 4} +} ;# ifcapable compound + +ifcapable subquery { + do_test select1-12.7 { + execsql { + SELECT * FROM t3 WHERE a=(SELECT 1); + } + } {1 2} + do_test select1-12.8 { + execsql { + SELECT * FROM t3 WHERE a=(SELECT 2); + } + } {} +} + +ifcapable {compound && subquery} { + do_test select1-12.9 { + execsql2 { + SELECT x FROM ( + SELECT a AS x, b AS y FROM t3 UNION SELECT a,b FROM t4 ORDER BY a,b + ) ORDER BY x; + } + } {x 1 x 3} + do_test select1-12.10 { + execsql2 { + SELECT z.x FROM ( + SELECT a AS x,b AS y FROM t3 UNION SELECT a, b FROM t4 ORDER BY a,b + ) AS 'z' ORDER BY x; + } + } {x 1 x 3} +} ;# ifcapable compound + + +# Check for a VDBE stack growth problem that existed at one point. +# +ifcapable subquery { + do_test select1-13.1 { + execsql { + BEGIN; + create TABLE abc(a, b, c, PRIMARY KEY(a, b)); + INSERT INTO abc VALUES(1, 1, 1); + } + for {set i 0} {$i<10} {incr i} { + execsql { + INSERT INTO abc SELECT a+(select max(a) FROM abc), + b+(select max(a) FROM abc), c+(select max(a) FROM abc) FROM abc; + } + } + execsql {COMMIT} + + # This used to seg-fault when the problem existed. + execsql { + SELECT count( + (SELECT a FROM abc WHERE a = NULL AND b >= upper.c) + ) FROM abc AS upper; + } + } {0} +} + +foreach tab [db eval {SELECT name FROM sqlite_master WHERE type = 'table'}] { + db eval "DROP TABLE $tab" +} +db close +sqlite3 db test.db + +do_test select1-14.1 { + execsql { + SELECT * FROM sqlite_master WHERE rowid>10; + SELECT * FROM sqlite_master WHERE rowid=10; + SELECT * FROM sqlite_master WHERE rowid<10; + SELECT * FROM sqlite_master WHERE rowid<=10; + SELECT * FROM sqlite_master WHERE rowid>=10; + SELECT * FROM sqlite_master; + } +} {} +do_test select1-14.2 { + execsql { + SELECT 10 IN (SELECT rowid FROM sqlite_master); + } +} {0} + +if {[db one {PRAGMA locking_mode}]=="normal"} { + # Check that ticket #3771 has been fixed. This test does not + # work with locking_mode=EXCLUSIVE so disable in that case. + # + do_test select1-15.1 { + execsql { + CREATE TABLE t1(a); + CREATE INDEX i1 ON t1(a); + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + INSERT INTO t1 VALUES(3); + } + } {} + do_test select1-15.2 { + sqlite3 db2 test.db + execsql { DROP INDEX i1 } db2 + db2 close + } {} + do_test select1-15.3 { + execsql { SELECT 2 IN (SELECT a FROM t1) } + } {1} +} + +# Crash bug reported on the mailing list on 2012-02-23 +# +do_test select1-16.1 { + catchsql {SELECT 1 FROM (SELECT *)} +} {1 {no tables specified}} + +# 2015-04-17: assertion fix. +do_catchsql_test select1-16.2 { + SELECT 1 FROM sqlite_master LIMIT 1,#1; +} {1 {near "#1": syntax error}} + +# 2019-01-16 Chromium bug 922312 +# Sorting with a LIMIT clause using SRT_EphemTab and SRT_Table +# +do_execsql_test select1-17.1 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); + CREATE TABLE t2(y,z); INSERT INTO t2 VALUES(2,3); + CREATE INDEX t2y ON t2(y); + SELECT * FROM t1,(SELECT * FROM t2 WHERE y=2 ORDER BY y,z); +} {1 2 3} +do_execsql_test select1-17.2 { + SELECT * FROM t1,(SELECT * FROM t2 WHERE y=2 ORDER BY y,z LIMIT 4); +} {1 2 3} +do_execsql_test select1-17.3 { + SELECT * FROM t1,(SELECT * FROM t2 WHERE y=2 + UNION ALL SELECT * FROM t2 WHERE y=3 ORDER BY y,z LIMIT 4); +} {1 2 3} + +# 2019-07-24 Ticket https://sqlite.org/src/tktview/c52b09c7f38903b1311 +# +do_execsql_test select1-18.1 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + CREATE TABLE t1(c); + CREATE TABLE t2(x PRIMARY KEY, y); + INSERT INTO t1(c) VALUES(123); + INSERT INTO t2(x) VALUES(123); + SELECT x FROM t2, t1 WHERE x BETWEEN c AND null OR x AND + x IN ((SELECT x FROM (SELECT x FROM t2, t1 + WHERE x BETWEEN (SELECT x FROM (SELECT x COLLATE rtrim + FROM t2, t1 WHERE x BETWEEN c AND null + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null + OR x AND x IN (c)) AND null + OR NOT EXISTS(SELECT -4.81 FROM t1, t2 WHERE x BETWEEN c AND null + OR x AND x IN ((SELECT x FROM (SELECT x FROM t2, t1 + WHERE x BETWEEN (SELECT x FROM (SELECT x BETWEEN c AND null + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null + OR x AND x IN (c)) AND null + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null + OR x AND x IN (c)))) AND x IN (c) + ), t1 WHERE x BETWEEN c AND null + OR x AND x IN (c))); +} {} +do_execsql_test select1-18.2 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + CREATE TABLE t1(c); + CREATE TABLE t2(x PRIMARY KEY, y); + INSERT INTO t1(c) VALUES(123); + INSERT INTO t2(x) VALUES(123); + SELECT x FROM t2, t1 WHERE x BETWEEN c AND (c+1) OR x AND + x IN ((SELECT x FROM (SELECT x FROM t2, t1 + WHERE x BETWEEN (SELECT x FROM (SELECT x COLLATE rtrim + FROM t2, t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c)) AND (c+1) + OR NOT EXISTS(SELECT -4.81 FROM t1, t2 WHERE x BETWEEN c AND (c+1) + OR x AND x IN ((SELECT x FROM (SELECT x FROM t2, t1 + WHERE x BETWEEN (SELECT x FROM (SELECT x BETWEEN c AND (c+1) + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c)) AND (c+1) + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c)))) AND x IN (c) + ), t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c))); +} {123} +do_execsql_test select1-18.3 { + SELECT 1 FROM t1 WHERE ( + SELECT 2 FROM t2 WHERE ( + SELECT 3 FROM ( + SELECT x FROM t2 WHERE x=c OR x=(SELECT x FROM (VALUES(0))) + ) WHERE x>c OR x=c + ) + ); +} {1} +do_execsql_test select1-18.4 { + SELECT 1 FROM t1, t2 WHERE ( + SELECT 3 FROM ( + SELECT x FROM t2 WHERE x=c OR x=(SELECT x FROM (VALUES(0))) + ) WHERE x>c OR x=c + ); +} {1} + +# 2019-12-17 gramfuzz find +# +do_execsql_test select1-19.10 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x); +} {} +do_catchsql_test select1-19.20 { + INSERT INTO t1 + SELECT 1,2,3,4,5,6,7 + UNION ALL SELECT 1,2,3,4,5,6,7 + ORDER BY 1; +} {1 {table t1 has 1 columns but 7 values were supplied}} +do_catchsql_test select1-19.21 { + INSERT INTO t1 + SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + ORDER BY 1; +} {1 {table t1 has 1 columns but 15 values were supplied}} + +# 2020-01-01 Found by Yongheng's fuzzer +# +reset_db +do_execsql_test select1-20.10 { + CREATE TABLE t1 ( + a INTEGER PRIMARY KEY, + b AS('Y') UNIQUE + ); + INSERT INTO t1(a) VALUES (10); + SELECT * FROM t1 JOIN t1 USING(a,b) + WHERE ((SELECT t1.a FROM t1 AS x GROUP BY b) AND b=0) + OR a = 10; +} {10 Y} +do_execsql_test select1-20.20 { + SELECT ifnull(a, max((SELECT 123))), count(a) FROM t1 ; +} {10 1} + +# 2020-10-02 dbsqlfuzz find +reset_db +do_execsql_test select1-21.1 { + CREATE TABLE t1(a IMTEGES PRIMARY KEY,R); + CREATE TABLE t2(x UNIQUE); + CREATE VIEW v1a(z,y) AS SELECT x IS NULL, x FROM t2; + SELECT a,(+a)b,(+a)b,(+a)b,NOT EXISTS(SELECT null FROM t2),CASE z WHEN 487 THEN 992 WHEN 391 THEN 203 WHEN 10 THEN '?k3 AND f1<5} + set r {} + db eval $sql data { + set f1 $data(f1) + lappend r $f1: + set sql2 "SELECT f2 FROM tbl1 WHERE f1=$f1 ORDER BY f2" + db eval $sql2 d2 { + lappend r $d2(f2) + } + } + set r +} {4: 2 3 4} +unset data + +# Create a largish table. Do this twice, once using the TCL cache and once +# without. Compare the performance to make sure things go faster with the +# cache turned on. +# +ifcapable tclvar { + do_test select2-2.0.1 { + set t1 [time { + execsql {CREATE TABLE tbl2(f1 int, f2 int, f3 int); BEGIN;} + for {set i 1} {$i<=30000} {incr i} { + set i2 [expr {$i*2}] + set i3 [expr {$i*3}] + db eval {INSERT INTO tbl2 VALUES($i,$i2,$i3)} + } + execsql {COMMIT} + }] + list + } {} + puts "time with cache: $::t1" +} +catch {execsql {DROP TABLE tbl2}} +do_test select2-2.0.2 { + set t2 [time { + execsql {CREATE TABLE tbl2(f1 int, f2 int, f3 int); BEGIN;} + for {set i 1} {$i<=30000} {incr i} { + set i2 [expr {$i*2}] + set i3 [expr {$i*3}] + execsql "INSERT INTO tbl2 VALUES($i,$i2,$i3)" + } + execsql {COMMIT} + }] + list +} {} +puts "time without cache: $t2" +#ifcapable tclvar { +# do_test select2-2.0.3 { +# expr {[lindex $t1 0]<[lindex $t2 0]} +# } 1 +#} + +do_test select2-2.1 { + execsql {SELECT count(*) FROM tbl2} +} {30000} +do_test select2-2.2 { + execsql {SELECT count(*) FROM tbl2 WHERE f2>1000} +} {29500} + +do_test select2-3.1 { + execsql {SELECT f1 FROM tbl2 WHERE 1000=f2} +} {500} + +do_test select2-3.2a { + execsql {CREATE INDEX idx1 ON tbl2(f2)} +} {} +do_test select2-3.2b { + execsql {SELECT f1 FROM tbl2 WHERE 1000=f2} +} {500} +do_test select2-3.2c { + execsql {SELECT f1 FROM tbl2 WHERE f2=1000} +} {500} +do_test select2-3.2d { + set sqlite_search_count 0 + execsql {SELECT * FROM tbl2 WHERE 1000=f2} + set sqlite_search_count +} {3} +do_test select2-3.2e { + set sqlite_search_count 0 + execsql {SELECT * FROM tbl2 WHERE f2=1000} + set sqlite_search_count +} {3} + +# Make sure queries run faster with an index than without +# +do_test select2-3.3 { + execsql {DROP INDEX idx1} + set sqlite_search_count 0 + execsql {SELECT f1 FROM tbl2 WHERE f2==2000} + set sqlite_search_count +} {29999} + +# Make sure we can optimize functions in the WHERE clause that +# use fields from two or more different table. (Bug #6) +# +do_test select2-4.1 { + execsql { + CREATE TABLE aa(a); + CREATE TABLE bb(b); + INSERT INTO aa VALUES(1); + INSERT INTO aa VALUES(3); + INSERT INTO bb VALUES(2); + INSERT INTO bb VALUES(4); + SELECT * FROM aa, bb WHERE max(a,b)>2; + } +} {1 4 3 2 3 4} +do_test select2-4.2 { + execsql { + INSERT INTO bb VALUES(0); + SELECT * FROM aa CROSS JOIN bb WHERE b; + } +} {1 2 1 4 3 2 3 4} +do_test select2-4.3 { + execsql { + SELECT * FROM aa CROSS JOIN bb WHERE NOT b; + } +} {1 0 3 0} +do_test select2-4.4 { + execsql { + SELECT * FROM aa, bb WHERE min(a,b); + } +} {1 2 1 4 3 2 3 4} +do_test select2-4.5 { + execsql { + SELECT * FROM aa, bb WHERE NOT min(a,b); + } +} {1 0 3 0} +do_test select2-4.6 { + execsql { + SELECT * FROM aa, bb WHERE CASE WHEN a=b-1 THEN 1 END; + } +} {1 2 3 4} +do_test select2-4.7 { + execsql { + SELECT * FROM aa, bb WHERE CASE WHEN a=b-1 THEN 0 ELSE 1 END; + } +} {1 4 1 0 3 2 3 0} + +finish_test diff --git a/testing/sqlite3/select3.test b/testing/sqlite3/select3.test new file mode 100644 index 000000000..ab16ab9fd --- /dev/null +++ b/testing/sqlite3/select3.test @@ -0,0 +1,436 @@ +# 2001 September 15 +# +# 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 aggregate functions and the +# GROUP BY and HAVING clauses of SELECT statements. +# +# $Id: select3.test,v 1.23 2008/01/16 18:20:42 danielk1977 Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Build some test data +# +do_test select3-1.0 { + execsql { + CREATE TABLE t1(n int, log int); + BEGIN; + } + for {set i 1} {$i<32} {incr i} { + for {set j 0} {(1<<$j)<$i} {incr j} {} + execsql "INSERT INTO t1 VALUES($i,$j)" + } + execsql { + COMMIT + } + execsql {SELECT DISTINCT log FROM t1 ORDER BY log} +} {0 1 2 3 4 5} + +# Basic aggregate functions. +# +do_test select3-1.1 { + execsql {SELECT count(*) FROM t1} +} {31} +do_test select3-1.2 { + execsql { + SELECT min(n),min(log),max(n),max(log),sum(n),sum(log),avg(n),avg(log) + FROM t1 + } +} {1 0 31 5 496 124 16.0 4.0} +do_test select3-1.3 { + execsql {SELECT max(n)/avg(n), max(log)/avg(log) FROM t1} +} {1.9375 1.25} + +# Try some basic GROUP BY clauses +# +do_test select3-2.1 { + execsql {SELECT log, count(*) FROM t1 GROUP BY log ORDER BY log} +} {0 1 1 1 2 2 3 4 4 8 5 15} +do_test select3-2.2 { + execsql {SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log} +} {0 1 1 2 2 3 3 5 4 9 5 17} +do_test select3-2.3.1 { + execsql {SELECT log, avg(n) FROM t1 GROUP BY log ORDER BY log} +} {0 1.0 1 2.0 2 3.5 3 6.5 4 12.5 5 24.0} +do_test select3-2.3.2 { + execsql {SELECT log, avg(n)+1 FROM t1 GROUP BY log ORDER BY log} +} {0 2.0 1 3.0 2 4.5 3 7.5 4 13.5 5 25.0} +do_test select3-2.4 { + execsql {SELECT log, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log} +} {0 0.0 1 0.0 2 0.5 3 1.5 4 3.5 5 7.0} +do_test select3-2.5 { + execsql {SELECT log*2+1, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log} +} {1 0.0 3 0.0 5 0.5 7 1.5 9 3.5 11 7.0} +do_test select3-2.6 { + execsql { + SELECT log*2+1 as x, count(*) FROM t1 GROUP BY x ORDER BY x + } +} {1 1 3 1 5 2 7 4 9 8 11 15} +do_test select3-2.7 { + execsql { + SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY y, x + } +} {1 1 3 1 5 2 7 4 9 8 11 15} +do_test select3-2.8 { + execsql { + SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY 10-(x+y) + } +} {11 15 9 8 7 4 5 2 3 1 1 1} +#do_test select3-2.9 { +# catchsql { +# SELECT log, count(*) FROM t1 GROUP BY 'x' ORDER BY log; +# } +#} {1 {GROUP BY terms must not be non-integer constants}} +do_test select3-2.10 { + catchsql { + SELECT log, count(*) FROM t1 GROUP BY 0 ORDER BY log; + } +} {1 {1st GROUP BY term out of range - should be between 1 and 2}} +do_test select3-2.11 { + catchsql { + SELECT log, count(*) FROM t1 GROUP BY 3 ORDER BY log; + } +} {1 {1st GROUP BY term out of range - should be between 1 and 2}} +do_test select3-2.12 { + catchsql { + SELECT log, count(*) FROM t1 GROUP BY 1 ORDER BY log; + } +} {0 {0 1 1 1 2 2 3 4 4 8 5 15}} + +# Cannot have an empty GROUP BY +do_test select3-2.13 { + catchsql { + SELECT log, count(*) FROM t1 GROUP BY ORDER BY log; + } +} {1 {near "ORDER": syntax error}} +do_test select3-2.14 { + catchsql { + SELECT log, count(*) FROM t1 GROUP BY; + } +} {1 {near ";": syntax error}} + +# Cannot have a HAVING without a GROUP BY +# +# Update: As of 3.39.0, you can. +# +do_execsql_test select3-3.1 { + SELECT log, count(*) FROM t1 HAVING log>=4 +} {} +do_execsql_test select3-3.2 { + SELECT count(*) FROM t1 HAVING log>=4 +} {} +do_execsql_test select3-3.3 { + SELECT count(*) FROM t1 HAVING log!=400 +} {31} + +# Toss in some HAVING clauses +# +do_test select3-4.1 { + execsql {SELECT log, count(*) FROM t1 GROUP BY log HAVING log>=4 ORDER BY log} +} {4 8 5 15} +do_test select3-4.2 { + execsql { + SELECT log, count(*) FROM t1 + GROUP BY log + HAVING count(*)>=4 + ORDER BY log + } +} {3 4 4 8 5 15} +do_test select3-4.3 { + execsql { + SELECT log, count(*) FROM t1 + GROUP BY log + HAVING count(*)>=4 + ORDER BY max(n)+0 + } +} {3 4 4 8 5 15} +do_test select3-4.4 { + execsql { + SELECT log AS x, count(*) AS y FROM t1 + GROUP BY x + HAVING y>=4 + ORDER BY max(n)+0 + } +} {3 4 4 8 5 15} +do_test select3-4.5 { + execsql { + SELECT log AS x FROM t1 + GROUP BY x + HAVING count(*)>=4 + ORDER BY max(n)+0 + } +} {3 4 5} + +do_test select3-5.1 { + execsql { + SELECT log, count(*), avg(n), max(n+log*2) FROM t1 + GROUP BY log + ORDER BY max(n+log*2)+0, avg(n)+0 + } +} {0 1 1.0 1 1 1 2.0 4 2 2 3.5 8 3 4 6.5 14 4 8 12.5 24 5 15 24.0 41} +do_test select3-5.2 { + execsql { + SELECT log, count(*), avg(n), max(n+log*2) FROM t1 + GROUP BY log + ORDER BY max(n+log*2)+0, min(log,avg(n))+0 + } +} {0 1 1.0 1 1 1 2.0 4 2 2 3.5 8 3 4 6.5 14 4 8 12.5 24 5 15 24.0 41} + +# Test sorting of GROUP BY results in the presence of an index +# on the GROUP BY column. +# +do_test select3-6.1 { + execsql { + SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log; + } +} {0 1 1 2 2 3 3 5 4 9 5 17} +do_test select3-6.2 { + execsql { + SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log DESC; + } +} {5 17 4 9 3 5 2 3 1 2 0 1} +do_test select3-6.3 { + execsql { + SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1; + } +} {0 1 1 2 2 3 3 5 4 9 5 17} +do_test select3-6.4 { + execsql { + SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1 DESC; + } +} {5 17 4 9 3 5 2 3 1 2 0 1} +do_test select3-6.5 { + execsql { + CREATE INDEX i1 ON t1(log); + SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log; + } +} {0 1 1 2 2 3 3 5 4 9 5 17} +do_test select3-6.6 { + execsql { + SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log DESC; + } +} {5 17 4 9 3 5 2 3 1 2 0 1} +do_test select3-6.7 { + execsql { + SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1; + } +} {0 1 1 2 2 3 3 5 4 9 5 17} +do_test select3-6.8 { + execsql { + SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1 DESC; + } +} {5 17 4 9 3 5 2 3 1 2 0 1} + +# Sometimes an aggregate query can return no rows at all. +# +do_test select3-7.1 { + execsql { + CREATE TABLE t2(a,b); + INSERT INTO t2 VALUES(1,2); + SELECT a, sum(b) FROM t2 WHERE b=5 GROUP BY a; + } +} {} +do_test select3-7.2 { + execsql { + SELECT a, sum(b) FROM t2 WHERE b=5; + } +} {{} {}} + +# If a table column is of type REAL but we are storing integer values +# in it, the values are stored as integers to take up less space. The +# values are converted by to REAL as they are read out of the table. +# Make sure the GROUP BY clause does this conversion correctly. +# Ticket #2251. +# +do_test select3-8.1 { + execsql { + CREATE TABLE A ( + A1 DOUBLE, + A2 VARCHAR COLLATE NOCASE, + A3 DOUBLE + ); + INSERT INTO A VALUES(39136,'ABC',1201900000); + INSERT INTO A VALUES(39136,'ABC',1207000000); + SELECT typeof(sum(a3)) FROM a; + } +} {real} +do_test select3-8.2 { + execsql { + SELECT typeof(sum(a3)) FROM a GROUP BY a1; + } +} {real} + +# 2019-05-09 ticket https://sqlite.org/src/tktview/6c1d3febc00b22d457c7 +# +unset -nocomplain x +foreach {id x} { + 100 127 + 101 128 + 102 -127 + 103 -128 + 104 -129 + 110 32767 + 111 32768 + 112 -32767 + 113 -32768 + 114 -32769 + 120 2147483647 + 121 2147483648 + 122 -2147483647 + 123 -2147483648 + 124 -2147483649 + 130 140737488355327 + 131 140737488355328 + 132 -140737488355327 + 133 -140737488355328 + 134 -140737488355329 + 140 9223372036854775807 + 141 -9223372036854775807 + 142 -9223372036854775808 + 143 9223372036854775806 + 144 9223372036854775805 + 145 -9223372036854775806 + 146 -9223372036854775805 + +} { + set x [expr {$x+0}] + do_execsql_test select3-8.$id { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1 (c0, c1 REAL PRIMARY KEY); + INSERT INTO t1(c0, c1) VALUES (0, $x), (0, 0); + UPDATE t1 SET c0 = NULL; + UPDATE OR REPLACE t1 SET c1 = 1; + SELECT DISTINCT * FROM t1 WHERE (t1.c0 IS NULL); + PRAGMA integrity_check; + } {{} 1.0 ok} +} + +# 2020-03-10 ticket e0c2ad1aa8a9c691 +reset_db +do_execsql_test select3-9.100 { + CREATE TABLE t0(c0 REAL, c1 REAL GENERATED ALWAYS AS (c0)); + INSERT INTO t0(c0) VALUES (1); + SELECT * FROM t0 GROUP BY c0; +} {1.0 1.0} + +reset_db +do_execsql_test select3.10.100 { + CREATE TABLE t1(a, b); + CREATE TABLE t2(c, d); + SELECT max(t1.a), + (SELECT 'xyz' FROM (SELECT * FROM t2 WHERE 0) WHERE t1.b=1) + FROM t1; +} {{} {}} + +#------------------------------------------------------------------------- +# dbsqlfuzz crash-8e17857db2c5a9294c975123ac807156a6559f13.txt +# Associated with the flatten-left-join branch circa 2022-06-23. +# +foreach {tn sql} { + 1 { + CREATE TABLE t1(a TEXT); + CREATE TABLE t2(x INT); + CREATE INDEX t2x ON t2(x); + INSERT INTO t1 VALUES('abc'); + } + 2 { + CREATE TABLE t1(a TEXT); + CREATE TABLE t2(x INT); + INSERT INTO t1 VALUES('abc'); + } + 3 { + CREATE TABLE t1(a TEXT); + CREATE TABLE t2(x INT); + INSERT INTO t1 VALUES('abc'); + PRAGMA automatic_index=OFF; + } +} { + reset_db + do_execsql_test select3-11.$tn.1 $sql + do_execsql_test select3.11.$tn.2 { + SELECT max(a), val FROM t1 LEFT JOIN ( + SELECT 'constant' AS val FROM t2 WHERE x=1234 + ) + } {abc {}} + do_execsql_test select3.11.$tn.3 { + INSERT INTO t2 VALUES(123); + SELECT max(a), val FROM t1 LEFT JOIN ( + SELECT 'constant' AS val FROM t2 WHERE x=1234 + ) + } {abc {}} + do_execsql_test select3.11.$tn.4 { + INSERT INTO t2 VALUES(1234); + SELECT max(a), val FROM t1 LEFT JOIN ( + SELECT 'constant' AS val FROM t2 WHERE x=1234 + ) + } {abc constant} +} + +reset_db +do_execsql_test 12.0 { + CREATE TABLE t1(a); + CREATE TABLE t2(x); +} +do_execsql_test 12.1 { + SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a; +} +do_execsql_test 12.2 { + INSERT INTO t1 VALUES(1), (1), (2), (3); + SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a; +} { + 0 {} + 0 {} + 0 {} +} +do_execsql_test 12.3 { + INSERT INTO t2 VALUES(45); + SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a; +} { + 2 59 + 1 59 + 1 59 +} +do_execsql_test 12.4 { + INSERT INTO t2 VALUES(210); + SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a; +} { + 4 59 + 2 59 + 2 59 +} +do_execsql_test 12.5 { + INSERT INTO t2 VALUES(NULL); + SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a; +} { + 4 59 + 2 59 + 2 59 +} +do_execsql_test 12.6 { + DELETE FROM t2; + DELETE FROM t1; + INSERT INTO t1 VALUES('value'); + INSERT INTO t2 VALUES('hello'); +} {} +do_execsql_test 12.7 { + SELECT group_concat(x), m FROM t1 + LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a; +} { + hello 59 +} +do_execsql_test 12.8 { + SELECT group_concat(x), m, n FROM t1 + LEFT JOIN (SELECT x, 59 AS m, 60 AS n FROM t2) GROUP BY a; +} { + hello 59 60 +} + +finish_test diff --git a/testing/sqlite3/select4.test b/testing/sqlite3/select4.test new file mode 100644 index 000000000..890897f2a --- /dev/null +++ b/testing/sqlite3/select4.test @@ -0,0 +1,1043 @@ +# 2001 September 15 +# +# 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 UNION, INTERSECT and EXCEPT operators +# in SELECT statements. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Most tests in this file depend on compound-select. But there are a couple +# right at the end that test DISTINCT, so we cannot omit the entire file. +# +ifcapable compound { + +# Build some test data +# +execsql { + CREATE TABLE t1(n int, log int); + BEGIN; +} +for {set i 1} {$i<32} {incr i} { + for {set j 0} {(1<<$j)<$i} {incr j} {} + execsql "INSERT INTO t1 VALUES($i,$j)" +} +execsql { + COMMIT; +} + +do_test select4-1.0 { + execsql {SELECT DISTINCT log FROM t1 ORDER BY log} +} {0 1 2 3 4 5} + +# Union All operator +# +do_test select4-1.1a { + lsort [execsql {SELECT DISTINCT log FROM t1}] +} {0 1 2 3 4 5} +do_test select4-1.1b { + lsort [execsql {SELECT n FROM t1 WHERE log=3}] +} {5 6 7 8} +do_test select4-1.1c { + execsql { + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + } +} {0 1 2 3 4 5 5 6 7 8} +do_test select4-1.1d { + execsql { + CREATE TABLE t2 AS + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + SELECT * FROM t2; + } +} {0 1 2 3 4 5 5 6 7 8} +execsql {DROP TABLE t2} +do_test select4-1.1e { + execsql { + CREATE TABLE t2 AS + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY log DESC; + SELECT * FROM t2; + } +} {8 7 6 5 5 4 3 2 1 0} +execsql {DROP TABLE t2} +do_test select4-1.1f { + execsql { + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=2 + } +} {0 1 2 3 4 5 3 4} +do_test select4-1.1g { + execsql { + CREATE TABLE t2 AS + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=2; + SELECT * FROM t2; + } +} {0 1 2 3 4 5 3 4} +execsql {DROP TABLE t2} +ifcapable subquery { + do_test select4-1.2 { + execsql { + SELECT log FROM t1 WHERE n IN + (SELECT DISTINCT log FROM t1 UNION ALL + SELECT n FROM t1 WHERE log=3) + ORDER BY log; + } + } {0 1 2 2 3 3 3 3} +} + +# EVIDENCE-OF: R-02644-22131 In a compound SELECT statement, only the +# last or right-most simple SELECT may have an ORDER BY clause. +# +do_test select4-1.3 { + set v [catch {execsql { + SELECT DISTINCT log FROM t1 ORDER BY log + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + }} msg] + lappend v $msg +} {1 {ORDER BY clause should come after UNION ALL not before}} +do_catchsql_test select4-1.4 { + SELECT (VALUES(0) INTERSECT SELECT(0) UNION SELECT(0) ORDER BY 1 UNION + SELECT 0 UNION SELECT 0 ORDER BY 1); +} {1 {ORDER BY clause should come after UNION not before}} + +# Union operator +# +do_test select4-2.1 { + execsql { + SELECT DISTINCT log FROM t1 + UNION + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + } +} {0 1 2 3 4 5 6 7 8} +ifcapable subquery { + do_test select4-2.2 { + execsql { + SELECT log FROM t1 WHERE n IN + (SELECT DISTINCT log FROM t1 UNION + SELECT n FROM t1 WHERE log=3) + ORDER BY log; + } + } {0 1 2 2 3 3 3 3} +} +do_test select4-2.3 { + set v [catch {execsql { + SELECT DISTINCT log FROM t1 ORDER BY log + UNION + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + }} msg] + lappend v $msg +} {1 {ORDER BY clause should come after UNION not before}} +do_test select4-2.4 { + set v [catch {execsql { + SELECT 0 ORDER BY (SELECT 0) UNION SELECT 0; + }} msg] + lappend v $msg +} {1 {ORDER BY clause should come after UNION not before}} +do_execsql_test select4-2.5 { + SELECT 123 AS x ORDER BY (SELECT x ORDER BY 1); +} {123} + +# Except operator +# +do_test select4-3.1.1 { + execsql { + SELECT DISTINCT log FROM t1 + EXCEPT + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + } +} {0 1 2 3 4} +do_test select4-3.1.2 { + execsql { + CREATE TABLE t2 AS + SELECT DISTINCT log FROM t1 + EXCEPT + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + SELECT * FROM t2; + } +} {0 1 2 3 4} +execsql {DROP TABLE t2} +do_test select4-3.1.3 { + execsql { + CREATE TABLE t2 AS + SELECT DISTINCT log FROM t1 + EXCEPT + SELECT n FROM t1 WHERE log=3 + ORDER BY log DESC; + SELECT * FROM t2; + } +} {4 3 2 1 0} +execsql {DROP TABLE t2} +ifcapable subquery { + do_test select4-3.2 { + execsql { + SELECT log FROM t1 WHERE n IN + (SELECT DISTINCT log FROM t1 EXCEPT + SELECT n FROM t1 WHERE log=3) + ORDER BY log; + } + } {0 1 2 2} +} +do_test select4-3.3 { + set v [catch {execsql { + SELECT DISTINCT log FROM t1 ORDER BY log + EXCEPT + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + }} msg] + lappend v $msg +} {1 {ORDER BY clause should come after EXCEPT not before}} + +# Intersect operator +# +do_test select4-4.1.1 { + execsql { + SELECT DISTINCT log FROM t1 + INTERSECT + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + } +} {5} + +do_test select4-4.1.2 { + execsql { + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT 6 + INTERSECT + SELECT n FROM t1 WHERE log=3 + ORDER BY t1.log; + } +} {5 6} + +do_test select4-4.1.3 { + execsql { + CREATE TABLE t2 AS + SELECT DISTINCT log FROM t1 UNION ALL SELECT 6 + INTERSECT + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + SELECT * FROM t2; + } +} {5 6} +execsql {DROP TABLE t2} +do_test select4-4.1.4 { + execsql { + CREATE TABLE t2 AS + SELECT DISTINCT log FROM t1 UNION ALL SELECT 6 + INTERSECT + SELECT n FROM t1 WHERE log=3 + ORDER BY log DESC; + SELECT * FROM t2; + } +} {6 5} +execsql {DROP TABLE t2} +ifcapable subquery { + do_test select4-4.2 { + execsql { + SELECT log FROM t1 WHERE n IN + (SELECT DISTINCT log FROM t1 INTERSECT + SELECT n FROM t1 WHERE log=3) + ORDER BY log; + } + } {3} +} +do_test select4-4.3 { + set v [catch {execsql { + SELECT DISTINCT log FROM t1 ORDER BY log + INTERSECT + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + }} msg] + lappend v $msg +} {1 {ORDER BY clause should come after INTERSECT not before}} +do_catchsql_test select4-4.4 { + SELECT 3 IN ( + SELECT 0 ORDER BY 1 + INTERSECT + SELECT 1 + INTERSECT + SELECT 2 + ORDER BY 1 + ); +} {1 {ORDER BY clause should come after INTERSECT not before}} + +# Various error messages while processing UNION or INTERSECT +# +do_test select4-5.1 { + set v [catch {execsql { + SELECT DISTINCT log FROM t2 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + }} msg] + lappend v $msg +} {1 {no such table: t2}} +do_test select4-5.2 { + set v [catch {execsql { + SELECT DISTINCT log AS "xyzzy" FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY xyzzy; + }} msg] + lappend v $msg +} {0 {0 1 2 3 4 5 5 6 7 8}} +do_test select4-5.2b { + set v [catch {execsql { + SELECT DISTINCT log AS xyzzy FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY "xyzzy"; + }} msg] + lappend v $msg +} {0 {0 1 2 3 4 5 5 6 7 8}} +do_test select4-5.2c { + set v [catch {execsql { + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY "xyzzy"; + }} msg] + lappend v $msg +} {1 {1st ORDER BY term does not match any column in the result set}} +do_test select4-5.2d { + set v [catch {execsql { + SELECT DISTINCT log FROM t1 + INTERSECT + SELECT n FROM t1 WHERE log=3 + ORDER BY "xyzzy"; + }} msg] + lappend v $msg +} {1 {1st ORDER BY term does not match any column in the result set}} +do_test select4-5.2e { + set v [catch {execsql { + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY n; + }} msg] + lappend v $msg +} {0 {0 1 2 3 4 5 5 6 7 8}} +do_test select4-5.2f { + catchsql { + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + } +} {0 {0 1 2 3 4 5 5 6 7 8}} +do_test select4-5.2g { + catchsql { + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY 1; + } +} {0 {0 1 2 3 4 5 5 6 7 8}} +do_test select4-5.2h { + catchsql { + SELECT DISTINCT log FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY 2; + } +} {1 {1st ORDER BY term out of range - should be between 1 and 1}} +do_test select4-5.2i { + catchsql { + SELECT DISTINCT 1, log FROM t1 + UNION ALL + SELECT 2, n FROM t1 WHERE log=3 + ORDER BY 2, 1; + } +} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}} +do_test select4-5.2j { + catchsql { + SELECT DISTINCT 1, log FROM t1 + UNION ALL + SELECT 2, n FROM t1 WHERE log=3 + ORDER BY 1, 2 DESC; + } +} {0 {1 5 1 4 1 3 1 2 1 1 1 0 2 8 2 7 2 6 2 5}} +do_test select4-5.2k { + catchsql { + SELECT DISTINCT 1, log FROM t1 + UNION ALL + SELECT 2, n FROM t1 WHERE log=3 + ORDER BY n, 1; + } +} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}} +do_test select4-5.3 { + set v [catch {execsql { + SELECT DISTINCT log, n FROM t1 + UNION ALL + SELECT n FROM t1 WHERE log=3 + ORDER BY log; + }} msg] + lappend v $msg +} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}} +do_test select4-5.3-3807-1 { + catchsql { + SELECT 1 UNION SELECT 2, 3 UNION SELECT 4, 5 ORDER BY 1; + } +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} +do_test select4-5.4 { + set v [catch {execsql { + SELECT log FROM t1 WHERE n=2 + UNION ALL + SELECT log FROM t1 WHERE n=3 + UNION ALL + SELECT log FROM t1 WHERE n=4 + UNION ALL + SELECT log FROM t1 WHERE n=5 + ORDER BY log; + }} msg] + lappend v $msg +} {0 {1 2 2 3}} + +do_test select4-6.1 { + execsql { + SELECT log, count(*) as cnt FROM t1 GROUP BY log + UNION + SELECT log, n FROM t1 WHERE n=7 + ORDER BY cnt, log; + } +} {0 1 1 1 2 2 3 4 3 7 4 8 5 15} +do_test select4-6.2 { + execsql { + SELECT log, count(*) FROM t1 GROUP BY log + UNION + SELECT log, n FROM t1 WHERE n=7 + ORDER BY count(*), log; + } +} {0 1 1 1 2 2 3 4 3 7 4 8 5 15} + +# NULLs are indistinct for the UNION operator. +# Make sure the UNION operator recognizes this +# +do_test select4-6.3 { + execsql { + SELECT NULL UNION SELECT NULL UNION + SELECT 1 UNION SELECT 2 AS 'x' + ORDER BY x; + } +} {{} 1 2} +do_test select4-6.3.1 { + execsql { + SELECT NULL UNION ALL SELECT NULL UNION ALL + SELECT 1 UNION ALL SELECT 2 AS 'x' + ORDER BY x; + } +} {{} {} 1 2} + +# Make sure the DISTINCT keyword treats NULLs as indistinct. +# +ifcapable subquery { + do_test select4-6.4 { + execsql { + SELECT * FROM ( + SELECT NULL, 1 UNION ALL SELECT NULL, 1 + ); + } + } {{} 1 {} 1} + do_test select4-6.5 { + execsql { + SELECT DISTINCT * FROM ( + SELECT NULL, 1 UNION ALL SELECT NULL, 1 + ); + } + } {{} 1} + do_test select4-6.6 { + execsql { + SELECT DISTINCT * FROM ( + SELECT 1,2 UNION ALL SELECT 1,2 + ); + } + } {1 2} +} + +# Test distinctness of NULL in other ways. +# +do_test select4-6.7 { + execsql { + SELECT NULL EXCEPT SELECT NULL + } +} {} + + +# Make sure column names are correct when a compound select appears as +# an expression in the WHERE clause. +# +do_test select4-7.1 { + execsql { + CREATE TABLE t2 AS SELECT log AS 'x', count(*) AS 'y' FROM t1 GROUP BY log; + SELECT * FROM t2 ORDER BY x; + } +} {0 1 1 1 2 2 3 4 4 8 5 15} +ifcapable subquery { + do_test select4-7.2 { + execsql2 { + SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 INTERSECT SELECT x FROM t2) + ORDER BY n + } + } {n 1 log 0 n 2 log 1 n 3 log 2 n 4 log 2 n 5 log 3} + do_test select4-7.3 { + execsql2 { + SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 EXCEPT SELECT x FROM t2) + ORDER BY n LIMIT 2 + } + } {n 6 log 3 n 7 log 3} + do_test select4-7.4 { + execsql2 { + SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 UNION SELECT x FROM t2) + ORDER BY n LIMIT 2 + } + } {n 1 log 0 n 2 log 1} +} ;# ifcapable subquery + +} ;# ifcapable compound + +# Make sure DISTINCT works appropriately on TEXT and NUMERIC columns. +do_test select4-8.1 { + execsql { + BEGIN; + CREATE TABLE t3(a text, b float, c text); + INSERT INTO t3 VALUES(1, 1.1, '1.1'); + INSERT INTO t3 VALUES(2, 1.10, '1.10'); + INSERT INTO t3 VALUES(3, 1.10, '1.1'); + INSERT INTO t3 VALUES(4, 1.1, '1.10'); + INSERT INTO t3 VALUES(5, 1.2, '1.2'); + INSERT INTO t3 VALUES(6, 1.3, '1.3'); + COMMIT; + } + execsql { + SELECT DISTINCT b FROM t3 ORDER BY c; + } +} {1.1 1.2 1.3} +do_test select4-8.2 { + execsql { + SELECT DISTINCT c FROM t3 ORDER BY c; + } +} {1.1 1.10 1.2 1.3} + +# Make sure the names of columns are taken from the right-most subquery +# right in a compound query. Ticket #1721 +# +ifcapable compound { + +do_test select4-9.1 { + execsql2 { + SELECT x, y FROM t2 UNION SELECT a, b FROM t3 ORDER BY x LIMIT 1 + } +} {x 0 y 1} +do_test select4-9.2 { + execsql2 { + SELECT x, y FROM t2 UNION ALL SELECT a, b FROM t3 ORDER BY x LIMIT 1 + } +} {x 0 y 1} +do_test select4-9.3 { + execsql2 { + SELECT x, y FROM t2 EXCEPT SELECT a, b FROM t3 ORDER BY x LIMIT 1 + } +} {x 0 y 1} +do_test select4-9.4 { + execsql2 { + SELECT x, y FROM t2 INTERSECT SELECT 0 AS a, 1 AS b; + } +} {x 0 y 1} +do_test select4-9.5 { + execsql2 { + SELECT 0 AS x, 1 AS y + UNION + SELECT 2 AS p, 3 AS q + UNION + SELECT 4 AS a, 5 AS b + ORDER BY x LIMIT 1 + } +} {x 0 y 1} + +ifcapable subquery { +do_test select4-9.6 { + execsql2 { + SELECT * FROM ( + SELECT 0 AS x, 1 AS y + UNION + SELECT 2 AS p, 3 AS q + UNION + SELECT 4 AS a, 5 AS b + ) ORDER BY 1 LIMIT 1; + } +} {x 0 y 1} +do_test select4-9.7 { + execsql2 { + SELECT * FROM ( + SELECT 0 AS x, 1 AS y + UNION + SELECT 2 AS p, 3 AS q + UNION + SELECT 4 AS a, 5 AS b + ) ORDER BY x LIMIT 1; + } +} {x 0 y 1} +} ;# ifcapable subquery + +do_test select4-9.8 { + execsql { + SELECT 0 AS x, 1 AS y + UNION + SELECT 2 AS y, -3 AS x + ORDER BY x LIMIT 1; + } +} {0 1} + +do_test select4-9.9.1 { + execsql2 { + SELECT 1 AS a, 2 AS b UNION ALL SELECT 3 AS b, 4 AS a + } +} {a 1 b 2 a 3 b 4} + +ifcapable subquery { +do_test select4-9.9.2 { + execsql2 { + SELECT * FROM (SELECT 1 AS a, 2 AS b UNION ALL SELECT 3 AS b, 4 AS a) + WHERE b=3 + } +} {} +do_test select4-9.10 { + execsql2 { + SELECT * FROM (SELECT 1 AS a, 2 AS b UNION ALL SELECT 3 AS b, 4 AS a) + WHERE b=2 + } +} {a 1 b 2} +do_test select4-9.11 { + execsql2 { + SELECT * FROM (SELECT 1 AS a, 2 AS b UNION ALL SELECT 3 AS e, 4 AS b) + WHERE b=2 + } +} {a 1 b 2} +do_test select4-9.12 { + execsql2 { + SELECT * FROM (SELECT 1 AS a, 2 AS b UNION ALL SELECT 3 AS e, 4 AS b) + WHERE b>0 + } +} {a 1 b 2 a 3 b 4} +} ;# ifcapable subquery + +# Try combining DISTINCT, LIMIT, and OFFSET. Make sure they all work +# together. +# +do_test select4-10.1 { + execsql { + SELECT DISTINCT log FROM t1 ORDER BY log + } +} {0 1 2 3 4 5} +do_test select4-10.2 { + execsql { + SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 4 + } +} {0 1 2 3} +do_test select4-10.3 { + execsql { + SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 0 + } +} {} +do_test select4-10.4 { + execsql { + SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1 + } +} {0 1 2 3 4 5} +do_test select4-10.5 { + execsql { + SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1 OFFSET 2 + } +} {2 3 4 5} +do_test select4-10.6 { + execsql { + SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 3 OFFSET 2 + } +} {2 3 4} +do_test select4-10.7 { + execsql { + SELECT DISTINCT log FROM t1 ORDER BY +log LIMIT 3 OFFSET 20 + } +} {} +do_test select4-10.8 { + execsql { + SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 0 OFFSET 3 + } +} {} +do_test select4-10.9 { + execsql { + SELECT DISTINCT max(n), log FROM t1 ORDER BY +log; -- LIMIT 2 OFFSET 1 + } +} {31 5} + +# Make sure compound SELECTs with wildly different numbers of columns +# do not cause assertion faults due to register allocation issues. +# +do_test select4-11.1 { + catchsql { + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + UNION + SELECT x FROM t2 + } +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} +do_test select4-11.2 { + catchsql { + SELECT x FROM t2 + UNION + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + } +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} +do_test select4-11.3 { + catchsql { + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + UNION ALL + SELECT x FROM t2 + } +} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}} +do_test select4-11.4 { + catchsql { + SELECT x FROM t2 + UNION ALL + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + } +} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}} +do_test select4-11.5 { + catchsql { + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + EXCEPT + SELECT x FROM t2 + } +} {1 {SELECTs to the left and right of EXCEPT do not have the same number of result columns}} +do_test select4-11.6 { + catchsql { + SELECT x FROM t2 + EXCEPT + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + } +} {1 {SELECTs to the left and right of EXCEPT do not have the same number of result columns}} +do_test select4-11.7 { + catchsql { + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + INTERSECT + SELECT x FROM t2 + } +} {1 {SELECTs to the left and right of INTERSECT do not have the same number of result columns}} +do_test select4-11.8 { + catchsql { + SELECT x FROM t2 + INTERSECT + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + } +} {1 {SELECTs to the left and right of INTERSECT do not have the same number of result columns}} + +do_test select4-11.11 { + catchsql { + SELECT x FROM t2 + UNION + SELECT x FROM t2 + UNION ALL + SELECT x FROM t2 + EXCEPT + SELECT x FROM t2 + INTERSECT + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + } +} {1 {SELECTs to the left and right of INTERSECT do not have the same number of result columns}} +do_test select4-11.12 { + catchsql { + SELECT x FROM t2 + UNION + SELECT x FROM t2 + UNION ALL + SELECT x FROM t2 + EXCEPT + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + EXCEPT + SELECT x FROM t2 + } +} {1 {SELECTs to the left and right of EXCEPT do not have the same number of result columns}} +do_test select4-11.13 { + catchsql { + SELECT x FROM t2 + UNION + SELECT x FROM t2 + UNION ALL + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + UNION ALL + SELECT x FROM t2 + EXCEPT + SELECT x FROM t2 + } +} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}} +do_test select4-11.14 { + catchsql { + SELECT x FROM t2 + UNION + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + UNION + SELECT x FROM t2 + UNION ALL + SELECT x FROM t2 + EXCEPT + SELECT x FROM t2 + } +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} +do_test select4-11.15 { + catchsql { + SELECT x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x FROM t2 + UNION + SELECT x FROM t2 + INTERSECT + SELECT x FROM t2 + UNION ALL + SELECT x FROM t2 + EXCEPT + SELECT x FROM t2 + } +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} +do_test select4-11.16 { + catchsql { + INSERT INTO t2(rowid) VALUES(2) UNION SELECT 3,4 UNION SELECT 5,6 ORDER BY 1; + } +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} + +do_test select4-12.1 { + sqlite3 db2 :memory: + catchsql { + SELECT 1 UNION SELECT 2,3 UNION SELECT 4,5 ORDER BY 1; + } db2 +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} + +} ;# ifcapable compound + + +# Ticket [3557ad65a076c] - Incorrect DISTINCT processing with an +# indexed query using IN. +# +do_test select4-13.1 { + sqlite3 db test.db + db eval { + CREATE TABLE t13(a,b); + INSERT INTO t13 VALUES(1,1); + INSERT INTO t13 VALUES(2,1); + INSERT INTO t13 VALUES(3,1); + INSERT INTO t13 VALUES(2,2); + INSERT INTO t13 VALUES(3,2); + INSERT INTO t13 VALUES(4,2); + CREATE INDEX t13ab ON t13(a,b); + SELECT DISTINCT b from t13 WHERE a IN (1,2,3); + } +} {1 2} + +# 2014-02-18: Make sure compound SELECTs work with VALUES clauses +# +do_execsql_test select4-14.1 { + CREATE TABLE t14(a,b,c); + INSERT INTO t14 VALUES(1,2,3),(4,5,6); + SELECT * FROM t14 INTERSECT VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {1 2 3} +do_execsql_test select4-14.2 { + SELECT * FROM t14 INTERSECT VALUES(1,2,3); +} {1 2 3} +do_execsql_test select4-14.3 { + SELECT * FROM t14 + UNION VALUES(3,2,1),(2,3,1),(1,2,3),(7,8,9),(4,5,6) + UNION SELECT * FROM t14 ORDER BY 1, 2, 3 +} {1 2 3 2 3 1 3 2 1 4 5 6 7 8 9} +do_execsql_test select4-14.4 { + SELECT * FROM t14 + UNION VALUES(3,2,1) + UNION SELECT * FROM t14 ORDER BY 1, 2, 3 +} {1 2 3 3 2 1 4 5 6} +do_execsql_test select4-14.5 { + SELECT * FROM t14 EXCEPT VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {4 5 6} +do_execsql_test select4-14.6 { + SELECT * FROM t14 EXCEPT VALUES(1,2,3) +} {4 5 6} +do_execsql_test select4-14.7 { + SELECT * FROM t14 EXCEPT VALUES(1,2,3) EXCEPT VALUES(4,5,6) +} {} +do_execsql_test select4-14.8 { + SELECT * FROM t14 EXCEPT VALUES('a','b','c') EXCEPT VALUES(4,5,6) +} {1 2 3} +do_execsql_test select4-14.9 { + SELECT * FROM t14 UNION ALL VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {1 2 3 4 5 6 3 2 1 2 3 1 1 2 3 2 1 3} +do_execsql_test select4-14.10 { + SELECT (VALUES(1),(2),(3),(4)) +} {1} +do_execsql_test select4-14.11 { + SELECT (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) +} {1} +do_execsql_test select4-14.12 { + VALUES(1) UNION VALUES(2); +} {1 2} +do_execsql_test select4-14.13 { + VALUES(1),(2),(3) EXCEPT VALUES(2); +} {1 3} +do_execsql_test select4-14.14 { + VALUES(1),(2),(3) EXCEPT VALUES(1),(3); +} {2} +do_execsql_test select4-14.15 { + SELECT * FROM (SELECT 123), (SELECT 456) ON likely(0 OR 1) OR 0; +} {123 456} +do_execsql_test select4-14.16 { + VALUES(1),(2),(3),(4) UNION ALL SELECT 5 LIMIT 99; +} {1 2 3 4 5} +do_execsql_test select4-14.17 { + VALUES(1),(2),(3),(4) UNION ALL SELECT 5 LIMIT 3; +} {1 2 3} + +# Ticket https://sqlite.org/src/info/d06a25c84454a372 +# Incorrect answer due to two co-routines using the same registers and expecting +# those register values to be preserved across a Yield. +# +do_execsql_test select4-15.1 { + DROP TABLE IF EXISTS tx; + CREATE TABLE tx(id INTEGER PRIMARY KEY, a, b); + INSERT INTO tx(a,b) VALUES(33,456); + INSERT INTO tx(a,b) VALUES(33,789); + + SELECT DISTINCT t0.id, t0.a, t0.b + FROM tx AS t0, tx AS t1 + WHERE t0.a=t1.a AND t1.a=33 AND t0.b=456 + UNION + SELECT DISTINCT t0.id, t0.a, t0.b + FROM tx AS t0, tx AS t1 + WHERE t0.a=t1.a AND t1.a=33 AND t0.b=789 + ORDER BY 1; +} {1 33 456 2 33 789} + +# Enhancement (2016-03-15): Use a co-routine for subqueries if the +# subquery is guaranteed to be the outer-most query +# +do_execsql_test select4-16.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z, + PRIMARY KEY(a,b DESC)) WITHOUT ROWID; + + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) + INSERT INTO t1(a,b,c,d) + SELECT x%10, x/10, x, printf('xyz%dabc',x) FROM c; + + SELECT t3.c FROM + (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2 + JOIN t1 AS t3 + WHERE t2.a=t3.a AND t2.m=t3.b + ORDER BY t3.a; +} {95 96 97 98 99} +do_execsql_test select4-16.2 { + SELECT t3.c FROM + (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2 + CROSS JOIN t1 AS t3 + WHERE t2.a=t3.a AND t2.m=t3.b + ORDER BY t3.a; +} {95 96 97 98 99} +do_execsql_test select4-16.3 { + SELECT t3.c FROM + (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2 + LEFT JOIN t1 AS t3 + WHERE t2.a=t3.a AND t2.m=t3.b + ORDER BY t3.a; +} {95 96 97 98 99} + +# Ticket https://sqlite.org/src/tktview/f7f8c97e975978d45 on 2016-04-25 +# +# The where push-down optimization from 2015-06-02 is suppose to disable +# on aggregate subqueries. But if the subquery is a compound where the +# last SELECT is non-aggregate but some other SELECT is an aggregate, the +# test is incomplete and the optimization is not properly disabled. +# +# The following test cases verify that the fix works. +# +do_execsql_test select4-17.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a int, b int); + INSERT INTO t1 VALUES(1,2),(1,18),(2,19); + SELECT x, y FROM ( + SELECT 98 AS x, 99 AS y + UNION + SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a + ) AS w WHERE y>=20 + ORDER BY +x; +} {1 20 98 99} +do_execsql_test select4-17.2 { + SELECT x, y FROM ( + SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a + UNION + SELECT 98 AS x, 99 AS y + ) AS w WHERE y>=20 + ORDER BY +x; +} {1 20 98 99} +do_catchsql_test select4-17.3 { + SELECT x, y FROM ( + SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a LIMIT 3 + UNION + SELECT 98 AS x, 99 AS y + ) AS w WHERE y>=20 + ORDER BY +x; +} {1 {LIMIT clause should come after UNION not before}} + +# 2020-04-03 ticket 51166be0159fd2ce from Yong Heng. +# Adverse interaction between the constant propagation and push-down +# optimizations. +# +reset_db +do_execsql_test select4-18.1 { + CREATE VIEW v0(v0) AS WITH v0 AS(SELECT 0 v0) SELECT(SELECT min(v0) OVER()) FROM v0 GROUP BY v0; + SELECT *FROM v0 v1 JOIN v0 USING(v0) WHERE datetime(v0) = (v0.v0)AND v0 = 10; +} {} +do_execsql_test select4-18.2 { + CREATE VIEW t1(aa) AS + WITH t2(bb) AS (SELECT 123) + SELECT (SELECT min(bb) OVER()) FROM t2 GROUP BY bb; + SELECT * FROM t1; +} {123} +do_execsql_test select4-18.3 { + SELECT * FROM t1 AS z1 JOIN t1 AS z2 USING(aa) + WHERE abs(z1.aa)=z2.aa AND z1.aa=123; +} {123} + +# 2021-03-31 Fix an assert() problem in the logic at the end of sqlite3Select() +# that validates AggInfo. The checks to ensure that AggInfo.aCol[].pCExpr +# references a valid expression was looking at an expression that had been +# deleted by the truth optimization in sqlite3ExprAnd() which was invoked by +# the push-down optimization. This is harmless in delivery builds, as that code +# only runs with SQLITE_DEBUG. But it should still be fixed. The problem +# was discovered by dbsqlfuzz (crash-dece7b67a3552ed7e571a7bda903afd1f7bd9b21) +# +reset_db +do_execsql_test select4-19.1 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(99); + SELECT sum((SELECT 1 FROM (SELECT 2 WHERE x IS NULL) WHERE 0)) FROM t1; +} {{}} + +finish_test diff --git a/testing/sqlite3/select5.test b/testing/sqlite3/select5.test new file mode 100644 index 000000000..8de306cf4 --- /dev/null +++ b/testing/sqlite3/select5.test @@ -0,0 +1,262 @@ +# 2001 September 15 +# +# 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 aggregate functions and the +# GROUP BY and HAVING clauses of SELECT statements. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Build some test data +# +execsql { + CREATE TABLE t1(x int, y int); + BEGIN; +} +for {set i 1} {$i<32} {incr i} { + for {set j 0} {(1<<$j)<$i} {incr j} {} + execsql "INSERT INTO t1 VALUES([expr {32-$i}],[expr {10-$j}])" +} +execsql { + COMMIT +} + +do_test select5-1.0 { + execsql {SELECT DISTINCT y FROM t1 ORDER BY y} +} {5 6 7 8 9 10} + +# Sort by an aggregate function. +# +do_test select5-1.1 { + execsql {SELECT y, count(*) FROM t1 GROUP BY y ORDER BY y} +} {5 15 6 8 7 4 8 2 9 1 10 1} +do_test select5-1.2 { + execsql {SELECT y, count(*) FROM t1 GROUP BY y ORDER BY count(*), y} +} {9 1 10 1 8 2 7 4 6 8 5 15} +do_test select5-1.3 { + execsql {SELECT count(*), y FROM t1 GROUP BY y ORDER BY count(*), y} +} {1 9 1 10 2 8 4 7 8 6 15 5} + +# Some error messages associated with aggregates and GROUP BY +# +do_test select5-2.1.1 { + catchsql { + SELECT y, count(*) FROM t1 GROUP BY z ORDER BY y + } +} {1 {no such column: z}} +do_test select5-2.1.2 { + catchsql { + SELECT y, count(*) FROM t1 GROUP BY temp.t1.y ORDER BY y + } +} {1 {no such column: temp.t1.y}} +do_test select5-2.2 { + set v [catch {execsql { + SELECT y, count(*) FROM t1 GROUP BY z(y) ORDER BY y + }} msg] + lappend v $msg +} {1 {no such function: z}} +do_test select5-2.3 { + set v [catch {execsql { + SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)<3 ORDER BY y + }} msg] + lappend v $msg +} {0 {8 2 9 1 10 1}} +do_test select5-2.4 { + set v [catch {execsql { + SELECT y, count(*) FROM t1 GROUP BY y HAVING z(y)<3 ORDER BY y + }} msg] + lappend v $msg +} {1 {no such function: z}} +do_test select5-2.5 { + set v [catch {execsql { + SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)100 + } +} {{}} +do_test select5-4.2 { + execsql { + SELECT count(x) FROM t1 WHERE x>100 + } +} {0} +do_test select5-4.3 { + execsql { + SELECT min(x) FROM t1 WHERE x>100 + } +} {{}} +do_test select5-4.4 { + execsql { + SELECT max(x) FROM t1 WHERE x>100 + } +} {{}} +do_test select5-4.5 { + execsql { + SELECT sum(x) FROM t1 WHERE x>100 + } +} {{}} + +# Some tests for queries with a GROUP BY clause but no aggregate functions. +# +# Note: The query in test cases 5.1 through 5.5 are not legal SQL. So if the +# implementation changes in the future and it returns different results, +# this is not such a big deal. +# +do_test select5-5.1 { + execsql { + CREATE TABLE t2(a, b, c); + INSERT INTO t2 VALUES(1, 2, 3); + INSERT INTO t2 VALUES(1, 4, 5); + INSERT INTO t2 VALUES(6, 4, 7); + CREATE INDEX t2_idx ON t2(a); + } +} {} +do_test select5-5.2 { + execsql { + SELECT a FROM t2 GROUP BY a; + } +} {1 6} +do_test select5-5.3 { + execsql { + SELECT a FROM t2 WHERE a>2 GROUP BY a; + } +} {6} +do_test select5-5.4 { + execsql { + SELECT a, b FROM t2 GROUP BY a, b; + } +} {1 2 1 4 6 4} +do_test select5-5.5 { + execsql { + SELECT a, b FROM t2 GROUP BY a; + } +} {1 2 6 4} + +# Test rendering of columns for the GROUP BY clause. +# +do_test select5-5.11 { + execsql { + SELECT max(c), b*a, b, a FROM t2 GROUP BY b*a, b, a + } +} {3 2 2 1 5 4 4 1 7 24 4 6} + +# NULL compare equal to each other for the purposes of processing +# the GROUP BY clause. +# +do_test select5-6.1 { + execsql { + CREATE TABLE t3(x,y); + INSERT INTO t3 VALUES(1,NULL); + INSERT INTO t3 VALUES(2,NULL); + INSERT INTO t3 VALUES(3,4); + SELECT count(x), y FROM t3 GROUP BY y ORDER BY 1 + } +} {1 4 2 {}} +do_test select5-6.2 { + execsql { + CREATE TABLE t4(x,y,z); + INSERT INTO t4 VALUES(1,2,NULL); + INSERT INTO t4 VALUES(2,3,NULL); + INSERT INTO t4 VALUES(3,NULL,5); + INSERT INTO t4 VALUES(4,NULL,6); + INSERT INTO t4 VALUES(4,NULL,6); + INSERT INTO t4 VALUES(5,NULL,NULL); + INSERT INTO t4 VALUES(5,NULL,NULL); + INSERT INTO t4 VALUES(6,7,8); + SELECT max(x), count(x), y, z FROM t4 GROUP BY y, z ORDER BY 1 + } +} {1 1 2 {} 2 1 3 {} 3 1 {} 5 4 2 {} 6 5 2 {} {} 6 1 7 8} + +do_test select5-7.2 { + execsql { + SELECT count(*), count(x) as cnt FROM t4 GROUP BY y ORDER BY cnt; + } +} {1 1 1 1 1 1 5 5} + +# See ticket #3324. +# +do_test select5-8.1 { + execsql { + CREATE TABLE t8a(a,b); + CREATE TABLE t8b(x); + INSERT INTO t8a VALUES('one', 1); + INSERT INTO t8a VALUES('one', 2); + INSERT INTO t8a VALUES('two', 3); + INSERT INTO t8a VALUES('one', NULL); + INSERT INTO t8b(rowid,x) VALUES(1,111); + INSERT INTO t8b(rowid,x) VALUES(2,222); + INSERT INTO t8b(rowid,x) VALUES(3,333); + SELECT a, count(b) FROM t8a, t8b WHERE b=t8b.rowid GROUP BY a ORDER BY a; + } +} {one 2 two 1} +do_test select5-8.2 { + execsql { + SELECT a, count(b) FROM t8a, t8b WHERE b=+t8b.rowid GROUP BY a ORDER BY a; + } +} {one 2 two 1} +do_test select5-8.3 { + execsql { + SELECT t8a.a, count(t8a.b) FROM t8a, t8b WHERE t8a.b=t8b.rowid + GROUP BY 1 ORDER BY 1; + } +} {one 2 two 1} +do_test select5-8.4 { + execsql { + SELECT a, count(*) FROM t8a, t8b WHERE b=+t8b.rowid GROUP BY a ORDER BY a; + } +} {one 2 two 1} +do_test select5-8.5 { + execsql { + SELECT a, count(b) FROM t8a, t8b WHERE b10 + } +} {10.5 3.7 14.2} +do_test select6-3.7 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1) + WHERE a<10 + } +} {} +do_test select6-3.8 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4) + WHERE a>10 + } +} {11.5 4.0 15.5} +do_test select6-3.9 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4) + WHERE a<10 + } +} {} +do_test select6-3.10 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b) + ORDER BY a + } +} {1.0 1 2.0 2.5 2 4.5 5.5 3 8.5 11.5 4 15.5 18.0 5 23.0} +do_test select6-3.11 { + execsql { + SELECT a,b,a+b FROM + (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b) + WHERE b<4 ORDER BY a + } +} {1.0 1 2.0 2.5 2 4.5 5.5 3 8.5} +do_test select6-3.12 { + execsql { + SELECT a,b,a+b FROM + (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b HAVING a>1) + WHERE b<4 ORDER BY a + } +} {2.5 2 4.5 5.5 3 8.5} +do_test select6-3.13 { + execsql { + SELECT a,b,a+b FROM + (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b HAVING a>1) + ORDER BY a + } +} {2.5 2 4.5 5.5 3 8.5 11.5 4 15.5 18.0 5 23.0} +do_test select6-3.14 { + execsql { + SELECT [count(*)],y FROM (SELECT count(*), y FROM t1 GROUP BY y) + ORDER BY [count(*)] + } +} {1 1 2 2 4 3 5 5 8 4} +do_test select6-3.15 { + execsql { + SELECT [count(*)],y FROM (SELECT count(*), y FROM t1 GROUP BY y) + ORDER BY y + } +} {1 1 2 2 4 3 8 4 5 5} + +do_test select6-4.1 { + execsql { + SELECT a,b,c FROM + (SELECT x AS 'a', y AS 'b', x+y AS 'c' FROM t1 WHERE y=4) + WHERE a<10 ORDER BY a; + } +} {8 4 12 9 4 13} +do_test select6-4.2 { + execsql { + SELECT y FROM (SELECT DISTINCT y FROM t1) WHERE y<5 ORDER BY y + } +} {1 2 3 4} +do_test select6-4.3 { + execsql { + SELECT DISTINCT y FROM (SELECT y FROM t1) WHERE y<5 ORDER BY y + } +} {1 2 3 4} +do_test select6-4.4 { + execsql { + SELECT avg(y) FROM (SELECT DISTINCT y FROM t1) WHERE y<5 ORDER BY y + } +} {2.5} +do_test select6-4.5 { + execsql { + SELECT avg(y) FROM (SELECT DISTINCT y FROM t1 WHERE y<5) ORDER BY y + } +} {2.5} + +do_test select6-5.1 { + execsql { + SELECT a,x,b FROM + (SELECT x+3 AS 'a', x FROM t1 WHERE y=3) AS 'p', + (SELECT x AS 'b' FROM t1 WHERE y=4) AS 'q' + WHERE a=b + ORDER BY a + } +} {8 5 8 9 6 9 10 7 10} +do_test select6-5.2 { + execsql { + SELECT a,x,b FROM + (SELECT x+3 AS 'a', x FROM t1 WHERE y=3), + (SELECT x AS 'b' FROM t1 WHERE y=4) + WHERE a=b + ORDER BY a + } +} {8 5 8 9 6 9 10 7 10} + +# Tests of compound sub-selects +# +do_test select6-6.1 { + execsql { + DELETE FROM t1 WHERE x>4; + SELECT * FROM t1 + } +} {1 1 2 2 3 2 4 3} +ifcapable compound { + do_test select6-6.2 { + execsql { + SELECT * FROM ( + SELECT x AS 'a' FROM t1 UNION ALL SELECT x+10 AS 'a' FROM t1 + ) ORDER BY a; + } + } {1 2 3 4 11 12 13 14} + do_test select6-6.3 { + execsql { + SELECT * FROM ( + SELECT x AS 'a' FROM t1 UNION ALL SELECT x+1 AS 'a' FROM t1 + ) ORDER BY a; + } + } {1 2 2 3 3 4 4 5} + do_test select6-6.4 { + execsql { + SELECT * FROM ( + SELECT x AS 'a' FROM t1 UNION SELECT x+1 AS 'a' FROM t1 + ) ORDER BY a; + } + } {1 2 3 4 5} + do_test select6-6.5 { + execsql { + SELECT * FROM ( + SELECT x AS 'a' FROM t1 INTERSECT SELECT x+1 AS 'a' FROM t1 + ) ORDER BY a; + } + } {2 3 4} + do_test select6-6.6 { + execsql { + SELECT * FROM ( + SELECT x AS 'a' FROM t1 EXCEPT SELECT x*2 AS 'a' FROM t1 + ) ORDER BY a; + } + } {1 3} +} ;# ifcapable compound + +# Subselects with no FROM clause +# +do_test select6-7.1 { + execsql { + SELECT * FROM (SELECT 1) + } +} {1} +do_test select6-7.2 { + execsql { + SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c') + } +} {abc 2 1 1 2 abc} +do_test select6-7.3 { + execsql { + SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c' WHERE 0) + } +} {} +do_test select6-7.4 { + execsql2 { + SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c' WHERE 1) + } +} {c abc b 2 a 1 a 1 b 2 c abc} + +# The remaining tests in this file depend on the EXPLAIN keyword. +# Skip these tests if EXPLAIN is disabled in the current build. +# +ifcapable {!explain} { + finish_test + return +} + +# The following procedure compiles the SQL given as an argument and returns +# TRUE if that SQL uses any transient tables and returns FALSE if no +# transient tables are used. This is used to make sure that the +# sqliteFlattenSubquery() routine in select.c is doing its job. +# +proc is_flat {sql} { + return [expr 0>[lsearch [execsql "EXPLAIN $sql"] OpenEphemeral]] +} + +# Check that the flattener works correctly for deeply nested subqueries +# involving joins. +# +do_test select6-8.1 { + execsql { + BEGIN; + CREATE TABLE t3(p,q); + INSERT INTO t3 VALUES(1,11); + INSERT INTO t3 VALUES(2,22); + CREATE TABLE t4(q,r); + INSERT INTO t4 VALUES(11,111); + INSERT INTO t4 VALUES(22,222); + COMMIT; + SELECT * FROM t3 NATURAL JOIN t4; + } +} {1 11 111 2 22 222} +do_test select6-8.2 { + execsql { + SELECT y, p, q, r FROM + (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m, + (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n + WHERE y=p + } +} {1 1 11 111 2 2 22 222 2 2 22 222} +# If view support is omitted from the build, then so is the query +# "flattener". So omit this test and test select6-8.6 in that case. +ifcapable view { +do_test select6-8.3 { + is_flat { + SELECT y, p, q, r FROM + (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m, + (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n + WHERE y=p + } +} {1} +} ;# ifcapable view +do_test select6-8.4 { + execsql { + SELECT DISTINCT y, p, q, r FROM + (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m, + (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n + WHERE y=p + } +} {1 1 11 111 2 2 22 222} +do_test select6-8.5 { + execsql { + SELECT * FROM + (SELECT y, p, q, r FROM + (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m, + (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n + WHERE y=p) AS e, + (SELECT r AS z FROM t4 WHERE q=11) AS f + WHERE e.r=f.z + } +} {1 1 11 111 111} +ifcapable view { +do_test select6-8.6 { + is_flat { + SELECT * FROM + (SELECT y, p, q, r FROM + (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m, + (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n + WHERE y=p) AS e, + (SELECT r AS z FROM t4 WHERE q=11) AS f + WHERE e.r=f.z + } +} {1} +} ;# ifcapable view + +# Ticket #1634 +# +do_test select6-9.1 { + execsql { + SELECT a.x, b.x FROM t1 AS a, (SELECT x FROM t1 LIMIT 2) AS b + ORDER BY 1, 2 + } +} {1 1 1 2 2 1 2 2 3 1 3 2 4 1 4 2} +do_test select6-9.2 { + execsql { + SELECT x FROM (SELECT x FROM t1 LIMIT 2); + } +} {1 2} +do_test select6-9.3 { + execsql { + SELECT x FROM (SELECT x FROM t1 LIMIT 2 OFFSET 1); + } +} {2 3} +do_test select6-9.4 { + execsql { + SELECT x FROM (SELECT x FROM t1) LIMIT 2; + } +} {1 2} +do_test select6-9.5 { + execsql { + SELECT x FROM (SELECT x FROM t1) LIMIT 2 OFFSET 1; + } +} {2 3} +do_test select6-9.6 { + execsql { + SELECT x FROM (SELECT x FROM t1 LIMIT 2) LIMIT 3; + } +} {1 2} +do_test select6-9.7 { + execsql { + SELECT x FROM (SELECT x FROM t1 LIMIT -1) LIMIT 3; + } +} {1 2 3} +do_test select6-9.8 { + execsql { + SELECT x FROM (SELECT x FROM t1 LIMIT -1); + } +} {1 2 3 4} +do_test select6-9.9 { + execsql { + SELECT x FROM (SELECT x FROM t1 LIMIT -1 OFFSET 1); + } +} {2 3 4} +do_test select6-9.10 { + execsql { + SELECT x, y FROM (SELECT x, (SELECT 10+x) y FROM t1 LIMIT -1 OFFSET 1); + } +} {2 12 3 13 4 14} +do_test select6-9.11 { + execsql { + SELECT x, y FROM (SELECT x, (SELECT 10)+x y FROM t1 LIMIT -1 OFFSET 1); + } +} {2 12 3 13 4 14} + + +#------------------------------------------------------------------------- +# Test that if a UNION ALL sub-query that would otherwise be eligible for +# flattening consists of two or more SELECT statements that do not all +# return the same number of result columns, the error is detected. +# +do_execsql_test 10.1 { + CREATE TABLE t(i,j,k); + CREATE TABLE j(l,m); + CREATE TABLE k(o); +} + +set err [list 1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}] + +do_execsql_test 10.2 { + SELECT * FROM (SELECT * FROM t), j; +} +do_catchsql_test 10.3 { + SELECT * FROM t UNION ALL SELECT * FROM j +} $err +do_catchsql_test 10.4 { + SELECT * FROM (SELECT i FROM t UNION ALL SELECT l, m FROM j) +} $err +do_catchsql_test 10.5 { + SELECT * FROM (SELECT j FROM t UNION ALL SELECT * FROM j) +} $err +do_catchsql_test 10.6 { + SELECT * FROM (SELECT * FROM t UNION ALL SELECT * FROM j) +} $err +do_catchsql_test 10.7 { + SELECT * FROM ( + SELECT * FROM t UNION ALL + SELECT l,m,l FROM j UNION ALL + SELECT * FROM k + ) +} $err +do_catchsql_test 10.8 { + SELECT * FROM ( + SELECT * FROM k UNION ALL + SELECT * FROM t UNION ALL + SELECT l,m,l FROM j + ) +} $err + +# 2015-02-09 Ticket [2f7170d73bf9abf80339187aa3677dce3dbcd5ca] +# "misuse of aggregate" error if aggregate column from FROM +# subquery is used in correlated subquery +# +do_execsql_test 11.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(w INT, x INT); + INSERT INTO t1(w,x) + VALUES(1,10),(2,20),(3,30), + (2,21),(3,31), + (3,32); + CREATE INDEX t1wx ON t1(w,x); + + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(w INT, y VARCHAR(8)); + INSERT INTO t2(w,y) VALUES(1,'one'),(2,'two'),(3,'three'),(4,'four'); + CREATE INDEX t2wy ON t2(w,y); + + SELECT cnt, xyz, (SELECT y FROM t2 WHERE w=cnt), '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY cnt, xyz; +} {1 1 one | 2 2 two | 3 3 three |} +do_execsql_test 11.2 { + SELECT cnt, xyz, lower((SELECT y FROM t2 WHERE w=cnt)), '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY cnt, xyz; +} {1 1 one | 2 2 two | 3 3 three |} +do_execsql_test 11.3 { + SELECT cnt, xyz, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + WHERE (SELECT y FROM t2 WHERE w=cnt)!='two' + ORDER BY cnt, xyz; +} {1 1 | 3 3 |} +do_execsql_test 11.4 { + SELECT cnt, xyz, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY lower((SELECT y FROM t2 WHERE w=cnt)); +} {1 1 | 3 3 | 2 2 |} +do_execsql_test 11.5 { + SELECT cnt, xyz, + CASE WHEN (SELECT y FROM t2 WHERE w=cnt)=='two' + THEN 'aaa' ELSE 'bbb' + END, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY +cnt; +} {1 1 bbb | 2 2 aaa | 3 3 bbb |} + +do_execsql_test 11.100 { + DROP TABLE t1; + DROP TABLE t2; + CREATE TABLE t1(x); + CREATE TABLE t2(y, z); + SELECT ( SELECT y FROM t2 WHERE z = cnt ) + FROM ( SELECT count(*) AS cnt FROM t1 ); +} {{}} + +# 2019-05-29 ticket https://sqlite.org/src/info/c41afac34f15781f +# A LIMIT clause in a subquery is incorrectly applied to a subquery. +# +do_execsql_test 12.100 { + DROP TABLE t1; + DROP TABLE t2; + CREATE TABLE t1(a); + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + CREATE TABLE t2(b); + INSERT INTO t2 VALUES(3); + SELECT * FROM ( + SELECT * FROM (SELECT * FROM t1 LIMIT 1) + UNION ALL + SELECT * from t2); +} {1 3} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 13.100 { + + CREATE TABLE t1(y INT); + INSERT INTO t1 (y) VALUES (1); + + CREATE TABLE t2(x INTEGER); + INSERT INTO t2 VALUES(0); + + CREATE TABLE empty1(z); +} + +do_execsql_test 13.110 { + SELECT t1.y + FROM ( SELECT 'AAA' ) + INNER JOIN ( + SELECT 1 AS abc FROM ( + SELECT 1 FROM t2 LEFT JOIN empty1 + ) + ) AS sub0 ON sub0.abc + , t1 + RIGHT JOIN (SELECT 'BBB' FROM ( SELECT 'CCC' )) +} {1} + +do_execsql_test 13.120 { + SELECT t1.y + FROM ( SELECT 'AAA' ) + INNER JOIN ( + SELECT 1 AS abc FROM ( + SELECT 1 FROM t2 LEFT JOIN empty1 + ) + ) AS sub0 ON sub0.abc + , t1 + RIGHT JOIN (SELECT 'BBB' FROM ( SELECT 'CCC' )) + WHERE t1.y +} {1} + + +finish_test diff --git a/testing/sqlite3/select7.test b/testing/sqlite3/select7.test new file mode 100644 index 000000000..0c4051006 --- /dev/null +++ b/testing/sqlite3/select7.test @@ -0,0 +1,250 @@ +# 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 compute SELECT statements and nested +# views. +# +# $Id: select7.test,v 1.11 2007/09/12 17:01:45 danielk1977 Exp $ + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix select7 + +ifcapable compound { + +# A 3-way INTERSECT. Ticket #875 +ifcapable tempdb { + do_test select7-1.1 { + execsql { + create temp table t1(x); + insert into t1 values('amx'); + insert into t1 values('anx'); + insert into t1 values('amy'); + insert into t1 values('bmy'); + select * from t1 where x like 'a__' + intersect select * from t1 where x like '_m_' + intersect select * from t1 where x like '__x'; + } + } {amx} +} + + +# Nested views do not handle * properly. Ticket #826. +# +ifcapable view { +do_test select7-2.1 { + execsql { + CREATE TABLE x(id integer primary key, a TEXT NULL); + INSERT INTO x (a) VALUES ('first'); + CREATE TABLE tempx(id integer primary key, a TEXT NULL); + INSERT INTO tempx (a) VALUES ('t-first'); + CREATE VIEW tv1 AS SELECT x.id, tx.id FROM x JOIN tempx tx ON tx.id=x.id; + CREATE VIEW tv1b AS SELECT x.id, tx.id FROM x JOIN tempx tx on tx.id=x.id; + CREATE VIEW tv2 AS SELECT * FROM tv1 UNION SELECT * FROM tv1b; + SELECT * FROM tv2; + } +} {1 1} +} ;# ifcapable view + +} ;# ifcapable compound + +# Do not allow GROUP BY without an aggregate. Ticket #1039. +# +# Change: force any query with a GROUP BY clause to be processed as +# an aggregate query, whether it contains aggregates or not. +# +ifcapable subquery { + # do_test select7-3.1 { + # catchsql { + # SELECT * FROM (SELECT * FROM sqlite_master) GROUP BY name + # } + # } {1 {GROUP BY may only be used on aggregate queries}} + do_test select7-3.1 { + catchsql { + SELECT * FROM (SELECT * FROM sqlite_master) GROUP BY name + } + } [list 0 [execsql {SELECT * FROM sqlite_master ORDER BY name}]] +} + +# Ticket #2018 - Make sure names are resolved correctly on all +# SELECT statements of a compound subquery. +# +ifcapable {subquery && compound} { + do_test select7-4.1 { + execsql { + CREATE TABLE IF NOT EXISTS photo(pk integer primary key, x); + CREATE TABLE IF NOT EXISTS tag(pk integer primary key, fk int, name); + + SELECT P.pk from PHOTO P WHERE NOT EXISTS ( + SELECT T2.pk from TAG T2 WHERE T2.fk = P.pk + EXCEPT + SELECT T3.pk from TAG T3 WHERE T3.fk = P.pk AND T3.name LIKE '%foo%' + ); + } + } {} + do_test select7-4.2 { + execsql { + INSERT INTO photo VALUES(1,1); + INSERT INTO photo VALUES(2,2); + INSERT INTO photo VALUES(3,3); + INSERT INTO tag VALUES(11,1,'one'); + INSERT INTO tag VALUES(12,1,'two'); + INSERT INTO tag VALUES(21,1,'one-b'); + SELECT P.pk from PHOTO P WHERE NOT EXISTS ( + SELECT T2.pk from TAG T2 WHERE T2.fk = P.pk + EXCEPT + SELECT T3.pk from TAG T3 WHERE T3.fk = P.pk AND T3.name LIKE '%foo%' + ); + } + } {2 3} +} + +# ticket #2347 +# +ifcapable {subquery && compound} { + do_test select7-5.1 { + catchsql { + CREATE TABLE t2(a,b); + SELECT 5 IN (SELECT a,b FROM t2); + } + } {1 {sub-select returns 2 columns - expected 1}} + do_test select7-5.2 { + catchsql { + SELECT 5 IN (SELECT * FROM t2); + } + } {1 {sub-select returns 2 columns - expected 1}} + do_test select7-5.3 { + catchsql { + SELECT 5 IN (SELECT a,b FROM t2 UNION SELECT b,a FROM t2); + } + } {1 {sub-select returns 2 columns - expected 1}} + do_test select7-5.4 { + catchsql { + SELECT 5 IN (SELECT * FROM t2 UNION SELECT * FROM t2); + } + } {1 {sub-select returns 2 columns - expected 1}} +} + +# Verify that an error occurs if you have too many terms on a +# compound select statement. +# +if {[clang_sanitize_address]==0} { + ifcapable compound { + if {$SQLITE_MAX_COMPOUND_SELECT>0} { + set sql {SELECT 0} + set result 0 + for {set i 1} {$i<$SQLITE_MAX_COMPOUND_SELECT} {incr i} { + append sql " UNION ALL SELECT $i" + lappend result $i + } + do_test select7-6.1 { + catchsql $sql + } [list 0 $result] + append sql { UNION ALL SELECT 99999999} + do_test select7-6.2 { + catchsql $sql + } {1 {too many terms in compound SELECT}} + } + } +} + +# https://issues.chromium.org/issues/358174302 +# Need to support an unlimited number of terms in a VALUES clause, even +# if some of those terms contain double-quoted string literals. +# +do_execsql_test select7-6.5 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a,b,c); +} +sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 10 +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 0 +do_catchsql_test select7-6.6 { + INSERT INTO t1 VALUES + (NULL,0,""), (X'',0.0,0.0), (X'',X'',""), (0.0,0.0,""), (NULL,NULL,0.0), + (0,"",0), (0.0,X'',0), ("",X'',0.0), (0.0,X'',NULL), (0,NULL,""), + (0,"",NULL), (0.0,NULL,X''), ("",X'',NULL), (NULL,0,""), + (0,NULL,0), (X'',X'',0.0); +} {1 {no such column: "" - should this be a string literal in single-quotes?}} +do_execsql_test select7-6.7 { + SELECT count(*) FROM t1; +} {0} +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 +do_catchsql_test select7-6.8 { + INSERT INTO t1 VALUES + (NULL,0,""), (X'',0.0,0.0), (X'',X'',""), (0.0,0.0,""), (NULL,NULL,0.0), + (0,"",0), (0.0,X'',0), ("",X'',0.0), (0.0,X'',NULL), (0,NULL,""), + (0,"",NULL), (0.0,NULL,X''), ("",X'',NULL), (NULL,0,""), + (0,NULL,0), (X'',X'',0.0); +} {0 {}} +do_execsql_test select7-6.9 { + SELECT count(*) FROM t1; +} {16} + +# This block of tests verifies that bug aa92c76cd4 is fixed. +# +do_test select7-7.1 { + execsql { + CREATE TABLE t3(a REAL); + INSERT INTO t3 VALUES(44.0); + INSERT INTO t3 VALUES(56.0); + } +} {} +do_test select7-7.2 { + execsql { + pragma vdbe_trace = 0; + SELECT (CASE WHEN a=0 THEN 0 ELSE (a + 25) / 50 END) AS categ, count(*) + FROM t3 GROUP BY categ + } +} {1.38 1 1.62 1} +do_test select7-7.3 { + execsql { + CREATE TABLE t4(a REAL); + INSERT INTO t4 VALUES( 2.0 ); + INSERT INTO t4 VALUES( 3.0 ); + } +} {} +do_test select7-7.4 { + execsql { + SELECT (CASE WHEN a=0 THEN 'zero' ELSE a/2 END) AS t FROM t4 GROUP BY t; + } +} {1.0 1.5} +do_test select7-7.5 { + execsql { SELECT a=0, typeof(a) FROM t4 } +} {0 real 0 real} +do_test select7-7.6 { + execsql { SELECT a=0, typeof(a) FROM t4 GROUP BY a } +} {0 real 0 real} + +do_test select7-7.7 { + execsql { + CREATE TABLE t5(a TEXT, b INT); + INSERT INTO t5 VALUES(123, 456); + SELECT typeof(a), a FROM t5 GROUP BY a HAVING a=5} { + set iOffsetIncr [expr $nRow / 5] + set iLimitIncr [expr $nRow / 5] + } + + set iLimitEnd [expr $nRow+$iLimitIncr] + set iOffsetEnd [expr $nRow+$iOffsetIncr] + + for {set iOffset 0} {$iOffset < $iOffsetEnd} {incr iOffset $iOffsetIncr} { + for {set iLimit 0} {$iLimit < $iLimitEnd} {incr iLimit} { + + set ::compound_sql "$sql LIMIT $iLimit" + if {$iOffset != 0} { + append ::compound_sql " OFFSET $iOffset" + } + + set iStart [expr {$iOffset*$nCol}] + set iEnd [expr {($iOffset*$nCol) + ($iLimit*$nCol) -1}] + + do_test $testname.limit=$iLimit.offset=$iOffset { + execsql $::compound_sql + } [lrange $result $iStart $iEnd] + } + } +} + +#------------------------------------------------------------------------- +# test_compound_select_flippable TESTNAME SELECT RESULT +# +# This command is for testing statements of the form: +# +# ORDER BY +# +# where each is a simple (non-compound) select statement +# and is one of "INTERSECT", "UNION ALL" or "UNION". +# +# This proc calls [test_compound_select] twice, once with the select +# statement as it is passed to this command, and once with the positions +# of exchanged. +# +proc test_compound_select_flippable {testname sql result} { + test_compound_select $testname $sql $result + + set select [string trim $sql] + set RE {(.*)(UNION ALL|INTERSECT|UNION)(.*)(ORDER BY.*)} + set rc [regexp $RE $select -> s1 op s2 order_by] + if {!$rc} {error "Statement is unflippable: $select"} + + set flipsql "$s2 $op $s1 $order_by" + test_compound_select $testname.flipped $flipsql $result +} + +############################################################################# +# Begin tests. +# + +# Create and populate a sample database. +# +do_test select9-1.0 { + execsql { + CREATE TABLE t1(a, b, c); + CREATE TABLE t2(d, e, f); + BEGIN; + INSERT INTO t1 VALUES(1, 'one', 'I'); + INSERT INTO t1 VALUES(3, NULL, NULL); + INSERT INTO t1 VALUES(5, 'five', 'V'); + INSERT INTO t1 VALUES(7, 'seven', 'VII'); + INSERT INTO t1 VALUES(9, NULL, NULL); + INSERT INTO t1 VALUES(2, 'two', 'II'); + INSERT INTO t1 VALUES(4, 'four', 'IV'); + INSERT INTO t1 VALUES(6, NULL, NULL); + INSERT INTO t1 VALUES(8, 'eight', 'VIII'); + INSERT INTO t1 VALUES(10, 'ten', 'X'); + + INSERT INTO t2 VALUES(1, 'two', 'IV'); + INSERT INTO t2 VALUES(2, 'four', 'VIII'); + INSERT INTO t2 VALUES(3, NULL, NULL); + INSERT INTO t2 VALUES(4, 'eight', 'XVI'); + INSERT INTO t2 VALUES(5, 'ten', 'XX'); + INSERT INTO t2 VALUES(6, NULL, NULL); + INSERT INTO t2 VALUES(7, 'fourteen', 'XXVIII'); + INSERT INTO t2 VALUES(8, 'sixteen', 'XXXII'); + INSERT INTO t2 VALUES(9, NULL, NULL); + INSERT INTO t2 VALUES(10, 'twenty', 'XL'); + + COMMIT; + } +} {} + +# Each iteration of this loop runs the same tests with a different set +# of indexes present within the database schema. The data returned by +# the compound SELECT statements in the test cases should be the same +# in each case. +# +set iOuterLoop 1 +foreach indexes [list { + /* Do not create any indexes. */ +} { + CREATE INDEX i1 ON t1(a) +} { + CREATE INDEX i2 ON t1(b) +} { + CREATE INDEX i3 ON t2(d) +} { + CREATE INDEX i4 ON t2(e) +}] { + + do_test select9-1.$iOuterLoop.1 { + execsql $indexes + } {} + + # Test some 2-way UNION ALL queries. No WHERE clauses. + # + test_compound_select select9-1.$iOuterLoop.2 { + SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 + } {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} + test_compound_select select9-1.$iOuterLoop.3 { + SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY 1 + } {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} + test_compound_select select9-1.$iOuterLoop.4 { + SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY 2 + } {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} + test_compound_select_flippable select9-1.$iOuterLoop.5 { + SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY 1, 2 + } {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} + test_compound_select_flippable select9-1.$iOuterLoop.6 { + SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY 2, 1 + } {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} + + # Test some 2-way UNION queries. + # + test_compound_select select9-1.$iOuterLoop.7 { + SELECT a, b FROM t1 UNION SELECT d, e FROM t2 + } {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} + + test_compound_select select9-1.$iOuterLoop.8 { + SELECT a, b FROM t1 UNION SELECT d, e FROM t2 ORDER BY 1 + } {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} + + test_compound_select select9-1.$iOuterLoop.9 { + SELECT a, b FROM t1 UNION SELECT d, e FROM t2 ORDER BY 2 + } {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} + + test_compound_select_flippable select9-1.$iOuterLoop.10 { + SELECT a, b FROM t1 UNION SELECT d, e FROM t2 ORDER BY 1, 2 + } {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} + + test_compound_select_flippable select9-1.$iOuterLoop.11 { + SELECT a, b FROM t1 UNION SELECT d, e FROM t2 ORDER BY 2, 1 + } {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} + + # Test some 2-way INTERSECT queries. + # + test_compound_select select9-1.$iOuterLoop.11 { + SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 + } {3 {} 6 {} 9 {}} + test_compound_select_flippable select9-1.$iOuterLoop.12 { + SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 ORDER BY 1 + } {3 {} 6 {} 9 {}} + test_compound_select select9-1.$iOuterLoop.13 { + SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 ORDER BY 2 + } {3 {} 6 {} 9 {}} + test_compound_select_flippable select9-1.$iOuterLoop.14 { + SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 ORDER BY 2, 1 + } {3 {} 6 {} 9 {}} + test_compound_select_flippable select9-1.$iOuterLoop.15 { + SELECT a, b FROM t1 INTERSECT SELECT d, e FROM t2 ORDER BY 1, 2 + } {3 {} 6 {} 9 {}} + + # Test some 2-way EXCEPT queries. + # + test_compound_select select9-1.$iOuterLoop.16 { + SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 + } {1 one 2 two 4 four 5 five 7 seven 8 eight 10 ten} + + test_compound_select select9-1.$iOuterLoop.17 { + SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 ORDER BY 1 + } {1 one 2 two 4 four 5 five 7 seven 8 eight 10 ten} + + test_compound_select select9-1.$iOuterLoop.18 { + SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 ORDER BY 2 + } {8 eight 5 five 4 four 1 one 7 seven 10 ten 2 two} + + test_compound_select select9-1.$iOuterLoop.19 { + SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 ORDER BY 1, 2 + } {1 one 2 two 4 four 5 five 7 seven 8 eight 10 ten} + + test_compound_select select9-1.$iOuterLoop.20 { + SELECT a, b FROM t1 EXCEPT SELECT d, e FROM t2 ORDER BY 2, 1 + } {8 eight 5 five 4 four 1 one 7 seven 10 ten 2 two} + + incr iOuterLoop +} + +do_test select9-2.0 { + execsql { + DROP INDEX i1; + DROP INDEX i2; + DROP INDEX i3; + DROP INDEX i4; + } +} {} + +proc reverse {lhs rhs} { + return [string compare $rhs $lhs] +} +db collate reverse reverse + +# This loop is similar to the previous one (test cases select9-1.*) +# except that the simple select statements have WHERE clauses attached +# to them. Sometimes the WHERE clause may be satisfied using the same +# index used for ORDER BY, sometimes not. +# +set iOuterLoop 1 +foreach indexes [list { + /* Do not create any indexes. */ +} { + CREATE INDEX i1 ON t1(a) +} { + DROP INDEX i1; + CREATE INDEX i1 ON t1(b, a) +} { + CREATE INDEX i2 ON t2(d DESC, e COLLATE REVERSE ASC); +} { + CREATE INDEX i3 ON t1(a DESC); +}] { + do_test select9-2.$iOuterLoop.1 { + execsql $indexes + } {} + + test_compound_select_flippable select9-2.$iOuterLoop.2 { + SELECT * FROM t1 WHERE a<5 UNION SELECT * FROM t2 WHERE d>=5 ORDER BY 1 + } {1 one I 2 two II 3 {} {} 4 four IV 5 ten XX 6 {} {} 7 fourteen XXVIII 8 sixteen XXXII 9 {} {} 10 twenty XL} + + test_compound_select_flippable select9-2.$iOuterLoop.2 { + SELECT * FROM t1 WHERE a<5 UNION SELECT * FROM t2 WHERE d>=5 ORDER BY 2, 1 + } {3 {} {} 6 {} {} 9 {} {} 4 four IV 7 fourteen XXVIII 1 one I 8 sixteen XXXII 5 ten XX 10 twenty XL 2 two II} + + test_compound_select_flippable select9-2.$iOuterLoop.3 { + SELECT * FROM t1 WHERE a<5 UNION SELECT * FROM t2 WHERE d>=5 + ORDER BY 2 COLLATE reverse, 1 + } {3 {} {} 6 {} {} 9 {} {} 2 two II 10 twenty XL 5 ten XX 8 sixteen XXXII 1 one I 7 fourteen XXVIII 4 four IV} + + test_compound_select_flippable select9-2.$iOuterLoop.4 { + SELECT * FROM t1 WHERE a<5 UNION ALL SELECT * FROM t2 WHERE d>=5 ORDER BY 1 + } {1 one I 2 two II 3 {} {} 4 four IV 5 ten XX 6 {} {} 7 fourteen XXVIII 8 sixteen XXXII 9 {} {} 10 twenty XL} + + test_compound_select_flippable select9-2.$iOuterLoop.5 { + SELECT * FROM t1 WHERE a<5 UNION ALL SELECT * FROM t2 WHERE d>=5 ORDER BY 2, 1 + } {3 {} {} 6 {} {} 9 {} {} 4 four IV 7 fourteen XXVIII 1 one I 8 sixteen XXXII 5 ten XX 10 twenty XL 2 two II} + + test_compound_select_flippable select9-2.$iOuterLoop.6 { + SELECT * FROM t1 WHERE a<5 UNION ALL SELECT * FROM t2 WHERE d>=5 + ORDER BY 2 COLLATE reverse, 1 + } {3 {} {} 6 {} {} 9 {} {} 2 two II 10 twenty XL 5 ten XX 8 sixteen XXXII 1 one I 7 fourteen XXVIII 4 four IV} + + test_compound_select select9-2.$iOuterLoop.4 { + SELECT a FROM t1 WHERE a<8 EXCEPT SELECT d FROM t2 WHERE d<=3 ORDER BY 1 + } {4 5 6 7} + + test_compound_select select9-2.$iOuterLoop.4 { + SELECT a FROM t1 WHERE a<8 INTERSECT SELECT d FROM t2 WHERE d<=3 ORDER BY 1 + } {1 2 3} + +} + +do_test select9-2.X { + execsql { + DROP INDEX i1; + DROP INDEX i2; + DROP INDEX i3; + } +} {} + +# This procedure executes the SQL. Then it checks the generated program +# for the SQL and appends a "nosort" to the result if the program contains the +# SortCallback opcode. If the program does not contain the SortCallback +# opcode it appends "sort" +# +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 +} + +# If the right indexes exist, the following query: +# +# SELECT t1.a FROM t1 UNION ALL SELECT t2.d FROM t2 ORDER BY 1 +# +# can use indexes to run without doing a in-memory sort operation. +# This block of tests (select9-3.*) is used to check if the same +# is possible with: +# +# CREATE VIEW v1 AS SELECT a FROM t1 UNION ALL SELECT d FROM t2 +# SELECT a FROM v1 ORDER BY 1 +# +# It turns out that it is. +# +do_test select9-3.1 { + cksort { SELECT a FROM t1 ORDER BY 1 } +} {1 2 3 4 5 6 7 8 9 10 sort} +do_test select9-3.2 { + execsql { CREATE INDEX i1 ON t1(a) } + cksort { SELECT a FROM t1 ORDER BY 1 } +} {1 2 3 4 5 6 7 8 9 10 nosort} +do_test select9-3.3 { + cksort { SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 5 } +} {1 1 2 2 3 sort} +do_test select9-3.4 { + execsql { CREATE INDEX i2 ON t2(d) } + cksort { SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 5 } +} {1 1 2 2 3 nosort} +do_test select9-3.5 { + execsql { CREATE VIEW v1 AS SELECT a FROM t1 UNION ALL SELECT d FROM t2 } + cksort { SELECT a FROM v1 ORDER BY 1 LIMIT 5 } +} {1 1 2 2 3 nosort} +do_test select9-3.X { + execsql { + DROP INDEX i1; + DROP INDEX i2; + DROP VIEW v1; + } +} {} + +# This block of tests is the same as the preceding one, except that +# "UNION" is tested instead of "UNION ALL". +# +do_test select9-4.1 { + cksort { SELECT a FROM t1 ORDER BY 1 } +} {1 2 3 4 5 6 7 8 9 10 sort} +do_test select9-4.2 { + execsql { CREATE INDEX i1 ON t1(a) } + cksort { SELECT a FROM t1 ORDER BY 1 } +} {1 2 3 4 5 6 7 8 9 10 nosort} +do_test select9-4.3 { + cksort { SELECT a FROM t1 UNION SELECT d FROM t2 ORDER BY 1 LIMIT 5 } +} {1 2 3 4 5 sort} +do_test select9-4.4 { + execsql { CREATE INDEX i2 ON t2(d) } + cksort { SELECT a FROM t1 UNION SELECT d FROM t2 ORDER BY 1 LIMIT 5 } +} {1 2 3 4 5 nosort} +do_test select9-4.5 { + execsql { CREATE VIEW v1 AS SELECT a FROM t1 UNION SELECT d FROM t2 } + cksort { SELECT a FROM v1 ORDER BY 1 LIMIT 5 } +} {1 2 3 4 5 sort} +do_test select9-4.X { + execsql { + DROP INDEX i1; + DROP INDEX i2; + DROP VIEW v1; + } +} {} + +# Testing to make sure that queries involving a view of a compound select +# are planned efficiently. This detects a problem reported on the mailing +# list on 2012-04-26. See +# +# http://www.mail-archive.com/sqlite-users%40sqlite.org/msg69746.html +# +# For additional information. +# +do_test select9-5.1 { + db eval { + CREATE TABLE t51(x, y); + CREATE TABLE t52(x, y); + CREATE VIEW v5 as + SELECT x, y FROM t51 + UNION ALL + SELECT x, y FROM t52; + CREATE INDEX t51x ON t51(x); + CREATE INDEX t52x ON t52(x); + EXPLAIN QUERY PLAN + SELECT * FROM v5 WHERE x='12345' ORDER BY y; + } +} {~/SCAN/} ;# Uses indices with "*" +do_test select9-5.2 { + db eval { + EXPLAIN QUERY PLAN + SELECT x, y FROM v5 WHERE x='12345' ORDER BY y; + } +} {~/SCAN/} ;# Uses indices with "x, y" +do_test select9-5.3 { + db eval { + EXPLAIN QUERY PLAN + SELECT x, y FROM v5 WHERE +x='12345' ORDER BY y; + } +} {/SCAN/} ;# Full table scan if the "+x" prevents index usage. + +# 2013-07-09: Ticket [490a4b7235624298]: +# "WHERE 0" on the first element of a UNION causes an assertion fault +# +do_execsql_test select9-6.1 { + CREATE TABLE t61(a); + CREATE TABLE t62(b); + INSERT INTO t61 VALUES(111); + INSERT INTO t62 VALUES(222); + SELECT a FROM t61 WHERE 0 UNION SELECT b FROM t62; +} {222} +do_execsql_test select9-6.2 { + SELECT a FROM t61 WHERE 0 UNION ALL SELECT b FROM t62; +} {222} +do_execsql_test select9-6.3 { + SELECT a FROM t61 UNION SELECT b FROM t62 WHERE 0; +} {111} + + + +finish_test diff --git a/testing/sqlite3/selectA.test b/testing/sqlite3/selectA.test new file mode 100644 index 000000000..91b154848 --- /dev/null +++ b/testing/sqlite3/selectA.test @@ -0,0 +1,1510 @@ +# 2008 June 24 +# +# 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 compound-SELECT merge +# optimization. Or, in other words, making sure that all +# possible combinations of UNION, UNION ALL, EXCEPT, and +# INTERSECT work together with an ORDER BY clause (with or w/o +# explicit sort order and explicit collating secquites) and +# with and without optional LIMIT and OFFSET clauses. +# +# $Id: selectA.test,v 1.6 2008/08/21 14:24:29 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix selectA + +ifcapable !compound { + finish_test + return +} + +do_test selectA-1.0 { + execsql { + CREATE TABLE t1(a,b,c COLLATE NOCASE); + INSERT INTO t1 VALUES(1,'a','a'); + INSERT INTO t1 VALUES(9.9, 'b', 'B'); + INSERT INTO t1 VALUES(NULL, 'C', 'c'); + INSERT INTO t1 VALUES('hello', 'd', 'D'); + INSERT INTO t1 VALUES(x'616263', 'e', 'e'); + SELECT * FROM t1; + } +} {1 a a 9.9 b B {} C c hello d D abc e e} +do_test selectA-1.1 { + execsql { + CREATE TABLE t2(x,y,z COLLATE NOCASE); + INSERT INTO t2 VALUES(NULL,'U','u'); + INSERT INTO t2 VALUES('mad', 'Z', 'z'); + INSERT INTO t2 VALUES(x'68617265', 'm', 'M'); + INSERT INTO t2 VALUES(5.2e6, 'X', 'x'); + INSERT INTO t2 VALUES(-23, 'Y', 'y'); + SELECT * FROM t2; + } +} {{} U u mad Z z hare m M 5200000.0 X x -23 Y y} +do_test selectA-1.2 { + execsql { + CREATE TABLE t3(a,b,c COLLATE NOCASE); + INSERT INTO t3 SELECT * FROM t1; + INSERT INTO t3 SELECT * FROM t2; + INSERT INTO t3 SELECT * FROM t1; + INSERT INTO t3 SELECT * FROM t2; + INSERT INTO t3 SELECT * FROM t1; + INSERT INTO t3 SELECT * FROM t2; + SELECT count(*) FROM t3; + } +} {30} + +do_test selectA-2.1 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.1.1 { # Ticket #3314 + execsql { + SELECT t1.a, t1.b, t1.c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.1.2 { # Ticket #3314 + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY t1.a, t1.b, t1.c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.2 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-2.3 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.4 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-2.5 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE,a,c + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.6 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE DESC,a,c + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.7 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.8 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.9 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.10 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY c COLLATE BINARY DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-2.11 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.12 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-2.13 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.14 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-2.15 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY b COLLATE NOCASE,a,c + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.16 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY b COLLATE NOCASE DESC,a,c + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.17 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.18 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.19 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.20 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY c COLLATE BINARY DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-2.21 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.22 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-2.23 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.24 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-2.25 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE,a,c + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.26 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE DESC,a,c + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.27 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.28 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.29 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.30 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY c COLLATE BINARY DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-2.31 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.32 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-2.33 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.34 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-2.35 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY y COLLATE NOCASE,x,z + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.36 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY y COLLATE NOCASE DESC,x,z + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.37 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.38 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.39 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.40 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY z COLLATE BINARY DESC,x,y + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-2.41 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY a,b,c + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-2.42 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY a,b,c + } +} {hello d D abc e e} +do_test selectA-2.43 { + execsql { + SELECT a,b,c FROM t1 WHERE b>='d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY a,b,c + } +} {hello d D abc e e} +do_test selectA-2.44 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY a,b,c + } +} {hello d D abc e e} +do_test selectA-2.45 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY a,b,c + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-2.46 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY a,b,c + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-2.47 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY a DESC + } +} {9.9 b B 1 a a {} C c} +do_test selectA-2.48 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY a DESC + } +} {abc e e hello d D} +do_test selectA-2.49 { + execsql { + SELECT a,b,c FROM t1 WHERE b>='d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY a DESC + } +} {abc e e hello d D} +do_test selectA-2.50 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY a DESC + } +} {abc e e hello d D} +do_test selectA-2.51 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY a DESC + } +} {9.9 b B 1 a a {} C c} +do_test selectA-2.52 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY a DESC + } +} {9.9 b B 1 a a {} C c} +do_test selectA-2.53 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY b, a DESC + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-2.54 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY b + } +} {hello d D abc e e} +do_test selectA-2.55 { + execsql { + SELECT a,b,c FROM t1 WHERE b>='d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY b DESC, c + } +} {abc e e hello d D} +do_test selectA-2.56 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY b, c DESC, a + } +} {hello d D abc e e} +do_test selectA-2.57 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY b COLLATE NOCASE + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.58 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY b + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-2.59 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY c, a DESC + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.60 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY c + } +} {hello d D abc e e} +do_test selectA-2.61 { + execsql { + SELECT a,b,c FROM t1 WHERE b>='d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY c COLLATE BINARY, b DESC, c, a, b, c, a, b, c + } +} {hello d D abc e e} +do_test selectA-2.62 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY c DESC, a + } +} {abc e e hello d D} +do_test selectA-2.63 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY c COLLATE NOCASE + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.64 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY c + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.65 { + execsql { + SELECT a,b,c FROM t3 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY c COLLATE NOCASE + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.66 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t3 + ORDER BY c + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.67 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t3 WHERE b<'d' + ORDER BY c DESC, a + } +} {abc e e hello d D} +do_test selectA-2.68 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT b,c,a FROM t3 + ORDER BY c DESC, a + } +} {abc e e hello d D} +do_test selectA-2.69 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT b,c,a FROM t3 + ORDER BY c COLLATE NOCASE + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.70 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT b,c,a FROM t3 + ORDER BY c + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.71 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' + INTERSECT SELECT a,b,c FROM t1 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT b,c,a FROM t3 + INTERSECT SELECT a,b,c FROM t1 + EXCEPT SELECT x,y,z FROM t2 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT y,x,z FROM t2 + INTERSECT SELECT a,b,c FROM t1 + EXCEPT SELECT c,b,a FROM t3 + ORDER BY c + } +} {1 a a 9.9 b B {} C c} +do_test selectA-2.72 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.73 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-2.74 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.75 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-2.76 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE,a,c + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.77 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE DESC,a,c + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.78 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.79 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.80 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.81 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY c COLLATE BINARY DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-2.82 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.83 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-2.84 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-2.85 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-2.86 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY y COLLATE NOCASE,x,z + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.87 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY y COLLATE NOCASE DESC,x,z + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.88 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.89 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-2.90 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.91 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY z COLLATE BINARY DESC,x,y + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-2.92 { + execsql { + SELECT x,y,z FROM t2 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT c,b,a FROM t1 + UNION SELECT a,b,c FROM t3 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT c,b,a FROM t1 + UNION SELECT a,b,c FROM t3 + ORDER BY y COLLATE NOCASE DESC,x,z + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-2.93 { + execsql { + SELECT upper((SELECT c FROM t1 UNION SELECT z FROM t2 ORDER BY 1)); + } +} {A} +do_test selectA-2.94 { + execsql { + SELECT lower((SELECT c FROM t1 UNION ALL SELECT z FROM t2 ORDER BY 1)); + } +} {a} +do_test selectA-2.95 { + execsql { + SELECT lower((SELECT c FROM t1 INTERSECT SELECT z FROM t2 ORDER BY 1)); + } +} {{}} +do_test selectA-2.96 { + execsql { + SELECT lower((SELECT z FROM t2 EXCEPT SELECT c FROM t1 ORDER BY 1)); + } +} {m} + + +do_test selectA-3.0 { + execsql { + CREATE UNIQUE INDEX t1a ON t1(a); + CREATE UNIQUE INDEX t1b ON t1(b); + CREATE UNIQUE INDEX t1c ON t1(c); + CREATE UNIQUE INDEX t2x ON t2(x); + CREATE UNIQUE INDEX t2y ON t2(y); + CREATE UNIQUE INDEX t2z ON t2(z); + SELECT name FROM sqlite_master WHERE type='index' + } +} {t1a t1b t1c t2x t2y t2z} +do_test selectA-3.1 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.1.1 { # Ticket #3314 + execsql { + SELECT t1.a,b,t1.c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY a,t1.b,t1.c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.2 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-3.3 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.4 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-3.5 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE,a,c + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.6 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE DESC,a,c + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.7 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.8 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.9 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.10 { + execsql { + SELECT a,b,c FROM t1 UNION ALL SELECT x,y,z FROM t2 + ORDER BY c COLLATE BINARY DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-3.11 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.12 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-3.13 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.14 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-3.15 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY b COLLATE NOCASE,a,c + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.16 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY b COLLATE NOCASE DESC,a,c + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.17 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.18 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.19 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.20 { + execsql { + SELECT x,y,z FROM t2 UNION ALL SELECT a,b,c FROM t1 + ORDER BY c COLLATE BINARY DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-3.21 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.22 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-3.23 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.24 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-3.25 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE,a,c + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.26 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE DESC,a,c + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.27 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.28 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.29 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.30 { + execsql { + SELECT a,b,c FROM t1 UNION SELECT x,y,z FROM t2 + ORDER BY c COLLATE BINARY DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-3.31 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.32 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-3.33 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.34 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-3.35 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY y COLLATE NOCASE,x,z + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.36 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY y COLLATE NOCASE DESC,x,z + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.37 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.38 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.39 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.40 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t1 + ORDER BY z COLLATE BINARY DESC,x,y + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-3.41 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY a,b,c + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-3.42 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY a,b,c + } +} {hello d D abc e e} +do_test selectA-3.43 { + execsql { + SELECT a,b,c FROM t1 WHERE b>='d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY a,b,c + } +} {hello d D abc e e} +do_test selectA-3.44 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY a,b,c + } +} {hello d D abc e e} +do_test selectA-3.45 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY a,b,c + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-3.46 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY a,b,c + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-3.47 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY a DESC + } +} {9.9 b B 1 a a {} C c} +do_test selectA-3.48 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY a DESC + } +} {abc e e hello d D} +do_test selectA-3.49 { + execsql { + SELECT a,b,c FROM t1 WHERE b>='d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY a DESC + } +} {abc e e hello d D} +do_test selectA-3.50 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY a DESC + } +} {abc e e hello d D} +do_test selectA-3.51 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY a DESC + } +} {9.9 b B 1 a a {} C c} +do_test selectA-3.52 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY a DESC + } +} {9.9 b B 1 a a {} C c} +do_test selectA-3.53 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY b, a DESC + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-3.54 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY b + } +} {hello d D abc e e} +do_test selectA-3.55 { + execsql { + SELECT a,b,c FROM t1 WHERE b>='d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY b DESC, c + } +} {abc e e hello d D} +do_test selectA-3.56 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY b, c DESC, a + } +} {hello d D abc e e} +do_test selectA-3.57 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY b COLLATE NOCASE + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.58 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY b + } +} {{} C c 1 a a 9.9 b B} +do_test selectA-3.59 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY c, a DESC + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.60 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b>='d' + ORDER BY c + } +} {hello d D abc e e} +do_test selectA-3.61 { + execsql { + SELECT a,b,c FROM t1 WHERE b>='d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY c COLLATE BINARY, b DESC, c, a, b, c, a, b, c + } +} {hello d D abc e e} +do_test selectA-3.62 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY c DESC, a + } +} {abc e e hello d D} +do_test selectA-3.63 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY c COLLATE NOCASE + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.64 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + ORDER BY c + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.65 { + execsql { + SELECT a,b,c FROM t3 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + ORDER BY c COLLATE NOCASE + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.66 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t3 + ORDER BY c + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.67 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t3 WHERE b<'d' + ORDER BY c DESC, a + } +} {abc e e hello d D} +do_test selectA-3.68 { + execsql { + SELECT a,b,c FROM t1 EXCEPT SELECT a,b,c FROM t1 WHERE b<'d' + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT b,c,a FROM t3 + ORDER BY c DESC, a + } +} {abc e e hello d D} +do_test selectA-3.69 { + execsql { + SELECT a,b,c FROM t1 INTERSECT SELECT a,b,c FROM t1 WHERE b<'d' + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT b,c,a FROM t3 + ORDER BY c COLLATE NOCASE + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.70 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' INTERSECT SELECT a,b,c FROM t1 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT b,c,a FROM t3 + ORDER BY c + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.71 { + execsql { + SELECT a,b,c FROM t1 WHERE b<'d' + INTERSECT SELECT a,b,c FROM t1 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT b,c,a FROM t3 + INTERSECT SELECT a,b,c FROM t1 + EXCEPT SELECT x,y,z FROM t2 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT y,x,z FROM t2 + INTERSECT SELECT a,b,c FROM t1 + EXCEPT SELECT c,b,a FROM t3 + ORDER BY c + } +} {1 a a 9.9 b B {} C c} +do_test selectA-3.72 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.73 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-3.74 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.75 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-3.76 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE,a,c + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.77 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY b COLLATE NOCASE DESC,a,c + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.78 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.79 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.80 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.81 { + execsql { + SELECT a,b,c FROM t3 UNION SELECT x,y,z FROM t2 + ORDER BY c COLLATE BINARY DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-3.82 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY a,b,c + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.83 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY a DESC,b,c + } +} {hare m M abc e e mad Z z hello d D 5200000.0 X x 9.9 b B 1 a a -23 Y y {} C c {} U u} +do_test selectA-3.84 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY a,c,b + } +} {{} C c {} U u -23 Y y 1 a a 9.9 b B 5200000.0 X x hello d D mad Z z abc e e hare m M} +do_test selectA-3.85 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY b,a,c + } +} {{} C c {} U u 5200000.0 X x -23 Y y mad Z z 1 a a 9.9 b B hello d D abc e e hare m M} +do_test selectA-3.86 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY y COLLATE NOCASE,x,z + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.87 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY y COLLATE NOCASE DESC,x,z + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.88 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY c,b,a + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.89 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY c,a,b + } +} {1 a a 9.9 b B {} C c hello d D abc e e hare m M {} U u 5200000.0 X x -23 Y y mad Z z} +do_test selectA-3.90 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY c DESC,a,b + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.91 { + execsql { + SELECT x,y,z FROM t2 UNION SELECT a,b,c FROM t3 + ORDER BY z COLLATE BINARY DESC,x,y + } +} {mad Z z -23 Y y 5200000.0 X x {} U u abc e e {} C c 1 a a hare m M hello d D 9.9 b B} +do_test selectA-3.92 { + execsql { + SELECT x,y,z FROM t2 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT c,b,a FROM t1 + UNION SELECT a,b,c FROM t3 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT c,b,a FROM t1 + UNION SELECT a,b,c FROM t3 + ORDER BY y COLLATE NOCASE DESC,x,z + } +} {mad Z z -23 Y y 5200000.0 X x {} U u hare m M abc e e hello d D {} C c 9.9 b B 1 a a} +do_test selectA-3.93 { + execsql { + SELECT upper((SELECT c FROM t1 UNION SELECT z FROM t2 ORDER BY 1)); + } +} {A} +do_test selectA-3.94 { + execsql { + SELECT lower((SELECT c FROM t1 UNION ALL SELECT z FROM t2 ORDER BY 1)); + } +} {a} +do_test selectA-3.95 { + execsql { + SELECT lower((SELECT c FROM t1 INTERSECT SELECT z FROM t2 ORDER BY 1)); + } +} {{}} +do_test selectA-3.96 { + execsql { + SELECT lower((SELECT z FROM t2 EXCEPT SELECT c FROM t1 ORDER BY 1)); + } +} {m} +do_test selectA-3.97 { + execsql { + SELECT upper((SELECT x FROM ( + SELECT x,y,z FROM t2 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT c,b,a FROM t1 + UNION SELECT a,b,c FROM t3 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT c,b,a FROM t1 + UNION SELECT a,b,c FROM t3 + ORDER BY y COLLATE NOCASE DESC,x,z))) + } +} {MAD} +do_execsql_test selectA-3.98 { + WITH RECURSIVE + xyz(n) AS ( + SELECT upper((SELECT x FROM ( + SELECT x,y,z FROM t2 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT c,b,a FROM t1 + UNION SELECT a,b,c FROM t3 + INTERSECT SELECT a,b,c FROM t3 + EXCEPT SELECT c,b,a FROM t1 + UNION SELECT a,b,c FROM t3 + ORDER BY y COLLATE NOCASE DESC,x,z))) + UNION ALL + SELECT n || '+' FROM xyz WHERE length(n)<5 + ) + SELECT n FROM xyz ORDER BY +n; +} {MAD MAD+ MAD++} + +#------------------------------------------------------------------------- +# At one point the following code exposed a temp register reuse problem. +# +proc f {args} { return 1 } +db func f f + +do_execsql_test 4.1.1 { + CREATE TABLE t4(a, b); + CREATE TABLE t5(c, d); + + INSERT INTO t5 VALUES(1, 'x'); + INSERT INTO t5 VALUES(2, 'x'); + INSERT INTO t4 VALUES(3, 'x'); + INSERT INTO t4 VALUES(4, 'x'); + + CREATE INDEX i1 ON t4(a); + CREATE INDEX i2 ON t5(c); +} + +do_eqp_test 4.1.2 { + SELECT c, d FROM t5 + UNION ALL + SELECT a, b FROM t4 WHERE f()==f() + ORDER BY 1,2 +} { + QUERY PLAN + `--MERGE (UNION ALL) + |--LEFT + | |--SCAN t5 USING INDEX i2 + | `--USE TEMP B-TREE FOR LAST TERM OF ORDER BY + `--RIGHT + |--SCAN t4 USING INDEX i1 + `--USE TEMP B-TREE FOR LAST TERM OF ORDER BY +} + +do_execsql_test 4.1.3 { + SELECT c, d FROM t5 + UNION ALL + SELECT a, b FROM t4 WHERE f()==f() + ORDER BY 1,2 +} { + 1 x 2 x 3 x 4 x +} + +do_execsql_test 4.2.1 { + CREATE TABLE t6(a, b); + CREATE TABLE t7(c, d); + + INSERT INTO t7 VALUES(2, 9); + INSERT INTO t6 VALUES(3, 0); + INSERT INTO t6 VALUES(4, 1); + INSERT INTO t7 VALUES(5, 6); + INSERT INTO t6 VALUES(6, 0); + INSERT INTO t7 VALUES(7, 6); + + CREATE INDEX i6 ON t6(a); + CREATE INDEX i7 ON t7(c); +} + +do_execsql_test 4.2.2 { + SELECT c, f(d,c,d,c,d) FROM t7 + UNION ALL + SELECT a, b FROM t6 + ORDER BY 1,2 +} {/2 . 3 . 4 . 5 . 6 . 7 ./} + + +proc strip_rnd {explain} { + regexp -all {sqlite_sq_[0123456789ABCDEF]*} $explain sqlite_sq +} + +proc do_same_test {tn q1 args} { + set r2 [strip_rnd [db eval "EXPLAIN $q1"]] + set i 1 + foreach q $args { + set tst [subst -nocommands {strip_rnd [db eval "EXPLAIN $q"]}] + uplevel do_test $tn.$i [list $tst] [list $r2] + incr i + } +} + +do_execsql_test 5.0 { + CREATE TABLE t8(a, b); + CREATE TABLE t9(c, d); +} {} + +do_same_test 5.1 { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY a; +} { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t8.a; +} { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY 1; +} { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY c; +} { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t9.c; +} + +do_same_test 5.2 { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY a COLLATE NOCASE +} { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t8.a COLLATE NOCASE +} { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY 1 COLLATE NOCASE +} { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY c COLLATE NOCASE +} { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t9.c COLLATE NOCASE +} + +do_same_test 5.3 { + SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY b, c COLLATE NOCASE +} { + SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY 2, 1 COLLATE NOCASE +} { + SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, a COLLATE NOCASE +} { + SELECT a, b FROM t8 EXCEPT SELECT * FROM t9 ORDER BY t9.d, c COLLATE NOCASE +} { + SELECT * FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, t8.a COLLATE NOCASE +} + +do_catchsql_test 5.4 { + SELECT * FROM t8 UNION SELECT * FROM t9 ORDER BY a+b COLLATE NOCASE +} {1 {1st ORDER BY term does not match any column in the result set}} + +do_execsql_test 6.1 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + CREATE TABLE t1(a INTEGER); + CREATE TABLE t2(b TEXT); + INSERT INTO t2(b) VALUES('12345'); + SELECT * FROM (SELECT a FROM t1 UNION SELECT b FROM t2) WHERE a=a; +} {12345} + +# 2020-06-15 ticket 8f157e8010b22af0 +# +reset_db +do_execsql_test 7.1 { + CREATE TABLE t1(c1); INSERT INTO t1 VALUES(12),(123),(1234),(NULL),('abc'); + CREATE TABLE t2(c2); INSERT INTO t2 VALUES(44),(55),(123); + CREATE TABLE t3(c3,c4); INSERT INTO t3 VALUES(66,1),(123,2),(77,3); + CREATE VIEW t4 AS SELECT c3 FROM t3; + CREATE VIEW t5 AS SELECT c3 FROM t3 ORDER BY c4; +} +do_execsql_test 7.2 { + SELECT * FROM t1, t2 WHERE c1=(SELECT 123 INTERSECT SELECT c2 FROM t4) AND c1=123; +} {123 123} +do_execsql_test 7.3 { + SELECT * FROM t1, t2 WHERE c1=(SELECT 123 INTERSECT SELECT c2 FROM t5) AND c1=123; +} {123 123} +do_execsql_test 7.4 { + CREATE TABLE a(b); + CREATE VIEW c(d) AS SELECT b FROM a ORDER BY b; + SELECT sum(d) OVER( PARTITION BY(SELECT 0 FROM c JOIN a WHERE b =(SELECT b INTERSECT SELECT d FROM c) AND b = 123)) FROM c; +} {} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 8.0 { + CREATE TABLE x1(x); + CREATE TABLE t1(a, b, c, d); + CREATE INDEX t1a ON t1(a); + CREATE INDEX t1b ON t1(b); +} + +do_execsql_test 8.1 { + SELECT 'ABCD' FROM t1 + WHERE (a=? OR b=?) + AND (0 OR (SELECT 'xyz' INTERSECT SELECT a ORDER BY 1)) +} {} + +#------------------------------------------------------------------------- +# dbsqlfuzz a34f455c91ad75a0cf8cd9476841903f42930a7a +# +reset_db +do_execsql_test 9.0 { + CREATE TABLE t1(a COLLATE nocase); + CREATE TABLE t2(b COLLATE nocase); + + INSERT INTO t1 VALUES('ABC'); + INSERT INTO t2 VALUES('abc'); +} + +do_execsql_test 9.1 { + SELECT a FROM t1 INTERSECT SELECT b FROM t2; +} {ABC} + +do_execsql_test 9.2 { + SELECT * FROM ( + SELECT a FROM t1 INTERSECT SELECT b FROM t2 + ) WHERE a||'' = 'ABC'; +} {ABC} + + + +finish_test diff --git a/testing/sqlite3/selectB.test b/testing/sqlite3/selectB.test new file mode 100644 index 000000000..05ec9c6bd --- /dev/null +++ b/testing/sqlite3/selectB.test @@ -0,0 +1,426 @@ +# 2008 June 24 +# +# 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. +# +# $Id: selectB.test,v 1.10 2009/04/02 16:59:47 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable !compound { + finish_test + return +} + +proc test_transform {testname sql1 sql2 results} { + set ::vdbe1 [list] + set ::vdbe2 [list] + db eval "explain $sql1" { lappend ::vdbe1 $opcode } + db eval "explain $sql2" { lappend ::vdbe2 $opcode } + + do_test $testname.transform { + set ::vdbe1 + } $::vdbe2 + + set ::sql1 $sql1 + do_test $testname.sql1 { + execsql $::sql1 + } $results + + set ::sql2 $sql2 + do_test $testname.sql2 { + execsql $::sql2 + } $results +} + +do_test selectB-1.1 { + execsql { + CREATE TABLE t1(a, b, c); + CREATE TABLE t2(d, e, f); + + INSERT INTO t1 VALUES( 2, 4, 6); + INSERT INTO t1 VALUES( 8, 10, 12); + INSERT INTO t1 VALUES(14, 16, 18); + + INSERT INTO t2 VALUES(3, 6, 9); + INSERT INTO t2 VALUES(12, 15, 18); + INSERT INTO t2 VALUES(21, 24, 27); + } +} {} + +for {set ii 1} {$ii <= 2} {incr ii} { + + if {$ii == 2} { + do_test selectB-2.1 { + execsql { + CREATE INDEX i1 ON t1(a); + CREATE INDEX i2 ON t2(d); + } + } {} + } + + test_transform selectB-$ii.2 { + SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) + } { + SELECT a FROM t1 UNION ALL SELECT d FROM t2 + } {2 8 14 3 12 21} + + test_transform selectB-$ii.3 { + SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1 + } { + SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 + } {2 3 8 12 14 21} + + test_transform selectB-$ii.4 { + SELECT * FROM + (SELECT a FROM t1 UNION ALL SELECT d FROM t2) + WHERE a>10 ORDER BY 1 + } { + SELECT a FROM t1 WHERE a>10 UNION ALL SELECT d FROM t2 WHERE d>10 ORDER BY 1 + } {12 14 21} + + test_transform selectB-$ii.5 { + SELECT * FROM + (SELECT a FROM t1 UNION ALL SELECT d FROM t2) + WHERE a>10 ORDER BY a + } { + SELECT a FROM t1 WHERE a>10 + UNION ALL + SELECT d FROM t2 WHERE d>10 + ORDER BY a + } {12 14 21} + + test_transform selectB-$ii.6 { + SELECT * FROM + (SELECT a FROM t1 UNION ALL SELECT d FROM t2 WHERE d > 12) + WHERE a>10 ORDER BY a + } { + SELECT a FROM t1 WHERE a>10 + UNION ALL + SELECT d FROM t2 WHERE d>12 AND d>10 + ORDER BY a + } {14 21} + + test_transform selectB-$ii.7 { + SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1 + LIMIT 2 + } { + SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 2 + } {2 3} + + test_transform selectB-$ii.8 { + SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1 + LIMIT 2 OFFSET 3 + } { + SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 2 OFFSET 3 + } {12 14} + + test_transform selectB-$ii.9 { + SELECT * FROM ( + SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1 + ) + } { + SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1 + } {2 8 14 3 12 21 6 12 18} + + test_transform selectB-$ii.10 { + SELECT * FROM ( + SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1 + ) ORDER BY 1 + } { + SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1 + ORDER BY 1 + } {2 3 6 8 12 12 14 18 21} + + test_transform selectB-$ii.11 { + SELECT * FROM ( + SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1 + ) WHERE a>=10 ORDER BY 1 LIMIT 3 + } { + SELECT a FROM t1 WHERE a>=10 UNION ALL SELECT d FROM t2 WHERE d>=10 + UNION ALL SELECT c FROM t1 WHERE c>=10 + ORDER BY 1 LIMIT 3 + } {12 12 14} + + test_transform selectB-$ii.12 { + SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2 LIMIT 2) + } { + SELECT a FROM t1 UNION ALL SELECT d FROM t2 LIMIT 2 + } {2 8} + + # An ORDER BY in a compound subqueries defeats flattening. Ticket #3773 + # test_transform selectB-$ii.13 { + # SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY a ASC) + # } { + # SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 ASC + # } {2 3 8 12 14 21} + # + # test_transform selectB-$ii.14 { + # SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY a DESC) + # } { + # SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 DESC + # } {21 14 12 8 3 2} + # + # test_transform selectB-$ii.14 { + # SELECT * FROM ( + # SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY a DESC + # ) LIMIT 2 OFFSET 2 + # } { + # SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 DESC + # LIMIT 2 OFFSET 2 + # } {12 8} + # + # test_transform selectB-$ii.15 { + # SELECT * FROM ( + # SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY a ASC, e DESC + # ) + # } { + # SELECT a, b FROM t1 UNION ALL SELECT d, e FROM t2 ORDER BY a ASC, e DESC + # } {2 4 3 6 8 10 12 15 14 16 21 24} +} + +do_test selectB-3.0 { + execsql { + DROP INDEX i1; + DROP INDEX i2; + } +} {} + +for {set ii 3} {$ii <= 6} {incr ii} { + + switch $ii { + 4 { + optimization_control db query-flattener off + } + 5 { + optimization_control db query-flattener on + do_test selectB-5.0 { + execsql { + CREATE INDEX i1 ON t1(a); + CREATE INDEX i2 ON t1(b); + CREATE INDEX i3 ON t1(c); + CREATE INDEX i4 ON t2(d); + CREATE INDEX i5 ON t2(e); + CREATE INDEX i6 ON t2(f); + } + } {} + } + 6 { + optimization_control db query-flattener off + } + } + + do_test selectB-$ii.1 { + execsql { + SELECT DISTINCT * FROM + (SELECT c FROM t1 UNION ALL SELECT e FROM t2) + ORDER BY 1; + } + } {6 12 15 18 24} + + do_test selectB-$ii.2 { + execsql { + SELECT c, count(*) FROM + (SELECT c FROM t1 UNION ALL SELECT e FROM t2) + GROUP BY c ORDER BY 1; + } + } {6 2 12 1 15 1 18 1 24 1} + do_test selectB-$ii.3 { + execsql { + SELECT c, count(*) FROM + (SELECT c FROM t1 UNION ALL SELECT e FROM t2) + GROUP BY c HAVING count(*)>1; + } + } {6 2} + do_test selectB-$ii.4 { + execsql { + SELECT t4.c, t3.a FROM + (SELECT c FROM t1 UNION ALL SELECT e FROM t2) AS t4, t1 AS t3 + WHERE t3.a=14 + ORDER BY 1 + } + } {6 14 6 14 12 14 15 14 18 14 24 14} + + do_test selectB-$ii.5 { + execsql { + SELECT d FROM t2 + EXCEPT + SELECT a FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) + } + } {} + do_test selectB-$ii.6 { + execsql { + SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) + EXCEPT + SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) + } + } {} + do_test selectB-$ii.7 { + execsql { + SELECT c FROM t1 + EXCEPT + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + } + } {12} + do_test selectB-$ii.8 { + execsql { + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + EXCEPT + SELECT c FROM t1 + } + } {9 15 24 27} + do_test selectB-$ii.9 { + execsql { + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + EXCEPT + SELECT c FROM t1 + ORDER BY c DESC + } + } {27 24 15 9} + + do_test selectB-$ii.10 { + execsql { + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + UNION + SELECT c FROM t1 + ORDER BY c DESC + } + } {27 24 18 15 12 9 6} + do_test selectB-$ii.11 { + execsql { + SELECT c FROM t1 + UNION + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + ORDER BY c + } + } {6 9 12 15 18 24 27} + do_test selectB-$ii.12 { + execsql { + SELECT c FROM t1 UNION SELECT e FROM t2 UNION ALL SELECT f FROM t2 + ORDER BY c + } + } {6 9 12 15 18 18 24 27} + do_test selectB-$ii.13 { + execsql { + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + UNION + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + ORDER BY 1 + } + } {6 9 15 18 24 27} + + do_test selectB-$ii.14 { + execsql { + SELECT c FROM t1 + INTERSECT + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + ORDER BY 1 + } + } {6 18} + do_test selectB-$ii.15 { + execsql { + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + INTERSECT + SELECT c FROM t1 + ORDER BY 1 + } + } {6 18} + do_test selectB-$ii.16 { + execsql { + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + INTERSECT + SELECT * FROM (SELECT e FROM t2 UNION ALL SELECT f FROM t2) + ORDER BY 1 + } + } {6 9 15 18 24 27} + + do_test selectB-$ii.17 { + execsql { + SELECT * FROM ( + SELECT a FROM t1 UNION ALL SELECT d FROM t2 LIMIT 4 + ) LIMIT 2 + } + } {2 8} + + do_test selectB-$ii.18 { + execsql { + SELECT * FROM ( + SELECT a FROM t1 UNION ALL SELECT d FROM t2 LIMIT 4 OFFSET 2 + ) LIMIT 2 + } + } {14 3} + + do_test selectB-$ii.19 { + execsql { + SELECT * FROM ( + SELECT DISTINCT (a/10) FROM t1 UNION ALL SELECT DISTINCT(d%2) FROM t2 + ) + } + } {0 1 1 0} + + do_test selectB-$ii.20 { + execsql { + SELECT DISTINCT * FROM ( + SELECT DISTINCT (a/10) FROM t1 UNION ALL SELECT DISTINCT(d%2) FROM t2 + ) + } + } {0 1} + + do_test selectB-$ii.21 { + execsql { + SELECT * FROM (SELECT * FROM t1 UNION ALL SELECT * FROM t2) ORDER BY a+b + } + } {2 4 6 3 6 9 8 10 12 12 15 18 14 16 18 21 24 27} + + do_test selectB-$ii.22 { + execsql { + SELECT * FROM (SELECT 345 UNION ALL SELECT d FROM t2) ORDER BY 1; + } + } {3 12 21 345} + + do_test selectB-$ii.23 { + execsql { + SELECT x, y FROM ( + SELECT a AS x, b AS y FROM t1 + UNION ALL + SELECT a*10 + 0.1, f*10 + 0.1 FROM t1 JOIN t2 ON (c=d) + UNION ALL + SELECT a*100, b*100 FROM t1 + ) ORDER BY 1; + } + } {2 4 8 10 14 16 80.1 180.1 200 400 800 1000 1400 1600} + + do_test selectB-$ii.24 { + execsql { + SELECT x, y FROM ( + SELECT a AS x, b AS y FROM t1 + UNION ALL + SELECT a*10 + 0.1, f*10 + 0.1 FROM t1 LEFT JOIN t2 ON (c=d) + UNION ALL + SELECT a*100, b*100 FROM t1 + ) ORDER BY 1; + } + } {2 4 8 10 14 16 20.1 {} 80.1 180.1 140.1 {} 200 400 800 1000 1400 1600} + + do_test selectB-$ii.25 { + execsql { + SELECT x+y FROM ( + SELECT a AS x, b AS y FROM t1 + UNION ALL + SELECT a*10 + 0.1, f*10 + 0.1 FROM t1 LEFT JOIN t2 ON (c=d) + UNION ALL + SELECT a*100, b*100 FROM t1 + ) WHERE y+x NOT NULL ORDER BY 1; + } + } {6 18 30 260.2 600 1800 3000} +} + +finish_test diff --git a/testing/sqlite3/selectC.test b/testing/sqlite3/selectC.test new file mode 100644 index 000000000..42fa1d11b --- /dev/null +++ b/testing/sqlite3/selectC.test @@ -0,0 +1,275 @@ +# 2008 September 16 +# +# 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. +# +# $Id: selectC.test,v 1.5 2009/05/17 15:26:21 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix selectC + +# Ticket # +do_test selectC-1.1 { + execsql { + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(1,'aaa','bbb'); + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 VALUES(2,'ccc','ddd'); + + SELECT DISTINCT a AS x, b||c AS y + FROM t1 + WHERE y IN ('aaabbb','xxx'); + } +} {1 aaabbb} +do_test selectC-1.2 { + execsql { + SELECT DISTINCT a AS x, b||c AS y + FROM t1 + WHERE b||c IN ('aaabbb','xxx'); + } +} {1 aaabbb} +do_test selectC-1.3 { + execsql { + SELECT DISTINCT a AS x, b||c AS y + FROM t1 + WHERE y='aaabbb' + } +} {1 aaabbb} +do_test selectC-1.4 { + execsql { + SELECT DISTINCT a AS x, b||c AS y + FROM t1 + WHERE b||c='aaabbb' + } +} {1 aaabbb} +do_test selectC-1.5 { + execsql { + SELECT DISTINCT a AS x, b||c AS y + FROM t1 + WHERE x=2 + } +} {2 cccddd} +do_test selectC-1.6 { + execsql { + SELECT DISTINCT a AS x, b||c AS y + FROM t1 + WHERE a=2 + } +} {2 cccddd} +do_test selectC-1.7 { + execsql { + SELECT DISTINCT a AS x, b||c AS y + FROM t1 + WHERE +y='aaabbb' + } +} {1 aaabbb} +do_test selectC-1.8 { + execsql { + SELECT a AS x, b||c AS y + FROM t1 + GROUP BY x, y + HAVING y='aaabbb' + } +} {1 aaabbb} +do_test selectC-1.9 { + execsql { + SELECT a AS x, b||c AS y + FROM t1 + GROUP BY x, y + HAVING b||c='aaabbb' + } +} {1 aaabbb} +do_test selectC-1.10 { + execsql { + SELECT a AS x, b||c AS y + FROM t1 + WHERE y='aaabbb' + GROUP BY x, y + } +} {1 aaabbb} +do_test selectC-1.11 { + execsql { + SELECT a AS x, b||c AS y + FROM t1 + WHERE b||c='aaabbb' + GROUP BY x, y + } +} {1 aaabbb} +proc longname_toupper x {return [string toupper $x]} +db function uppercaseconversionfunctionwithaverylongname longname_toupper +do_test selectC-1.12.1 { + execsql { + SELECT DISTINCT upper(b) AS x + FROM t1 + ORDER BY x + } +} {AAA CCC} +do_test selectC-1.12.2 { + execsql { + SELECT DISTINCT uppercaseconversionfunctionwithaverylongname(b) AS x + FROM t1 + ORDER BY x + } +} {AAA CCC} +do_test selectC-1.13.1 { + execsql { + SELECT upper(b) AS x + FROM t1 + GROUP BY x + ORDER BY x + } +} {AAA CCC} +do_test selectC-1.13.2 { + execsql { + SELECT uppercaseconversionfunctionwithaverylongname(b) AS x + FROM t1 + GROUP BY x + ORDER BY x + } +} {AAA CCC} +do_test selectC-1.14.1 { + execsql { + SELECT upper(b) AS x + FROM t1 + ORDER BY x DESC + } +} {CCC AAA AAA} +do_test selectC-1.14.2 { + execsql { + SELECT uppercaseconversionfunctionwithaverylongname(b) AS x + FROM t1 + ORDER BY x DESC + } +} {CCC AAA AAA} + +# The following query used to leak memory. Verify that has been fixed. +# +ifcapable trigger&&compound { + do_test selectC-2.1 { + catchsql { + CREATE TABLE t21a(a,b); + INSERT INTO t21a VALUES(1,2); + CREATE TABLE t21b(n); + CREATE TRIGGER r21 AFTER INSERT ON t21b BEGIN + SELECT a FROM t21a WHERE a>new.x UNION ALL + SELECT b FROM t21a WHERE b>new.x ORDER BY 1 LIMIT 2; + END; + INSERT INTO t21b VALUES(6); + } + } {1 {no such column: new.x}} +} + +# Check that ticket [883034dcb5] is fixed. +# +do_test selectC-3.1 { + execsql { + CREATE TABLE person ( + org_id TEXT NOT NULL, + nickname TEXT NOT NULL, + license TEXT, + CONSTRAINT person_pk PRIMARY KEY (org_id, nickname), + CONSTRAINT person_license_uk UNIQUE (license) + ); + INSERT INTO person VALUES('meyers', 'jack', '2GAT123'); + INSERT INTO person VALUES('meyers', 'hill', 'V345FMP'); + INSERT INTO person VALUES('meyers', 'jim', '2GAT138'); + INSERT INTO person VALUES('smith', 'maggy', ''); + INSERT INTO person VALUES('smith', 'jose', 'JJZ109'); + INSERT INTO person VALUES('smith', 'jack', 'THX138'); + INSERT INTO person VALUES('lakeside', 'dave', '953OKG'); + INSERT INTO person VALUES('lakeside', 'amy', NULL); + INSERT INTO person VALUES('lake-apts', 'tom', NULL); + INSERT INTO person VALUES('acorn', 'hideo', 'CQB421'); + + SELECT + org_id, + count((NOT (org_id IS NULL)) AND (NOT (nickname IS NULL))) + FROM person + WHERE (CASE WHEN license != '' THEN 1 ELSE 0 END) + GROUP BY 1; + } +} {acorn 1 lakeside 1 meyers 3 smith 2} +do_test selectC-3.2 { + execsql { + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t2 VALUES('abc', 'xxx'); + INSERT INTO t2 VALUES('def', 'yyy'); + SELECT a, max(b || a) FROM t2 WHERE (b||b||b)!='value' GROUP BY a; + } +} {abc xxxabc def yyydef} +do_test selectC-3.3 { + execsql { + SELECT b, max(a || b) FROM t2 WHERE (b||b||b)!='value' GROUP BY a; + } +} {xxx abcxxx yyy defyyy} + + +proc udf {} { incr ::udf } +set ::udf 0 +db function udf udf + +do_execsql_test selectC-4.1 { + create table t_distinct_bug (a, b, c); + insert into t_distinct_bug values ('1', '1', 'a'); + insert into t_distinct_bug values ('1', '2', 'b'); + insert into t_distinct_bug values ('1', '3', 'c'); + insert into t_distinct_bug values ('1', '1', 'd'); + insert into t_distinct_bug values ('1', '2', 'e'); + insert into t_distinct_bug values ('1', '3', 'f'); +} {} + +do_execsql_test selectC-4.2 { + select a from (select distinct a, b from t_distinct_bug) +} {1 1 1} + +do_execsql_test selectC-4.2b { + CREATE VIEW v42b AS SELECT DISTINCT a, b FROM t_distinct_bug; + SELECT a FROM v42b; +} {1 1 1} + +do_execsql_test selectC-4.3 { + select a, udf() from (select distinct a, b from t_distinct_bug) +} {1 1 1 2 1 3} + +#------------------------------------------------------------------------- +# Test that the problem in ticket #190c2507 has been fixed. +# +do_execsql_test 5.0 { + CREATE TABLE x1(a); + CREATE TABLE x2(b); + CREATE TABLE x3(c); + CREATE VIEW vvv AS SELECT b FROM x2 ORDER BY 1; + + INSERT INTO x1 VALUES('a'), ('b'); + INSERT INTO x2 VALUES(22), (23), (25), (24), (21); + INSERT INTO x3 VALUES(302), (303), (301); +} + +do_execsql_test 5.1 { + CREATE TABLE x4 AS SELECT b FROM vvv UNION ALL SELECT c from x3; + SELECT * FROM x4; +} {21 22 23 24 25 302 303 301} + +do_execsql_test 5.2 { + SELECT * FROM x1, x4 +} { + a 21 a 22 a 23 a 24 a 25 a 302 a 303 a 301 + b 21 b 22 b 23 b 24 b 25 b 302 b 303 b 301 +} + +do_execsql_test 5.3 { + SELECT * FROM x1, (SELECT b FROM vvv UNION ALL SELECT c from x3) ORDER BY 1,2; +} { + a 21 a 22 a 23 a 24 a 25 a 301 a 302 a 303 + b 21 b 22 b 23 b 24 b 25 b 301 b 302 b 303 +} + +finish_test diff --git a/testing/sqlite3/selectD.test b/testing/sqlite3/selectD.test new file mode 100644 index 000000000..818d8ccc0 --- /dev/null +++ b/testing/sqlite3/selectD.test @@ -0,0 +1,174 @@ +# 2012 December 19 +# +# 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 name resolution in SELECT +# statements that have parenthesized FROM clauses. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + + +for {set i 1} {$i<=2} {incr i} { + db close + forcedelete test$i.db + sqlite3 db test$i.db + if {$i==2} { + optimization_control db query-flattener off + } + do_test selectD-$i.0 { + db eval { + ATTACH ':memory:' AS aux1; + CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(111,'x1'); + CREATE TABLE t2(a,b); INSERT INTO t2 VALUES(222,'x2'); + CREATE TEMP TABLE t3(a,b); INSERT INTO t3 VALUES(333,'x3'); + CREATE TABLE main.t4(a,b); INSERT INTO main.t4 VALUES(444,'x4'); + CREATE TABLE aux1.t4(a,b); INSERT INTO aux1.t4 VALUES(555,'x5'); + } + } {} + do_test selectD-$i.1 { + db eval { + SELECT * + FROM (t1), (t2), (t3), (t4) + WHERE t4.a=t3.a+111 + AND t3.a=t2.a+111 + AND t2.a=t1.a+111; + } + } {111 x1 222 x2 333 x3 444 x4} + do_test selectD-$i.2.1 { + db eval { + SELECT * + FROM t1 JOIN (t2 JOIN (t3 JOIN t4 ON t4.a=t3.a+111) + ON t3.a=t2.a+111) + ON t2.a=t1.a+111; + } + } {111 x1 222 x2 333 x3 444 x4} + do_test selectD-$i.2.2 { + db eval { + SELECT t3.a + FROM t1 JOIN (t2 JOIN (t3 JOIN t4 ON t4.a=t3.a+111) + ON t3.a=t2.a+111) + ON t2.a=t1.a+111; + } + } {333} + do_test selectD-$i.2.3 { + db eval { + SELECT t3.* + FROM t1 JOIN (t2 JOIN (t3 JOIN t4 ON t4.a=t3.a+111) + ON t3.a=t2.a+111) + ON t2.a=t1.a+111; + } + } {333 x3} + do_test selectD-$i.2.3 { + db eval { + SELECT t3.*, t2.* + FROM t1 JOIN (t2 JOIN (t3 JOIN t4 ON t4.a=t3.a+111) + ON t3.a=t2.a+111) + ON t2.a=t1.a+111; + } + } {333 x3 222 x2} + do_test selectD-$i.2.4 { + db eval { + SELECT * + FROM t1 JOIN (t2 JOIN (main.t4 JOIN aux1.t4 ON aux1.t4.a=main.t4.a+111) + ON main.t4.a=t2.a+222) + ON t2.a=t1.a+111; + } + } {111 x1 222 x2 444 x4 555 x5} + do_test selectD-$i.2.5 { + db eval { + SELECT * + FROM t1 JOIN (t2 JOIN (main.t4 AS x JOIN aux1.t4 ON aux1.t4.a=x.a+111) + ON x.a=t2.a+222) + ON t2.a=t1.a+111; + } + } {111 x1 222 x2 444 x4 555 x5} + do_test selectD-$i.2.6 { + catchsql { + SELECT * + FROM t1 JOIN (t2 JOIN (main.t4 JOIN aux.t4 ON aux.t4.a=main.t4.a+111) + ON main.t4.a=t2.a+222) + ON t2.a=t1.a+111; + } + } {1 {no such table: aux.t4}} + do_test selectD-$i.2.7 { + db eval { + SELECT x.a, y.b + FROM t1 JOIN (t2 JOIN (main.t4 x JOIN aux1.t4 y ON y.a=x.a+111) + ON x.a=t2.a+222) + ON t2.a=t1.a+111; + } + } {444 x5} + do_test selectD-$i.3 { + db eval { + UPDATE t2 SET a=111; + UPDATE t3 SET a=111; + UPDATE t4 SET a=111; + SELECT * + FROM t1 JOIN (t2 JOIN (t3 JOIN t4 USING(a)) USING (a)) USING (a); + } + } {111 x1 x2 x3 x4} + do_test selectD-$i.4 { + db eval { + UPDATE t2 SET a=111; + UPDATE t3 SET a=111; + UPDATE t4 SET a=111; + SELECT * + FROM t1 LEFT JOIN (t2 LEFT JOIN (t3 LEFT JOIN t4 USING(a)) + USING (a)) + USING (a); + } + } {111 x1 x2 x3 x4} + do_test selectD-$i.5 { + db eval { + UPDATE t3 SET a=222; + UPDATE t4 SET a=222; + SELECT * + FROM (t1 LEFT JOIN t2 USING(a)) JOIN (t3 LEFT JOIN t4 USING(a)) + ON t1.a=t3.a-111; + } + } {111 x1 x2 222 x3 x4} + do_test selectD-$i.6 { + db eval { + UPDATE t4 SET a=333; + SELECT * + FROM (t1 LEFT JOIN t2 USING(a)) JOIN (t3 LEFT JOIN t4 USING(a)) + ON t1.a=t3.a-111; + } + } {111 x1 x2 222 x3 {}} + do_test selectD-$i.7 { + db eval { + SELECT t1.*, t2.*, t3.*, t4.b + FROM (t1 LEFT JOIN t2 USING(a)) JOIN (t3 LEFT JOIN t4 USING(a)) + ON t1.a=t3.a-111; + } + } {111 x1 111 x2 222 x3 {}} +} + +# The following test was added on 2013-04-24 in order to verify that +# the datatypes and affinities of sub-sub-queries are set prior to computing +# the datatypes and affinities of the parent sub-queries because the +# latter computation depends on the former. +# +do_execsql_test selectD-4.1 { + CREATE TABLE t41(a INTEGER PRIMARY KEY, b INTEGER); + CREATE TABLE t42(d INTEGER PRIMARY KEY, e INTEGER); + CREATE TABLE t43(f INTEGER PRIMARY KEY, g INTEGER); + EXPLAIN QUERY PLAN + SELECT * + FROM t41 + LEFT JOIN (SELECT count(*) AS cnt, x1.d + FROM (t42 INNER JOIN t43 ON d=g) AS x1 + WHERE x1.d>5 + GROUP BY x1.d) AS x2 + ON t41.b=x2.d; +} {/SEARCH x2 USING AUTOMATIC/} + +finish_test diff --git a/testing/sqlite3/selectE.test b/testing/sqlite3/selectE.test new file mode 100644 index 000000000..1cabeff37 --- /dev/null +++ b/testing/sqlite3/selectE.test @@ -0,0 +1,100 @@ +# 2013-05-07 +# +# 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 compound SELECT statements +# that have ORDER BY clauses with collating sequences that differ +# from the collating sequence used for comparison in the compound. +# +# Ticket 6709574d2a8d8b9be3a9cb1afbf4ff2de48ea4e7: +# drh added on 2013-05-06 15:21:16: +# +# In the code shown below (which is intended to be run from the +# sqlite3.exe command-line tool) the three SELECT statements should all +# generate the same answer. But the third one does not. It is as if the +# COLLATE clause on the ORDER BY somehow got pulled into the EXCEPT +# operator. Note that the ".print" commands are instructions to the +# sqlite3.exe shell program to output delimiter lines so that you can more +# easily tell where the output of one query ends and the next query +# begins. +# +# CREATE TABLE t1(a); +# INSERT INTO t1 VALUES('abc'),('def'); +# CREATE TABLE t2(a); +# INSERT INTO t2 VALUES('DEF'); +# +# SELECT a FROM t1 EXCEPT SELECT a FROM t2 ORDER BY a; +# .print ----- +# SELECT a FROM (SELECT a FROM t1 EXCEPT SELECT a FROM t2) +# ORDER BY a COLLATE nocase; +# .print ----- +# SELECT a FROM t1 EXCEPT SELECT a FROM t2 ORDER BY a COLLATE nocase; +# +# Bisecting shows that this problem was introduced in SQLite version 3.6.0 +# by check-in [8bbfa97837a74ef] on 2008-06-15. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_test selectE-1.0 { + db eval { + CREATE TABLE t1(a); + INSERT INTO t1 VALUES('abc'),('def'),('ghi'); + CREATE TABLE t2(a); + INSERT INTO t2 VALUES('DEF'),('abc'); + CREATE TABLE t3(a); + INSERT INTO t3 VALUES('def'),('jkl'); + + SELECT a FROM t1 EXCEPT SELECT a FROM t2 + ORDER BY a COLLATE nocase; + } +} {def ghi} +do_test selectE-1.1 { + db eval { + SELECT a FROM t2 EXCEPT SELECT a FROM t3 + ORDER BY a COLLATE nocase; + } +} {abc DEF} +do_test selectE-1.2 { + db eval { + SELECT a FROM t2 EXCEPT SELECT a FROM t3 + ORDER BY a COLLATE binary; + } +} {DEF abc} +do_test selectE-1.3 { + db eval { + SELECT a FROM t2 EXCEPT SELECT a FROM t3 + ORDER BY a; + } +} {DEF abc} + +do_test selectE-2.1 { + db eval { + DELETE FROM t2; + DELETE FROM t3; + INSERT INTO t2 VALUES('ABC'),('def'),('GHI'),('jkl'); + INSERT INTO t3 SELECT lower(a) FROM t2; + SELECT a COLLATE nocase FROM t2 EXCEPT SELECT a FROM t3 + ORDER BY 1 + } +} {} +do_test selectE-2.2 { + db eval { + SELECT a COLLATE nocase FROM t2 EXCEPT SELECT a FROM t3 + ORDER BY 1 COLLATE binary + } +} {} + +do_catchsql_test selectE-3.1 { + SELECT 1 EXCEPT SELECT 2 ORDER BY 1 COLLATE nocase EXCEPT SELECT 3; +} {1 {ORDER BY clause should come after EXCEPT not before}} + + +finish_test diff --git a/testing/sqlite3/selectF.test b/testing/sqlite3/selectF.test new file mode 100644 index 000000000..3fb226e01 --- /dev/null +++ b/testing/sqlite3/selectF.test @@ -0,0 +1,49 @@ +# 2014-03-03 +# +# 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 verifies that an OP_Copy operation is used instead of OP_SCopy +# in a compound select in a case where the source register might be changed +# before the copy is used. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix selectF + +do_execsql_test 1 { + BEGIN TRANSACTION; + CREATE TABLE t1(a, b, c); + INSERT INTO "t1" VALUES(1,'one','I'); + CREATE TABLE t2(d, e, f); + INSERT INTO "t2" VALUES(5,'ten','XX'); + INSERT INTO "t2" VALUES(6,NULL,NULL); + + CREATE INDEX i1 ON t1(b, a); + COMMIT; +} + +#explain_i { +# SELECT * FROM t2 +# UNION ALL +# SELECT * FROM t1 WHERE a<5 +# ORDER BY 2, 1 +#} + +do_execsql_test 2 { + SELECT * FROM t2 + UNION ALL + SELECT * FROM t1 WHERE a<5 + ORDER BY 2, 1 +} {6 {} {} 1 one I 5 ten XX} + + + +finish_test diff --git a/testing/sqlite3/selectG.test b/testing/sqlite3/selectG.test new file mode 100644 index 000000000..fab4c4ed4 --- /dev/null +++ b/testing/sqlite3/selectG.test @@ -0,0 +1,59 @@ +# 2015-01-05 +# +# 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 verifies that INSERT operations with a very large number of +# VALUE terms works and does not hit the SQLITE_LIMIT_COMPOUND_SELECT limit. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix selectG + +# Do an INSERT with a VALUES clause that contains 100,000 entries. Verify +# that this insert happens quickly (in less than 10 seconds). Actually, the +# insert will normally happen in less than 0.5 seconds on a workstation, but +# we allow plenty of overhead for slower machines. The speed test checks +# for an O(N*N) inefficiency that was once in the code and that would make +# the insert run for over a minute. +# +do_test 100 { + set sql "CREATE TABLE t1(x);\nINSERT INTO t1(x) VALUES" + for {set i 1} {$i<100000} {incr i} { + append sql "($i)," + } + append sql "($i);" + set microsec [lindex [time {db eval $sql}] 0] + db eval { + SELECT count(x), sum(x), avg(x), $microsec<10000000 FROM t1; + } +} {100000 5000050000 50000.5 1} + +# 2018-01-14. A 100K-entry VALUES clause within a scalar expression does +# not cause processor stack overflow. +# +do_test 110 { + set sql "SELECT (VALUES" + for {set i 1} {$i<100000} {incr i} { + append sql "($i)," + } + append sql "($i));" + db eval $sql +} {1} + +# Only the left-most term of a multi-valued VALUES within a scalar +# expression is evaluated. +# +do_test 120 { + set n [llength [split [db eval "explain $sql"] \n]] + expr {$n<10} +} {1} + +finish_test diff --git a/testing/sqlite3/selectH.test b/testing/sqlite3/selectH.test new file mode 100644 index 000000000..41f0999fe --- /dev/null +++ b/testing/sqlite3/selectH.test @@ -0,0 +1,145 @@ +# 2023-02-16 +# +# 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. +# +#*********************************************************************** +# +# Test cases for the omit-unused-subquery-column optimization. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix selectH + +do_execsql_test 1.1 { + CREATE TABLE t1( + c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, + c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, + c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, + c30, c31, c32, c33, c34, c35, c36, c37, c38, c39, + c40, c41, c42, c43, c44, c45, c46, c47, c48, c49, + c50, c51, c52, c53, c54, c55, c56, c57, c58, c59, + c60, c61, c62, c63, c64, c65 + ); + INSERT INTO t1 VALUES( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65 + ); + CREATE INDEX t1c60 ON t1(c60); +} + +# The SQL counter(N) function adjusts the value of the global +# TCL variable ::selectH_cnt by the value N and returns the new +# value. By putting calls to counter(N) as unused columns in a +# view or subquery, we can check to see if the counter gets incremented, +# and if not that means that the unused column was omitted. +# +unset -nocomplain selectH_cnt +set selectH_cnt 0 +proc selectH_counter {amt} { + global selectH_cnt + incr selectH_cnt $amt + return $selectH_cnt +} +db func counter selectH_counter + +do_execsql_test 1.2 { + SELECT DISTINCT c44 FROM ( + SELECT c0 AS a, *, counter(1) FROM t1 + UNION ALL + SELECT c1 AS a, *, counter(1) FROM t1 + ) WHERE c60=60; +} {44} +do_test 1.3 { + set ::selectH_cnt +} {0} + +do_execsql_test 2.1 { + SELECT a FROM ( + SELECT counter(1) AS cnt, c15 AS a, *, c62 AS b FROM t1 + UNION ALL + SELECT counter(1) AS cnt, c16 AS a, *, c61 AS b FROM t1 + ORDER BY b + ); +} {16 15} +do_test 2.2 { + set ::selectH_cnt +} {0} + +do_execsql_test 3.1 { + CREATE VIEW v1 AS + SELECT c16 AS a, *, counter(1) AS x FROM t1 + UNION ALL + SELECT c17 AS a, *, counter(1) AS x FROM t1 + UNION ALL + SELECT c18 AS a, *, counter(1) AS x FROM t1 + UNION ALL + SELECT c19 AS a, *, counter(1) AS x FROM t1; + SELECT count(*) FROM v1 WHERE c60=60; +} {4} +do_test 3.2 { + set ::selectH_cnt +} {0} +do_execsql_test 3.3 { + SELECT count(a) FROM v1 WHERE c60=60; +} {4} +do_execsql_test 3.4 { + SELECT a FROM v1 WHERE c60=60; +} {16 17 18 19} +do_test 3.5 { + set ::selectH_cnt +} {0} +do_execsql_test 3.6 { + SELECT x FROM v1 WHERE c60=60; +} {1 2 3 4} +do_test 3.7 { + set ::selectH_cnt +} {4} + +# 2023-02-25 dbsqlfuzz bf1d3ed6e0e0dd8766027797d43db40c776d2b15 +# +do_execsql_test 4.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT); + SELECT 1 FROM (SELECT DISTINCT name COLLATE rtrim FROM sqlite_schema + UNION ALL SELECT a FROM t1); +} {1 1} + +do_execsql_test 4.2 { + SELECT DISTINCT name COLLATE rtrim FROM sqlite_schema + UNION ALL + SELECT a FROM t1 +} {v1 t1} + +#------------------------------------------------------------------------- +# forum post https://sqlite.org/forum/forumpost/b83c7b2168 +# +reset_db +do_execsql_test 5.0 { + CREATE TABLE t1 (val1); + INSERT INTO t1 VALUES(4); + INSERT INTO t1 VALUES(5); + CREATE TABLE t2 (val2); +} +do_execsql_test 5.1 { + SELECT DISTINCT val1 FROM t1 UNION ALL SELECT val2 FROM t2; +} { + 4 5 +} +do_execsql_test 5.2 { + SELECT count(1234) FROM ( + SELECT DISTINCT val1 FROM t1 UNION ALL SELECT val2 FROM t2 + ) +} {2} + +finish_test