]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Share schemas between databases attached to the same database handle.
authordan <dan@noemail.net>
Tue, 12 Feb 2019 19:20:33 +0000 (19:20 +0000)
committerdan <dan@noemail.net>
Tue, 12 Feb 2019 19:20:33 +0000 (19:20 +0000)
FossilOrigin-Name: ea611d7cba604dc901c8088ccfa13367a5ee75f9499ea8d8b62a590daac2eae0

manifest
manifest.uuid
src/attach.c
src/build.c
src/callback.c
src/fkey.c
src/prepare.c
src/sqliteInt.h
src/vdbe.c
test/reuse1.test
test/reuse2.test

index 97d130f856d953386239cb6d1ad7f45d4c823f95..41c81c5273d464d56ce2807a70d7b8f4205e1fd3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
@@ -450,7 +450,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 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
@@ -458,8 +458,8 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
 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
@@ -468,7 +468,7 @@ F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319
 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
@@ -509,7 +509,7 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
 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
@@ -519,7 +519,7 @@ F src/shell.c.in e32838e30357f2d4913a76345aa9407bd6662d48121ebe44528a9fb4feaee6d
 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
@@ -586,7 +586,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
 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
@@ -1226,8 +1226,8 @@ F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
 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
@@ -1807,7 +1807,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 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
index 94c2fb7d7d915d03ed7ef2eadb91c317d8b8dbde..b279b45e82ff5b77375ecc7903352873f76d5dd1 100644 (file)
@@ -1 +1 @@
-dbedd81bf2e29ae9ed88526c1cc97e5c4d0a256ad7d960304bbb5e15c44f51f0
\ No newline at end of file
+ea611d7cba604dc901c8088ccfa13367a5ee75f9499ea8d8b62a590daac2eae0
\ No newline at end of file
index 224d120b6fed7442c3f772aa9ae044cc44dfb5e6..47cf37ae26ed7030138f54762a03c64508a85fa5 100644 (file)
@@ -231,12 +231,14 @@ static void attachFunc(
   ** 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 ){
index 1cec6b44bbda712ad62aacba558c45e501f6de57..9c17cf776f89975a7c357a5e52578a78f60a7c60 100644 (file)
@@ -311,9 +311,20 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
     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
@@ -347,6 +358,7 @@ Table *sqlite3LocateTable(
   /* 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;
@@ -363,8 +375,16 @@ Table *sqlite3LocateTable(
       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
@@ -536,7 +556,7 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
   if( db->nSchemaLock==0 ){
     for(i=0; i<db->nDb; i++){
       if( DbHasProperty(db, i, DB_ResetWanted) ){
-        sqlite3SchemaZero(db, i);
+        sqlite3SchemaClearOrDisconnect(db, i);
       }
     }
   }
@@ -553,7 +573,7 @@ void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
     Db *pDb = &db->aDb[i];
     if( pDb->pSchema ){
       if( db->nSchemaLock==0 ){
-        sqlite3SchemaClear(pDb->pSchema);
+        sqlite3SchemaClearOrDisconnect(db, i);
       }else{
         DbSetProperty(db, i, DB_ResetWanted);
       }
index 8030bf9043f747d181d2f3820222f848faa7d515..fbb452108a02e95d2b04b1b59bdfa1491f01a43b 100644 (file)
@@ -517,19 +517,22 @@ void sqlite3SchemaClear(void *p){
   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);
 }
 
 /*
@@ -708,7 +711,7 @@ void sqlite3SchemaReleaseAll(sqlite3 *db){
   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);
       }
     }
@@ -716,6 +719,17 @@ void sqlite3SchemaReleaseAll(sqlite3 *db){
   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.
index 9633c414497029848c5a7836716753c55d495ad4..369c887e19703f3035441f1b95cb209da5134b58 100644 (file)
@@ -1395,9 +1395,9 @@ void sqlite3FkDelete(sqlite3 *db, Table *pTab){
   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 ){
index 86c85596738e107497f1cd46c129f5b8d23a61c6..8662ac601588b4d200df6b0636afae7fa8653405 100644 (file)
@@ -195,12 +195,14 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
   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);
index 97972490be82c4fdb3c713bbc17a6ce4013f6148..a73bce5b861a4897e7e2e7e7d2aaf876d85033bc 100644 (file)
@@ -4323,9 +4323,10 @@ int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
 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 *);
index ae31f616305705871f0b00cbaac37872f4c97514..456b6e98d1091fc47834a54b0aefc456a9ce21f7 100644 (file)
@@ -5779,6 +5779,7 @@ case OP_ParseSchema: {
 
 #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);
index 47c7b1c31cdc4c3fa787ac887d94a37c50e08396..801c4c4ada47312570c86342fd50815b59284c8e 100644 (file)
@@ -113,6 +113,7 @@ ifcapable fts5 {
     SELECT * FROM main.ft;
   } {one two three}
 
+breakpoint
   do_execsql_test 2.2 {
     SELECT * FROM aux.ft;
   } {aux1 aux2 aux3}
@@ -300,7 +301,6 @@ do_execsql_test 5.4 {
 }
 db close
 sqlite3 db test.db -reuse-schema 1
-breakpoint
 foreach {tn sql} {
   1 { ANALYZE }
   2 { ANALYZE t1 }
index 71f13dd182b8ea10f9928a18e5efa3cbba76667f..20f3dd0dd03ebdfca80d5580bf6a6ffc41753cc8 100644 (file)
@@ -112,5 +112,140 @@ do_execsql_test 3.11.2 {
   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
 
+