From: danielk1977 Date: Wed, 21 Jun 2006 07:02:33 +0000 (+0000) Subject: Fix a problem with virtual tables and joins. (CVS 3278) X-Git-Tag: version-3.6.10~2889 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fbbe005a595e4cced9b8699f8dd5be240075fcd1;p=thirdparty%2Fsqlite.git Fix a problem with virtual tables and joins. (CVS 3278) FossilOrigin-Name: 643e63e5883eec109a91a44dae62b58650646575 --- diff --git a/manifest b/manifest index f402497176..7dbc0a6fc3 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index fd2061af5e..8cab2de92a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3e19a7d8eabcd2fa71ced3f76c5f9bc1f3900b81 \ No newline at end of file +643e63e5883eec109a91a44dae62b58650646575 \ No newline at end of file diff --git a/src/select.c b/src/select.c index be9c6c23c7..c909fc00f5 100644 --- a/src/select.c +++ b/src/select.c @@ -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); diff --git a/src/test8.c b/src/test8.c index 9bf61b0f69..70f1ebb754 100644 --- a/src/test8.c +++ b/src/test8.c @@ -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 && i1 + } +} {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.at5.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.at5.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.at5.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