/ Check-in [635e3a76]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Avoid resetting the shared-cache schema when on of the connections using the shared cache closes. Delay resetting the schema until the last connection closes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:635e3a762ddeb1f952f66a08c1d4d53e3f42c9eb
User & Date: drh 2012-06-06 19:01:13
References
2012-10-25
17:21
Use a constant string "BINARY" for the unspecified collating sequence. This is part of check-in [635e3a762dd] that is being back-ported. check-in: 9078ea75 user: drh tags: branch-3.7.9
Context
2012-06-06
19:30
Have the FTS unicode61 strip out diacritics when tokenizing text. This can be disabled by specifying the tokenizer option "remove_diacritics=0". check-in: 790f76a5 user: dan tags: trunk
19:01
Avoid resetting the shared-cache schema when on of the connections using the shared cache closes. Delay resetting the schema until the last connection closes. check-in: 635e3a76 user: drh tags: trunk
10:56
Make sure the Index.azColl pointers do not point to connection-specific memory. Also, remove an unnecessary reinitialization to sqlite3.pDfltColl. Closed-Leaf check-in: c469850b user: drh tags: shared-schema
2012-06-05
13:56
Add sqlite3_quota_ferror() and sqlite3_quota_file_available() interfaces to test_quota.c. Change sqlite3_quota_fwrite() to use a const input buffer. check-in: 61669c95 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/attach.c.

   212    212       int iDb = db->nDb - 1;
   213    213       assert( iDb>=2 );
   214    214       if( db->aDb[iDb].pBt ){
   215    215         sqlite3BtreeClose(db->aDb[iDb].pBt);
   216    216         db->aDb[iDb].pBt = 0;
   217    217         db->aDb[iDb].pSchema = 0;
   218    218       }
   219         -    sqlite3ResetInternalSchema(db, -1);
          219  +    sqlite3ResetAllSchemasOfConnection(db);
   220    220       db->nDb = iDb;
   221    221       if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
   222    222         db->mallocFailed = 1;
   223    223         sqlite3DbFree(db, zErrDyn);
   224    224         zErrDyn = sqlite3MPrintf(db, "out of memory");
   225    225       }else if( zErrDyn==0 ){
   226    226         zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
................................................................................
   284    284       sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
   285    285       goto detach_error;
   286    286     }
   287    287   
   288    288     sqlite3BtreeClose(pDb->pBt);
   289    289     pDb->pBt = 0;
   290    290     pDb->pSchema = 0;
   291         -  sqlite3ResetInternalSchema(db, -1);
          291  +  sqlite3ResetAllSchemasOfConnection(db);
   292    292     return;
   293    293   
   294    294   detach_error:
   295    295     sqlite3_result_error(context, zErr, -1);
   296    296   }
   297    297   
   298    298   /*

Changes to src/backup.c.

   410    410       ** the case where the source and destination databases have the
   411    411       ** same schema version.
   412    412       */
   413    413       if( rc==SQLITE_DONE ){
   414    414         rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
   415    415         if( rc==SQLITE_OK ){
   416    416           if( p->pDestDb ){
   417         -          sqlite3ResetInternalSchema(p->pDestDb, -1);
          417  +          sqlite3ResetAllSchemasOfConnection(p->pDestDb);
   418    418           }
   419    419           if( destMode==PAGER_JOURNALMODE_WAL ){
   420    420             rc = sqlite3BtreeSetVersion(p->pDest, 2);
   421    421           }
   422    422         }
   423    423         if( rc==SQLITE_OK ){
   424    424           int nDestTruncate;

Changes to src/build.c.

   390    390       }
   391    391       freeIndex(db, pIndex);
   392    392     }
   393    393     db->flags |= SQLITE_InternChanges;
   394    394   }
   395    395   
   396    396   /*
   397         -** Erase all schema information from the in-memory hash tables of
   398         -** a single database.  This routine is called to reclaim memory
   399         -** before the database closes.  It is also called during a rollback
   400         -** if there were schema changes during the transaction or if a
   401         -** schema-cookie mismatch occurs.
   402         -**
   403         -** If iDb<0 then reset the internal schema tables for all database
   404         -** files.  If iDb>=0 then reset the internal schema for only the
   405         -** single file indicated.
   406         -*/
   407         -void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
   408         -  int i, j;
   409         -  assert( iDb<db->nDb );
   410         -
   411         -  if( iDb>=0 ){
   412         -    /* Case 1:  Reset the single schema identified by iDb */
   413         -    Db *pDb = &db->aDb[iDb];
   414         -    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   415         -    assert( pDb->pSchema!=0 );
   416         -    sqlite3SchemaClear(pDb->pSchema);
   417         -
   418         -    /* If any database other than TEMP is reset, then also reset TEMP
   419         -    ** since TEMP might be holding triggers that reference tables in the
   420         -    ** other database.
   421         -    */
   422         -    if( iDb!=1 ){
   423         -      pDb = &db->aDb[1];
   424         -      assert( pDb->pSchema!=0 );
   425         -      sqlite3SchemaClear(pDb->pSchema);
   426         -    }
   427         -    return;
   428         -  }
   429         -  /* Case 2 (from here to the end): Reset all schemas for all attached
   430         -  ** databases. */
   431         -  assert( iDb<0 );
   432         -  sqlite3BtreeEnterAll(db);
   433         -  for(i=0; i<db->nDb; i++){
   434         -    Db *pDb = &db->aDb[i];
   435         -    if( pDb->pSchema ){
   436         -      sqlite3SchemaClear(pDb->pSchema);
   437         -    }
   438         -  }
   439         -  db->flags &= ~SQLITE_InternChanges;
   440         -  sqlite3VtabUnlockList(db);
   441         -  sqlite3BtreeLeaveAll(db);
   442         -
   443         -  /* If one or more of the auxiliary database files has been closed,
   444         -  ** then remove them from the auxiliary database list.  We take the
   445         -  ** opportunity to do this here since we have just deleted all of the
   446         -  ** schema hash tables and therefore do not have to make any changes
   447         -  ** to any of those tables.
   448         -  */
          397  +** Look through the list of open database files in db->aDb[] and if
          398  +** any have been closed, remove them from the list.  Reallocate the
          399  +** db->aDb[] structure to a smaller size, if possible.
          400  +**
          401  +** Entry 0 (the "main" database) and entry 1 (the "temp" database)
          402  +** are never candidates for being collapsed.
          403  +*/
          404  +void sqlite3CollapseDatabaseArray(sqlite3 *db){
          405  +  int i, j;
   449    406     for(i=j=2; i<db->nDb; i++){
   450    407       struct Db *pDb = &db->aDb[i];
   451    408       if( pDb->pBt==0 ){
   452    409         sqlite3DbFree(db, pDb->zName);
   453    410         pDb->zName = 0;
   454    411         continue;
   455    412       }
................................................................................
   462    419     db->nDb = j;
   463    420     if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
   464    421       memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
   465    422       sqlite3DbFree(db, db->aDb);
   466    423       db->aDb = db->aDbStatic;
   467    424     }
   468    425   }
          426  +
          427  +/*
          428  +** Reset the schema for the database at index iDb.  Also reset the
          429  +** TEMP schema.
          430  +*/
          431  +void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
          432  +  Db *pDb;
          433  +  assert( iDb<db->nDb );
          434  +
          435  +  /* Case 1:  Reset the single schema identified by iDb */
          436  +  pDb = &db->aDb[iDb];
          437  +  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
          438  +  assert( pDb->pSchema!=0 );
          439  +  sqlite3SchemaClear(pDb->pSchema);
          440  +
          441  +  /* If any database other than TEMP is reset, then also reset TEMP
          442  +  ** since TEMP might be holding triggers that reference tables in the
          443  +  ** other database.
          444  +  */
          445  +  if( iDb!=1 ){
          446  +    pDb = &db->aDb[1];
          447  +    assert( pDb->pSchema!=0 );
          448  +    sqlite3SchemaClear(pDb->pSchema);
          449  +  }
          450  +  return;
          451  +}
          452  +
          453  +/*
          454  +** Erase all schema information from all attached databases (including
          455  +** "main" and "temp") for a single database connection.
          456  +*/
          457  +void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
          458  +  int i;
          459  +  sqlite3BtreeEnterAll(db);
          460  +  for(i=0; i<db->nDb; i++){
          461  +    Db *pDb = &db->aDb[i];
          462  +    if( pDb->pSchema ){
          463  +      sqlite3SchemaClear(pDb->pSchema);
          464  +    }
          465  +  }
          466  +  db->flags &= ~SQLITE_InternChanges;
          467  +  sqlite3VtabUnlockList(db);
          468  +  sqlite3BtreeLeaveAll(db);
          469  +  sqlite3CollapseDatabaseArray(db);
          470  +}
   469    471   
   470    472   /*
   471    473   ** This routine is called when a commit occurs.
   472    474   */
   473    475   void sqlite3CommitInternalChanges(sqlite3 *db){
   474    476     db->flags &= ~SQLITE_InternChanges;
   475    477   }
................................................................................
  2759   2761         memcpy(zExtra, zColl, nColl);
  2760   2762         zColl = zExtra;
  2761   2763         zExtra += nColl;
  2762   2764         nExtra -= nColl;
  2763   2765       }else{
  2764   2766         zColl = pTab->aCol[j].zColl;
  2765   2767         if( !zColl ){
  2766         -        zColl = db->pDfltColl->zName;
         2768  +        zColl = "BINARY";
  2767   2769         }
  2768   2770       }
  2769   2771       if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
  2770   2772         goto exit_create_index;
  2771   2773       }
  2772   2774       pIndex->azColl[i] = zColl;
  2773   2775       requestedSortOrder = pListItem->sortOrder & sortOrderMask;

Changes to src/main.c.

   715    715       pDestructor->nRef--;
   716    716       if( pDestructor->nRef==0 ){
   717    717         pDestructor->xDestroy(pDestructor->pUserData);
   718    718         sqlite3DbFree(db, pDestructor);
   719    719       }
   720    720     }
   721    721   }
          722  +
          723  +/*
          724  +** Disconnect all sqlite3_vtab objects that belong to database connection
          725  +** db. This is called when db is being closed.
          726  +*/
          727  +static void disconnectAllVtab(sqlite3 *db){
          728  +#ifndef SQLITE_OMIT_VIRTUALTABLE
          729  +  int i;
          730  +  sqlite3BtreeEnterAll(db);
          731  +  for(i=0; i<db->nDb; i++){
          732  +    Schema *pSchema = db->aDb[i].pSchema;
          733  +    if( db->aDb[i].pSchema ){
          734  +      HashElem *p;
          735  +      for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
          736  +        Table *pTab = (Table *)sqliteHashData(p);
          737  +        if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
          738  +      }
          739  +    }
          740  +  }
          741  +  sqlite3BtreeLeaveAll(db);
          742  +#else
          743  +  UNUSED_PARAMETER(db);
          744  +#endif
          745  +}
   722    746   
   723    747   /*
   724    748   ** Close an existing SQLite database
   725    749   */
   726    750   int sqlite3_close(sqlite3 *db){
   727    751     HashElem *i;                    /* Hash table iterator */
   728    752     int j;
................................................................................
   731    755       return SQLITE_OK;
   732    756     }
   733    757     if( !sqlite3SafetyCheckSickOrOk(db) ){
   734    758       return SQLITE_MISUSE_BKPT;
   735    759     }
   736    760     sqlite3_mutex_enter(db->mutex);
   737    761   
   738         -  /* Force xDestroy calls on all virtual tables */
   739         -  sqlite3ResetInternalSchema(db, -1);
          762  +  /* Force xDisconnect calls on all virtual tables */
          763  +  disconnectAllVtab(db);
   740    764   
   741         -  /* If a transaction is open, the ResetInternalSchema() call above
          765  +  /* If a transaction is open, the disconnectAllVtab() call above
   742    766     ** will not have called the xDisconnect() method on any virtual
   743    767     ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
   744    768     ** call will do so. We need to do this before the check for active
   745    769     ** SQL statements below, as the v-table implementation may be storing
   746    770     ** some prepared statements internally.
   747    771     */
   748    772     sqlite3VtabRollback(db);
................................................................................
   765    789         return SQLITE_BUSY;
   766    790       }
   767    791     }
   768    792   
   769    793     /* Free any outstanding Savepoint structures. */
   770    794     sqlite3CloseSavepoints(db);
   771    795   
          796  +  /* Close all database connections */
   772    797     for(j=0; j<db->nDb; j++){
   773    798       struct Db *pDb = &db->aDb[j];
   774    799       if( pDb->pBt ){
   775    800         sqlite3BtreeClose(pDb->pBt);
   776    801         pDb->pBt = 0;
   777    802         if( j!=1 ){
   778    803           pDb->pSchema = 0;
   779    804         }
   780    805       }
   781    806     }
   782         -  sqlite3ResetInternalSchema(db, -1);
          807  +  /* Clear the TEMP schema separately and last */
          808  +  if( db->aDb[1].pSchema ){
          809  +    sqlite3SchemaClear(db->aDb[1].pSchema);
          810  +  }
          811  +  sqlite3VtabUnlockList(db);
          812  +
          813  +  /* Free up the array of auxiliary databases */
          814  +  sqlite3CollapseDatabaseArray(db);
          815  +  assert( db->nDb<=2 );
          816  +  assert( db->aDb==db->aDbStatic );
   783    817   
   784    818     /* Tell the code in notify.c that the connection no longer holds any
   785    819     ** locks and does not require any further unlock-notify callbacks.
   786    820     */
   787    821     sqlite3ConnectionClosed(db);
   788    822   
   789         -  assert( db->nDb<=2 );
   790         -  assert( db->aDb==db->aDbStatic );
   791    823     for(j=0; j<ArraySize(db->aFunc.a); j++){
   792    824       FuncDef *pNext, *pHash, *p;
   793    825       for(p=db->aFunc.a[j]; p; p=pHash){
   794    826         pHash = p->pHash;
   795    827         while( p ){
   796    828           functionDestroy(db, p);
   797    829           pNext = p->pNext;
................................................................................
   870    902       }
   871    903     }
   872    904     sqlite3VtabRollback(db);
   873    905     sqlite3EndBenignMalloc();
   874    906   
   875    907     if( db->flags&SQLITE_InternChanges ){
   876    908       sqlite3ExpirePreparedStatements(db);
   877         -    sqlite3ResetInternalSchema(db, -1);
          909  +    sqlite3ResetAllSchemasOfConnection(db);
   878    910     }
   879    911   
   880    912     /* Any deferred constraint violations have now been resolved. */
   881    913     db->nDeferredCons = 0;
   882    914   
   883    915     /* If one has been configured, invoke the rollback-hook callback */
   884    916     if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){

Changes to src/pragma.c.

   114    114       if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){
   115    115         sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
   116    116           "from within a transaction");
   117    117         return SQLITE_ERROR;
   118    118       }
   119    119       sqlite3BtreeClose(db->aDb[1].pBt);
   120    120       db->aDb[1].pBt = 0;
   121         -    sqlite3ResetInternalSchema(db, -1);
          121  +    sqlite3ResetAllSchemasOfConnection(db);
   122    122     }
   123    123     return SQLITE_OK;
   124    124   }
   125    125   #endif /* SQLITE_PAGER_PRAGMAS */
   126    126   
   127    127   #ifndef SQLITE_OMIT_PAGER_PRAGMAS
   128    128   /*

Changes to src/prepare.c.

   258    258     if( meta[BTREE_TEXT_ENCODING-1] ){  /* text encoding */
   259    259       if( iDb==0 ){
   260    260         u8 encoding;
   261    261         /* If opening the main database, set ENC(db). */
   262    262         encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
   263    263         if( encoding==0 ) encoding = SQLITE_UTF8;
   264    264         ENC(db) = encoding;
   265         -      db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
   266    265       }else{
   267    266         /* If opening an attached database, the encoding much match ENC(db) */
   268    267         if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
   269    268           sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
   270    269               " text encoding as main database");
   271    270           rc = SQLITE_ERROR;
   272    271           goto initone_error_out;
................................................................................
   338    337       if( rc==SQLITE_OK ){
   339    338         sqlite3AnalysisLoad(db, iDb);
   340    339       }
   341    340   #endif
   342    341     }
   343    342     if( db->mallocFailed ){
   344    343       rc = SQLITE_NOMEM;
   345         -    sqlite3ResetInternalSchema(db, -1);
          344  +    sqlite3ResetAllSchemasOfConnection(db);
   346    345     }
   347    346     if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
   348    347       /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
   349    348       ** the schema loaded, even if errors occurred. In this situation the 
   350    349       ** current sqlite3_prepare() operation will fail, but the following one
   351    350       ** will attempt to compile the supplied statement against whatever subset
   352    351       ** of the schema was loaded before the error occurred. The primary
................................................................................
   391    390     assert( sqlite3_mutex_held(db->mutex) );
   392    391     rc = SQLITE_OK;
   393    392     db->init.busy = 1;
   394    393     for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
   395    394       if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
   396    395       rc = sqlite3InitOne(db, i, pzErrMsg);
   397    396       if( rc ){
   398         -      sqlite3ResetInternalSchema(db, i);
          397  +      sqlite3ResetOneSchema(db, i);
   399    398       }
   400    399     }
   401    400   
   402    401     /* Once all the other databases have been initialised, load the schema
   403    402     ** for the TEMP database. This is loaded last, as the TEMP database
   404    403     ** schema may contain references to objects in other databases.
   405    404     */
   406    405   #ifndef SQLITE_OMIT_TEMPDB
   407    406     if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
   408    407                       && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
   409    408       rc = sqlite3InitOne(db, 1, pzErrMsg);
   410    409       if( rc ){
   411         -      sqlite3ResetInternalSchema(db, 1);
          410  +      sqlite3ResetOneSchema(db, 1);
   412    411       }
   413    412     }
   414    413   #endif
   415    414   
   416    415     db->init.busy = 0;
   417    416     if( rc==SQLITE_OK && commit_internal ){
   418    417       sqlite3CommitInternalChanges(db);
................................................................................
   472    471   
   473    472       /* Read the schema cookie from the database. If it does not match the 
   474    473       ** value stored as part of the in-memory schema representation,
   475    474       ** set Parse.rc to SQLITE_SCHEMA. */
   476    475       sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
   477    476       assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   478    477       if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
   479         -      sqlite3ResetInternalSchema(db, iDb);
          478  +      sqlite3ResetOneSchema(db, iDb);
   480    479         pParse->rc = SQLITE_SCHEMA;
   481    480       }
   482    481   
   483    482       /* Close the transaction, if one was opened. */
   484    483       if( openedTransaction ){
   485    484         sqlite3BtreeCommit(pBt);
   486    485       }

Changes to src/sqliteInt.h.

  2705   2705   ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
  2706   2706   void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
  2707   2707   void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
  2708   2708   void sqlite3ExprListDelete(sqlite3*, ExprList*);
  2709   2709   int sqlite3Init(sqlite3*, char**);
  2710   2710   int sqlite3InitCallback(void*, int, char**, char**);
  2711   2711   void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
  2712         -void sqlite3ResetInternalSchema(sqlite3*, int);
         2712  +void sqlite3ResetAllSchemasOfConnection(sqlite3*);
         2713  +void sqlite3ResetOneSchema(sqlite3*,int);
         2714  +void sqlite3CollapseDatabaseArray(sqlite3*);
  2713   2715   void sqlite3BeginParse(Parse*,int);
  2714   2716   void sqlite3CommitInternalChanges(sqlite3*);
  2715   2717   Table *sqlite3ResultSetOfSelect(Parse*,Select*);
  2716   2718   void sqlite3OpenMasterTable(Parse *, int);
  2717   2719   void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
  2718   2720   void sqlite3AddColumn(Parse*,Token*);
  2719   2721   void sqlite3AddNotNull(Parse*, int);
................................................................................
  3110   3112   #  define sqlite3VtabLock(X) 
  3111   3113   #  define sqlite3VtabUnlock(X)
  3112   3114   #  define sqlite3VtabUnlockList(X)
  3113   3115   #  define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
  3114   3116   #  define sqlite3GetVTable(X,Y)  ((VTable*)0)
  3115   3117   #else
  3116   3118      void sqlite3VtabClear(sqlite3 *db, Table*);
         3119  +   void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
  3117   3120      int sqlite3VtabSync(sqlite3 *db, char **);
  3118   3121      int sqlite3VtabRollback(sqlite3 *db);
  3119   3122      int sqlite3VtabCommit(sqlite3 *db);
  3120   3123      void sqlite3VtabLock(VTable *);
  3121   3124      void sqlite3VtabUnlock(VTable *);
  3122   3125      void sqlite3VtabUnlockList(sqlite3*);
  3123   3126      int sqlite3VtabSavepoint(sqlite3 *, int, int);

Changes to src/test8.c.

  1296   1296     echoRollbackTo
  1297   1297   };
  1298   1298   
  1299   1299   /*
  1300   1300   ** Decode a pointer to an sqlite3 object.
  1301   1301   */
  1302   1302   extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
         1303  +extern const char *sqlite3TestErrorName(int rc);
  1303   1304   
  1304   1305   static void moduleDestroy(void *p){
  1305   1306     sqlite3_free(p);
  1306   1307   }
  1307   1308   
  1308   1309   /*
  1309   1310   ** Register the echo virtual table module.
................................................................................
  1310   1311   */
  1311   1312   static int register_echo_module(
  1312   1313     ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  1313   1314     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1314   1315     int objc,              /* Number of arguments */
  1315   1316     Tcl_Obj *CONST objv[]  /* Command arguments */
  1316   1317   ){
         1318  +  int rc;
  1317   1319     sqlite3 *db;
  1318   1320     EchoModule *pMod;
  1319   1321     if( objc!=2 ){
  1320   1322       Tcl_WrongNumArgs(interp, 1, objv, "DB");
  1321   1323       return TCL_ERROR;
  1322   1324     }
  1323   1325     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  1324   1326   
  1325   1327     /* Virtual table module "echo" */
  1326   1328     pMod = sqlite3_malloc(sizeof(EchoModule));
  1327   1329     pMod->interp = interp;
  1328         -  sqlite3_create_module_v2(db, "echo", &echoModule, (void*)pMod, moduleDestroy);
         1330  +  rc = sqlite3_create_module_v2(
         1331  +      db, "echo", &echoModule, (void*)pMod, moduleDestroy
         1332  +  );
  1329   1333   
  1330   1334     /* Virtual table module "echo_v2" */
  1331         -  pMod = sqlite3_malloc(sizeof(EchoModule));
  1332         -  pMod->interp = interp;
  1333         -  sqlite3_create_module_v2(db, "echo_v2", 
  1334         -      &echoModuleV2, (void*)pMod, moduleDestroy
  1335         -  );
         1335  +  if( rc==SQLITE_OK ){
         1336  +    pMod = sqlite3_malloc(sizeof(EchoModule));
         1337  +    pMod->interp = interp;
         1338  +    rc = sqlite3_create_module_v2(db, "echo_v2", 
         1339  +        &echoModuleV2, (void*)pMod, moduleDestroy
         1340  +    );
         1341  +  }
         1342  +
         1343  +  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
  1336   1344     return TCL_OK;
  1337   1345   }
  1338   1346   
  1339   1347   /*
  1340   1348   ** Tcl interface to sqlite3_declare_vtab, invoked as follows from Tcl:
  1341   1349   **
  1342   1350   ** sqlite3_declare_vtab DB SQL

Changes to src/vacuum.c.

   335    335       sqlite3BtreeClose(pDb->pBt);
   336    336       pDb->pBt = 0;
   337    337       pDb->pSchema = 0;
   338    338     }
   339    339   
   340    340     /* This both clears the schemas and reduces the size of the db->aDb[]
   341    341     ** array. */ 
   342         -  sqlite3ResetInternalSchema(db, -1);
          342  +  sqlite3ResetAllSchemasOfConnection(db);
   343    343   
   344    344     return rc;
   345    345   }
   346    346   
   347    347   #endif  /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */

Changes to src/vdbe.c.

  2743   2743             rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
  2744   2744             if( rc!=SQLITE_OK ){
  2745   2745               goto abort_due_to_error;
  2746   2746             }
  2747   2747           }
  2748   2748           if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
  2749   2749             sqlite3ExpirePreparedStatements(db);
  2750         -          sqlite3ResetInternalSchema(db, -1);
         2750  +          sqlite3ResetAllSchemasOfConnection(db);
  2751   2751             db->flags = (db->flags | SQLITE_InternChanges);
  2752   2752           }
  2753   2753         }
  2754   2754     
  2755   2755         /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all 
  2756   2756         ** savepoints nested inside of the savepoint being operated on. */
  2757   2757         while( db->pSavepoint!=pSavepoint ){
................................................................................
  3047   3047       ** prepared queries. If such a query is out-of-date, we do not want to
  3048   3048       ** discard the database schema, as the user code implementing the
  3049   3049       ** v-table would have to be ready for the sqlite3_vtab structure itself
  3050   3050       ** to be invalidated whenever sqlite3_step() is called from within 
  3051   3051       ** a v-table method.
  3052   3052       */
  3053   3053       if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
  3054         -      sqlite3ResetInternalSchema(db, pOp->p1);
         3054  +      sqlite3ResetOneSchema(db, pOp->p1);
  3055   3055       }
  3056   3056   
  3057   3057       p->expired = 1;
  3058   3058       rc = SQLITE_SCHEMA;
  3059   3059     }
  3060   3060     break;
  3061   3061   }
................................................................................
  4860   4860         assert( !db->mallocFailed );
  4861   4861         rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
  4862   4862         if( rc==SQLITE_OK ) rc = initData.rc;
  4863   4863         sqlite3DbFree(db, zSql);
  4864   4864         db->init.busy = 0;
  4865   4865       }
  4866   4866     }
  4867         -  if( rc ) sqlite3ResetInternalSchema(db, -1);
         4867  +  if( rc ) sqlite3ResetAllSchemasOfConnection(db);
  4868   4868     if( rc==SQLITE_NOMEM ){
  4869   4869       goto no_mem;
  4870   4870     }
  4871   4871     break;  
  4872   4872   }
  4873   4873   
  4874   4874   #if !defined(SQLITE_OMIT_ANALYZE)
................................................................................
  6155   6155     testcase( sqlite3GlobalConfig.xLog!=0 );
  6156   6156     sqlite3_log(rc, "statement aborts at %d: [%s] %s", 
  6157   6157                      pc, p->zSql, p->zErrMsg);
  6158   6158     sqlite3VdbeHalt(p);
  6159   6159     if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
  6160   6160     rc = SQLITE_ERROR;
  6161   6161     if( resetSchemaOnFault>0 ){
  6162         -    sqlite3ResetInternalSchema(db, resetSchemaOnFault-1);
         6162  +    sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
  6163   6163     }
  6164   6164   
  6165   6165     /* This is the only way out of this procedure.  We have to
  6166   6166     ** release the mutexes on btrees that were acquired at the
  6167   6167     ** top. */
  6168   6168   vdbe_return:
  6169   6169     db->lastRowid = lastRowid;

Changes to src/vtab.c.

    18     18   ** Before a virtual table xCreate() or xConnect() method is invoked, the
    19     19   ** sqlite3.pVtabCtx member variable is set to point to an instance of
    20     20   ** this struct allocated on the stack. It is used by the implementation of 
    21     21   ** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
    22     22   ** are invoked only from within xCreate and xConnect methods.
    23     23   */
    24     24   struct VtabCtx {
    25         -  Table *pTab;
    26         -  VTable *pVTable;
           25  +  VTable *pVTable;    /* The virtual table being constructed */
           26  +  Table *pTab;        /* The Table object to which the virtual table belongs */
    27     27   };
    28     28   
    29     29   /*
    30     30   ** The actual function that does the work of creating a new module.
    31     31   ** This function implements the sqlite3_create_module() and
    32     32   ** sqlite3_create_module_v2() interfaces.
    33     33   */
................................................................................
    34     34   static int createModule(
    35     35     sqlite3 *db,                    /* Database in which module is registered */
    36     36     const char *zName,              /* Name assigned to this module */
    37     37     const sqlite3_module *pModule,  /* The definition of the module */
    38     38     void *pAux,                     /* Context pointer for xCreate/xConnect */
    39     39     void (*xDestroy)(void *)        /* Module destructor function */
    40     40   ){
    41         -  int rc, nName;
    42         -  Module *pMod;
           41  +  int rc = SQLITE_OK;
           42  +  int nName;
    43     43   
    44     44     sqlite3_mutex_enter(db->mutex);
    45     45     nName = sqlite3Strlen30(zName);
    46         -  pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
    47         -  if( pMod ){
    48         -    Module *pDel;
    49         -    char *zCopy = (char *)(&pMod[1]);
    50         -    memcpy(zCopy, zName, nName+1);
    51         -    pMod->zName = zCopy;
    52         -    pMod->pModule = pModule;
    53         -    pMod->pAux = pAux;
    54         -    pMod->xDestroy = xDestroy;
    55         -    pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
    56         -    if( pDel && pDel->xDestroy ){
    57         -      sqlite3ResetInternalSchema(db, -1);
    58         -      pDel->xDestroy(pDel->pAux);
    59         -    }
    60         -    sqlite3DbFree(db, pDel);
    61         -    if( pDel==pMod ){
    62         -      db->mallocFailed = 1;
    63         -    }
    64         -  }else if( xDestroy ){
    65         -    xDestroy(pAux);
    66         -  }
    67         -  rc = sqlite3ApiExit(db, SQLITE_OK);
           46  +  if( sqlite3HashFind(&db->aModule, zName, nName) ){
           47  +    rc = SQLITE_MISUSE_BKPT;
           48  +  }else{
           49  +    Module *pMod;
           50  +    pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
           51  +    if( pMod ){
           52  +      Module *pDel;
           53  +      char *zCopy = (char *)(&pMod[1]);
           54  +      memcpy(zCopy, zName, nName+1);
           55  +      pMod->zName = zCopy;
           56  +      pMod->pModule = pModule;
           57  +      pMod->pAux = pAux;
           58  +      pMod->xDestroy = xDestroy;
           59  +      pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod);
           60  +      assert( pDel==0 || pDel==pMod );
           61  +      if( pDel ){
           62  +        db->mallocFailed = 1;
           63  +        sqlite3DbFree(db, pDel);
           64  +      }
           65  +    }
           66  +  }
           67  +  rc = sqlite3ApiExit(db, rc);
           68  +  if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
           69  +
    68     70     sqlite3_mutex_leave(db->mutex);
    69     71     return rc;
    70     72   }
    71     73   
    72     74   
    73     75   /*
    74     76   ** External API function used to create a new virtual-table module.
................................................................................
   175    177       }
   176    178       pVTable = pNext;
   177    179     }
   178    180   
   179    181     assert( !db || pRet );
   180    182     return pRet;
   181    183   }
          184  +
          185  +/*
          186  +** Table *p is a virtual table. This function removes the VTable object
          187  +** for table *p associated with database connection db from the linked
          188  +** list in p->pVTab. It also decrements the VTable ref count. This is
          189  +** used when closing database connection db to free all of its VTable
          190  +** objects without disturbing the rest of the Schema object (which may
          191  +** be being used by other shared-cache connections).
          192  +*/
          193  +void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
          194  +  VTable **ppVTab;
          195  +
          196  +  assert( IsVirtual(p) );
          197  +  assert( sqlite3BtreeHoldsAllMutexes(db) );
          198  +  assert( sqlite3_mutex_held(db->mutex) );
          199  +
          200  +  for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
          201  +    if( (*ppVTab)->db==db  ){
          202  +      VTable *pVTab = *ppVTab;
          203  +      *ppVTab = pVTab->pNext;
          204  +      sqlite3VtabUnlock(pVTab);
          205  +      break;
          206  +    }
          207  +  }
          208  +}
   182    209   
   183    210   
   184    211   /*
   185    212   ** Disconnect all the virtual table objects in the sqlite3.pDisconnect list.
   186    213   **
   187    214   ** This function may only be called when the mutexes associated with all
   188    215   ** shared b-tree databases opened using connection db are held by the 

Changes to test/capi3.test.

   645    645     set STMT [sqlite3_prepare $DB $sql -1 TAIL]
   646    646     expr 0
   647    647   } {0}
   648    648   do_test capi3-6.1 {
   649    649     db cache flush
   650    650     sqlite3_close $DB
   651    651   } {SQLITE_BUSY}
          652  +
          653  +# 6.2 and 6.3 used to return SQLITE_ERROR and SQLITE_SCHEMA, respectively.
          654  +# But since attempting to close a connection no longer resets the internal
          655  +# schema and expires all statements, this is no longer the case.
   652    656   do_test capi3-6.2 {
   653    657     sqlite3_step $STMT
   654         -} {SQLITE_ERROR}
          658  +} {SQLITE_ROW}
   655    659   #check_data $STMT capi3-6.3 {INTEGER} {1} {1.0} {1}
   656    660   do_test capi3-6.3 {
   657    661     sqlite3_finalize $STMT
   658         -} {SQLITE_SCHEMA}
          662  +} {SQLITE_OK}
          663  +
   659    664   do_test capi3-6.4-misuse {
   660    665     db cache flush
   661    666     sqlite3_close $DB
   662    667   } {SQLITE_OK}
   663    668   db close
   664    669   
   665    670   # This procedure sets the value of the file-format in file 'test.db'

Added test/shared8.test.

            1  +# 2012 May 15
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# The tests in this file are intended to show that closing one database
           13  +# connection to a shared-cache while there exist other connections (a)
           14  +# does not cause the schema to be reloaded and (b) does not cause any
           15  +# other problems.
           16  +#
           17  +
           18  +set testdir [file dirname $argv0]
           19  +source $testdir/tester.tcl
           20  +ifcapable !shared_cache { finish_test ; return }
           21  +set testprefix shared8
           22  +
           23  +db close
           24  +set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
           25  +do_test 0.0 { sqlite3_enable_shared_cache } {1}
           26  +
           27  +proc roman {n} {
           28  +  array set R {1 i 2 ii 3 iii 4 iv 5 v 6 vi 7 vii 8 viii 9 ix 10 x}
           29  +  set R($n)
           30  +}
           31  +
           32  +#-------------------------------------------------------------------------
           33  +# The following tests work as follows:
           34  +#
           35  +#    1.0: Open connection [db1] and populate the database.
           36  +#
           37  +#    1.1: Using "PRAGMA writable_schema", destroy the database schema on
           38  +#         disk. The schema is still in memory, so it is possible to keep
           39  +#         using it, but any attempt to reload it from disk will fail.
           40  +#
           41  +#    1.3-4: Open connection db2. Check that it can see the db schema. Then
           42  +#           close db1 and check that db2 still works. This shows that closing
           43  +#           db1 did not reset the in-memory schema.
           44  +#
           45  +#    1.5-7: Similar to 1.3-4.
           46  +#
           47  +#    1.8: Close all database connections (deleting the in-memory schema).
           48  +#         Then open a new connection and check that it cannot read the db.
           49  +#         
           50  +do_test 1.0 {
           51  +  sqlite3 db1 test.db
           52  +  db1 func roman roman
           53  +  execsql {
           54  +    CREATE TABLE t1(a, b);
           55  +    INSERT INTO t1 VALUES(1, 1);
           56  +    INSERT INTO t1 VALUES(2, 2);
           57  +    INSERT INTO t1 VALUES(3, 3);
           58  +    INSERT INTO t1 VALUES(4, 4);
           59  +    CREATE VIEW v1 AS SELECT a, roman(b) FROM t1;
           60  +    SELECT * FROM v1;
           61  +  } db1
           62  +} {1 i 2 ii 3 iii 4 iv}
           63  +
           64  +do_test 1.1 {
           65  +  execsql { 
           66  +    PRAGMA writable_schema = 1;
           67  +    DELETE FROM sqlite_master WHERE 1;
           68  +    PRAGMA writable_schema = 0;
           69  +    SELECT * FROM sqlite_master;
           70  +  } db1
           71  +} {}
           72  +
           73  +do_test 1.2 {
           74  +  execsql { SELECT * FROM v1 } db1
           75  +} {1 i 2 ii 3 iii 4 iv}
           76  +
           77  +do_test 1.3 {
           78  +  sqlite3 db2 test.db
           79  +  db2 func roman roman
           80  +  execsql { SELECT * FROM v1 } db2
           81  +} {1 i 2 ii 3 iii 4 iv}
           82  +
           83  +do_test 1.4 {
           84  +  db1 close
           85  +  execsql { SELECT * FROM v1 } db2
           86  +} {1 i 2 ii 3 iii 4 iv}
           87  +
           88  +do_test 1.5 {
           89  +  sqlite3 db3 test.db
           90  +  db3 func roman roman
           91  +  execsql { SELECT * FROM v1 } db3
           92  +} {1 i 2 ii 3 iii 4 iv}
           93  +
           94  +do_test 1.6 {
           95  +  execsql { SELECT * FROM v1 } db2
           96  +} {1 i 2 ii 3 iii 4 iv}
           97  +
           98  +do_test 1.7 {
           99  +  db2 close
          100  +  execsql { SELECT * FROM v1 } db3
          101  +} {1 i 2 ii 3 iii 4 iv}
          102  +
          103  +do_test 1.8 {
          104  +  db3 close
          105  +  sqlite3 db4 test.db
          106  +  catchsql { SELECT * FROM v1 } db4
          107  +} {1 {no such table: v1}}
          108  +
          109  +
          110  +foreach db {db1 db2 db3 db4} { catch { $db close } }
          111  +sqlite3_enable_shared_cache $::enable_shared_cache
          112  +finish_test
          113  +

Changes to test/vtab1.test.

  1270   1270       {xFilter {SELECT rowid, * FROM 't6'}}
  1271   1271   } {
  1272   1272     set echo_module {}
  1273   1273     do_execsql_test 18.$tn.1 $sql $res
  1274   1274     do_test         18.$tn.2 { lrange $::echo_module 2 end } $filter
  1275   1275   }
  1276   1276   do_execsql_test 18.2.x {  PRAGMA case_sensitive_like = OFF }
         1277  +
         1278  +#-------------------------------------------------------------------------
         1279  +# Test that an existing module may not be overridden.
         1280  +#
         1281  +do_test 19.1 {
         1282  +  sqlite3 db2 test.db
         1283  +  register_echo_module [sqlite3_connection_pointer db2]
         1284  +} SQLITE_OK
         1285  +do_test 19.2 {
         1286  +  register_echo_module [sqlite3_connection_pointer db2]
         1287  +} SQLITE_MISUSE
         1288  +do_test 19.3 {
         1289  +  db2 close
         1290  +} {}
  1277   1291   
  1278   1292   finish_test