/ Check-in [e9f01c01]
Login

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

Overview
Comment:Change the signature of sqlite3PagerPagecount() so that it can return an error code. (CVS 5195)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e9f01c01866d302d81bf9ebc484ea6351cbc0f60
User & Date: danielk1977 2008-06-07 08:58:22
Context
2008-06-09
15:51
Add test file incrblob2.test to test opening two blob handles on a single database blob. (CVS 5196) check-in: c1d877fe user: danielk1977 tags: trunk
2008-06-07
08:58
Change the signature of sqlite3PagerPagecount() so that it can return an error code. (CVS 5195) check-in: e9f01c01 user: danielk1977 tags: trunk
05:19
Do not call xSync() from zeroJournalHdr() if the Pager.noSync flag is set (i.e. for temp files). (CVS 5194) check-in: 9f5cbe29 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665

1666
1667
1668
1669
1670
1671
1672
....
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805



1806
1807
1808
1809
1810
1811
1812
....
2138
2139
2140
2141
2142
2143
2144







2145
2146
2147
2148
2149
2150
2151
....
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
....
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
....
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
....
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
....
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
....
4094
4095
4096
4097
4098
4099
4100

4101

4102
4103
4104
4105
4106
4107
4108
....
4123
4124
4125
4126
4127
4128
4129
4130

4131
4132
4133
4134
4135
4136
4137
....
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
....
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
....
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
....
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
....
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.458 2008/05/09 16:57:51 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"

................................................................................
  if( pBt->pPage1 ) return SQLITE_OK;
  rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0);
  if( rc!=SQLITE_OK ) return rc;

  /* Do some checking to help insure the file we opened really is
  ** a valid database file. 
  */
  rc = SQLITE_NOTADB;
  nPage = sqlite3PagerPagecount(pBt->pPager);
  if( nPage<0 ){
    rc = SQLITE_IOERR;
    goto page1_init_failed;
  }else if( nPage>0 ){
    int pageSize;
    int usableSize;
    u8 *page1 = pPage1->aData;

    if( memcmp(page1, zMagicHeader, 16)!=0 ){
      goto page1_init_failed;
    }
    if( page1[18]>1 ){
      pBt->readOnly = 1;
    }
    if( page1[19]>1 ){
................................................................................
** Create a new database by initializing the first page of the
** file.
*/
static int newDatabase(BtShared *pBt){
  MemPage *pP1;
  unsigned char *data;
  int rc;


  assert( sqlite3_mutex_held(pBt->mutex) );
  if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK;



  pP1 = pBt->pPage1;
  assert( pP1!=0 );
  data = pP1->aData;
  rc = sqlite3PagerWrite(pP1->pDbPage);
  if( rc ) return rc;
  memcpy(data, zMagicHeader, sizeof(zMagicHeader));
  assert( sizeof(zMagicHeader)==16 );
................................................................................
    releasePage(pPtrPage);
    if( rc==SQLITE_OK ){
      rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
    }
  }
  return rc;
}








/* Forward declaration required by incrVacuumStep(). */
static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);

/*
** Perform a single step of an incremental-vacuum. If successful,
** return SQLITE_OK. If there is no work to do (and therefore no
................................................................................
static int incrVacuumStep(BtShared *pBt, Pgno nFin){
  Pgno iLastPg;             /* Last page in the database */
  Pgno nFreeList;           /* Number of pages still on the free-list */

  assert( sqlite3_mutex_held(pBt->mutex) );
  iLastPg = pBt->nTrunc;
  if( iLastPg==0 ){
    iLastPg = sqlite3PagerPagecount(pBt->pPager);
  }

  if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
    int rc;
    u8 eType;
    Pgno iPtrPage;

................................................................................
  if( !pBt->incrVacuum ){
    Pgno nFin = 0;

    if( pBt->nTrunc==0 ){
      Pgno nFree;
      Pgno nPtrmap;
      const int pgsz = pBt->pageSize;
      Pgno nOrig = sqlite3PagerPagecount(pBt->pPager);

      if( PTRMAP_ISPAGE(pBt, nOrig) ){
        return SQLITE_CORRUPT_BKPT;
      }
      if( nOrig==PENDING_BYTE_PAGE(pBt) ){
        nOrig--;
      }
................................................................................
      return rc;
    }
    if( pBt->readOnly && wrFlag ){
      return SQLITE_READONLY;
    }
  }
  pCur->pgnoRoot = (Pgno)iTable;
  if( iTable==1 && sqlite3PagerPagecount(pBt->pPager)==0 ){
    rc = SQLITE_EMPTY;
    goto create_cursor_exception;
  }
  rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0);
  if( rc!=SQLITE_OK ){
    goto create_cursor_exception;
  }
................................................................................
    Pgno iGuess = ovfl+1;
    u8 eType;

    while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){
      iGuess++;
    }

    if( iGuess<=sqlite3PagerPagecount(pBt->pPager) ){
      rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      if( eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){
        next = iGuess;
      }
................................................................................
    u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
    
    /* If the 'exact' parameter was true and a query of the pointer-map
    ** shows that the page 'nearby' is somewhere on the free-list, then
    ** the entire-list will be searched for that page.
    */
#ifndef SQLITE_OMIT_AUTOVACUUM
    if( exact && nearby<=sqlite3PagerPagecount(pBt->pPager) ){
      u8 eType;
      assert( nearby>0 );
      assert( pBt->autoVacuum );
      rc = ptrmapGet(pBt, nearby, &eType, 0);
      if( rc ) return rc;
      if( eType==PTRMAP_FREEPAGE ){
        searchList = 1;
................................................................................
        }else{
          closest = 0;
        }

        iPage = get4byte(&aData[8+closest*4]);
        if( !searchList || iPage==nearby ){
          *pPgno = iPage;

          if( *pPgno>sqlite3PagerPagecount(pBt->pPager) ){

            /* Free page off the end of the file */
            rc = SQLITE_CORRUPT_BKPT;
            goto end_allocate_page;
          }
          TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
                 ": %d more free pages\n",
                 *pPgno, closest+1, k, pTrunk->pgno, n-1));
................................................................................
      }
      releasePage(pPrevTrunk);
      pPrevTrunk = 0;
    }while( searchList );
  }else{
    /* There are no pages on the freelist, so create a new page at the
    ** end of the file */
    *pPgno = sqlite3PagerPagecount(pBt->pPager) + 1;


#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pBt->nTrunc ){
      /* An incr-vacuum has already run within this transaction. So the
      ** page to allocate is not from the physical end of the file, but
      ** at pBt->nTrunc. 
      */
................................................................................
  }
  ovflPgno = get4byte(&pCell[info.iOverflow]);
  ovflPageSize = pBt->usableSize - 4;
  nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
  assert( ovflPgno==0 || nOvfl>0 );
  while( nOvfl-- ){
    MemPage *pOvfl;
    if( ovflPgno==0 || ovflPgno>sqlite3PagerPagecount(pBt->pPager) ){
      return SQLITE_CORRUPT_BKPT;
    }

    rc = getOverflowPage(pBt, ovflPgno, &pOvfl, (nOvfl==0)?0:&ovflPgno);
    if( rc ) return rc;
    rc = freePage(pOvfl);
    sqlite3PagerUnref(pOvfl->pDbPage);
................................................................................
    ** information currently contained in the child.  If this is the 
    ** case, then do not do the transfer.  Leave page 1 empty except
    ** for the right-pointer to the child page.  The child page becomes
    ** the virtual root of the tree.
    */
    pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    assert( pgnoChild>0 );
    assert( pgnoChild<=sqlite3PagerPagecount(pPage->pBt->pPager) );
    rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0);
    if( rc ) goto end_shallow_balance;
    if( pPage->pgno==1 ){
      rc = sqlite3BtreeInitPage(pChild, pPage);
      if( rc ) goto end_shallow_balance;
      assert( pChild->nOverflow==0 );
      if( pChild->nFree>=100 ){
................................................................................
){
  MemPage *pPage = 0;
  int rc;
  unsigned char *pCell;
  int i;

  assert( sqlite3_mutex_held(pBt->mutex) );
  if( pgno>sqlite3PagerPagecount(pBt->pPager) ){
    return SQLITE_CORRUPT_BKPT;
  }

  rc = getAndInitPage(pBt, pgno, &pPage, pParent);
  if( rc ) goto cleardatabasepage_out;
  for(i=0; i<pPage->nCell; i++){
    pCell = findCell(pPage, i);
................................................................................
  nRef = sqlite3PagerRefcount(pBt->pPager);
  if( lockBtreeWithRetry(p)!=SQLITE_OK ){
    sqlite3BtreeLeave(p);
    return sqlite3StrDup("Unable to acquire a read lock on the database");
  }
  sCheck.pBt = pBt;
  sCheck.pPager = pBt->pPager;
  sCheck.nPage = sqlite3PagerPagecount(sCheck.pPager);
  sCheck.mxErr = mxErr;
  sCheck.nErr = 0;
  *pnErr = 0;
#ifndef SQLITE_OMIT_AUTOVACUUM
  if( pBt->nTrunc!=0 ){
    sCheck.nPage = pBt->nTrunc;
  }
................................................................................
  if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){
    return SQLITE_ERROR;
  }
  if( pBtTo->pCursor ){
    return SQLITE_BUSY;
  }

  nToPage = sqlite3PagerPagecount(pBtTo->pPager);
  nFromPage = sqlite3PagerPagecount(pBtFrom->pPager);
  iSkip = PENDING_BYTE_PAGE(pBtTo);

  /* Variable nNewPage is the number of pages required to store the
  ** contents of pFrom using the current page-size of pTo.
  */
  nNewPage = ((i64)nFromPage * (i64)nFromPageSize + (i64)nToPageSize - 1) / 
      (i64)nToPageSize;







|







 







<
|
<
|





>







 







>


|
>
>
>







 







>
>
>
>
>
>
>







 







|







 







|







 







|







 







|







 







|







 







>
|
>







 







|
>







 







|







 







|







 







|







 







|







 







|
|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
1650
1651
1652
1653
1654
1655
1656

1657

1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
....
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
....
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
....
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
....
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
....
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
....
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
....
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
....
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
....
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
....
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
....
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
....
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
....
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
....
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.459 2008/06/07 08:58:22 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"

................................................................................
  if( pBt->pPage1 ) return SQLITE_OK;
  rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0);
  if( rc!=SQLITE_OK ) return rc;

  /* Do some checking to help insure the file we opened really is
  ** a valid database file. 
  */

  rc = sqlite3PagerPagecount(pBt->pPager, &nPage);

  if( rc!=SQLITE_OK ){
    goto page1_init_failed;
  }else if( nPage>0 ){
    int pageSize;
    int usableSize;
    u8 *page1 = pPage1->aData;
    rc = SQLITE_NOTADB;
    if( memcmp(page1, zMagicHeader, 16)!=0 ){
      goto page1_init_failed;
    }
    if( page1[18]>1 ){
      pBt->readOnly = 1;
    }
    if( page1[19]>1 ){
................................................................................
** Create a new database by initializing the first page of the
** file.
*/
static int newDatabase(BtShared *pBt){
  MemPage *pP1;
  unsigned char *data;
  int rc;
  int nPage;

  assert( sqlite3_mutex_held(pBt->mutex) );
  rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
  if( rc!=SQLITE_OK || nPage>0 ){
    return rc;
  }
  pP1 = pBt->pPage1;
  assert( pP1!=0 );
  data = pP1->aData;
  rc = sqlite3PagerWrite(pP1->pDbPage);
  if( rc ) return rc;
  memcpy(data, zMagicHeader, sizeof(zMagicHeader));
  assert( sizeof(zMagicHeader)==16 );
................................................................................
    releasePage(pPtrPage);
    if( rc==SQLITE_OK ){
      rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
    }
  }
  return rc;
}

static int pagerPagecount(Pager *pPager){
  int rc;
  int nPage;
  rc = sqlite3PagerPagecount(pPager, &nPage);
  return (rc==SQLITE_OK?nPage:-1);
}

/* Forward declaration required by incrVacuumStep(). */
static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);

/*
** Perform a single step of an incremental-vacuum. If successful,
** return SQLITE_OK. If there is no work to do (and therefore no
................................................................................
static int incrVacuumStep(BtShared *pBt, Pgno nFin){
  Pgno iLastPg;             /* Last page in the database */
  Pgno nFreeList;           /* Number of pages still on the free-list */

  assert( sqlite3_mutex_held(pBt->mutex) );
  iLastPg = pBt->nTrunc;
  if( iLastPg==0 ){
    iLastPg = pagerPagecount(pBt->pPager);
  }

  if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
    int rc;
    u8 eType;
    Pgno iPtrPage;

................................................................................
  if( !pBt->incrVacuum ){
    Pgno nFin = 0;

    if( pBt->nTrunc==0 ){
      Pgno nFree;
      Pgno nPtrmap;
      const int pgsz = pBt->pageSize;
      int nOrig = pagerPagecount(pBt->pPager);

      if( PTRMAP_ISPAGE(pBt, nOrig) ){
        return SQLITE_CORRUPT_BKPT;
      }
      if( nOrig==PENDING_BYTE_PAGE(pBt) ){
        nOrig--;
      }
................................................................................
      return rc;
    }
    if( pBt->readOnly && wrFlag ){
      return SQLITE_READONLY;
    }
  }
  pCur->pgnoRoot = (Pgno)iTable;
  if( iTable==1 && pagerPagecount(pBt->pPager)==0 ){
    rc = SQLITE_EMPTY;
    goto create_cursor_exception;
  }
  rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0);
  if( rc!=SQLITE_OK ){
    goto create_cursor_exception;
  }
................................................................................
    Pgno iGuess = ovfl+1;
    u8 eType;

    while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){
      iGuess++;
    }

    if( iGuess<=pagerPagecount(pBt->pPager) ){
      rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      if( eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){
        next = iGuess;
      }
................................................................................
    u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
    
    /* If the 'exact' parameter was true and a query of the pointer-map
    ** shows that the page 'nearby' is somewhere on the free-list, then
    ** the entire-list will be searched for that page.
    */
#ifndef SQLITE_OMIT_AUTOVACUUM
    if( exact && nearby<=pagerPagecount(pBt->pPager) ){
      u8 eType;
      assert( nearby>0 );
      assert( pBt->autoVacuum );
      rc = ptrmapGet(pBt, nearby, &eType, 0);
      if( rc ) return rc;
      if( eType==PTRMAP_FREEPAGE ){
        searchList = 1;
................................................................................
        }else{
          closest = 0;
        }

        iPage = get4byte(&aData[8+closest*4]);
        if( !searchList || iPage==nearby ){
          *pPgno = iPage;
          int nPage;
          nPage = pagerPagecount(pBt->pPager);
          if( *pPgno>nPage ){
            /* Free page off the end of the file */
            rc = SQLITE_CORRUPT_BKPT;
            goto end_allocate_page;
          }
          TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
                 ": %d more free pages\n",
                 *pPgno, closest+1, k, pTrunk->pgno, n-1));
................................................................................
      }
      releasePage(pPrevTrunk);
      pPrevTrunk = 0;
    }while( searchList );
  }else{
    /* There are no pages on the freelist, so create a new page at the
    ** end of the file */
    int nPage = pagerPagecount(pBt->pPager);
    *pPgno = nPage + 1;

#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pBt->nTrunc ){
      /* An incr-vacuum has already run within this transaction. So the
      ** page to allocate is not from the physical end of the file, but
      ** at pBt->nTrunc. 
      */
................................................................................
  }
  ovflPgno = get4byte(&pCell[info.iOverflow]);
  ovflPageSize = pBt->usableSize - 4;
  nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
  assert( ovflPgno==0 || nOvfl>0 );
  while( nOvfl-- ){
    MemPage *pOvfl;
    if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt->pPager) ){
      return SQLITE_CORRUPT_BKPT;
    }

    rc = getOverflowPage(pBt, ovflPgno, &pOvfl, (nOvfl==0)?0:&ovflPgno);
    if( rc ) return rc;
    rc = freePage(pOvfl);
    sqlite3PagerUnref(pOvfl->pDbPage);
................................................................................
    ** information currently contained in the child.  If this is the 
    ** case, then do not do the transfer.  Leave page 1 empty except
    ** for the right-pointer to the child page.  The child page becomes
    ** the virtual root of the tree.
    */
    pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    assert( pgnoChild>0 );
    assert( pgnoChild<=pagerPagecount(pPage->pBt->pPager) );
    rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0);
    if( rc ) goto end_shallow_balance;
    if( pPage->pgno==1 ){
      rc = sqlite3BtreeInitPage(pChild, pPage);
      if( rc ) goto end_shallow_balance;
      assert( pChild->nOverflow==0 );
      if( pChild->nFree>=100 ){
................................................................................
){
  MemPage *pPage = 0;
  int rc;
  unsigned char *pCell;
  int i;

  assert( sqlite3_mutex_held(pBt->mutex) );
  if( pgno>pagerPagecount(pBt->pPager) ){
    return SQLITE_CORRUPT_BKPT;
  }

  rc = getAndInitPage(pBt, pgno, &pPage, pParent);
  if( rc ) goto cleardatabasepage_out;
  for(i=0; i<pPage->nCell; i++){
    pCell = findCell(pPage, i);
................................................................................
  nRef = sqlite3PagerRefcount(pBt->pPager);
  if( lockBtreeWithRetry(p)!=SQLITE_OK ){
    sqlite3BtreeLeave(p);
    return sqlite3StrDup("Unable to acquire a read lock on the database");
  }
  sCheck.pBt = pBt;
  sCheck.pPager = pBt->pPager;
  sCheck.nPage = pagerPagecount(sCheck.pPager);
  sCheck.mxErr = mxErr;
  sCheck.nErr = 0;
  *pnErr = 0;
#ifndef SQLITE_OMIT_AUTOVACUUM
  if( pBt->nTrunc!=0 ){
    sCheck.nPage = pBt->nTrunc;
  }
................................................................................
  if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){
    return SQLITE_ERROR;
  }
  if( pBtTo->pCursor ){
    return SQLITE_BUSY;
  }

  nToPage = pagerPagecount(pBtTo->pPager);
  nFromPage = pagerPagecount(pBtFrom->pPager);
  iSkip = PENDING_BYTE_PAGE(pBtTo);

  /* Variable nNewPage is the number of pages required to store the
  ** contents of pFrom using the current page-size of pTo.
  */
  nNewPage = ((i64)nFromPage * (i64)nFromPageSize + (i64)nToPageSize - 1) / 
      (i64)nToPageSize;

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
....
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
....
2551
2552
2553
2554
2555
2556
2557



2558
2559
2560
2561
2562
2563
2564
2565
....
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
....
3144
3145
3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
....
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
....
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
....
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
....
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
....
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.455 2008/06/07 05:19:38 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
................................................................................
**
** Regardless of mxPage, return the current maximum page count.
*/
int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
  if( mxPage>0 ){
    pPager->mxPgno = mxPage;
  }
  sqlite3PagerPagecount(pPager);
  return pPager->mxPgno;
}

/*
** The following set of routines are used to disable the simulated
** I/O error mechanism.  These routines are used to avoid simulated
** errors in places where we do not care about errors.
................................................................................
** pPager. 
**
** If the PENDING_BYTE lies on the page directly after the end of the
** file, then consider this page part of the file too. For example, if
** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the
** file is 4096 bytes, 5 is returned instead of 4.
*/
int sqlite3PagerPagecount(Pager *pPager){
  i64 n = 0;
  int rc;
  assert( pPager!=0 );
  if( pPager->errCode ){
    return -1;
  }
  if( pPager->dbSize>=0 ){
    n = pPager->dbSize;
  } else {
    assert(pPager->fd->pMethods||pPager->tempFile);
    if( (pPager->fd->pMethods)
     && (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
      pPager->nRef++;
      pager_error(pPager, rc);
      pPager->nRef--;
      return -1;
    }
    if( n>0 && n<pPager->pageSize ){
      n = 1;
    }else{
      n /= pPager->pageSize;
    }
    if( pPager->state!=PAGER_UNLOCK ){
................................................................................
  }
  if( n==(PENDING_BYTE/pPager->pageSize) ){
    n++;
  }
  if( n>pPager->mxPgno ){
    pPager->mxPgno = n;
  }



  return n;
}


#ifndef SQLITE_OMIT_MEMORYDB
/*
** Clear a PgHistory block
*/
................................................................................

/*
** Truncate the file to the number of pages specified.
*/
int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
  int rc;
  assert( pPager->state>=PAGER_SHARED || MEMDB );
  sqlite3PagerPagecount(pPager);
  if( pPager->errCode ){
    rc = pPager->errCode;
    return rc;
  }
  if( nPage>=(unsigned)pPager->dbSize ){
    return SQLITE_OK;
  }
................................................................................

    rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
    if( rc==SQLITE_OK && exists ){
      rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
    }

    if( rc==SQLITE_OK && exists && !locked ){

      int nPage = sqlite3PagerPagecount(pPager);
      if( nPage==0 ){
        sqlite3OsDelete(pVfs, pPager->zJournal, 0);
        exists = 0;
      }else if( nPage<0 ){
        rc = SQLITE_IOERR;
      }
    }

    res = (rc!=SQLITE_OK ? -1 : (exists && !locked));
  }

  return res;
................................................................................
        ** a codec is in use.
        ** 
        ** There is a vanishingly small chance that a change will not be 
        ** detected.  The chance of an undetected change is so small that
        ** it can be neglected.
        */
        char dbFileVers[sizeof(pPager->dbFileVers)];
        sqlite3PagerPagecount(pPager);

        if( pPager->errCode ){
          rc = pPager->errCode;
          goto failed;
        }

        if( pPager->dbSize>0 ){
................................................................................
    makeClean(pPg);
    pPg->nRef = 1;

    pPager->nRef++;
    if( pPager->nExtra>0 ){
      memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
    }
    nMax = sqlite3PagerPagecount(pPager);
    if( pPager->errCode ){
      rc = pPager->errCode;
      sqlite3PagerUnref(pPg);
      return rc;
    }

    /* Populate the page with data, either by reading from the database
    ** file, or by setting the entire page to zero.
    */
................................................................................
  int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE);

  int rc;
  assert( !MEMDB );
  assert( pPager->state>=PAGER_RESERVED );
  assert( pPager->useJournal );
  assert( pPager->pInJournal==0 );
  sqlite3PagerPagecount(pPager);
  pagerLeave(pPager);
  pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
  pagerEnter(pPager);
  if( pPager->pInJournal==0 ){
    rc = SQLITE_NOMEM;
    goto failed_to_open_journal;
  }
................................................................................
    ** by this connection. Instead of deleting the journal file it was 
    ** kept open and either was truncated to 0 bytes or its header was
    ** overwritten with zeros.
    */
    assert( pPager->nRec==0 );
    assert( pPager->origDbSize==0 );
    assert( pPager->pInJournal==0 );
    sqlite3PagerPagecount(pPager);
    pagerLeave(pPager);
    pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
    pagerEnter(pPager);
    if( !pPager->pInJournal ){
      rc = SQLITE_NOMEM;
    }else{
      pPager->origDbSize = pPager->dbSize;
................................................................................

    /* This trick assumes that both the page-size and sector-size are
    ** an integer power of 2. It sets variable pg1 to the identifier
    ** of the first page of the sector pPg is located on.
    */
    pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;

    nPageCount = sqlite3PagerPagecount(pPager);
    if( pPg->pgno>nPageCount ){
      nPage = (pPg->pgno - pg1)+1;
    }else if( (pg1+nPagePerSector-1)>nPageCount ){
      nPage = nPageCount+1-pg1;
    }else{
      nPage = nPagePerSector;
    }







|







 







|







 







|




|










|







 







>
>
>
|







 







|







 







>
|
|


<
<







 







|







 







|
|
<







 







|







 







|







 







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
....
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
....
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
....
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
....
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158


3159
3160
3161
3162
3163
3164
3165
....
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
....
3787
3788
3789
3790
3791
3792
3793
3794
3795

3796
3797
3798
3799
3800
3801
3802
....
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
....
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
....
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.456 2008/06/07 08:58:22 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
................................................................................
**
** Regardless of mxPage, return the current maximum page count.
*/
int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
  if( mxPage>0 ){
    pPager->mxPgno = mxPage;
  }
  sqlite3PagerPagecount(pPager, 0);
  return pPager->mxPgno;
}

/*
** The following set of routines are used to disable the simulated
** I/O error mechanism.  These routines are used to avoid simulated
** errors in places where we do not care about errors.
................................................................................
** pPager. 
**
** If the PENDING_BYTE lies on the page directly after the end of the
** file, then consider this page part of the file too. For example, if
** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the
** file is 4096 bytes, 5 is returned instead of 4.
*/
int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
  i64 n = 0;
  int rc;
  assert( pPager!=0 );
  if( pPager->errCode ){
    return pPager->errCode;
  }
  if( pPager->dbSize>=0 ){
    n = pPager->dbSize;
  } else {
    assert(pPager->fd->pMethods||pPager->tempFile);
    if( (pPager->fd->pMethods)
     && (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
      pPager->nRef++;
      pager_error(pPager, rc);
      pPager->nRef--;
      return rc;
    }
    if( n>0 && n<pPager->pageSize ){
      n = 1;
    }else{
      n /= pPager->pageSize;
    }
    if( pPager->state!=PAGER_UNLOCK ){
................................................................................
  }
  if( n==(PENDING_BYTE/pPager->pageSize) ){
    n++;
  }
  if( n>pPager->mxPgno ){
    pPager->mxPgno = n;
  }
  if( pnPage ){
    *pnPage = n;
  }
  return SQLITE_OK;
}


#ifndef SQLITE_OMIT_MEMORYDB
/*
** Clear a PgHistory block
*/
................................................................................

/*
** Truncate the file to the number of pages specified.
*/
int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
  int rc;
  assert( pPager->state>=PAGER_SHARED || MEMDB );
  sqlite3PagerPagecount(pPager, 0);
  if( pPager->errCode ){
    rc = pPager->errCode;
    return rc;
  }
  if( nPage>=(unsigned)pPager->dbSize ){
    return SQLITE_OK;
  }
................................................................................

    rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
    if( rc==SQLITE_OK && exists ){
      rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
    }

    if( rc==SQLITE_OK && exists && !locked ){
      int nPage;
      rc = sqlite3PagerPagecount(pPager, &nPage);
      if( rc==SQLITE_OK && nPage==0 ){
        sqlite3OsDelete(pVfs, pPager->zJournal, 0);
        exists = 0;


      }
    }

    res = (rc!=SQLITE_OK ? -1 : (exists && !locked));
  }

  return res;
................................................................................
        ** a codec is in use.
        ** 
        ** There is a vanishingly small chance that a change will not be 
        ** detected.  The chance of an undetected change is so small that
        ** it can be neglected.
        */
        char dbFileVers[sizeof(pPager->dbFileVers)];
        sqlite3PagerPagecount(pPager, 0);

        if( pPager->errCode ){
          rc = pPager->errCode;
          goto failed;
        }

        if( pPager->dbSize>0 ){
................................................................................
    makeClean(pPg);
    pPg->nRef = 1;

    pPager->nRef++;
    if( pPager->nExtra>0 ){
      memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
    }
    rc = sqlite3PagerPagecount(pPager, &nMax);
    if( rc!=SQLITE_OK ){

      sqlite3PagerUnref(pPg);
      return rc;
    }

    /* Populate the page with data, either by reading from the database
    ** file, or by setting the entire page to zero.
    */
................................................................................
  int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE);

  int rc;
  assert( !MEMDB );
  assert( pPager->state>=PAGER_RESERVED );
  assert( pPager->useJournal );
  assert( pPager->pInJournal==0 );
  sqlite3PagerPagecount(pPager, 0);
  pagerLeave(pPager);
  pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
  pagerEnter(pPager);
  if( pPager->pInJournal==0 ){
    rc = SQLITE_NOMEM;
    goto failed_to_open_journal;
  }
................................................................................
    ** by this connection. Instead of deleting the journal file it was 
    ** kept open and either was truncated to 0 bytes or its header was
    ** overwritten with zeros.
    */
    assert( pPager->nRec==0 );
    assert( pPager->origDbSize==0 );
    assert( pPager->pInJournal==0 );
    sqlite3PagerPagecount(pPager, 0);
    pagerLeave(pPager);
    pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
    pagerEnter(pPager);
    if( !pPager->pInJournal ){
      rc = SQLITE_NOMEM;
    }else{
      pPager->origDbSize = pPager->dbSize;
................................................................................

    /* This trick assumes that both the page-size and sector-size are
    ** an integer power of 2. It sets variable pg1 to the identifier
    ** of the first page of the sector pPg is located on.
    */
    pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;

    sqlite3PagerPagecount(pPager, (int *)&nPageCount);
    if( pPg->pgno>nPageCount ){
      nPage = (pPg->pgno - pg1)+1;
    }else if( (pg1+nPagePerSector-1)>nPageCount ){
      nPage = nPageCount+1-pg1;
    }else{
      nPage = nPagePerSector;
    }

Changes to src/pager.h.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem.  The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.75 2008/06/06 11:11:26 danielk1977 Exp $
*/

#ifndef _PAGER_H_
#define _PAGER_H_

/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
................................................................................
int sqlite3PagerClose(Pager *pPager);
int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
int sqlite3PagerRef(DbPage*);
int sqlite3PagerUnref(DbPage*);
int sqlite3PagerWrite(DbPage*);
int sqlite3PagerPagecount(Pager*);
int sqlite3PagerTruncate(Pager*,Pgno);
int sqlite3PagerBegin(DbPage*, int exFlag);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno, int);
int sqlite3PagerCommitPhaseTwo(Pager*);
int sqlite3PagerRollback(Pager*);
int sqlite3PagerIsreadonly(Pager*);
int sqlite3PagerStmtBegin(Pager*);







|







 







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem.  The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.76 2008/06/07 08:58:22 danielk1977 Exp $
*/

#ifndef _PAGER_H_
#define _PAGER_H_

/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
................................................................................
int sqlite3PagerClose(Pager *pPager);
int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
int sqlite3PagerRef(DbPage*);
int sqlite3PagerUnref(DbPage*);
int sqlite3PagerWrite(DbPage*);
int sqlite3PagerPagecount(Pager*, int*);
int sqlite3PagerTruncate(Pager*,Pgno);
int sqlite3PagerBegin(DbPage*, int exFlag);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno, int);
int sqlite3PagerCommitPhaseTwo(Pager*);
int sqlite3PagerRollback(Pager*);
int sqlite3PagerIsreadonly(Pager*);
int sqlite3PagerStmtBegin(Pager*);

Changes to src/test2.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
301
302
303
304
305
306
307

308
309
310
311
312
313
314

315
316
317
318
319
320
321
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the pager.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test2.c,v 1.57 2008/03/21 16:45:48 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

................................................................................
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  const char **argv      /* Text of each argument */
){
  Pager *pPager;
  char zBuf[100];

  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TextToPtr(argv[1]);
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3PagerPagecount(pPager));

  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

/*
** Usage:   page_get ID PGNO
**







|







 







>






|
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the pager.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test2.c,v 1.58 2008/06/07 08:58:22 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

................................................................................
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  const char **argv      /* Text of each argument */
){
  Pager *pPager;
  char zBuf[100];
  int nPage;
  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID\"", 0);
    return TCL_ERROR;
  }
  pPager = sqlite3TextToPtr(argv[1]);
  sqlite3PagerPagecount(pPager, &nPage);
  sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nPage);
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

/*
** Usage:   page_get ID PGNO
**

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
485
486
487
488
489
490
491
492









493
494
495
496
497
498
499
500
....
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
....
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.747 2008/06/06 15:04:37 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
   if( db->u1.isInterrupted ) goto abort_due_to_interrupt;

#ifdef SQLITE_DEBUG
static int fileExists(sqlite3 *db, const char *zFile){
  int res;









  int rc = sqlite3OsAccess(db->pVfs, zFile, SQLITE_ACCESS_EXISTS, &res);
  return (res && rc==SQLITE_OK);
}
#endif

/*
** Execute as much of a VDBE program as we can then return.
**
................................................................................
      p->pc = pc;
      p->rc = rc = SQLITE_BUSY;
      goto vdbe_return;
    }
    case SQLITE_OK: {
      int flags = sqlite3BtreeFlags(pCur->pCursor);
      /* Sanity checking.  Only the lower four bits of the flags byte should
      ** be used.  Bit 3 (mask 0x08) is unpreditable.  The lower 3 bits
      ** (mask 0x07) should be either 5 (intkey+leafdata for tables) or
      ** 2 (zerodata for indices).  If these conditions are not met it can
      ** only mean that we are dealing with a corrupt database file
      */
      if( (flags & 0xf0)!=0 || ((flags & 0x07)!=5 && (flags & 0x07)!=2) ){
        rc = SQLITE_CORRUPT_BKPT;
        goto abort_due_to_error;
................................................................................
** Write the current number of pages in database P1 to memory cell P2.
*/
case OP_Pagecount: {            /* out2-prerelease */
  int p1 = pOp->p1; 
  int nPage;
  Pager *pPager = sqlite3BtreePager(db->aDb[p1].pBt);

  nPage = sqlite3PagerPagecount(pPager);
  if( nPage<0 ){
    rc = SQLITE_IOERR;
  }else{
    pOut->flags = MEM_Int;
    pOut->u.i = nPage;
  }
  break;
}
#endif








|







 







|
>
>
>
>
>
>
>
>
>
|







 







|







 







|
<
|
<







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
....
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
....
4822
4823
4824
4825
4826
4827
4828
4829

4830

4831
4832
4833
4834
4835
4836
4837
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.748 2008/06/07 08:58:22 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
   if( db->u1.isInterrupted ) goto abort_due_to_interrupt;

#ifdef SQLITE_DEBUG
static int fileExists(sqlite3 *db, const char *zFile){
  int res = 0;
  int rc = SQLITE_OK;
#ifdef SQLITE_TEST
  /* If we are currently testing IO errors, then do not call OsAccess() to
  ** test for the presence of zFile. This is because any IO error that
  ** occurs here will not be reported, causing the test to fail.
  */
  extern int sqlite3_io_error_pending;
  if( sqlite3_io_error_pending<=0 )
#endif
    rc = sqlite3OsAccess(db->pVfs, zFile, SQLITE_ACCESS_EXISTS, &res);
  return (res && rc==SQLITE_OK);
}
#endif

/*
** Execute as much of a VDBE program as we can then return.
**
................................................................................
      p->pc = pc;
      p->rc = rc = SQLITE_BUSY;
      goto vdbe_return;
    }
    case SQLITE_OK: {
      int flags = sqlite3BtreeFlags(pCur->pCursor);
      /* Sanity checking.  Only the lower four bits of the flags byte should
      ** be used.  Bit 3 (mask 0x08) is unpredictable.  The lower 3 bits
      ** (mask 0x07) should be either 5 (intkey+leafdata for tables) or
      ** 2 (zerodata for indices).  If these conditions are not met it can
      ** only mean that we are dealing with a corrupt database file
      */
      if( (flags & 0xf0)!=0 || ((flags & 0x07)!=5 && (flags & 0x07)!=2) ){
        rc = SQLITE_CORRUPT_BKPT;
        goto abort_due_to_error;
................................................................................
** Write the current number of pages in database P1 to memory cell P2.
*/
case OP_Pagecount: {            /* out2-prerelease */
  int p1 = pOp->p1; 
  int nPage;
  Pager *pPager = sqlite3BtreePager(db->aDb[p1].pBt);

  rc = sqlite3PagerPagecount(pPager, &nPage);

  if( rc==SQLITE_OK ){

    pOut->flags = MEM_Int;
    pOut->u.i = nPage;
  }
  break;
}
#endif

Changes to test/ioerr.test.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of I/O errors
# such as writes failing because the disk is full.
# 
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
# $Id: ioerr.test,v 1.36 2008/06/05 11:39:12 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl


# If SQLITE_DEFAULT_AUTOVACUUM is set to true, then a simulated IO error
# on the 8th IO operation in the SQL script below doesn't report an error.
#
# This is because the 8th IO call attempts to read page 2 of the database
# file when the file on disk is only 1 page. The pager layer detects that
# this has happened and suppresses the error returned by the OS layer.







|



<







11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of I/O errors
# such as writes failing because the disk is full.
# 
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
# $Id: ioerr.test,v 1.37 2008/06/07 08:58:23 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl


# If SQLITE_DEFAULT_AUTOVACUUM is set to true, then a simulated IO error
# on the 8th IO operation in the SQL script below doesn't report an error.
#
# This is because the 8th IO call attempts to read page 2 of the database
# file when the file on disk is only 1 page. The pager layer detects that
# this has happened and suppresses the error returned by the OS layer.