aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c160
-rw-r--r--src/insert.c6
-rw-r--r--src/sqliteInt.h6
-rw-r--r--src/trigger.c67
-rw-r--r--src/vdbe.c38
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 *
**