aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c124
-rw-r--r--src/main.c150
-rw-r--r--src/sqliteInt.h13
-rw-r--r--src/tokenize.c8
-rw-r--r--src/vdbe.c54
5 files changed, 167 insertions, 182 deletions
diff --git a/src/build.c b/src/build.c
index 7f27985f2..09427a9c3 100644
--- a/src/build.c
+++ b/src/build.c
@@ -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},
diff --git a/src/main.c b/src/main.c
index 24a4c19c4..f6cce31c6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,22 +14,13 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.246 2004/07/22 01:19:35 drh Exp $
+** $Id: main.c,v 1.247 2004/07/24 03:30:48 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/*
-** A pointer to this structure is used to communicate information
-** from sqlite3Init into the sqlite3InitCallback.
-*/
-typedef struct {
- sqlite *db; /* The database being initialized */
- char **pzErrMsg; /* Error message stored here */
-} InitData;
-
-/*
** The following constant value is used by the SQLITE_BIGENDIAN and
** SQLITE_LITTLEENDIAN macros.
*/
@@ -49,89 +40,69 @@ static void corruptSchema(InitData *pData, const char *zExtra){
/*
** This is the callback routine for the code that initializes the
** database. See sqlite3Init() below for additional information.
+** This routine is also called from the OP_ParseSchema opcode of the VDBE.
**
** Each callback contains the following information:
**
-** argv[0] = "table" or "index" or "view" or "trigger"
-** argv[1] = name of thing being created
-** argv[2] = root page number for table or index. NULL for trigger or view.
-** argv[3] = SQL text for the CREATE statement.
-** argv[4] = "1" for temporary files, "0" for main database, "2" or more
+** argv[0] = name of thing being created
+** argv[1] = root page number for table or index. NULL for trigger or view.
+** argv[2] = SQL text for the CREATE statement.
+** argv[3] = "1" for temporary files, "0" for main database, "2" or more
** for auxiliary database files.
**
*/
-static
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
- int nErr = 0;
+ sqlite *db = pData->db;
+ int iDb;
- assert( argc==5 );
+ assert( argc==4 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
- if( argv[0]==0 ){
+ if( argv[1]==0 || argv[3]==0 ){
corruptSchema(pData, 0);
return 1;
}
- switch( argv[0][0] ){
- case 'v':
- case 'i':
- case 't': { /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
- sqlite *db = pData->db;
- if( argv[2]==0 || argv[4]==0 ){
- corruptSchema(pData, 0);
- return 1;
- }
- if( argv[3] && argv[3][0] ){
- /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
- ** But because db->init.busy is set to 1, no VDBE code is generated
- ** or executed. All the parser does is build the internal data
- ** structures that describe the table, index, or view.
- */
- char *zErr;
- int rc;
- assert( db->init.busy );
- db->init.iDb = atoi(argv[4]);
- assert( db->init.iDb>=0 && db->init.iDb<db->nDb );
- db->init.newTnum = atoi(argv[2]);
- rc = sqlite3_exec(db, argv[3], 0, 0, &zErr);
- db->init.iDb = 0;
- if( SQLITE_OK!=rc ){
- corruptSchema(pData, zErr);
- sqlite3_free(zErr);
- return rc;
- }
- }else{
- /* If the SQL column is blank it means this is an index that
- ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
- ** constraint for a CREATE TABLE. The index should have already
- ** been created when we processed the CREATE TABLE. All we have
- ** to do here is record the root page number for that index.
- */
- int iDb;
- Index *pIndex;
-
- iDb = atoi(argv[4]);
- assert( iDb>=0 && iDb<db->nDb );
- pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zName);
- if( pIndex==0 || pIndex->tnum!=0 ){
- /* This can occur if there exists an index on a TEMP table which
- ** has the same name as another index on a permanent index. Since
- ** the permanent table is hidden by the TEMP table, we can also
- ** safely ignore the index on the permanent table.
- */
- /* Do Nothing */;
- }else{
- pIndex->tnum = atoi(argv[2]);
- }
- }
+ iDb = atoi(argv[3]);
+ assert( iDb>=0 && iDb<db->nDb );
+ if( argv[2] && argv[2][0] ){
+ /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
+ ** But because db->init.busy is set to 1, no VDBE code is generated
+ ** or executed. All the parser does is build the internal data
+ ** structures that describe the table, index, or view.
+ */
+ char *zErr;
+ int rc;
+ assert( db->init.busy );
+ db->init.iDb = iDb;
+ db->init.newTnum = atoi(argv[1]);
+ rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
+ db->init.iDb = 0;
+ if( SQLITE_OK!=rc ){
+ corruptSchema(pData, zErr);
+ sqlite3_free(zErr);
+ return rc;
}
- break;
- default: {
- /* This can not happen! */
- nErr = 1;
- assert( nErr==0 );
+ }else{
+ /* If the SQL column is blank it means this is an index that
+ ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
+ ** constraint for a CREATE TABLE. The index should have already
+ ** been created when we processed the CREATE TABLE. All we have
+ ** to do here is record the root page number for that index.
+ */
+ Index *pIndex;
+ pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName);
+ if( pIndex==0 || pIndex->tnum!=0 ){
+ /* This can occur if there exists an index on a TEMP table which
+ ** has the same name as another index on a permanent index. Since
+ ** the permanent table is hidden by the TEMP table, we can also
+ ** safely ignore the index on the permanent table.
+ */
+ /* Do Nothing */;
+ }else{
+ pIndex->tnum = atoi(argv[1]);
}
}
- return nErr;
+ return 0;
}
/*
@@ -147,7 +118,7 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){
BtCursor *curMain;
int size;
Table *pTab;
- char const *azArg[6];
+ char const *azArg[5];
char zDbNum[30];
int meta[10];
InitData initData;
@@ -192,16 +163,15 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){
/* Construct the schema tables. */
sqlite3SafetyOff(db);
- azArg[0] = "table";
- azArg[1] = zMasterName;
- azArg[2] = "1";
- azArg[3] = zMasterSchema;
+ azArg[0] = zMasterName;
+ azArg[1] = "1";
+ azArg[2] = zMasterSchema;
sprintf(zDbNum, "%d", iDb);
- azArg[4] = zDbNum;
- azArg[5] = 0;
+ azArg[3] = zDbNum;
+ azArg[4] = 0;
initData.db = db;
initData.pzErrMsg = pzErrMsg;
- rc = sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
+ rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0);
if( rc!=SQLITE_OK ){
sqlite3SafetyOn(db);
return rc;
@@ -304,14 +274,14 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){
/* For an empty database, there is nothing to read */
rc = SQLITE_OK;
}else{
- char *zSql = 0;
+ char *zSql;
+ zSql = sqlite3MPrintf(
+ "SELECT name, rootpage, sql, %s FROM '%q'.%s",
+ zDbNum, db->aDb[iDb].zName, zMasterName);
sqlite3SafetyOff(db);
- sqlite3SetString(&zSql,
- "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
- db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
- sqliteFree(zSql);
sqlite3SafetyOn(db);
+ sqliteFree(zSql);
sqlite3BtreeCloseCursor(curMain);
}
if( sqlite3_malloc_failed ){
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d6cde4e5e..cdab05c9a 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.308 2004/07/22 15:02:25 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.309 2004/07/24 03:30:48 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -1160,6 +1160,16 @@ struct DbFixer {
};
/*
+** A pointer to this structure is used to communicate information
+** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
+*/
+typedef struct {
+ sqlite *db; /* The database being initialized */
+ char **pzErrMsg; /* Error message stored here */
+} InitData;
+
+
+/*
* This global flag is set for performance testing of triggers. When it is set
* SQLite will perform the overhead of building new and old trigger references
* even when no triggers exist
@@ -1210,6 +1220,7 @@ void sqlite3ExprDelete(Expr*);
ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*);
void sqlite3ExprListDelete(ExprList*);
int sqlite3Init(sqlite*, char**);
+int sqlite3InitCallback(void*, int, char**, char**);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
void sqlite3ResetInternalSchema(sqlite*, int);
void sqlite3BeginParse(Parse*,int);
diff --git a/src/tokenize.c b/src/tokenize.c
index 8600cc6fd..dde809146 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.78 2004/06/18 06:02:35 danielk1977 Exp $
+** $Id: tokenize.c,v 1.79 2004/07/24 03:30:48 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -431,6 +431,11 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
sqlite3SetString(pzErrMsg, "out of memory", (char*)0);
return 1;
}
+#ifndef NDEBUG
+ if( sqlite3OsFileExists("vdbe_sqltrace") ){
+ printf("SQL To Compiler: [%s]\n", zSql);
+ }
+#endif
pParse->sLastToken.dyn = 0;
pParse->zTail = zSql;
while( sqlite3_malloc_failed==0 && zSql[i]!=0 ){
@@ -714,4 +719,3 @@ int sqlite3_complete16(const void *zSql){
sqlite3ValueFree(pVal);
return rc;
}
-
diff --git a/src/vdbe.c b/src/vdbe.c
index beeae2d7c..12e0978b3 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.403 2004/07/21 02:53:30 drh Exp $
+** $Id: vdbe.c,v 1.404 2004/07/24 03:30:48 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -3670,24 +3670,19 @@ case OP_Clear: {
break;
}
-/* Opcode: CreateTable * P2 P3
+/* Opcode: CreateTable P1 * *
**
** Allocate a new table in the main database file if P2==0 or in the
** auxiliary database file if P2==1. Push the page number
** for the root page of the new table onto the stack.
**
-** The root page number is also written to a memory location that P3
-** points to. This is the mechanism is used to write the root page
-** number into the parser's internal data structures that describe the
-** new table.
-**
** The difference between a table and an index is this: A table must
** have a 4-byte integer key and can have arbitrary data. An index
** has an arbitrary key but no data.
**
** See also: CreateIndex
*/
-/* Opcode: CreateIndex * P2 P3
+/* Opcode: CreateIndex P1 * *
**
** Allocate a new index in the main database file if P2==0 or in the
** auxiliary database file if P2==1. Push the page number of the
@@ -3699,28 +3694,59 @@ case OP_CreateIndex:
case OP_CreateTable: {
int pgno;
int flags;
- assert( pOp->p3!=0 && pOp->p3type==P3_POINTER );
- assert( pOp->p2>=0 && pOp->p2<db->nDb );
- assert( db->aDb[pOp->p2].pBt!=0 );
+ Db *pDb;
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ pDb = &db->aDb[pOp->p1];
+ assert( pDb->pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
/* flags = BTREE_INTKEY; */
flags = BTREE_LEAFDATA|BTREE_INTKEY;
}else{
flags = BTREE_ZERODATA;
}
- rc = sqlite3BtreeCreateTable(db->aDb[pOp->p2].pBt, &pgno, flags);
+ rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
pTos++;
if( rc==SQLITE_OK ){
pTos->i = pgno;
pTos->flags = MEM_Int;
- *(u32*)pOp->p3 = pgno;
- pOp->p3 = 0;
}else{
pTos->flags = MEM_Null;
}
break;
}
+/* Opcode: ParseSchema P1 * P3
+**
+** Read and parse all entries from the SQLITE_MASTER table of database P1
+** that match the WHERE clause P3.
+**
+** This opcode invokes the parser to create a new virtual machine,
+** then runs the new virtual machine. It is thus a reentrant opcode.
+*/
+case OP_ParseSchema: {
+ char *zSql;
+ int iDb = pOp->p1;
+ const char *zMaster;
+ InitData initData;
+
+ assert( iDb>=0 && iDb<db->nDb );
+ zMaster = iDb==1 ? TEMP_MASTER_NAME : MASTER_NAME;
+ initData.db = db;
+ initData.pzErrMsg = &p->zErrMsg;
+ zSql = sqlite3MPrintf(
+ "SELECT name, rootpage, sql, %d FROM '%q'.%s WHERE %s",
+ pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3);
+ sqlite3SafetyOff(db);
+ assert( db->init.busy==0 );
+ db->init.busy = 1;
+ rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
+ db->init.busy = 0;
+ sqlite3SafetyOn(db);
+ sqliteFree(zSql);
+ break;
+}
+
+
/* Opcode: IntegrityCk * P2 *
**
** Do an analysis of the currently open database. Push onto the