/ Check-in [a10662aa]
Login

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

Overview
Comment:Change sqlite3BtreeBeginTrans() to return the BTREE_SCHEMA_COOKIE, for a small speed improvement when starting new transactions.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a10662aa915ae2b5a78b3e10920350d32255b2d6b1a8aac0aba1ad173b07ed2b
User & Date: drh 2018-06-06 16:28:40
Context
2018-06-06
17:45
Another minor optimization to OP_Transaction. check-in: d80077ae user: drh tags: trunk
17:03
Merge changes from trunk, including all the 3.24.0 changes plus some later enhancements. check-in: d7299bfe user: drh tags: begin-concurrent
16:28
Change sqlite3BtreeBeginTrans() to return the BTREE_SCHEMA_COOKIE, for a small speed improvement when starting new transactions. check-in: a10662aa user: drh tags: trunk
01:18
Fix the ".archive" command in the CLI (and the corresponding -A command-line option) so that it silently ignores filenames that contain "../" in their names. This prevents the "Zip Slip" attack. check-in: 27291f2d user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/backup.c.

   378    378       }
   379    379   
   380    380       /* If there is no open read-transaction on the source database, open
   381    381       ** one now. If a transaction is opened here, then it will be closed
   382    382       ** before this function exits.
   383    383       */
   384    384       if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
   385         -      rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
          385  +      rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
   386    386         bCloseTrans = 1;
   387    387       }
   388    388   
   389    389       /* If the destination database has not yet been locked (i.e. if this
   390    390       ** is the first call to backup_step() for the current backup operation),
   391    391       ** try to set its page size to the same as the source database. This
   392    392       ** is especially important on ZipVFS systems, as in that case it is
................................................................................
   394    394       ** writing to it with another.  */
   395    395       if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
   396    396         rc = SQLITE_NOMEM;
   397    397       }
   398    398   
   399    399       /* Lock the destination database, if it is not locked already. */
   400    400       if( SQLITE_OK==rc && p->bDestLocked==0
   401         -     && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) 
          401  +     && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
          402  +                                                (int*)&p->iDestSchema)) 
   402    403       ){
   403    404         p->bDestLocked = 1;
   404         -      sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
   405    405       }
   406    406   
   407    407       /* Do not allow backup if the destination database is in WAL mode
   408    408       ** and the page sizes are different between source and destination */
   409    409       pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
   410    410       pgszDest = sqlite3BtreeGetPageSize(p->pDest);
   411    411       destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));

Changes to src/btree.c.

  3296   3296   ** a reserved lock.  B tries to promote to exclusive but is blocked because
  3297   3297   ** of A's read lock.  A tries to promote to reserved but is blocked by B.
  3298   3298   ** One or the other of the two processes must give way or there can be
  3299   3299   ** no progress.  By returning SQLITE_BUSY and not invoking the busy callback
  3300   3300   ** when A already has a read lock, we encourage A to give up and let B
  3301   3301   ** proceed.
  3302   3302   */
  3303         -int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
         3303  +int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
  3304   3304     BtShared *pBt = p->pBt;
  3305   3305     int rc = SQLITE_OK;
  3306   3306   
  3307   3307     sqlite3BtreeEnter(p);
  3308   3308     btreeIntegrity(p);
  3309   3309   
  3310   3310     /* If the btree is already in a write-transaction, or it
................................................................................
  3424   3424           }
  3425   3425         }
  3426   3426       }
  3427   3427     }
  3428   3428   
  3429   3429   
  3430   3430   trans_begun:
  3431         -  if( rc==SQLITE_OK && wrflag ){
  3432         -    /* This call makes sure that the pager has the correct number of
  3433         -    ** open savepoints. If the second parameter is greater than 0 and
  3434         -    ** the sub-journal is not already open, then it will be opened here.
  3435         -    */
  3436         -    rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
         3431  +  if( rc==SQLITE_OK ){
         3432  +    if( pSchemaVersion ){
         3433  +      *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
         3434  +    }
         3435  +    if( wrflag ){
         3436  +      /* This call makes sure that the pager has the correct number of
         3437  +      ** open savepoints. If the second parameter is greater than 0 and
         3438  +      ** the sub-journal is not already open, then it will be opened here.
         3439  +      */
         3440  +      rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
         3441  +    }
  3437   3442     }
  3438   3443   
  3439   3444     btreeIntegrity(p);
  3440   3445     sqlite3BtreeLeave(p);
  3441   3446     return rc;
  3442   3447   }
  3443   3448   
................................................................................
 10080  10085   
 10081  10086     /* If setting the version fields to 1, do not automatically open the
 10082  10087     ** WAL connection, even if the version fields are currently set to 2.
 10083  10088     */
 10084  10089     pBt->btsFlags &= ~BTS_NO_WAL;
 10085  10090     if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
 10086  10091   
 10087         -  rc = sqlite3BtreeBeginTrans(pBtree, 0);
        10092  +  rc = sqlite3BtreeBeginTrans(pBtree, 0, 0);
 10088  10093     if( rc==SQLITE_OK ){
 10089  10094       u8 *aData = pBt->pPage1->aData;
 10090  10095       if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
 10091         -      rc = sqlite3BtreeBeginTrans(pBtree, 2);
        10096  +      rc = sqlite3BtreeBeginTrans(pBtree, 2, 0);
 10092  10097         if( rc==SQLITE_OK ){
 10093  10098           rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
 10094  10099           if( rc==SQLITE_OK ){
 10095  10100             aData[18] = (u8)iVersion;
 10096  10101             aData[19] = (u8)iVersion;
 10097  10102           }
 10098  10103         }

Changes to src/btree.h.

    74     74   int sqlite3BtreeMaxPageCount(Btree*,int);
    75     75   u32 sqlite3BtreeLastPage(Btree*);
    76     76   int sqlite3BtreeSecureDelete(Btree*,int);
    77     77   int sqlite3BtreeGetOptimalReserve(Btree*);
    78     78   int sqlite3BtreeGetReserveNoMutex(Btree *p);
    79     79   int sqlite3BtreeSetAutoVacuum(Btree *, int);
    80     80   int sqlite3BtreeGetAutoVacuum(Btree *);
    81         -int sqlite3BtreeBeginTrans(Btree*,int);
           81  +int sqlite3BtreeBeginTrans(Btree*,int,int*);
    82     82   int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
    83     83   int sqlite3BtreeCommitPhaseTwo(Btree*, int);
    84     84   int sqlite3BtreeCommit(Btree*);
    85     85   int sqlite3BtreeRollback(Btree*,int,int);
    86     86   int sqlite3BtreeBeginStmt(Btree*,int);
    87     87   int sqlite3BtreeCreateTable(Btree*, int*, int flags);
    88     88   int sqlite3BtreeIsInTrans(Btree*);

Changes to src/dbpage.c.

   365    365   */
   366    366   static int dbpageBegin(sqlite3_vtab *pVtab){
   367    367     DbpageTable *pTab = (DbpageTable *)pVtab;
   368    368     sqlite3 *db = pTab->db;
   369    369     int i;
   370    370     for(i=0; i<db->nDb; i++){
   371    371       Btree *pBt = db->aDb[i].pBt;
   372         -    if( pBt ) sqlite3BtreeBeginTrans(pBt, 1);
          372  +    if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0);
   373    373     }
   374    374     return SQLITE_OK;
   375    375   }
   376    376   
   377    377   
   378    378   /*
   379    379   ** Invoke this routine to register the "dbpage" virtual table module

Changes to src/prepare.c.

   184    184     }
   185    185   
   186    186     /* If there is not already a read-only (or read-write) transaction opened
   187    187     ** on the b-tree database, open one now. If a transaction is opened, it 
   188    188     ** will be closed before this function returns.  */
   189    189     sqlite3BtreeEnter(pDb->pBt);
   190    190     if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
   191         -    rc = sqlite3BtreeBeginTrans(pDb->pBt, 0);
          191  +    rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
   192    192       if( rc!=SQLITE_OK ){
   193    193         sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
   194    194         goto initone_error_out;
   195    195       }
   196    196       openedTransaction = 1;
   197    197     }
   198    198   
................................................................................
   429    429       Btree *pBt = db->aDb[iDb].pBt;     /* Btree database to read cookie from */
   430    430       if( pBt==0 ) continue;
   431    431   
   432    432       /* If there is not already a read-only (or read-write) transaction opened
   433    433       ** on the b-tree database, open one now. If a transaction is opened, it 
   434    434       ** will be closed immediately after reading the meta-value. */
   435    435       if( !sqlite3BtreeIsInReadTrans(pBt) ){
   436         -      rc = sqlite3BtreeBeginTrans(pBt, 0);
          436  +      rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
   437    437         if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
   438    438           sqlite3OomFault(db);
   439    439         }
   440    440         if( rc!=SQLITE_OK ) return;
   441    441         openedTransaction = 1;
   442    442       }
   443    443   

Changes to src/test3.c.

   129    129     if( argc!=2 ){
   130    130       Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   131    131          " ID\"", 0);
   132    132       return TCL_ERROR;
   133    133     }
   134    134     pBt = sqlite3TestTextToPtr(argv[1]);
   135    135     sqlite3BtreeEnter(pBt);
   136         -  rc = sqlite3BtreeBeginTrans(pBt, 1);
          136  +  rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
   137    137     sqlite3BtreeLeave(pBt);
   138    138     if( rc!=SQLITE_OK ){
   139    139       Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
   140    140       return TCL_ERROR;
   141    141     }
   142    142     return TCL_OK;
   143    143   }

Changes to src/vacuum.c.

   220    220   
   221    221     /* Begin a transaction and take an exclusive lock on the main database
   222    222     ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
   223    223     ** to ensure that we do not try to change the page-size on a WAL database.
   224    224     */
   225    225     rc = execSql(db, pzErrMsg, "BEGIN");
   226    226     if( rc!=SQLITE_OK ) goto end_of_vacuum;
   227         -  rc = sqlite3BtreeBeginTrans(pMain, 2);
          227  +  rc = sqlite3BtreeBeginTrans(pMain, 2, 0);
   228    228     if( rc!=SQLITE_OK ) goto end_of_vacuum;
   229    229   
   230    230     /* Do not attempt to change the page size for a WAL database */
   231    231     if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
   232    232                                                  ==PAGER_JOURNALMODE_WAL ){
   233    233       db->nextPagesize = 0;
   234    234     }

Changes to src/vdbe.c.

  3198   3198   ** if the schema generation counter in P4 differs from the current
  3199   3199   ** generation counter, then an SQLITE_SCHEMA error is raised and execution
  3200   3200   ** halts.  The sqlite3_step() wrapper function might then reprepare the
  3201   3201   ** statement and rerun it from the beginning.
  3202   3202   */
  3203   3203   case OP_Transaction: {
  3204   3204     Btree *pBt;
  3205         -  int iMeta;
  3206         -  int iGen;
         3205  +  int iMeta = 0;
         3206  +  int iGen = 0;
  3207   3207   
  3208   3208     assert( p->bIsReader );
  3209   3209     assert( p->readOnly==0 || pOp->p2==0 );
  3210   3210     assert( pOp->p1>=0 && pOp->p1<db->nDb );
  3211   3211     assert( DbMaskTest(p->btreeMask, pOp->p1) );
  3212   3212     if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
  3213   3213       rc = SQLITE_READONLY;
  3214   3214       goto abort_due_to_error;
  3215   3215     }
  3216   3216     pBt = db->aDb[pOp->p1].pBt;
  3217   3217   
  3218   3218     if( pBt ){
  3219         -    rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
         3219  +    rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta);
  3220   3220       testcase( rc==SQLITE_BUSY_SNAPSHOT );
  3221   3221       testcase( rc==SQLITE_BUSY_RECOVERY );
  3222   3222       if( rc!=SQLITE_OK ){
  3223   3223         if( (rc&0xff)==SQLITE_BUSY ){
  3224   3224           p->pc = (int)(pOp - aOp);
  3225   3225           p->rc = rc;
  3226   3226           goto vdbe_return;
................................................................................
  3251   3251       }
  3252   3252   
  3253   3253       /* Gather the schema version number for checking:
  3254   3254       ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
  3255   3255       ** version is checked to ensure that the schema has not changed since the
  3256   3256       ** SQL statement was prepared.
  3257   3257       */
  3258         -    sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
  3259   3258       iGen = db->aDb[pOp->p1].pSchema->iGeneration;
  3260         -  }else{
  3261         -    iGen = iMeta = 0;
  3262   3259     }
  3263   3260     assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
  3264   3261     if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
  3265   3262       sqlite3DbFree(db, p->zErrMsg);
  3266   3263       p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
  3267   3264       /* If the schema-cookie from the database file matches the cookie 
  3268   3265       ** stored with the in-memory representation of the schema, do
................................................................................
  3622   3619     pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
  3623   3620     if( pCx==0 ) goto no_mem;
  3624   3621     pCx->nullRow = 1;
  3625   3622     pCx->isEphemeral = 1;
  3626   3623     rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, 
  3627   3624                           BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
  3628   3625     if( rc==SQLITE_OK ){
  3629         -    rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1);
         3626  +    rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
  3630   3627     }
  3631   3628     if( rc==SQLITE_OK ){
  3632   3629       /* If a transient index is required, create it by calling
  3633   3630       ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
  3634   3631       ** opening it. If a transient table is required, just use the
  3635   3632       ** automatically created table with root-page 1 (an BLOB_INTKEY table).
  3636   3633       */