diff options
author | drh <> | 2022-12-08 13:56:06 +0000 |
---|---|---|
committer | drh <> | 2022-12-08 13:56:06 +0000 |
commit | 05cb9d881e3d92b95d021b68a69ceafd83b7a9a7 (patch) | |
tree | fc94a9f8606db6c71b7a0a417690317425827820 /src | |
parent | 619ff3f505fe795d27cb48839f2b14fb6ce16091 (diff) | |
download | sqlite-05cb9d881e3d92b95d021b68a69ceafd83b7a9a7.tar.gz sqlite-05cb9d881e3d92b95d021b68a69ceafd83b7a9a7.zip |
Do not use a co-routine on a subquery that is participating in a self-join.
FossilOrigin-Name: ea4306a03cd8dd706100dac3f11653068a25c50c5d06c34ad08534aec0a580bc
Diffstat (limited to 'src')
-rw-r--r-- | src/select.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/src/select.c b/src/select.c index 8f3e5bb9a..827bfb7cf 100644 --- a/src/select.c +++ b/src/select.c @@ -6697,18 +6697,23 @@ static void havingToWhere(Parse *pParse, Select *p){ } /* -** Check to see if the pThis entry of pTabList is a self-join of a prior view. -** If it is, then return the SrcItem for the prior view. If it is not, -** then return 0. +** Check to see if the pThis entry of pTabList is a self-join of another view. +** Search FROM-clause entries in the range of iFirst..iEnd, including iFirst +** but stopping before iEnd. +** +** If pThis is a self-join, then return the SrcItem for the first other +** instance of that view found. If pThis is not a self-join then return 0. */ static SrcItem *isSelfJoinView( SrcList *pTabList, /* Search for self-joins in this FROM clause */ - SrcItem *pThis /* Search for prior reference to this subquery */ + SrcItem *pThis, /* Search for prior reference to this subquery */ + int iFirst, int iEnd /* Range of FROM-clause entries to search. */ ){ SrcItem *pItem; assert( pThis->pSelect!=0 ); if( pThis->pSelect->selFlags & SF_PushDown ) return 0; - for(pItem = pTabList->a; pItem<pThis; pItem++){ + while( iFirst<iEnd ){ + pItem = &pTabList->a[iFirst++]; Select *pS1; if( pItem->pSelect==0 ) continue; if( pItem->fg.viaCoroutine ) continue; @@ -6873,6 +6878,7 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ ** (2) The subquery is not a CTE that should be materialized ** (3) The subquery is not part of a left operand for a RIGHT JOIN ** (4) The SQLITE_Coroutine optimization disable flag is not set +** (5) The subquery is not self-joined */ static int fromClauseTermCanBeCoroutine( Parse *pParse, /* Parsing context */ @@ -6883,6 +6889,9 @@ static int fromClauseTermCanBeCoroutine( if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ) return 0;/* (2) */ if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */ if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */ + if( isSelfJoinView(pTabList, pItem, i+1, pTabList->nSrc)!=0 ){ + return 0; /* (5) */ + } if( i==0 ){ if( pTabList->nSrc==1 ) return 1; /* (1a-i) */ if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1a-ii) */ @@ -7319,7 +7328,7 @@ int sqlite3Select( VdbeComment((v, "%!S", pItem)); } pSub->nSelectRow = pCteUse->nRowEst; - }else if( (pPrior = isSelfJoinView(pTabList, pItem))!=0 ){ + }else if( (pPrior = isSelfJoinView(pTabList, pItem, 0, i))!=0 ){ /* This view has already been materialized by a prior entry in ** this same FROM clause. Reuse it. */ if( pPrior->addrFillSub ){ |