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.
D 2016-01-15T05:39:55.053
C Work\stoward\smaking\sthe\sschema\sparsing\slogic\ssimplier\sand\smore\scompact.
D 2016-01-15T15:06:41.166
F Makefile.in a476545d0c8626224d0bacac85c6e2967474af81
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 01e855f958932d0d3ed62ec675fc63e2cef61fcb
@ -284,10 +284,10 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc
F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c 5d93e2477acb99d50a8b045f2e26a0be3d7751fe
F src/btree.c d9c6b2e2df06314079aa582f12937401a62171a6
F src/btree.h 68ef301795e00cdf1d3ab93abc44a43b7fe771e0
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
F src/build.c 9d497ff4bf3c82cecb520436e0e9963785627583
F src/build.c 2778ccdb327923b2eb6cea304e232efd0c85cbe1
F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
@ -336,7 +336,7 @@ F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/prepare.c 74855ddbdfad6a1c4a4d5c4b0913ebb01174ba19
F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 08dbe0292b24abc79b0c55ea97368e8a6bd235ec
@ -406,7 +406,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3
F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3
F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c 4f3585480f61f96af3327e921baad223af0ce23e
F src/vdbe.c b90d9d38e5e0260c2eafa3cb4c2274d8ea94da27
F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637
F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189
F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e
@ -1415,7 +1415,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 0d1b3d7d3ca66cb0b97493f1aeade1703af3c9f4
R b460170dac8e7d7fa7ff80be818c5f70
U mistachkin
Z 9c8571095ec15b56fdafaa6935514e64
P 584848d4396d7755027fab377c97e40fbcc90d21
R d396ff3cd92323018eeceb835a86df32
U drh
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;
}
/*
** 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);
if( rc ) return rc;
rc = sqlite3BtreeClearTable(p, iTable, 0);
@ -8551,76 +8559,67 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
*piMoved = 0;
if( iTable>1 ){
#ifdef SQLITE_OMIT_AUTOVACUUM
freePage(pPage, &rc);
releasePage(pPage);
freePage(pPage, &rc);
releasePage(pPage);
#else
if( pBt->autoVacuum ){
Pgno maxRootPgno;
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno);
if( pBt->autoVacuum ){
Pgno maxRootPgno;
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno);
if( iTable==maxRootPgno ){
/* 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.
*/
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.
if( iTable==maxRootPgno ){
/* 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.
*/
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);
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{
/* If sqlite3BtreeDropTable was called on page 1.
** This really never should happen except in a corrupt
** database.
/* 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.
*/
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);
}
#endif
return rc;
}
int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){

View File

@ -758,7 +758,8 @@ int sqlite3TwoPartName(
int iDb; /* Database holding the object */
sqlite3 *db = pParse->db;
if( ALWAYS(pName2!=0) && pName2->n>0 ){
assert( pName2!=0 );
if( pName2->n>0 ){
if( db->init.busy ) {
sqlite3ErrorMsg(pParse, "corrupt database");
return -1;
@ -847,62 +848,46 @@ void sqlite3StartTable(
int iDb; /* Database number to create the table in */
Token *pName; /* Unqualified name of the table to create */
/* The table or view name to create is passed to this routine via tokens
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
**
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
** CREATE TABLE yyy(...);
**
** Then pName1 is set to "yyy" and pName2 is "".
**
** The call below sets the pName pointer to point at the token (pName1 or
** pName2) that stores the unqualified table name. The variable iDb is
** set to the index of the database that the table or view is to be
** created in.
*/
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( db->init.busy && db->init.newTnum==1 ){
/* Special case: Parsing the sqlite_master or sqlite_temp_master schema */
iDb = db->init.iDb;
zName = sqlite3DbStrDup(db, SCHEMA_TABLE(iDb));
pName = pName1;
}else{
/* The common case */
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;
zName = sqlite3NameFromToken(db, pName);
}
if( !OMIT_TEMPDB && isTemp ) iDb = 1;
pParse->sNameToken = *pName;
zName = sqlite3NameFromToken(db, pName);
if( zName==0 ) return;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto begin_table_error;
}
if( db->init.iDb==1 ) isTemp = 1;
#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;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
goto begin_table_error;
}
if( isView ){
if( !OMIT_TEMPDB && isTemp ){
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) ){
if( !isVirtual && sqlite3AuthCheck(pParse, (int)aCode[isTemp+2*isView],
zName, 0, zDb) ){
goto begin_table_error;
}
}
@ -1864,9 +1849,13 @@ void sqlite3EndTable(
** 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
** 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 ){
p->tnum = db->init.newTnum;
if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
}
/* 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){
Vdbe *v = sqlite3GetVdbe(pParse);
int r1 = sqlite3GetTempReg(pParse);
assert( iTable>1 );
sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
sqlite3MayAbort(pParse);
#ifndef SQLITE_OMIT_AUTOVACUUM

View File

@ -137,61 +137,27 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
#ifndef SQLITE_OMIT_DEPRECATED
int size;
#endif
Table *pTab;
Db *pDb;
char const *azArg[4];
int meta[5];
InitData initData;
char const *zMasterSchema;
char const *zMasterName;
const char *zMasterName;
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( db->aDb[iDb].pSchema );
assert( sqlite3_mutex_held(db->mutex) );
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
/* zMasterSchema and zInitScript are set to point at the master schema
** and initialisation script appropriate for the database being
** initialized. zMasterName is the name of the master table.
*/
if( !OMIT_TEMPDB && iDb==1 ){
zMasterSchema = temp_master_schema;
}else{
zMasterSchema = master_schema;
}
zMasterName = SCHEMA_TABLE(iDb);
/* Construct the schema tables. */
azArg[0] = zMasterName;
/* Construct the in-memory representation schema tables (sqlite_master or
** sqlite_temp_master) by invoking the parser directly. The appropriate
** table name will be inserted automatically by the parser so we can just
** use the abbreviation "x" here. The parser will also automatically tag
** the schema table as read-only. */
azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
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;
initData.db = db;
initData.iDb = iDb;
@ -202,10 +168,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = initData.rc;
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
*/
@ -324,7 +286,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
{
char *zSql;
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);
#ifndef SQLITE_OMIT_AUTHORIZATION
{

View File

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