/ Check-in [06dcfe72]
Login

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

Overview
Comment:Do not load the root-page of a b-tree table/index when opening a cursor. Instead, allow it to be loaded when the cursor is first used (in function moveToRoot()). Also move the root-page flags sanity checks that were a part of the OP_OpenRead/OpenWrite opcodes into the moveToRoot() function. (CVS 6856)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 06dcfe72a6ff3f63639eeb00ec5b5022d10fc55b
User & Date: danielk1977 2009-07-07 15:47:12
Context
2009-07-07
17:38
Improvements to corrupt database detection in defragmentPage(). (CVS 6857) check-in: 87bbc8d6 user: drh tags: trunk
15:47
Do not load the root-page of a b-tree table/index when opening a cursor. Instead, allow it to be loaded when the cursor is first used (in function moveToRoot()). Also move the root-page flags sanity checks that were a part of the OP_OpenRead/OpenWrite opcodes into the moveToRoot() function. (CVS 6856) check-in: 06dcfe72 user: danielk1977 tags: trunk
13:56
If an error occurs in PagerBegin(), call pager_end_transaction() to reset the internal state of the pager object. (CVS 6855) check-in: ea7ed166 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.655 2009/07/07 11:39:59 drh Exp $
           12  +** $Id: btree.c,v 1.656 2009/07/07 15:47:12 danielk1977 Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** See the header comment on "btreeInt.h" for additional information.
    16     16   ** Including a description of file format and an overview of operation.
    17     17   */
    18     18   #include "btreeInt.h"
    19     19   
................................................................................
  3234   3234     if( NEVER(wrFlag && pBt->readOnly) ){
  3235   3235       return SQLITE_READONLY;
  3236   3236     }
  3237   3237     if( iTable==1 && pagerPagecount(pBt)==0 ){
  3238   3238       return SQLITE_EMPTY;
  3239   3239     }
  3240   3240   
  3241         -  pCur->pgnoRoot = (Pgno)iTable;
  3242         -  rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
  3243         -  if( rc!=SQLITE_OK ){
  3244         -    assert( pCur->apPage[0]==0 );
  3245         -    return rc;
  3246         -  }
  3247         -
  3248   3241     /* Now that no other errors can occur, finish filling in the BtCursor
  3249   3242     ** variables and link the cursor into the BtShared list.  */
         3243  +  pCur->pgnoRoot = (Pgno)iTable;
         3244  +  pCur->iPage = -1;
  3250   3245     pCur->pKeyInfo = pKeyInfo;
  3251   3246     pCur->pBtree = p;
  3252   3247     pCur->pBt = pBt;
  3253   3248     pCur->wrFlag = (u8)wrFlag;
  3254   3249     pCur->pNext = pBt->pCursor;
  3255   3250     if( pCur->pNext ){
  3256   3251       pCur->pNext->pPrev = pCur;
................................................................................
  3987   3982     }
  3988   3983   
  3989   3984     if( pCur->iPage>=0 ){
  3990   3985       int i;
  3991   3986       for(i=1; i<=pCur->iPage; i++){
  3992   3987         releasePage(pCur->apPage[i]);
  3993   3988       }
         3989  +    pCur->iPage = 0;
  3994   3990     }else{
  3995   3991       if( 
  3996   3992         SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]))
  3997   3993       ){
  3998   3994         pCur->eState = CURSOR_INVALID;
  3999   3995         return rc;
  4000   3996       }
         3997  +    pCur->iPage = 0;
         3998  +
         3999  +    /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
         4000  +    ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
         4001  +    ** NULL, the caller expects a table b-tree. If this is not the case,
         4002  +    ** return an SQLITE_CORRUPT error.  */
         4003  +    assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 );
         4004  +    if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){
         4005  +      return SQLITE_CORRUPT_BKPT;
         4006  +    }
  4001   4007     }
  4002   4008   
  4003   4009     pRoot = pCur->apPage[0];
  4004   4010     assert( pRoot->pgno==pCur->pgnoRoot );
  4005         -  pCur->iPage = 0;
  4006   4011     pCur->aiIdx[0] = 0;
  4007   4012     pCur->info.nSize = 0;
  4008   4013     pCur->atLast = 0;
  4009   4014     pCur->validNKey = 0;
  4010   4015   
  4011   4016     if( pRoot->nCell==0 && !pRoot->leaf ){
  4012   4017       Pgno subpage;

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.869 2009/07/03 16:25:07 danielk1977 Exp $
           46  +** $Id: vdbe.c,v 1.870 2009/07/07 15:47:12 danielk1977 Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "vdbeInt.h"
    50     50   
    51     51   /*
    52     52   ** The following global variable is incremented every time a cursor
    53     53   ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes.  The test
................................................................................
  2909   2909     KeyInfo *pKeyInfo;
  2910   2910     int p2;
  2911   2911     int iDb;
  2912   2912     int wrFlag;
  2913   2913     Btree *pX;
  2914   2914     VdbeCursor *pCur;
  2915   2915     Db *pDb;
  2916         -  int flags;
  2917   2916   
  2918   2917     nField = 0;
  2919   2918     pKeyInfo = 0;
  2920   2919     p2 = pOp->p2;
  2921   2920     iDb = pOp->p3;
  2922   2921     assert( iDb>=0 && iDb<db->nDb );
  2923   2922     assert( (p->btreeMask & (1<<iDb))!=0 );
................................................................................
  2957   2956     assert( pOp->p1>=0 );
  2958   2957     pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
  2959   2958     if( pCur==0 ) goto no_mem;
  2960   2959     pCur->nullRow = 1;
  2961   2960     rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
  2962   2961     pCur->pKeyInfo = pKeyInfo;
  2963   2962   
  2964         -  switch( rc ){
  2965         -    case SQLITE_OK: {
  2966         -      flags = sqlite3BtreeFlags(pCur->pCursor);
  2967         -
  2968         -      /* Sanity checking.  Only the lower four bits of the flags byte should
  2969         -      ** be used.  Bit 3 (mask 0x08) is unpredictable.  The lower 3 bits
  2970         -      ** (mask 0x07) should be either 5 (intkey+leafdata for tables) or
  2971         -      ** 2 (zerodata for indices).  If these conditions are not met it can
  2972         -      ** only mean that we are dealing with a corrupt database file.
  2973         -      ** Note:  All of the above is checked already in sqlite3BtreeCursor().
  2974         -      */
  2975         -      assert( (flags & 0xf0)==0 );
  2976         -      assert( (flags & 0x07)==5 || (flags & 0x07)==2 );
  2977         -
  2978         -      pCur->isTable = (flags & BTREE_INTKEY)!=0 ?1:0;
  2979         -      pCur->isIndex = (flags & BTREE_ZERODATA)!=0 ?1:0;
  2980         -      /* If P4==0 it means we are expected to open a table.  If P4!=0 then
  2981         -      ** we expect to be opening an index.  If this is not what happened,
  2982         -      ** then the database is corrupt
  2983         -      */
  2984         -      if( (pCur->isTable && pOp->p4type==P4_KEYINFO)
  2985         -       || (pCur->isIndex && pOp->p4type!=P4_KEYINFO) ){
  2986         -        rc = SQLITE_CORRUPT_BKPT;
  2987         -        goto abort_due_to_error;
  2988         -      }
  2989         -      break;
  2990         -    }
  2991         -    case SQLITE_EMPTY: {
  2992         -      pCur->isTable = pOp->p4type!=P4_KEYINFO;
  2993         -      pCur->isIndex = !pCur->isTable;
  2994         -      pCur->pCursor = 0;
  2995         -      rc = SQLITE_OK;
  2996         -      break;
  2997         -    }
  2998         -    default: {
  2999         -      assert( rc!=SQLITE_BUSY );  /* Busy conditions detected earlier */
  3000         -      goto abort_due_to_error;
  3001         -    }
  3002         -  }
         2963  +  /* Since it performs no memory allocation or IO, the only values that
         2964  +  ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK. 
         2965  +  ** SQLITE_EMPTY is only returned when attempting to open the table
         2966  +  ** rooted at page 1 of a zero-byte database.  */
         2967  +  assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
         2968  +  if( rc==SQLITE_EMPTY ){
         2969  +    pCur->pCursor = 0;
         2970  +    rc = SQLITE_OK;
         2971  +  }
         2972  +
         2973  +  /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
         2974  +  ** SQLite used to check if the root-page flags were sane at this point
         2975  +  ** and report database corruption if they were not, but this check has
         2976  +  ** since moved into the btree layer.  */  
         2977  +  pCur->isTable = pOp->p4type!=P4_KEYINFO;
         2978  +  pCur->isIndex = !pCur->isTable;
  3003   2979     break;
  3004   2980   }
  3005   2981   
  3006   2982   /* Opcode: OpenEphemeral P1 P2 * P4 *
  3007   2983   **
  3008   2984   ** Open a new cursor P1 to a transient table.
  3009   2985   ** The cursor is always opened read/write even if