From d702fccbce3d1b2441d53dab726140871dee20a6 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Sun, 26 May 2002 23:24:40 +0000 Subject: [PATCH] Require the INSTEAD OF syntax to create triggers on database views. (CVS 591) FossilOrigin-Name: d9e48cd5180e2aae7672b9d54e18c37d0fe5258a --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/trigger.c | 20 +++++++++++++++++++- test/trigger1.test | 35 +++++++++++++++++++++++++++++++++++ www/lang.tcl | 21 ++++++++++++++------- 5 files changed, 78 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index ad6cf7c786..ecec19fcc6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sfunctions\sto\shandle\sNULLs\scorrectly.\s\sAdded\sthe\sNULLIF()\sfunction.\s(CVS\s590) -D 2002-05-26T21:34:58 +C Require\sthe\sINSTEAD\sOF\ssyntax\sto\screate\striggers\son\sdatabase\sviews.\s(CVS\s591) +D 2002-05-26T23:24:41 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -49,7 +49,7 @@ F src/test2.c 669cc22781c6461a273416ec1a7414d25c081730 F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f F src/tokenize.c facec7dc0b4a13e17ad67702f548dac2f7c6a732 -F src/trigger.c f9adb404ea355a8be2c9cd9740794a898cf1096c +F src/trigger.c b7a93ffa7b91dafff433e6c87d603bfb1d50e3ee F src/update.c f68375173bf5338cae3e97012708e10f206aedd9 F src/util.c a9f6e6f03e8b7137204ac15b35a58f321e38037e F src/vdbe.c caa269517b2392986c8f55401f272e76b9de82d9 @@ -100,7 +100,7 @@ F test/tclsqlite.test 79deeffd7cd637ca0f06c5dbbf2f44d272079533 F test/temptable.test daa83489eea2e9aaeeece09675c28be84c72cb67 F test/tester.tcl dc1b56bd628b487e4d75bfd1e7480b5ed8810ac6 F test/trans.test ae0b9a82d5d34122c3a3108781eb8d078091ccee -F test/trigger1.test a0550c5cce97170dbebb88eee09506d9ad1174e9 +F test/trigger1.test bb63749fa8a395a60541100607d86381604b7194 F test/trigger2.test 7f2b0a9b20004449c78b834c2f22494db3b2e63a F test/unique.test 572aa791327c1e8d797932263e9d67f176cfdb44 F test/update.test a0aa0bf83e6fad8407d0e4ad25ebb09b513f5bf4 @@ -128,14 +128,14 @@ F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c F www/faq.tcl 45bdb18b75ac3aa1befec42985fb892413aac0bb F www/formatchng.tcl 2ce21ff30663fad6618198fe747ce675df577590 F www/index.tcl d0c52fbf031d0a3ee6d9d77aa669d5a4b24b6130 -F www/lang.tcl be7a241fe3dbb145ff25fe951c3d8ad16b543a1f +F www/lang.tcl e87aa6b305d92977a6bd84bfcddd18fa76dff60a F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc F www/opcode.tcl bdec8ef9f100dbd87bbef8976c54b88e43fd8ccc F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 9051173742f1b0e15a809d12a0c9c98fd2c4614d -R 0620e522ec88d7386c2177fd29ebfac3 -U drh -Z 0624defcbccb679d773bc9ffe5a1ecda +P 46ce1a9ab6e527958ebc757fa2175c488299cd84 +R 35b518a6cb0a7aed91c92408e7bd6686 +U danielk1977 +Z 9e3f1ec0355281ef07dac5144d661dfb diff --git a/manifest.uuid b/manifest.uuid index 424c86b5e6..6cf893c246 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -46ce1a9ab6e527958ebc757fa2175c488299cd84 \ No newline at end of file +d9e48cd5180e2aae7672b9d54e18c37d0fe5258a \ No newline at end of file diff --git a/src/trigger.c b/src/trigger.c index 82ba258a01..92971b7610 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -20,7 +20,7 @@ void sqliteCreateTrigger( Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ Token *pName, /* The name of the trigger */ - int tr_tm, /* One of TK_BEFORE, TK_AFTER */ + int tr_tm, /* One of TK_BEFORE, TK_AFTER , TK_INSTEAD */ int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ IdList *pColumns, /* column list if this is an UPDATE OF trigger */ Token *pTableName, /* The name of the table/view the trigger applies to */ @@ -38,6 +38,9 @@ void sqliteCreateTrigger( /* Check that: ** 1. the trigger name does not already exist. ** 2. the table (or view) does exist. + ** 3. that we are not trying to create a trigger on the sqlite_master table + ** 4. That we are not trying to create an INSTEAD OF trigger on a table. + ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view. */ { char *tmp_str = sqliteStrNDup(pName->z, pName->n); @@ -67,6 +70,21 @@ void sqliteCreateTrigger( pParse->nErr++; goto trigger_cleanup; } + if( tab->pSelect && tr_tm != TK_INSTEAD ){ + sqliteSetNString(&pParse->zErrMsg, "cannot create ", -1, + (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", -1, " trigger on view: ", -1 + , pTableName->z, pTableName->n, 0); + goto trigger_cleanup; + } + if( !tab->pSelect && tr_tm == TK_INSTEAD ){ + sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF", -1, + " trigger on table: ", -1, pTableName->z, pTableName->n, 0); + goto trigger_cleanup; + } + } + + if (tr_tm == TK_INSTEAD){ + tr_tm = TK_BEFORE; } /* Build the Trigger object */ diff --git a/test/trigger1.test b/test/trigger1.test index 153f71766a..bfd5e6e6a9 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -19,6 +19,12 @@ # trig-1.6: Error if dropped trigger doesn't exist # trig-1.7: Dropping the table automatically drops all triggers # trig-1.8: A trigger created on a TEMP table is not inserted into sqlite_master +# trig-1.9: Ensure that we cannot create a trigger on sqlite_master +# trig-1.10: +# trig-1.11: +# trig-1.12: Ensure that INSTEAD OF triggers cannot be created on tables +# trig-1.13: Ensure that AFTER triggers cannot be created on views +# trig-1.14: Ensure that BEFORE triggers cannot be created on views # set testdir [file dirname $argv0] @@ -145,4 +151,33 @@ do_test trig_cd-1.11 { } } {1 x-a 2 b 4 d} +# Ensure that we cannot create INSTEAD OF triggers on tables +do_test trig_cd-1.12 { + catchsql { + create table t1(a,b); + create trigger t1t instead of update on t1 for each row begin + delete from t1 WHERE a=old.a+2; + end; + } +} {1 {cannot create INSTEAD OF trigger on table: t1}} +# Ensure that we cannot create BEFORE triggers on views +do_test trig_cd-1.13 { + catchsql { + create view v1 as select * from t1; + create trigger v1t before update on v1 for each row begin + delete from t1 WHERE a=old.a+2; + end; + } +} {1 {cannot create BEFORE trigger on view: v1}} +# Ensure that we cannot create AFTER triggers on views +do_test trig_cd-1.14 { + catchsql { + create table t1(a,b); + create view v1 as select * from t1; + create trigger v1t AFTER update on v1 for each row begin + delete from t1 WHERE a=old.a+2; + end; + } +} {1 {cannot create AFTER trigger on view: v1}} + finish_test diff --git a/www/lang.tcl b/www/lang.tcl index a99d387ae4..e12fa55aa9 100644 --- a/www/lang.tcl +++ b/www/lang.tcl @@ -1,7 +1,7 @@ # # Run this Tcl script to generate the sqlite.html file. # -set rcsid {$Id: lang.tcl,v 1.35 2002/05/15 11:43:16 drh Exp $} +set rcsid {$Id: lang.tcl,v 1.36 2002/05/26 23:24:41 danielk1977 Exp $} puts { @@ -353,6 +353,12 @@ CREATE TRIGGER [ BEFORE | AFTER ] } +Syntax {sql-statement} { +CREATE TRIGGER INSTEAD OF + ON + +} + Syntax {database-event} { DELETE | INSERT | @@ -425,12 +431,13 @@ policy is used instead.

Triggers are automatically dropped when the table that they are associated with is dropped.

-

Triggers may be created on views, as well as ordinary tables. If one or -more INSERT, DELETE or UPDATE triggers are defined on a view, then it is not -an error to execute an INSERT, DELETE or UPDATE statement on the view, -respectively. Thereafter, executing an INSERT, DELETE or UPDATE on the view -causes the associated triggers to fire. The real tables underlying the view -are not modified (except possibly explicitly, by a trigger program).

+

Triggers may be created on views, as well as ordinary tables, by specifying +INSTEAD OF in the CREATE TRIGGER statement. If one or more ON INSERT, ON DELETE +or ON UPDATE triggers are defined on a view, then it is not an error to execute +an INSERT, DELETE or UPDATE statement on the view, respectively. Thereafter, +executing an INSERT, DELETE or UPDATE on the view causes the associated + triggers to fire. The real tables underlying the view are not modified + (except possibly explicitly, by a trigger program).

Example: