3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
6 # May you do good and not evil.
7 # May you find forgiveness for yourself and forgive others.
8 # May you share freely, never taking more than you give.
10 #***********************************************************************
13 set testdir [file dirname $argv0]
14 source $testdir/tester.tcl
19 CREATE TABLE t1x(x INTEGER PRIMARY KEY);
20 INSERT INTO t1x VALUES(1),(3),(5),(7),(9);
21 CREATE TABLE t1y(y INTEGER UNIQUE);
22 INSERT INTO t1y VALUES(2),(4),(6),(8);
23 CREATE TABLE t1z(z TEXT UNIQUE);
24 INSERT INTO t1z VALUES('a'),('c'),('e'),('g');
25 CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT, d TEXT);
26 INSERT INTO t2 VALUES(1,2,'a','12a'),(1,2,'b','12b'),
27 (2,3,'g','23g'),(3,5,'c','35c'),
28 (4,6,'h','46h'),(5,6,'e','56e');
29 CREATE TABLE t3x AS SELECT x FROM t1x;
30 CREATE TABLE t3y AS SELECT y FROM t1y;
31 CREATE TABLE t3z AS SELECT z FROM t1z;
32 SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY c;
37 SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d;
42 SELECT d FROM t2 WHERE a IN t3x AND b IN t3y AND c IN t3z ORDER BY d;
49 CREATE INDEX t2abc ON t2(a,b,c);
50 SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY d;
55 SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d;
59 regexp {OpenEphemeral} [db eval {
60 EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z
65 SELECT d FROM t2 WHERE a IN t3x AND b IN t3y AND c IN t3z ORDER BY d;
69 regexp {OpenEphemeral} [db eval {
70 EXPLAIN SELECT d FROM t2 WHERE a IN t3x AND b IN t1y AND c IN t1z
74 regexp {OpenEphemeral} [db eval {
75 EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t3y AND c IN t1z
79 regexp {OpenEphemeral} [db eval {
80 EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t3z
87 CREATE INDEX t2ab ON t2(a,b);
88 SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY d;
93 SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d;
97 regexp {OpenEphemeral} [db eval {
98 EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z
105 CREATE INDEX t2abcd ON t2(a,b,c,d);
106 SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY d;
111 SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d;
115 regexp {OpenEphemeral} [db eval {
116 EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z
124 CREATE INDEX t2cbad ON t2(c,b,a,d);
125 SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z ORDER BY d;
130 SELECT d FROM t2 WHERE a IN t1y AND b IN t1x AND c IN t1z ORDER BY d;
134 regexp {OpenEphemeral} [db eval {
135 EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t1z
139 #-------------------------------------------------------------------------
140 # At one point SQLite was removing the DISTINCT keyword from expressions
143 # <expr1> IN (SELECT DISTINCT <expr2> FROM...)
145 # However, there are a few obscure cases where this is incorrect. For
146 # example, if the SELECT features a LIMIT clause, or if the collation
147 # sequence or affinity used by the DISTINCT does not match the one used
148 # by the IN(...) expression.
150 do_execsql_test 6.1.1 {
151 CREATE TABLE t1(a COLLATE nocase);
152 INSERT INTO t1 VALUES('one');
153 INSERT INTO t1 VALUES('ONE');
155 do_execsql_test 6.1.2 {
156 SELECT count(*) FROM t1 WHERE a COLLATE BINARY IN (SELECT DISTINCT a FROM t1)
159 do_execsql_test 6.2.1 {
160 CREATE TABLE t3(a, b);
161 INSERT INTO t3 VALUES(1, 1);
162 INSERT INTO t3 VALUES(1, 2);
163 INSERT INTO t3 VALUES(1, 3);
164 INSERT INTO t3 VALUES(2, 4);
165 INSERT INTO t3 VALUES(2, 5);
166 INSERT INTO t3 VALUES(2, 6);
167 INSERT INTO t3 VALUES(3, 7);
168 INSERT INTO t3 VALUES(3, 8);
169 INSERT INTO t3 VALUES(3, 9);
171 do_execsql_test 6.2.2 {
172 SELECT count(*) FROM t3 WHERE b IN (SELECT DISTINCT a FROM t3 LIMIT 5);
174 do_execsql_test 6.2.3 {
175 SELECT count(*) FROM t3 WHERE b IN (SELECT a FROM t3 LIMIT 5);
178 do_execsql_test 6.3.1 {
181 INSERT INTO x1 VALUES(1), (1), (2);
182 INSERT INTO x2 VALUES(1), (2);
183 SELECT count(*) FROM x2 WHERE b IN (SELECT DISTINCT a FROM x1 LIMIT 2);
186 #-------------------------------------------------------------------------
187 # Test to confirm that bug [5e3c886796e5] is fixed.
189 do_execsql_test 7.1 {
190 CREATE TABLE y1(a, b);
193 INSERT INTO y1 VALUES(1, 'one');
194 INSERT INTO y1 VALUES('two', 'two');
195 INSERT INTO y1 VALUES(3, 'three');
197 INSERT INTO y2 VALUES('one');
198 INSERT INTO y2 VALUES('two');
199 INSERT INTO y2 VALUES('three');
202 do_execsql_test 7.2.1 {
203 SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2);
205 do_execsql_test 7.2.2 {
206 SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
209 do_execsql_test 7.3.1 {
210 CREATE INDEX y2c ON y2(c);
211 SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2);
213 do_execsql_test 7.3.2 {
214 SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
217 #-------------------------------------------------------------------------
218 # Tests to confirm that indexes on the rowid column do not confuse
219 # the query planner. See ticket [0eab1ac7591f511d].
221 do_execsql_test 8.0 {
222 CREATE TABLE n1(a INTEGER PRIMARY KEY, b VARCHAR(500));
223 CREATE UNIQUE INDEX n1a ON n1(a);
226 do_execsql_test 8.1 {
227 SELECT count(*) FROM n1 WHERE a IN (1, 2, 3)
229 do_execsql_test 8.2 {
230 SELECT count(*) FROM n1 WHERE a IN (SELECT +a FROM n1)
232 do_execsql_test 8.3 {
233 INSERT INTO n1 VALUES(1, NULL), (2, NULL), (3, NULL);
234 SELECT count(*) FROM n1 WHERE a IN (1, 2, 3)
236 do_execsql_test 8.4 {
237 SELECT count(*) FROM n1 WHERE a IN (SELECT +a FROM n1)
240 #-------------------------------------------------------------------------
241 # Test that ticket 61fe97454c is fixed.
243 do_execsql_test 9.0 {
244 CREATE TABLE t9(a INTEGER PRIMARY KEY);
245 INSERT INTO t9 VALUES (44), (45);
247 do_execsql_test 9.1 {
248 SELECT * FROM t9 WHERE a IN (44, 45, 44, 45)
251 #-------------------------------------------------------------------------
252 # Test that ticket c7a117190 is fixed.
255 do_execsql_test 9.0 {
257 CREATE VIEW v0(c0) AS SELECT LOWER(CAST('1e500' AS TEXT)) FROM t0;
258 INSERT INTO t0(c0) VALUES (NULL);
261 do_execsql_test 9.1 {
262 SELECT lower('1e500') FROM t0 WHERE rowid NOT IN (0, 0, lower('1e500'));
265 do_execsql_test 9.2 {
266 SELECT lower('1e500') FROM t0 WHERE rowid != lower('1e500');