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:
18
manifest
18
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.
|
||||
|
||||
@@ -1 +1 @@
|
||||
d163535ec8d463d74112d38a606fa4d900e66deb1a414c947973cd1880e41526
|
||||
23ac2377315af02b73db6ae37bfeeda1453e41efb702a6b707346956c2d41a9d
|
||||
|
||||
97
src/select.c
97
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.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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user