Work toward making the schema parsing logic simplier and more compact.

FossilOrigin-Name: c52ca2c0662bb30ab34574f933429512655b19ff
This commit is contained in:
drh 2016-01-15 15:06:41 +00:00
parent 1e38927c12
commit 055f298ad4
6 changed files with 115 additions and 163 deletions

View File

@ -1,5 +1,5 @@
C Fix\sa\scouple\sC99-isms\sin\sFTS5\sthat\scause\scompile\serrors\son\sMSVC. C Work\stoward\smaking\sthe\sschema\sparsing\slogic\ssimplier\sand\smore\scompact.
D 2016-01-15T05:39:55.053 D 2016-01-15T15:06:41.166
F Makefile.in a476545d0c8626224d0bacac85c6e2967474af81 F Makefile.in a476545d0c8626224d0bacac85c6e2967474af81
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 01e855f958932d0d3ed62ec675fc63e2cef61fcb F Makefile.msc 01e855f958932d0d3ed62ec675fc63e2cef61fcb
@ -284,10 +284,10 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc
F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c 5d93e2477acb99d50a8b045f2e26a0be3d7751fe F src/btree.c d9c6b2e2df06314079aa582f12937401a62171a6
F src/btree.h 68ef301795e00cdf1d3ab93abc44a43b7fe771e0 F src/btree.h 68ef301795e00cdf1d3ab93abc44a43b7fe771e0
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
F src/build.c 9d497ff4bf3c82cecb520436e0e9963785627583 F src/build.c 2778ccdb327923b2eb6cea304e232efd0c85cbe1
F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
@ -336,7 +336,7 @@ F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6 F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/prepare.c 74855ddbdfad6a1c4a4d5c4b0913ebb01174ba19
F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32 F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 08dbe0292b24abc79b0c55ea97368e8a6bd235ec F src/resolve.c 08dbe0292b24abc79b0c55ea97368e8a6bd235ec
@ -406,7 +406,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3
F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3
F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70 F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c 4f3585480f61f96af3327e921baad223af0ce23e F src/vdbe.c b90d9d38e5e0260c2eafa3cb4c2274d8ea94da27
F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637 F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637
F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189
F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e
@ -1415,7 +1415,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 0d1b3d7d3ca66cb0b97493f1aeade1703af3c9f4 P 584848d4396d7755027fab377c97e40fbcc90d21
R b460170dac8e7d7fa7ff80be818c5f70 R d396ff3cd92323018eeceb835a86df32
U mistachkin U drh
Z 9c8571095ec15b56fdafaa6935514e64 Z d625867287e0b3ea5f45a2d19f9bb7c8

View File

@ -1 +1 @@
584848d4396d7755027fab377c97e40fbcc90d21 c52ca2c0662bb30ab34574f933429512655b19ff

View File

@ -8541,6 +8541,14 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
return SQLITE_LOCKED_SHAREDCACHE; return SQLITE_LOCKED_SHAREDCACHE;
} }
/*
** It is illegal to drop the sqlite_master table on page 1. But again,
** this error is caught long before reaching this point.
*/
if( NEVER(iTable<2) ){
return SQLITE_CORRUPT_BKPT;
}
rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc; if( rc ) return rc;
rc = sqlite3BtreeClearTable(p, iTable, 0); rc = sqlite3BtreeClearTable(p, iTable, 0);
@ -8551,76 +8559,67 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
*piMoved = 0; *piMoved = 0;
if( iTable>1 ){
#ifdef SQLITE_OMIT_AUTOVACUUM #ifdef SQLITE_OMIT_AUTOVACUUM
freePage(pPage, &rc); freePage(pPage, &rc);
releasePage(pPage); releasePage(pPage);
#else #else
if( pBt->autoVacuum ){ if( pBt->autoVacuum ){
Pgno maxRootPgno; Pgno maxRootPgno;
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno); sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno);
if( iTable==maxRootPgno ){ if( iTable==maxRootPgno ){
/* If the table being dropped is the table with the largest root-page /* If the table being dropped is the table with the largest root-page
** number in the database, put the root page on the free list. ** number in the database, put the root page on the free list.
*/
freePage(pPage, &rc);
releasePage(pPage);
if( rc!=SQLITE_OK ){
return rc;
}
}else{
/* The table being dropped does not have the largest root-page
** number in the database. So move the page that does into the
** gap left by the deleted root-page.
*/
MemPage *pMove;
releasePage(pPage);
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
if( rc!=SQLITE_OK ){
return rc;
}
rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
releasePage(pMove);
if( rc!=SQLITE_OK ){
return rc;
}
pMove = 0;
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
freePage(pMove, &rc);
releasePage(pMove);
if( rc!=SQLITE_OK ){
return rc;
}
*piMoved = maxRootPgno;
}
/* Set the new 'max-root-page' value in the database header. This
** is the old value less one, less one more if that happens to
** be a root-page number, less one again if that is the
** PENDING_BYTE_PAGE.
*/ */
maxRootPgno--;
while( maxRootPgno==PENDING_BYTE_PAGE(pBt)
|| PTRMAP_ISPAGE(pBt, maxRootPgno) ){
maxRootPgno--;
}
assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
}else{
freePage(pPage, &rc); freePage(pPage, &rc);
releasePage(pPage); releasePage(pPage);
if( rc!=SQLITE_OK ){
return rc;
}
}else{
/* The table being dropped does not have the largest root-page
** number in the database. So move the page that does into the
** gap left by the deleted root-page.
*/
MemPage *pMove;
releasePage(pPage);
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
if( rc!=SQLITE_OK ){
return rc;
}
rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
releasePage(pMove);
if( rc!=SQLITE_OK ){
return rc;
}
pMove = 0;
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
freePage(pMove, &rc);
releasePage(pMove);
if( rc!=SQLITE_OK ){
return rc;
}
*piMoved = maxRootPgno;
} }
#endif
}else{ /* Set the new 'max-root-page' value in the database header. This
/* If sqlite3BtreeDropTable was called on page 1. ** is the old value less one, less one more if that happens to
** This really never should happen except in a corrupt ** be a root-page number, less one again if that is the
** database. ** PENDING_BYTE_PAGE.
*/ */
zeroPage(pPage, PTF_INTKEY|PTF_LEAF ); maxRootPgno--;
while( maxRootPgno==PENDING_BYTE_PAGE(pBt)
|| PTRMAP_ISPAGE(pBt, maxRootPgno) ){
maxRootPgno--;
}
assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
}else{
freePage(pPage, &rc);
releasePage(pPage); releasePage(pPage);
} }
#endif
return rc; return rc;
} }
int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){

View File

@ -758,7 +758,8 @@ int sqlite3TwoPartName(
int iDb; /* Database holding the object */ int iDb; /* Database holding the object */
sqlite3 *db = pParse->db; sqlite3 *db = pParse->db;
if( ALWAYS(pName2!=0) && pName2->n>0 ){ assert( pName2!=0 );
if( pName2->n>0 ){
if( db->init.busy ) { if( db->init.busy ) {
sqlite3ErrorMsg(pParse, "corrupt database"); sqlite3ErrorMsg(pParse, "corrupt database");
return -1; return -1;
@ -847,62 +848,46 @@ void sqlite3StartTable(
int iDb; /* Database number to create the table in */ int iDb; /* Database number to create the table in */
Token *pName; /* Unqualified name of the table to create */ Token *pName; /* Unqualified name of the table to create */
/* The table or view name to create is passed to this routine via tokens if( db->init.busy && db->init.newTnum==1 ){
** pName1 and pName2. If the table name was fully qualified, for example: /* Special case: Parsing the sqlite_master or sqlite_temp_master schema */
** iDb = db->init.iDb;
** CREATE TABLE xxx.yyy (...); zName = sqlite3DbStrDup(db, SCHEMA_TABLE(iDb));
** pName = pName1;
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if }else{
** the table name is not fully qualified, i.e.: /* The common case */
** iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
** CREATE TABLE yyy(...); if( iDb<0 ) return;
** if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){
** Then pName1 is set to "yyy" and pName2 is "". /* If creating a temp table, the name may not be qualified. Unless
** ** the database name is "temp" anyway. */
** The call below sets the pName pointer to point at the token (pName1 or sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
** pName2) that stores the unqualified table name. The variable iDb is return;
** set to the index of the database that the table or view is to be }
** created in. if( !OMIT_TEMPDB && isTemp ) iDb = 1;
*/ zName = sqlite3NameFromToken(db, pName);
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
if( iDb<0 ) return;
if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){
/* If creating a temp table, the name may not be qualified. Unless
** the database name is "temp" anyway. */
sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
return;
} }
if( !OMIT_TEMPDB && isTemp ) iDb = 1;
pParse->sNameToken = *pName; pParse->sNameToken = *pName;
zName = sqlite3NameFromToken(db, pName);
if( zName==0 ) return; if( zName==0 ) return;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto begin_table_error; goto begin_table_error;
} }
if( db->init.iDb==1 ) isTemp = 1; if( db->init.iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION #ifndef SQLITE_OMIT_AUTHORIZATION
assert( (isTemp & 1)==isTemp ); assert( isTemp==0 || isTemp==1 );
assert( isView==0 || isView==1 );
{ {
int code; static const u8 aCode[] = {
SQLITE_CREATE_TABLE,
SQLITE_CREATE_TEMP_TABLE,
SQLITE_CREATE_VIEW,
SQLITE_CREATE_TEMP_VIEW
};
char *zDb = db->aDb[iDb].zName; char *zDb = db->aDb[iDb].zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
goto begin_table_error; goto begin_table_error;
} }
if( isView ){ if( !isVirtual && sqlite3AuthCheck(pParse, (int)aCode[isTemp+2*isView],
if( !OMIT_TEMPDB && isTemp ){ zName, 0, zDb) ){
code = SQLITE_CREATE_TEMP_VIEW;
}else{
code = SQLITE_CREATE_VIEW;
}
}else{
if( !OMIT_TEMPDB && isTemp ){
code = SQLITE_CREATE_TEMP_TABLE;
}else{
code = SQLITE_CREATE_TABLE;
}
}
if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){
goto begin_table_error; goto begin_table_error;
} }
} }
@ -1864,9 +1849,13 @@ void sqlite3EndTable(
** So do not write to the disk again. Extract the root page number ** So do not write to the disk again. Extract the root page number
** for the table from the db->init.newTnum field. (The page number ** for the table from the db->init.newTnum field. (The page number
** should have been put there by the sqliteOpenCb routine.) ** should have been put there by the sqliteOpenCb routine.)
**
** If the root page number is 1, that means this is the sqlite_master
** table itself. So mark it read-only.
*/ */
if( db->init.busy ){ if( db->init.busy ){
p->tnum = db->init.newTnum; p->tnum = db->init.newTnum;
if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
} }
/* Special processing for WITHOUT ROWID Tables */ /* Special processing for WITHOUT ROWID Tables */
@ -2319,6 +2308,7 @@ void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
static void destroyRootPage(Parse *pParse, int iTable, int iDb){ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse); Vdbe *v = sqlite3GetVdbe(pParse);
int r1 = sqlite3GetTempReg(pParse); int r1 = sqlite3GetTempReg(pParse);
assert( iTable>1 );
sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
sqlite3MayAbort(pParse); sqlite3MayAbort(pParse);
#ifndef SQLITE_OMIT_AUTOVACUUM #ifndef SQLITE_OMIT_AUTOVACUUM

View File

@ -137,61 +137,27 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
#ifndef SQLITE_OMIT_DEPRECATED #ifndef SQLITE_OMIT_DEPRECATED
int size; int size;
#endif #endif
Table *pTab;
Db *pDb; Db *pDb;
char const *azArg[4]; char const *azArg[4];
int meta[5]; int meta[5];
InitData initData; InitData initData;
char const *zMasterSchema; const char *zMasterName;
char const *zMasterName;
int openedTransaction = 0; int openedTransaction = 0;
/*
** The master database table has a structure like this
*/
static const char master_schema[] =
"CREATE TABLE sqlite_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
#ifndef SQLITE_OMIT_TEMPDB
static const char temp_master_schema[] =
"CREATE TEMP TABLE sqlite_temp_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
#else
#define temp_master_schema 0
#endif
assert( iDb>=0 && iDb<db->nDb ); assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pSchema ); assert( db->aDb[iDb].pSchema );
assert( sqlite3_mutex_held(db->mutex) ); assert( sqlite3_mutex_held(db->mutex) );
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
/* zMasterSchema and zInitScript are set to point at the master schema /* Construct the in-memory representation schema tables (sqlite_master or
** and initialisation script appropriate for the database being ** sqlite_temp_master) by invoking the parser directly. The appropriate
** initialized. zMasterName is the name of the master table. ** table name will be inserted automatically by the parser so we can just
*/ ** use the abbreviation "x" here. The parser will also automatically tag
if( !OMIT_TEMPDB && iDb==1 ){ ** the schema table as read-only. */
zMasterSchema = temp_master_schema; azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
}else{
zMasterSchema = master_schema;
}
zMasterName = SCHEMA_TABLE(iDb);
/* Construct the schema tables. */
azArg[0] = zMasterName;
azArg[1] = "1"; azArg[1] = "1";
azArg[2] = zMasterSchema; azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
"rootpage integer,sql text)";
azArg[3] = 0; azArg[3] = 0;
initData.db = db; initData.db = db;
initData.iDb = iDb; initData.iDb = iDb;
@ -202,10 +168,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = initData.rc; rc = initData.rc;
goto error_out; goto error_out;
} }
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( ALWAYS(pTab) ){
pTab->tabFlags |= TF_Readonly;
}
/* Create a cursor to hold the database open /* Create a cursor to hold the database open
*/ */
@ -324,7 +286,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
{ {
char *zSql; char *zSql;
zSql = sqlite3MPrintf(db, zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid", "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
db->aDb[iDb].zName, zMasterName); db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE_OMIT_AUTHORIZATION #ifndef SQLITE_OMIT_AUTHORIZATION
{ {

View File

@ -5099,6 +5099,7 @@ case OP_Destroy: { /* out2 */
int iDb; int iDb;
assert( p->readOnly==0 ); assert( p->readOnly==0 );
assert( pOp->p1>1 );
pOut = out2Prerelease(p, pOp); pOut = out2Prerelease(p, pOp);
pOut->flags = MEM_Null; pOut->flags = MEM_Null;
if( db->nVdbeRead > db->nVDestroy+1 ){ if( db->nVdbeRead > db->nVDestroy+1 ){