1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Prepared statements now work with CREATE and DROP. All tests pass.

No memory leaks. (CVS 1866)

FossilOrigin-Name: ebdb661e0eefe123c422d3c1c371e325bb6cf673
This commit is contained in:
drh
2004-07-24 17:38:29 +00:00
parent 3f7d4e49d8
commit 956bc92cde
9 changed files with 178 additions and 134 deletions

View File

@@ -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) C Prepared\sstatements\snow\swork\swith\sCREATE\sand\sDROP.\s\sAll\stests\spass.\nNo\smemory\sleaks.\s(CVS\s1866)
D 2004-07-24T14:35:58 D 2004-07-24T17:38:29
F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -29,7 +29,7 @@ F src/attach.c 784456629b3d7e50e4691f496700658fd1f16441
F src/auth.c 60db23b98bb94c8b0178180faaf49dc116674217 F src/auth.c 60db23b98bb94c8b0178180faaf49dc116674217
F src/btree.c edf4ece708350dec7f28ebd4620c6d33afe6993a F src/btree.c edf4ece708350dec7f28ebd4620c6d33afe6993a
F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029 F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029
F src/build.c 3075ca2e66d6da3f98840d18f6e2bc4d15ced569 F src/build.c 7d2981666b6d0c530766dbf1284aabc328e1ec71
F src/date.c e1bb384a7856c18dce9cadb0afbe6934ba5ddb00 F src/date.c e1bb384a7856c18dce9cadb0afbe6934ba5ddb00
F src/delete.c e81545e546f6bc87d7508a93a09ca70695265af3 F src/delete.c e81545e546f6bc87d7508a93a09ca70695265af3
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
@@ -37,7 +37,7 @@ F src/expr.c a4e8ac69c872f86bc207364be0e32d0638f61e90
F src/func.c b163fb49efec999eb7bf982f7de5b9be388301f3 F src/func.c b163fb49efec999eb7bf982f7de5b9be388301f3
F src/hash.c f0a2f22c2a7052d67053b5f4690ea3010bb3fb9f F src/hash.c f0a2f22c2a7052d67053b5f4690ea3010bb3fb9f
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
F src/insert.c d99ffe87e1e1397f4233afcd06841d52d6b17b18 F src/insert.c bedcba371401395033a1a1c578d8fdc3fec87bec
F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
F src/main.c 49ea4a45223a002d06b5a4a5db36327acafc1779 F src/main.c 49ea4a45223a002d06b5a4a5db36327acafc1779
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
@@ -60,7 +60,7 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c aefda626660086addca4ce85c34aeef5d0f44c25 F src/select.c aefda626660086addca4ce85c34aeef5d0f44c25
F src/shell.c 93c96c847228c02fb84bb381875d87ee71fbbeb4 F src/shell.c 93c96c847228c02fb84bb381875d87ee71fbbeb4
F src/sqlite.h.in 80de11cde2c9f78eff4dab0aad1eb5196d6e2a3f F src/sqlite.h.in 80de11cde2c9f78eff4dab0aad1eb5196d6e2a3f
F src/sqliteInt.h 31d5887a802b5f218f604a1fd44fe989873cf2bc F src/sqliteInt.h d2aebb8c8941bc9cab4506de313f304d358c93b8
F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49 F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49
F src/tclsqlite.c 3ce001b3c301876a9c8163472077a4c10e0d49f3 F src/tclsqlite.c 3ce001b3c301876a9c8163472077a4c10e0d49f3
F src/test1.c ef00096c283ccfec1b2ae5fdaccb85fb06e24281 F src/test1.c ef00096c283ccfec1b2ae5fdaccb85fb06e24281
@@ -69,12 +69,12 @@ F src/test3.c 94d0a2a90bccd85802488cb42c69ec8afd2e4646
F src/test4.c a921a69821fd30209589228e64f94e9f715b6fe2 F src/test4.c a921a69821fd30209589228e64f94e9f715b6fe2
F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1 F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
F src/tokenize.c bc7a80e4cf54f42ea4b030c62261c4243133af84 F src/tokenize.c bc7a80e4cf54f42ea4b030c62261c4243133af84
F src/trigger.c 6aaf6d79cc2157c70a06031dd1531707d644cfb4 F src/trigger.c 360cf8f12edd4eb3a8a2895b136aac238c3cf44e
F src/update.c b66b1896c9da54678ba3eff2bf0b4d291a95986a F src/update.c b66b1896c9da54678ba3eff2bf0b4d291a95986a
F src/utf.c f03535db72bfa09e24202ccdd245f21d2fc65f0a F src/utf.c f03535db72bfa09e24202ccdd245f21d2fc65f0a
F src/util.c 2aacc79b7bf5df5859813dafd3bf3258f67a5234 F src/util.c 2aacc79b7bf5df5859813dafd3bf3258f67a5234
F src/vacuum.c 23ec8c5f3134c6315f883d648fa63b72d8c3ead3 F src/vacuum.c 23ec8c5f3134c6315f883d648fa63b72d8c3ead3
F src/vdbe.c cad659a06b30c03b870c4a00a828d78f7a69bbcf F src/vdbe.c f40f4ca4d9a7ba7c330e5673419f32dd3512547c
F src/vdbe.h 75b241c02431b9c0f16eaa9cdbb34146c6287f52 F src/vdbe.h 75b241c02431b9c0f16eaa9cdbb34146c6287f52
F src/vdbeInt.h 3d8e08c54dcb5ca2169db8bb3a37b81a12efaecd F src/vdbeInt.h 3d8e08c54dcb5ca2169db8bb3a37b81a12efaecd
F src/vdbeapi.c c5c6d8f162a9581dde497b1a4034f9a0bf54c355 F src/vdbeapi.c c5c6d8f162a9581dde497b1a4034f9a0bf54c355
@@ -140,13 +140,13 @@ F test/minmax.test 6513f9a1bb85fd35ff72b34b7b6634fad6b1e69c
F test/misc1.test 72768ec8cabc952a4cfcddca43d566f9e0bce899 F test/misc1.test 72768ec8cabc952a4cfcddca43d566f9e0bce899
F test/misc2.test 703734f5817215ca54e364833b3bf5ff36fcc21e F test/misc2.test 703734f5817215ca54e364833b3bf5ff36fcc21e
F test/misc3.test eb488314990bfc0959221a1acc465013238bf168 F test/misc3.test eb488314990bfc0959221a1acc465013238bf168
F test/misc4.test b31a0a08077038b03a9320fd5d9731093da708a8 F test/misc4.test 9f8ab4896dd627f5f9ba893a7b57c9f0a95dfd64
F test/misuse.test 2a64ce711419f2fd12806ed95af930fd4e7bb8f3 F test/misuse.test 2a64ce711419f2fd12806ed95af930fd4e7bb8f3
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0 F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721 F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721
F test/pager.test 059cc5c58d3b5a851343dff8c56cf7286425d03a F test/pager.test 059cc5c58d3b5a851343dff8c56cf7286425d03a
F test/pager2.test 55469c7c1c1a54d6b32d7b3cc99001e90101a1ce F test/pager2.test 55469c7c1c1a54d6b32d7b3cc99001e90101a1ce
F test/pragma.test f7414c1d902688825ca11f7f5e03628704d903b5 F test/pragma.test 66a66b7f3b273b93325c9a5794acb418f52fdcbf
F test/printf.test 428ad9be92963b68ba222dac4c19724cc4e304ea F test/printf.test 428ad9be92963b68ba222dac4c19724cc4e304ea
F test/progress.test 76c722f090b1ccb575e7e4e203a71608c5763beb x F test/progress.test 76c722f090b1ccb575e7e4e203a71608c5763beb x
F test/quick.test 5bb4afdb204c57329c86fa11f3f0a5296675fd7f F test/quick.test 5bb4afdb204c57329c86fa11f3f0a5296675fd7f
@@ -240,7 +240,7 @@ F www/tclsqlite.tcl 06a86cba4d7fc88e2bcd633b57702d3d16abebb5
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 49b991492496e104f5eca620a5d465a742b7ff3a P 6db3f122aad25b5226670ce682b7263d55c0d301
R 360d271fab96b9095f5b4369737eb03f R 987e7be0c6defafac7646ce8c68bde8c
U drh U drh
Z e2b908232fc8aa315ba06b1f36120ee8 Z 4bf2f79f0d58a1ba844cc564cece29c1

View File

@@ -1 +1 @@
6db3f122aad25b5226670ce682b7263d55c0d301 ebdb661e0eefe123c422d3c1c371e325bb6cf673

View File

@@ -23,7 +23,7 @@
** ROLLBACK ** ROLLBACK
** PRAGMA ** 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 "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -191,6 +191,14 @@ Index *sqlite3FindIndex(sqlite *db, const char *zName, const char *zDb){
return p; 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 ** Remove the given index from the index hash table, and free
** its memory structures. ** its memory structures.
@@ -209,10 +217,7 @@ static void sqliteDeleteIndex(sqlite *db, Index *p){
sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName, sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
strlen(pOld->zName)+1, pOld); strlen(pOld->zName)+1, pOld);
} }
if( p->zColAff ){ freeIndex(p);
sqliteFree(p->zColAff);
}
sqliteFree(p);
} }
/* /*
@@ -220,7 +225,13 @@ static void sqliteDeleteIndex(sqlite *db, Index *p){
** the index from the index hash table and free its memory ** the index from the index hash table and free its memory
** structures. ** structures.
*/ */
void sqlite3UnlinkAndDeleteIndex(sqlite *db, Index *pIndex){ 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 ){ if( pIndex->pTable->pIndex==pIndex ){
pIndex->pTable->pIndex = pIndex->pNext; pIndex->pTable->pIndex = pIndex->pNext;
}else{ }else{
@@ -230,7 +241,9 @@ void sqlite3UnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
p->pNext = pIndex->pNext; p->pNext = pIndex->pNext;
} }
} }
sqliteDeleteIndex(db, pIndex); freeIndex(pIndex);
}
db->flags |= SQLITE_InternChanges;
} }
/* /*
@@ -328,6 +341,23 @@ void sqlite3CommitInternalChanges(sqlite *db){
db->flags &= ~SQLITE_InternChanges; 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 ** Remove the memory data structures associated with the given
** Table. No changes are made to disk by this routine. ** Table. No changes are made to disk by this routine.
@@ -344,7 +374,6 @@ void sqlite3CommitInternalChanges(sqlite *db){
** unlinked. ** unlinked.
*/ */
void sqlite3DeleteTable(sqlite *db, Table *pTable){ void sqlite3DeleteTable(sqlite *db, Table *pTable){
int i;
Index *pIndex, *pNext; Index *pIndex, *pNext;
FKey *pFKey, *pNextFKey; FKey *pFKey, *pNextFKey;
@@ -371,17 +400,9 @@ void sqlite3DeleteTable(sqlite *db, Table *pTable){
/* Delete the Table structure itself. /* Delete the Table structure itself.
*/ */
for(i=0; i<pTable->nCol; i++){ sqliteResetColumnNames(pTable);
Column *pCol = &pTable->aCol[i];
sqliteFree(pCol->zName);
sqliteFree(pCol->zDflt);
sqliteFree(pCol->zType);
}
sqliteFree(pTable->zName); sqliteFree(pTable->zName);
sqliteFree(pTable->aCol);
if( pTable->zColAff ){
sqliteFree(pTable->zColAff); sqliteFree(pTable->zColAff);
}
sqlite3SelectDelete(pTable->pSelect); sqlite3SelectDelete(pTable->pSelect);
sqliteFree(pTable); sqliteFree(pTable);
} }
@@ -390,18 +411,22 @@ void sqlite3DeleteTable(sqlite *db, Table *pTable){
** Unlink the given table from the hash tables and the delete the ** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys. ** table structure with all its indices and foreign keys.
*/ */
static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){ void sqlite3UnlinkAndDeleteTable(sqlite *db, int iDb, const char *zTabName){
Table *pOld; Table *p;
FKey *pF1, *pF2; FKey *pF1, *pF2;
int i = p->iDb; Db *pDb;
assert( db!=0 ); assert( db!=0 );
pOld = sqlite3HashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1,0); assert( iDb>=0 && iDb<db->nDb );
assert( pOld==0 || pOld==p ); 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){ for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
int nTo = strlen(pF1->zTo) + 1; int nTo = strlen(pF1->zTo) + 1;
pF2 = sqlite3HashFind(&db->aDb[i].aFKey, pF1->zTo, nTo); pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo);
if( pF2==pF1 ){ if( pF2==pF1 ){
sqlite3HashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo); sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo);
}else{ }else{
while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
if( pF2 ){ if( pF2 ){
@@ -410,6 +435,8 @@ static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
} }
} }
sqlite3DeleteTable(db, p); sqlite3DeleteTable(db, p);
}
db->flags |= SQLITE_InternChanges;
} }
/* /*
@@ -1530,28 +1557,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
return nErr; 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. ** 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)){ for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i); Table *pTab = sqliteHashData(i);
if( pTab->pSelect ){ if( pTab->pSelect ){
sqliteViewResetColumnNames(pTab); sqliteResetColumnNames(pTab);
} }
} }
DbClearProperty(db, idx, DB_UnresetViews); DbClearProperty(db, idx, DB_UnresetViews);
@@ -1660,11 +1665,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
while( pTrigger ){ while( pTrigger ){
assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 ); assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 );
sqlite3DropTriggerPtr(pParse, pTrigger, 1); sqlite3DropTriggerPtr(pParse, pTrigger, 1);
if( pParse->explain ){
pTrigger = pTrigger->pNext; pTrigger = pTrigger->pNext;
}else{
pTrigger = pTab->pTrigger;
}
} }
/* Drop all SQLITE_MASTER table and index entries that refer to the /* 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); sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
} }
} }
sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
sqlite3EndWriteOperation(pParse); 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); sqliteViewResetAll(db, iDb);
exit_drop_table: exit_drop_table:
@@ -2192,7 +2184,9 @@ void sqlite3CreateIndex(
/* Clean up before exiting */ /* Clean up before exiting */
exit_create_index: exit_create_index:
if( pIndex ) sqliteFree(pIndex); if( pIndex ){
freeIndex(pIndex);
}
sqlite3ExprListDelete(pList); sqlite3ExprListDelete(pList);
sqlite3SrcListDelete(pTblName); sqlite3SrcListDelete(pTblName);
sqliteFree(zName); sqliteFree(zName);
@@ -2261,16 +2255,10 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
sqlite3ChangeCookie(db, v, pIndex->iDb); sqlite3ChangeCookie(db, v, pIndex->iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0);
sqlite3EndWriteOperation(pParse); sqlite3EndWriteOperation(pParse);
} }
/* Delete the in-memory description of this index.
*/
if( !pParse->explain ){
sqlite3UnlinkAndDeleteIndex(db, pIndex);
db->flags |= SQLITE_InternChanges;
}
exit_drop_index: exit_drop_index:
sqlite3SrcListDelete(pName); sqlite3SrcListDelete(pName);
} }

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite. ** 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" #include "sqliteInt.h"
@@ -50,7 +50,7 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
pIdx->zColAff[pIdx->nColumn] = '\0'; 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; pTab->zColAff = zColAff;
} }
sqlite3VdbeChangeP3(v, -1, pTab->zColAff, P3_STATIC); sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0);
} }

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** 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_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
@@ -1272,7 +1272,9 @@ void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
Table *sqlite3FindTable(sqlite*,const char*, const char*); Table *sqlite3FindTable(sqlite*,const char*, const char*);
Table *sqlite3LocateTable(Parse*,const char*, const char*); Table *sqlite3LocateTable(Parse*,const char*, const char*);
Index *sqlite3FindIndex(sqlite*,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*); void sqlite3Vacuum(Parse*, Token*);
int sqlite3RunVacuum(char**, sqlite*); int sqlite3RunVacuum(char**, sqlite*);
int sqlite3GlobCompare(const unsigned char*,const unsigned char*); int sqlite3GlobCompare(const unsigned char*,const unsigned char*);

View File

@@ -141,7 +141,7 @@ void sqlite3BeginTrigger(
if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
goto trigger_cleanup; 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; goto trigger_cleanup;
} }
} }
@@ -239,10 +239,12 @@ void sqlite3FinishTrigger(
sqlite3ChangeCookie(db, v, nt->iDb); sqlite3ChangeCookie(db, v, nt->iDb);
} }
sqlite3VdbeAddOp(v, OP_Close, 0, 0); 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); sqlite3EndWriteOperation(pParse);
} }
if( !pParse->explain ){ if( db->init.busy ){
Table *pTab; Table *pTab;
sqlite3HashInsert(&db->aDb[nt->iDb].trigHash, sqlite3HashInsert(&db->aDb[nt->iDb].trigHash,
nt->name, strlen(nt->name)+1, nt); nt->name, strlen(nt->name)+1, nt);
@@ -444,6 +446,15 @@ drop_trigger_cleanup:
sqlite3SrcListDelete(pName); 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, ** 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 ** 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; Table *pTable;
Vdbe *v; Vdbe *v;
sqlite *db = pParse->db; sqlite *db = pParse->db;
int iDb;
assert( pTrigger->iDb<db->nDb ); iDb = pTrigger->iDb;
pTable = sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName); assert( iDb>=0 && iDb<db->nDb );
pTable = tableOfTrigger(db, pTrigger);
assert(pTable); assert(pTable);
assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 ); assert( pTable->iDb==iDb || iDb==1 );
#ifndef SQLITE_OMIT_AUTHORIZATION #ifndef SQLITE_OMIT_AUTHORIZATION
{ {
int code = SQLITE_DROP_TRIGGER; int code = SQLITE_DROP_TRIGGER;
const char *zDb = db->aDb[pTrigger->iDb].zName; const char *zDb = db->aDb[iDb].zName;
const char *zTab = SCHEMA_TABLE(pTrigger->iDb); const char *zTab = SCHEMA_TABLE(iDb);
if( pTrigger->iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
return; return;
@@ -487,20 +500,26 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
{ OP_Next, 0, ADDR(1), 0}, /* 8 */ { OP_Next, 0, ADDR(1), 0}, /* 8 */
}; };
sqlite3BeginWriteOperation(pParse, 0, pTrigger->iDb); sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3OpenMasterTable(v, pTrigger->iDb); sqlite3OpenMasterTable(v, iDb);
base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0);
sqlite3ChangeCookie(db, v, pTrigger->iDb); sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0); 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. ** Remove a trigger from the hash tables of the sqlite* pointer.
*/ */
if( !pParse->explain ){ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
const char *zName = pTrigger->name; Trigger *pTrigger;
int nName = strlen(zName); 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 ){ if( pTable->pTrigger == pTrigger ){
pTable->pTrigger = pTrigger->pNext; pTable->pTrigger = pTrigger->pNext;
}else{ }else{
@@ -514,8 +533,8 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
} }
assert(cc); assert(cc);
} }
sqlite3HashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
sqlite3DeleteTrigger(pTrigger); sqlite3DeleteTrigger(pTrigger);
db->flags |= SQLITE_InternChanges;
} }
} }

View File

@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** 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 "sqliteInt.h"
#include "os.h" #include "os.h"
@@ -3764,6 +3764,42 @@ case OP_ParseSchema: {
break; 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 * /* Opcode: IntegrityCk * P2 *
** **

View File

@@ -13,7 +13,7 @@
# This file implements tests for miscellanous features that were # This file implements tests for miscellanous features that were
# left out of other test files. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@@ -64,11 +64,9 @@ do_test misc4-1.6 {
# those statements are executed, try to use the tables, indices, views, # those statements are executed, try to use the tables, indices, views,
# are triggers that were created. # are triggers that were created.
# #
if 0 {
do_test misc4-2.1 { do_test misc4-2.1 {
set stmt [sqlite3_prepare $DB {CREATE TABLE t3(x);} -1 TAIL] set stmt [sqlite3_prepare $DB {CREATE TABLE t3(x);} -1 TAIL]
catchsql { catchsql {
pragma vdbe_trace=on;
INSERT INTO t3 VALUES(1); INSERT INTO t3 VALUES(1);
} }
} {1 {no such table: t3}} } {1 {no such table: t3}}
@@ -83,6 +81,6 @@ do_test misc4-2.4 {
INSERT INTO t3 VALUES(1); INSERT INTO t3 VALUES(1);
} }
} {0 {}} } {0 {}}
}
finish_test finish_test

View File

@@ -12,7 +12,7 @@
# #
# This file implements tests for the PRAGMA command. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@@ -306,6 +306,7 @@ catchsql {COMMIT;}
# Test schema-query pragmas # Test schema-query pragmas
# #
do_test pragma-6.1 { do_test pragma-6.1 {
set res {}
foreach {idx name file} [execsql {pragma database_list}] { foreach {idx name file} [execsql {pragma database_list}] {
lappend res $idx $name lappend res $idx $name
} }