diff options
author | drh <> | 2024-04-18 16:11:01 +0000 |
---|---|---|
committer | drh <> | 2024-04-18 16:11:01 +0000 |
commit | 0526db32e2657b2b16fa3333e5b8c6e24754eaf2 (patch) | |
tree | ca76dd3163ef69ff01ebc69fdcfdf5ea5e162f9a /src | |
parent | 06915d014545ebf1b00163351e76fbaa6a3ba7b8 (diff) | |
download | sqlite-0526db32e2657b2b16fa3333e5b8c6e24754eaf2.tar.gz sqlite-0526db32e2657b2b16fa3333e5b8c6e24754eaf2.zip |
Correct handling of OUTER JOIN when on or the other operand is a subquery
implemented using the VALUES-as-coroutine optimization.
dbsqlfuzz bde3bf80aedf25afa56e2997a0545a314765d3f8.
FossilOrigin-Name: 8c0f69e0e4ae0a446838cc193bfd4395fd251f3c7659b35ac388e5a0a7650a66
Diffstat (limited to 'src')
-rw-r--r-- | src/vdbe.c | 6 | ||||
-rw-r--r-- | src/where.c | 13 | ||||
-rw-r--r-- | src/wherecode.c | 18 |
3 files changed, 29 insertions, 8 deletions
diff --git a/src/vdbe.c b/src/vdbe.c index ed1d277b2..143fd49c1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1152,7 +1152,9 @@ jump_to_p2: ** ** The instruction at the address in register P1 is a Yield. ** Jump to the P2 parameter of that Yield. -** After the jump, register P1 becomes undefined. +** After the jump, the value register P1 is left with a value +** such that subsequent OP_Yields go back to the this same +** OP_EndCoroutine instruction. ** ** See also: InitCoroutine */ @@ -1164,8 +1166,8 @@ case OP_EndCoroutine: { /* in1 */ pCaller = &aOp[pIn1->u.i]; assert( pCaller->opcode==OP_Yield ); assert( pCaller->p2>=0 && pCaller->p2<p->nOp ); + pIn1->u.i = (int)(pOp - p->aOp) - 1; pOp = &aOp[pCaller->p2 - 1]; - pIn1->flags = MEM_Undefined; break; } diff --git a/src/where.c b/src/where.c index 65b6ae2c9..93984347b 100644 --- a/src/where.c +++ b/src/where.c @@ -6940,8 +6940,17 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); if( (ws & WHERE_IDX_ONLY)==0 ){ - assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); - sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); + SrcItem *pSrc = &pTabList->a[pLevel->iFrom]; + assert( pLevel->iTabCur==pSrc->iCursor ); + if( pSrc->fg.viaCoroutine ){ + int m, n; + n = pSrc->regResult; + assert( pSrc->pTab!=0 ); + m = pSrc->pTab->nCol; + sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1); + }else{ + sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); + } } if( (ws & WHERE_INDEXED) || ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx) diff --git a/src/wherecode.c b/src/wherecode.c index 1f9c84f00..e91bc283b 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -2730,11 +2730,21 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( pRJ->regReturn); for(k=0; k<iLevel; k++){ int iIdxCur; + SrcItem *pRight; + assert( pWInfo->a[k].pWLoop->iTab == pWInfo->a[k].iFrom ); + pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom]; mAll |= pWInfo->a[k].pWLoop->maskSelf; - sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur); - iIdxCur = pWInfo->a[k].iIdxCur; - if( iIdxCur ){ - sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); + if( pRight->fg.viaCoroutine ){ + sqlite3VdbeAddOp3( + v, OP_Null, 0, pRight->regResult, + pRight->regResult + pRight->pSelect->pEList->nExpr-1 + ); + }else{ + sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur); + iIdxCur = pWInfo->a[k].iIdxCur; + if( iIdxCur ){ + sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); + } } } if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){ |