From: dan Date: Wed, 9 Sep 2009 15:06:10 +0000 (+0000) Subject: Add some tests that involve BEFORE UPDATE or BEFORE DELETE triggers messing with... X-Git-Tag: fts3-refactor~200 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ae0931edae1cafdf3d0890aca09613fcb8c869ca;p=thirdparty%2Fsqlite.git Add some tests that involve BEFORE UPDATE or BEFORE DELETE triggers messing with the row being updated or deleted. SQLite behaviour in this scenario is undefined, so the tests just check that the behaviour is relatively sane and there are no crashes. FossilOrigin-Name: 9a4c59a2ddd0df2d9425097004b450a6685f2147 --- 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