1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-01 06:27:03 +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)
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

View File

@ -1 +1 @@
6db3f122aad25b5226670ce682b7263d55c0d301
ebdb661e0eefe123c422d3c1c371e325bb6cf673

View 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);
}

View 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);
}

View 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*);

View 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;
}
}

View 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 *
**

View 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

View 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
}