diff options
Diffstat (limited to 'src/build.c')
-rw-r--r-- | src/build.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/src/build.c b/src/build.c index b4528347d..7e73b6a8e 100644 --- a/src/build.c +++ b/src/build.c @@ -156,6 +156,7 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); if( db->init.busy==0 ){ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); sqlite3VdbeAddOp3(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb], db->aDb[iDb].pSchema->iGeneration); @@ -271,9 +272,12 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ int nName; assert( zName!=0 ); nName = sqlite3Strlen30(zName); + /* All mutexes are required for schema access. Make sure we hold them. */ + assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; + assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName); if( p ) break; } @@ -333,11 +337,14 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; int nName = sqlite3Strlen30(zName); + /* All mutexes are required for schema access. Make sure we hold them. */ + assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ Schema *pSchema = db->aDb[j].pSchema; assert( pSchema ); if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; + assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&pSchema->idxHash, zName, nName); if( p ) break; } @@ -364,8 +371,10 @@ static void freeIndex(sqlite3 *db, Index *p){ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; int len; - Hash *pHash = &db->aDb[iDb].pSchema->idxHash; + Hash *pHash; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + pHash = &db->aDb[iDb].pSchema->idxHash; len = sqlite3Strlen30(zIdxName); pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0); if( ALWAYS(pIndex) ){ @@ -393,26 +402,40 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ ** if there were schema changes during the transaction or if a ** schema-cookie mismatch occurs. ** -** If iDb==0 then reset the internal schema tables for all database -** files. If iDb>=1 then reset the internal schema for only the +** If iDb<0 then reset the internal schema tables for all database +** files. If iDb>=0 then reset the internal schema for only the ** single file indicated. */ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ int i, j; - assert( iDb>=0 && iDb<db->nDb ); + assert( iDb<db->nDb ); - if( iDb==0 ){ - sqlite3BtreeEnterAll(db); + if( iDb>=0 ){ + /* Case 1: Reset the single schema identified by iDb */ + Db *pDb = &db->aDb[iDb]; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + if( ALWAYS(pDb->pSchema) ){ + sqlite3SchemaClear(pDb->pSchema); + } + /* If any database other than TEMP is reset, then also reset TEMP + ** since TEMP might be holding triggers that reference tables in the + ** other database. + */ + if( iDb!=1 && (pDb = &db->aDb[1])!=0 && ALWAYS(pDb->pSchema) ){ + sqlite3SchemaClear(pDb->pSchema); + } + return; } - for(i=iDb; i<db->nDb; i++){ + /* Case 2 (from here to the end): Reset all schemas for all attached + ** databases. */ + assert( iDb<0 ); + sqlite3BtreeEnterAll(db); + for(i=0; i<db->nDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ - assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); - sqlite3SchemaFree(pDb->pSchema); + sqlite3SchemaClear(pDb->pSchema); } - if( iDb>0 ) return; } - assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); @@ -498,6 +521,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ TESTONLY ( Index *pOld = ) sqlite3HashInsert( &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0 ); + assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); } freeIndex(db, pIndex); @@ -532,6 +556,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ assert( db!=0 ); assert( iDb>=0 && iDb<db->nDb ); assert( zTabName ); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ pDb = &db->aDb[iDb]; p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, @@ -816,6 +841,7 @@ void sqlite3StartTable( */ #ifndef SQLITE_OMIT_AUTOINCREMENT if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pTable->pSchema->pSeqTab = pTable; } #endif @@ -1276,6 +1302,7 @@ void sqlite3ChangeCookie(Parse *pParse, int iDb){ int r1 = sqlite3GetTempReg(pParse); sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1); sqlite3ReleaseTempReg(pParse, r1); @@ -1578,6 +1605,7 @@ void sqlite3EndTable( */ if( p->tabFlags & TF_Autoincrement ){ Db *pDb = &db->aDb[iDb]; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", @@ -1598,6 +1626,7 @@ void sqlite3EndTable( if( db->init.busy ){ Table *pOld; Schema *pSchema = p->pSchema; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, sqlite3Strlen30(p->zName),p); if( pOld ){ @@ -1782,6 +1811,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ pSelTab->nCol = 0; pSelTab->aCol = 0; sqlite3DeleteTable(db, pSelTab); + assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); pTable->pSchema->flags |= DB_UnresetViews; }else{ pTable->nCol = 0; @@ -1802,6 +1832,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ */ static void sqliteViewResetAll(sqlite3 *db, int idx){ HashElem *i; + assert( sqlite3SchemaMutexHeld(db, idx, 0) ); if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); @@ -1835,10 +1866,13 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){ ** in order to be certain that we got the right one. */ #ifndef SQLITE_OMIT_AUTOVACUUM -void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){ +void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){ HashElem *pElem; Hash *pHash; + Db *pDb; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + pDb = &db->aDb[iDb]; pHash = &pDb->pSchema->tblHash; for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); @@ -2212,6 +2246,7 @@ void sqlite3CreateForeignKey( pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */ pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */ + assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey ); @@ -2567,6 +2602,7 @@ Index *sqlite3CreateIndex( pIndex->onError = (u8)onError; pIndex->autoIndex = (u8)(pName==0); pIndex->pSchema = db->aDb[iDb].pSchema; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); /* Check to see if we should honor DESC requests on index columns */ @@ -2696,6 +2732,7 @@ Index *sqlite3CreateIndex( */ if( db->init.busy ){ Index *p; + assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); p = sqlite3HashInsert(&pIndex->pSchema->idxHash, pIndex->zName, sqlite3Strlen30(pIndex->zName), pIndex); @@ -3449,6 +3486,7 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ assert( iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDb<SQLITE_MAX_ATTACHED+2 ); + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); mask = ((yDbMask)1)<<iDb; if( (pToplevel->cookieMask & mask)==0 ){ pToplevel->cookieMask |= mask; @@ -3576,6 +3614,7 @@ static void reindexDatabases(Parse *pParse, char const *zColl){ HashElem *k; /* For looping over tables in pDb */ Table *pTab; /* A table in the database */ + assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ assert( pDb!=0 ); for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ |