]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add support for IF EXISTS on CREATE/DROP TRIGGER/VIEW. Ticket #1899. (CVS 3406)
authordrh <drh@noemail.net>
Mon, 11 Sep 2006 23:45:48 +0000 (23:45 +0000)
committerdrh <drh@noemail.net>
Mon, 11 Sep 2006 23:45:48 +0000 (23:45 +0000)
FossilOrigin-Name: e4fe736cfbbdc081581911a01690576034877b72

manifest
manifest.uuid
src/build.c
src/parse.y
src/sqliteInt.h
src/trigger.c
src/vacuum.c
test/trigger1.test
test/view.test
www/lang.tcl

index 05334df8c43990510065e9cab3470ac6963d9eb8..bffdcbbe151410b909eefa1488c1588cc0c516fc 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Re-use\sdeleted\srowids\sfor\snew\ssegments.\s\sThis\shas\sa\ssomewhat\nsurprising\simpact\son\sperformance,\sI\sbelieve\sbecause\sit\skeeps\sthe\sindex\nsmaller\s(by\skeeping\srowids\ssmaller),\sand\salso\sbecause\sit\simproves\nlocality\sin\sthe\stable\s(deleting\sa\srow\smeans\swe've\salready\stouched\sthe\npages\sleading\sto\sthat\srowid).\s(CVS\s3405)
-D 2006-09-11T21:39:22
+C Add\ssupport\sfor\sIF\sEXISTS\son\sCREATE/DROP\sTRIGGER/VIEW.\s\sTicket\s#1899.\s(CVS\s3406)
+D 2006-09-11T23:45:49
 F Makefile.in cabd42d34340f49260bc2a7668c38eba8d4cfd99
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -50,7 +50,7 @@ F src/attach.c b11eb4d5d3fb99a10a626956bccc7215f6b68b16
 F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f
 F src/btree.c 8f18bb08f84d6a12104fd0f01255febe6289a186
 F src/btree.h 061c50e37de7f50b58528e352d400cf33ead7418
-F src/build.c 4359b34a36938716ed10ac037eec9dc5173b8f4b
+F src/build.c 7199949a6a3449e9ec69408cc79a48ed04fd0b85
 F src/callback.c fd9bb39f7ff6b52bad8365617abc61c720640429
 F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675
 F src/date.c d5519023569adf30892ff7be6deadf25ecdf1ecd
@@ -78,7 +78,7 @@ F src/os_win.c c6976ae50b61fb5b7dce399e578aa1865f02b84f
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c e51c079b3cad8394898a6c22330150339103700a
 F src/pager.h 0cff9de5e9019cb695a04d18df8caaaff933a272
-F src/parse.y b26898e5270c3dc58798047e72cd57113663f761
+F src/parse.y 3279443a2b8173230dd27b9821373b681bb1f3c8
 F src/pragma.c dcb79b8170231f3aed99d4004b4d0a0fc14c4b4d
 F src/prepare.c 84e2c855600c7bfbe2ca691b263301de525f9123
 F src/printf.c b179b6ed12f793e028dd169e2e2e2b2a37eedc63
@@ -88,7 +88,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 233f7766e532a204bed465249ffc584424ed1757
 F src/sqlite.h.in 19f5390cce182242b309a053aa1ee2b902bee147
 F src/sqlite3ext.h 11a046b3519c4b9b7709e6d6a95c3a36366f684a
-F src/sqliteInt.h 259adce944cc3b28da1fa3df9beb9ba86017a45d
+F src/sqliteInt.h fc2439b695dd80a3c58c8f14759e621dbf630b03
 F src/table.c d8817f43a6c6bf139487db161760b9e1e02da3f1
 F src/tclsqlite.c e029f739bed90071789fe81a226d53e97a80a4d8
 F src/test1.c e8213bf8024a47b49ee8ad276ea07d8e3d4c3c26
@@ -107,11 +107,11 @@ F src/test_schema.c ced72140a3a25c148975428e170ec1850d3c3a7d
 F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c
 F src/test_tclvar.c 315e77c17f128ff8c06b38c08617fd07c825a95b
 F src/tokenize.c dfdff21768fbedd40e8d3ca84fc5d0d7af2b46dd
-F src/trigger.c 0fc40125820409a6274834a6e04ad804d96e2793
+F src/trigger.c 74ccec784683232f89f3b4db34a089d8cace2058
 F src/update.c 951f95ef044cf6d28557c48dc35cb0711a0b9129
 F src/utf.c 4459801e9b00cfd69993bfca58545d3775682d6e
 F src/util.c 5409031819ee4672c5f9c3ac7cf517e267a25845
-F src/vacuum.c 5dac7938d70bf0cb5182a291c8605e69cde2398d
+F src/vacuum.c e2cd47929d63c16d835b6052b82fd7422010b903
 F src/vdbe.c a77869949ddd0afe01443611edb949e24e67c91c
 F src/vdbe.h 258b5d1c0aaa72192f09ff0568ce42b383f156fa
 F src/vdbeInt.h e3eaab262b67b84474625cfc38aec1125c32834b
@@ -294,7 +294,7 @@ F test/tkt1667.test ef52c857940755ea5eab24d68f808826e7dcdc94
 F test/tkt1873.test 7159a1c1bf627bbb03f11362e4ad4de11d6ff316
 F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567
 F test/trans.test 06bff0246886858793fca3748721936e2f65e3df
-F test/trigger1.test e8c717e959c2f98c8181cd9466e140fa7aac781f
+F test/trigger1.test 2c79e2bf76350811e362814e98779c120b6a9421
 F test/trigger2.test 33bf8ae9b788013be194efe5f66c04a202facbb4
 F test/trigger3.test 9102fd3933db294dc654b5aee9edfe9e94f2b9e2
 F test/trigger4.test 4bed3705c9df4aaf7a7b164a2d573410d05ca025
@@ -312,7 +312,7 @@ F test/utf16align.test 7360e84472095518c56746f76b1f9d4dce99fb4d
 F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f
 F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
-F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
+F test/view.test 852bd4101e6d171c46ad682eb5c5faf662b2eba4
 F test/vtab1.test c7275c6c6575dfbbd975757f646f94477a6ea5c0
 F test/vtab2.test 43763026b124e68785de05d3fbf957a4b5f81a0d
 F test/vtab3.test f38d6d7d19f08bffdadce4d5b8cba078f8118587
@@ -375,7 +375,7 @@ F www/fullscanb.gif f7c94cb227f060511f8909e10f570157263e9a25
 F www/index-ex1-x-b.gif f9b1d85c3fa2435cf38b15970c7e3aa1edae23a3
 F www/index.tcl 7b9c5747a838501dace958131755651d6ca31adb
 F www/indirect1b1.gif adfca361d2df59e34f9c5cac52a670c2bfc303a1
-F www/lang.tcl 529f5f0f44b55f26cdb66c6547a86b1332e1144a
+F www/lang.tcl 73ce7ce69eff7afef4d62cdeb7b050a670952acd
 F www/lockingv3.tcl f59b19d6c8920a931f096699d6faaf61c05db55f
 F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c
 F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf
@@ -397,7 +397,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P d5ffef3870f06d2dd744ce9470d3c0e68062e804
-R 4f28d2c19780234e639fe3db42d9de5e
-U shess
-Z 323322cfc0451e1239808887226bd556
+P 2f5f6290c9ef99c7b060aecc4d996c976c50c9d7
+R d17bd6ef8648d9d2f3852e6272db6a75
+U drh
+Z 86240886575897a77ef3f7d53b2d3c49
index 298e7e013e4f100dddf4e6beb70d79c14b228dd0..a92c67e518dabf83fe5019ddfedad03c9e8d649c 100644 (file)
@@ -1 +1 @@
-2f5f6290c9ef99c7b060aecc4d996c976c50c9d7
\ No newline at end of file
+e4fe736cfbbdc081581911a01690576034877b72
\ No newline at end of file
index 1f7a9267d5e90d79a58830f50c72ddb2b6a43a3b..eeceded71eea602d041c87016281cdcbd8151bab 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.410 2006/08/14 14:23:42 drh Exp $
+** $Id: build.c,v 1.411 2006/09/11 23:45:49 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1590,7 +1590,8 @@ void sqlite3CreateView(
   Token *pName1,     /* The token that holds the name of the view */
   Token *pName2,     /* The token that holds the name of the view */
   Select *pSelect,   /* A SELECT statement that will become the new view */
-  int isTemp         /* TRUE for a TEMPORARY view */
+  int isTemp,        /* TRUE for a TEMPORARY view */
+  int noErr          /* Suppress error messages if VIEW already exists */
 ){
   Table *p;
   int n;
@@ -1605,7 +1606,7 @@ void sqlite3CreateView(
     sqlite3SelectDelete(pSelect);
     return;
   }
-  sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, 0);
+  sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
   p = pParse->pNewTable;
   if( p==0 || pParse->nErr ){
     sqlite3SelectDelete(pSelect);
index f9445113c4730a831e2fcd662b6e80548d71bde0..122d7842c39ea631006d3ab8046b40ee51ead15a 100644 (file)
@@ -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.208 2006/08/25 23:42:53 drh Exp $
+** @(#) $Id: parse.y,v 1.209 2006/09/11 23:45:49 drh Exp $
 */
 
 // All token codes are small integers with #defines that begin with "TK_"
@@ -355,8 +355,8 @@ ifexists(A) ::= .            {A = 0;}
 ///////////////////// The CREATE VIEW statement /////////////////////////////
 //
 %ifndef SQLITE_OMIT_VIEW
-cmd ::= CREATE(X) temp(T) VIEW nm(Y) dbnm(Z) AS select(S). {
-  sqlite3CreateView(pParse, &X, &Y, &Z, S, T);
+cmd ::= CREATE(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) AS select(S). {
+  sqlite3CreateView(pParse, &X, &Y, &Z, S, T, E);
 }
 cmd ::= DROP VIEW ifexists(E) fullname(X). {
   sqlite3DropTable(pParse, X, 1, E);
@@ -931,10 +931,10 @@ cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
   sqlite3FinishTrigger(pParse, S, &all);
 }
 
-trigger_decl(A) ::= temp(T) TRIGGER nm(B) dbnm(Z) trigger_time(C)
-                    trigger_event(D)
+trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z) 
+                    trigger_time(C) trigger_event(D)
                     ON fullname(E) foreach_clause(F) when_clause(G). {
-  sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, F, G, T);
+  sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, F, G, T, NOERR);
   A = (Z.n==0?B:Z);
 }
 
@@ -1019,8 +1019,8 @@ raisetype(A) ::= FAIL.      {A = OE_Fail;}
 
 ////////////////////////  DROP TRIGGER statement //////////////////////////////
 %ifndef SQLITE_OMIT_TRIGGER
-cmd ::= DROP TRIGGER fullname(X). {
-  sqlite3DropTrigger(pParse,X);
+cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). {
+  sqlite3DropTrigger(pParse,X,NOERR);
 }
 %endif // !SQLITE_OMIT_TRIGGER
 
index 582685414a48c2fac04c49850c9fbdd5950063cc..fae55f2ec72f62d27646ef7301a85dd4c0028201 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.525 2006/09/02 20:57:52 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.526 2006/09/11 23:45:50 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1600,7 +1600,7 @@ void sqlite3AddDefaultValue(Parse*,Expr*);
 void sqlite3AddCollateType(Parse*, const char*, int);
 void sqlite3EndTable(Parse*,Token*,Token*,Select*);
 
-void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int);
+void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
 
 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
   int sqlite3ViewGetColumnNames(Parse*,Table*);
@@ -1691,9 +1691,9 @@ void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);
 
 #ifndef SQLITE_OMIT_TRIGGER
   void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
-                           int,Expr*,int);
+                           int,Expr*,int, int);
   void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
-  void sqlite3DropTrigger(Parse*, SrcList*);
+  void sqlite3DropTrigger(Parse*, SrcList*, int);
   void sqlite3DropTriggerPtr(Parse*, Trigger*);
   int sqlite3TriggersExist(Parse*, Table*, int, ExprList*);
   int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, 
index 15992df3812a1103c4515cf1ecb0b64d9b941834..efff8b833b6cd6228f6e866585632df965b8d9a0 100644 (file)
@@ -49,7 +49,8 @@ void sqlite3BeginTrigger(
   SrcList *pTableName,/* The name of the table/view the trigger applies to */
   int foreach,        /* One of TK_ROW or TK_STATEMENT */
   Expr *pWhen,        /* WHEN clause */
-  int isTemp          /* True if the TEMPORARY keyword is present */
+  int isTemp,         /* True if the TEMPORARY keyword is present */
+  int noErr           /* Suppress errors if the trigger already exists */
 ){
   Trigger *pTrigger = 0;
   Table *pTab;
@@ -115,7 +116,9 @@ void sqlite3BeginTrigger(
     goto trigger_cleanup;
   }
   if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){
-    sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
+    if( !noErr ){
+      sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
+    }
     goto trigger_cleanup;
   }
 
@@ -439,7 +442,7 @@ void sqlite3DeleteTrigger(Trigger *pTrigger){
 ** same job as this routine except it takes a pointer to the trigger
 ** instead of the trigger name.
 **/
-void sqlite3DropTrigger(Parse *pParse, SrcList *pName){
+void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
   Trigger *pTrigger = 0;
   int i;
   const char *zDb;
@@ -463,7 +466,9 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName){
     if( pTrigger ) break;
   }
   if( !pTrigger ){
-    sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
+    if( !noErr ){
+      sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
+    }
     goto drop_trigger_cleanup;
   }
   sqlite3DropTriggerPtr(pParse, pTrigger);
index f15648c3d20f232f4a7d5b8ea233a90ccd2c90c3..f7737f88abaf4787ef34ab8a8eca3ce8114334c4 100644 (file)
@@ -14,7 +14,7 @@
 ** Most of the code in this file may be omitted by defining the
 ** SQLITE_OMIT_VACUUM macro.
 **
-** $Id: vacuum.c,v 1.60 2006/09/11 11:13:27 drh Exp $
+** $Id: vacuum.c,v 1.61 2006/09/11 23:45:50 drh Exp $
 */
 #include "sqliteInt.h"
 #include "vdbeInt.h"
@@ -188,13 +188,6 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
   /* Query the schema of the main database. Create a mirror schema
   ** in the temporary database.
   */
-  rc = execSql(db,
-      "INSERT INTO vacuum_db.sqlite_master "
-      "  SELECT 'table', name, name, 0, sql"
-      "    FROM sqlite_master"
-      "   WHERE type='table' AND rootpage==0"
-  );
-  if( rc ) goto end_of_vacuum;
   rc = execExecSql(db, 
       "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
       "  FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
@@ -209,11 +202,6 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
       "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
       "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
   if( rc!=SQLITE_OK ) goto end_of_vacuum;
-  rc = execExecSql(db, 
-      "SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) "
-      "  FROM sqlite_master WHERE type='view'"
-  );
-  if( rc!=SQLITE_OK ) goto end_of_vacuum;
 
   /* Loop through the tables in the main database. For each, do
   ** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy
@@ -244,17 +232,19 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
   if( rc!=SQLITE_OK ) goto end_of_vacuum;
 
 
-  /* Copy the triggers from the main database to the temporary database.
-  ** This was deferred before in case the triggers interfered with copying
-  ** the data. It's possible the indices should be deferred until this
-  ** point also.
+  /* Copy the triggers, views, and virtual tables from the main database
+  ** over to the temporary database.  None of these objects has any
+  ** associated storage, so all we have to do is copy their entries
+  ** from the SQLITE_MASTER table.
   */
-  rc = execExecSql(db, 
-      "SELECT 'CREATE TRIGGER  vacuum_db.' || substr(sql, 16, 1000000) "
-      "FROM sqlite_master WHERE type='trigger'"
+  rc = execSql(db,
+      "INSERT INTO vacuum_db.sqlite_master "
+      "  SELECT type, name, tbl_name, rootpage, sql"
+      "    FROM sqlite_master"
+      "   WHERE type='view' OR type='trigger'"
+      "      OR (type='table' AND rootpage=0)"
   );
-  if( rc!=SQLITE_OK ) goto end_of_vacuum;
-
+  if( rc ) goto end_of_vacuum;
 
   /* At this point, unless the main db was completely empty, there is now a
   ** transaction open on the vacuum database, but not on the main database.
index 3147927f8c8923137323f0cb14f573276b524725..ca23335822c420a2e8ad2968760bf879c0e7d03d 100644 (file)
@@ -60,6 +60,13 @@ execsql {
          INSERT INTO t1 values(1);
        END;
 }
+do_test trigger1-1.2.0 {
+    catchsql {
+       CREATE TRIGGER IF NOT EXISTS tr1 DELETE ON t1 BEGIN
+           SELECT * FROM sqlite_master;
+       END
+     }
+} {0 {}}
 do_test trigger1-1.2.1 {
     catchsql {
        CREATE TRIGGER tr1 DELETE ON t1 BEGIN
@@ -95,7 +102,7 @@ do_test trigger1-1.3 {
 
 do_test trigger1-1.4 {
     catchsql {
-       DROP TRIGGER tr1;
+       DROP TRIGGER IF EXISTS tr1;
        CREATE TRIGGER tr1 DELETE ON t1 BEGIN
            SELECT * FROM sqlite_master;
        END
@@ -111,7 +118,13 @@ do_test trigger1-1.5 {
     }
 } {}
 
-do_test trigger1-1.6 {
+do_test trigger1-1.6.1 {
+    catchsql {
+       DROP TRIGGER IF EXISTS biggles;
+    }
+} {0 {}}
+
+do_test trigger1-1.6.2 {
     catchsql {
        DROP TRIGGER biggles;
     }
index 19c33f9d4fb9ccc21dc410b71fc477c2a6a19c0e..83ffec25678637d7c2aaa673fae5fb1d84c0970a 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing VIEW statements.
 #
-# $Id: view.test,v 1.32 2006/06/11 23:41:56 drh Exp $
+# $Id: view.test,v 1.33 2006/09/11 23:45:50 drh Exp $
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 
@@ -34,7 +34,7 @@ do_test view-1.0 {
 do_test view-1.1 {
   execsql {
     BEGIN;
-    CREATE VIEW v1 AS SELECT a,b FROM t1;
+    CREATE VIEW IF NOT EXISTS v1 AS SELECT a,b FROM t1;
     SELECT * FROM v1 ORDER BY a;
   }
 } {1 2 4 5 7 8}
@@ -59,7 +59,7 @@ do_test view-1.3.1 {
 } {1 2 4 5 7 8}
 do_test view-1.4 {
   catchsql {
-    DROP VIEW v1;
+    DROP VIEW IF EXISTS v1;
     SELECT * FROM v1 ORDER BY a;
   }
 } {1 {no such table: v1}}
@@ -482,5 +482,20 @@ do_test view-15.2 {
   }
 } {x 2 y 3}
 
+do_test view-16.1 {
+  catchsql {
+    CREATE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1;
+  }
+} {0 {}}
+do_test view-16.2 {
+  execsql {
+    SELECT sql FROM sqlite_master WHERE name='v1'
+  }
+} {{CREATE VIEW v1 AS SELECT a AS 'xyz', b+c AS 'pqr', c-b FROM t1}}
+do_test view-16.3 {
+  catchsql {
+    DROP VIEW IF EXISTS nosuchview
+  }
+} {0 {}}
 
 finish_test
index 75cda0f2620642b96d4cd77dc3b1a93c65fe1cf0..cd17ac480c7ba503dc1d36f47ce7c2a25e43cecb 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the lang-*.html files.
 #
-set rcsid {$Id: lang.tcl,v 1.116 2006/08/29 13:08:38 drh Exp $}
+set rcsid {$Id: lang.tcl,v 1.117 2006/09/11 23:45:50 drh Exp $}
 source common.tcl
 
 if {[llength $argv]>0} {
@@ -638,13 +638,13 @@ statement.  </p>
 Section {CREATE TRIGGER} createtrigger
 
 Syntax {sql-statement} {
-CREATE [TEMP | TEMPORARY] TRIGGER <trigger-name> [ BEFORE | AFTER ]
+CREATE [TEMP | TEMPORARY] TRIGGER [IF NOT EXISTS] <trigger-name> [ BEFORE | AFTER ]
 <database-event> ON [<database-name> .] <table-name>
 <trigger-action>
 }
 
 Syntax {sql-statement} {
-CREATE [TEMP | TEMPORARY] TRIGGER <trigger-name> INSTEAD OF
+CREATE [TEMP | TEMPORARY] TRIGGER [IF NOT EXISTS] <trigger-name> INSTEAD OF
 <database-event> ON [<database-name> .] <view-name>
 <trigger-action>
 }
@@ -794,7 +794,7 @@ statement.</p>
 Section {CREATE VIEW} {createview}
 
 Syntax {sql-command} {
-CREATE [TEMP | TEMPORARY] VIEW [<database-name>.] <view-name> AS <select-statement>
+CREATE [TEMP | TEMPORARY] VIEW [IF NOT EXISTS] [<database-name>.] <view-name> AS <select-statement>
 }
 
 puts {
@@ -941,7 +941,7 @@ result if the table does not exist.</p>
 
 Section {DROP TRIGGER} droptrigger
 Syntax {sql-statement} {
-DROP TRIGGER [<database-name> .] <trigger-name>
+DROP TRIGGER [IF EXISTS] [<database-name> .] <trigger-name>
 }
 puts { 
 <p>The DROP TRIGGER statement removes a trigger created by the 
@@ -954,7 +954,7 @@ dropped when the associated table is dropped.</p>
 Section {DROP VIEW} dropview
 
 Syntax {sql-command} {
-DROP VIEW <view-name>
+DROP VIEW [IF EXISTS] <view-name>
 }
 
 puts {