1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21:03 +03:00

Progress towards getting prepared statements and CREATE and DROP to play

nicely together.  Work is incomplete.  Some tests are known to fail. (CVS 1864)

FossilOrigin-Name: 49b991492496e104f5eca620a5d465a742b7ff3a
This commit is contained in:
drh
2004-07-24 03:30:47 +00:00
parent 3e27c02625
commit 234c39dff7
9 changed files with 223 additions and 215 deletions

View File

@@ -23,7 +23,7 @@
** ROLLBACK
** PRAGMA
**
** $Id: build.c,v 1.240 2004/07/22 01:19:35 drh Exp $
** $Id: build.c,v 1.241 2004/07/24 03:30:48 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -231,8 +231,8 @@ void sqlite3UnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
/*
** Erase all schema information from the in-memory hash tables of
** a sigle database. This routine is called to reclaim memory
** before the closes. It is also called during a rollback
** a single database. This routine is called to reclaim memory
** before the database closes. It is also called during a rollback
** if there were schema changes during the transaction or if a
** schema-cookie mismatch occurs.
**
@@ -1169,14 +1169,16 @@ void sqlite3ChangeCookie(sqlite *db, Vdbe *v, int iDb){
** Measure the number of characters needed to output the given
** identifier. The number returned includes any quotes used
** but does not include the null terminator.
**
** The estimate is conservative. It might be larger that what is
** really needed.
*/
static int identLength(const char *z){
int n;
int needQuote = 0;
for(n=0; *z; n++, z++){
if( *z=='\'' ){ n++; needQuote=1; }
if( *z=='"' ){ n++; }
}
return n + needQuote*2;
return n + 2;
}
/*
@@ -1191,12 +1193,12 @@ static void identPut(char *z, int *pIdx, char *zIdent){
}
needQuote = zIdent[j]!=0 || isdigit(zIdent[0])
|| sqlite3KeywordCode(zIdent, j)!=TK_ID;
if( needQuote ) z[i++] = '\'';
if( needQuote ) z[i++] = '"';
for(j=0; zIdent[j]; j++){
z[i++] = zIdent[j];
if( zIdent[j]=='\'' ) z[i++] = '\'';
if( zIdent[j]=='"' ) z[i++] = '"';
}
if( needQuote ) z[i++] = '\'';
if( needQuote ) z[i++] = '"';
z[i] = 0;
*pIdx = i;
}
@@ -1209,16 +1211,18 @@ static void identPut(char *z, int *pIdx, char *zIdent){
static char *createTableStmt(Table *p){
int i, k, n;
char *zStmt;
char *zSep, *zSep2, *zEnd;
char *zSep, *zSep2, *zEnd, *z;
Column *pCol;
n = 0;
for(i=0; i<p->nCol; i++){
n += identLength(p->aCol[i].zName);
if( p->aCol[i].zType ){
n += (strlen(p->aCol[i].zType) + 1);
for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
n += identLength(pCol->zName);
z = pCol->zType;
if( z ){
n += (strlen(z) + 1);
}
}
n += identLength(p->zName);
if( n<40 ){
if( n<50 ){
zSep = "";
zSep2 = ",";
zEnd = ")";
@@ -1234,15 +1238,15 @@ static char *createTableStmt(Table *p){
k = strlen(zStmt);
identPut(zStmt, &k, p->zName);
zStmt[k++] = '(';
for(i=0; i<p->nCol; i++){
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
strcpy(&zStmt[k], zSep);
k += strlen(&zStmt[k]);
zSep = zSep2;
identPut(zStmt, &k, p->aCol[i].zName);
if( p->aCol[i].zType ){
identPut(zStmt, &k, pCol->zName);
if( (z = pCol->zType)!=0 ){
zStmt[k++] = ' ';
strcpy(&zStmt[k], p->aCol[i].zType);
k += strlen(p->aCol[i].zType);
strcpy(&zStmt[k], z);
k += strlen(z);
}
}
strcpy(&zStmt[k], zEnd);
@@ -1305,12 +1309,11 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
if( p->pSelect==0 ){
/* A regular table */
sqlite3VdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER);
sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0);
}else{
/* A view */
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
}
p->tnum = 0;
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
@@ -1371,13 +1374,15 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
sqlite3ChangeCookie(db, v, p->iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0,
sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC);
sqlite3EndWriteOperation(pParse);
}
/* Add the table to the in-memory representation of the database.
*/
if( pParse->explain==0 && pParse->nErr==0 ){
if( db->init.busy && pParse->nErr==0 ){
Table *pOld;
FKey *pFKey;
pOld = sqlite3HashInsert(&db->aDb[p->iDb].tblHash,
@@ -1565,26 +1570,6 @@ static void sqliteViewResetAll(sqlite *db, int idx){
DbClearProperty(db, idx, DB_UnresetViews);
}
#if 0
/*
** Given a token, look up a table with that name. If not found, leave
** an error for the parser to find and return NULL.
*/
Table *sqlite3TableFromToken(Parse *pParse, Token *pTok){
char *zName;
Table *pTab;
zName = sqlite3NameFromToken(pTok);
if( zName==0 ) return 0;
pTab = sqlite3FindTable(pParse->db, zName, 0);
sqliteFree(zName);
if( pTab==0 ){
sqlite3ErrorMsg(pParse, "no such table: %T", pTok);
pParse->checkSchema = 1;
}
return pTab;
}
#endif
/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
@@ -2099,7 +2084,7 @@ void sqlite3CreateIndex(
/* Link the new Index structure to its table and to the other
** in-memory database structures.
*/
if( !pParse->explain ){
if( db->init.busy ){
Index *p;
p = sqlite3HashInsert(&db->aDb[pIndex->iDb].idxHash,
pIndex->zName, strlen(pIndex->zName)+1, pIndex);
@@ -2108,14 +2093,9 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
db->flags |= SQLITE_InternChanges;
}
/* If the db->init.busy is 1 it means we are reading the SQL off the
** "sqlite_master" table on the disk. So do not write to the disk
** again. Extract the table number from the db->init.newTnum field.
*/
if( db->init.busy && pTblName!=0 ){
pIndex->tnum = db->init.newTnum;
if( pTblName!=0 ){
pIndex->tnum = db->init.newTnum;
}
}
/* If the db->init.busy is 0 then create the index on disk. This
@@ -2148,8 +2128,7 @@ void sqlite3CreateIndex(
sqlite3VdbeOp3(v, OP_String8, 0, 0, "index", P3_STATIC);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pIndex->zName, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeOp3(v, OP_CreateIndex, 0, iDb,(char*)&pIndex->tnum,P3_POINTER);
pIndex->tnum = 0;
sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0);
if( pTblName ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
@@ -2185,11 +2164,11 @@ void sqlite3CreateIndex(
sqlite3VdbeResolveLabel(v, lbl2);
sqlite3VdbeAddOp(v, OP_Close, 2, 0);
sqlite3VdbeAddOp(v, OP_Close, 1, 0);
}
if( pTblName!=0 ){
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3EndWriteOperation(pParse);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC);
}
}
@@ -2198,19 +2177,21 @@ void sqlite3CreateIndex(
** OE_Ignore. This is necessary for the correct operation of UPDATE
** and INSERT.
*/
if( onError!=OE_Replace || pTab->pIndex==0
|| pTab->pIndex->onError==OE_Replace){
pIndex->pNext = pTab->pIndex;
pTab->pIndex = pIndex;
}else{
Index *pOther = pTab->pIndex;
while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
pOther = pOther->pNext;
if( db->init.busy || pTblName==0 ){
if( onError!=OE_Replace || pTab->pIndex==0
|| pTab->pIndex->onError==OE_Replace){
pIndex->pNext = pTab->pIndex;
pTab->pIndex = pIndex;
}else{
Index *pOther = pTab->pIndex;
while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
pOther = pOther->pNext;
}
pIndex->pNext = pOther->pNext;
pOther->pNext = pIndex;
}
pIndex->pNext = pOther->pNext;
pOther->pNext = pIndex;
pIndex = 0;
}
pIndex = 0;
/* Clean up before exiting */
exit_create_index:
@@ -2244,13 +2225,6 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
"or PRIMARY KEY constraint cannot be dropped", 0);
goto exit_drop_index;
}
/*
if( pIndex->iDb>1 ){
sqlite3ErrorMsg(pParse, "cannot alter schema of attached "
"databases", 0);
goto exit_drop_index;
}
*/
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_INDEX;
@@ -2272,7 +2246,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
if( v ){
static VdbeOpList dropIndex[] = {
{ OP_Rewind, 0, ADDR(9), 0},
{ OP_String8, 0, 0, 0}, /* 1 */
{ OP_String8, 0, 0, 0}, /* 1 */
{ OP_MemStore, 1, 1, 0},
{ OP_MemLoad, 1, 0, 0}, /* 3 */
{ OP_Column, 0, 1, 0},