Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Share schemas between databases attached to the same database handle. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | reuse-schema |
Files: | files | file ages | folders |
SHA3-256: |
ea611d7cba604dc901c8088ccfa13367 |
User & Date: | dan 2019-02-12 19:20:33.146 |
Context
2019-02-12
| ||
20:58 | Add tests for creating temp schema objects with SQLITE_OPEN_REUSE_SCHEMA connections. (check-in: 8c07b609fc user: dan tags: reuse-schema) | |
19:20 | Share schemas between databases attached to the same database handle. (check-in: ea611d7cba user: dan tags: reuse-schema) | |
2019-02-11
| ||
20:13 | Merge latest trunk changes into this branch. (check-in: dbedd81bf2 user: dan tags: reuse-schema) | |
Changes
Changes to src/attach.c.
︙ | ︙ | |||
227 228 229 230 231 232 233 | /* If the file was opened successfully, read the schema for the new database. ** If this fails, or if opening the file failed, then close the file and ** remove the entry from the db->aDb[] array. i.e. put everything back the ** way we found it. */ if( rc==SQLITE_OK ){ | < > > | | | > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | /* If the file was opened successfully, read the schema for the new database. ** If this fails, or if opening the file failed, then close the file and ** remove the entry from the db->aDb[] array. i.e. put everything back the ** way we found it. */ if( rc==SQLITE_OK ){ db->init.iDb = 0; db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); 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 ){ u8 newAuth = 0; rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth); if( newAuth<db->auth.authLevel ){ rc = SQLITE_AUTH_USER; |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | return 0; } #endif while(1){ 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 ){ assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); if( p ) return p; } } /* Not found. If the name we were looking for was temp.sqlite_master ** then change the name to sqlite_temp_master and try again. */ if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break; if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break; zName = TEMP_MASTER_NAME; | > > > > > > > > > > > | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | return 0; } #endif while(1){ 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 ** then change the name to sqlite_temp_master and try again. */ if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break; if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break; zName = TEMP_MASTER_NAME; |
︙ | ︙ | |||
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | ){ Table *p; sqlite3 *db = pParse->db; /* 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 && SQLITE_OK!=sqlite3ReadSchema(pParse) ){ return 0; } p = sqlite3FindTable(db, zName, zDbase); if( p==0 ){ #ifndef SQLITE_OMIT_VIRTUALTABLE /* If zName is the not the name of a table in the schema created using ** CREATE, then check to see if it is the name of an virtual table that ** can be an eponymous virtual table. */ if( pParse->disableVtab==0 ){ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ pMod = sqlite3PragmaVtabRegister(db, zName); } | > > > > > > > > | | > | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | ){ Table *p; sqlite3 *db = pParse->db; /* 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; } p = sqlite3FindTable(db, zName, zDbase); if( p==0 ){ #ifndef SQLITE_OMIT_VIRTUALTABLE /* If zName is the not the name of a table in the schema created using ** CREATE, then check to see if it is the name of an virtual table that ** can be an eponymous virtual table. */ if( pParse->disableVtab==0 ){ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ pMod = sqlite3PragmaVtabRegister(db, zName); } 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( flags & LOCATE_NOERR ) return 0; pParse->checkSchema = 1; }else if( IsVirtual(p) && pParse->disableVtab ){ p = 0; |
︙ | ︙ | |||
532 533 534 535 536 537 538 | DbSetProperty(db, iDb, DB_ResetWanted); DbSetProperty(db, 1, DB_ResetWanted); db->mDbFlags &= ~DBFLAG_SchemaKnownOk; } if( db->nSchemaLock==0 ){ for(i=0; i<db->nDb; i++){ if( DbHasProperty(db, i, DB_ResetWanted) ){ | | | | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | DbSetProperty(db, iDb, DB_ResetWanted); DbSetProperty(db, 1, DB_ResetWanted); db->mDbFlags &= ~DBFLAG_SchemaKnownOk; } if( db->nSchemaLock==0 ){ for(i=0; i<db->nDb; i++){ if( DbHasProperty(db, i, DB_ResetWanted) ){ sqlite3SchemaClearOrDisconnect(db, i); } } } } /* ** 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; i<db->nDb; i=(i?i+1:2)){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ if( db->nSchemaLock==0 ){ sqlite3SchemaClearOrDisconnect(db, i); }else{ DbSetProperty(db, i, DB_ResetWanted); } } } sqlite3SchemaClear(db->aDb[1].pSchema); db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); |
︙ | ︙ |
Changes to src/callback.c.
︙ | ︙ | |||
513 514 515 516 517 518 519 | pSchema->pSeqTab = 0; if( pSchema->schemaFlags & DB_SchemaLoaded ){ pSchema->iGeneration++; } pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted); } | > > > > > > > > > | < < < | > | | < < < < | 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 | pSchema->pSeqTab = 0; if( pSchema->schemaFlags & DB_SchemaLoaded ){ pSchema->iGeneration++; } pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted); } /* ** 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 ){ sqlite3SchemaDisconnect(db, iDb, 1); }else{ sqlite3SchemaClear(pDb->pSchema); } } /* ** Global linked list of SchemaPool objects. Read and write access must ** be protected by the SQLITE_MUTEX_STATIC_MASTER mutex. */ static SchemaPool *SQLITE_WSD schemaPoolList = 0; |
︙ | ︙ | |||
704 705 706 707 708 709 710 | void sqlite3SchemaReleaseAll(sqlite3 *db){ int i; assert_schema_state_ok(db); sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) ); for(i=0; i<db->nDb; i++){ if( i!=1 ){ Db *pDb = &db->aDb[i]; | | > > > > > > > > > > > | 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | void sqlite3SchemaReleaseAll(sqlite3 *db){ int i; assert_schema_state_ok(db); sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) ); for(i=0; i<db->nDb; i++){ if( i!=1 ){ Db *pDb = &db->aDb[i]; 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. |
︙ | ︙ |
Changes to src/fkey.c.
︙ | ︙ | |||
1391 1392 1393 1394 1395 1396 1397 | ** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash ** hash table. */ void sqlite3FkDelete(sqlite3 *db, Table *pTab){ FKey *pFKey; /* Iterator variable */ FKey *pNext; /* Copy of pFKey->pNextFrom */ | > | < | 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 | ** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash ** hash table. */ void sqlite3FkDelete(sqlite3 *db, Table *pTab){ FKey *pFKey; /* Iterator variable */ FKey *pNext; /* Copy of pFKey->pNextFrom */ 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 ){ if( pFKey->pPrevTo ){ pFKey->pPrevTo->pNextTo = pFKey->pNextTo; }else{ void *p = (void *)pFKey->pNextTo; |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
191 192 193 194 195 196 197 198 | assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ); assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pSchema || (IsReuseSchema(db) && iDb!=1) ); assert( sqlite3_mutex_held(db->mutex) ); assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); pDb = &db->aDb[iDb]; if( pDb->pSPool ){ | > < | > > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ); assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pSchema || (IsReuseSchema(db) && iDb!=1) ); assert( sqlite3_mutex_held(db->mutex) ); assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); pDb = &db->aDb[iDb]; assert( pDb->pSPool==0 || IsReuseSchema(db) ); if( pDb->pSPool ){ /* 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. */ Schema *pNew = sqlite3SchemaExtract(pDb->pSPool); if( pNew ){ pDb->pSchema = pNew; return SQLITE_OK; } rc = sqlite3SchemaDisconnect(db, iDb, 1); if( rc!=SQLITE_OK ) goto error_out; assert( pDb->pSchema && pDb->pSPool==0 ); } |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
4319 4320 4321 4322 4323 4324 4325 | void sqlite3DeleteIndexSamples(sqlite3*,Index*); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3SchemaClear(void *); int sqlite3SchemaConnect(sqlite3*, int, u64); int sqlite3SchemaDisconnect(sqlite3 *, int, int); | | | > | 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 | void sqlite3DeleteIndexSamples(sqlite3*,Index*); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3SchemaClear(void *); int sqlite3SchemaConnect(sqlite3*, int, u64); int sqlite3SchemaDisconnect(sqlite3 *, int, int); void sqlite3SchemaClearOrDisconnect(sqlite3*, int); Schema *sqlite3SchemaExtract(SchemaPool*); void sqlite3SchemaReleaseAll(sqlite3*); void sqlite3SchemaRelease(sqlite3*, int); void sqlite3SchemaWritable(Parse*, int); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *); KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); void sqlite3KeyInfoUnref(KeyInfo*); KeyInfo *sqlite3KeyInfoRef(KeyInfo*); KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 | iDb = pOp->p1; assert( iDb>=0 && iDb<db->nDb ); assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); #ifndef SQLITE_OMIT_ALTERTABLE if( pOp->p4.z==0 ){ sqlite3SchemaClear(db->aDb[iDb].pSchema); db->mDbFlags &= ~DBFLAG_SchemaKnownOk; rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable); db->mDbFlags |= DBFLAG_SchemaChange; p->expired = 0; }else #endif | > | 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 | iDb = pOp->p1; assert( iDb>=0 && iDb<db->nDb ); assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); #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); db->mDbFlags |= DBFLAG_SchemaChange; p->expired = 0; }else #endif |
︙ | ︙ |
Changes to test/reuse1.test.
︙ | ︙ | |||
109 110 111 112 113 114 115 116 117 118 119 120 121 122 | sqlite3 db test.db -reuse-schema 1 do_execsql_test 2.1 { ATTACH 'test.db2' AS aux; SELECT * FROM main.ft; } {one two three} do_execsql_test 2.2 { SELECT * FROM aux.ft; } {aux1 aux2 aux3} do_execsql_test 2.2 { SELECT * FROM aux.ft_content; } {1 aux1 2 aux2 3 aux3} | > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | sqlite3 db test.db -reuse-schema 1 do_execsql_test 2.1 { ATTACH 'test.db2' AS aux; SELECT * FROM main.ft; } {one two three} breakpoint do_execsql_test 2.2 { SELECT * FROM aux.ft; } {aux1 aux2 aux3} do_execsql_test 2.2 { SELECT * FROM aux.ft_content; } {1 aux1 2 aux2 3 aux3} |
︙ | ︙ | |||
296 297 298 299 300 301 302 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c); CREATE INDEX i1 ON t1(b); INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6); } db close sqlite3 db test.db -reuse-schema 1 | < | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c); CREATE INDEX i1 ON t1(b); INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6); } db close sqlite3 db test.db -reuse-schema 1 foreach {tn sql} { 1 { ANALYZE } 2 { ANALYZE t1 } 3 { ANALYZE i1 } 4 { ANALYZE main } 5 { ANALYZE main.t1 } 6 { ANALYZE main.i1 } |
︙ | ︙ |
Changes to test/reuse2.test.
︙ | ︙ | |||
108 109 110 111 112 113 114 115 116 | } {nref=1 nschema=1 nref=2 nschema=1} do_execsql_test -db db3 3.11.1 { SELECT * FROM t1 } do_execsql_test 3.11.2 { SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool ORDER BY 1; } {nref=3 nschema=1} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | } {nref=1 nschema=1 nref=2 nschema=1} do_execsql_test -db db3 3.11.1 { SELECT * FROM t1 } 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 |