sl@0: # 2001 September 15 sl@0: # sl@0: # The author disclaims copyright to this source code. In place of sl@0: # a legal notice, here is a blessing: sl@0: # sl@0: # May you do good and not evil. sl@0: # May you find forgiveness for yourself and forgive others. sl@0: # May you share freely, never taking more than you give. sl@0: # sl@0: #*********************************************************************** sl@0: # This file implements regression tests for SQLite library. The sl@0: # focus of this file is testing SELECT statements that are part of sl@0: # expressions. sl@0: # sl@0: # $Id: subselect.test,v 1.16 2008/08/04 03:51:24 danielk1977 Exp $ sl@0: sl@0: set testdir [file dirname $argv0] sl@0: source $testdir/tester.tcl sl@0: sl@0: # Omit this whole file if the library is build without subquery support. sl@0: ifcapable !subquery { sl@0: finish_test sl@0: return sl@0: } sl@0: sl@0: # Basic sanity checking. Try a simple subselect. sl@0: # sl@0: do_test subselect-1.1 { sl@0: execsql { sl@0: CREATE TABLE t1(a int, b int); sl@0: INSERT INTO t1 VALUES(1,2); sl@0: INSERT INTO t1 VALUES(3,4); sl@0: INSERT INTO t1 VALUES(5,6); sl@0: } sl@0: execsql {SELECT * FROM t1 WHERE a = (SELECT count(*) FROM t1)} sl@0: } {3 4} sl@0: sl@0: # Try a select with more than one result column. sl@0: # sl@0: do_test subselect-1.2 { sl@0: set v [catch {execsql {SELECT * FROM t1 WHERE a = (SELECT * FROM t1)}} msg] sl@0: lappend v $msg sl@0: } {1 {only a single result allowed for a SELECT that is part of an expression}} sl@0: sl@0: # A subselect without an aggregate. sl@0: # sl@0: do_test subselect-1.3a { sl@0: execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=2)} sl@0: } {2} sl@0: do_test subselect-1.3b { sl@0: execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=4)} sl@0: } {4} sl@0: do_test subselect-1.3c { sl@0: execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=6)} sl@0: } {6} sl@0: do_test subselect-1.3d { sl@0: execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=8)} sl@0: } {} sl@0: ifcapable compound { sl@0: do_test subselect-1.3e { sl@0: execsql { sl@0: SELECT b FROM t1 sl@0: WHERE a = (SELECT a FROM t1 UNION SELECT b FROM t1 ORDER BY 1); sl@0: } sl@0: } {2} sl@0: } sl@0: sl@0: # What if the subselect doesn't return any value. We should get sl@0: # NULL as the result. Check it out. sl@0: # sl@0: do_test subselect-1.4 { sl@0: execsql {SELECT b from t1 where a = coalesce((SELECT a FROM t1 WHERE b=5),1)} sl@0: } {2} sl@0: sl@0: # Try multiple subselects within a single expression. sl@0: # sl@0: do_test subselect-1.5 { sl@0: execsql { sl@0: CREATE TABLE t2(x int, y int); sl@0: INSERT INTO t2 VALUES(1,2); sl@0: INSERT INTO t2 VALUES(2,4); sl@0: INSERT INTO t2 VALUES(3,8); sl@0: INSERT INTO t2 VALUES(4,16); sl@0: } sl@0: execsql { sl@0: SELECT y from t2 sl@0: WHERE x = (SELECT sum(b) FROM t1 where a notnull) - (SELECT sum(a) FROM t1) sl@0: } sl@0: } {8} sl@0: sl@0: # Try something useful. Delete every entry from t2 where the sl@0: # x value is less than half of the maximum. sl@0: # sl@0: do_test subselect-1.6 { sl@0: execsql {DELETE FROM t2 WHERE x < 0.5*(SELECT max(x) FROM t2)} sl@0: execsql {SELECT x FROM t2 ORDER BY x} sl@0: } {2 3 4} sl@0: sl@0: # Make sure sorting works for SELECTs there used as a scalar expression. sl@0: # sl@0: do_test subselect-2.1 { sl@0: execsql { sl@0: SELECT (SELECT a FROM t1 ORDER BY a), (SELECT a FROM t1 ORDER BY a DESC) sl@0: } sl@0: } {1 5} sl@0: do_test subselect-2.2 { sl@0: execsql { sl@0: SELECT 1 IN (SELECT a FROM t1 ORDER BY a); sl@0: } sl@0: } {1} sl@0: do_test subselect-2.3 { sl@0: execsql { sl@0: SELECT 2 IN (SELECT a FROM t1 ORDER BY a DESC); sl@0: } sl@0: } {0} sl@0: sl@0: # Verify that the ORDER BY clause is honored in a subquery. sl@0: # sl@0: ifcapable compound { sl@0: do_test subselect-3.1 { sl@0: execsql { sl@0: CREATE TABLE t3(x int); sl@0: INSERT INTO t3 SELECT a FROM t1 UNION ALL SELECT b FROM t1; sl@0: SELECT * FROM t3 ORDER BY x; sl@0: } sl@0: } {1 2 3 4 5 6} sl@0: } ;# ifcapable compound sl@0: ifcapable !compound { sl@0: do_test subselect-3.1 { sl@0: execsql { sl@0: CREATE TABLE t3(x int); sl@0: INSERT INTO t3 SELECT a FROM t1; sl@0: INSERT INTO t3 SELECT b FROM t1; sl@0: SELECT * FROM t3 ORDER BY x; sl@0: } sl@0: } {1 2 3 4 5 6} sl@0: } ;# ifcapable !compound sl@0: sl@0: do_test subselect-3.2 { sl@0: execsql { sl@0: SELECT sum(x) FROM (SELECT x FROM t3 ORDER BY x LIMIT 2); sl@0: } sl@0: } {3} sl@0: do_test subselect-3.3 { sl@0: execsql { sl@0: SELECT sum(x) FROM (SELECT x FROM t3 ORDER BY x DESC LIMIT 2); sl@0: } sl@0: } {11} sl@0: do_test subselect-3.4 { sl@0: execsql { sl@0: SELECT (SELECT x FROM t3 ORDER BY x); sl@0: } sl@0: } {1} sl@0: do_test subselect-3.5 { sl@0: execsql { sl@0: SELECT (SELECT x FROM t3 ORDER BY x DESC); sl@0: } sl@0: } {6} sl@0: do_test subselect-3.6 { sl@0: execsql { sl@0: SELECT (SELECT x FROM t3 ORDER BY x LIMIT 1); sl@0: } sl@0: } {1} sl@0: do_test subselect-3.7 { sl@0: execsql { sl@0: SELECT (SELECT x FROM t3 ORDER BY x DESC LIMIT 1); sl@0: } sl@0: } {6} sl@0: do_test subselect-3.8 { sl@0: execsql { sl@0: SELECT (SELECT x FROM t3 ORDER BY x LIMIT 1 OFFSET 2); sl@0: } sl@0: } {3} sl@0: do_test subselect-3.9 { sl@0: execsql { sl@0: SELECT (SELECT x FROM t3 ORDER BY x DESC LIMIT 1 OFFSET 2); sl@0: } sl@0: } {4} sl@0: do_test subselect-3.10 { sl@0: execsql { sl@0: SELECT x FROM t3 WHERE x IN sl@0: (SELECT x FROM t3 ORDER BY x DESC LIMIT 1 OFFSET 2); sl@0: } sl@0: } {4} sl@0: sl@0: # Ticket #2295. sl@0: # Make sure type affinities work correctly on subqueries with sl@0: # an ORDER BY clause. sl@0: # sl@0: do_test subselect-4.1 { sl@0: execsql { sl@0: CREATE TABLE t4(a TEXT, b TEXT); sl@0: INSERT INTO t4 VALUES('a','1'); sl@0: INSERT INTO t4 VALUES('b','2'); sl@0: INSERT INTO t4 VALUES('c','3'); sl@0: SELECT a FROM t4 WHERE b IN (SELECT b FROM t4 ORDER BY b); sl@0: } sl@0: } {a b c} sl@0: do_test subselect-4.2 { sl@0: execsql { sl@0: SELECT a FROM t4 WHERE b IN (SELECT b FROM t4 ORDER BY b LIMIT 1); sl@0: } sl@0: } {a} sl@0: do_test subselect-4.3 { sl@0: execsql { sl@0: SELECT a FROM t4 WHERE b IN (SELECT b FROM t4 ORDER BY b DESC LIMIT 1); sl@0: } sl@0: } {c} sl@0: sl@0: finish_test