diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 160 | ||||
-rw-r--r-- | src/insert.c | 6 | ||||
-rw-r--r-- | src/sqliteInt.h | 6 | ||||
-rw-r--r-- | src/trigger.c | 67 | ||||
-rw-r--r-- | src/vdbe.c | 38 |
5 files changed, 161 insertions, 116 deletions
diff --git a/src/build.c b/src/build.c index 4494c43a0..56a59d4df 100644 --- a/src/build.c +++ b/src/build.c @@ -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> @@ -192,6 +192,14 @@ Index *sqlite3FindIndex(sqlite *db, const char *zName, const char *zDb){ } /* +** 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; } /* @@ -329,6 +342,23 @@ void sqlite3CommitInternalChanges(sqlite *db){ } /* +** 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; } /* @@ -1531,28 +1558,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ } /* -** 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. */ static void sqliteViewResetAll(sqlite *db, int 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); } diff --git a/src/insert.c b/src/insert.c index 7a79df20e..7959947d1 100644 --- a/src/insert.c +++ b/src/insert.c @@ -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); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 94656ab41..39561702a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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*); diff --git a/src/trigger.c b/src/trigger.c index 4ece0557b..49bd0768c 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -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); @@ -445,6 +447,15 @@ drop_trigger_cleanup: } /* +** 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 ** table. @@ -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; } } diff --git a/src/vdbe.c b/src/vdbe.c index 390576d63..aab44e30d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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 * ** |