aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2025-07-09 20:11:49 +0000
committerdrh <>2025-07-09 20:11:49 +0000
commit33c2e37f981af6766a6309f24a54b91fa3fa9080 (patch)
tree74cd8affeb6a15449f6bccbb08bb753aa687ca96 /src
parent8663a78ec9f6c85db6224007a49c264359e908ce (diff)
downloadsqlite-33c2e37f981af6766a6309f24a54b91fa3fa9080.tar.gz
sqlite-33c2e37f981af6766a6309f24a54b91fa3fa9080.zip
Fix the empty-table optimization on INTERSECT so that it does not try to
use an uninitialized register for LIMIT processing. FossilOrigin-Name: 6918ada008507b4564ca0dc5f4f6818c49a42eb14a16285b2074e21dcc8f2c3f
Diffstat (limited to 'src')
-rw-r--r--src/select.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/src/select.c b/src/select.c
index 99b05c76a..1b1266313 100644
--- a/src/select.c
+++ b/src/select.c
@@ -3130,7 +3130,7 @@ static int multiSelect(
int tab1, tab2;
int iCont, iBreak, iStart;
Expr *pLimit;
- int addr;
+ int addr, iLimit, iOffset;
SelectDest intersectdest;
int r1;
int emptyBypass;
@@ -3157,6 +3157,11 @@ static int multiSelect(
if( rc ){
goto multi_select_end;
}
+
+ /* Initialize LIMIT counters before checking to see if the LHS
+ ** is empty, in case the jump is taken */
+ iBreak = sqlite3VdbeMakeLabel(pParse);
+ computeLimitRegisters(pParse, p, iBreak);
emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v);
/* Code the current SELECT into temporary table "tab2"
@@ -3164,9 +3169,17 @@ static int multiSelect(
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
assert( p->addrOpenEphm[1] == -1 );
p->addrOpenEphm[1] = addr;
- p->pPrior = 0;
+
+ /* Disable prior SELECTs and the LIMIT counters during the computation
+ ** of the RHS select */
pLimit = p->pLimit;
+ iLimit = p->iLimit;
+ iOffset = p->iOffset;
+ p->pPrior = 0;
p->pLimit = 0;
+ p->iLimit = 0;
+ p->iOffset = 0;
+
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
@@ -3179,19 +3192,21 @@ static int multiSelect(
p->nSelectRow = pPrior->nSelectRow;
}
sqlite3ExprDelete(db, p->pLimit);
+
+ /* Reinstate the LIMIT counters prior to running the final intersect */
p->pLimit = pLimit;
+ p->iLimit = iLimit;
+ p->iOffset = iOffset;
/* Generate code to take the intersection of the two temporary
** tables.
*/
if( rc ) break;
assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(pParse);
- iCont = sqlite3VdbeMakeLabel(pParse);
- computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp1(v, OP_Rewind, tab1);
r1 = sqlite3GetTempReg(pParse);
iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
+ iCont = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r1);