From: dan Date: Sat, 23 Aug 2025 16:26:36 +0000 (+0000) Subject: Fix the cases in joinI.test on this branch. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4bace197e10f565b89b991c2da825da3d6d30946;p=thirdparty%2Fsqlite.git Fix the cases in joinI.test on this branch. FossilOrigin-Name: 23ac2377315af02b73db6ae37bfeeda1453e41efb702a6b707346956c2d41a9d --- diff --git a/manifest b/manifest index 9565585a14..24ad7a244a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Steal\sthe\stest/joinI.test\sfrom\sthe\son-clause-error-fix\sbranch\sthat\ndemonstrates\sthat\sthis\sbranch\sdoes\snot\swork. -D 2025-08-22T19:30:26.745 +C Fix\sthe\scases\sin\sjoinI.test\son\sthis\sbranch. +D 2025-08-23T16:26:36.004 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 a8dadaafc129724107aee67153732e3cd3637207993e2f60073b76344edba239 +F src/select.c 32ccbdbc89ba40065891c891a6a9dcd50fb3171eaf041b8549929f479dd540cb 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 7a313bfc16ea0a3b48f9b0fe69f887c971cc7884ce05969f9f02a229b8a31aae +F src/sqliteInt.h 27c73e48878d31ef230ba867d1f8c3af6aed357fd93ccc605d3f1aae007ea62b F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364 F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -1335,7 +1335,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127 F test/joinH.test fd76024ff104baec16417db5cafc0894ad4e0863e70803e63c1bba0322706339 -F test/joinI.test 78cae6f746a78f32d8aedb8cf7b93bcd802c245db0986330844dfb1a6700ebab +F test/joinI.test c30a1096c80a1300f088feb64fd356309cd14059d78352426550d2676f015ab4 F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4 F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6 @@ -2170,8 +2170,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0ec8a8f64434f8cc04f02a356ecaa409ebd886566ba09c32f0fff8ebd103a609 -R 1752fb5ac5dd2e1a0b7a8c6b08170380 -U drh -Z 1500a43de7f87186b8488707b788a405 +P d163535ec8d463d74112d38a606fa4d900e66deb1a414c947973cd1880e41526 +R 690bd5803e72eefc9593af834d5d854a +U dan +Z fa70e0c9e7cfdd60641dd6afc4b1e883 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index bc0325b4e7..83b0dedec4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d163535ec8d463d74112d38a606fa4d900e66deb1a414c947973cd1880e41526 +23ac2377315af02b73db6ae37bfeeda1453e41efb702a6b707346956c2d41a9d diff --git a/src/select.c b/src/select.c index b9cc333acc..d8873fb065 100644 --- a/src/select.c +++ b/src/select.c @@ -7497,28 +7497,91 @@ static SQLITE_NOINLINE void existsToJoin( } /* -** The xExpr and xSelect callbacks for the search of invalid ON clause terms. +** Type used for Walker callbacks by selectCheckOnClauses(). +*/ +typedef struct CheckOnCtx CheckOnCtx; +struct CheckOnCtx { + SrcList *pSrc; /* SrcList for this context */ + int iJoin; /* Cursor numbers must be =< than this */ + CheckOnCtx *pParent; /* Parent context */ +}; + +/* +** True if the SrcList passed as the only argument contains at least +** one RIGHT or FULL JOIN. False otherwise. +*/ +#define hasRightJoin(pSrc) (((pSrc)->a[0].fg.jointype & JT_LTORJ)!=0) + +/* +** The xExpr callback 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) + CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx; + + /* Check if pExpr is root or near-root of an ON clause constraint that needs + ** to be checked to ensure that it does not refer to tables in its FROM + ** clause to the right of itself. i.e. it is either: + ** + ** + an ON clause on an OUTER join, or + ** + an ON clause on an INNER join within a FROM that features at + ** least one RIGHT or FULL join. + */ + if( (ExprHasProperty(pExpr, EP_OuterON)) + || (ExprHasProperty(pExpr, EP_InnerON) && hasRightJoin(pCtx->pSrc)) ){ - if( pExpr->w.iJoiniTable ){ - if( ExprHasProperty(pExpr, EP_OuterON) || pWalker->eCode ){ - sqlite3ErrorMsg(pWalker->pParse, - "ON clause references tables to its right"); - return WRC_Abort; + /* If CheckOnCtx.iJoin is already set, then fall through and process + ** this expression node as normal. Or, if CheckOnCtx.iJoin is still 0, + ** set it to the cursor number of the RHS of the join to which this + ** ON expression was attached and then iterate through the entire + ** expression. */ + assert( pCtx->iJoin==0 || pCtx->iJoin==pExpr->w.iJoin ); + if( pCtx->iJoin==0 ){ + pCtx->iJoin = pExpr->w.iJoin; + sqlite3WalkExprNN(pWalker, pExpr); + pCtx->iJoin = 0; + return WRC_Prune; + } + } + + if( pExpr->op==TK_COLUMN ){ + /* A column expression. Find the SrcList (if any) to which it refers. + ** Then, if CheckOnCtx.iJoin indicates that this expression is part of an + ** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it + ** does not refer to a table to the right of CheckOnCtx.iJoin. */ + do { + SrcList *pSrc = pCtx->pSrc; + int iTab = pExpr->iTable; + if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){ + if( pCtx->iJoin && iTab>pCtx->iJoin ){ + sqlite3ErrorMsg(pWalker->pParse, + "ON clause references tables to its right"); + return WRC_Abort; + } + break; } - } + pCtx = pCtx->pParent; + }while( pCtx ); } return WRC_Continue; } + +/* +** The xSelect callback for the search of invalid ON clause terms. +*/ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){ - UNUSED_PARAMETER(pWalker); - if( (pSelect->selFlags & SF_OnToWhere)==0 ){ - return WRC_Prune; - }else{ + CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx; + if( pSelect->pSrc==pCtx->pSrc || pSelect->pSrc->nSrc==0 ){ return WRC_Continue; + }else{ + CheckOnCtx sCtx; + memset(&sCtx, 0, sizeof(sCtx)); + sCtx.pSrc = pSelect->pSrc; + sCtx.pParent = pCtx; + pWalker->u.pCheckOnCtx = &sCtx; + sqlite3WalkSelect(pWalker, pSelect); + pWalker->u.pCheckOnCtx = pCtx; + pSelect->selFlags &= ~SF_OnToWhere; + return WRC_Prune; } } @@ -7528,15 +7591,17 @@ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){ */ static void selectCheckOnClauses(Parse *pParse, Select *pSelect){ Walker w; - + CheckOnCtx sCtx; 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); + w.u.pCheckOnCtx = &sCtx; + memset(&sCtx, 0, sizeof(sCtx)); + sCtx.pSrc = pSelect->pSrc; + sqlite3WalkExprNN(&w, pSelect->pWhere); pSelect->selFlags &= ~SF_OnToWhere; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d80ede7c75..f012650088 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4414,6 +4414,7 @@ struct Walker { SrcItem *pSrcItem; /* A single FROM clause item */ DbFixer *pFix; /* See sqlite3FixSelect() */ Mem *aMem; /* See sqlite3BtreeCursorHint() */ + struct CheckOnCtx *pCheckOnCtx; /* See selectCheckOnClauses() */ } u; }; diff --git a/test/joinI.test b/test/joinI.test index a422f19470..96dba7bb8d 100644 --- a/test/joinI.test +++ b/test/joinI.test @@ -93,4 +93,19 @@ do_catchsql_test 3.6 { ) CROSS JOIN t4; } {1 {ON clause references tables to its right}} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE parent1(parent1key, child1key, Child2key, child3key); + CREATE TABLE child1 ( child1key NVARCHAR, value NVARCHAR ); + CREATE TABLE child2 ( child2key NVARCHAR, value NVARCHAR ); +} + +do_execsql_test 4.1 { + SELECT parent1.parent1key, child1.value, child2.value + FROM parent1 + LEFT OUTER JOIN child1 ON child1.child1key = parent1.child1key + INNER JOIN child2 ON child2.child2key = parent1.child2key; +} + finish_test