-C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
-D 2019-02-11T20:13:13.880
+C Share\sschemas\sbetween\sdatabases\sattached\sto\sthe\ssame\sdatabase\shandle.
+D 2019-02-12T19:20:33.146
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 56456706c4da271309914c756c9c8ea537685f1c79f8785afa72f968d6810482
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 995b37de876639f1b6c14fcf15f3ee1004e3cbea354ebb43d7f5c4de0d649a64
F src/analyze.c e75c3c1d6534265f74a4763282f17e9ad946606ef0a68c5517fcfb355cc243d0
-F src/attach.c 3f9b0f6c79500cc40f4e543bc130a0b4ee13f52b45cbb6735608776cbdb79f0e
+F src/attach.c 99c6496d244e2d43b96d8f22381e55236953cbd75273e40a072154ba0b23151c
F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btree.c 18046bf14f0e3fa294ef3f7c2dc30ca7e95f3ac11ec222ad906e40b150051bde
F src/btree.h 63b94fb38ce571c15eb6a3661815561b501d23d5948b2d1e951fbd7a2d04e8d3
F src/btreeInt.h cd82f0f08886078bf99b29e1a7045960b1ca5d9d5829c38607e1299c508eaf00
-F src/build.c 4406cadbd4dffa2f3a5e01c6264344d6caf69238c71736e3557405bb39030cd8
-F src/callback.c eca06835c52403036e200f0add94174aa3ca6bd128546a1877f6826697ebdf5b
+F src/build.c 70fa06d96fd4265652921c52c40e664e3b6f7d1b8fce9702976dff56a0117e81
+F src/callback.c eaa832c5b8b6f64e9ca78f61c3d9034a6a4d697ae426dbbc7de1c760045f6dc3
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf
F src/expr.c 182dc9ff30aa6a430b7f728ce84fda85ec10890e29fdf75be1e871d13222a99c
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c bd0138acdc008c1845ccf92f8e73787880562de649471804801c06fed814c765
+F src/fkey.c 878bec1b4d9aab3b34585121b834fce9b2780352b7282510e4ffc94b75ce6c83
F src/func.c 0341881d22903aac5ba7f352b188806d6436e1d6ae4235ff01e44d56879dfe63
F src/global.c 0dea3065ea72a65ae941559b6686aad6516d4913e76fa4f79a95ff7787f624ec
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/pcache1.c a72804486dfa8e4b6bc30d666c97ecf1155f91a4351fc6e48ea4097e4eb304fb
F src/pragma.c af67dedaad8bafe9a5f9adcec32a0da6dd118617dd8220ad1d118f5a6bf83a02
F src/pragma.h a776bb9c915207e9d1117b5754743ddf1bf6a39cc092a4a44e74e6cb5fab1177
-F src/prepare.c c73b6ab0290a41066850b4c855643bd1d2c854e540373351492cdbb6628e51ae
+F src/prepare.c c8bd9570e92b879023d5750412f81ac6613f3754c2462ee26fce9945d1fbc3a9
F src/printf.c cbf27c320091a83279d1738f68a27a9fe01698c607ce80516ab6bdb5a9c36a1a
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 1588690ee4cc39b4b9ea3230d4e3543d5ec3b5e898c87521f1375af0f1934cd4
F src/sqlite.h.in 528af7447d87ca678409b3280faa3905bab5fab265590821b0df0c8bc956e3a2
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
-F src/sqliteInt.h 2ddea4f7ce00097eb080c2c82f07606f91bb313df3f086c61ffa78220c1e10a0
+F src/sqliteInt.h 6173e47d1cddb8c9aa5ccfaa0f40b9f62635050d503245e6439b3cd96fb6a53d
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 41d9cc5d5f9d2a470dcf0a28432c66e25c15b86e51535283e9aef632adf02ac8
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c 82a2e3f691a3b654be872e305dab1f455e565dedf5e6a90c818c1ab307c00432
F src/vacuum.c 7dbed4a756f014f3ce54e6ae3c403ee725e8179cf73fc6dd5c064e5627649f9f
-F src/vdbe.c 4b593855fb962534718b7f2cf1427d8c32d6d7743ea7e6debd0674345ca50812
+F src/vdbe.c a9a47fee453e93a725469b3c6d9b58425178658ed3ec50709a08408a293773b3
F src/vdbe.h 323218c4bfd64c719ba85d05fbc87cdd126991cadb39e73ccac7b59f30c3d53e
F src/vdbeInt.h a76d5eed62c76bcd8de7afd3147fac1bc40c5a870582664bcd7d071ef437c37f
F src/vdbeapi.c 57a2d794a8833f269b878dbc24e955369bdb379af6c4e93ebc5ce1a20fa3daf4
F test/releasetest.tcl 7712811e0f4e2f198ec786cb2e1352b3793d7395f48a3cceef0572d8823eb75e x
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
-F test/reuse1.test 34781abbe671ec6858fb5969efadc1b3be1f95a6b46483c227fa6055645a8482
-F test/reuse2.test 5722f9da159adc271af2b0e658ab0455253f63f8613b6016b2963685c813081d
+F test/reuse1.test 5eee2efc7ee559fa9bdd214e35b351d5a949ad466c1671c256fee1f133e7eeea
+F test/reuse2.test 03216f8879c6cff34614237bbf28ebea8433d7dabd62419458d4e16279ac6fb3
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 2ebeb747832bd53284ab23b4c2558f0fa550c0ea2b4a6c1640eeb83f8132c556 09e337386beb2008eba969f79601d1b8ed953951ce6e43782586e168140d78d2
-R 222bf41ad3d7e5e224508834a065b9a0
+P dbedd81bf2e29ae9ed88526c1cc97e5c4d0a256ad7d960304bbb5e15c44f51f0
+R 14fe2aae9901ea2c51f09b6a35487b91
U dan
-Z 7f2395c847d339f950a01f130fcddd71
+Z e0c4573554e8346fa5f24c3693c882d2
-dbedd81bf2e29ae9ed88526c1cc97e5c4d0a256ad7d960304bbb5e15c44f51f0
\ No newline at end of file
+ea611d7cba604dc901c8088ccfa13367a5ee75f9499ea8d8b62a590daac2eae0
\ No newline at end of file
** way we found it.
*/
if( rc==SQLITE_OK ){
- sqlite3BtreeEnterAll(db);
db->init.iDb = 0;
db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
- rc = sqlite3Init(db, &zErrDyn);
- sqlite3BtreeLeaveAll(db);
- assert( zErrDyn==0 || rc!=SQLITE_OK );
+ if( !IsReuseSchema(db) ){
+ sqlite3BtreeEnterAll(db);
+ rc = sqlite3Init(db, &zErrDyn);
+ sqlite3BtreeLeaveAll(db);
+ assert( zErrDyn==0 || rc!=SQLITE_OK );
+ }
}
#ifdef SQLITE_USER_AUTHENTICATION
if( rc==SQLITE_OK ){
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].zDbSName)==0 ){
+ int bUnload = 0;
assert( sqlite3SchemaMutexHeld(db, j, 0) );
+ if( IsReuseSchema(db)
+ && DbHasProperty(db, j, DB_SchemaLoaded)==0
+ && db->init.busy==0
+ ){
+ sqlite3InitOne(db, j, 0, 0);
+ bUnload = (j!=1);
+ }
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
if( p ) return p;
+ if( bUnload ){
+ sqlite3SchemaRelease(db, j);
+ }
}
}
/* Not found. If the name we were looking for was temp.sqlite_master
/* Read the database schema. If an error occurs, leave an error message
** and code in pParse and return NULL. */
if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0
+ && !IsReuseSchema(db)
&& SQLITE_OK!=sqlite3ReadSchema(pParse)
){
return 0;
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
- if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
- return pMod->pEpoTab;
+ if( pMod ){
+ if( IsReuseSchema(db)
+ && DbHasProperty(db, 0, DB_SchemaLoaded)==0
+ && db->init.busy==0
+ ){
+ sqlite3InitOne(db, 0, 0, 0);
+ }
+ if( sqlite3VtabEponymousTableInit(pParse, pMod) ){
+ return pMod->pEpoTab;
+ }
}
}
#endif
if( db->nSchemaLock==0 ){
for(i=0; i<db->nDb; i++){
if( DbHasProperty(db, i, DB_ResetWanted) ){
- sqlite3SchemaZero(db, i);
+ sqlite3SchemaClearOrDisconnect(db, i);
}
}
}
Db *pDb = &db->aDb[i];
if( pDb->pSchema ){
if( db->nSchemaLock==0 ){
- sqlite3SchemaClear(pDb->pSchema);
+ sqlite3SchemaClearOrDisconnect(db, i);
}else{
DbSetProperty(db, i, DB_ResetWanted);
}
pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted);
}
-void sqlite3SchemaZero(sqlite3 *db, int iDb){
+/*
+** If this database was opened with the SQLITE_OPEN_REUSE_SCHEMA flag
+** and iDb!=1, then disconnect from the schema-pool associated with
+** database iDb. Otherwise, clear the Schema object belonging to
+** database iDb.
+**
+** If an OOM error occurs while disconnecting from a schema-pool,
+** the db->mallocFailed flag is set.
+*/
+void sqlite3SchemaClearOrDisconnect(sqlite3 *db, int iDb){
Db *pDb = &db->aDb[iDb];
if( IsReuseSchema(db) && iDb!=1 ){
- if( pDb->pSPool ){
- Schema *pNew = sqlite3SchemaGet(db, 0);
- if( pNew ){
- sqlite3SchemaDisconnect(db, iDb, 0);
- pDb->pSchema = pNew;
- }
- return;
- }
+ sqlite3SchemaDisconnect(db, iDb, 1);
+ }else{
+ sqlite3SchemaClear(pDb->pSchema);
}
- sqlite3SchemaClear(pDb->pSchema);
}
/*
for(i=0; i<db->nDb; i++){
if( i!=1 ){
Db *pDb = &db->aDb[i];
- if( pDb->pSPool && pDb->pSchema && DbHasProperty(db,i,DB_SchemaLoaded) ){
+ if( pDb->pSPool && DbHasProperty(db,i,DB_SchemaLoaded) ){
schemaRelease(pDb);
}
}
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
+void sqlite3SchemaRelease(sqlite3 *db, int iDb){
+ Db *pDb = &db->aDb[iDb];
+ assert( iDb!=1 );
+ assert_schema_state_ok(db);
+ sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
+ if( pDb->pSPool && DbHasProperty(db, iDb, DB_SchemaLoaded) ){
+ schemaRelease(pDb);
+ }
+ sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
+}
+
/*
** Find and return the schema associated with a BTree. Create
** a new one if necessary.
FKey *pFKey; /* Iterator variable */
FKey *pNext; /* Copy of pFKey->pNextFrom */
- assert( db==0 || IsVirtual(pTab)
- || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
+ assert( db==0 || IsVirtual(pTab)
+ || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
/* Remove the FK from the fkeyHash hash table. */
if( !db || db->pnBytesFreed==0 ){
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
pDb = &db->aDb[iDb];
+ assert( pDb->pSPool==0 || IsReuseSchema(db) );
if( pDb->pSPool ){
- assert( IsReuseSchema(db) );
/* See if there is a free schema object in the schema-pool. If not,
** disconnect from said schema pool and continue. This function will
** connect to a (possibly different) schema-pool before returning. */
- if( (pDb->pSchema = sqlite3SchemaExtract(pDb->pSPool)) ){
+ Schema *pNew = sqlite3SchemaExtract(pDb->pSPool);
+ if( pNew ){
+ pDb->pSchema = pNew;
return SQLITE_OK;
}
rc = sqlite3SchemaDisconnect(db, iDb, 1);
void sqlite3SchemaClear(void *);
int sqlite3SchemaConnect(sqlite3*, int, u64);
int sqlite3SchemaDisconnect(sqlite3 *, int, int);
-void sqlite3SchemaZero(sqlite3*, int);
+void sqlite3SchemaClearOrDisconnect(sqlite3*, int);
Schema *sqlite3SchemaExtract(SchemaPool*);
-void sqlite3SchemaReleaseAll(sqlite3 *);
+void sqlite3SchemaReleaseAll(sqlite3*);
+void sqlite3SchemaRelease(sqlite3*, int);
void sqlite3SchemaWritable(Parse*, int);
Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
#ifndef SQLITE_OMIT_ALTERTABLE
if( pOp->p4.z==0 ){
+ assert( !IsReuseSchema(db) || iDb==1 );
sqlite3SchemaClear(db->aDb[iDb].pSchema);
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable);
SELECT * FROM main.ft;
} {one two three}
+breakpoint
do_execsql_test 2.2 {
SELECT * FROM aux.ft;
} {aux1 aux2 aux3}
}
db close
sqlite3 db test.db -reuse-schema 1
-breakpoint
foreach {tn sql} {
1 { ANALYZE }
2 { ANALYZE t1 }
SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
} {nref=3 nschema=1}
+#--------------------------------------------------------------------------
+catch {db1 close}
+catch {db2 close}
+catch {db3 close}
+reset_db
+do_execsql_test 4.0.1 {
+ CREATE TABLE x1(a, b, c);
+ CREATE INDEX x1a ON x1(a);
+ CREATE INDEX x1b ON x1(b);
+}
+do_test 4.0.2 {
+ db close
+ for {set i 1} {$i < 6} {incr i} {
+ forcedelete test.db${i}-journal test.db${i}-wal test.db${i}-wal2
+ forcecopy test.db test.db${i}
+ }
+ sqlite3 db test.db
+ sqlite3 db2 test.db -reuse-schema 1
+} {}
+
+register_schemapool_module db
+do_execsql_test 4.0.3 {
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {}
+
+do_test 4.1.1 {
+ execsql {
+ ATTACH 'test.db1' AS db1;
+ ATTACH 'test.db2' AS db2;
+ ATTACH 'test.db3' AS db3;
+ ATTACH 'test.db4' AS db4;
+ ATTACH 'test.db5' AS db5;
+ } db2
+} {}
+do_execsql_test 4.1.2 {
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {}
+do_execsql_test -db db2 4.1.3 {
+ SELECT * FROM db3.x1
+}
+do_execsql_test 4.1.4 {
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {nref=1 nschema=1}
+do_execsql_test -db db2 4.1.5 {
+ SELECT * FROM db2.x1
+}
+do_execsql_test 4.1.6 {
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {nref=2 nschema=1}
+do_execsql_test -db db2 4.1.7 {
+ SELECT * FROM x1
+}
+do_execsql_test 4.1.8 {
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {nref=3 nschema=1}
+
+do_test 4.2.1 {
+ catchsql { SELECT * FROM abc } db2
+} {1 {no such table: abc}}
+do_execsql_test 4.2.2 {
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {nref=6 nschema=1}
+
+register_schemapool_module db2
+do_execsql_test -db db2 4.3.1 {
+ INSERT INTO x1 VALUES(1, 2, 3);
+ INSERT INTO db1.x1 VALUES(4, 5, 6);
+ INSERT INTO db2.x1 VALUES(7, 8, 9);
+ INSERT INTO db3.x1 VALUES(10, 11, 12);
+ INSERT INTO db4.x1 VALUES(13, 14, 15);
+ INSERT INTO db5.x1 VALUES(16, 17, 18);
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {nref=6 nschema=1}
+
+do_execsql_test -db db2 4.3.2 {
+ SELECT * FROM db5.x1;
+ SELECT * FROM db4.x1;
+ SELECT * FROM db3.x1;
+ SELECT * FROM db2.x1;
+ SELECT * FROM db1.x1;
+ SELECT * FROM x1;
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {
+ 16 17 18 13 14 15 10 11 12 7 8 9 4 5 6 1 2 3
+ nref=6 nschema=1
+}
+
+do_execsql_test -db db2 4.3.3 {
+ UPDATE x1 SET a=a+10;
+ UPDATE db5.x1 SET a=a+10;
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {
+ nref=6 nschema=1
+}
+
+do_execsql_test -db db2 4.3.4 {
+ SELECT * FROM db5.x1;
+ SELECT * FROM db4.x1;
+ SELECT * FROM db3.x1;
+ SELECT * FROM db2.x1;
+ SELECT * FROM db1.x1;
+ SELECT * FROM x1;
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {
+ 26 17 18 13 14 15 10 11 12 7 8 9 4 5 6 11 2 3
+ nref=6 nschema=1
+}
+
+do_execsql_test -db db2 4.3.5 {
+ DELETE FROM db3.x1;
+ DELETE FROM x1;
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {
+ nref=6 nschema=1
+}
+
+do_execsql_test -db db2 4.3.6 {
+ SELECT * FROM db5.x1;
+ SELECT * FROM db4.x1;
+ SELECT * FROM db3.x1;
+ SELECT * FROM db2.x1;
+ SELECT * FROM db1.x1;
+ SELECT * FROM x1;
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {
+ 26 17 18 13 14 15 7 8 9 4 5 6
+ nref=6 nschema=1
+}
+
+do_execsql_test -db db2 4.3.6 {
+ SELECT * FROM db5.x1, db4.x1, db1.x1;
+ SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1;
+} {26 17 18 13 14 15 4 5 6 nref=6 nschema=3}
+
finish_test
+