diff --git a/manifest b/manifest index 84fd6272be..503a340c38 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Update\sthe\sREADME\sfile\sto\sstate\sthat\sTCL\sis\srequired\sin\sorder\sto\srun\nthe\smakefiles\sfor\sSQLite.\s\sTicket\s[7d96113ff]. -D 2009-09-09T14:48:21 +C Add\ssome\stests\sthat\sinvolve\sBEFORE\sUPDATE\sor\sBEFORE\sDELETE\striggers\smessing\swith\sthe\srow\sbeing\supdated\sor\sdeleted.\sSQLite\sbehaviour\sin\sthis\sscenario\sis\sundefined,\sso\sthe\stests\sjust\scheck\sthat\sthe\sbehaviour\sis\srelatively\ssane\sand\sthere\sare\sno\scrashes. +D 2009-09-09T15:06:11 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 73ddeec9dd10b85876c5c2ce1fdce627e1dcc7f8 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -204,11 +201,11 @@ F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241 F src/tokenize.c af8a56e6a50c5042fc305bfa796275e9bf26ff2b F src/trigger.c 054c08339b3471c785f1cf041ed878a425850e33 -F src/update.c 7a2c0dad3badd60320ff12bb42ca1446c1f7da28 +F src/update.c e5f9f75aad9fd5c11a3f95a10e865df9a3fa9015 F src/utf.c 99cf927eabb104621ba889ac0dd075fc1657ad30 F src/util.c 59d4e9456bf1fe581f415a783fa0cee6115c8f35 F src/vacuum.c 3fe0eebea6d2311c1c2ab2962887d11f7a4dcfb0 -F src/vdbe.c aba680ec9cf68890f3600a4c0c1936b1d789d111 +F src/vdbe.c 3c094e85665fee59a3329c2ed1d2af1156d97dda F src/vdbe.h 13e00f573bccf0c03e95fd3d4759da4ea9b75e60 F src/vdbeInt.h 004dbb28a9195b6c85fe3255c7cc300ffd8b9453 F src/vdbeapi.c b7e5f34436e298e2b0168e71323b5d97f7e9b080 @@ -685,7 +682,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4 F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31 F test/triggerA.test 0718ad2d9bfef27c7af00e636df79bee6b988da7 F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe -F test/triggerC.test 427f3036f0d1a8e65db99d3e98b9c34edf559104 +F test/triggerC.test 1ee7e3a78aec7b58eb040d0ae0a320e5bab35262 F test/types.test 9a825ec8eea4e965d7113b74c76a78bb5240f2ac F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84 F test/types3.test a0f66bf12f80fad89493535474f7a6d16fa58150 @@ -753,14 +750,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P f509eb8b488bb39deda4ca88f66ed40c6784af02 -R da67957663dcbc2d53dc5652878fe664 -U drh -Z 777a74b9b9e0c4f6449961c8e129d00f ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFKp8A5oxKgR168RlERAjt/AJ4gMrGikRwbSEyhUqLgxBxmA/wIJQCeKkVo -Dy4rR7nKZ1aig9GbafKkLeA= -=Bx64 ------END PGP SIGNATURE----- +P ba20091ae8146d276414f97527bf63e50fac8691 +R 4a5962d8497c5cdcdace65d61bc8bd95 +U dan +Z 53c9ac18a32dd76d72b70838d180fa3b diff --git a/manifest.uuid b/manifest.uuid index 1bfb807d43..c12c16ec60 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ba20091ae8146d276414f97527bf63e50fac8691 \ No newline at end of file +9a4c59a2ddd0df2d9425097004b450a6685f2147 \ No newline at end of file diff --git a/src/update.c b/src/update.c index b0df33399d..f0880de407 100644 --- a/src/update.c +++ b/src/update.c @@ -428,6 +428,13 @@ void sqlite3Update( sqlite3TableAffinityStr(v, pTab); sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, -1, regOldRowid, onError, addr); + + /* The row-trigger may have deleted the row being updated. In this + ** case, jump to the next row. No updates or AFTER triggers are + ** required. This behaviour - what happens when the row being updated + ** is deleted or renamed by a BEFORE trigger - is left undefined in the + ** documentation. */ + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); } if( !isView ){ diff --git a/src/vdbe.c b/src/vdbe.c index 823b5f6f8c..26f476cbe9 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4729,9 +4729,9 @@ case OP_Program: { /* jump */ pRt = &p->aMem[pOp->p3]; assert( pProgram->nOp>0 ); - /* If the SQLITE_NoRecTriggers flag it set, then recursive invocation of + /* If the SQLITE_RecTriggers flag is clear, then recursive invocation of ** triggers is disabled for backwards compatibility (flag set/cleared by - ** the "PRAGMA disable_recursive_triggers" command). + ** the "PRAGMA recursive_triggers" command). ** ** It is recursive invocation of triggers, at the SQL level, that is ** disabled. In some cases a single trigger may generate more than one diff --git a/test/triggerC.test b/test/triggerC.test index 2df9e135e8..807a50afd7 100644 --- a/test/triggerC.test +++ b/test/triggerC.test @@ -667,7 +667,99 @@ do_test triggerC-6.3 { # Test some of the "undefined behaviour" associated with triggers. The # undefined behaviour occurs when a row being updated or deleted is # manipulated by a BEFORE trigger. -# +# +do_test triggerC-7.1 { + execsql { + CREATE TABLE t8(x); + CREATE TABLE t7(a, b); + INSERT INTO t7 VALUES(1, 2); + INSERT INTO t7 VALUES(3, 4); + INSERT INTO t7 VALUES(5, 6); + CREATE TRIGGER t7t BEFORE UPDATE ON t7 BEGIN + DELETE FROM t7 WHERE a = 1; + END; + CREATE TRIGGER t7ta AFTER UPDATE ON t7 BEGIN + INSERT INTO t8 VALUES('after fired ' || old.rowid || '->' || new.rowid); + END; + } +} {} +do_test triggerC-7.2 { + execsql { + BEGIN; + UPDATE t7 SET b=7 WHERE a = 5; + SELECT * FROM t7; + SELECT * FROM t8; + ROLLBACK; + } +} {3 4 5 7 {after fired 3->3}} +do_test triggerC-7.3 { + execsql { + BEGIN; + UPDATE t7 SET b=7 WHERE a = 1; + SELECT * FROM t7; + SELECT * FROM t8; + ROLLBACK; + } +} {3 4 5 6} + +do_test triggerC-7.4 { + execsql { + DROP TRIGGER t7t; + CREATE TRIGGER t7t BEFORE UPDATE ON t7 WHEN (old.rowid!=1 OR new.rowid!=8) + BEGIN + UPDATE t7 set rowid = 8 WHERE rowid=1; + END; + } +} {} +do_test triggerC-7.5 { + execsql { + BEGIN; + UPDATE t7 SET b=7 WHERE a = 5; + SELECT rowid, * FROM t7; + SELECT * FROM t8; + ROLLBACK; + } +} {2 3 4 3 5 7 8 1 2 {after fired 1->8} {after fired 3->3}} +do_test triggerC-7.6 { + execsql { + BEGIN; + UPDATE t7 SET b=7 WHERE a = 1; + SELECT rowid, * FROM t7; + SELECT * FROM t8; + ROLLBACK; + } +} {2 3 4 3 5 6 8 1 2 {after fired 1->8}} + +do_test triggerC-7.7 { + execsql { + DROP TRIGGER t7t; + DROP TRIGGER t7ta; + CREATE TRIGGER t7t BEFORE DELETE ON t7 BEGIN + UPDATE t7 set rowid = 8 WHERE rowid=1; + END; + CREATE TRIGGER t7ta AFTER DELETE ON t7 BEGIN + INSERT INTO t8 VALUES('after fired ' || old.rowid); + END; + } +} {} +do_test triggerC-7.8 { + execsql { + BEGIN; + DELETE FROM t7 WHERE a = 3; + SELECT rowid, * FROM t7; + SELECT * FROM t8; + ROLLBACK; + } +} {3 5 6 8 1 2 {after fired 2}} +do_test triggerC-7.9 { + execsql { + BEGIN; + DELETE FROM t7 WHERE a = 1; + SELECT rowid, * FROM t7; + SELECT * FROM t8; + ROLLBACK; + } +} {2 3 4 3 5 6 8 1 2} finish_test