# 2021 January 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 cases where EXISTS expressions are # transformed to IN() expressions by where.c # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix exists2 do_execsql_test 1.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); INSERT INTO t1 VALUES(3, 'three'); INSERT INTO t1 VALUES(4, 'four'); INSERT INTO t1 VALUES(5, 'five'); INSERT INTO t1 VALUES(6, 'six'); INSERT INTO t1 VALUES(7, 'seven'); CREATE TABLE t2(c INTEGER, d INTEGER); INSERT INTO t2 VALUES(1, 1); INSERT INTO t2 VALUES(3, 2); INSERT INTO t2 VALUES(5, 3); INSERT INTO t2 VALUES(7, 4); } proc do_execsql_eqp_test {tn sql eqp res} { # cf.: https://sqlite.org/forum/info/a9f6bb5c78248929 # uplevel [list do_eqp_test $tn.1 $sql [string trim $eqp]] uplevel [list do_execsql_test $tn.2 $sql $res] } do_execsql_eqp_test 1.1 { SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t1.a=t2.c); } { USING INTEGER PRIMARY KEY } { 1 one 3 three 5 five 7 seven } do_execsql_eqp_test 1.2 { SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c=t1.a); } { SEARCH TABLE t1 USING INTEGER PRIMARY KEY } { 1 one 3 three 5 five 7 seven } do_execsql_eqp_test 1.3 { SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a); } { SEARCH TABLE t1 USING INTEGER PRIMARY KEY } { 2 two 4 four 6 six } do_execsql_eqp_test 1.4 { SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a+1); } { SCAN TABLE t1 } { 1 one 3 three 5 five 7 seven } do_execsql_eqp_test 1.5 { SELECT t1.* FROM t1 WHERE EXISTS( SELECT * FROM t2 WHERE t1.a=t2.c AND d IN (1, 2, 3) ); } { SEARCH TABLE t1 USING INTEGER PRIMARY KEY } { 1 one 3 three 5 five } do_execsql_eqp_test 1.6 { SELECT t1.* FROM t1 WHERE EXISTS( SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c ); } { SEARCH TABLE t1 USING INTEGER PRIMARY KEY } { 1 one 3 three 5 five } do_execsql_eqp_test 1.7 { SELECT t1.* FROM t1 WHERE EXISTS( SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c ); } { SEARCH TABLE t1 USING INTEGER PRIMARY KEY } { 1 one 3 three 5 five } #------------------------------------------------------------------------- # reset_db do_execsql_test 2.0 { CREATE TABLE t3(a TEXT PRIMARY KEY, b TEXT, x INT) WITHOUT ROWID; CREATE TABLE t4(c TEXT COLLATE nocase, y INT); INSERT INTO t3 VALUES('one', 'i', 1); INSERT INTO t3 VALUES('two', 'ii', 2); INSERT INTO t3 VALUES('three', 'iii', 3); INSERT INTO t3 VALUES('four', 'iv', 4); INSERT INTO t3 VALUES('five', 'v', 5); INSERT INTO t4 VALUES('FIVE',5), ('four',4), ('TWO',2), ('one',1); } do_execsql_test 2.1 { SELECT a FROM t3, t4 WHERE a=c } {four one} do_execsql_test 2.2 { SELECT a FROM t3, t4 WHERE c=a } {five four one two} do_execsql_eqp_test 2.3 { SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c) } { SEARCH TABLE t3 USING PRIMARY KEY } { four one } do_execsql_eqp_test 2.4 { SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a) } { SCAN TABLE t3 } { five four one two } do_execsql_test 2.5 { CREATE INDEX t3anc ON t3(a COLLATE nocase, x); } do_execsql_eqp_test 2.6 { SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a) } { SEARCH TABLE t3 USING COVERING INDEX t3anc } { five four one two } do_execsql_test 2.6a { SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (c,y)=(a,x)) } {five four one two} do_execsql_eqp_test 2.7 { SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c) } { SEARCH TABLE t3 USING PRIMARY KEY } { four one } do_execsql_test 2.7a { SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (a,x)=(c,y)) } { four one } do_execsql_test 2.7b { SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (a,x)=(c,y) LIMIT 1) } { four one } # EXISTS clauses using vector expressions in the WHERE clause. # reset_db do_execsql_test 3.0 { CREATE TABLE t1(a,b); INSERT INTO t1(a,b) VALUES(1,111),(2,222),(8,888); CREATE TABLE t2(x INTEGER PRIMARY KEY, y); INSERT INTO t2(x,y) VALUES(2,222),(3,333),(7,333); SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,y)=(a,b)); } {222} do_execsql_test 3.1 { SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (a,b)=(x,y)); } {222} do_execsql_test 3.2 { SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,b)=(a,y)); } {222} finish_test