]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Prepared statements now work with CREATE and DROP. All tests pass.
authordrh <drh@noemail.net>
Sat, 24 Jul 2004 17:38:29 +0000 (17:38 +0000)
committerdrh <drh@noemail.net>
Sat, 24 Jul 2004 17:38:29 +0000 (17:38 +0000)
No memory leaks. (CVS 1866)

FossilOrigin-Name: ebdb661e0eefe123c422d3c1c371e325bb6cf673

manifest
manifest.uuid
src/build.c
src/insert.c
src/sqliteInt.h
src/trigger.c
src/vdbe.c
test/misc4.test
test/pragma.test

index bda594b98f2204ba5022bc84e2947711c3609a3c..13627fa0c40c4b747b4742cc49f8bcc0792d4495 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\smore\sproblems\swith\sdeferred\sexecution\sof\sCREATE.\s\sStill\sneed\sto\sdo\sDROP.\nThere\sis\snow\sa\smemory\sleak.\s(CVS\s1865)
-D 2004-07-24T14:35:58
+C Prepared\sstatements\snow\swork\swith\sCREATE\sand\sDROP.\s\sAll\stests\spass.\nNo\smemory\sleaks.\s(CVS\s1866)
+D 2004-07-24T17:38:29
 F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -29,7 +29,7 @@ F src/attach.c 784456629b3d7e50e4691f496700658fd1f16441
 F src/auth.c 60db23b98bb94c8b0178180faaf49dc116674217
 F src/btree.c edf4ece708350dec7f28ebd4620c6d33afe6993a
 F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029
-F src/build.c 3075ca2e66d6da3f98840d18f6e2bc4d15ced569
+F src/build.c 7d2981666b6d0c530766dbf1284aabc328e1ec71
 F src/date.c e1bb384a7856c18dce9cadb0afbe6934ba5ddb00
 F src/delete.c e81545e546f6bc87d7508a93a09ca70695265af3
 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
@@ -37,7 +37,7 @@ F src/expr.c a4e8ac69c872f86bc207364be0e32d0638f61e90
 F src/func.c b163fb49efec999eb7bf982f7de5b9be388301f3
 F src/hash.c f0a2f22c2a7052d67053b5f4690ea3010bb3fb9f
 F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
-F src/insert.c d99ffe87e1e1397f4233afcd06841d52d6b17b18
+F src/insert.c bedcba371401395033a1a1c578d8fdc3fec87bec
 F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
 F src/main.c 49ea4a45223a002d06b5a4a5db36327acafc1779
 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
@@ -60,7 +60,7 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
 F src/select.c aefda626660086addca4ce85c34aeef5d0f44c25
 F src/shell.c 93c96c847228c02fb84bb381875d87ee71fbbeb4
 F src/sqlite.h.in 80de11cde2c9f78eff4dab0aad1eb5196d6e2a3f
-F src/sqliteInt.h 31d5887a802b5f218f604a1fd44fe989873cf2bc
+F src/sqliteInt.h d2aebb8c8941bc9cab4506de313f304d358c93b8
 F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49
 F src/tclsqlite.c 3ce001b3c301876a9c8163472077a4c10e0d49f3
 F src/test1.c ef00096c283ccfec1b2ae5fdaccb85fb06e24281
@@ -69,12 +69,12 @@ F src/test3.c 94d0a2a90bccd85802488cb42c69ec8afd2e4646
 F src/test4.c a921a69821fd30209589228e64f94e9f715b6fe2
 F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
 F src/tokenize.c bc7a80e4cf54f42ea4b030c62261c4243133af84
-F src/trigger.c 6aaf6d79cc2157c70a06031dd1531707d644cfb4
+F src/trigger.c 360cf8f12edd4eb3a8a2895b136aac238c3cf44e
 F src/update.c b66b1896c9da54678ba3eff2bf0b4d291a95986a
 F src/utf.c f03535db72bfa09e24202ccdd245f21d2fc65f0a
 F src/util.c 2aacc79b7bf5df5859813dafd3bf3258f67a5234
 F src/vacuum.c 23ec8c5f3134c6315f883d648fa63b72d8c3ead3
-F src/vdbe.c cad659a06b30c03b870c4a00a828d78f7a69bbcf
+F src/vdbe.c f40f4ca4d9a7ba7c330e5673419f32dd3512547c
 F src/vdbe.h 75b241c02431b9c0f16eaa9cdbb34146c6287f52
 F src/vdbeInt.h 3d8e08c54dcb5ca2169db8bb3a37b81a12efaecd
 F src/vdbeapi.c c5c6d8f162a9581dde497b1a4034f9a0bf54c355
@@ -140,13 +140,13 @@ F test/minmax.test 6513f9a1bb85fd35ff72b34b7b6634fad6b1e69c
 F test/misc1.test 72768ec8cabc952a4cfcddca43d566f9e0bce899
 F test/misc2.test 703734f5817215ca54e364833b3bf5ff36fcc21e
 F test/misc3.test eb488314990bfc0959221a1acc465013238bf168
-F test/misc4.test b31a0a08077038b03a9320fd5d9731093da708a8
+F test/misc4.test 9f8ab4896dd627f5f9ba893a7b57c9f0a95dfd64
 F test/misuse.test 2a64ce711419f2fd12806ed95af930fd4e7bb8f3
 F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
 F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721
 F test/pager.test 059cc5c58d3b5a851343dff8c56cf7286425d03a
 F test/pager2.test 55469c7c1c1a54d6b32d7b3cc99001e90101a1ce
-F test/pragma.test f7414c1d902688825ca11f7f5e03628704d903b5
+F test/pragma.test 66a66b7f3b273b93325c9a5794acb418f52fdcbf
 F test/printf.test 428ad9be92963b68ba222dac4c19724cc4e304ea
 F test/progress.test 76c722f090b1ccb575e7e4e203a71608c5763beb x
 F test/quick.test 5bb4afdb204c57329c86fa11f3f0a5296675fd7f
@@ -240,7 +240,7 @@ F www/tclsqlite.tcl 06a86cba4d7fc88e2bcd633b57702d3d16abebb5
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 49b991492496e104f5eca620a5d465a742b7ff3a
-R 360d271fab96b9095f5b4369737eb03f
+P 6db3f122aad25b5226670ce682b7263d55c0d301
+R 987e7be0c6defafac7646ce8c68bde8c
 U drh
-Z e2b908232fc8aa315ba06b1f36120ee8
+Z 4bf2f79f0d58a1ba844cc564cece29c1
index 32b7dfe7ebe9db138bff6e206babbabfd3779108..28707535220223df52168b384a299001da3b14be 100644 (file)
@@ -1 +1 @@
-6db3f122aad25b5226670ce682b7263d55c0d301
\ No newline at end of file
+ebdb661e0eefe123c422d3c1c371e325bb6cf673
\ No newline at end of file
index 4494c43a0d25338e4579f7e6bfce68c0e75e6116..56a59d4df1649d639e5bad3ee4da840524937e65 100644 (file)
@@ -23,7 +23,7 @@
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.242 2004/07/24 14:35:58 drh Exp $
+** $Id: build.c,v 1.243 2004/07/24 17:38:29 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -191,6 +191,14 @@ Index *sqlite3FindIndex(sqlite *db, const char *zName, const char *zDb){
   return p;
 }
 
+/*
+** Reclaim the memory used by an index
+*/
+static void freeIndex(Index *p){
+  sqliteFree(p->zColAff);
+  sqliteFree(p);
+}
+
 /*
 ** Remove the given index from the index hash table, and free
 ** its memory structures.
@@ -209,10 +217,7 @@ static void sqliteDeleteIndex(sqlite *db, Index *p){
     sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
                      strlen(pOld->zName)+1, pOld);
   }
-  if( p->zColAff ){
-    sqliteFree(p->zColAff);
-  }
-  sqliteFree(p);
+  freeIndex(p);
 }
 
 /*
@@ -220,17 +225,25 @@ static void sqliteDeleteIndex(sqlite *db, Index *p){
 ** the index from the index hash table and free its memory
 ** structures.
 */
-void sqlite3UnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
-  if( pIndex->pTable->pIndex==pIndex ){
-    pIndex->pTable->pIndex = pIndex->pNext;
-  }else{
-    Index *p;
-    for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
-    if( p && p->pNext==pIndex ){
-      p->pNext = pIndex->pNext;
+void sqlite3UnlinkAndDeleteIndex(sqlite *db, int iDb, const char *zIdxName){
+  Index *pIndex;
+  int len;
+
+  len = strlen(zIdxName);
+  pIndex = sqlite3HashInsert(&db->aDb[iDb].idxHash, zIdxName, len+1, 0);
+  if( pIndex ){
+    if( pIndex->pTable->pIndex==pIndex ){
+      pIndex->pTable->pIndex = pIndex->pNext;
+    }else{
+      Index *p;
+      for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
+      if( p && p->pNext==pIndex ){
+        p->pNext = pIndex->pNext;
+      }
     }
+    freeIndex(pIndex);
   }
-  sqliteDeleteIndex(db, pIndex);
+  db->flags |= SQLITE_InternChanges;
 }
 
 /*
@@ -328,6 +341,23 @@ void sqlite3CommitInternalChanges(sqlite *db){
   db->flags &= ~SQLITE_InternChanges;
 }
 
+/*
+** Clear the column names from a table or view.
+*/
+static void sqliteResetColumnNames(Table *pTable){
+  int i;
+  Column *pCol;
+  assert( pTable!=0 );
+  for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
+    sqliteFree(pCol->zName);
+    sqliteFree(pCol->zDflt);
+    sqliteFree(pCol->zType);
+  }
+  sqliteFree(pTable->aCol);
+  pTable->aCol = 0;
+  pTable->nCol = 0;
+}
+
 /*
 ** Remove the memory data structures associated with the given
 ** Table.  No changes are made to disk by this routine.
@@ -344,7 +374,6 @@ void sqlite3CommitInternalChanges(sqlite *db){
 ** unlinked.
 */
 void sqlite3DeleteTable(sqlite *db, Table *pTable){
-  int i;
   Index *pIndex, *pNext;
   FKey *pFKey, *pNextFKey;
 
@@ -371,17 +400,9 @@ void sqlite3DeleteTable(sqlite *db, Table *pTable){
 
   /* Delete the Table structure itself.
   */
-  for(i=0; i<pTable->nCol; i++){
-    Column *pCol = &pTable->aCol[i];
-    sqliteFree(pCol->zName);
-    sqliteFree(pCol->zDflt);
-    sqliteFree(pCol->zType);
-  }
+  sqliteResetColumnNames(pTable);
   sqliteFree(pTable->zName);
-  sqliteFree(pTable->aCol);
-  if( pTable->zColAff ){
-    sqliteFree(pTable->zColAff);
-  }
+  sqliteFree(pTable->zColAff);
   sqlite3SelectDelete(pTable->pSelect);
   sqliteFree(pTable);
 }
@@ -390,26 +411,32 @@ void sqlite3DeleteTable(sqlite *db, Table *pTable){
 ** Unlink the given table from the hash tables and the delete the
 ** table structure with all its indices and foreign keys.
 */
-static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
-  Table *pOld;
+void sqlite3UnlinkAndDeleteTable(sqlite *db, int iDb, const char *zTabName){
+  Table *p;
   FKey *pF1, *pF2;
-  int i = p->iDb;
+  Db *pDb;
+
   assert( db!=0 );
-  pOld = sqlite3HashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1,0);
-  assert( pOld==0 || pOld==p );
-  for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
-    int nTo = strlen(pF1->zTo) + 1;
-    pF2 = sqlite3HashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
-    if( pF2==pF1 ){
-      sqlite3HashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
-    }else{
-      while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
-      if( pF2 ){
-        pF2->pNextTo = pF1->pNextTo;
+  assert( iDb>=0 && iDb<db->nDb );
+  assert( zTabName && zTabName[0] );
+  pDb = &db->aDb[iDb];
+  p = sqlite3HashInsert(&pDb->tblHash, zTabName, strlen(zTabName)+1, 0);
+  if( p ){
+    for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
+      int nTo = strlen(pF1->zTo) + 1;
+      pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo);
+      if( pF2==pF1 ){
+        sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo);
+      }else{
+        while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
+        if( pF2 ){
+          pF2->pNextTo = pF1->pNextTo;
+        }
       }
     }
+    sqlite3DeleteTable(db, p);
   }
-  sqlite3DeleteTable(db, p);
+  db->flags |= SQLITE_InternChanges;
 }
 
 /*
@@ -1530,28 +1557,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
   return nErr;  
 }
 
-/*
-** Clear the column names from the VIEW pTable.
-**
-** This routine is called whenever any other table or view is modified.
-** The view passed into this routine might depend directly or indirectly
-** on the modified or deleted table so we need to clear the old column
-** names so that they will be recomputed.
-*/
-static void sqliteViewResetColumnNames(Table *pTable){
-  int i;
-  Column *pCol;
-  assert( pTable!=0 && pTable->pSelect!=0 );
-  for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
-    sqliteFree(pCol->zName);
-    sqliteFree(pCol->zDflt);
-    sqliteFree(pCol->zType);
-  }
-  sqliteFree(pTable->aCol);
-  pTable->aCol = 0;
-  pTable->nCol = 0;
-}
-
 /*
 ** Clear the column names from every VIEW in database idx.
 */
@@ -1561,7 +1566,7 @@ static void sqliteViewResetAll(sqlite *db, int idx){
   for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
     Table *pTab = sqliteHashData(i);
     if( pTab->pSelect ){
-      sqliteViewResetColumnNames(pTab);
+      sqliteResetColumnNames(pTab);
     }
   }
   DbClearProperty(db, idx, DB_UnresetViews);
@@ -1660,11 +1665,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
     while( pTrigger ){
       assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 );
       sqlite3DropTriggerPtr(pParse, pTrigger, 1);
-      if( pParse->explain ){
-        pTrigger = pTrigger->pNext;
-      }else{
-        pTrigger = pTab->pTrigger;
-      }
+      pTrigger = pTrigger->pNext;
     }
 
     /* Drop all SQLITE_MASTER table and index entries that refer to the
@@ -1685,18 +1686,9 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
         sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
       }
     }
+    sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
     sqlite3EndWriteOperation(pParse);
   }
-
-  /* Delete the in-memory description of the table.
-  **
-  ** Exception: if the SQL statement began with the EXPLAIN keyword,
-  ** then no changes should be made.
-  */
-  if( !pParse->explain ){
-    sqliteUnlinkAndDeleteTable(db, pTab);
-    db->flags |= SQLITE_InternChanges;
-  }
   sqliteViewResetAll(db, iDb);
 
 exit_drop_table:
@@ -2192,7 +2184,9 @@ void sqlite3CreateIndex(
 
   /* Clean up before exiting */
 exit_create_index:
-  if( pIndex ) sqliteFree(pIndex);
+  if( pIndex ){
+    freeIndex(pIndex);
+  }
   sqlite3ExprListDelete(pList);
   sqlite3SrcListDelete(pTblName);
   sqliteFree(zName);
@@ -2261,16 +2255,10 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
     sqlite3ChangeCookie(db, v, pIndex->iDb);
     sqlite3VdbeAddOp(v, OP_Close, 0, 0);
     sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
+    sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0);
     sqlite3EndWriteOperation(pParse);
   }
 
-  /* Delete the in-memory description of this index.
-  */
-  if( !pParse->explain ){
-    sqlite3UnlinkAndDeleteIndex(db, pIndex);
-    db->flags |= SQLITE_InternChanges;
-  }
-
 exit_drop_index:
   sqlite3SrcListDelete(pName);
 }
index 7a79df20e1f7c3a7a770c25630ac258dbea97cc9..7959947d15060e4ed32a7da1ed3c8cf10dbeb7b3 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.113 2004/06/21 06:50:28 danielk1977 Exp $
+** $Id: insert.c,v 1.114 2004/07/24 17:38:29 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -50,7 +50,7 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
     pIdx->zColAff[pIdx->nColumn] = '\0';
   }
  
-  sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, P3_STATIC);
+  sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, 0);
 }
 
 /*
@@ -91,7 +91,7 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
     pTab->zColAff = zColAff;
   }
 
-  sqlite3VdbeChangeP3(v, -1, pTab->zColAff, P3_STATIC);
+  sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0);
 }
 
 
index 94656ab414e3fcfec52673db1b0a42578941aa6f..39561702a3796589f6cc473c9fb16901d4be77d7 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.310 2004/07/24 14:35:58 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.311 2004/07/24 17:38:29 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1272,7 +1272,9 @@ void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
 Table *sqlite3FindTable(sqlite*,const char*, const char*);
 Table *sqlite3LocateTable(Parse*,const char*, const char*);
 Index *sqlite3FindIndex(sqlite*,const char*, const char*);
-void sqlite3UnlinkAndDeleteIndex(sqlite*,Index*);
+void sqlite3UnlinkAndDeleteTable(sqlite*,int,const char*);
+void sqlite3UnlinkAndDeleteIndex(sqlite*,int,const char*);
+void sqlite3UnlinkAndDeleteTrigger(sqlite*,int,const char*);
 void sqlite3Vacuum(Parse*, Token*);
 int sqlite3RunVacuum(char**, sqlite*);
 int sqlite3GlobCompare(const unsigned char*,const unsigned char*);
index 4ece0557b5fc7794cd4f6a3426b12f7a38aecb74..49bd0768cd21afe1b9c3c9a7a452367c55ded10c 100644 (file)
@@ -141,7 +141,7 @@ void sqlite3BeginTrigger(
     if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
       goto trigger_cleanup;
     }
-    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb), 0, zDb)){
+    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb),0,zDb)){
       goto trigger_cleanup;
     }
   }
@@ -213,13 +213,13 @@ void sqlite3FinishTrigger(
   if( !db->init.busy ){
     static VdbeOpList insertTrig[] = {
       { OP_NewRecno,   0, 0,  0          },
-      { OP_String8,     0, 0,  "trigger"  },
-      { OP_String8,     0, 0,  0          },  /* 2: trigger name */
-      { OP_String8,     0, 0,  0          },  /* 3: table name */
+      { OP_String8,    0, 0,  "trigger"  },
+      { OP_String8,    0, 0,  0          },  /* 2: trigger name */
+      { OP_String8,    0, 0,  0          },  /* 3: table name */
       { OP_Integer,    0, 0,  0          },
-      { OP_String8,     0, 0,  "CREATE TRIGGER "},
-      { OP_String8,     0, 0,  0          },  /* 6: SQL */
-      { OP_Concat8,     2, 0,  0          }, 
+      { OP_String8,    0, 0,  "CREATE TRIGGER "},
+      { OP_String8,    0, 0,  0          },  /* 6: SQL */
+      { OP_Concat8,    2, 0,  0          }, 
       { OP_MakeRecord, 5, 0,  "tttit"    },
       { OP_PutIntKey,  0, 0,  0          },
     };
@@ -239,10 +239,12 @@ void sqlite3FinishTrigger(
       sqlite3ChangeCookie(db, v, nt->iDb);
     }
     sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+    sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0, 
+       sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC);
     sqlite3EndWriteOperation(pParse);
   }
 
-  if( !pParse->explain ){
+  if( db->init.busy ){
     Table *pTab;
     sqlite3HashInsert(&db->aDb[nt->iDb].trigHash, 
                      nt->name, strlen(nt->name)+1, nt);
@@ -444,6 +446,15 @@ drop_trigger_cleanup:
   sqlite3SrcListDelete(pName);
 }
 
+/*
+** Return a pointer to the Table structure for the table that a trigger
+** is set on.
+*/
+static Table *tableOfTrigger(sqlite3 *db, Trigger *pTrigger){
+  return sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
+}
+
+
 /*
 ** 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
@@ -453,17 +464,19 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
   Table   *pTable;
   Vdbe *v;
   sqlite *db = pParse->db;
+  int iDb;
 
-  assert( pTrigger->iDb<db->nDb );
-  pTable = sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
+  iDb = pTrigger->iDb;
+  assert( iDb>=0 && iDb<db->nDb );
+  pTable = tableOfTrigger(db, pTrigger);
   assert(pTable);
-  assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 );
+  assert( pTable->iDb==iDb || iDb==1 );
 #ifndef SQLITE_OMIT_AUTHORIZATION
   {
     int code = SQLITE_DROP_TRIGGER;
-    const char *zDb = db->aDb[pTrigger->iDb].zName;
-    const char *zTab = SCHEMA_TABLE(pTrigger->iDb);
-    if( pTrigger->iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
+    const char *zDb = db->aDb[iDb].zName;
+    const char *zTab = SCHEMA_TABLE(iDb);
+    if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
     if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
       sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
       return;
@@ -487,20 +500,26 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
       { OP_Next,       0, ADDR(1),  0}, /* 8 */
     };
 
-    sqlite3BeginWriteOperation(pParse, 0, pTrigger->iDb);
-    sqlite3OpenMasterTable(v, pTrigger->iDb);
+    sqlite3BeginWriteOperation(pParse, 0, iDb);
+    sqlite3OpenMasterTable(v, iDb);
     base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
     sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0);
-    sqlite3ChangeCookie(db, v, pTrigger->iDb);
+    sqlite3ChangeCookie(db, v, iDb);
     sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+    sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0);
   }
+}
 
-  /*
-  ** If this is not an "explain", then delete the trigger structure.
-  */
-  if( !pParse->explain ){
-    const char *zName = pTrigger->name;
-    int nName = strlen(zName);
+/*
+** Remove a trigger from the hash tables of the sqlite* pointer.
+*/
+void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
+  Trigger *pTrigger;
+  int nName = strlen(zName);
+  pTrigger = sqlite3HashInsert(&(db->aDb[iDb].trigHash), zName, nName+1, 0);
+  if( pTrigger ){
+    Table *pTable = tableOfTrigger(db, pTrigger);
+    assert( pTable!=0 );
     if( pTable->pTrigger == pTrigger ){
       pTable->pTrigger = pTrigger->pNext;
     }else{
@@ -514,8 +533,8 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
       }
       assert(cc);
     }
-    sqlite3HashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
     sqlite3DeleteTrigger(pTrigger);
+    db->flags |= SQLITE_InternChanges;
   }
 }
 
index 390576d63965932614f581f3b45f0d6982c65835..aab44e30dc9c06b0b9f5b603f41e805345aea516 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.405 2004/07/24 14:35:59 drh Exp $
+** $Id: vdbe.c,v 1.406 2004/07/24 17:38:29 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -3764,6 +3764,42 @@ case OP_ParseSchema: {
   break;  
 }
 
+/* Opcode: DropTable P1 * P3
+**
+** Remove the internal (in-memory) data structures that describe
+** the table named P3 in database P1.  This is called after a table
+** is dropped in order to keep the internal representation of the
+** schema consistent with what is on disk.
+*/
+case OP_DropTable: {
+  sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3);
+  break;
+}
+
+/* Opcode: DropIndex P1 * P3
+**
+** Remove the internal (in-memory) data structures that describe
+** the index named P3 in database P1.  This is called after an index
+** is dropped in order to keep the internal representation of the
+** schema consistent with what is on disk.
+*/
+case OP_DropIndex: {
+  sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3);
+  break;
+}
+
+/* Opcode: DropTrigger P1 * P3
+**
+** Remove the internal (in-memory) data structures that describe
+** the trigger named P3 in database P1.  This is called after a trigger
+** is dropped in order to keep the internal representation of the
+** schema consistent with what is on disk.
+*/
+case OP_DropTrigger: {
+  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3);
+  break;
+}
+
 
 /* Opcode: IntegrityCk * P2 *
 **
index 23cd465fb91205b1ead428ac85840375752f9fe7..75c9e20c84d8833bd99ab216cfbdba5a88fa28c1 100644 (file)
@@ -13,7 +13,7 @@
 # This file implements tests for miscellanous features that were
 # left out of other test files.
 #
-# $Id: misc4.test,v 1.5 2004/07/24 14:35:59 drh Exp $
+# $Id: misc4.test,v 1.6 2004/07/24 17:38:30 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -64,11 +64,9 @@ do_test misc4-1.6 {
 # those statements are executed, try to use the tables, indices, views,
 # are triggers that were created.
 #
-if 0 {
 do_test misc4-2.1 {
   set stmt [sqlite3_prepare $DB {CREATE TABLE t3(x);} -1 TAIL]
   catchsql {
-pragma vdbe_trace=on;
     INSERT INTO t3 VALUES(1);
   }
 } {1 {no such table: t3}}
@@ -83,6 +81,6 @@ do_test misc4-2.4 {
     INSERT INTO t3 VALUES(1);
   }
 } {0 {}}
-}
+
 
 finish_test
index 9cea4c0c5cda8cfbe8f3ad91e6cdb90a5b6ccbe2..490851f1061bb7140892e0681f9d5051b4529ab3 100644 (file)
@@ -12,7 +12,7 @@
 #
 # This file implements tests for the PRAGMA command.
 #
-# $Id: pragma.test,v 1.16 2004/07/22 15:02:26 drh Exp $
+# $Id: pragma.test,v 1.17 2004/07/24 17:38:30 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -306,6 +306,7 @@ catchsql {COMMIT;}
 # Test schema-query pragmas
 #
 do_test pragma-6.1 {
+  set res {}
   foreach {idx name file} [execsql {pragma database_list}] {
     lappend res $idx $name
   }