Additional schema mutex checks for sqlite3RootPageMoved().
Reduce the scope of sqlite3ResetInternalSchema() in a few places.
FossilOrigin-Name: 39c00907833413c0d97d3e06fdda967b825d23ea
diff --git a/src/build.c b/src/build.c
index 51b7905..7e73b6a 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1866,10 +1866,13 @@
** 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);
diff --git a/src/prepare.c b/src/prepare.c
index aad2bc0..b5edaf5 100644
--- a/src/prepare.c
+++ b/src/prepare.c
@@ -472,6 +472,7 @@
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
+ sqlite3ResetInternalSchema(db, iDb);
pParse->rc = SQLITE_SCHEMA;
}
@@ -613,9 +614,6 @@
if( pParse->checkSchema ){
schemaIsValid(pParse);
}
- if( pParse->rc==SQLITE_SCHEMA ){
- sqlite3ResetInternalSchema(db, -1);
- }
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM;
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 1d8194a..b874c5e 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2956,7 +2956,7 @@
extern int sqlite3PendingByte;
#endif
#endif
-void sqlite3RootPageMoved(Db*, int, int);
+void sqlite3RootPageMoved(sqlite3*, int, int, int);
void sqlite3Reindex(Parse*, Token*, Token*);
void sqlite3AlterFunctions(void);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
diff --git a/src/vdbe.c b/src/vdbe.c
index 6dc305d..94fd0ff 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -551,7 +551,7 @@
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
- u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */
+ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
u8 encoding = ENC(db); /* The database encoding */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int checkProgress; /* True if progress callbacks are enabled */
@@ -2953,7 +2953,6 @@
*/
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
sqlite3ResetInternalSchema(db, pOp->p1);
- sqlite3VdbeMutexResync(p);
}
p->expired = 1;
@@ -4534,8 +4533,10 @@
pOut->u.i = iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( rc==SQLITE_OK && iMoved!=0 ){
- sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1);
- resetSchemaOnFault = 1;
+ sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1);
+ /* All OP_Destroy operations occur on the same btree */
+ assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 );
+ resetSchemaOnFault = iDb+1;
}
#endif
}
@@ -5969,9 +5970,8 @@
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
- if( resetSchemaOnFault ){
- sqlite3ResetInternalSchema(db, 0);
- sqlite3VdbeMutexResync(p);
+ if( resetSchemaOnFault>0 ){
+ sqlite3ResetInternalSchema(db, resetSchemaOnFault-1);
}
/* This is the only way out of this procedure. We have to