diff options
author | drh <> | 2023-03-02 13:49:50 +0000 |
---|---|---|
committer | drh <> | 2023-03-02 13:49:50 +0000 |
commit | 3f23ce664e84366c3e7c7fcf675c480e2d3988af (patch) | |
tree | 733e4e32c1c90f451026185292a439a573476513 /src/expr.c | |
parent | c355f6c839f3df778eae3892a6bdd1b099566930 (diff) | |
download | sqlite-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.c | 20 |
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; } |