Work toward making the schema parsing logic simplier and more compact.
FossilOrigin-Name: c52ca2c0662bb30ab34574f933429512655b19ff
This commit is contained in:
parent
1e38927c12
commit
055f298ad4
20
manifest
20
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
584848d4396d7755027fab377c97e40fbcc90d21
|
||||
c52ca2c0662bb30ab34574f933429512655b19ff
|
119
src/btree.c
119
src/btree.c
@ -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){
|
||||
|
78
src/build.c
78
src/build.c
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 ){
|
||||
|
Loading…
x
Reference in New Issue
Block a user