0
0
mirror of https://github.com/sqlite/sqlite.git synced 2024-11-25 00:49:41 +01:00

Do not allow an ON clause to references tables to its right if there is a

RIGHT or LEFT join anywhere in the query.  Other RDBMSes prohibit this always,
but SQLite must allow ON clauses to reference tables to their right for legacy
compatibility, unless there is a RIGHT or LEFT join someplace in the query,
in which case there is no legacy to support.

FossilOrigin-Name: e615dbe02ca949252d1526ed5c48f8ce08159773ea2008ce666484379d0d9854
This commit is contained in:
drh 2022-06-20 17:04:44 +00:00
parent ae8776e092
commit d7480403bc
6 changed files with 46 additions and 27 deletions

View File

@ -741,10 +741,19 @@ do_execsql_test 20.0 {
CREATE TABLE t0(a INT);
CREATE TABLE t1(b INT);
INSERT INTO rt0 VALUES(0, 0, 0);
}
do_catchsql_test 20.1 {
SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE +x0 = 0;
} {}
do_execsql_test 20.1 {
} {1 {ON clause references tables to its right}}
do_catchsql_test 20.2 {
SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE x0 = 0;
} {}
} {1 {ON clause references tables to its right}}
db null -
do_execsql_test 20.3 {
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE +x0 = 0;
} {- - 0 0.0 0.0}
do_execsql_test 20.4 {
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE x0 = 0;
} {- - 0 0.0 0.0}
finish_test

View File

@ -1,5 +1,5 @@
C The\sfix\sat\s[cab9b4cccd13bf0a]\swas\sincomplete,\sas\sdemonstrated\sby\n[forum:/forumpost/57bdf2217d|forum\spost\s57bdf2217d].\s\sThis\scheck-in\nshould\scomplete\sthe\sfix.
D 2022-06-20T12:42:28.345
C Do\snot\sallow\san\sON\sclause\sto\sreferences\stables\sto\sits\sright\sif\sthere\sis\sa\nRIGHT\sor\sLEFT\sjoin\sanywhere\sin\sthe\squery.\s\sOther\sRDBMSes\sprohibit\sthis\salways,\nbut\sSQLite\smust\sallow\sON\sclauses\sto\sreference\stables\sto\stheir\sright\sfor\slegacy\ncompatibility,\sunless\sthere\sis\sa\sRIGHT\sor\sLEFT\sjoin\ssomeplace\sin\sthe\squery,\nin\swhich\scase\sthere\sis\sno\slegacy\sto\ssupport.
D 2022-06-20T17:04:44.141
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -416,7 +416,7 @@ F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/geopoly.c cc3f89c11abcf114fa60d74709ae8b5bc1eae5a261b30bc1bb7085089c03bfab
F ext/rtree/rtree.c d7b4b8b81d8d54376a7f81de5be85ec58b37c11604bcf42984a8418b34158d93
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 70c092dcf34716b64edc9dbab171790322aa87b89a48f7437b8b4c7b466449c4
F ext/rtree/rtree1.test d47f58832145fcfed9067bc457ca8664962196c4566c17a1ebd679367db55d11
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
@ -570,7 +570,7 @@ F src/printf.c 6166a30417b05c5b2f82e1f183f75faa2926ad60531c0b688a57dbc951441a20
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c a4eb3c617027fd049b07432f3b942ea7151fa793a332a11a7d0f58c9539e104f
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c e3181898cc05e8a78195f1792f170760df49262d6267dcaa834160900aab7d37
F src/select.c baadb1b3fd0e87f82f0c416b68a5b8d90d8f4ffb3568c9a86f84a2be7d40261f
F src/shell.c.in 08e59f1cb9d9b1180aba52861aaada0c95f6ddd210488719684e160a0724c806
F src/sqlite.h.in 172528c287399a34f188154017b7268bf82c6d5b780902e361958d2318c4e37c
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@ -660,7 +660,7 @@ F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c 2db3d41a1fd3b93d86680b4f33530d1f96ce9941771ebee80effba071d9d1e38
F src/whereInt.h b48ca529ffe293c18cbfa8326af18a09e39910de66fb3e96ef788c7cbf8ef3a7
F src/wherecode.c 0b09abfcb88c61c6a6984a3e065786631ff35495e9bdf865e6b74ab0a1299c5b
F src/whereexpr.c 20255cf03e0b765b742301197d165511ff99e95da0d7ee9c8a2ebc1e888dd049
F src/whereexpr.c 3b5f9f6f9fc07039b242ecf7a66e87392e9c49d62923b3c593c904090bd9345c
F src/window.c fff1b51757438c664e471d5184634e48dcdf8ea34b640f3b1b0810b1e06de18c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@ -1168,7 +1168,7 @@ F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test d22b6cba8fb59ab3f1c82701434c360705eb12d4ce200c449f37b018fc47681a
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/join7.test 2268dcbb54b724391dda3748ea95c60d960607ffeed67885675998e7117697f6
F test/join8.test c839d7cd4704b600468fd4d82d92bfe3eac67623c41dbfb99f804cdad7a3846e
F test/join8.test 6d063ef3fa580ff9e50015107b0e6caf51e7055731749ba6391b8f11c1e00e3f
F test/join9.test 9056ddd3b0c0f4f9d658f4521038d9a37dc23ead8ca9a505d0b0db2b6a471e05
F test/joinA.test 7eab225dc1c1ab258a5e62513a4ed7cabbd3db971d59d5d92f4fb6fa14c12f6a
F test/joinB.test 1b2ba3fc8568b49411787fccbf540570c148e9b6a53a30f80691cb6268098ded
@ -1978,8 +1978,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 11162446f12ae3af6e4a63bb5c374129b2505f6006f91d4028c7165f05fe9651
R e2f301053cf79999e11ddef561e846ed
P fb0a23b6789da8e934562ce9ebd9d58ea13a10fd10dee5cbfc7ac8f394e1aeec
R 9a31acf363f55129767709f03c1bfdcf
U drh
Z 238d98417a47860062f9a4d41505b756
Z ae2f170f0ee7cf50c320a853890db816
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
fb0a23b6789da8e934562ce9ebd9d58ea13a10fd10dee5cbfc7ac8f394e1aeec
e615dbe02ca949252d1526ed5c48f8ce08159773ea2008ce666484379d0d9854

View File

@ -424,11 +424,13 @@ void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
}
}
/* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every
** term that is marked with EP_OuterON and w.iJoin==iTable into
** an ordinary term that omits the EP_OuterON mark.
/* Undo the work of sqlite3SetJoinExpr(). This is used when a LEFT JOIN
** is simplified into an ordinary JOIN, and when an ON expression is
** "pushed down" into the WHERE clause of a subquery.
**
** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
** Convert every term that is marked with EP_OuterON and w.iJoin==iTable into
** an ordinary term that omits the EP_OuterON mark. Or if iTable<0, then
** just clear every EP_OuterON and EP_InnerON mark from the expression tree.
**
** If nullable is true, that means that Expr p might evaluate to NULL even
** if it is a reference to a NOT NULL column. This can happen, for example,
@ -438,10 +440,9 @@ void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
*/
static void unsetJoinExpr(Expr *p, int iTable, int nullable){
while( p ){
if( ExprHasProperty(p, EP_OuterON)
&& (iTable<0 || p->w.iJoin==iTable) ){
ExprClearProperty(p, EP_OuterON);
ExprSetProperty(p, EP_InnerON);
if( iTable<0 || (ExprHasProperty(p, EP_OuterON) && p->w.iJoin==iTable) ){
ExprClearProperty(p, EP_OuterON|EP_InnerON);
if( iTable>=0 ) ExprSetProperty(p, EP_InnerON);
}
if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){
ExprClearProperty(p, EP_CanBeNull);
@ -6771,6 +6772,7 @@ int sqlite3Select(
SELECTTRACE(0x100,pParse,p,
("LEFT-JOIN simplifies to JOIN on term %d\n",i));
pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
assert( pItem->iCursor>=0 );
unsetJoinExpr(p->pWhere, pItem->iCursor,
pTabList->a[0].fg.jointype & JT_LTORJ);
}

View File

@ -1121,9 +1121,15 @@ static void exprAnalyze(
}
}else if( (prereqAll>>1)>=x ){
/* The ON clause of an INNER JOIN references a table to its right.
** Most other SQL database engines raise an error. But all versions
** of SQLite going back to 3.0.0 have just put the ON clause constraint
** into the WHERE clause and carried on. */
** Most other SQL database engines raise an error. But SQLite versions
** 3.0 through 3.38 just put the ON clause constraint into the WHERE
** clause and carried on. Beginning with 3.39, raise an error only
** if there is a RIGHT or LEFT JOIN in the query. This makes SQLite
** more like other systems, and also preserves legacy. */
if( pSrc->nSrc>0 && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
return;
}
ExprClearProperty(pExpr, EP_InnerON);
}
}

View File

@ -684,11 +684,13 @@ do_execsql_test join8-22030 {
CREATE TABLE t3(c INTEGER PRIMARY KEY, d INT);
CREATE INDEX t3d ON t3(d);
INSERT INTO t3 VALUES(0, 0);
}
do_catchsql_test join8-22031 {
SELECT * FROM t1 JOIN t2 ON d>b RIGHT JOIN t3 ON true WHERE +d = 0;
} {}
do_execsql_test join8-22040 {
} {1 {ON clause references tables to its right}}
do_catchsql_test join8-22040 {
SELECT * FROM t1 JOIN t2 ON d>b RIGHT JOIN t3 ON true WHERE d = 0;
} {}
} {1 {ON clause references tables to its right}}
# 2022-06-10