aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2022-04-11 17:27:38 +0000
committerdrh <>2022-04-11 17:27:38 +0000
commit6134b2dff2d5df510210880f935bbd2b0a08f93c (patch)
tree9872e7deb3017e5b1c637fb916e99d815cb01932 /src
parentff02ac7f078bbe25c3940ffa35458f0807055fa3 (diff)
downloadsqlite-6134b2dff2d5df510210880f935bbd2b0a08f93c.tar.gz
sqlite-6134b2dff2d5df510210880f935bbd2b0a08f93c.zip
Fix handling of "continue" and "break" from inside the loop for the right
operand of a RIGHT JOIN. FossilOrigin-Name: b6e773a26c2c6ee76ea61acb059b4e676d07ea62f6db9c513638f8986557cf04
Diffstat (limited to 'src')
-rw-r--r--src/vdbe.c10
-rw-r--r--src/where.c11
-rw-r--r--src/whereInt.h1
3 files changed, 16 insertions, 6 deletions
diff --git a/src/vdbe.c b/src/vdbe.c
index 18286c297..45a47756e 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -993,8 +993,12 @@ jump_to_p2:
/* Opcode: Return P1 P2 P3 * *
**
-** Jump to the next instruction after the address in register P1. After
-** the jump, register P1 becomes undefined.
+** Jump to the next instruction after the address stored in register P1.
+**
+** It used to be that after the jump, register P1 would become undefined.
+** However, for the subroutine used for the inner loop of a RIGHT JOIN,
+** it is useful for R1 register to be unchanged, so that is what happens
+** now.
**
** P2 is not used by the byte-code engine. However, if P2 is positive
** and also less than the current address, then the "EXPLAIN" output
@@ -1012,7 +1016,7 @@ case OP_Return: { /* in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags==MEM_Int );
pOp = &aOp[pIn1->u.i];
- pIn1->flags = MEM_Undefined;
+ /* pIn1->flags = MEM_Undefined; */
break;
}
diff --git a/src/where.c b/src/where.c
index 3677759ce..defbc860f 100644
--- a/src/where.c
+++ b/src/where.c
@@ -5880,6 +5880,7 @@ WhereInfo *sqlite3WhereBegin(
pRJ->regBloom = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
pRJ->regReturn = ++pParse->nMem;
+ pRJ->addrInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, pRJ->regReturn);
assert( pTab==pTabItem->pTab );
if( HasRowid(pTab) ){
KeyInfo *pInfo;
@@ -6013,7 +6014,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Terminate the subroutine that forms the interior of the loop of
** the RIGHT JOIN table */
WhereRightJoin *pRJ = pLevel->pRJ;
- sqlite3VdbeChangeP1(v, pRJ->addrSubrtn-1, sqlite3VdbeCurrentAddr(v));
+ int addrHere = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeChangeP1(v, pRJ->addrSubrtn-1, addrHere);
+ sqlite3VdbeChangeP1(v, pRJ->addrInit, addrHere);
+ sqlite3VdbeResolveLabel(v, pLevel->addrCont);
+ pLevel->addrCont = 0;
sqlite3VdbeAddOp2(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn);
}
pLoop = pLevel->pWLoop;
@@ -6043,7 +6048,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
/* The common case: Advance to the next row */
- sqlite3VdbeResolveLabel(v, pLevel->addrCont);
+ if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont);
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
sqlite3VdbeChangeP5(v, pLevel->p5);
VdbeCoverage(v);
@@ -6058,7 +6063,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
#endif
- }else{
+ }else if( pLevel->addrCont ){
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
diff --git a/src/whereInt.h b/src/whereInt.h
index 7b5be3011..6be8234e2 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -52,6 +52,7 @@ struct WhereRightJoin {
int regBloom; /* Bloom filter for iRJMatch */
int regReturn; /* Return register for the interior subroutine */
int addrSubrtn; /* Starting address for the interior subroutine */
+ int addrInit; /* OP_Integer used for early init of regReturn */
};
/*