testing/sqlite3: Import SELECT statement TCL tests

This commit is contained in:
Pekka Enberg 2025-07-07 15:34:32 +03:00
parent 4206fc2e23
commit 38f3d213db
18 changed files with 7351 additions and 0 deletions

21
testing/sqlite3/all.test Executable file
View file

@ -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

1213
testing/sqlite3/select1.test Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,185 @@
# 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: select2.test,v 1.28 2009/01/15 15:23:59 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Create a table with some data
#
execsql {CREATE TABLE tbl1(f1 int, f2 int)}
execsql {BEGIN}
for {set i 0} {$i<=30} {incr i} {
execsql "INSERT INTO tbl1 VALUES([expr {$i%9}],[expr {$i%10}])"
}
execsql {COMMIT}
# Do a second query inside a first.
#
do_test select2-1.1 {
set sql {SELECT DISTINCT f1 FROM tbl1 ORDER BY f1}
set r {}
catch {unset data}
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
} {0: 0 7 8 9 1: 0 1 8 9 2: 0 1 2 9 3: 0 1 2 3 4: 2 3 4 5: 3 4 5 6: 4 5 6 7: 5 6 7 8: 6 7 8}
do_test select2-1.2 {
set sql {SELECT DISTINCT f1 FROM tbl1 WHERE f1>3 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

View file

@ -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

1043
testing/sqlite3/select4.test Normal file

File diff suppressed because it is too large Load diff

View file

@ -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(*)<z ORDER BY y
}} msg]
lappend v $msg
} {1 {no such column: z}}
# Get the Agg function to rehash in vdbe.c
#
do_test select5-3.1 {
execsql {
SELECT x, count(*), avg(y) FROM t1 GROUP BY x HAVING x<4 ORDER BY x
}
} {1 1 5.0 2 1 5.0 3 1 5.0}
# Run various aggregate functions when the count is zero.
#
do_test select5-4.1 {
execsql {
SELECT avg(x) FROM t1 WHERE x>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 b<x GROUP BY a ORDER BY a;
}
} {one 6 two 3}
do_test select5-8.6 {
execsql {
SELECT a, count(t8a.b) FROM t8a, t8b WHERE b=t8b.rowid
GROUP BY a ORDER BY 2;
}
} {two 1 one 2}
do_test select5-8.7 {
execsql {
SELECT a, count(b) FROM t8a, t8b GROUP BY a ORDER BY 2;
}
} {two 3 one 6}
do_test select5-8.8 {
execsql {
SELECT a, count(*) FROM t8a, t8b GROUP BY a ORDER BY 2;
}
} {two 3 one 9}
# 2021-04-26 forum https://sqlite.org/forum/forumpost/74330094d8
reset_db
do_execsql_test select5-9.1 {
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1(a,b) VALUES(1,null),(null,null),(1,null);
CREATE UNIQUE INDEX t1b ON t1(abs(b));
SELECT quote(a), quote(b), '|' FROM t1 GROUP BY a, abs(b);
} {NULL NULL | 1 NULL |}
finish_test

View file

@ -0,0 +1,670 @@
# 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 SELECT statements that contain
# subqueries in their FROM clause.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Omit this whole file if the library is build without subquery support.
ifcapable !subquery {
finish_test
return
}
set ::testprefix select6
do_test select6-1.0 {
execsql {
BEGIN;
CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES(1,1);
INSERT INTO t1 VALUES(2,2);
INSERT INTO t1 VALUES(3,2);
INSERT INTO t1 VALUES(4,3);
INSERT INTO t1 VALUES(5,3);
INSERT INTO t1 VALUES(6,3);
INSERT INTO t1 VALUES(7,3);
INSERT INTO t1 VALUES(8,4);
INSERT INTO t1 VALUES(9,4);
INSERT INTO t1 VALUES(10,4);
INSERT INTO t1 VALUES(11,4);
INSERT INTO t1 VALUES(12,4);
INSERT INTO t1 VALUES(13,4);
INSERT INTO t1 VALUES(14,4);
INSERT INTO t1 VALUES(15,4);
INSERT INTO t1 VALUES(16,5);
INSERT INTO t1 VALUES(17,5);
INSERT INTO t1 VALUES(18,5);
INSERT INTO t1 VALUES(19,5);
INSERT INTO t1 VALUES(20,5);
COMMIT;
SELECT DISTINCT y FROM t1 ORDER BY y;
}
} {1 2 3 4 5}
do_test select6-1.1 {
execsql2 {SELECT * FROM (SELECT x, y FROM t1 WHERE x<2)}
} {x 1 y 1}
do_test select6-1.2 {
execsql {SELECT count(*) FROM (SELECT y FROM t1)}
} {20}
do_test select6-1.3 {
execsql {SELECT count(*) FROM (SELECT DISTINCT y FROM t1)}
} {5}
do_test select6-1.4 {
execsql {SELECT count(*) FROM (SELECT DISTINCT * FROM (SELECT y FROM t1))}
} {5}
do_test select6-1.5 {
execsql {SELECT count(*) FROM (SELECT * FROM (SELECT DISTINCT y FROM t1))}
} {5}
do_test select6-1.6 {
execsql {
SELECT *
FROM (SELECT count(*),y FROM t1 GROUP BY y) AS a,
(SELECT max(x),y FROM t1 GROUP BY y) as b
WHERE a.y=b.y ORDER BY a.y
}
} {1 1 1 1 2 2 3 2 4 3 7 3 8 4 15 4 5 5 20 5}
do_test select6-1.7 {
execsql {
SELECT a.y, a.[count(*)], [max(x)], [count(*)]
FROM (SELECT count(*),y FROM t1 GROUP BY y) AS a,
(SELECT max(x),y FROM t1 GROUP BY y) as b
WHERE a.y=b.y ORDER BY a.y
}
} {1 1 1 1 2 2 3 2 3 4 7 4 4 8 15 8 5 5 20 5}
do_test select6-1.8 {
execsql {
SELECT q, p, r
FROM (SELECT count(*) as p , y as q FROM t1 GROUP BY y) AS a,
(SELECT max(x) as r, y as s FROM t1 GROUP BY y) as b
WHERE q=s ORDER BY s
}
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
do_test select6-1.9 {
execsql {
SELECT q, p, r, b.[min(x)+y]
FROM (SELECT count(*) as p , y as q FROM t1 GROUP BY y) AS a,
(SELECT max(x) as r, y as s, min(x)+y FROM t1 GROUP BY y) as b
WHERE q=s ORDER BY s
}
} {1 1 1 2 2 2 3 4 3 4 7 7 4 8 15 12 5 5 20 21}
do_test select6-2.0 {
execsql {
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
INSERT INTO t2 SELECT * FROM t1;
SELECT DISTINCT b FROM t2 ORDER BY b;
}
} {1 2 3 4 5}
do_test select6-2.1 {
execsql2 {SELECT * FROM (SELECT a, b FROM t2 WHERE a<2)}
} {a 1 b 1}
do_test select6-2.2 {
execsql {SELECT count(*) FROM (SELECT b FROM t2)}
} {20}
do_test select6-2.3 {
execsql {SELECT count(*) FROM (SELECT DISTINCT b FROM t2)}
} {5}
do_test select6-2.4 {
execsql {SELECT count(*) FROM (SELECT DISTINCT * FROM (SELECT b FROM t2))}
} {5}
do_test select6-2.5 {
execsql {SELECT count(*) FROM (SELECT * FROM (SELECT DISTINCT b FROM t2))}
} {5}
do_test select6-2.6 {
execsql {
SELECT *
FROM (SELECT count(*),b FROM t2 GROUP BY b) AS a,
(SELECT max(a),b FROM t2 GROUP BY b) as b
WHERE a.b=b.b ORDER BY a.b
}
} {1 1 1 1 2 2 3 2 4 3 7 3 8 4 15 4 5 5 20 5}
do_test select6-2.7 {
execsql {
SELECT a.b, a.[count(*)], [max(a)], [count(*)]
FROM (SELECT count(*),b FROM t2 GROUP BY b) AS a,
(SELECT max(a),b FROM t2 GROUP BY b) as b
WHERE a.b=b.b ORDER BY a.b
}
} {1 1 1 1 2 2 3 2 3 4 7 4 4 8 15 8 5 5 20 5}
do_test select6-2.8 {
execsql {
SELECT q, p, r
FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY b) AS a,
(SELECT max(a) as r, b as s FROM t2 GROUP BY b) as b
WHERE q=s ORDER BY s
}
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
do_test select6-2.9 {
execsql {
SELECT a.q, a.p, b.r
FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a,
(SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b
WHERE a.q=b.s ORDER BY a.q
}
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
do_test select6-3.1 {
execsql2 {
SELECT * FROM (SELECT * FROM (SELECT * FROM t1 WHERE x=3));
}
} {x 3 y 2}
do_test select6-3.2 {
execsql {
SELECT * FROM
(SELECT a.q, a.p, b.r
FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a,
(SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b
WHERE a.q=b.s ORDER BY a.q)
}
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
do_test select6-3.3 {
execsql {
SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
}
} {10.5 3.7 14.2}
do_test select6-3.4 {
execsql {
SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4)
}
} {11.5 4.0 15.5}
do_test select6-3.5 {
execsql {
SELECT x,y,x+y FROM (SELECT avg(a) as 'x', avg(b) as 'y' FROM t2 WHERE a=4)
}
} {4.0 3.0 7.0}
do_test select6-3.6 {
execsql {
SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
WHERE a>10
}
} {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

View file

@ -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<b;
}
} {text 123}
do_execsql_test 8.0 {
CREATE TABLE t01(x, y);
CREATE TABLE t02(x, y);
}
do_catchsql_test 8.1 {
SELECT * FROM (
SELECT * FROM t01 UNION SELECT x FROM t02
) WHERE y=1
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
do_catchsql_test 8.2 {
CREATE VIEW v0 as SELECT x, y FROM t01 UNION SELECT x FROM t02;
EXPLAIN QUERY PLAN SELECT * FROM v0 WHERE x='0' OR y;
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
finish_test

View file

@ -0,0 +1,61 @@
# 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 that LIMIT and OFFSET work for
# unusual combinations SELECT statements.
#
# $Id: select8.test,v 1.1 2008/01/12 12:48:09 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
execsql {
CREATE TABLE songs(songid, artist, timesplayed);
INSERT INTO songs VALUES(1,'one',1);
INSERT INTO songs VALUES(2,'one',2);
INSERT INTO songs VALUES(3,'two',3);
INSERT INTO songs VALUES(4,'three',5);
INSERT INTO songs VALUES(5,'one',7);
INSERT INTO songs VALUES(6,'two',11);
}
set result [execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
FROM songs
GROUP BY LOWER(artist)
}]
do_test select8-1.1 {
execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
FROM songs
GROUP BY LOWER(artist)
LIMIT 1 OFFSET 1
}
} [lrange $result 2 3]
do_test select8-1.2 {
execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
FROM songs
GROUP BY LOWER(artist)
LIMIT 2 OFFSET 1
}
} [lrange $result 2 5]
do_test select8-1.3 {
execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
FROM songs
GROUP BY LOWER(artist)
LIMIT -1 OFFSET 2
}
} [lrange $result 4 end]
finish_test

View file

@ -0,0 +1,472 @@
# 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: select9.test,v 1.4 2008/07/01 14:39:35 danielk1977 Exp $
# The tests in this file are focused on test compound SELECT statements
# that have any or all of an ORDER BY, LIMIT or OFFSET clauses. As of
# version 3.6.0, SQLite contains code to use SQL indexes where possible
# to optimize such statements.
#
# TODO Points:
#
# * Are there any "column affinity" issues to consider?
set testdir [file dirname $argv0]
source $testdir/tester.tcl
#-------------------------------------------------------------------------
# test_compound_select TESTNAME SELECT RESULT
#
# This command is used to run multiple LIMIT/OFFSET test cases based on
# the single SELECT statement passed as the second argument. The SELECT
# statement may not contain a LIMIT or OFFSET clause. This proc tests
# many statements of the form:
#
# "$SELECT limit $X offset $Y"
#
# for various values of $X and $Y.
#
# The third argument, $RESULT, should contain the expected result of
# the command [execsql $SELECT].
#
# The first argument, $TESTNAME, is used as the base test case name to
# pass to [do_test] for each individual LIMIT OFFSET test case.
#
proc test_compound_select {testname sql result} {
set nCol 1
db eval $sql A {
set nCol [llength $A(*)]
break
}
set nRow [expr {[llength $result] / $nCol}]
set ::compound_sql $sql
do_test $testname {
execsql $::compound_sql
} $result
#return
set iLimitIncr 1
set iOffsetIncr 1
if {[info exists ::G(isquick)] && $::G(isquick) && $nRow>=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:
#
# <simple select 1> <compound op> <simple select 2> ORDER BY <order by>
#
# where each <simple select> is a simple (non-compound) select statement
# and <compound op> 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 <select statement 1> and <select statement 2> 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

1510
testing/sqlite3/selectA.test Normal file

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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