]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Ensure that new.* values of an UPDATE do not get clobbered after the
authordrh <drh@noemail.net>
Thu, 26 Apr 2018 15:50:10 +0000 (15:50 +0000)
committerdrh <drh@noemail.net>
Thu, 26 Apr 2018 15:50:10 +0000 (15:50 +0000)
BEFORE triggers run when unmodified columns of the row being updated are
reloaded.  Fix for ticket [d85fffd6ffe856092ed8da]

FossilOrigin-Name: 0a514e62ad1ebe5c12da8daed429ae2f9d9910471d3c5cef3b6870bdadfefca1

manifest
manifest.uuid
src/update.c
src/vdbe.h
src/vdbeaux.c
test/trigger1.test

index 954f369eef16d009ac52cb99bbab73f09354436e..11e53dfe699e2266bf0e36ae7292642eb4c18699 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Clarification\sof\sthe\sbehavior\sof\sa\sBEFORE\sUPDATE\strigger\swhen\sthe\strigger\nchanges\sthe\svalues\sof\ssome\sof\sthe\scolumns\sused\sto\scompute\snew\scolumns\sin\nthe\sUPDATE.
-D 2018-04-26T15:04:18.138
+C Ensure\sthat\snew.*\svalues\sof\san\sUPDATE\sdo\snot\sget\sclobbered\safter\sthe\nBEFORE\striggers\srun\swhen\sunmodified\scolumns\sof\sthe\srow\sbeing\supdated\sare\nreloaded.\s\sFix\sfor\sticket\s[d85fffd6ffe856092ed8da]
+D 2018-04-26T15:50:10.476
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439
@@ -557,16 +557,16 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97
 F src/treeview.c 6cea286ca9af8b126dae9714799265353387244eba0d451c3cc2cd60946cc4c7
 F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995
-F src/update.c 2946cf3c6995f9d5cdccedcc08339d18b8eae72c15f06c011ef3230550c0583b
+F src/update.c 75ac1102d791d999ca918d7b3dced4b3023fb0ed1167a4b11591c5bc3cfbb439
 F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4
 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
 F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5
 F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55
-F src/vdbe.h 574ce9a0d57b026fc93ac379a339b8d391977f335ab4176a7e21ba902e9184bd
+F src/vdbe.h fff31fb658cf1aac5a2fb4d06f8d16589aef38a906e78a1565a78b8c5df7fc0a
 F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110
 F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858
-F src/vdbeaux.c 944bae5207bbce456c466d01dcf2aac3ad49c957325d35c0ba7de882d3e5c25c
+F src/vdbeaux.c b82ca213e6b5461ef773beb76a2cfb720b301372dd4797007eb13ef6cf6f18c4
 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
 F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d
 F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
@@ -1477,7 +1477,7 @@ F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
 F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
 F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
-F test/trigger1.test d7bdbff72c65293dddc8a443c3fd90b957869ac274c5e25ea6acc326f5e3c233
+F test/trigger1.test 254eb5245c472af5fd5a6d8c321f7af97b8532db2eff7a24c31ac67155a12c27
 F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
@@ -1725,7 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 368c14da868a843767344f6cc17c499fddd83244c0510337ed9a918e64ee2413
-R d67c07078741cec11cd337cb536cdcc8
+P 7bb23c2a3d37f0d5e5515b917860818906819d54a0066e1ba8e9792a82f7d279
+R fca770ecccc439d6123031b9ede2b90c
 U drh
-Z aca21fa0a22205b706503004c2920563
+Z 0f59500027b236c3f3feca2847bff4bf
index 1c442962fc9447cee620439d6ca2f5f47fd3516e..83dbc5ed7f3d5a8134e6d7896852cf95ec67c7fa 100644 (file)
@@ -1 +1 @@
-7bb23c2a3d37f0d5e5515b917860818906819d54a0066e1ba8e9792a82f7d279
\ No newline at end of file
+0a514e62ad1ebe5c12da8daed429ae2f9d9910471d3c5cef3b6870bdadfefca1
\ No newline at end of file
index dcab4eeb0b9df476dcfff785eac9bc74b64b155c..d098df820d842df46bb08c2a2c70365eb3883dcc 100644 (file)
@@ -602,6 +602,12 @@ void sqlite3Update(
       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
@@ -639,7 +645,8 @@ void sqlite3Update(
       VdbeCoverage(v);
     }
 
-    /* If it did not delete it, the BEFORE trigger may still have modified 
+    /* After-BEFORE-trigger-reload-loop:
+    ** If it did not delete it, the BEFORE trigger may still have modified 
     ** some of the columns of the row being updated. Load the values for 
     ** all columns not modified by the update statement into their registers
     ** in case this has happened. Only unmodified columns are reloaded.
index 60525a9e9ef13a95ceb7866841cd62c2bdb88641..6dcf2e4dd2e847a4aa17865d55d694d9f78645d7 100644 (file)
@@ -200,6 +200,7 @@ void sqlite3VdbeEndCoroutine(Vdbe*,int);
 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);
index be092b98b7659fbc1f49a33fa29e3b162735eab3..aff08ea3e6ca3f0aecc5d4adcec99ccacea675de 100644 (file)
@@ -843,6 +843,12 @@ void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
   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.
index e785343b3539591676919eb2dd9d0eb8dcb9a084..f3a0e629772ead781894386701665c560c6eac19 100644 (file)
@@ -751,4 +751,15 @@ do_execsql_test trigger1-18.1 {
   SELECT * FROM t18;
 } {1 3 2}     ;# Not: 1 1001 1000
 
+# 2018-04-26 ticket [https://www.sqlite.org/src/tktview/d85fffd6ffe856092e]
+# VDBE Program uses an expired value.
+#
+do_execsql_test trigger1-19.0 {
+  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}
+
 finish_test