/ Check-in [93f811ec]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Change a few selected functions to macros to speed things up. (CVS 4015)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 93f811ec747f6a42daf9ee27cd8b013f248552a1
User & Date: danielk1977 2007-05-16 17:28:43
Context
2007-05-16
17:50
Avoid passing a negative value to isspace() in a couple places. (CVS 4016) check-in: d5db8be3 user: danielk1977 tags: trunk
17:28
Change a few selected functions to macros to speed things up. (CVS 4015) check-in: 93f811ec user: danielk1977 tags: trunk
14:23
Omit some extra code when OMIT_INCRBLOB is defined. (CVS 4014) check-in: 1d89be28 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.381 2007/05/12 10:41:48 danielk1977 Exp $
           12  +** $Id: btree.c,v 1.382 2007/05/16 17:28:43 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   
................................................................................
   415    415   /*
   416    416   ** Given a btree page and a cell index (0 means the first cell on
   417    417   ** the page, 1 means the second cell, and so forth) return a pointer
   418    418   ** to the cell content.
   419    419   **
   420    420   ** This routine works only for pages that do not contain overflow cells.
   421    421   */
          422  +#define findCell(pPage, iCell) \
          423  +  ((pPage)->aData + get2byte(&(pPage)->aData[(pPage)->cellOffset+2*(iCell)]))
   422    424   u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell){
   423    425     u8 *data = pPage->aData;
   424    426     assert( iCell>=0 );
   425    427     assert( iCell<get2byte(&data[pPage->hdrOffset+3]) );
   426         -  return data + get2byte(&data[pPage->cellOffset+2*iCell]);
          428  +  return findCell(pPage, iCell);
   427    429   }
   428    430   
   429    431   /*
   430    432   ** This a more complex version of sqlite3BtreeFindCell() that works for
   431    433   ** pages that do contain overflow cells.  See insert
   432    434   */
   433    435   static u8 *findOverflowCell(MemPage *pPage, int iCell){
................................................................................
   440    442       if( k<=iCell ){
   441    443         if( k==iCell ){
   442    444           return pOvfl->pCell;
   443    445         }
   444    446         iCell--;
   445    447       }
   446    448     }
   447         -  return sqlite3BtreeFindCell(pPage, iCell);
          449  +  return findCell(pPage, iCell);
   448    450   }
   449    451   
   450    452   /*
   451    453   ** Parse a cell content block and fill in the CellInfo structure.  There
   452    454   ** are two versions of this function.  sqlite3BtreeParseCell() takes a 
   453    455   ** cell index as the second argument and sqlite3BtreeParseCellPtr() 
   454    456   ** takes a pointer to the body of the cell as its second argument.
          457  +**
          458  +** Within this file, the parseCell() macro can be called instead of
          459  +** sqlite3BtreeParseCellPtr(). Using some compilers, this will be faster.
   455    460   */
   456    461   void sqlite3BtreeParseCellPtr(
   457    462     MemPage *pPage,         /* Page containing the cell */
   458    463     u8 *pCell,              /* Pointer to the cell text. */
   459    464     CellInfo *pInfo         /* Fill in this structure */
   460    465   ){
   461    466     int n;                  /* Number bytes in cell content header */
................................................................................
   515    520       }else{
   516    521         pInfo->nLocal = minLocal;
   517    522       }
   518    523       pInfo->iOverflow = pInfo->nLocal + n;
   519    524       pInfo->nSize = pInfo->iOverflow + 4;
   520    525     }
   521    526   }
          527  +#define parseCell(pPage, iCell, pInfo) \
          528  +  sqlite3BtreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo))
   522    529   void sqlite3BtreeParseCell(
   523    530     MemPage *pPage,         /* Page containing the cell */
   524    531     int iCell,              /* The cell index.  First cell is 0 */
   525    532     CellInfo *pInfo         /* Fill in this structure */
   526    533   ){
   527         -  sqlite3BtreeParseCellPtr(pPage, sqlite3BtreeFindCell(pPage, iCell), pInfo);
          534  +  parseCell(pPage, iCell, pInfo);
   528    535   }
   529    536   
   530    537   /*
   531    538   ** Compute the total number of bytes that a Cell needs in the cell
   532    539   ** data area of the btree-page.  The return number includes the cell
   533    540   ** data header and the local payload, but not any overflow page or
   534    541   ** the space used by the cell pointer.
................................................................................
  1657   1664     int isInitOrig = pPage->isInit;
  1658   1665     Pgno pgno = pPage->pgno;
  1659   1666   
  1660   1667     sqlite3BtreeInitPage(pPage, 0);
  1661   1668     nCell = pPage->nCell;
  1662   1669   
  1663   1670     for(i=0; i<nCell; i++){
  1664         -    u8 *pCell = sqlite3BtreeFindCell(pPage, i);
         1671  +    u8 *pCell = findCell(pPage, i);
  1665   1672   
  1666   1673       rc = ptrmapPutOvflPtr(pPage, pCell);
  1667   1674       if( rc!=SQLITE_OK ){
  1668   1675         goto set_child_ptrmaps_out;
  1669   1676       }
  1670   1677   
  1671   1678       if( !pPage->leaf ){
................................................................................
  1712   1719       int i;
  1713   1720       int nCell;
  1714   1721   
  1715   1722       sqlite3BtreeInitPage(pPage, 0);
  1716   1723       nCell = pPage->nCell;
  1717   1724   
  1718   1725       for(i=0; i<nCell; i++){
  1719         -      u8 *pCell = sqlite3BtreeFindCell(pPage, i);
         1726  +      u8 *pCell = findCell(pPage, i);
  1720   1727         if( eType==PTRMAP_OVERFLOW1 ){
  1721   1728           CellInfo info;
  1722   1729           sqlite3BtreeParseCellPtr(pPage, pCell, &info);
  1723   1730           if( info.iOverflow ){
  1724   1731             if( iFrom==get4byte(&pCell[info.iOverflow]) ){
  1725   1732               put4byte(&pCell[info.iOverflow], iTo);
  1726   1733               break;
................................................................................
  2451   2458   void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
  2452   2459     if( pCur->pPage ){
  2453   2460       sqlite3PagerUnref(pCur->pPage->pDbPage);
  2454   2461     }
  2455   2462   }
  2456   2463   
  2457   2464   /*
  2458         -** Make sure the BtCursor.info field of the given cursor is valid.
  2459         -** If it is not already valid, call sqlite3BtreeParseCell() to fill it in.
         2465  +** The GET_CELL_INFO() macro. Takes one argument, a pointer to a valid
         2466  +** btree cursor (type BtCursor*).  This macro makes sure the BtCursor.info
         2467  +** field of the given cursor is valid.  If it is not already valid, call
         2468  +** sqlite3BtreeParseCell() to fill it in.
  2460   2469   **
  2461   2470   ** BtCursor.info is a cache of the information in the current cell.
  2462   2471   ** Using this cache reduces the number of calls to sqlite3BtreeParseCell().
  2463   2472   */
  2464         -static void getCellInfo(BtCursor *pCur){
  2465         -  if( pCur->info.nSize==0 ){
  2466         -    sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info);
  2467         -  }else{
  2468   2473   #ifndef NDEBUG
         2474  +  static void assertCellInfo(BtCursor *pCur){
  2469   2475       CellInfo info;
  2470   2476       memset(&info, 0, sizeof(info));
  2471   2477       sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &info);
  2472   2478       assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
         2479  +  }
         2480  +#else
         2481  +  #define assertCellInfo(x)
  2473   2482   #endif
  2474         -  }
  2475         -}
         2483  +
         2484  +#define GET_CELL_INFO(pCur)                                             \
         2485  +  if( pCur->info.nSize==0 )                                             \
         2486  +    sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info);         \
         2487  +  else                                                                  \
         2488  +    assertCellInfo(pCur);
         2489  +   
  2476   2490   
  2477   2491   /*
  2478   2492   ** Set *pSize to the size of the buffer needed to hold the value of
  2479   2493   ** the key for the current entry.  If the cursor is not pointing
  2480   2494   ** to a valid entry, *pSize is set to 0. 
  2481   2495   **
  2482   2496   ** For a table with the INTKEY flag set, this routine returns the key
................................................................................
  2485   2499   int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
  2486   2500     int rc = restoreOrClearCursorPosition(pCur);
  2487   2501     if( rc==SQLITE_OK ){
  2488   2502       assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
  2489   2503       if( pCur->eState==CURSOR_INVALID ){
  2490   2504         *pSize = 0;
  2491   2505       }else{
  2492         -      getCellInfo(pCur);
         2506  +      GET_CELL_INFO(pCur);
  2493   2507         *pSize = pCur->info.nKey;
  2494   2508       }
  2495   2509     }
  2496   2510     return rc;
  2497   2511   }
  2498   2512   
  2499   2513   /*
................................................................................
  2507   2521     int rc = restoreOrClearCursorPosition(pCur);
  2508   2522     if( rc==SQLITE_OK ){
  2509   2523       assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
  2510   2524       if( pCur->eState==CURSOR_INVALID ){
  2511   2525         /* Not pointing at a valid entry - set *pSize to 0. */
  2512   2526         *pSize = 0;
  2513   2527       }else{
  2514         -      getCellInfo(pCur);
         2528  +      GET_CELL_INFO(pCur);
  2515   2529         *pSize = pCur->info.nData;
  2516   2530       }
  2517   2531     }
  2518   2532     return rc;
  2519   2533   }
  2520   2534   
  2521   2535   /*
................................................................................
  2680   2694     BtShared *pBt = pCur->pBtree->pBt;   /* Btree this cursor belongs to */
  2681   2695   
  2682   2696     assert( pPage );
  2683   2697     assert( pCur->eState==CURSOR_VALID );
  2684   2698     assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  2685   2699     assert( offset>=0 );
  2686   2700   
  2687         -  getCellInfo(pCur);
         2701  +  GET_CELL_INFO(pCur);
  2688   2702     aPayload = pCur->info.pCell + pCur->info.nHeader;
  2689   2703     nKey = (pPage->intKey ? 0 : pCur->info.nKey);
  2690   2704   
  2691   2705     if( skipKey ){
  2692   2706       offset += nKey;
  2693   2707     }
  2694   2708     if( offset+amt > nKey+pCur->info.nData ){
................................................................................
  2870   2884     u32 nKey;
  2871   2885     int nLocal;
  2872   2886   
  2873   2887     assert( pCur!=0 && pCur->pPage!=0 );
  2874   2888     assert( pCur->eState==CURSOR_VALID );
  2875   2889     pPage = pCur->pPage;
  2876   2890     assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  2877         -  getCellInfo(pCur);
         2891  +  GET_CELL_INFO(pCur);
  2878   2892     aPayload = pCur->info.pCell;
  2879   2893     aPayload += pCur->info.nHeader;
  2880   2894     if( pPage->intKey ){
  2881   2895       nKey = 0;
  2882   2896     }else{
  2883   2897       nKey = pCur->info.nKey;
  2884   2898     }
................................................................................
  3041   3055     Pgno pgno;
  3042   3056     int rc;
  3043   3057     MemPage *pPage;
  3044   3058   
  3045   3059     assert( pCur->eState==CURSOR_VALID );
  3046   3060     while( !(pPage = pCur->pPage)->leaf ){
  3047   3061       assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  3048         -    pgno = get4byte(sqlite3BtreeFindCell(pPage, pCur->idx));
         3062  +    pgno = get4byte(findCell(pPage, pCur->idx));
  3049   3063       rc = moveToChild(pCur, pgno);
  3050   3064       if( rc ) return rc;
  3051   3065     }
  3052   3066     return SQLITE_OK;
  3053   3067   }
  3054   3068   
  3055   3069   /*
................................................................................
  3178   3192       }
  3179   3193       if( lwr<=upr ) for(;;){
  3180   3194         void *pCellKey;
  3181   3195         i64 nCellKey;
  3182   3196         pCur->info.nSize = 0;
  3183   3197         if( pPage->intKey ){
  3184   3198           u8 *pCell;
  3185         -        pCell = sqlite3BtreeFindCell(pPage, pCur->idx) + pPage->childPtrSize;
         3199  +        pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize;
  3186   3200           if( pPage->hasData ){
  3187   3201             u32 dummy;
  3188   3202             pCell += getVarint32(pCell, &dummy);
  3189   3203           }
  3190   3204           getVarint(pCell, (u64 *)&nCellKey);
  3191   3205           if( nCellKey<nKey ){
  3192   3206             c = -1;
................................................................................
  3233   3247       assert( lwr==upr+1 );
  3234   3248       assert( pPage->isInit );
  3235   3249       if( pPage->leaf ){
  3236   3250         chldPg = 0;
  3237   3251       }else if( lwr>=pPage->nCell ){
  3238   3252         chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
  3239   3253       }else{
  3240         -      chldPg = get4byte(sqlite3BtreeFindCell(pPage, lwr));
         3254  +      chldPg = get4byte(findCell(pPage, lwr));
  3241   3255       }
  3242   3256       if( chldPg==0 ){
  3243   3257         assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
  3244   3258         if( pRes ) *pRes = c;
  3245   3259         return SQLITE_OK;
  3246   3260       }
  3247   3261       pCur->idx = lwr;
................................................................................
  3360   3374     }
  3361   3375     pCur->skip = 0;
  3362   3376   
  3363   3377     pPage = pCur->pPage;
  3364   3378     assert( pPage->isInit );
  3365   3379     assert( pCur->idx>=0 );
  3366   3380     if( !pPage->leaf ){
  3367         -    pgno = get4byte( sqlite3BtreeFindCell(pPage, pCur->idx) );
         3381  +    pgno = get4byte( findCell(pPage, pCur->idx) );
  3368   3382       rc = moveToChild(pCur, pgno);
  3369   3383       if( rc ) return rc;
  3370   3384       rc = moveToRightmost(pCur);
  3371   3385     }else{
  3372   3386       while( pCur->idx==0 ){
  3373   3387         if( sqlite3BtreeIsRootPage(pPage) ){
  3374   3388           pCur->eState = CURSOR_INVALID;
................................................................................
  3929   3943     int i;
  3930   3944     BtShared *pBt = pPage->pBt;
  3931   3945     int rc = SQLITE_OK;
  3932   3946   
  3933   3947     if( pPage->leaf ) return SQLITE_OK;
  3934   3948   
  3935   3949     for(i=0; i<pPage->nCell; i++){
  3936         -    u8 *pCell = sqlite3BtreeFindCell(pPage, i);
         3950  +    u8 *pCell = findCell(pPage, i);
  3937   3951       if( !pPage->leaf ){
  3938   3952         rc = reparentPage(pBt, get4byte(pCell), pPage, i);
  3939   3953         if( rc!=SQLITE_OK ) return rc;
  3940   3954       }
  3941   3955     }
  3942   3956     if( !pPage->leaf ){
  3943   3957       rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), 
................................................................................
  4183   4197     sqlite3PagerRef(pParent->pDbPage);
  4184   4198   
  4185   4199     /* pPage is currently the right-child of pParent. Change this
  4186   4200     ** so that the right-child is the new page allocated above and
  4187   4201     ** pPage is the next-to-right child. 
  4188   4202     */
  4189   4203     assert( pPage->nCell>0 );
  4190         -  pCell = sqlite3BtreeFindCell(pPage, pPage->nCell-1);
         4204  +  pCell = findCell(pPage, pPage->nCell-1);
  4191   4205     sqlite3BtreeParseCellPtr(pPage, pCell, &info);
  4192   4206     rc = fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize);
  4193   4207     if( rc!=SQLITE_OK ){
  4194   4208       return rc;
  4195   4209     }
  4196   4210     assert( parentSize<64 );
  4197   4211     rc = insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
................................................................................
  4333   4347     ** is the rightmost child of pParent then set idx to pParent->nCell 
  4334   4348     */
  4335   4349     if( pParent->idxShift ){
  4336   4350       Pgno pgno;
  4337   4351       pgno = pPage->pgno;
  4338   4352       assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  4339   4353       for(idx=0; idx<pParent->nCell; idx++){
  4340         -      if( get4byte(sqlite3BtreeFindCell(pParent, idx))==pgno ){
         4354  +      if( get4byte(findCell(pParent, idx))==pgno ){
  4341   4355           break;
  4342   4356         }
  4343   4357       }
  4344   4358       assert( idx<pParent->nCell
  4345   4359                || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno );
  4346   4360     }else{
  4347   4361       idx = pPage->idxParent;
................................................................................
  4367   4381     }
  4368   4382     if( nxDiv<0 ){
  4369   4383       nxDiv = 0;
  4370   4384     }
  4371   4385     nDiv = 0;
  4372   4386     for(i=0, k=nxDiv; i<NB; i++, k++){
  4373   4387       if( k<pParent->nCell ){
  4374         -      apDiv[i] = sqlite3BtreeFindCell(pParent, k);
         4388  +      apDiv[i] = findCell(pParent, k);
  4375   4389         nDiv++;
  4376   4390         assert( !pParent->leaf );
  4377   4391         pgnoOld[i] = get4byte(apDiv[i]);
  4378   4392       }else if( k==pParent->nCell ){
  4379   4393         pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]);
  4380   4394       }else{
  4381   4395         break;
................................................................................
  4868   4882         assert( pChild->nOverflow==0 );
  4869   4883         if( pChild->nFree>=100 ){
  4870   4884           /* The child information will fit on the root page, so do the
  4871   4885           ** copy */
  4872   4886           int i;
  4873   4887           zeroPage(pPage, pChild->aData[0]);
  4874   4888           for(i=0; i<pChild->nCell; i++){
  4875         -          apCell[i] = sqlite3BtreeFindCell(pChild,i);
         4889  +          apCell[i] = findCell(pChild,i);
  4876   4890             szCell[i] = cellSizePtr(pChild, apCell[i]);
  4877   4891           }
  4878   4892           assemblePage(pPage, pChild->nCell, apCell, szCell);
  4879   4893           /* Copy the right-pointer of the child to the parent. */
  4880   4894           put4byte(&pPage->aData[pPage->hdrOffset+8], 
  4881   4895               get4byte(&pChild->aData[pChild->hdrOffset+8]));
  4882   4896           freePage(pChild);
................................................................................
  5101   5115     rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
  5102   5116     if( rc ) goto end_insert;
  5103   5117     assert( szNew==cellSizePtr(pPage, newCell) );
  5104   5118     assert( szNew<=MX_CELL_SIZE(pBt) );
  5105   5119     if( loc==0 && CURSOR_VALID==pCur->eState ){
  5106   5120       int szOld;
  5107   5121       assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  5108         -    oldCell = sqlite3BtreeFindCell(pPage, pCur->idx);
         5122  +    oldCell = findCell(pPage, pCur->idx);
  5109   5123       if( !pPage->leaf ){
  5110   5124         memcpy(newCell, oldCell, 4);
  5111   5125       }
  5112   5126       szOld = cellSizePtr(pPage, oldCell);
  5113   5127       rc = clearCell(pPage, oldCell);
  5114   5128       if( rc ) goto end_insert;
  5115   5129       dropCell(pPage, pCur->idx, szOld);
................................................................................
  5173   5187       return rc;
  5174   5188     }
  5175   5189   
  5176   5190     /* Locate the cell within it's page and leave pCell pointing to the
  5177   5191     ** data. The clearCell() call frees any overflow pages associated with the
  5178   5192     ** cell. The cell itself is still intact.
  5179   5193     */
  5180         -  pCell = sqlite3BtreeFindCell(pPage, pCur->idx);
         5194  +  pCell = findCell(pPage, pCur->idx);
  5181   5195     if( !pPage->leaf ){
  5182   5196       pgnoChild = get4byte(pCell);
  5183   5197     }
  5184   5198     rc = clearCell(pPage, pCell);
  5185   5199     if( rc ) return rc;
  5186   5200   
  5187   5201     if( !pPage->leaf ){
................................................................................
  5205   5219       if( rc==SQLITE_OK ){
  5206   5220         rc = sqlite3PagerWrite(leafCur.pPage->pDbPage);
  5207   5221       }
  5208   5222       if( rc==SQLITE_OK ){
  5209   5223         TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n",
  5210   5224            pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno));
  5211   5225         dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell));
  5212         -      pNext = sqlite3BtreeFindCell(leafCur.pPage, leafCur.idx);
         5226  +      pNext = findCell(leafCur.pPage, leafCur.idx);
  5213   5227         szNext = cellSizePtr(leafCur.pPage, pNext);
  5214   5228         assert( MX_CELL_SIZE(pBt)>=szNext+4 );
  5215   5229         tempCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) );
  5216   5230         if( tempCell==0 ){
  5217   5231           rc = SQLITE_NOMEM;
  5218   5232         }
  5219   5233       }
................................................................................
  5396   5410     if( pgno>sqlite3PagerPagecount(pBt->pPager) ){
  5397   5411       return SQLITE_CORRUPT_BKPT;
  5398   5412     }
  5399   5413   
  5400   5414     rc = getAndInitPage(pBt, pgno, &pPage, pParent);
  5401   5415     if( rc ) goto cleardatabasepage_out;
  5402   5416     for(i=0; i<pPage->nCell; i++){
  5403         -    pCell = sqlite3BtreeFindCell(pPage, i);
         5417  +    pCell = findCell(pPage, i);
  5404   5418       if( !pPage->leaf ){
  5405   5419         rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1);
  5406   5420         if( rc ) goto cleardatabasepage_out;
  5407   5421       }
  5408   5422       rc = clearCell(pPage, pCell);
  5409   5423       if( rc ) goto cleardatabasepage_out;
  5410   5424     }
................................................................................
  5883   5897       int sz;
  5884   5898       CellInfo info;
  5885   5899   
  5886   5900       /* Check payload overflow pages
  5887   5901       */
  5888   5902       sqlite3_snprintf(sizeof(zContext), zContext,
  5889   5903                "On tree page %d cell %d: ", iPage, i);
  5890         -    pCell = sqlite3BtreeFindCell(pPage,i);
         5904  +    pCell = findCell(pPage,i);
  5891   5905       sqlite3BtreeParseCellPtr(pPage, pCell, &info);
  5892   5906       sz = info.nData;
  5893   5907       if( !pPage->intKey ) sz += info.nKey;
  5894   5908       assert( sz==info.nPayload );
  5895   5909       if( sz>info.nLocal ){
  5896   5910         int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
  5897   5911         Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);

Changes to src/btreeInt.h.

     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: btreeInt.h,v 1.3 2007/05/16 14:23:00 danielk1977 Exp $
           12  +** $Id: btreeInt.h,v 1.4 2007/05/16 17:28:43 danielk1977 Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** For a detailed discussion of BTrees, refer to
    16     16   **
    17     17   **     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
    18     18   **     "Sorting And Searching", pages 473-480. Addison-Wesley
    19     19   **     Publishing Company, Reading, Massachusetts.
................................................................................
   566    566     char *zErrMsg;    /* An error message.  NULL if no errors seen. */
   567    567     int nErr;         /* Number of messages written to zErrMsg so far */
   568    568   };
   569    569   
   570    570   /*
   571    571   ** Read or write a two- and four-byte big-endian integer values.
   572    572   */
   573         -#define get2byte(x) ((x)[0]<<8 | (x)[1])
          573  +#define get2byte(x)   ((x)[0]<<8 | (x)[1])
          574  +#define put2byte(p,v) ((p)[0] = (v)>>8, (p)[1] = (v))
   574    575   #define get4byte sqlite3Get4byte
   575         -#define put2byte sqlite3Put2byte
   576    576   #define put4byte sqlite3Put4byte
   577    577   
   578    578   /*
   579    579   ** Internal routines that should be accessed by the btree layer only.
   580    580   */
   581    581   int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int);
   582    582   int sqlite3BtreeInitPage(MemPage *pPage, MemPage *pParent);

Changes to src/malloc.c.

     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     12   ** Memory allocation functions used throughout sqlite.
    13     13   **
    14     14   **
    15         -** $Id: malloc.c,v 1.1 2007/05/05 11:48:54 drh Exp $
           15  +** $Id: malloc.c,v 1.2 2007/05/16 17:28:43 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include "os.h"
    19     19   #include <stdarg.h>
    20     20   #include <ctype.h>
    21     21   
    22     22   /*
................................................................................
   784    784   ** function. However, if a malloc() failure has occured since the previous
   785    785   ** invocation SQLITE_NOMEM is returned instead. 
   786    786   **
   787    787   ** If the first argument, db, is not NULL and a malloc() error has occured,
   788    788   ** then the connection error-code (the value returned by sqlite3_errcode())
   789    789   ** is set to SQLITE_NOMEM.
   790    790   */
   791         -static int mallocHasFailed = 0;
          791  +int sqlite3_mallocHasFailed = 0;
   792    792   int sqlite3ApiExit(sqlite3* db, int rc){
   793    793     if( sqlite3MallocFailed() ){
   794         -    mallocHasFailed = 0;
          794  +    sqlite3_mallocHasFailed = 0;
   795    795       sqlite3OsLeaveMutex();
   796    796       sqlite3Error(db, SQLITE_NOMEM, 0);
   797    797       rc = SQLITE_NOMEM;
   798    798     }
   799    799     return rc & (db ? db->errMask : 0xff);
   800    800   }
   801    801   
   802         -/* 
   803         -** Return true is a malloc has failed in this thread since the last call
   804         -** to sqlite3ApiExit(), or false otherwise.
   805         -*/
   806         -int sqlite3MallocFailed(){
   807         -  return (mallocHasFailed && sqlite3OsInMutex(1));
   808         -}
   809         -
   810    802   /* 
   811    803   ** Set the "malloc has failed" condition to true for this thread.
   812    804   */
   813    805   void sqlite3FailedMalloc(){
   814    806     if( !sqlite3MallocFailed() ){
   815    807       sqlite3OsEnterMutex();
   816         -    assert( mallocHasFailed==0 );
   817         -    mallocHasFailed = 1;
          808  +    assert( sqlite3_mallocHasFailed==0 );
          809  +    sqlite3_mallocHasFailed = 1;
   818    810     }
   819    811   }
   820    812   
   821    813   #ifdef SQLITE_MEMDEBUG
   822    814   /*
   823    815   ** This function sets a flag in the thread-specific-data structure that will
   824    816   ** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called.

Changes to src/sqliteInt.h.

     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     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.568 2007/05/15 16:51:37 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.569 2007/05/16 17:28:43 danielk1977 Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   #include "limits.h"
    19     19   
    20     20   
    21     21   #if defined(SQLITE_TCL) || defined(TCLSH)
................................................................................
   250    250   #define sqliteRealloc(x,y)       sqlite3Realloc(x,y)
   251    251   #define sqliteStrDup(x)          sqlite3StrDup(x)
   252    252   #define sqliteStrNDup(x,y)       sqlite3StrNDup(x,y)
   253    253   #define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y)
   254    254   
   255    255   #endif
   256    256   
          257  +/* Variable sqlite3_mallocHasFailed is set to true after a malloc() 
          258  +** failure occurs. 
          259  +**
          260  +** The sqlite3MallocFailed() macro returns true if a malloc has failed
          261  +** in this thread since the last call to sqlite3ApiExit(), or false 
          262  +** otherwise.
          263  +*/
          264  +extern int sqlite3_mallocHasFailed;
          265  +#define sqlite3MallocFailed() (sqlite3_mallocHasFailed && sqlite3OsInMutex(1))
          266  +
   257    267   #define sqliteFree(x)          sqlite3FreeX(x)
   258    268   #define sqliteAllocSize(x)     sqlite3AllocSize(x)
   259         -
   260    269   
   261    270   /*
   262    271   ** An instance of this structure might be allocated to store information
   263    272   ** specific to a single thread.
   264    273   */
   265    274   struct ThreadData {
   266    275     int dummy;               /* So that this structure is never empty */
................................................................................
   328    337   typedef struct TableLock TableLock;
   329    338   typedef struct Token Token;
   330    339   typedef struct TriggerStack TriggerStack;
   331    340   typedef struct TriggerStep TriggerStep;
   332    341   typedef struct Trigger Trigger;
   333    342   typedef struct WhereInfo WhereInfo;
   334    343   typedef struct WhereLevel WhereLevel;
          344  +
          345  +#include "os.h"
   335    346   
   336    347   /*
   337    348   ** Each database file to be accessed by the system is an instance
   338    349   ** of the following structure.  There are normally two of these structures
   339    350   ** in the sqlite.aDb[] array.  aDb[0] is the main database file and
   340    351   ** aDb[1] is the database file used to hold temporary tables.  Additional
   341    352   ** databases may be attached.
................................................................................
  1874   1885   Schema *sqlite3SchemaGet(Btree *);
  1875   1886   int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
  1876   1887   KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
  1877   1888   int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, 
  1878   1889     void (*)(sqlite3_context*,int,sqlite3_value **),
  1879   1890     void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*));
  1880   1891   int sqlite3ApiExit(sqlite3 *db, int);
  1881         -int sqlite3MallocFailed(void);
  1882   1892   void sqlite3FailedMalloc(void);
  1883   1893   void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
  1884   1894   int sqlite3OpenTempDatabase(Parse *);
  1885   1895   
  1886   1896   #ifndef SQLITE_OMIT_LOAD_EXTENSION
  1887   1897     void sqlite3CloseExtensions(sqlite3*);
  1888   1898     int sqlite3AutoLoadExtensions(sqlite3*);

Changes to src/util.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Utility functions used throughout sqlite.
    13     13   **
    14     14   ** This file contains functions for allocating memory, comparing
    15     15   ** strings, and stuff like that.
    16     16   **
    17         -** $Id: util.c,v 1.203 2007/05/15 16:51:37 drh Exp $
           17  +** $Id: util.c,v 1.204 2007/05/16 17:28:43 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <stdarg.h>
    22     22   #include <ctype.h>
    23     23   
    24     24   
................................................................................
   533    533       v >>= 7;
   534    534     }while( v!=0 && i<9 );
   535    535     return i;
   536    536   }
   537    537   
   538    538   
   539    539   /*
   540         -** Read or write a two- and four-byte big-endian integer values.
          540  +** Read or write a four-byte big-endian integer value.
   541    541   */
   542         -u32 sqlite3Get2byte(const u8 *p){
   543         -  return (p[0]<<8) | p[1];
   544         -}
   545    542   u32 sqlite3Get4byte(const u8 *p){
   546    543     return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
   547    544   }
   548         -void sqlite3Put2byte(unsigned char *p, u32 v){
   549         -  p[0] = v>>8;
   550         -  p[1] = v;
   551         -}
   552    545   void sqlite3Put4byte(unsigned char *p, u32 v){
   553    546     p[0] = v>>24;
   554    547     p[1] = v>>16;
   555    548     p[2] = v>>8;
   556    549     p[3] = v;
   557    550   }
   558    551   

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.620 2007/05/16 14:23:00 danielk1977 Exp $
           46  +** $Id: vdbe.c,v 1.621 2007/05/16 17:28:43 danielk1977 Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "os.h"
    50     50   #include <ctype.h>
    51     51   #include <math.h>
    52     52   #include "vdbeInt.h"
    53     53   
................................................................................
   147    147   ** string that the stack entry itself controls.  In other words, it
   148    148   ** converts an MEM_Ephem string into an MEM_Dyn string.
   149    149   */
   150    150   #define Deephemeralize(P) \
   151    151      if( ((P)->flags&MEM_Ephem)!=0 \
   152    152          && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
   153    153   
          154  +/*
          155  +** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
          156  +** P if required.
          157  +*/
          158  +#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
          159  +
   154    160   /*
   155    161   ** Argument pMem points at a memory cell that will be passed to a
   156    162   ** user-defined function or returned to the user as the result of a query.
   157    163   ** The second argument, 'db_enc' is the text encoding used by the vdbe for
   158    164   ** stack variables.  This routine sets the pMem->enc and pMem->type
   159    165   ** variables used by the sqlite3_value_*() routines.
   160    166   */
................................................................................
  1466   1472   */
  1467   1473   case OP_ToText: {                  /* same as TK_TO_TEXT, no-push */
  1468   1474     assert( pTos>=p->aStack );
  1469   1475     if( pTos->flags & MEM_Null ) break;
  1470   1476     assert( MEM_Str==(MEM_Blob>>3) );
  1471   1477     pTos->flags |= (pTos->flags&MEM_Blob)>>3;
  1472   1478     applyAffinity(pTos, SQLITE_AFF_TEXT, encoding);
  1473         -  rc = sqlite3VdbeMemExpandBlob(pTos);
         1479  +  rc = ExpandBlob(pTos);
  1474   1480     assert( pTos->flags & MEM_Str );
  1475   1481     pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
  1476   1482     break;
  1477   1483   }
  1478   1484   
  1479   1485   /* Opcode: ToBlob * * *
  1480   1486   **
................................................................................
  1671   1677     affinity = pOp->p1 & 0xFF;
  1672   1678     if( affinity ){
  1673   1679       applyAffinity(pNos, affinity, encoding);
  1674   1680       applyAffinity(pTos, affinity, encoding);
  1675   1681     }
  1676   1682   
  1677   1683     assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 );
  1678         -  sqlite3VdbeMemExpandBlob(pNos);
  1679         -  sqlite3VdbeMemExpandBlob(pTos);
         1684  +  ExpandBlob(pNos);
         1685  +  ExpandBlob(pTos);
  1680   1686     res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3);
  1681   1687     switch( pOp->opcode ){
  1682   1688       case OP_Eq:    res = res==0;     break;
  1683   1689       case OP_Ne:    res = res!=0;     break;
  1684   1690       case OP_Lt:    res = res<0;      break;
  1685   1691       case OP_Le:    res = res<=0;     break;
  1686   1692       case OP_Gt:    res = res>0;      break;
................................................................................
  2271   2277       if( zAffinity ){
  2272   2278         applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
  2273   2279       }
  2274   2280       if( pRec->flags&MEM_Null ){
  2275   2281         containsNull = 1;
  2276   2282       }
  2277   2283       if( pRec->flags&MEM_Zero && pRec->n>0 ){
  2278         -      sqlite3VdbeMemExpandBlob(pRec);
         2284  +      ExpandBlob(pRec);
  2279   2285       }
  2280   2286       serial_type = sqlite3VdbeSerialType(pRec, file_format);
  2281   2287       len = sqlite3VdbeSerialTypeLen(serial_type);
  2282   2288       nData += len;
  2283   2289       nHdr += sqlite3VarintLen(serial_type);
  2284   2290       if( pRec->flags & MEM_Zero ){
  2285   2291         /* Only pure zero-filled BLOBs can be input to this Opcode.
................................................................................
  2924   2930         if( rc!=SQLITE_OK ){
  2925   2931           goto abort_due_to_error;
  2926   2932         }
  2927   2933         pC->lastRowid = pTos->u.i;
  2928   2934         pC->rowidIsValid = res==0;
  2929   2935       }else{
  2930   2936         assert( pTos->flags & MEM_Blob );
  2931         -      sqlite3VdbeMemExpandBlob(pTos);
         2937  +      ExpandBlob(pTos);
  2932   2938         rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
  2933   2939         if( rc!=SQLITE_OK ){
  2934   2940           goto abort_due_to_error;
  2935   2941         }
  2936   2942         pC->rowidIsValid = 0;
  2937   2943       }
  2938   2944       pC->deferredMoveto = 0;
................................................................................
  3827   3833     BtCursor *pCrsr;
  3828   3834     assert( pTos>=p->aStack );
  3829   3835     assert( i>=0 && i<p->nCursor );
  3830   3836     assert( p->apCsr[i]!=0 );
  3831   3837     assert( pTos->flags & MEM_Blob );
  3832   3838     if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
  3833   3839       assert( pC->isTable==0 );
  3834         -    rc = sqlite3VdbeMemExpandBlob(pTos);
         3840  +    rc = ExpandBlob(pTos);
  3835   3841       if( rc==SQLITE_OK ){
  3836   3842         int nKey = pTos->n;
  3837   3843         const char *zKey = pTos->z;
  3838   3844         rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p2);
  3839   3845         assert( pC->deferredMoveto==0 );
  3840   3846         pC->cacheStatus = CACHE_STALE;
  3841   3847       }
................................................................................
  3963   3969     assert( p->apCsr[i]!=0 );
  3964   3970     assert( pTos>=p->aStack );
  3965   3971     if( (pC = p->apCsr[i])->pCursor!=0 ){
  3966   3972       int res;
  3967   3973    
  3968   3974       assert( pTos->flags & MEM_Blob );  /* Created using OP_MakeRecord */
  3969   3975       assert( pC->deferredMoveto==0 );
  3970         -    sqlite3VdbeMemExpandBlob(pTos);
         3976  +    ExpandBlob(pTos);
  3971   3977       *pC->pIncrKey = pOp->p3!=0;
  3972   3978       assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT );
  3973   3979       rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res);
  3974   3980       *pC->pIncrKey = 0;
  3975   3981       if( rc!=SQLITE_OK ){
  3976   3982         break;
  3977   3983       }

Changes to src/vdbemem.c.

    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "os.h"
    20     20   #include <math.h>
    21     21   #include <ctype.h>
    22     22   #include "vdbeInt.h"
    23     23   
           24  +/*
           25  +** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
           26  +** P if required.
           27  +*/
           28  +#define expandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
           29  +
    24     30   /*
    25     31   ** If pMem is an object with a valid string representation, this routine
    26     32   ** ensures the internal encoding for the string representation is
    27     33   ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
    28     34   **
    29     35   ** If pMem is not a string object, or the encoding of the string
    30     36   ** representation is already stored using the requested encoding, then this
................................................................................
    59     65   ** Make the given Mem object MEM_Dyn.
    60     66   **
    61     67   ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
    62     68   */
    63     69   int sqlite3VdbeMemDynamicify(Mem *pMem){
    64     70     int n;
    65     71     u8 *z;
    66         -  sqlite3VdbeMemExpandBlob(pMem);
           72  +  expandBlob(pMem);
    67     73     if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){
    68     74       return SQLITE_OK;
    69     75     }
    70     76     assert( (pMem->flags & MEM_Dyn)==0 );
    71     77     n = pMem->n;
    72     78     assert( pMem->flags & (MEM_Str|MEM_Blob) );
    73     79     z = sqliteMallocRaw( n+2 );
................................................................................
   116    122   ** of the Mem.z[] array can be modified.
   117    123   **
   118    124   ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
   119    125   */
   120    126   int sqlite3VdbeMemMakeWriteable(Mem *pMem){
   121    127     int n;
   122    128     u8 *z;
   123         -  sqlite3VdbeMemExpandBlob(pMem);
          129  +  expandBlob(pMem);
   124    130     if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){
   125    131       return SQLITE_OK;
   126    132     }
   127    133     assert( (pMem->flags & MEM_Dyn)==0 );
   128    134     assert( pMem->flags & (MEM_Str|MEM_Blob) );
   129    135     if( (n = pMem->n)+2<sizeof(pMem->zShort) ){
   130    136       z = (u8*)pMem->zShort;
................................................................................
   832    838     assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
   833    839   
   834    840     if( pVal->flags&MEM_Null ){
   835    841       return 0;
   836    842     }
   837    843     assert( (MEM_Blob>>3) == MEM_Str );
   838    844     pVal->flags |= (pVal->flags & MEM_Blob)>>3;
   839         -  sqlite3VdbeMemExpandBlob(pVal);
          845  +  expandBlob(pVal);
   840    846     if( pVal->flags&MEM_Str ){
   841    847       sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
   842    848       if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){
   843    849         assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );
   844    850         if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){
   845    851           return 0;
   846    852         }