Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -88,10 +88,11 @@ Expr *pRowidExpr = 0; /* Expression defining the new record number */ int openAll = 0; /* True if all indices need to be opened */ AuthContext sContext; /* The authorization context */ NameContext sNC; /* The name-context to resolve expressions in */ int iDb; /* Database containing the table being updated */ + int regRowid; /* Memory holding rowid to be updated */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* Trying to update a view */ int triggers_exist = 0; /* True if any row triggers exist */ #endif @@ -304,11 +305,10 @@ */ addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0); if( !isView ){ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); - sqlite3VdbeAddOp(v, OP_Dup, 0, 0); /* Open a cursor and make it point to the record that is ** being updated. */ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); } @@ -393,13 +393,15 @@ ** Also, the old data is needed to delete the old index entires. ** So make the cursor point at the old record. */ if( !triggers_exist ){ addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0); - sqlite3VdbeAddOp(v, OP_Dup, 0, 0); } + regRowid = pParse->nMem++; + sqlite3VdbeAddOp(v, OP_MemStore, regRowid, 0); sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr); + sqlite3VdbeAddOp(v, OP_MemLoad, regRowid, 0); /* If the record number will change, push the record number as it ** will be after the update. (The old record number is currently ** on top of the stack.) */ ADDED test/bb20090903.test Index: test/bb20090903.test ================================================================== --- /dev/null +++ test/bb20090903.test @@ -0,0 +1,116 @@ +# 2009 Sep 03 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +proc moverows {x} { + db eval {UPDATE t1 SET x=x+1000} + return $x +} + +do_test bb20090903-1.0 { + db eval { + CREATE TABLE t1(x INTEGER PRIMARY KEY, y); + INSERT INTO t1 VALUES(1,1); + INSERT INTO t1 VALUES(2,2); + INSERT INTO t1 SELECT x+2, y+2 FROM t1; + INSERT INTO t1 SELECT x+4, y+4 FROM t1; + INSERT INTO t1 SELECT x+8, y+8 FROM t1; + INSERT INTO t1 SELECT x+16, y+16 FROM t1; + INSERT INTO t1 SELECT x+32, y+32 FROM t1; + } + db function moverows moverows + db eval { + UPDATE t1 SET y=moverows(y); + } + db eval { + SELECT * FROM t1; + } +} {1 1 1001 1 1002 2 1003 3 1004 4 1005 5 1006 6 1007 7 1008 8 1009 9 1010 10 1011 11 1012 12 1013 13 1014 14 1015 15 1016 16 1017 17 1018 18 1019 19 1020 20 1021 21 1022 22 1023 23 1024 24 1025 25 1026 26 1027 27 1028 28 1029 29 1030 30 1031 31 1032 32 1033 33 1034 34 1035 35 1036 36 1037 37 1038 38 1039 39 1040 40 1041 41 1042 42 1043 43 1044 44 1045 45 1046 46 1047 47 1048 48 1049 49 1050 50 1051 51 1052 52 1053 53 1054 54 1055 55 1056 56 1057 57 1058 58 1059 59 1060 60 1061 61 1062 62 1063 63 1064 64} + +do_test bb20090903-1.2 { + db eval { + DELETE FROM t1 WHERE x<1000; + UPDATE t1 SET x=x-1000; + SELECT count(*) FROM t1; + SELECT count(*) FROM t1 WHERE x!=y; + } +} {64 0} + +do_test bb20090903-1.3 { + db eval { + CREATE TABLE t2(x INTEGER PRIMARY KEY, y); + INSERT INTO t2 SELECT * FROM t1; + CREATE TRIGGER r2a AFTER UPDATE ON t2 BEGIN + DELETE FROM t2; + END; + UPDATE t2 SET x=x+1000; + SELECT * FROM t2; + } +} {} + +do_test bb20090903-1.4 { + db eval { + INSERT INTO t2 SELECT * FROM t1; + DROP TRIGGER r2a; + CREATE TRIGGER r2a BEFORE UPDATE ON t2 BEGIN + DELETE FROM t2; + END; + UPDATE t2 SET x=x+1000; + SELECT * FROM t2; + } +} {} + +do_test bb20090903-1.5 { + db eval { + INSERT INTO t2 SELECT * FROM t1; + CREATE TABLE t3(x); + DROP TRIGGER r2a; + CREATE TRIGGER r2a AFTER UPDATE ON t2 BEGIN + INSERT INTO t3 VALUES(old.x); + END; + UPDATE t2 SET x=x+1000; + SELECT * FROM t3; + } +} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64} + +do_test bb20090903-1.6 { + db eval { + DELETE FROM t2; + INSERT INTO t2 SELECT * FROM t1; + DROP TRIGGER r2a; + CREATE TRIGGER r2a AFTER UPDATE ON t2 BEGIN + DELETE FROM t2 WHERE x>10 AND x<1000; + END; + UPDATE t2 SET x=x+1000; + SELECT * FROM t2; + } +} {1001 1 1002 2 1003 3 1004 4 1005 5 1006 6 1007 7 1008 8 1009 9 1010 10} + +do_test bb20090903-1.7 { + db eval { + DELETE FROM t2; + INSERT INTO t2 SELECT * FROM t1; + DROP TRIGGER r2a; + CREATE TRIGGER r2a BEFORE UPDATE ON t2 BEGIN + DELETE FROM t2 WHERE x>10 AND x<1000; + END; + UPDATE t2 SET x=x+1000; + SELECT * FROM t2; + } +} {1001 1 1002 2 1003 3 1004 4 1005 5 1006 6 1007 7 1008 8 1009 9 1010 10} + + + +finish_test