1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21: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

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