Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -600,25 +600,25 @@ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); }else{ j = aXRef[i]; if( j>=0 ){ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); - if( tmask&TRIGGER_BEFORE ){ - /* Must preserve copied values even in case the original is - ** reloaded in the After-BEFORE-trigger-reload-loop below. - ** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28 */ - sqlite3VdbeSwapOpcode(v, -1, OP_SCopy, OP_Copy); - } }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){ /* This branch loads the value of a column that will not be changed ** into a register. This is done if there are no BEFORE triggers, or ** if there are one or more BEFORE triggers that use this value via ** a new.* reference in a trigger program. */ testcase( i==31 ); testcase( i==32 ); sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); + if( tmask & TRIGGER_BEFORE ){ + /* This value will be recomputed in After-BEFORE-trigger-reload-loop + ** below, so make sure that it is not cached and reused. + ** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */ + sqlite3ExprCacheRemove(pParse, regNew+i, 1); + } }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); } } } Index: src/vdbe.h ================================================================== --- src/vdbe.h +++ src/vdbe.h @@ -198,11 +198,10 @@ # define sqlite3VdbeVerifyNoResultRow(A) #endif VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); -void sqlite3VdbeSwapOpcode(Vdbe*, u32 addr, u8, u8); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); void sqlite3VdbeChangeP5(Vdbe*, u16 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -841,16 +841,10 @@ void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ assert( p->nOp>0 || p->db->mallocFailed ); if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; } -/* Change the opcode to iNew if it was previously iOld */ -void sqlite3VdbeSwapOpcode(Vdbe *p, u32 addr, u8 iOld, u8 iNew){ - VdbeOp *pOp = sqlite3VdbeGetOp(p,addr); - if( pOp->opcode==iOld ) pOp->opcode = iNew; -} - /* ** Change the P2 operand of instruction addr so that it points to ** the address of the next instruction to be coded. */ void sqlite3VdbeJumpHere(Vdbe *p, int addr){ Index: test/trigger1.test ================================================================== --- test/trigger1.test +++ test/trigger1.test @@ -758,8 +758,14 @@ CREATE TABLE t19(a INT PRIMARY KEY, b, c)WITHOUT ROWID; INSERT INTO t19(a,b,c) VALUES(1,2,3); CREATE TRIGGER t19r3 BEFORE UPDATE ON t19 BEGIN SELECT new.b; END; UPDATE t19 SET c=b WHERE a=1; SELECT * FROM t19; +} {1 2 2} +do_execsql_test trigger1-19.1 { + DELETE FROM t19; + INSERT INTO t19(a,b,c) VALUES(1,2,3); + UPDATE t19 SET c=CASE WHEN b=2 THEN b ELSE b+99 END WHERE a=1; + SELECT * FROM t19; } {1 2 2} finish_test