From: drh <> Date: Fri, 22 Aug 2025 19:17:44 +0000 (+0000) Subject: Remember if a SELECT statement contains an ON clause. If it does, then after X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fbb07ff67f585a0d60010d8a5b05c2d442f07fc8;p=thirdparty%2Fsqlite.git Remember if a SELECT statement contains an ON clause. If it does, then after name resolution, scan the WHERE clause to verify that the ON clause does not reference tables to its right. FossilOrigin-Name: 0ec8a8f64434f8cc04f02a356ecaa409ebd886566ba09c32f0fff8ebd103a609 --- diff --git a/manifest b/manifest index c098e4e21c..01c8ad28a1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\streeview\sso\sthat\sit\sshows\sthe\scontents\sof\sON\sclauses\swhile\nthey\sare\sstill\sattached\sto\sthe\sSrcItem\sobject\sand\sbefore\sthey\sare\nmoved\sinto\sthe\sWHERE\sclause. -D 2025-08-22T18:19:26.194 +C Remember\sif\sa\sSELECT\sstatement\scontains\san\sON\sclause.\s\sIf\sit\sdoes,\sthen\safter\nname\sresolution,\sscan\sthe\sWHERE\sclause\sto\sverify\sthat\sthe\sON\sclause\sdoes\snot\nreference\stables\sto\sits\sright. +D 2025-08-22T19:17:44.984 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -741,12 +741,12 @@ F src/printf.c 5f0c957af9699e849d786e8fbaa3baab648ca5612230dc17916434c14bc8698f F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c f8d1d011aba0964ff1bdccd049d4d2c2fec217efd90d202a4bb775e926b2c25d F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 -F src/select.c 78ebf432355e820962a5001277cb43ffe3d82441c6dc9c8f0aeb0b15fbd5dd02 +F src/select.c a8dadaafc129724107aee67153732e3cd3637207993e2f60073b76344edba239 F src/shell.c.in 0636915df0dbac6c780f04959f5d1055f206fb281b2c8fc8b113fe7bfc7d44ef F src/sqlite.h.in ebfc0358de0e18aabee7fa918f2f846894e23bebc74160fbe265c99046ee61b8 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e -F src/sqliteInt.h a54f83985985655d1276e9e356dd6ae19b8d0b62c2abc75cc9e8f402ea141207 +F src/sqliteInt.h 7a313bfc16ea0a3b48f9b0fe69f887c971cc7884ce05969f9f02a229b8a31aae F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364 F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -826,7 +826,7 @@ F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 F src/where.c f2f075bd17065922235632feb368efe92a7f03d42797eb575267574fbf6d4218 F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da F src/wherecode.c 71c5c6804b7f882dec8ec858758accae02fcfca13df3cc720f1f258e663ec7c5 -F src/whereexpr.c 78c28a8da187816d5d82049f2e343fb39f4a8e30b5bf1bda9b96cecde40ca8bd +F src/whereexpr.c 403a44eeec1a0f0914fccc6a59376b6924bc00ef6728fe6ffce4cf3051b320fc F src/window.c d01227141f622f24fbe36ca105fbe6ef023f9fd98f1ccd65da95f88886565db5 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d @@ -2169,8 +2169,11 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9ada44eb6d26532e45cdd2ed8d5707f1734d0177a13b493ff9cf070e0a992522 -R 6e697a296e1f3201fc9a77e474a82c56 +P 3e285bc117bcbfafe083709d27cca776d6ba418a9f0f58a6d4178035fba2d6ca +R 96dd89e794ca1ca3ff39762daec8741d +T *branch * on-clause-fix-3rd-try +T *sym-on-clause-fix-3rd-try * +T -sym-trunk * U drh -Z ad617721d7c7f540adf02c29a96cfdc3 +Z 3d2156998fed14f6409bf44712a40780 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index bb4c1eff6c..eda1ade79b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3e285bc117bcbfafe083709d27cca776d6ba418a9f0f58a6d4178035fba2d6ca +0ec8a8f64434f8cc04f02a356ecaa409ebd886566ba09c32f0fff8ebd103a609 diff --git a/src/select.c b/src/select.c index 8bdd13e272..b9cc333acc 100644 --- a/src/select.c +++ b/src/select.c @@ -660,6 +660,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){ p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn); pRight->u3.pOn = 0; pRight->fg.isOn = 1; + p->selFlags |= SF_OnToWhere; } } return 0; @@ -7495,6 +7496,50 @@ static SQLITE_NOINLINE void existsToJoin( } } +/* +** The xExpr and xSelect callbacks for the search of invalid ON clause terms. +*/ +static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_COLUMN + && ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) + ){ + if( pExpr->w.iJoiniTable ){ + if( ExprHasProperty(pExpr, EP_OuterON) || pWalker->eCode ){ + sqlite3ErrorMsg(pWalker->pParse, + "ON clause references tables to its right"); + return WRC_Abort; + } + } + } + return WRC_Continue; +} +static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){ + UNUSED_PARAMETER(pWalker); + if( (pSelect->selFlags & SF_OnToWhere)==0 ){ + return WRC_Prune; + }else{ + return WRC_Continue; + } +} + +/* +** Check all ON clauses in pSelect to verify that they do not reference +** columns to the right. +*/ +static void selectCheckOnClauses(Parse *pParse, Select *pSelect){ + Walker w; + + assert( pSelect->selFlags & SF_OnToWhere ); + assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 ); + memset(&w, 0, sizeof(w)); + w.pParse = pParse; + w.eCode = (pSelect->pSrc->a[0].fg.jointype & JT_LTORJ)!=0; + w.xExprCallback = selectCheckOnClausesExpr; + w.xSelectCallback = selectCheckOnClausesSelect; + sqlite3WalkSelect(&w, pSelect); + pSelect->selFlags &= ~SF_OnToWhere; +} + /* ** Generate byte-code for the SELECT statement given in the p argument. ** @@ -7622,6 +7667,18 @@ int sqlite3Select( } #endif + /* If the SELECT statement contains ON clauses that were moved into + ** into the WHERE clause, go through and verify that none of the terms + ** in the ON clauses reference tables to the right of the ON clause. + ** Do this now, after name resolution, but before query flattening + */ + if( p->selFlags & SF_OnToWhere ){ + selectCheckOnClauses(pParse, p); + if( pParse->nErr ){ + goto select_end; + } + } + /* If the SF_UFSrcCheck flag is set, then this function is being called ** as part of populating the temp table for an UPDATE...FROM statement. ** In this case, it is an error if the target object (pSrc->a[0]) name diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a09c94ae62..d80ede7c75 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3660,6 +3660,7 @@ struct Select { #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ #define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */ #define SF_Correlated 0x20000000 /* True if references the outer context */ +#define SF_OnToWhere 0x40000000 /* One or more ON clauses moved to WHERE */ /* True if SrcItem X is a subquery that has SF_NestedFrom */ #define IsNestedFrom(X) \ diff --git a/src/whereexpr.c b/src/whereexpr.c index 0d17b0d752..0d99ca85e6 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1170,21 +1170,7 @@ static void exprAnalyze( prereqAll |= x; extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ - if( (prereqAll>>1)>=x ){ - sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); - return; - } }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 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 FULL JOIN in the query. This makes SQLite - ** more like other systems, and also preserves legacy. */ - if( ALWAYS(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); } }