diff options
author | drh <drh@noemail.net> | 2003-05-17 19:04:03 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2003-05-17 19:04:03 +0000 |
commit | 79a519c04743df1e04df149f357dc417d18fea3c (patch) | |
tree | 329bac8c02a4b1b431f18da02bf8ec0279e01850 | |
parent | 24f1eb74c860d60782a9149a23f8f6b295b61b87 (diff) | |
download | sqlite-79a519c04743df1e04df149f357dc417d18fea3c.tar.gz sqlite-79a519c04743df1e04df149f357dc417d18fea3c.zip |
Prevent an infinite loop when deleting a table that has a TEMP trigger. (CVS 984)
FossilOrigin-Name: c8c823b068916711857fa67db10fb479999b55c2
-rw-r--r-- | manifest | 20 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/build.c | 8 | ||||
-rw-r--r-- | src/parse.y | 4 | ||||
-rw-r--r-- | src/sqliteInt.h | 6 | ||||
-rw-r--r-- | src/trigger.c | 42 | ||||
-rw-r--r-- | test/trigger1.test | 43 |
7 files changed, 90 insertions, 35 deletions
@@ -1,5 +1,5 @@ -C Version\s2.8.2\s(CVS\s983) -D 2003-05-17T17:52:34 +C Prevent\san\sinfinite\sloop\swhen\sdeleting\sa\stable\sthat\shas\sa\sTEMP\strigger.\s(CVS\s984) +D 2003-05-17T19:04:04 F Makefile.in 1ff85c27d4350c74118341024e8a4fb2a04a3a43 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -24,7 +24,7 @@ F src/auth.c c8f50d4507e37779d96ff3c55417bc2b612dfed6 F src/btree.c 8092dca45dcdb69c61273db0213cbb85760673c7 F src/btree.h 23c50e00709de16a5dce1fcea9c0429cc955ff0e F src/btree_rb.c 1d809e703aab8bef916ebb0b6ba9254a1c36d9a6 -F src/build.c 95dfb188f448e6299108396546a8333ecdcb1716 +F src/build.c 3f5d1798e40020e3a038dbe058406f665b4a51a4 F src/copy.c 5e5d558d283536592cd67b5dc1519c3152bd7e20 F src/delete.c 0f81e6799c089487615d38e042a2de4d2d6192bc F src/encode.c ed720e54ec4ef4d4de651592f1dd1c74d422bbd2 @@ -39,7 +39,7 @@ F src/os.c 94b618c0c0a76210e53857d77c96d2f042dc33b1 F src/os.h 9e5bbddff123187295e3d00d49af06192cd1cd49 F src/pager.c 51fdfda63e2d8c01fff8f7fe0c49f2636d5b1321 F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31 -F src/parse.y 39b5240cb78047dc56d6d37c398baed7ba556779 +F src/parse.y 917250e5d86bdee752355e6617ea2e8ee12438bf F src/pragma.c ec64704e61286948f39157617f1ce2f506dd1b74 F src/printf.c fc5fdef6e92ad205005263661fe9716f55a49f3e F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe @@ -47,7 +47,7 @@ F src/select.c 15d921308065c9320363af6f43c01d9f09ea7118 F src/shell.c 2565cb32cd862024bcfd88400e05437636cf21a1 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in eec06462cba262c0ee03f38462a18a4bc66dda4e -F src/sqliteInt.h cab919e43875a561603ca6e0d060fd0690c2ee7c +F src/sqliteInt.h 3ba355793a1e0b891cfa414901759189c9287a18 F src/table.c 4301926464d88d2c2c7cd21c3360aa75bf068b95 F src/tclsqlite.c 9e25f98f1765afa0716144ef57abda75c88f688d F src/test1.c 4596acd9d9f2a49fda0160a8a6dee5bfc7c6c325 @@ -55,7 +55,7 @@ F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700 F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5 F src/threadtest.c d641a5219e718e18a1a80a50eb9bb549f451f42e F src/tokenize.c 2ba93fe10d5f57f0cc20b07417c3244a30c324b3 -F src/trigger.c 8ee811986080de60d9d883ad96daffea82014f27 +F src/trigger.c 7607b209e6de07371e94f3266a850562f522297e F src/update.c 8e657c7b3d27b5592d8caa362d9c4765e0b3cd6a F src/util.c 8065b78806a5132119452d9e0417cf071e6f02f9 F src/vacuum.c 0820984615786c9ccdaad8032a792309b354a8eb @@ -119,7 +119,7 @@ F test/tclsqlite.test d9bdfc0afca9ee605c50ecb39e94ae4dea8c222b F test/temptable.test c82bd6f800f10e8cf96921af6315e5f1c21e2692 F test/tester.tcl d7a5835edaf118539241145d8188f0822b673488 F test/trans.test 75e7a171b5d2d94ee56766459113e2ad0e5f809d -F test/trigger1.test 61ef41666f066ac417730dc26056053a7c36cd11 +F test/trigger1.test 589fb8f3015613b1158736e9a29771efbbe989dd F test/trigger2.test 00ceb8aff6bddd511bbac7c837af2863fa0c9cb4 F test/trigger3.test 870afef7997a5b86bf3ea893ce0c2e85d6356c72 F test/trigger4.test 9a5c1406344d743020c2753ae8d6dfe6eb75f818 @@ -165,7 +165,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be F www/sqlite.tcl 4bd1729e320f5fa9125f0022b281fbe839192125 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P e134459d653b03bfacb98eec2c5d91eef7e4ed24 -R 9ef2fffc5f0c5816e46decff70d83cb0 +P f542e5fc8896111e5165cc625607f95e4993bb16 +R fa932d99cd2f240b0dbcaa691638c769 U drh -Z 035b9ad097ef44ba8b7f0d2886016b52 +Z c96cb30883171b8cc67337276b3d728f diff --git a/manifest.uuid b/manifest.uuid index 83f434f0c..b058f6b57 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f542e5fc8896111e5165cc625607f95e4993bb16
\ No newline at end of file +c8c823b068916711857fa67db10fb479999b55c2
\ No newline at end of file diff --git a/src/build.c b/src/build.c index b160a32ee..100b701c8 100644 --- a/src/build.c +++ b/src/build.c @@ -23,7 +23,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.153 2003/05/17 17:35:11 drh Exp $ +** $Id: build.c,v 1.154 2003/05/17 19:04:04 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -1297,12 +1297,8 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){ /* Drop all triggers associated with the table being dropped */ pTrigger = pTable->pTrigger; while( pTrigger ){ - SrcList *pNm; assert( pTrigger->iDb==pTable->iDb || pTrigger->iDb==1 ); - pNm = sqliteSrcListAppend(0, 0, 0); - pNm->a[0].zName = sqliteStrDup(pTrigger->name); - pNm->a[0].zDatabase = sqliteStrDup(db->aDb[pTable->iDb].zName); - sqliteDropTrigger(pParse, pNm, 1); + sqliteDropTriggerPtr(pParse, pTrigger, 1); if( pParse->explain ){ pTrigger = pTrigger->pNext; }else{ diff --git a/src/parse.y b/src/parse.y index 8c183ce8c..f3b979516 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.97 2003/04/29 17:19:18 drh Exp $ +** @(#) $Id: parse.y,v 1.98 2003/05/17 19:04:04 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -848,7 +848,7 @@ expr(A) ::= RAISE(X) LP FAIL COMMA nm(Z) RP(Y). { //////////////////////// DROP TRIGGER statement ////////////////////////////// cmd ::= DROP TRIGGER nm(X) dbnm(D). { - sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D),0); + sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D)); } //////////////////////// ATTACH DATABASE file AS name ///////////////////////// diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 93b4dcc28..699facf80 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.185 2003/05/17 17:35:12 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.186 2003/05/17 19:04:04 drh Exp $ */ #include "config.h" #include "sqlite.h" @@ -893,6 +893,7 @@ struct Trigger { char *name; /* The name of the trigger */ char *table; /* The table or view to which the trigger applies */ u8 iDb; /* Database containing this trigger */ + u8 iTabDb; /* Database containing Trigger.table */ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */ u8 tr_tm; /* One of TK_BEFORE, TK_AFTER */ Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */ @@ -1135,7 +1136,8 @@ int sqliteSafetyCheck(sqlite*); void sqliteChangeCookie(sqlite*, Vdbe*); void sqliteBeginTrigger(Parse*, Token*,int,int,IdList*,SrcList*,int,Expr*,int); void sqliteFinishTrigger(Parse*, TriggerStep*, Token*); -void sqliteDropTrigger(Parse*, SrcList*, int); +void sqliteDropTrigger(Parse*, SrcList*); +void sqliteDropTriggerPtr(Parse*, Trigger*, int); int sqliteTriggersExist(Parse* , Trigger* , int , int , int, ExprList*); int sqliteCodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, int, int); diff --git a/src/trigger.c b/src/trigger.c index 227e47153..6ac45fc23 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -127,6 +127,7 @@ void sqliteBeginTrigger( nt->table = sqliteStrDup(pTableName->a[0].zName); if( sqlite_malloc_failed ) goto trigger_cleanup; nt->iDb = iDb; + nt->iTabDb = tab->iDb; nt->op = op; nt->tr_tm = tr_tm; nt->pWhen = sqliteExprDup(pWhen); @@ -184,7 +185,7 @@ void sqliteFinishTrigger( v = sqliteGetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqliteBeginWriteOperation(pParse, 0, 0); - sqliteOpenMasterTable(v, nt->iDb==1); + sqliteOpenMasterTable(v, nt->iDb); addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqliteVdbeChangeP3(v, addr+2, nt->name, 0); sqliteVdbeChangeP3(v, addr+3, nt->table, 0); @@ -359,18 +360,18 @@ void sqliteDeleteTrigger(Trigger *pTrigger){ /* * This function is called to drop a trigger from the database schema. * - * This may be called directly from the parser, or from within - * sqliteDropTable(). In the latter case the "nested" argument is true. + * This may be called directly from the parser and therefore identifies + * the trigger by name. The sqliteDropTriggerPtr() routine does the + * same job as this routine except it take a spointer to the trigger + * instead of the trigger name. * * Note that this function does not delete the trigger entirely. Instead it * removes it from the internal schema and places it in the trigDrop hash * table. This is so that the trigger can be restored into the database schema * if the transaction is rolled back. */ -void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){ +void sqliteDropTrigger(Parse *pParse, SrcList *pName){ Trigger *pTrigger; - Table *pTable; - Vdbe *v; int i; const char *zDb; const char *zName; @@ -392,13 +393,29 @@ void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){ sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0); goto drop_trigger_cleanup; } + sqliteDropTriggerPtr(pParse, pTrigger, 0); + +drop_trigger_cleanup: + sqliteSrcListDelete(pName); +} + +/* +** Drop a trigger given a pointer to that trigger. If nested is false, +** then also generate code to remove the trigger from the SQLITE_MASTER +** table. +*/ +void sqliteDropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){ + Table *pTable; + Vdbe *v; + sqlite *db = pParse->db; + assert( pTrigger->iDb<db->nDb ); if( pTrigger->iDb>=2 ){ sqliteErrorMsg(pParse, "triggers may not be removed from " "auxiliary database %s", db->aDb[pTrigger->iDb].zName); - goto drop_trigger_cleanup; + return; } - pTable = sqliteFindTable(db, pTrigger->table, db->aDb[pTrigger->iDb].zName); + pTable = sqliteFindTable(db, pTrigger->table,db->aDb[pTrigger->iTabDb].zName); assert(pTable); assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION @@ -409,7 +426,7 @@ void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){ if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER; if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ - goto drop_trigger_cleanup; + return; } } #endif @@ -432,7 +449,7 @@ void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){ sqliteBeginWriteOperation(pParse, 0, 0); sqliteOpenMasterTable(v, pTrigger->iDb); base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); - sqliteVdbeChangeP3(v, base+1, zName, 0); + sqliteVdbeChangeP3(v, base+1, pTrigger->name, 0); if( pTrigger->iDb==0 ){ sqliteChangeCookie(db, v); } @@ -444,6 +461,8 @@ void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){ * If this is not an "explain", then delete the trigger structure. */ if( !pParse->explain ){ + const char *zName = pTrigger->name; + int nName = strlen(zName); if( pTable->pTrigger == pTrigger ){ pTable->pTrigger = pTrigger->pNext; }else{ @@ -460,9 +479,6 @@ void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){ sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0); sqliteDeleteTrigger(pTrigger); } - -drop_trigger_cleanup: - sqliteSrcListDelete(pName); } /* diff --git a/test/trigger1.test b/test/trigger1.test index bad2f92df..cbcb90c87 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -30,13 +30,20 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -do_test trigger1-1.1 { +do_test trigger1-1.1.2 { catchsql { CREATE TRIGGER trig UPDATE ON no_such_table BEGIN SELECT * from sqlite_master; END; } } {1 {no such table: no_such_table}} +do_test trigger1-1.1.2 { + catchsql { + CREATE TEMP TRIGGER trig UPDATE ON no_such_table BEGIN + SELECT * from sqlite_master; + END; + } +} {1 {no such table: no_such_table}} execsql { CREATE TABLE t1(a); @@ -267,4 +274,38 @@ do_test trigger-3.9 { } } {1 2 3 4 5 6 3 4} +do_test trigger-4.1 { + execsql { + CREATE TEMP TRIGGER r1 BEFORE INSERT ON t1 BEGIN + INSERT INTO t2 VALUES(NEW.a,NEW.b); + END; + INSERT INTO t1 VALUES(7,8); + SELECT * FROM t2; + } +} {3 4 7 8} +do_test trigger-4.2 { + sqlite db2 test.db + execsql { + INSERT INTO t1 VALUES(9,10); + } db2; + db2 close + execsql { + SELECT * FROM t2; + } +} {3 4 7 8} +do_test trigger-4.3 { + execsql { + DROP TABLE t1; + SELECT * FROM t2; + }; +} {3 4 7 8} +do_test trigger-4.4 { + db close + sqlite db test.db + execsql { + SELECT * FROM t2; + }; +} {3 4 7 8} + + finish_test |