aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <>2023-03-02 13:49:50 +0000
committerdrh <>2023-03-02 13:49:50 +0000
commit3f23ce664e84366c3e7c7fcf675c480e2d3988af (patch)
tree733e4e32c1c90f451026185292a439a573476513 /src/expr.c
parentc355f6c839f3df778eae3892a6bdd1b099566930 (diff)
downloadsqlite-3f23ce664e84366c3e7c7fcf675c480e2d3988af.tar.gz
sqlite-3f23ce664e84366c3e7c7fcf675c480e2d3988af.zip
When flattening the right operand of a LEFT JOIN
(check-in [41c27bc0ff1d3135]), ensure that the OP_IfNullRow opcode does not NULL-out a subquery result that was computed within OP_Once. This fixes the problem problem reported by [forum:/forumpost/402f05296d|forum post 402f05296d]. FossilOrigin-Name: 8fe13f7a5e5eb798189acb25a608df7a94c2f5cc83463331a048b779c7890c82
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/src/expr.c b/src/expr.c
index 763e961b6..b688e5b40 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -4833,16 +4833,22 @@ expr_code_doover:
break;
}
}
- addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
- /* Temporarily disable factoring of constant expressions, since
- ** even though expressions may appear to be constant, they are not
- ** really constant because they originate from the right-hand side
- ** of a LEFT JOIN. */
- pParse->okConstFactor = 0;
+ addrINR = sqlite3VdbeAddOp3(v, OP_IfNullRow, pExpr->iTable, 0, target);
+ /* The OP_IfNullRow opcode above can overwrite the result register with
+ ** NULL. So we have to ensure that the result register is not a value
+ ** that is suppose to be a constant. Two defenses are needed:
+ ** (1) Temporarily disable factoring of constant expressions
+ ** (2) Make sure the computed value really is stored in register
+ ** "target" and not someplace else.
+ */
+ pParse->okConstFactor = 0; /* note (1) above */
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
pParse->okConstFactor = okConstFactor;
+ if( inReg!=target ){ /* note (2) above */
+ sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
+ inReg = target;
+ }
sqlite3VdbeJumpHere(v, addrINR);
- sqlite3VdbeChangeP3(v, addrINR, inReg);
break;
}