]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Allow CREATE and DROP TRIGGER on attached databases. (CVS 1488)
authordanielk1977 <danielk1977@noemail.net>
Sat, 29 May 2004 02:37:19 +0000 (02:37 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Sat, 29 May 2004 02:37:19 +0000 (02:37 +0000)
FossilOrigin-Name: 4060a37d0baaa60c50f2dde4a1ab344133fcabbb

manifest
manifest.uuid
src/build.c
src/parse.y
src/sqliteInt.h
src/tclsqlite.c
src/trigger.c
src/vdbe.c
test/attach.test
test/attach3.test
test/trigger1.test

index 925dcad8cea39db2f79594585b3c2d66d93f8319..b62be5461ddb974e2d1b7decbc4d1536140173b8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Factor\scommon\scode\sfor\sgenerating\sindex\skeys\sinto\sa\sprocedure.\s\sOther\nspeed\simprovements\sand\sbug\sfixes.\s(CVS\s1487)
-D 2004-05-28T16:00:22
+C Allow\sCREATE\sand\sDROP\sTRIGGER\son\sattached\sdatabases.\s(CVS\s1488)
+D 2004-05-29T02:37:19
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -26,7 +26,7 @@ F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
 F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
 F src/btree.c 6db76fbf63efd6008c5e6cb038ea40f94abffcf7
 F src/btree.h b65140b5ae891f30d2a39e64b9f0343225553545
-F src/build.c 60ec4b38c0f158c9f2e4778ef6af13d19af7bfcd
+F src/build.c ed09cd54a48ef2ef700c7e3a63b5e35224bde9cc
 F src/date.c 0eb922af5c5f5e2455f8dc2f98023ed3e04a857e
 F src/delete.c 72f8febf6170cda830f509c8f9dffbed3df3596c
 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
@@ -48,28 +48,28 @@ F src/os_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be
 F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
 F src/pager.c 6ff6b906427d4824099140776cb8768f922f3dc5
 F src/pager.h 78a00ac280899bcba1a89dc51585dcae6b7b3253
-F src/parse.y 9d3be712abc9005495701efbec741c58408f1343
+F src/parse.y fbb2378795cad3f6141836fb2035b97bd5ddad4e
 F src/pragma.c 0c17b613d719c62a0dbad659b7d8a6e7ce7e9733
 F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
 F src/select.c ee54bf2faa76f5e30832fd589a1f10c485047469
 F src/shell.c ed4d237b3e52a0a42512bfcc53530e46de20c28f
 F src/sqlite.h.in edc6408c7f53c2104f781a76b926036e17018ec9
-F src/sqliteInt.h d95d08442d19e2ee592ce1ec7865cbbcf23640bd
+F src/sqliteInt.h 01f9250ee3a1ab681b7ed91ad2b3748c2f230521
 F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
-F src/tclsqlite.c 877d0b96013a25b03ed6bd2d32917c42e84403bc
+F src/tclsqlite.c b314f12760547e4ef090e055f1298f70627450d3
 F src/test1.c 32934478366531503d634968db414df17cb38238
 F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872
 F src/test3.c 5e4a6d596f982f6f47a5f9f75ede9b4a3b739968
 F src/test4.c 34848a9fd31aa65857b20a8bfc03aff77d8c3426
 F src/test5.c 9a1f15133f6955f067c5246e564723b5f23ff221
 F src/tokenize.c 50a87c7414de54a008427c9fed22e4e86efb6844
-F src/trigger.c 9ab75040aec65b593b54a7c1d4546f2f9ca058ef
+F src/trigger.c 9040e5dd7e5586e863c20acdca6808e8f7bb9727
 F src/update.c 96461bcf4e946697e83c09c77c7e61b545a2f66e
 F src/utf.c d87fffc1ea7e52d73014ccea06afe1382bbb28b2
 F src/util.c 4df9d9b0d930d81ec581bcb68748e7c48bdc8c7d
 F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
-F src/vdbe.c 68f3583ba2cb13ef0121be99e0edccfff133281a
+F src/vdbe.c ea010d63dfdf84b7d23781144fe2cd11add2c1bd
 F src/vdbe.h e73f890e0f2a6c42b183d7d6937947930fe4fdeb
 F src/vdbeInt.h c2bcd6e5a6e6a3753e4c5a368629c3a625719bfc
 F src/vdbeapi.c 0c5d64c81871cb4fe5407e639604ee95738b6942
@@ -77,9 +77,9 @@ F src/vdbeaux.c bbcf1bb953526130495b01b23751cf756cfed2fb
 F src/vdbemem.c c97c145ff6d9fc5b4236704c04a65849117e6214
 F src/where.c efe5d25fe18cd7381722457898cd863e84097a0c
 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
-F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83
+F test/attach.test e872e1cf3e97949727d1a2c9582efeaf04b192a3
 F test/attach2.test 5472d442bb2ef1ee587e0ae7472bb68b52509a38
-F test/attach3.test 8c55071e4629fe781f3b1955454db2b7f33c943b
+F test/attach3.test 65c52f1e5f435518db06a877eed6afe2cac652c9
 F test/auth.test 95809b8f6a9bec18b94d28cafd03fe27d2f8a9e9
 F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81
 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
@@ -151,7 +151,7 @@ F test/thread1.test 53f050d5be6932d9430df7756edd379366508ff6
 F test/threadtest1.c f7f896e62ed46feae1dc411114a48c15a0f82ee2
 F test/threadtest2.c d94ca4114fd1504f7e0ae724bcd83d4b40931d86
 F test/trans.test 0cb8256daff1ae0da75321e00125338c6681158d
-F test/trigger1.test 4538c1c7d6bbca5dfe619ea6e1682b07ece95b21
+F test/trigger1.test 99b7cd9a568ac60aa04bbc3b9db9575ffa97709a
 F test/trigger2.test 0767ab30cb5a2c8402c8524f3d566b410b6f5263
 F test/trigger3.test a95ccace88291449f5eae7139ec438a42f90654d
 F test/trigger4.test 542afce45774e8f8e1130b96b8675f414d6e4bd8
@@ -204,7 +204,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P c8a40218c20cf5d0abad330e8fa59ca4c36e7608
-R 3143f6cfe246debfe7547a873f48094e
-U drh
-Z 33a80435a29a583c43c0f69454c7f7ae
+P 6661bb5f9c1692f94b8b7d900b6be07f027e6324
+R fde9d916f771cc8e55efbaa7078f8e6a
+U danielk1977
+Z b5bca915020b46ffea1984f7a4d9cf29
index c1e422d992901ea812dab9810dce4108e5a3d2df..f022fb6e2b7f30bd4be89d9b85ea779033feb2d6 100644 (file)
@@ -1 +1 @@
-6661bb5f9c1692f94b8b7d900b6be07f027e6324
\ No newline at end of file
+4060a37d0baaa60c50f2dde4a1ab344133fcabbb
\ No newline at end of file
index bf208acd22d31573d74474274e5794af2ddfce25..8710897e8882608ad73eed23499b3c932328a075 100644 (file)
@@ -23,7 +23,7 @@
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.197 2004/05/28 16:00:22 drh Exp $
+** $Id: build.c,v 1.198 2004/05/29 02:37:19 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -425,7 +425,7 @@ int findDb(sqlite3 *db, Token *pName){
   return -1;
 }
 
-static int resolveSchemaName(
+int sqlite3TwoPartName(
   Parse *pParse, 
   Token *pName1, 
   Token *pName2, 
@@ -501,7 +501,7 @@ void sqlite3StartTable(
   ** set to the index of the database that the table or view is to be
   ** created in.
   */
-  iDb = resolveSchemaName(pParse, pName1, pName2, &pName);
+  iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
   if( iDb<0 ) return;
   if( isTemp && iDb>1 ){
     /* If creating a temp table, the name may not be qualified */
@@ -1166,7 +1166,7 @@ void sqlite3CreateView(
     sqlite3SelectDelete(pSelect);
     return;
   }
-  resolveSchemaName(pParse, pName1, pName2, &pName);
+  sqlite3TwoPartName(pParse, pName1, pName2, &pName);
   if( sqlite3FixInit(&sFix, pParse, p->iDb, "view", pName)
     && sqlite3FixSelect(&sFix, pSelect)
   ){
@@ -1606,7 +1606,7 @@ void sqlite3CreateIndex(
   Parse *pParse,   /* All information about this parse */
   Token *pName1,   /* First part of index name. May be NULL */
   Token *pName2,   /* Second part of index name. May be NULL */
-  Token *pTblName, /* Name of the table to index. Use pParse->pNewTable if 0 */
+  SrcList *pTblName, /* Name of the table to index. Use pParse->pNewTable if 0 */
   IdList *pList,   /* A list of columns to be indexed */
   int onError,     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
   Token *pStart,   /* The CREATE token that begins a CREATE TABLE statement */
@@ -1624,50 +1624,38 @@ void sqlite3CreateIndex(
   int iDb;          /* Index of the database that is being written */
   Token *pName = 0; /* Unqualified name of the index to create */
 
-/*
   if( pParse->nErr || sqlite3_malloc_failed ) goto exit_create_index;
-  if( db->init.busy 
-     && sqlite3FixInit(&sFix, pParse, db->init.iDb, "index", pName)
-     && sqlite3FixSrcList(&sFix, pTable)
-  ){
-    goto exit_create_index;
-  }
-*/
 
   /*
   ** Find the table that is to be indexed.  Return early if not found.
   */
   if( pTblName!=0 ){
-    char *zTblName;
 
     /* Use the two-part index name to determine the database 
-    ** to search for the table. If no database name is specified, 
-    ** iDb is set to 0. In this case search both the temp and main
-    ** databases for the named table.
+    ** to search for the table. 'Fix' the table name to this db
+    ** before looking up the table.
     */
     assert( pName1 && pName2 );
-    iDb = resolveSchemaName(pParse, pName1, pName2, &pName);
+    iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
     if( iDb<0 ) goto exit_create_index;
 
-    /* Now search for the table in the database iDb. If iDb is
-    ** zero, then search both the "main" and "temp" databases.
+    /* If the index name was unqualified, check if the the table
+    ** is a temp table. If so, set the database to 1.
     */
-    zTblName = sqlite3TableNameFromToken(pTblName);
-    if( !zTblName ){
-      pParse->nErr++;
-      pParse->rc = SQLITE_NOMEM;
-      goto exit_create_index;
-    }
-    assert( pName1!=0 );
-    if( iDb==0 ){
-      pTab = sqlite3FindTable(db, zTblName, "temp");
+    pTab = sqlite3SrcListLookup(pParse, pTblName);
+    if( pName2 && pName2->n==0 && pTab && pTab->iDb==1 ){
+      iDb = 1;
     }
-    if( !pTab ){
-      pTab = sqlite3LocateTable(pParse, zTblName, db->aDb[iDb].zName);
+
+    if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
+        sqlite3FixSrcList(&sFix, pTblName)
+    ){
+      goto exit_create_index;
     }
-    sqliteFree( zTblName );
+    pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName, 
+        pTblName->a[0].zDatabase);
     if( !pTab ) goto exit_create_index;
-    iDb = pTab->iDb;
+    assert( iDb==pTab->iDb );
   }else{
     assert( pName==0 );
     pTab =  pParse->pNewTable;
@@ -1679,12 +1667,6 @@ void sqlite3CreateIndex(
     sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
     goto exit_create_index;
   }
-/*
-  if( pTab->iDb>=2 && db->init.busy==0 ){
-    sqlite3ErrorMsg(pParse, "table %s may not have indices added", pTab->zName);
-    goto exit_create_index;
-  }
-*/
   if( pTab->pSelect ){
     sqlite3ErrorMsg(pParse, "views may not be indexed");
     goto exit_create_index;
index 6f3a34e27a296f487e3ea4a75ac868a97a0e3419..4b117c23354facaae48b2ab4a45153f34f20d47a 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.122 2004/05/28 12:33:31 danielk1977 Exp $
+** @(#) $Id: parse.y,v 1.123 2004/05/29 02:37:19 danielk1977 Exp $
 */
 %token_prefix TK_
 %token_type {Token}
@@ -730,10 +730,11 @@ expritem(A) ::= .                       {A = 0;}
 ///////////////////////////// The CREATE INDEX command ///////////////////////
 //
 cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D)
-        ON nm(Y) LP idxlist(Z) RP(E) onconf(R). {
+        ON nm(Y) dbnm(C) LP idxlist(Z) RP(E) onconf(R). {
   if( U!=OE_None ) U = R;
   if( U==OE_Default) U = OE_Abort;
-  sqlite3CreateIndex(pParse, &X, &D, &Y, Z, U, &S, &E);
+  sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,&C),
+      Z, U, &S, &E);
 }
 
 %type uniqueflag {int}
@@ -788,10 +789,10 @@ cmd ::= CREATE(A) trigger_decl BEGIN trigger_cmd_list(S) END(Z). {
   sqlite3FinishTrigger(pParse, S, &all);
 }
 
-trigger_decl ::= temp(T) TRIGGER nm(B) trigger_time(C) trigger_event(D)
+trigger_decl ::= temp(T) TRIGGER nm(B) dbnm(Z) trigger_time(C) trigger_event(D)
                  ON nm(E) dbnm(DB) foreach_clause(F) when_clause(G). {
   SrcList *pTab = sqlite3SrcListAppend(0, &E, &DB);
-  sqlite3BeginTrigger(pParse, &B, C, D.a, D.b, pTab, F, G, T);
+  sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, pTab, F, G, T);
 }
 
 %type trigger_time  {int}
index c19a6cc354259b3b103fc47a0ee7a8b66e84b8de..f1d13b52f4a15287dc23338b9b7daf3324e437f1 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.260 2004/05/28 16:00:22 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.261 2004/05/29 02:37:19 danielk1977 Exp $
 */
 #include "config.h"
 #include "sqlite.h"
@@ -229,7 +229,7 @@ extern int sqlite3_iMallocFail;   /* Fail sqliteMalloc() after this many calls *
 /*
 ** The name of the schema table.
 */
-#define SCHEMA_TABLE(x)  (x?TEMP_MASTER_NAME:MASTER_NAME)
+#define SCHEMA_TABLE(x)  (x==1?TEMP_MASTER_NAME:MASTER_NAME)
 
 /*
 ** A convenience macro that returns the number of elements in
@@ -1221,7 +1221,8 @@ void sqlite3SrcListAddAlias(SrcList*, Token*);
 void sqlite3SrcListAssignCursors(Parse*, SrcList*);
 void sqlite3IdListDelete(IdList*);
 void sqlite3SrcListDelete(SrcList*);
-void sqlite3CreateIndex(Parse*,Token*,Token*,Token*,IdList*,int,Token*,Token*);
+void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,IdList*,int,Token*,
+                        Token*);
 void sqlite3DropIndex(Parse*, SrcList*);
 void sqlite3AddKeyType(Vdbe*, ExprList*);
 void sqlite3AddIdxKeyType(Vdbe*, Index*);
@@ -1286,7 +1287,8 @@ int sqlite3SafetyOn(sqlite*);
 int sqlite3SafetyOff(sqlite*);
 int sqlite3SafetyCheck(sqlite*);
 void sqlite3ChangeCookie(sqlite*, Vdbe*, int);
-void sqlite3BeginTrigger(Parse*, Token*,int,int,IdList*,SrcList*,int,Expr*,int);
+void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
+                         int,Expr*,int);
 void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
 void sqlite3DropTrigger(Parse*, SrcList*);
 void sqlite3DropTriggerPtr(Parse*, Trigger*, int);
@@ -1352,3 +1354,4 @@ void sqlite3Error(sqlite *, int, const char*,...);
 int sqlite3utfTranslate(const void *, int , u8 , void **, int *, u8);
 u8 sqlite3UtfReadBom(const void *zData, int nData);
 void *sqlite3HexToBlob(const char *z);
+int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
index 29e6093037227951945f59e2e33a8b1033e69f3d..c446710a7398505b49afb55c56d62a853c80e350 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** A TCL Interface to SQLite
 **
-** $Id: tclsqlite.c,v 1.75 2004/05/27 13:35:20 danielk1977 Exp $
+** $Id: tclsqlite.c,v 1.76 2004/05/29 02:37:19 danielk1977 Exp $
 */
 #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
 
@@ -75,182 +75,6 @@ struct CallbackData {
   char **azColName;         /* Column names translated to UTF-8 */
 };
 
-#ifdef UTF_TRANSLATION_NEEDED
-/*
-** Called for each row of the result.
-**
-** This version is used when TCL expects UTF-8 data but the database
-** uses the ISO8859 format.  A translation must occur from ISO8859 into
-** UTF-8.
-*/
-static int DbEvalCallback(
-  void *clientData,      /* An instance of CallbackData */
-  int nCol,              /* Number of columns in the result */
-  char ** azCol,         /* Data for each column */
-  char ** azN            /* Name for each column */
-){
-  CallbackData *cbData = (CallbackData*)clientData;
-  int i, rc;
-  Tcl_DString dCol;
-  Tcl_DStringInit(&dCol);
-  if( cbData->azColName==0 ){
-    assert( cbData->once );
-    cbData->once = 0;
-    if( cbData->zArray[0] ){
-      Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0);
-    }
-    cbData->azColName = malloc( nCol*sizeof(char*) );
-    if( cbData->azColName==0 ){ return 1; }
-    cbData->nColName = nCol;
-    for(i=0; i<nCol; i++){
-      Tcl_ExternalToUtfDString(NULL, azN[i], -1, &dCol);
-      cbData->azColName[i] = malloc( Tcl_DStringLength(&dCol) + 1 );
-      if( cbData->azColName[i] ){
-        strcpy(cbData->azColName[i], Tcl_DStringValue(&dCol));
-      }else{
-        return 1;
-      }
-      if( cbData->zArray[0] ){
-        Tcl_SetVar2(cbData->interp, cbData->zArray, "*",
-             Tcl_DStringValue(&dCol), TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
-        if( azN[nCol]!=0 ){
-          Tcl_DString dType;
-          Tcl_DStringInit(&dType);
-          Tcl_DStringAppend(&dType, "typeof:", -1);
-          Tcl_DStringAppend(&dType, Tcl_DStringValue(&dCol), -1);
-          Tcl_DStringFree(&dCol);
-          Tcl_ExternalToUtfDString(NULL, azN[i+nCol], -1, &dCol);
-          Tcl_SetVar2(cbData->interp, cbData->zArray, 
-               Tcl_DStringValue(&dType), Tcl_DStringValue(&dCol),
-               TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
-          Tcl_DStringFree(&dType);
-        }
-      }
-      
-      Tcl_DStringFree(&dCol);
-    }
-  }
-  if( azCol!=0 ){
-    if( cbData->zArray[0] ){
-      for(i=0; i<nCol; i++){
-        char *z = azCol[i];
-        if( z==0 ) z = "";
-        Tcl_DStringInit(&dCol);
-        Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
-        Tcl_SetVar2(cbData->interp, cbData->zArray, cbData->azColName[i], 
-              Tcl_DStringValue(&dCol), 0);
-        Tcl_DStringFree(&dCol);
-      }
-    }else{
-      for(i=0; i<nCol; i++){
-        char *z = azCol[i];
-        if( z==0 ) z = "";
-        Tcl_DStringInit(&dCol);
-        Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
-        Tcl_SetVar(cbData->interp, cbData->azColName[i],
-                   Tcl_DStringValue(&dCol), 0);
-        Tcl_DStringFree(&dCol);
-      }
-    }
-  }
-  rc = Tcl_EvalObj(cbData->interp, cbData->pCode);
-  if( rc==TCL_CONTINUE ) rc = TCL_OK;
-  cbData->tcl_rc = rc;
-  return rc!=TCL_OK;
-}
-#endif /* UTF_TRANSLATION_NEEDED */
-
-#ifndef UTF_TRANSLATION_NEEDED
-/*
-** Called for each row of the result.
-**
-** This version is used when either of the following is true:
-**
-**    (1) This version of TCL uses UTF-8 and the data in the
-**        SQLite database is already in the UTF-8 format.
-**
-**    (2) This version of TCL uses ISO8859 and the data in the
-**        SQLite database is already in the ISO8859 format.
-*/
-static int DbEvalCallback(
-  void *clientData,      /* An instance of CallbackData */
-  int nCol,              /* Number of columns in the result */
-  char ** azCol,         /* Data for each column */
-  char ** azN            /* Name for each column */
-){
-  CallbackData *cbData = (CallbackData*)clientData;
-  int i, rc;
-  if( azCol==0 || (cbData->once && cbData->zArray[0]) ){
-    Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0);
-    for(i=0; i<nCol; i++){
-      Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i],
-         TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
-      if( azN[nCol] ){
-        char *z = sqlite3_mprintf("typeof:%s", azN[i]);
-        Tcl_SetVar2(cbData->interp, cbData->zArray, z, azN[i+nCol],
-           TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
-        sqlite3_freemem(z);
-      }
-    }
-    cbData->once = 0;
-  }
-  if( azCol!=0 ){
-    if( cbData->zArray[0] ){
-      for(i=0; i<nCol; i++){
-        char *z = azCol[i];
-        if( z==0 ) z = "";
-        Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], z, 0);
-      }
-    }else{
-      for(i=0; i<nCol; i++){
-        char *z = azCol[i];
-        if( z==0 ) z = "";
-        Tcl_SetVar(cbData->interp, azN[i], z, 0);
-      }
-    }
-  }
-  rc = Tcl_EvalObj(cbData->interp, cbData->pCode);
-  if( rc==TCL_CONTINUE ) rc = TCL_OK;
-  cbData->tcl_rc = rc;
-  return rc!=TCL_OK;
-}
-#endif
-
-/*
-** This is an alternative callback for database queries.  Instead
-** of invoking a TCL script to handle the result, this callback just
-** appends each column of the result to a list.  After the query
-** is complete, the list is returned.
-*/
-static int DbEvalCallback2(
-  void *clientData,      /* An instance of CallbackData */
-  int nCol,              /* Number of columns in the result */
-  char ** azCol,         /* Data for each column */
-  char ** azN            /* Name for each column */
-){
-  Tcl_Obj *pList = (Tcl_Obj*)clientData;
-  int i;
-  if( azCol==0 ) return 0;
-  for(i=0; i<nCol; i++){
-    Tcl_Obj *pElem;
-    if( azCol[i] && *azCol[i] ){
-#ifdef UTF_TRANSLATION_NEEDED
-      Tcl_DString dCol;
-      Tcl_DStringInit(&dCol);
-      Tcl_ExternalToUtfDString(NULL, azCol[i], -1, &dCol);
-      pElem = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1);
-      Tcl_DStringFree(&dCol);
-#else
-      pElem = Tcl_NewStringObj(azCol[i], -1);
-#endif
-    }else{
-      pElem = Tcl_NewObj();
-    }
-    Tcl_ListObjAppendElement(0, pList, pElem);
-  }
-  return 0;
-}
-
 /*
 ** This is a second alternative callback for database queries.  A the
 ** first column of the first row of the result is made the TCL result.
@@ -475,6 +299,26 @@ static int auth_callback(
 }
 #endif /* SQLITE_OMIT_AUTHORIZATION */
 
+/*
+** zText is a pointer to text obtained via an sqlite3_result_text()
+** or similar interface. This routine returns a Tcl string object, 
+** reference count set to 0, containing the text. If a translation
+** between iso8859 and UTF-8 is required, it is preformed.
+*/
+static Tcl_Obj *dbTextToObj(char const *zText){
+  Tcl_Obj *pVal;
+#ifdef UTF_TRANSLATION_NEEDED
+  Tcl_DString dCol;
+  Tcl_DStringInit(&dCol);
+  Tcl_ExternalToUtfDString(NULL, zText, -1, &dCol);
+  pVal = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1);
+  Tcl_DStringFree(&dCol);
+#else
+  pVal = Tcl_NewStringObj(zText, -1);
+#endif
+  return pVal;
+}
+
 /*
 ** The "sqlite" command below creates a new Tcl command for each
 ** connection it opens to an SQLite database.  This routine is invoked
@@ -777,7 +621,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     char const *zSql;
     char const *zLeft;
     sqlite3_stmt *pStmt;
-    Tcl_Obj *pRet = 0;
+
+    Tcl_Obj *pRet = Tcl_NewObj();
+    Tcl_IncrRefCount(pRet);
 
     if( objc!=5 && objc!=3 ){
       Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?");
@@ -790,7 +636,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
       int i;
   
       if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){
-        Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_STATIC);
+        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
         rc = TCL_ERROR;
         break;
       }
@@ -801,7 +647,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
 
         for(i=0; i<sqlite3_column_count(pStmt); i++){
           Tcl_ListObjAppendElement(interp, pColList,
-              Tcl_NewStringObj(sqlite3_column_name(pStmt, i), -1)
+              dbTextToObj(sqlite3_column_name(pStmt, i))
           );
         }
         Tcl_ObjSetVar2(interp,objv[3],Tcl_NewStringObj("*",-1),pColList,0);
@@ -813,14 +659,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
           
           /* Set pVal to contain the i'th column of this row. */
           if( SQLITE3_BLOB!=sqlite3_column_type(pStmt, i) ){
-            pVal = Tcl_NewStringObj(sqlite3_column_text(pStmt, i), -1);
+            pVal = dbTextToObj(sqlite3_column_text(pStmt, i));
           }else{
             int bytes = sqlite3_column_bytes(pStmt, i);
             pVal = Tcl_NewByteArrayObj(sqlite3_column_blob(pStmt, i), bytes);
           }
   
           if( objc==5 ){
-            Tcl_Obj *pName = Tcl_NewStringObj(sqlite3_column_name(pStmt, i), -1);
+            Tcl_Obj *pName = dbTextToObj(sqlite3_column_name(pStmt, i));
             Tcl_IncrRefCount(pName);
             if( !strcmp("", Tcl_GetString(objv[3])) ){
               Tcl_ObjSetVar2(interp, pName, 0, pVal, 0);
@@ -829,10 +675,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
             }
             Tcl_DecrRefCount(pName);
           }else{
-            if( !pRet ){
-              pRet = Tcl_NewObj();
-              Tcl_IncrRefCount(pRet);
-            }
             Tcl_ListObjAppendElement(interp, pRet, pVal);
           }
         }
@@ -848,7 +690,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
       }
   
       if( pStmt && SQLITE_OK!=sqlite3_errcode(pDb->db) ){
-        Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_STATIC);
+        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
         rc = TCL_ERROR;
         break;
       }
@@ -857,83 +699,13 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
       zSql = zLeft;
     }
 
-    if( rc==TCL_OK && pRet ){
+    if( rc==TCL_OK ){
       Tcl_SetObjResult(interp, pRet);
-      Tcl_DecrRefCount(pRet);
     }
+    Tcl_DecrRefCount(pRet);
 
     break;
   }
-#if 0
-  case DB_EVAL: {
-    CallbackData cbData;
-    char *zErrMsg;
-    char *zSql;
-#ifdef UTF_TRANSLATION_NEEDED
-    Tcl_DString dSql;
-    int i;
-#endif
-
-    if( objc!=5 && objc!=3 ){
-      Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?");
-      return TCL_ERROR;
-    }
-    pDb->interp = interp;
-    zSql = Tcl_GetStringFromObj(objv[2], 0);
-#ifdef UTF_TRANSLATION_NEEDED
-    Tcl_DStringInit(&dSql);
-    Tcl_UtfToExternalDString(NULL, zSql, -1, &dSql);
-    zSql = Tcl_DStringValue(&dSql);
-#endif
-    Tcl_IncrRefCount(objv[2]);
-    if( objc==5 ){
-      cbData.interp = interp;
-      cbData.once = 1;
-      cbData.zArray = Tcl_GetStringFromObj(objv[3], 0);
-      cbData.pCode = objv[4];
-      cbData.tcl_rc = TCL_OK;
-      cbData.nColName = 0;
-      cbData.azColName = 0;
-      zErrMsg = 0;
-      Tcl_IncrRefCount(objv[3]);
-      Tcl_IncrRefCount(objv[4]);
-      rc = sqlite3_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg);
-      Tcl_DecrRefCount(objv[4]);
-      Tcl_DecrRefCount(objv[3]);
-      if( cbData.tcl_rc==TCL_BREAK ){ cbData.tcl_rc = TCL_OK; }
-    }else{
-      Tcl_Obj *pList = Tcl_NewObj();
-      cbData.tcl_rc = TCL_OK;
-      rc = sqlite3_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg);
-      Tcl_SetObjResult(interp, pList);
-    }
-    pDb->rc = rc;
-    if( rc==SQLITE_ABORT ){
-      if( zErrMsg ) free(zErrMsg);
-      rc = cbData.tcl_rc;
-    }else if( zErrMsg ){
-      Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
-      free(zErrMsg);
-      rc = TCL_ERROR;
-    }else if( rc!=SQLITE_OK ){
-      Tcl_AppendResult(interp, sqlite3_error_string(rc), 0);
-      rc = TCL_ERROR;
-    }else{
-    }
-    Tcl_DecrRefCount(objv[2]);
-#ifdef UTF_TRANSLATION_NEEDED
-    Tcl_DStringFree(&dSql);
-    if( objc==5 && cbData.azColName ){
-      for(i=0; i<cbData.nColName; i++){
-        if( cbData.azColName[i] ) free(cbData.azColName[i]);
-      }
-      free(cbData.azColName);
-      cbData.azColName = 0;
-    }
-#endif
-    return rc;
-  }
-#endif
 
   /*
   **     $db function NAME SCRIPT
index e224db6f5345693124a4d133ebc8dc46ec64676e..e9e31b2db6d1519d82ad4333371999ef3021b82f 100644 (file)
@@ -40,7 +40,8 @@ void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
 */
 void sqlite3BeginTrigger(
   Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */
-  Token *pName,       /* The name of the trigger */
+  Token *pName1,      /* The name of the trigger */
+  Token *pName2,      /* The name of the trigger */
   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 */
@@ -49,76 +50,100 @@ void sqlite3BeginTrigger(
   Expr *pWhen,        /* WHEN clause */
   int isTemp          /* True if the TEMPORARY keyword is present */
 ){
-  Trigger *nt;
-  Table   *tab;
+  Trigger *pTrigger;
+  Table *pTab;
   char *zName = 0;        /* Name of the trigger */
   sqlite *db = pParse->db;
-  int iDb;                /* When database to store the trigger in */
+  int iDb;                /* The database to store the trigger in */
+  Token *pName;           /* The unqualified db name */
   DbFixer sFix;
 
-  /* Check that: 
-  ** 1. the trigger name does not already exist.
-  ** 2. the table (or view) does exist in the same database as the trigger.
-  ** 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.
+  if( isTemp ){
+    /* If TEMP was specified, then the trigger name may not be qualified. */
+    if( pName2 && pName2->n>0 ){
+      sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
+      goto trigger_cleanup;
+    }
+    iDb = 1;
+    pName = pName1;
+  }else{
+    /* Figure out the db that the the trigger will be created in */
+    iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
+    if( iDb<0 ){
+      goto trigger_cleanup;
+    }
+  }
+
+  /* If the trigger name was unqualified, and the table is a temp table,
+  ** then set iDb to 1 to create the trigger in the temporary database.
+  ** If sqlite3SrcListLookup() returns 0, indicating the table does not
+  ** exist, the error is caught by the block below.
   */
+  pTab = sqlite3SrcListLookup(pParse, pTableName);
+  if( pName2->n==0 && pTab && pTab->iDb==1 ){
+    iDb = 1;
+  }
+
+  /* Ensure the table name matches database name and that the table exists */
   if( sqlite3_malloc_failed ) goto trigger_cleanup;
   assert( pTableName->nSrc==1 );
-  if( db->init.busy
-   && sqlite3FixInit(&sFix, pParse, db->init.iDb, "trigger", pName)
-   && sqlite3FixSrcList(&sFix, pTableName)
-  ){
-    goto trigger_cleanup;
-  }
-  tab = sqlite3SrcListLookup(pParse, pTableName);
-  if( !tab ){
+  if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && 
+      sqlite3FixSrcList(&sFix, pTableName) ){
     goto trigger_cleanup;
   }
-  iDb = isTemp ? 1 : tab->iDb;
-  if( iDb>=2 && !db->init.busy ){
-    sqlite3ErrorMsg(pParse, "triggers may not be added to auxiliary "
-       "database %s", db->aDb[tab->iDb].zName);
+  pTab = sqlite3SrcListLookup(pParse, pTableName);
+  if( !pTab ){
+    /* The table does not exist. */
     goto trigger_cleanup;
   }
 
+  /* Check that no trigger of the specified name exists */
   zName = sqliteStrNDup(pName->z, pName->n);
   sqlite3Dequote(zName);
   if( sqlite3HashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){
     sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
     goto trigger_cleanup;
   }
-  if( sqlite3StrNICmp(tab->zName, "sqlite_", 7)==0 ){
+
+  /* Do not create a trigger on a system table */
+  if( (iDb!=1 && sqlite3StrICmp(pTab->zName, MASTER_NAME)==0) || 
+      (iDb==1 && sqlite3StrICmp(pTab->zName, TEMP_MASTER_NAME)==0) 
+  ){
     sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
     pParse->nErr++;
     goto trigger_cleanup;
   }
-  if( tab->pSelect && tr_tm != TK_INSTEAD ){
+
+  /* INSTEAD of triggers are only for views and views only support INSTEAD
+  ** of triggers.
+  */
+  if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
     sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", 
         (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
     goto trigger_cleanup;
   }
-  if( !tab->pSelect && tr_tm == TK_INSTEAD ){
+  if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
     sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
         " trigger on table: %S", pTableName, 0);
     goto trigger_cleanup;
   }
+
 #ifndef SQLITE_OMIT_AUTHORIZATION
   {
     int code = SQLITE_CREATE_TRIGGER;
-    const char *zDb = db->aDb[tab->iDb].zName;
+    const char *zDb = db->aDb[pTab->iDb].zName;
     const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
-    if( tab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
-    if( sqlite3AuthCheck(pParse, code, zName, tab->zName, zDbTrig) ){
+    if( pTab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
+    if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
       goto trigger_cleanup;
     }
-    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0, zDb)){
+    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb), 0, zDb)){
       goto trigger_cleanup;
     }
   }
 #endif
 
-  /* INSTEAD OF triggers can only appear on views and BEGIN triggers
+  /* INSTEAD OF triggers can only appear on views and BEFORE triggers
   ** cannot appear on views.  So we might as well translate every
   ** INSTEAD OF trigger into a BEFORE trigger.  It simplifies code
   ** elsewhere.
@@ -128,22 +153,22 @@ void sqlite3BeginTrigger(
   }
 
   /* Build the Trigger object */
-  nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
-  if( nt==0 ) goto trigger_cleanup;
-  nt->name = zName;
+  pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger));
+  if( pTrigger==0 ) goto trigger_cleanup;
+  pTrigger->name = zName;
   zName = 0;
-  nt->table = sqliteStrDup(pTableName->a[0].zName);
+  pTrigger->table = sqliteStrDup(pTableName->a[0].zName);
   if( sqlite3_malloc_failed ) goto trigger_cleanup;
-  nt->iDb = iDb;
-  nt->iTabDb = tab->iDb;
-  nt->op = op;
-  nt->tr_tm = tr_tm;
-  nt->pWhen = sqlite3ExprDup(pWhen);
-  nt->pColumns = sqlite3IdListDup(pColumns);
-  nt->foreach = foreach;
-  sqlite3TokenCopy(&nt->nameToken,pName);
+  pTrigger->iDb = iDb;
+  pTrigger->iTabDb = pTab->iDb;
+  pTrigger->op = op;
+  pTrigger->tr_tm = tr_tm;
+  pTrigger->pWhen = sqlite3ExprDup(pWhen);
+  pTrigger->pColumns = sqlite3IdListDup(pColumns);
+  pTrigger->foreach = foreach;
+  sqlite3TokenCopy(&pTrigger->nameToken,pName);
   assert( pParse->pNewTrigger==0 );
-  pParse->pNewTrigger = nt;
+  pParse->pNewTrigger = pTrigger;
 
 trigger_cleanup:
   sqliteFree(zName);
@@ -198,7 +223,7 @@ void sqlite3FinishTrigger(
     /* Make an entry in the sqlite_master table */
     v = sqlite3GetVdbe(pParse);
     if( v==0 ) goto triggerfinish_cleanup;
-    sqlite3BeginWriteOperation(pParse, 0, 0);
+    sqlite3BeginWriteOperation(pParse, 0, nt->iDb);
     sqlite3OpenMasterTable(v, nt->iDb);
     addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
     sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); 
@@ -425,11 +450,6 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
   sqlite *db = pParse->db;
 
   assert( pTrigger->iDb<db->nDb );
-  if( pTrigger->iDb>=2 ){
-    sqlite3ErrorMsg(pParse, "triggers may not be removed from "
-       "auxiliary database %s", db->aDb[pTrigger->iDb].zName);
-    return;
-  }
   pTable = sqlite3FindTable(db, pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
   assert(pTable);
   assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 );
@@ -438,7 +458,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
     int code = SQLITE_DROP_TRIGGER;
     const char *zDb = db->aDb[pTrigger->iDb].zName;
     const char *zTab = SCHEMA_TABLE(pTrigger->iDb);
-    if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
+    if( pTrigger->iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
     if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
       sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
       return;
@@ -462,7 +482,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
       { OP_Next,       0, ADDR(1),  0}, /* 8 */
     };
 
-    sqlite3BeginWriteOperation(pParse, 0, 0);
+    sqlite3BeginWriteOperation(pParse, 0, pTrigger->iDb);
     sqlite3OpenMasterTable(v, pTrigger->iDb);
     base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
     sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0);
index 22b61be7f8f9b0f60cdef71374755471ffc2c380..6199d02dcce931c01ba01f0ea96d8402f5b2a497 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.345 2004/05/28 16:00:22 drh Exp $
+** $Id: vdbe.c,v 1.346 2004/05/29 02:37:19 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -2142,12 +2142,12 @@ case OP_MakeRecord: {
   pTos++;
   pTos->n = nByte;
   if( nByte<=sizeof(zTemp) ){
-    assert( zNewRecord==zTemp );
+    assert( zNewRecord==(unsigned char *)zTemp );
     pTos->z = pTos->zShort;
     memcpy(pTos->zShort, zTemp, nByte);
     pTos->flags = MEM_Blob | MEM_Short;
   }else{
-    assert( zNewRecord!=zTemp );
+    assert( zNewRecord!=(unsigned char *)zTemp );
     pTos->z = zNewRecord;
     pTos->flags = MEM_Blob | MEM_Dyn;
   }
index 817a34dbda51e28ceff8fb8b0472394324f84600..85957d8de813969c6b4b500c07aadcc185825b4e 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this script is testing the ATTACH and DETACH commands
 # and related functionality.
 #
-# $Id: attach.test,v 1.16 2004/05/11 09:57:35 drh Exp $
+# $Id: attach.test,v 1.17 2004/05/29 02:37:20 danielk1977 Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -488,7 +488,7 @@ do_test attach-5.1 {
       SELECT 'no-op';
     END;
   } db2
-} {1 {triggers may not be added to auxiliary database orig}}
+} {1 {trigger r1 cannot reference objects in database orig}}
 do_test attach-5.2 {
   catchsql {
     CREATE TABLE t5(x,y);
index a3c8352f8506eb0650cadaddbb4197836e3afe10..c75caa7d35c3eab6187285a9d4ccd1bbfcd1b675 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this script is testing the ATTACH and DETACH commands
 # and schema changes to attached databases.
 #
-# $Id: attach3.test,v 1.3 2004/05/28 12:33:32 danielk1977 Exp $
+# $Id: attach3.test,v 1.4 2004/05/29 02:37:20 danielk1977 Exp $
 #
 
 
@@ -63,7 +63,7 @@ do_test attach3-1.5 {
 } {1 2}
 
 # Create an index on the auxilary database table.
-do_test attach4-2.1 {
+do_test attach3-2.1 {
   execsql {
     CREATE INDEX aux.i1 on t3(e);
   }
@@ -71,31 +71,31 @@ do_test attach4-2.1 {
 execsql {
   pragma vdbe_trace = off;
 }
-do_test attach4-2.2 {
+do_test attach3-2.2 {
   execsql {
     SELECT * FROM sqlite_master WHERE name = 'i1';
   }
 } {}
-do_test attach4-2.3 {
+do_test attach3-2.3 {
   execsql {
     SELECT * FROM aux.sqlite_master WHERE name = 'i1';
   }
 } {index i1 t3 5 {CREATE INDEX i1 on t3(e)}}
 
 # Drop the index on the aux database table.
-do_test attach4-3.1 {
+do_test attach3-3.1 {
   execsql {
     DROP INDEX aux.i1;
     SELECT * FROM aux.sqlite_master WHERE name = 'i1';
   }
 } {}
-do_test attach4-3.2 {
+do_test attach3-3.2 {
   execsql {
     CREATE INDEX aux.i1 on t3(e);
     SELECT * FROM aux.sqlite_master WHERE name = 'i1';
   }
 } {index i1 t3 5 {CREATE INDEX i1 on t3(e)}}
-do_test attach4-3.3 {
+do_test attach3-3.3 {
   execsql {
     DROP INDEX i1;
     SELECT * FROM aux.sqlite_master WHERE name = 'i1';
@@ -103,20 +103,20 @@ do_test attach4-3.3 {
 } {}
 
 # Drop tables t1 and t2 in the auxilary database.
-do_test attach4-4.1 {
+do_test attach3-4.1 {
   execsql {
     DROP TABLE aux.t1;
     SELECT name FROM aux.sqlite_master;
   }
 } {t2 t3}
-do_test attach4-4.2 {
+do_test attach3-4.2 {
   # This will drop main.t2
   execsql {
     DROP TABLE t2;
     SELECT name FROM aux.sqlite_master;
   }
 } {t2 t3}
-do_test attach4-4.3 {
+do_test attach3-4.3 {
   execsql {
     DROP TABLE t2;
     SELECT name FROM aux.sqlite_master;
@@ -124,17 +124,17 @@ do_test attach4-4.3 {
 } {t3}
 
 # Create a view in the auxilary database.
-do_test attach4-5.1 {
+do_test attach3-5.1 {
   execsql {
     CREATE VIEW aux.v1 AS SELECT * FROM t3;
   }
 } {}
-do_test attach4-5.2 {
+do_test attach3-5.2 {
   execsql {
     SELECT * FROM aux.sqlite_master WHERE name = 'v1';
   }
 } {view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t3}}
-do_test attach4-5.3 {
+do_test attach3-5.3 {
   execsql {
     INSERT INTO aux.t3 VALUES('hello', 'world');
     SELECT * FROM v1;
@@ -142,17 +142,52 @@ do_test attach4-5.3 {
 } {1 2 hello world}
 
 # Drop the view 
-do_test attach4-6.1 {
+do_test attach3-6.1 {
   execsql {
     DROP VIEW aux.v1;
   }
 } {}
-do_test attach4-5.2 {
+do_test attach3-6.2 {
   execsql {
     SELECT * FROM aux.sqlite_master WHERE name = 'v1';
   }
 } {}
 
+# Create a trigger in the auxilary database.
+do_test attach3-7.1 {
+  execsql {
+    CREATE TRIGGER aux.tr1 AFTER INSERT ON t3 BEGIN
+      INSERT INTO t3 VALUES(new.e*2, new.f*2);
+    END;
+  }
+} {}
+do_test attach3-7.2 {
+  execsql {
+    DELETE FROM t3;
+    INSERT INTO t3 VALUES(10, 20);
+    SELECT * FROM t3;
+  }
+} {10 20 20 40}
+do_test attach3-5.3 {
+  execsql {
+    SELECT * FROM aux.sqlite_master WHERE name = 'tr1';
+  }
+} {trigger tr1 t3 0 {CREATE TRIGGER aux.tr1 AFTER INSERT ON t3 BEGIN
+      INSERT INTO t3 VALUES(new.e*2, new.f*2);
+    END}}
+
+# Drop the trigger 
+do_test attach3-8.1 {
+  execsql {
+    DROP TRIGGER aux.tr1;
+  }
+} {}
+do_test attach3-8.2 {
+  execsql {
+    SELECT * FROM aux.sqlite_master WHERE name = 'tr1';
+  }
+} {}
+
 finish_test
 
 
index b55ca12378c9afa11a87e9f010aafed8f07b64a0..7c23f874dd44dd56eed0d2377e95f6b5b39f4abf 100644 (file)
@@ -36,7 +36,7 @@ do_test trigger1-1.1.2 {
        SELECT * from sqlite_master;
      END;
    } 
-} {1 {no such table: no_such_table}}
+} {1 {no such table: main.no_such_table}}
 do_test trigger1-1.1.2 {
    catchsql {
      CREATE TEMP TRIGGER trig UPDATE ON no_such_table BEGIN
@@ -166,7 +166,7 @@ do_test trigger1-1.12 {
       delete from t1 WHERE a=old.a+2;
     end;
   }
-} {1 {cannot create INSTEAD OF trigger on table: t1}}
+} {1 {cannot create INSTEAD OF trigger on table: main.t1}}
 # Ensure that we cannot create BEFORE triggers on views
 do_test trigger1-1.13 {
   catchsql {
@@ -175,7 +175,7 @@ do_test trigger1-1.13 {
       delete from t1 WHERE a=old.a+2;
     end;
   }
-} {1 {cannot create BEFORE trigger on view: v1}}
+} {1 {cannot create BEFORE trigger on view: main.v1}}
 # Ensure that we cannot create AFTER triggers on views
 do_test trigger1-1.14 {
   catchsql {
@@ -185,7 +185,7 @@ do_test trigger1-1.14 {
       delete from t1 WHERE a=old.a+2;
     end;
   }
-} {1 {cannot create AFTER trigger on view: v1}}
+} {1 {cannot create AFTER trigger on view: main.v1}}
 
 # Check for memory leaks in the trigger parser
 #