/ Check-in [776d9128]
Login

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

Overview
Comment:Size and performance optimization for sqlite3Init().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 776d91284a891bec64d6f649ff17de898b6ac6f66dd3d2afccc394a012a40c7d
User & Date: drh 2017-08-25 15:43:34
Context
2017-08-25
19:51
Fix a few over-length source code lines. No functional changes. check-in: 1783c54c user: drh tags: trunk
15:43
Size and performance optimization for sqlite3Init(). check-in: 776d9128 user: drh tags: trunk
13:34
Small performance optimization in sqlite3WhereBegin(). check-in: 39f708d1 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/prepare.c.

   145    145     const char *zMasterName;
   146    146     int openedTransaction = 0;
   147    147   
   148    148     assert( iDb>=0 && iDb<db->nDb );
   149    149     assert( db->aDb[iDb].pSchema );
   150    150     assert( sqlite3_mutex_held(db->mutex) );
   151    151     assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
          152  +
          153  +  db->init.busy = 1;
   152    154   
   153    155     /* Construct the in-memory representation schema tables (sqlite_master or
   154    156     ** sqlite_temp_master) by invoking the parser directly.  The appropriate
   155    157     ** table name will be inserted automatically by the parser so we can just
   156    158     ** use the abbreviation "x" here.  The parser will also automatically tag
   157    159     ** the schema table as read-only. */
   158    160     azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
   159    161     azArg[1] = "1";
   160    162     azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
   161         -                            "rootpage integer,sql text)";
          163  +                            "rootpage int,sql text)";
   162    164     azArg[3] = 0;
   163    165     initData.db = db;
   164    166     initData.iDb = iDb;
   165    167     initData.rc = SQLITE_OK;
   166    168     initData.pzErrMsg = pzErrMsg;
   167    169     sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
   168    170     if( initData.rc ){
................................................................................
   170    172       goto error_out;
   171    173     }
   172    174   
   173    175     /* Create a cursor to hold the database open
   174    176     */
   175    177     pDb = &db->aDb[iDb];
   176    178     if( pDb->pBt==0 ){
   177         -    if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
   178         -      DbSetProperty(db, 1, DB_SchemaLoaded);
   179         -    }
   180         -    return SQLITE_OK;
          179  +    assert( iDb==1 );
          180  +    DbSetProperty(db, 1, DB_SchemaLoaded);
          181  +    rc = SQLITE_OK;
          182  +    goto error_out;
   181    183     }
   182    184   
   183    185     /* If there is not already a read-only (or read-write) transaction opened
   184    186     ** on the b-tree database, open one now. If a transaction is opened, it 
   185    187     ** will be closed before this function returns.  */
   186    188     sqlite3BtreeEnter(pDb->pBt);
   187    189     if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
................................................................................
   332    334   initone_error_out:
   333    335     if( openedTransaction ){
   334    336       sqlite3BtreeCommit(pDb->pBt);
   335    337     }
   336    338     sqlite3BtreeLeave(pDb->pBt);
   337    339   
   338    340   error_out:
   339         -  if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
   340         -    sqlite3OomFault(db);
          341  +  if( rc ){
          342  +    if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
          343  +      sqlite3OomFault(db);
          344  +    }
          345  +    sqlite3ResetOneSchema(db, iDb);
   341    346     }
          347  +  db->init.busy = 0;
   342    348     return rc;
   343    349   }
   344    350   
   345    351   /*
   346    352   ** Initialize all database files - the main database file, the file
   347    353   ** used to store temporary tables, and any additional database files
   348    354   ** created using ATTACH statements.  Return a success code.  If an
................................................................................
   355    361   int sqlite3Init(sqlite3 *db, char **pzErrMsg){
   356    362     int i, rc;
   357    363     int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange);
   358    364     
   359    365     assert( sqlite3_mutex_held(db->mutex) );
   360    366     assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
   361    367     assert( db->init.busy==0 );
   362         -  rc = SQLITE_OK;
   363         -  db->init.busy = 1;
   364    368     ENC(db) = SCHEMA_ENC(db);
   365         -  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
   366         -    if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
   367         -    rc = sqlite3InitOne(db, i, pzErrMsg);
   368         -    if( rc ){
   369         -      sqlite3ResetOneSchema(db, i);
          369  +  assert( db->nDb>0 );
          370  +  /* Do the main schema first */
          371  +  if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
          372  +    rc = sqlite3InitOne(db, 0, pzErrMsg);
          373  +    if( rc ) return rc;
          374  +  }
          375  +  /* All other schemas after the main schema. The "temp" schema must be last */
          376  +  for(i=db->nDb-1; i>0; i--){
          377  +    if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
          378  +      rc = sqlite3InitOne(db, i, pzErrMsg);
          379  +      if( rc ) return rc;
   370    380       }
   371    381     }
   372         -
   373         -  /* Once all the other databases have been initialized, load the schema
   374         -  ** for the TEMP database. This is loaded last, as the TEMP database
   375         -  ** schema may contain references to objects in other databases.
   376         -  */
   377         -#ifndef SQLITE_OMIT_TEMPDB
   378         -  assert( db->nDb>1 );
   379         -  if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
   380         -    rc = sqlite3InitOne(db, 1, pzErrMsg);
   381         -    if( rc ){
   382         -      sqlite3ResetOneSchema(db, 1);
   383         -    }
   384         -  }
   385         -#endif
   386         -
   387         -  db->init.busy = 0;
   388         -  if( rc==SQLITE_OK && commit_internal ){
          382  +  if( commit_internal ){
   389    383       sqlite3CommitInternalChanges(db);
   390    384     }
   391         -
   392         -  return rc; 
          385  +  return SQLITE_OK;
   393    386   }
   394    387   
   395    388   /*
   396    389   ** This routine is a no-op if the database schema is already initialized.
   397    390   ** Otherwise, the schema is loaded. An error code is returned.
   398    391   */
   399    392   int sqlite3ReadSchema(Parse *pParse){