Fix a problem with virtual tables and joins. (CVS 3278)

FossilOrigin-Name: 643e63e5883eec109a91a44dae62b58650646575
This commit is contained in:
danielk1977
2006-06-21 07:02:33 +00:00
parent 93626f4869
commit fbbe005a59
6 changed files with 478 additions and 15 deletions
+9 -8
View File
@@ -1,5 +1,5 @@
C Fix\ssome\sproblems\swith\svirtual\stables\sand\sjoins\sin\swhere.c.\s(CVS\s3277)
D 2006-06-20T13:07:27
C Fix\sa\sproblem\swith\svirtual\stables\sand\sjoins.\s(CVS\s3278)
D 2006-06-21T07:02:33
F Makefile.in f839b470345d3cb4b0644068474623fe2464b5d3
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -69,7 +69,7 @@ F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55
F src/prepare.c 6dc945dab34cf97364c661d2b7a12be65d338267
F src/printf.c 7029e5f7344a478394a02c52837ff296ee1ab240
F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
F src/select.c 6dd3fdfeaebe2565944241e7e7a0d3e1d8469c12
F src/select.c 380fa06c99ae01050c0054c4b1db91e9f1d8322d
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c ad73192b30a338a58fe81183d4a5d5a1d4e51d36
F src/sqlite.h.in 7855b46387f3f6ac1925301f450df9cbd7a1269b
@@ -84,7 +84,7 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
F src/test8.c ec03e990c8c64d6d71dae459bf1dd72e75996362
F src/test8.c 03563ba045b2c46dc98284144d3e0052d9ea08ba
F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
@@ -291,11 +291,12 @@ F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f
F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
F test/vtab1.test 1a5233154cbdf3e5324feba9c74dda0eee0ac135
F test/vtab1.test ab6cf2670f769efc0ac8a7d8c272f910da296dbc
F test/vtab2.test e57f9865368df26ef5eb8bc630962d82086f174b
F test/vtab3.test f38d6d7d19f08bffdadce4d5b8cba078f8118587
F test/vtab4.test 4b4293341443839ef6dc02f8d9e614702a6c67ff
F test/vtab5.test a275f233722cbc89141710e5df62421ae26d456b
F test/vtab6.test 0b4fe07e421b2b9a334bec8781e75cbd8e230bd3
F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
@@ -371,7 +372,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P c6ea353bd9f5fe6c9cc3349d2034ada283f9c80e
R 29f7d43d1ba21e43482cd4da4cb99600
P 3e19a7d8eabcd2fa71ced3f76c5f9bc1f3900b81
R dd2e65c82fc19b7cf06d61c3f62a9682
U danielk1977
Z 1d9af2117d83aafa007dd01f8ea28b29
Z 403c1a151f48024ee7e51bb28ac7757a
+1 -1
View File
@@ -1 +1 @@
3e19a7d8eabcd2fa71ced3f76c5f9bc1f3900b81
643e63e5883eec109a91a44dae62b58650646575
+2 -1
View File
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.317 2006/06/20 13:07:27 danielk1977 Exp $
** $Id: select.c,v 1.318 2006/06/21 07:02:33 danielk1977 Exp $
*/
#include "sqliteInt.h"
@@ -2008,6 +2008,7 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
assert( pExpr->pList==0 );
pExpr->pList = sqlite3ExprListDup(pNew->pList);
pExpr->iTable = pNew->iTable;
pExpr->pTab = pNew->pTab;
pExpr->iColumn = pNew->iColumn;
pExpr->iAgg = pNew->iAgg;
sqlite3TokenCopy(&pExpr->token, &pNew->token);
+8 -4
View File
@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.27 2006/06/20 11:01:08 danielk1977 Exp $
** $Id: test8.c,v 1.28 2006/06/21 07:02:34 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -325,9 +325,12 @@ static int echoColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
if( ((echo_cursor *)cur)->errcode ){
return ((echo_cursor *)cur)->errcode;
}
assert( sqlite3_data_count(pStmt)>iCol );
sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol));
if( !pStmt ){
sqlite3_result_null(ctx);
}else{
assert( sqlite3_data_count(pStmt)>iCol );
sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol));
}
return SQLITE_OK;
}
@@ -373,6 +376,7 @@ static int echoFilter(
sqlite3_finalize(pCur->pStmt);
pCur->pStmt = 0;
rc = sqlite3_prepare(db, idxStr, -1, &pCur->pStmt, 0);
assert( pCur->pStmt || rc!=SQLITE_OK );
for(i=0; rc==SQLITE_OK && i<argc; i++){
switch( sqlite3_value_type(argv[i]) ){
case SQLITE_INTEGER: {
+6 -1
View File
@@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.24 2006/06/20 13:07:28 danielk1977 Exp $
# $Id: vtab1.test,v 1.25 2006/06/21 07:02:34 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -280,6 +280,11 @@ do_test vtab1-3.7 {
SELECT rowid, * FROM t1;
}
} {1 1 2 3 2 4 5 6}
do_test vtab1-3.8 {
execsql {
SELECT a AS d, b AS e, c AS f FROM t1;
}
} {1 2 3 4 5 6}
# Execute some SELECT statements with WHERE clauses on the t1 table.
# Then check the echo_module variable (written to by the module methods
+452
View File
@@ -0,0 +1,452 @@
# 2002 May 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.
#
# This file implements tests for joins, including outer joins involving
# virtual tables. The test cases in this file are copied from the file
# join.test, and some of the comments still reflect that.
#
# $Id: vtab6.test,v 1.1 2006/06/21 07:02:34 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
register_echo_module [sqlite3_connection_pointer db]
execsql {
CREATE TABLE real_t1(a,b,c);
CREATE TABLE real_t2(b,c,d);
CREATE TABLE real_t3(c,d,e);
CREATE TABLE real_t4(d,e,f);
CREATE TABLE real_t5(a INTEGER PRIMARY KEY);
CREATE TABLE real_t6(a INTEGER);
CREATE TABLE real_t7 (x, y);
CREATE TABLE real_t8 (a integer primary key, b);
CREATE TABLE real_t9(a INTEGER PRIMARY KEY, b);
CREATE TABLE real_t10(x INTEGER PRIMARY KEY, y);
CREATE TABLE real_t11(p INTEGER PRIMARY KEY, q);
CREATE TABLE real_t12(a,b);
CREATE TABLE real_t13(b,c);
CREATE TABLE real_t21(a,b,c);
CREATE TABLE real_t22(p,q);
}
foreach t [list t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t21 t22] {
execsql "CREATE VIRTUAL TABLE $t USING echo(real_$t)"
}
do_test vtab6-1.1 {
execsql {
INSERT INTO t1 VALUES(1,2,3);
INSERT INTO t1 VALUES(2,3,4);
INSERT INTO t1 VALUES(3,4,5);
SELECT * FROM t1;
}
} {1 2 3 2 3 4 3 4 5}
do_test vtab6-1.2 {
execsql {
INSERT INTO t2 VALUES(1,2,3);
INSERT INTO t2 VALUES(2,3,4);
INSERT INTO t2 VALUES(3,4,5);
SELECT * FROM t2;
}
} {1 2 3 2 3 4 3 4 5}
do_test vtab6-1.3 {
execsql2 {
SELECT * FROM t1 NATURAL JOIN t2;
}
} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
do_test vtab6-1.3.1 {
execsql2 {
SELECT * FROM t2 NATURAL JOIN t1;
}
} {b 2 c 3 d 4 a 1 b 3 c 4 d 5 a 2}
do_test vtab6-1.3.2 {
execsql2 {
SELECT * FROM t2 AS x NATURAL JOIN t1;
}
} {b 2 c 3 d 4 a 1 b 3 c 4 d 5 a 2}
do_test vtab6-1.3.3 {
execsql2 {
SELECT * FROM t2 NATURAL JOIN t1 AS y;
}
} {b 2 c 3 d 4 a 1 b 3 c 4 d 5 a 2}
do_test vtab6-1.3.4 {
execsql {
SELECT b FROM t1 NATURAL JOIN t2;
}
} {2 3}
do_test vtab6-1.4.1 {
execsql2 {
SELECT * FROM t1 INNER JOIN t2 USING(b,c);
}
} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
do_test vtab6-1.4.2 {
execsql2 {
SELECT * FROM t1 AS x INNER JOIN t2 USING(b,c);
}
} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
do_test vtab6-1.4.3 {
execsql2 {
SELECT * FROM t1 INNER JOIN t2 AS y USING(b,c);
}
} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
do_test vtab6-1.4.4 {
execsql2 {
SELECT * FROM t1 AS x INNER JOIN t2 AS y USING(b,c);
}
} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
do_test vtab6-1.4.5 {
execsql {
SELECT b FROM t1 JOIN t2 USING(b);
}
} {2 3}
do_test vtab6-1.5 {
execsql2 {
SELECT * FROM t1 INNER JOIN t2 USING(b);
}
} {a 1 b 2 c 3 c 3 d 4 a 2 b 3 c 4 c 4 d 5}
do_test vtab6-1.6 {
execsql2 {
SELECT * FROM t1 INNER JOIN t2 USING(c);
}
} {a 1 b 2 c 3 b 2 d 4 a 2 b 3 c 4 b 3 d 5}
do_test vtab6-1.7 {
execsql2 {
SELECT * FROM t1 INNER JOIN t2 USING(c,b);
}
} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
do_test vtab6-1.8 {
execsql {
SELECT * FROM t1 NATURAL CROSS JOIN t2;
}
} {1 2 3 4 2 3 4 5}
do_test vtab6-1.9 {
execsql {
SELECT * FROM t1 CROSS JOIN t2 USING(b,c);
}
} {1 2 3 4 2 3 4 5}
do_test vtab6-1.10 {
execsql {
SELECT * FROM t1 NATURAL INNER JOIN t2;
}
} {1 2 3 4 2 3 4 5}
do_test vtab6-1.11 {
execsql {
SELECT * FROM t1 INNER JOIN t2 USING(b,c);
}
} {1 2 3 4 2 3 4 5}
do_test vtab6-1.12 {
execsql {
SELECT * FROM t1 natural inner join t2;
}
} {1 2 3 4 2 3 4 5}
ifcapable subquery {
breakpoint
do_test vtab6-1.13 {
execsql2 {
SELECT * FROM t1 NATURAL JOIN
(SELECT b as 'c', c as 'd', d as 'e' FROM t2) as t3
}
} {a 1 b 2 c 3 d 4 e 5}
do_test vtab6-1.14 {
execsql2 {
SELECT * FROM (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as 'tx'
NATURAL JOIN t1
}
} {c 3 d 4 e 5 a 1 b 2}
}
do_test vtab6-1.15 {
execsql {
INSERT INTO t3 VALUES(2,3,4);
INSERT INTO t3 VALUES(3,4,5);
INSERT INTO t3 VALUES(4,5,6);
SELECT * FROM t3;
}
} {2 3 4 3 4 5 4 5 6}
do_test vtab6-1.16 {
execsql {
SELECT * FROM t1 natural join t2 natural join t3;
}
} {1 2 3 4 5 2 3 4 5 6}
do_test vtab6-1.17 {
execsql2 {
SELECT * FROM t1 natural join t2 natural join t3;
}
} {a 1 b 2 c 3 d 4 e 5 a 2 b 3 c 4 d 5 e 6}
do_test vtab6-1.18 {
execsql {
INSERT INTO t4 VALUES(2,3,4);
INSERT INTO t4 VALUES(3,4,5);
INSERT INTO t4 VALUES(4,5,6);
SELECT * FROM t4;
}
} {2 3 4 3 4 5 4 5 6}
do_test vtab6-1.19.1 {
execsql {
SELECT * FROM t1 natural join t2 natural join t4;
}
} {1 2 3 4 5 6}
do_test vtab6-1.19.2 {
execsql2 {
SELECT * FROM t1 natural join t2 natural join t4;
}
} {a 1 b 2 c 3 d 4 e 5 f 6}
do_test vtab6-1.20 {
execsql {
SELECT * FROM t1 natural join t2 natural join t3 WHERE t1.a=1
}
} {1 2 3 4 5}
do_test vtab6-2.1 {
execsql {
SELECT * FROM t1 NATURAL LEFT JOIN t2;
}
} {1 2 3 4 2 3 4 5 3 4 5 {}}
do_test vtab6-2.2 {
execsql {
SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1;
}
} {1 2 3 {} 2 3 4 1 3 4 5 2}
do_test vtab6-2.3 {
catchsql {
SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
}
} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
do_test vtab6-2.4 {
execsql {
SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d
}
} {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3}
do_test vtab6-2.5 {
execsql {
SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t1.a>1
}
} {2 3 4 {} {} {} 3 4 5 1 2 3}
do_test vtab6-2.6 {
execsql {
SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t2.b IS NULL OR t2.b>1
}
} {1 2 3 {} {} {} 2 3 4 {} {} {}}
do_test vtab6-3.1 {
catchsql {
SELECT * FROM t1 NATURAL JOIN t2 ON t1.a=t2.b;
}
} {1 {a NATURAL join may not have an ON or USING clause}}
do_test vtab6-3.2 {
catchsql {
SELECT * FROM t1 NATURAL JOIN t2 USING(b);
}
} {1 {a NATURAL join may not have an ON or USING clause}}
do_test vtab6-3.3 {
catchsql {
SELECT * FROM t1 JOIN t2 ON t1.a=t2.b USING(b);
}
} {1 {cannot have both ON and USING clauses in the same join}}
do_test vtab6-3.4 {
catchsql {
SELECT * FROM t1 JOIN t2 USING(a);
}
} {1 {cannot join using column a - column not present in both tables}}
do_test vtab6-3.5 {
catchsql {
SELECT * FROM t1 USING(a);
}
} {0 {1 2 3 2 3 4 3 4 5}}
do_test vtab6-3.6 {
catchsql {
SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
}
} {1 {no such column: t3.a}}
do_test vtab6-3.7 {
catchsql {
SELECT * FROM t1 INNER OUTER JOIN t2;
}
} {1 {unknown or unsupported join type: INNER OUTER}}
do_test vtab6-3.7 {
catchsql {
SELECT * FROM t1 LEFT BOGUS JOIN t2;
}
} {1 {unknown or unsupported join type: LEFT BOGUS}}
do_test vtab6-4.1 {
execsql {
BEGIN;
INSERT INTO t6 VALUES(NULL);
INSERT INTO t6 VALUES(NULL);
INSERT INTO t6 SELECT * FROM t6;
INSERT INTO t6 SELECT * FROM t6;
INSERT INTO t6 SELECT * FROM t6;
INSERT INTO t6 SELECT * FROM t6;
INSERT INTO t6 SELECT * FROM t6;
INSERT INTO t6 SELECT * FROM t6;
COMMIT;
}
execsql {
SELECT * FROM t6 NATURAL JOIN t5;
}
} {}
do_test vtab6-4.2 {
execsql {
SELECT * FROM t6, t5 WHERE t6.a<t5.a;
}
} {}
do_test vtab6-4.3 {
execsql {
SELECT * FROM t6, t5 WHERE t6.a>t5.a;
}
} {}
do_test vtab6-4.4 {
execsql {
UPDATE t6 SET a='xyz';
SELECT * FROM t6 NATURAL JOIN t5;
}
} {}
do_test vtab6-4.6 {
execsql {
SELECT * FROM t6, t5 WHERE t6.a<t5.a;
}
} {}
do_test vtab6-4.7 {
execsql {
SELECT * FROM t6, t5 WHERE t6.a>t5.a;
}
} {}
do_test vtab6-4.8 {
execsql {
UPDATE t6 SET a=1;
SELECT * FROM t6 NATURAL JOIN t5;
}
} {}
do_test vtab6-4.9 {
execsql {
SELECT * FROM t6, t5 WHERE t6.a<t5.a;
}
} {}
do_test vtab6-4.10 {
execsql {
SELECT * FROM t6, t5 WHERE t6.a>t5.a;
}
} {}
# A test for ticket #247.
#
do_test vtab6-7.1 {
execsql {
INSERT INTO t7 VALUES ("pa1", 1);
INSERT INTO t7 VALUES ("pa2", NULL);
INSERT INTO t7 VALUES ("pa3", NULL);
INSERT INTO t7 VALUES ("pa4", 2);
INSERT INTO t7 VALUES ("pa30", 131);
INSERT INTO t7 VALUES ("pa31", 130);
INSERT INTO t7 VALUES ("pa28", NULL);
INSERT INTO t8 VALUES (1, "pa1");
INSERT INTO t8 VALUES (2, "pa4");
INSERT INTO t8 VALUES (3, NULL);
INSERT INTO t8 VALUES (4, NULL);
INSERT INTO t8 VALUES (130, "pa31");
INSERT INTO t8 VALUES (131, "pa30");
SELECT coalesce(t8.a,999) from t7 LEFT JOIN t8 on y=a;
}
} {1 999 999 2 131 130 999}
# Make sure a left join where the right table is really a view that
# is itself a join works right. Ticket #306.
#
ifcapable view {
do_test vtab6-8.1 {
execsql {
BEGIN;
INSERT INTO t9 VALUES(1,11);
INSERT INTO t9 VALUES(2,22);
INSERT INTO t10 VALUES(1,2);
INSERT INTO t10 VALUES(3,3);
INSERT INTO t11 VALUES(2,111);
INSERT INTO t11 VALUES(3,333);
CREATE VIEW v10_11 AS SELECT x, q FROM t10, t11 WHERE t10.y=t11.p;
COMMIT;
SELECT * FROM t9 LEFT JOIN v10_11 ON( a=x );
}
} {1 11 1 111 2 22 {} {}}
ifcapable subquery {
do_test vtab6-8.2 {
execsql {
SELECT * FROM t9 LEFT JOIN (SELECT x, q FROM t10, t11 WHERE t10.y=t11.p)
ON( a=x);
}
} {1 11 1 111 2 22 {} {}}
}
do_test vtab6-8.3 {
execsql {
SELECT * FROM v10_11 LEFT JOIN t9 ON( a=x );
}
} {1 111 1 11 3 333 {} {}}
} ;# ifcapable view
# Ticket #350 describes a scenario where LEFT OUTER JOIN does not
# function correctly if the right table in the join is really
# subquery.
#
# To test the problem, we generate the same LEFT OUTER JOIN in two
# separate selects but with on using a subquery and the other calling
# the table directly. Then connect the two SELECTs using an EXCEPT.
# Both queries should generate the same results so the answer should
# be an empty set.
#
ifcapable compound {
do_test vtab6-9.1 {
execsql {
BEGIN;
INSERT INTO t12 VALUES(1,11);
INSERT INTO t12 VALUES(2,22);
INSERT INTO t13 VALUES(22,222);
COMMIT;
}
} {}
ifcapable subquery {
do_test vtab6-9.1.1 {
execsql {
SELECT * FROM t12 NATURAL LEFT JOIN t13
EXCEPT
SELECT * FROM t12 NATURAL LEFT JOIN (SELECT * FROM t13 WHERE b>0);
}
} {}
}
ifcapable view {
do_test vtab6-9.2 {
execsql {
CREATE VIEW v13 AS SELECT * FROM t13 WHERE b>0;
SELECT * FROM t12 NATURAL LEFT JOIN t13
EXCEPT
SELECT * FROM t12 NATURAL LEFT JOIN v13;
}
} {}
} ;# ifcapable view
} ;# ifcapable compound
ifcapable subquery {
do_test vtab6-10.1 {
execsql {
CREATE INDEX i22 ON real_t22(q);
SELECT a FROM t21 LEFT JOIN t22 ON b=p WHERE q=
(SELECT max(m.q) FROM t22 m JOIN t21 n ON n.b=m.p WHERE n.c=1);
}
} {}
} ;# ifcapable subquery
finish_test