1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-12-24 14:17:58 +03:00

Fix the cases in joinI.test on this branch.

FossilOrigin-Name: 23ac2377315af02b73db6ae37bfeeda1453e41efb702a6b707346956c2d41a9d
This commit is contained in:
dan
2025-08-23 16:26:36 +00:00
parent d271627f96
commit 4bace197e1
5 changed files with 107 additions and 26 deletions

View File

@@ -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.

View File

@@ -1 +1 @@
d163535ec8d463d74112d38a606fa4d900e66deb1a414c947973cd1880e41526
23ac2377315af02b73db6ae37bfeeda1453e41efb702a6b707346956c2d41a9d

View File

@@ -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.iJoin<pExpr->iTable ){
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;
}

View File

@@ -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;
};

View File

@@ -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