/ Check-in [58cf812f]
Login

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

Overview
Comment:Avoid many unnecessary calls to sqlite3ReadSchema() and sqlite3Init() when the schema is known to be valid already.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 58cf812fd81329e82b3fdd61b7ad2040c9b90d2d80f592b9231e0e1902c8d577
User & Date: drh 2018-04-25 12:01:45
Context
2018-04-25
13:27
Add the new SQLITE_SHELL_INIT_PROC compile-time entry point to the CLI. This is needed to work around the tighter sqlite3_config() constraints now in the CLI. check-in: 3bcdbccf user: drh tags: trunk
12:01
Avoid many unnecessary calls to sqlite3ReadSchema() and sqlite3Init() when the schema is known to be valid already. check-in: 58cf812f user: drh tags: trunk
10:30
Add an assert() to ensure that schema mutexes are held prior to accessing the DB_SchemaLoaded flag inside of sqlite3Init(). check-in: d8b46290 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/attach.c.

   154    154       }
   155    155       assert( pVfs );
   156    156       flags |= SQLITE_OPEN_MAIN_DB;
   157    157       rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
   158    158       sqlite3_free( zPath );
   159    159       db->nDb++;
   160    160     }
   161         -  db->skipBtreeMutex = 0;
          161  +  db->noSharedCache = 0;
   162    162     if( rc==SQLITE_CONSTRAINT ){
   163    163       rc = SQLITE_ERROR;
   164    164       zErrDyn = sqlite3MPrintf(db, "database is already attached");
   165    165     }else if( rc==SQLITE_OK ){
   166    166       Pager *pPager;
   167    167       pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt);
   168    168       if( !pNew->pSchema ){
................................................................................
   226    226     ** If this fails, or if opening the file failed, then close the file and 
   227    227     ** remove the entry from the db->aDb[] array. i.e. put everything back the
   228    228     ** way we found it.
   229    229     */
   230    230     if( rc==SQLITE_OK ){
   231    231       sqlite3BtreeEnterAll(db);
   232    232       db->init.iDb = 0;
          233  +    db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
   233    234       rc = sqlite3Init(db, &zErrDyn);
   234    235       sqlite3BtreeLeaveAll(db);
   235    236       assert( zErrDyn==0 || rc!=SQLITE_OK );
   236    237     }
   237    238   #ifdef SQLITE_USER_AUTHENTICATION
   238    239     if( rc==SQLITE_OK ){
   239    240       u8 newAuth = 0;

Changes to src/btmutex.c.

   191    191     for(i=0; i<db->nDb; i++){
   192    192       p = db->aDb[i].pBt;
   193    193       if( p && p->sharable ){
   194    194         sqlite3BtreeEnter(p);
   195    195         skipOk = 0;
   196    196       }
   197    197     }
   198         -  db->skipBtreeMutex = skipOk;
          198  +  db->noSharedCache = skipOk;
   199    199   }
   200    200   void sqlite3BtreeEnterAll(sqlite3 *db){
   201         -  if( db->skipBtreeMutex==0 ) btreeEnterAll(db);
          201  +  if( db->noSharedCache==0 ) btreeEnterAll(db);
   202    202   }
   203    203   static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){
   204    204     int i;
   205    205     Btree *p;
   206    206     assert( sqlite3_mutex_held(db->mutex) );
   207    207     for(i=0; i<db->nDb; i++){
   208    208       p = db->aDb[i].pBt;
   209    209       if( p ) sqlite3BtreeLeave(p);
   210    210     }
   211    211   }
   212    212   void sqlite3BtreeLeaveAll(sqlite3 *db){
   213         -  if( db->skipBtreeMutex==0 ) btreeLeaveAll(db);
          213  +  if( db->noSharedCache==0 ) btreeLeaveAll(db);
   214    214   }
   215    215   
   216    216   #ifndef NDEBUG
   217    217   /*
   218    218   ** Return true if the current thread holds the database connection
   219    219   ** mutex and all required BtShared mutexes.
   220    220   **

Changes to src/build.c.

   339    339   Table *sqlite3LocateTable(
   340    340     Parse *pParse,         /* context in which to report errors */
   341    341     u32 flags,             /* LOCATE_VIEW or LOCATE_NOERR */
   342    342     const char *zName,     /* Name of the table we are looking for */
   343    343     const char *zDbase     /* Name of the database.  Might be NULL */
   344    344   ){
   345    345     Table *p;
          346  +  sqlite3 *db = pParse->db;
   346    347   
   347    348     /* Read the database schema. If an error occurs, leave an error message
   348    349     ** and code in pParse and return NULL. */
   349         -  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
          350  +  if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 
          351  +   && SQLITE_OK!=sqlite3ReadSchema(pParse)
          352  +  ){
   350    353       return 0;
   351    354     }
   352    355   
   353         -  p = sqlite3FindTable(pParse->db, zName, zDbase);
          356  +  p = sqlite3FindTable(db, zName, zDbase);
   354    357     if( p==0 ){
   355    358       const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
   356    359   #ifndef SQLITE_OMIT_VIRTUALTABLE
   357         -    if( sqlite3FindDbName(pParse->db, zDbase)<1 ){
          360  +    if( sqlite3FindDbName(db, zDbase)<1 ){
   358    361         /* If zName is the not the name of a table in the schema created using
   359    362         ** CREATE, then check to see if it is the name of an virtual table that
   360    363         ** can be an eponymous virtual table. */
   361         -      Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
          364  +      Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
   362    365         if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
   363         -        pMod = sqlite3PragmaVtabRegister(pParse->db, zName);
          366  +        pMod = sqlite3PragmaVtabRegister(db, zName);
   364    367         }
   365    368         if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
   366    369           return pMod->pEpoTab;
   367    370         }
   368    371       }
   369    372   #endif
   370    373       if( (flags & LOCATE_NOERR)==0 ){
................................................................................
   521    524     int i;
   522    525     assert( iDb<db->nDb );
   523    526   
   524    527     if( iDb>=0 ){
   525    528       assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   526    529       DbSetProperty(db, iDb, DB_ResetWanted);
   527    530       DbSetProperty(db, 1, DB_ResetWanted);
          531  +    db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
   528    532     }
   529    533   
   530    534     if( db->nSchemaLock==0 ){
   531    535       for(i=0; i<db->nDb; i++){
   532    536         if( DbHasProperty(db, i, DB_ResetWanted) ){
   533    537           sqlite3SchemaClear(db->aDb[i].pSchema);
   534    538         }
................................................................................
   546    550     assert( db->nSchemaLock==0 );
   547    551     for(i=0; i<db->nDb; i++){
   548    552       Db *pDb = &db->aDb[i];
   549    553       if( pDb->pSchema ){
   550    554         sqlite3SchemaClear(pDb->pSchema);
   551    555       }
   552    556     }
   553         -  db->mDbFlags &= ~DBFLAG_SchemaChange;
          557  +  db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk);
   554    558     sqlite3VtabUnlockList(db);
   555    559     sqlite3BtreeLeaveAll(db);
   556    560     sqlite3CollapseDatabaseArray(db);
   557    561   }
   558    562   
   559    563   /*
   560    564   ** This routine is called when a commit occurs.

Changes to src/prepare.c.

   141    141     Db *pDb;
   142    142     char const *azArg[4];
   143    143     int meta[5];
   144    144     InitData initData;
   145    145     const char *zMasterName;
   146    146     int openedTransaction = 0;
   147    147   
          148  +  assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
   148    149     assert( iDb>=0 && iDb<db->nDb );
   149    150     assert( db->aDb[iDb].pSchema );
   150    151     assert( sqlite3_mutex_held(db->mutex) );
   151    152     assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
   152    153   
   153    154     db->init.busy = 1;
   154    155   
................................................................................
   392    393   */
   393    394   int sqlite3ReadSchema(Parse *pParse){
   394    395     int rc = SQLITE_OK;
   395    396     sqlite3 *db = pParse->db;
   396    397     assert( sqlite3_mutex_held(db->mutex) );
   397    398     if( !db->init.busy ){
   398    399       rc = sqlite3Init(db, &pParse->zErrMsg);
   399         -  }
   400         -  if( rc!=SQLITE_OK ){
   401         -    pParse->rc = rc;
   402         -    pParse->nErr++;
          400  +    if( rc!=SQLITE_OK ){
          401  +      pParse->rc = rc;
          402  +      pParse->nErr++;
          403  +    }else if( db->noSharedCache ){
          404  +      db->mDbFlags |= DBFLAG_SchemaKnownOk;
          405  +    }
   403    406     }
   404    407     return rc;
   405    408   }
   406    409   
   407    410   
   408    411   /*
   409    412   ** Check schema cookies in all databases.  If any cookie is out

Changes to src/sqliteInt.h.

  1358   1358     u8 bBenignMalloc;             /* Do not require OOMs if true */
  1359   1359     u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  1360   1360     signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  1361   1361     u8 suppressErr;               /* Do not issue error messages if true */
  1362   1362     u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  1363   1363     u8 isTransactionSavepoint;    /* True if the outermost savepoint is a TS */
  1364   1364     u8 mTrace;                    /* zero or more SQLITE_TRACE flags */
  1365         -  u8 skipBtreeMutex;            /* True if no shared-cache backends */
         1365  +  u8 noSharedCache;             /* True if no shared-cache backends */
  1366   1366     u8 nSqlExec;                  /* Number of pending OP_SqlExec opcodes */
  1367   1367     int nextPagesize;             /* Pagesize after VACUUM if >0 */
  1368   1368     u32 magic;                    /* Magic number for detect library misuse */
  1369   1369     int nChange;                  /* Value returned by sqlite3_changes() */
  1370   1370     int nTotalChange;             /* Value returned by sqlite3_total_changes() */
  1371   1371     int aLimit[SQLITE_N_LIMIT];   /* Limits */
  1372   1372     int nMaxSorterMmap;           /* Maximum size of regions mapped by sorter */
................................................................................
  1518   1518   
  1519   1519   /*
  1520   1520   ** Allowed values for sqlite3.mDbFlags
  1521   1521   */
  1522   1522   #define DBFLAG_SchemaChange   0x0001  /* Uncommitted Hash table changes */
  1523   1523   #define DBFLAG_PreferBuiltin  0x0002  /* Preference to built-in funcs */
  1524   1524   #define DBFLAG_Vacuum         0x0004  /* Currently in a VACUUM */
         1525  +#define DBFLAG_SchemaKnownOk  0x0008  /* Schema is known to be valid */
  1525   1526   
  1526   1527   /*
  1527   1528   ** Bits of the sqlite3.dbOptFlags field that are used by the
  1528   1529   ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
  1529   1530   ** selectively disable various optimizations.
  1530   1531   */
  1531   1532   #define SQLITE_QueryFlattener 0x0001   /* Query flattening */