b411c4d69e
required for virtual columns if they are part of an outer join. Add a test case (derived from dbsqlfuzz b9e65e2f110df998f1306571fae7af6c01e4d92b) to prove it. FossilOrigin-Name: 4484ec6d26b31305e31de89bdbae26344d8083a7e7de20861430d31737d9979c
345 lines
9.0 KiB
Plaintext
345 lines
9.0 KiB
Plaintext
# 2022 May 17
|
|
#
|
|
# 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.
|
|
#
|
|
|
|
set testdir [file dirname $argv0]
|
|
source $testdir/tester.tcl
|
|
set testprefix joinH
|
|
|
|
do_execsql_test 1.0 {
|
|
CREATE TABLE t1(a INT);
|
|
CREATE TABLE t2(b INT);
|
|
INSERT INTO t2(b) VALUES(NULL);
|
|
}
|
|
|
|
db nullvalue NULL
|
|
|
|
do_execsql_test 1.1 {
|
|
SELECT DISTINCT a FROM t1 FULL JOIN t2 ON true WHERE (b ISNULL);
|
|
} {NULL}
|
|
do_execsql_test 1.2 {
|
|
SELECT a FROM t1 FULL JOIN t2 ON true;
|
|
} {NULL}
|
|
do_execsql_test 1.3 {
|
|
SELECT a FROM t1 FULL JOIN t2 ON true WHERE (b ISNULL);
|
|
} {NULL}
|
|
do_execsql_test 1.4 {
|
|
SELECT DISTINCT a FROM t1 FULL JOIN t2 ON true;
|
|
} {NULL}
|
|
|
|
#-----------------------------------------------------------
|
|
|
|
reset_db
|
|
do_execsql_test 2.0 {
|
|
CREATE TABLE r3(x);
|
|
CREATE TABLE r4(y INTEGER PRIMARY KEY);
|
|
INSERT INTO r4 VALUES(55);
|
|
}
|
|
|
|
do_execsql_test 2.1 {
|
|
SELECT 'value!' FROM r3 FULL JOIN r4 ON (y=x);
|
|
} {value!}
|
|
|
|
do_execsql_test 2.2 {
|
|
SELECT 'value!' FROM r3 FULL JOIN r4 ON (y=x) WHERE +y=55;
|
|
} {value!}
|
|
|
|
#-----------------------------------------------------------
|
|
reset_db
|
|
do_execsql_test 3.1 {
|
|
CREATE TABLE t0 (c0);
|
|
CREATE TABLE t1 (c0);
|
|
CREATE TABLE t2 (c0 , c1 , c2 , UNIQUE (c0), UNIQUE (c2 DESC));
|
|
INSERT INTO t2 VALUES ('x', 'y', 'z');
|
|
ANALYZE;
|
|
CREATE VIEW v0(c0) AS SELECT FALSE;
|
|
}
|
|
|
|
do_catchsql_test 3.2 {
|
|
SELECT * FROM t0 LEFT OUTER JOIN t1 ON v0.c0 INNER JOIN v0 INNER JOIN t2 ON (t2.c2 NOT NULL);
|
|
} {1 {ON clause references tables to its right}}
|
|
|
|
#-------------------------------------------------------------
|
|
|
|
reset_db
|
|
do_execsql_test 4.1 {
|
|
CREATE TABLE t1(a,b,c,d,e,f,g,h,PRIMARY KEY(a,b,c)) WITHOUT ROWID;
|
|
CREATE TABLE t2(i, j);
|
|
INSERT INTO t2 VALUES(10, 20);
|
|
}
|
|
|
|
do_execsql_test 4.2 {
|
|
SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33);
|
|
} {1}
|
|
|
|
do_execsql_test 4.3 {
|
|
CREATE INDEX i1 ON t1( (d IS NULL), d );
|
|
}
|
|
|
|
do_execsql_test 4.4 {
|
|
SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33);
|
|
} {1}
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
reset_db
|
|
do_execsql_test 5.0 {
|
|
CREATE TABLE t0(w);
|
|
CREATE TABLE t1(x);
|
|
CREATE TABLE t2(y);
|
|
CREATE TABLE t3(z);
|
|
INSERT INTO t3 VALUES('t3val');
|
|
}
|
|
|
|
do_execsql_test 5.1 {
|
|
SELECT * FROM t1 INNER JOIN t2 ON (0) RIGHT OUTER JOIN t3;
|
|
} {{} {} t3val}
|
|
|
|
do_execsql_test 5.2 {
|
|
SELECT * FROM t1 INNER JOIN t2 ON (0) FULL OUTER JOIN t3;
|
|
} {{} {} t3val}
|
|
|
|
do_execsql_test 5.3 {
|
|
SELECT * FROM t3 LEFT JOIN t2 ON (0);
|
|
} {t3val {}}
|
|
|
|
do_execsql_test 5.4 {
|
|
SELECT * FROM t0 RIGHT JOIN t1 INNER JOIN t2 ON (0) RIGHT JOIN t3
|
|
} {{} {} {} t3val}
|
|
|
|
do_execsql_test 5.5 {
|
|
SELECT * FROM t0 RIGHT JOIN t1 INNER JOIN t2 ON (0)
|
|
} {}
|
|
|
|
|
|
reset_db
|
|
db null NULL
|
|
do_execsql_test 6.0 {
|
|
CREATE TABLE t1(a INT);
|
|
CREATE TABLE t2(b INT);
|
|
INSERT INTO t1 VALUES(3);
|
|
SELECT CASE WHEN t2.b THEN 0 ELSE 1 END FROM t1 LEFT JOIN t2 ON true;
|
|
} {1}
|
|
do_execsql_test 6.1 {
|
|
SELECT * FROM t1 LEFT JOIN t2 ON true WHERE CASE WHEN t2.b THEN 0 ELSE 1 END;
|
|
} {3 NULL}
|
|
|
|
#-------------------------------------------------------------------------
|
|
reset_db
|
|
do_execsql_test 7.0 {
|
|
CREATE TABLE t1(a, b);
|
|
CREATE TABLE t2(c);
|
|
CREATE TABLE t3(d);
|
|
|
|
INSERT INTO t1 VALUES ('a', 'a');
|
|
INSERT INTO t2 VALUES ('ddd');
|
|
INSERT INTO t3 VALUES(1234);
|
|
}
|
|
|
|
do_execsql_test 7.1 {
|
|
SELECT t2.rowid FROM t1 JOIN (t2 JOIN t3);
|
|
} {1}
|
|
|
|
do_execsql_test 7.1 {
|
|
UPDATE t1 SET b = t2.rowid FROM t2, t3;
|
|
}
|
|
|
|
do_execsql_test 7.2 {
|
|
SELECT * FROM t1
|
|
} {a 1}
|
|
|
|
#-------------------------------------------------------------------------
|
|
reset_db
|
|
do_execsql_test 8.0 {
|
|
CREATE TABLE x1(a INTEGER PRIMARY KEY, b);
|
|
CREATE TABLE x2(c, d);
|
|
CREATE TABLE x3(rowid, _rowid_);
|
|
|
|
CREATE TABLE x4(rowid, _rowid_, oid);
|
|
|
|
INSERT INTO x1 VALUES(1000, 'thousand');
|
|
INSERT INTO x2 VALUES('c', 'd');
|
|
INSERT INTO x3(oid, rowid, _rowid_) VALUES(43, 'hello', 'world');
|
|
INSERT INTO x4(oid, rowid, _rowid_) VALUES('forty three', 'hello', 'world');
|
|
}
|
|
|
|
do_execsql_test 8.1 {
|
|
SELECT x3.oid FROM x1 JOIN (x2 JOIN x3 ON c='c')
|
|
} 43
|
|
|
|
breakpoint
|
|
do_execsql_test 8.2 {
|
|
SELECT x3.rowid FROM x1 JOIN (x2 JOIN x3 ON c='c')
|
|
} {hello}
|
|
|
|
do_execsql_test 8.3 {
|
|
SELECT x4.oid FROM x1 JOIN (x2 JOIN x4 ON c='c')
|
|
} {{forty three}}
|
|
|
|
|
|
#---------------------------------------------------------------------
|
|
#
|
|
reset_db
|
|
do_execsql_test 9.0 {
|
|
CREATE TABLE x1(a);
|
|
CREATE TABLE x2(b);
|
|
CREATE TABLE x3(c);
|
|
|
|
CREATE TABLE wo1(a PRIMARY KEY, b) WITHOUT ROWID;
|
|
CREATE TABLE wo2(a PRIMARY KEY, rowid) WITHOUT ROWID;
|
|
CREATE TABLE wo3(a PRIMARY KEY, b) WITHOUT ROWID;
|
|
}
|
|
|
|
do_catchsql_test 9.1 {
|
|
SELECT rowid FROM wo1, x1, x2;
|
|
} {1 {ambiguous column name: rowid}}
|
|
do_catchsql_test 9.2 {
|
|
SELECT rowid FROM wo1, (x1, x2);
|
|
} {1 {ambiguous column name: rowid}}
|
|
do_catchsql_test 9.3 {
|
|
SELECT rowid FROM wo1 JOIN (x1 JOIN x2);
|
|
} {1 {ambiguous column name: rowid}}
|
|
do_catchsql_test 9.4 {
|
|
SELECT a FROM wo1, x1, x2;
|
|
} {1 {ambiguous column name: a}}
|
|
|
|
|
|
# It is not possible to use "rowid" in a USING clause.
|
|
#
|
|
do_catchsql_test 9.5 {
|
|
SELECT * FROM x1 JOIN x2 USING (rowid);
|
|
} {1 {cannot join using column rowid - column not present in both tables}}
|
|
do_catchsql_test 9.6 {
|
|
SELECT * FROM wo2 JOIN x2 USING (rowid);
|
|
} {1 {cannot join using column rowid - column not present in both tables}}
|
|
|
|
# "rowid" columns are not matched by NATURAL JOIN. If they were, then
|
|
# the SELECT below would return zero rows.
|
|
do_execsql_test 9.7 {
|
|
INSERT INTO x1(rowid, a) VALUES(101, 'A');
|
|
INSERT INTO x2(rowid, b) VALUES(55, 'B');
|
|
SELECT * FROM x1 NATURAL JOIN x2;
|
|
} {A B}
|
|
|
|
do_execsql_test 9.8 {
|
|
INSERT INTO wo1(a, b) VALUES('mya', 'myb');
|
|
INSERT INTO wo2(a, rowid) VALUES('mypk', 'myrowid');
|
|
INSERT INTO wo3(a, b) VALUES('MYA', 'MYB');
|
|
INSERT INTO x3(rowid, c) VALUES(99, 'x3B');
|
|
}
|
|
|
|
do_catchsql_test 9.8 {
|
|
SELECT rowid FROM x1 JOIN (x2 JOIN wo2);
|
|
} {0 myrowid}
|
|
do_catchsql_test 9.9 {
|
|
SELECT _rowid_ FROM wo1 JOIN (wo3 JOIN x3)
|
|
} {0 99}
|
|
do_catchsql_test 9.10 {
|
|
SELECT oid FROM wo1 JOIN (wo3 JOIN x3)
|
|
} {0 99}
|
|
do_catchsql_test 9.11 {
|
|
SELECT oid FROM wo2 JOIN (wo3 JOIN x3)
|
|
} {0 99}
|
|
|
|
reset_db
|
|
do_execsql_test 10.0 {
|
|
CREATE TABLE rt0 (c0 INTEGER, c1 INTEGER, c2 INTEGER, c3 INTEGER, c4 INTEGER);
|
|
CREATE TABLE rt3 (c3 INTEGER);
|
|
|
|
INSERT INTO rt0(c3, c1) VALUES (x'', '1');
|
|
INSERT INTO rt0(c3, c1) VALUES ('-1', -1e500);
|
|
INSERT INTO rt0(c3, c1) VALUES (1, x'');
|
|
|
|
CREATE VIEW v6(c0, c1, c2) AS SELECT 0, 0, 0;
|
|
}
|
|
|
|
do_execsql_test 10.1 {
|
|
SELECT COUNT(*) FROM rt0 LEFT JOIN rt3 JOIN v6 ON ((CASE v6.c0 WHEN rt0.c4 THEN rt3.c3 END) NOT BETWEEN (rt0.c4) AND (NULL)) WHERE (rt0.c1); -- 2
|
|
} {0}
|
|
|
|
do_execsql_test 10.2 {
|
|
SELECT COUNT(*) FROM rt0 LEFT JOIN rt3 RIGHT OUTER JOIN v6 ON ((CASE v6.c0 WHEN rt0.c4 THEN rt3.c3 END) NOT BETWEEN (rt0.c4) AND (NULL)) WHERE (rt0.c1); -- 2
|
|
} {0}
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
do_execsql_test 11.1 {
|
|
CREATE TABLE t1(a, b);
|
|
CREATE TABLE t2(c, d);
|
|
CREATE TABLE t3(e, f);
|
|
|
|
INSERT INTO t1 VALUES(1, 1);
|
|
INSERT INTO t2 VALUES(2, 2);
|
|
INSERT INTO t3 VALUES(3, 3);
|
|
}
|
|
|
|
do_execsql_test 11.2 {
|
|
SELECT * FROM t1 LEFT JOIN t2 RIGHT JOIN t3 ON (t2.c=10)
|
|
} {{} {} {} {} 3 3}
|
|
|
|
do_execsql_test 11.3 {
|
|
SELECT * FROM t1 LEFT JOIN t2 RIGHT JOIN t3 ON (t2.c=10) WHERE t1.a=1
|
|
} {}
|
|
|
|
#-------------------------------------------------------------------------
|
|
reset_db
|
|
|
|
do_execsql_test 12.1 {
|
|
CREATE TABLE t1(a1 INT, b1 TEXT);
|
|
INSERT INTO t1 VALUES(88,'');
|
|
CREATE TABLE t2(c2 INT, d2 TEXT);
|
|
INSERT INTO t2 VALUES(88,'');
|
|
CREATE TABLE t3(e3 TEXT PRIMARY KEY);
|
|
INSERT INTO t3 VALUES('');
|
|
}
|
|
|
|
do_execsql_test 12.2 {
|
|
SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1;
|
|
}
|
|
do_execsql_test 12.3 {
|
|
SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------
|
|
# 2024-04-05 dbsqlfuzz b9e65e2f110df998f1306571fae7af6c01e4d92b
|
|
reset_db
|
|
do_execsql_test 13.1 {
|
|
CREATE TABLE t1(a INT AS (b), b INT);
|
|
INSERT INTO t1(b) VALUES(123);
|
|
CREATE TABLE t2(a INT, c INT);
|
|
SELECT a FROM t2 NATURAL RIGHT JOIN t1;
|
|
} {123}
|
|
do_execsql_test 13.2 {
|
|
CREATE INDEX t1a ON t1(a);
|
|
SELECT a FROM t2 NATURAL RIGHT JOIN t1;
|
|
} {123}
|
|
# Further tests of the same logic (indexes on expressions
|
|
# used by RIGHT JOIN) from check-in ffe23af73fcb324d and
|
|
# forum post https://sqlite.org/forum/forumpost/9b491e1debf0b67a.
|
|
db null NULL
|
|
do_execsql_test 13.3 {
|
|
CREATE TABLE t3(a INT, b INT);
|
|
CREATE UNIQUE INDEX t3x ON t3(a, a+b);
|
|
INSERT INTO t3(a,b) VALUES(1,2),(4,8),(16,32),(4,80),(1,-300);
|
|
CREATE TABLE t4(x INT, y INT);
|
|
INSERT INTO t4(x,y) SELECT a, b FROM t3;
|
|
INSERT INTO t4(x,y) VALUES(99,99);
|
|
SELECT a1.a, sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t4 ON a=x
|
|
GROUP BY a1.a ORDER BY 1;
|
|
} {NULL NULL 1 -592 4 192 16 48}
|
|
do_execsql_test 13.4 {
|
|
SELECT sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t3 ON true
|
|
GROUP BY a1.a ORDER BY 1;
|
|
} {-1480 240 480}
|
|
|
|
finish_test
|