From: drh Date: Tue, 15 May 2012 18:28:27 +0000 (+0000) Subject: The former sqlite3ResetInternalSchema() routine was really two different X-Git-Tag: version-3.7.13~14^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=81028a455de1b4e8782c3f233369515e83822bde;p=thirdparty%2Fsqlite.git The former sqlite3ResetInternalSchema() routine was really two different routines, selected by parameter, each with a confused mission. So split this routine up into three separate smaller routines, calling each separately as needed. Hopefully this will make further refactoring and schema reset collateral damage containment easier. FossilOrigin-Name: aa0c3493d3647d7efe527067e9fcccefda8e3008 --- diff --git a/manifest b/manifest index ea85d284ac..2d4da7eb65 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sa\sconnection\sdisconnects\sfrom\sa\sshared-cache\sdatabase,\sonly\sdelete\sthe\sin-memory\sschema\sif\sthere\sare\sno\sother\sconnections. -D 2012-05-15T17:15:34.812 +C The\sformer\ssqlite3ResetInternalSchema()\sroutine\swas\sreally\stwo\sdifferent\s\nroutines,\sselected\sby\sparameter,\seach\swith\sa\sconfused\smission.\s\sSo\ssplit\nthis\sroutine\sup\sinto\sthree\sseparate\ssmaller\sroutines,\scalling\seach\nseparately\sas\sneeded.\s\sHopefully\sthis\swill\smake\sfurther\srefactoring\sand\nschema\sreset\scollateral\sdamage\scontainment\seasier. +D 2012-05-15T18:28:27.325 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -113,15 +113,15 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad F src/alter.c 149cc80d9257971b0bff34e58fb2263e01998289 F src/analyze.c 70c46504c0d2543ea5cdca01140b2cd3e1d886e7 -F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f +F src/attach.c 577bf5675b0c50495fc28549f2fcbdb1bac71143 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 -F src/backup.c 6be23a344d3301ae38e92fddb3a33b91c309fce4 +F src/backup.c d7fb4c6d2ad3fe51a4ce1a897fde7b00f4de5fef F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c df800f10896bc2ddaa1125c532d6e7a7b9efc532 F src/btree.h 48a013f8964f12d944d90e4700df47b72dd6d923 F src/btreeInt.h 38a639c0542c29fe8331a221c4aed0cb8686249e -F src/build.c 95fd8aa1bf81acf15e9ef46b07d1f70111ea88d0 +F src/build.c 6da3a261958d79805df198808b35209e93acf52d F src/callback.c 0cb4228cdcd827dcc5def98fb099edcc9142dbcd F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33 @@ -140,7 +140,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416 F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d -F src/main.c 62146c65069408bc66ad72954655c9cc14bd8f01 +F src/main.c 28804c01149c1e707418434a42dc36438acdc5c8 F src/malloc.c 15afac5e59b6584efe072e9933aefb4230e74f97 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1 @@ -167,8 +167,8 @@ F src/parse.y f29df90bd3adc64b33114ab1de9fb7768fcf2099 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c F src/pcache1.c b30b1c35908346ecc43d8d9d17f2ddf6817f8f60 -F src/pragma.c e708b3bb5704605816f617e0b1d63a5488060715 -F src/prepare.c 9a00a9612ebf80203fbb41f8a29ab8cb27a05f40 +F src/pragma.c 28d7955a9e9a27d41cb462690228d39e3cec231c +F src/prepare.c ef197444dac110ee57a5f49745368b447a8c6bd1 F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 748e75299faff345f34f0e5bd02a2bac8aa69fcd @@ -177,7 +177,7 @@ F src/select.c d7b9018b7dd2e821183d69477ab55c39b8272335 F src/shell.c 04399b2f9942bd02ed5ffee3b84bcdb39c52a1e6 F src/sqlite.h.in 4f4d4792f6fb00387c877af013cb09d955643f12 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 -F src/sqliteInt.h cef468b8f16c847c235cb9a3d06253389abe3bc9 +F src/sqliteInt.h 05b22e581622128168d786a7c852d1763dd45559 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -233,8 +233,8 @@ F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684 F src/update.c d3076782c887c10e882996550345da9c4c9f9dea F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84 F src/util.c 4f6cfad661b2e3454b0cdd5b1b9d39a54942d0e3 -F src/vacuum.c bfd53f9bd20a8fdb70b0fa8e77182b866875c0d8 -F src/vdbe.c e1d26b98288889c22f00cf4851ec351ee67ad8b9 +F src/vacuum.c 587a52bb8833d7ac15af8916f25437e2575028bd +F src/vdbe.c 6ed3e89957a0dd55e9c4ab7842949051ba8eaaa9 F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb F src/vdbeInt.h 6ff4180a05683566a8835d12f7ec504b22932c82 F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91 @@ -243,7 +243,7 @@ F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb F src/vdbemem.c cb55e84b8e2c15704968ee05f0fae25883299b74 F src/vdbesort.c b25814d385895544ebc8118245c8311ded7f81c9 F src/vdbetrace.c d6e50e04e1ec498150e519058f617d91b8f5c843 -F src/vtab.c 1fbe133809ae542a9cf3a3d8187774b68436fa85 +F src/vtab.c 4c1d7e7206aa330da12cfbed29bbe08a5fd2c08e F src/wal.c 7bb3ad807afc7973406c805d5157ec7a2f65e146 F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f @@ -998,10 +998,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 736d6ea677f58e4aa2914fa79a3156b775c5a3f5 -R cdb1dff646b0010ea62b89ecb700e74c -T *branch * shared-schema -T *sym-shared-schema * -T -sym-trunk * -U dan -Z 9910d0bfd0815b5cd0d4b52750333b7f +P 46f4eb5430d7bc9a339cdf7124ff4bd518eaa39b +R 3470c7e3b0ec734f279c648e5bd9b93d +U drh +Z 93dd6b08b78f998064cdd25b32f8367e diff --git a/manifest.uuid b/manifest.uuid index 917ae6d0b9..680e37e511 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -46f4eb5430d7bc9a339cdf7124ff4bd518eaa39b \ No newline at end of file +aa0c3493d3647d7efe527067e9fcccefda8e3008 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 18f8823b31..e295c30111 100644 --- a/src/attach.c +++ b/src/attach.c @@ -216,7 +216,7 @@ static void attachFunc( db->aDb[iDb].pBt = 0; db->aDb[iDb].pSchema = 0; } - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); db->nDb = iDb; if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ db->mallocFailed = 1; @@ -288,7 +288,7 @@ static void detachFunc( sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); return; detach_error: diff --git a/src/backup.c b/src/backup.c index 7a4047f34c..0ada33c3be 100644 --- a/src/backup.c +++ b/src/backup.c @@ -414,7 +414,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); if( rc==SQLITE_OK ){ if( p->pDestDb ){ - sqlite3ResetInternalSchema(p->pDestDb, -1); + sqlite3ResetAllSchemasOfConnection(p->pDestDb); } if( destMode==PAGER_JOURNALMODE_WAL ){ rc = sqlite3BtreeSetVersion(p->pDest, 2); diff --git a/src/build.c b/src/build.c index e02f0402fc..3eefac9391 100644 --- a/src/build.c +++ b/src/build.c @@ -394,58 +394,15 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ } /* -** Erase all schema information from the in-memory hash tables of -** a single database. This routine is called to reclaim memory -** before the database closes. It is also called during a rollback -** if there were schema changes during the transaction or if a -** schema-cookie mismatch occurs. +** Look through the list of open database files in db->aDb[] and if +** any have been closed, remove them from the list. Reallocate the +** db->aDb[] structure to a smaller size, if possible. ** -** 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. +** Entry 0 (the "main" database) and entry 1 (the "temp" database) +** are never candidates for being collapsed. */ -void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ +void sqlite3CollapseDatabaseArray(sqlite3 *db){ int i, j; - assert( iDbnDb ); - - if( iDb>=0 ){ - /* Case 1: Reset the single schema identified by iDb */ - Db *pDb = &db->aDb[iDb]; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - assert( pDb->pSchema!=0 ); - 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]; - assert( pDb->pSchema!=0 ); - sqlite3SchemaClear(pDb->pSchema); - } - return; - } - /* Case 2 (from here to the end): Reset all schemas for all attached - ** databases. */ - assert( iDb<0 ); - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Db *pDb = &db->aDb[i]; - if( pDb->pSchema ){ - sqlite3SchemaClear(pDb->pSchema); - } - } - db->flags &= ~SQLITE_InternChanges; - sqlite3VtabUnlockList(db); - sqlite3BtreeLeaveAll(db); - - /* If one or more of the auxiliary database files has been closed, - ** then remove them from the auxiliary database list. We take the - ** opportunity to do this here since we have just deleted all of the - ** schema hash tables and therefore do not have to make any changes - ** to any of those tables. - */ for(i=j=2; inDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ @@ -467,6 +424,50 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ } } +/* +** Reset the schema for the database at index iDb. Also reset the +** TEMP schema. +*/ +void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ + assert( iDbnDb ); + + /* Case 1: Reset the single schema identified by iDb */ + Db *pDb = &db->aDb[iDb]; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + assert( pDb->pSchema!=0 ); + 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]; + assert( pDb->pSchema!=0 ); + sqlite3SchemaClear(pDb->pSchema); + } + return; +} + +/* +** Erase all schema information from all attached databases (including +** "main" and "temp") for a single database connection. +*/ +void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ + int i; + sqlite3BtreeEnterAll(db); + for(i=0; inDb; i++){ + Db *pDb = &db->aDb[i]; + if( pDb->pSchema ){ + sqlite3SchemaClear(pDb->pSchema); + } + } + db->flags &= ~SQLITE_InternChanges; + sqlite3VtabUnlockList(db); + sqlite3BtreeLeaveAll(db); + sqlite3CollapseDatabaseArray(db); +} + /* ** This routine is called when a commit occurs. */ diff --git a/src/main.c b/src/main.c index 869fbb376b..c0c7aa5f66 100644 --- a/src/main.c +++ b/src/main.c @@ -806,7 +806,7 @@ int sqlite3_close(sqlite3 *db){ /* This call frees the schema associated with the temp database only (if ** any). It also frees the db->aDb array, if required. */ - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); assert( db->nDb<=2 ); assert( db->aDb==db->aDbStatic ); @@ -901,7 +901,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ if( db->flags&SQLITE_InternChanges ){ sqlite3ExpirePreparedStatements(db); - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); } /* Any deferred constraint violations have now been resolved. */ diff --git a/src/pragma.c b/src/pragma.c index 2db0b61508..3401c73c1b 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -118,7 +118,7 @@ static int invalidateTempStorage(Parse *pParse){ } sqlite3BtreeClose(db->aDb[1].pBt); db->aDb[1].pBt = 0; - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); } return SQLITE_OK; } diff --git a/src/prepare.c b/src/prepare.c index c46e55ed2c..f1dbb6b3b0 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -342,7 +342,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ } if( db->mallocFailed ){ rc = SQLITE_NOMEM; - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); } if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider @@ -395,7 +395,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqlite3InitOne(db, i, pzErrMsg); if( rc ){ - sqlite3ResetInternalSchema(db, i); + sqlite3ResetOneSchema(db, i); } } @@ -408,7 +408,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); if( rc ){ - sqlite3ResetInternalSchema(db, 1); + sqlite3ResetOneSchema(db, 1); } } #endif @@ -476,7 +476,7 @@ static void schemaIsValid(Parse *pParse){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ - sqlite3ResetInternalSchema(db, iDb); + sqlite3ResetOneSchema(db, iDb); pParse->rc = SQLITE_SCHEMA; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index cefff07ec5..8cd022d7a5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2696,7 +2696,9 @@ void sqlite3ExprListDelete(sqlite3*, ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); -void sqlite3ResetInternalSchema(sqlite3*, int); +void sqlite3ResetAllSchemasOfConnection(sqlite3*); +void sqlite3ResetOneSchema(sqlite3*,int); +void sqlite3CollapseDatabaseArray(sqlite3*); void sqlite3BeginParse(Parse*,int); void sqlite3CommitInternalChanges(sqlite3*); Table *sqlite3ResultSetOfSelect(Parse*,Select*); diff --git a/src/vacuum.c b/src/vacuum.c index c03b4500b3..401d41dfb7 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -339,7 +339,7 @@ end_of_vacuum: /* This both clears the schemas and reduces the size of the db->aDb[] ** array. */ - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); return rc; } diff --git a/src/vdbe.c b/src/vdbe.c index fa5180c9a4..aa42a0f735 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2747,7 +2747,7 @@ case OP_Savepoint: { } if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ sqlite3ExpirePreparedStatements(db); - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); db->flags = (db->flags | SQLITE_InternChanges); } } @@ -3051,7 +3051,7 @@ case OP_VerifyCookie: { ** a v-table method. */ if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ - sqlite3ResetInternalSchema(db, pOp->p1); + sqlite3ResetOneSchema(db, pOp->p1); } p->expired = 1; @@ -4864,7 +4864,7 @@ case OP_ParseSchema: { db->init.busy = 0; } } - if( rc ) sqlite3ResetInternalSchema(db, -1); + if( rc ) sqlite3ResetAllSchemasOfConnection(db); if( rc==SQLITE_NOMEM ){ goto no_mem; } @@ -6159,7 +6159,7 @@ vdbe_error_halt: if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; if( resetSchemaOnFault>0 ){ - sqlite3ResetInternalSchema(db, resetSchemaOnFault-1); + sqlite3ResetOneSchema(db, resetSchemaOnFault-1); } /* This is the only way out of this procedure. We have to diff --git a/src/vtab.c b/src/vtab.c index f660b54439..24eee1a81a 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -22,8 +22,8 @@ ** are invoked only from within xCreate and xConnect methods. */ struct VtabCtx { - Table *pTab; - VTable *pVTable; + VTable *pVTable; /* The virtual table being constructed */ + Table *pTab; /* The Table object to which the virtual table belongs */ }; /* @@ -54,7 +54,7 @@ static int createModule( pMod->xDestroy = xDestroy; pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod); if( pDel && pDel->xDestroy ){ - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); pDel->xDestroy(pDel->pAux); } sqlite3DbFree(db, pDel);