/ Check-in [0092b36c]
Login

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

Overview
Comment:Pull the experimental file-size-in-header changes into the trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:0092b36c7bbd04bf3826de7805e8a14739390f31
User & Date: drh 2010-03-29 21:22:01
Context
2010-03-30
11:57
Change an #if into an #ifdef. check-in: 371bab5d user: drh tags: trunk
2010-03-29
21:22
Pull the experimental file-size-in-header changes into the trunk. check-in: 0092b36c user: drh tags: trunk
21:13
The btree layer now tracks when a database is empty at the start of a transaction and rolls back to that state. Closed-Leaf check-in: 01ef6c19 user: drh tags: experimental
2010-03-27
09:44
Increase the estimated cost of using a virtual table as the outer loop of a join when there exists an ORDER BY clause that is not satisfied by the virtual table. Fix for [775b39dd3c]. check-in: 9e075e70 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
....
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
....
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
....
2329
2330
2331
2332
2333
2334
2335

2336
2337
2338
2339
2340
2341
2342
....
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
....
2397
2398
2399
2400
2401
2402
2403


2404
2405
2406
2407
2408
2409
2410
....
2486
2487
2488
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499
....
2765
2766
2767
2768
2769
2770
2771

2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
....
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865

2866
2867
2868
2869
2870
2871
2872
....
2882
2883
2884
2885
2886
2887
2888




2889
2890
2891
2892
2893
2894
2895
....
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947

2948

2949
2950
2951
2952
2953
2954
2955
....
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
....
3264
3265
3266
3267
3268
3269
3270

3271

3272
3273
3274
3275
3276
3277
3278
....
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838

4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861


4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
** optimization 2 above is omitted if the corresponding bit is already
** set in BtShared.pHasContent. The contents of the bitvec are cleared
** at the end of every transaction.
*/
static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
  int rc = SQLITE_OK;
  if( !pBt->pHasContent ){
    int nPage = 100;
    sqlite3PagerPagecount(pBt->pPager, &nPage);
    /* If sqlite3PagerPagecount() fails there is no harm because the
    ** nPage variable is unchanged from its default value of 100 */
    pBt->pHasContent = sqlite3BitvecCreate((u32)nPage);
    if( !pBt->pHasContent ){
      rc = SQLITE_NOMEM;
    }
  }
  if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
    rc = sqlite3BitvecSet(pBt->pHasContent, pgno);
  }
................................................................................
}

/*
** Return the size of the database file in pages. If there is any kind of
** error, return ((unsigned int)-1).
*/
static Pgno pagerPagecount(BtShared *pBt){
  int nPage = -1;
  int rc;
  assert( pBt->pPage1 );
  rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
  assert( rc==SQLITE_OK || nPage==-1 );
  return (Pgno)nPage;
}

/*
** Get a page from the pager and initialize it.  This routine is just a
** convenience wrapper around separate calls to btreeGetPage() and 
** btreeInitPage().
**
................................................................................
  if( rc!=SQLITE_OK ) return rc;
  rc = btreeGetPage(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 ){
................................................................................
  */
  pBt->maxLocal = (pBt->usableSize-12)*64/255 - 23;
  pBt->minLocal = (pBt->usableSize-12)*32/255 - 23;
  pBt->maxLeaf = pBt->usableSize - 35;
  pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23;
  assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
  pBt->pPage1 = pPage1;

  return SQLITE_OK;

page1_init_failed:
  releasePage(pPage1);
  pBt->pPage1 = 0;
  return rc;
}
................................................................................
** into a new empty database by initializing the first page of
** the database.
*/
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));
................................................................................
  pBt->pageSizeFixed = 1;
#ifndef SQLITE_OMIT_AUTOVACUUM
  assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
  assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
  put4byte(&data[36 + 4*4], pBt->autoVacuum);
  put4byte(&data[36 + 7*4], pBt->incrVacuum);
#endif


  return SQLITE_OK;
}

/*
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read-
** transaction.  If the second argument is 2 or more and exclusive
................................................................................

  /* Any read-only or read-write transaction implies a read-lock on 
  ** page 1. So if some other shared-cache client already has a write-lock 
  ** on page 1, the transaction cannot be opened. */
  rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
  if( SQLITE_OK!=rc ) goto trans_begun;


  do {
    /* Call lockBtree() until either pBt->pPage1 is populated or
    ** lockBtree() returns something other than SQLITE_OK. lockBtree()
    ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
    ** reading page 1 it discovers that the page-size of the database 
    ** file is not pBt->pageSize. In this case lockBtree() will update
    ** pBt->pageSize to the page-size of the file on disk.
................................................................................
** process is complete.  If nFin is zero, it is assumed that
** incrVacuumStep() will be called a finite amount of times
** which may or may not empty the freelist.  A full autovacuum
** has nFin>0.  A "PRAGMA incremental_vacuum" has nFin==0.
*/
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
  Pgno nFreeList;           /* Number of pages still on the free-list */


  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( iLastPg>nFin );

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

    nFreeList = get4byte(&pBt->pPage1->aData[36]);
    if( nFreeList==0 ){
      return SQLITE_DONE;
    }
................................................................................
  }

  if( nFin==0 ){
    iLastPg--;
    while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
      if( PTRMAP_ISPAGE(pBt, iLastPg) ){
        MemPage *pPg;
        int rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        rc = sqlite3PagerWrite(pPg->pDbPage);
        releasePage(pPg);
        if( rc!=SQLITE_OK ){
          return rc;
        }
      }
      iLastPg--;
    }
    sqlite3PagerTruncateImage(pBt->pPager, iLastPg);

  }
  return SQLITE_OK;
}

/*
** A write-transaction must be opened before calling this function.
** It performs a single unit of work towards an incremental vacuum.
................................................................................
  sqlite3BtreeEnter(p);
  assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE );
  if( !pBt->autoVacuum ){
    rc = SQLITE_DONE;
  }else{
    invalidateAllOverflowCache(pBt);
    rc = incrVacuumStep(pBt, 0, pagerPagecount(pBt));




  }
  sqlite3BtreeLeave(p);
  return rc;
}

/*
** This routine is called prior to sqlite3PagerCommit when a transaction
................................................................................
    }
    if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;

    for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
      rc = incrVacuumStep(pBt, nFin, iFree);
    }
    if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
      rc = SQLITE_OK;
      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
      put4byte(&pBt->pPage1->aData[32], 0);
      put4byte(&pBt->pPage1->aData[36], 0);

      sqlite3PagerTruncateImage(pBt->pPager, nFin);

    }
    if( rc!=SQLITE_OK ){
      sqlite3PagerRollback(pPager);
    }
  }

  assert( nRef==sqlite3PagerRefcount(pPager) );
................................................................................
  int rc;
  BtShared *pBt = p->pBt;
  sqlite3BtreeEnter(p);
  assert( p->inTrans==TRANS_WRITE );
  assert( pBt->readOnly==0 );
  assert( iStatement>0 );
  assert( iStatement>p->db->nSavepoint );
  if( NEVER(p->inTrans!=TRANS_WRITE || pBt->readOnly) ){
    rc = SQLITE_INTERNAL;
  }else{
    assert( pBt->inTransaction==TRANS_WRITE );
    /* At the pager level, a statement transaction is a savepoint with
    ** an index greater than all savepoints created explicitly using
    ** SQL statements. It is illegal to open, release or rollback any
    ** such savepoints while the statement transaction savepoint is active.
    */
    rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);
  }
  sqlite3BtreeLeave(p);
  return rc;
}

/*
** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
** or SAVEPOINT_RELEASE. This function either releases or rolls back the
................................................................................
  if( p && p->inTrans==TRANS_WRITE ){
    BtShared *pBt = p->pBt;
    assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
    assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
    sqlite3BtreeEnter(p);
    rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
    if( rc==SQLITE_OK ){

      rc = newDatabase(pBt);

    }
    sqlite3BtreeLeave(p);
  }
  return rc;
}

/*
................................................................................
      }
      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);
    *pPgno = nPage + 1;


    if( *pPgno==PENDING_BYTE_PAGE(pBt) ){
      (*pPgno)++;
    }

#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){
      /* If *pPgno refers to a pointer-map page, allocate two new pages
      ** at the end of the file instead of one. The first allocated page
      ** becomes a new pointer-map page, the second is used by the caller.
      */
      MemPage *pPg = 0;
      TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno));
      assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
      rc = btreeGetPage(pBt, *pPgno, &pPg, 0);
      if( rc==SQLITE_OK ){
        rc = sqlite3PagerWrite(pPg->pDbPage);
        releasePage(pPg);
      }
      if( rc ) return rc;
      (*pPgno)++;
      if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ (*pPgno)++; }
    }
#endif



    assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
    rc = btreeGetPage(pBt, *pPgno, ppPage, 0);
    if( rc ) return rc;
    rc = sqlite3PagerWrite((*ppPage)->pDbPage);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
    }
    TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
  }







|
<
<
<
|







 







|
<
<
<
<
|







 







|
|







 







>







 







<


<
|
|







 







>
>







 







>







 







>





<







 







|












>







 







>
>
>
>







 







<



>

>







 







<
<
<
|
|
|
|
|
|
|
<







 







>

>







 







|
|
<
>
|
<
|
<

|





|
|
|





|
|


>
>


|







512
513
514
515
516
517
518
519



520
521
522
523
524
525
526
527
....
1557
1558
1559
1560
1561
1562
1563
1564




1565
1566
1567
1568
1569
1570
1571
1572
....
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
....
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
....
2360
2361
2362
2363
2364
2365
2366

2367
2368

2369
2370
2371
2372
2373
2374
2375
2376
2377
....
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
....
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
....
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772

2773
2774
2775
2776
2777
2778
2779
....
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
....
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
....
2937
2938
2939
2940
2941
2942
2943

2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
....
3229
3230
3231
3232
3233
3234
3235



3236
3237
3238
3239
3240
3241
3242

3243
3244
3245
3246
3247
3248
3249
....
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
....
4828
4829
4830
4831
4832
4833
4834
4835
4836

4837
4838

4839

4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
** optimization 2 above is omitted if the corresponding bit is already
** set in BtShared.pHasContent. The contents of the bitvec are cleared
** at the end of every transaction.
*/
static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
  int rc = SQLITE_OK;
  if( !pBt->pHasContent ){
    assert( pgno<=pBt->nPage );



    pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
    if( !pBt->pHasContent ){
      rc = SQLITE_NOMEM;
    }
  }
  if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
    rc = sqlite3BitvecSet(pBt->pHasContent, pgno);
  }
................................................................................
}

/*
** Return the size of the database file in pages. If there is any kind of
** error, return ((unsigned int)-1).
*/
static Pgno pagerPagecount(BtShared *pBt){
  int nPage = (int)pBt->nPage;




  return nPage;
}

/*
** Get a page from the pager and initialize it.  This routine is just a
** convenience wrapper around separate calls to btreeGetPage() and 
** btreeInitPage().
**
................................................................................
  if( rc!=SQLITE_OK ) return rc;
  rc = btreeGetPage(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. 
  */
  nPage = get4byte(28+(u8*)pPage1->aData);
  if( nPage==0 && (rc = sqlite3PagerPagecount(pBt->pPager, &nPage))!=0 ){
    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 ){
................................................................................
  */
  pBt->maxLocal = (pBt->usableSize-12)*64/255 - 23;
  pBt->minLocal = (pBt->usableSize-12)*32/255 - 23;
  pBt->maxLeaf = pBt->usableSize - 35;
  pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23;
  assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
  pBt->pPage1 = pPage1;
  pBt->nPage = nPage;
  return SQLITE_OK;

page1_init_failed:
  releasePage(pPage1);
  pBt->pPage1 = 0;
  return rc;
}
................................................................................
** into a new empty database by initializing the first page of
** the database.
*/
static int newDatabase(BtShared *pBt){
  MemPage *pP1;
  unsigned char *data;
  int rc;


  assert( sqlite3_mutex_held(pBt->mutex) );

  if( pBt->nPage>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));
................................................................................
  pBt->pageSizeFixed = 1;
#ifndef SQLITE_OMIT_AUTOVACUUM
  assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
  assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
  put4byte(&data[36 + 4*4], pBt->autoVacuum);
  put4byte(&data[36 + 7*4], pBt->incrVacuum);
#endif
  pBt->nPage = 1;
  data[31] = 1;
  return SQLITE_OK;
}

/*
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read-
** transaction.  If the second argument is 2 or more and exclusive
................................................................................

  /* Any read-only or read-write transaction implies a read-lock on 
  ** page 1. So if some other shared-cache client already has a write-lock 
  ** on page 1, the transaction cannot be opened. */
  rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
  if( SQLITE_OK!=rc ) goto trans_begun;

  pBt->initiallyEmpty = pBt->nPage==0;
  do {
    /* Call lockBtree() until either pBt->pPage1 is populated or
    ** lockBtree() returns something other than SQLITE_OK. lockBtree()
    ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
    ** reading page 1 it discovers that the page-size of the database 
    ** file is not pBt->pageSize. In this case lockBtree() will update
    ** pBt->pageSize to the page-size of the file on disk.
................................................................................
** process is complete.  If nFin is zero, it is assumed that
** incrVacuumStep() will be called a finite amount of times
** which may or may not empty the freelist.  A full autovacuum
** has nFin>0.  A "PRAGMA incremental_vacuum" has nFin==0.
*/
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
  Pgno nFreeList;           /* Number of pages still on the free-list */
  int rc;

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( iLastPg>nFin );

  if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){

    u8 eType;
    Pgno iPtrPage;

    nFreeList = get4byte(&pBt->pPage1->aData[36]);
    if( nFreeList==0 ){
      return SQLITE_DONE;
    }
................................................................................
  }

  if( nFin==0 ){
    iLastPg--;
    while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
      if( PTRMAP_ISPAGE(pBt, iLastPg) ){
        MemPage *pPg;
        rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        rc = sqlite3PagerWrite(pPg->pDbPage);
        releasePage(pPg);
        if( rc!=SQLITE_OK ){
          return rc;
        }
      }
      iLastPg--;
    }
    sqlite3PagerTruncateImage(pBt->pPager, iLastPg);
    pBt->nPage = iLastPg;
  }
  return SQLITE_OK;
}

/*
** A write-transaction must be opened before calling this function.
** It performs a single unit of work towards an incremental vacuum.
................................................................................
  sqlite3BtreeEnter(p);
  assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE );
  if( !pBt->autoVacuum ){
    rc = SQLITE_DONE;
  }else{
    invalidateAllOverflowCache(pBt);
    rc = incrVacuumStep(pBt, 0, pagerPagecount(pBt));
    if( rc==SQLITE_OK ){
      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
      put4byte(&pBt->pPage1->aData[28], pBt->nPage);
    }
  }
  sqlite3BtreeLeave(p);
  return rc;
}

/*
** This routine is called prior to sqlite3PagerCommit when a transaction
................................................................................
    }
    if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;

    for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
      rc = incrVacuumStep(pBt, nFin, iFree);
    }
    if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){

      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
      put4byte(&pBt->pPage1->aData[32], 0);
      put4byte(&pBt->pPage1->aData[36], 0);
      put4byte(&pBt->pPage1->aData[28], nFin);
      sqlite3PagerTruncateImage(pBt->pPager, nFin);
      pBt->nPage = nFin;
    }
    if( rc!=SQLITE_OK ){
      sqlite3PagerRollback(pPager);
    }
  }

  assert( nRef==sqlite3PagerRefcount(pPager) );
................................................................................
  int rc;
  BtShared *pBt = p->pBt;
  sqlite3BtreeEnter(p);
  assert( p->inTrans==TRANS_WRITE );
  assert( pBt->readOnly==0 );
  assert( iStatement>0 );
  assert( iStatement>p->db->nSavepoint );



  assert( pBt->inTransaction==TRANS_WRITE );
  /* At the pager level, a statement transaction is a savepoint with
  ** an index greater than all savepoints created explicitly using
  ** SQL statements. It is illegal to open, release or rollback any
  ** such savepoints while the statement transaction savepoint is active.
  */
  rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);

  sqlite3BtreeLeave(p);
  return rc;
}

/*
** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
** or SAVEPOINT_RELEASE. This function either releases or rolls back the
................................................................................
  if( p && p->inTrans==TRANS_WRITE ){
    BtShared *pBt = p->pBt;
    assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
    assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
    sqlite3BtreeEnter(p);
    rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
    if( rc==SQLITE_OK ){
      if( iSavepoint<0 && pBt->initiallyEmpty ) pBt->nPage = 0;
      rc = newDatabase(pBt);
      pBt->nPage = get4byte(28 + pBt->pPage1->aData);
    }
    sqlite3BtreeLeave(p);
  }
  return rc;
}

/*
................................................................................
      }
      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 */
    rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
    if( rc ) return rc;

    pBt->nPage++;
    if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;



#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){
      /* If *pPgno refers to a pointer-map page, allocate two new pages
      ** at the end of the file instead of one. The first allocated page
      ** becomes a new pointer-map page, the second is used by the caller.
      */
      MemPage *pPg = 0;
      TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
      assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
      rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1);
      if( rc==SQLITE_OK ){
        rc = sqlite3PagerWrite(pPg->pDbPage);
        releasePage(pPg);
      }
      if( rc ) return rc;
      pBt->nPage++;
      if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
    }
#endif
    put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
    *pPgno = pBt->nPage;

    assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
    rc = btreeGetPage(pBt, *pPgno, ppPage, 1);
    if( rc ) return rc;
    rc = sqlite3PagerWrite((*ppPage)->pDbPage);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
    }
    TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
  }

Changes to src/btreeInt.h.

404
405
406
407
408
409
410

411
412
413
414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
  Pager *pPager;        /* The page cache */
  sqlite3 *db;          /* Database connection currently using this Btree */
  BtCursor *pCursor;    /* A list of all open cursors */
  MemPage *pPage1;      /* First page of the database */
  u8 readOnly;          /* True if the underlying file is readonly */
  u8 pageSizeFixed;     /* True if the page size can no longer be changed */
  u8 secureDelete;      /* True if secure_delete is enabled */

#ifndef SQLITE_OMIT_AUTOVACUUM
  u8 autoVacuum;        /* True if auto-vacuum is enabled */
  u8 incrVacuum;        /* True if incr-vacuum is enabled */
#endif
  u16 pageSize;         /* Total number of bytes on a page */
  u16 usableSize;       /* Number of usable bytes on each page */
  u16 maxLocal;         /* Maximum local payload in non-LEAFDATA tables */
  u16 minLocal;         /* Minimum local payload in non-LEAFDATA tables */
  u16 maxLeaf;          /* Maximum local payload in a LEAFDATA table */
  u16 minLeaf;          /* Minimum local payload in a LEAFDATA table */
  u8 inTransaction;     /* Transaction state */
  int nTransaction;     /* Number of open transactions (read + write) */

  void *pSchema;        /* Pointer to space allocated by sqlite3BtreeSchema() */
  void (*xFreeSchema)(void*);  /* Destructor for BtShared.pSchema */
  sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
  Bitvec *pHasContent;  /* Set of pages moved to free-list this transaction */
#ifndef SQLITE_OMIT_SHARED_CACHE
  int nRef;             /* Number of references to this structure */
  BtShared *pNext;      /* Next on a list of sharable BtShared structs */







>












>







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
  Pager *pPager;        /* The page cache */
  sqlite3 *db;          /* Database connection currently using this Btree */
  BtCursor *pCursor;    /* A list of all open cursors */
  MemPage *pPage1;      /* First page of the database */
  u8 readOnly;          /* True if the underlying file is readonly */
  u8 pageSizeFixed;     /* True if the page size can no longer be changed */
  u8 secureDelete;      /* True if secure_delete is enabled */
  u8 initiallyEmpty;    /* Database is empty at start of transaction */
#ifndef SQLITE_OMIT_AUTOVACUUM
  u8 autoVacuum;        /* True if auto-vacuum is enabled */
  u8 incrVacuum;        /* True if incr-vacuum is enabled */
#endif
  u16 pageSize;         /* Total number of bytes on a page */
  u16 usableSize;       /* Number of usable bytes on each page */
  u16 maxLocal;         /* Maximum local payload in non-LEAFDATA tables */
  u16 minLocal;         /* Minimum local payload in non-LEAFDATA tables */
  u16 maxLeaf;          /* Maximum local payload in a LEAFDATA table */
  u16 minLeaf;          /* Minimum local payload in a LEAFDATA table */
  u8 inTransaction;     /* Transaction state */
  int nTransaction;     /* Number of open transactions (read + write) */
  u32 nPage;            /* Number of pages in the database */
  void *pSchema;        /* Pointer to space allocated by sqlite3BtreeSchema() */
  void (*xFreeSchema)(void*);  /* Destructor for BtShared.pSchema */
  sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
  Bitvec *pHasContent;  /* Set of pages moved to free-list this transaction */
#ifndef SQLITE_OMIT_SHARED_CACHE
  int nRef;             /* Number of references to this structure */
  BtShared *pNext;      /* Next on a list of sharable BtShared structs */

Changes to src/pager.c.

4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
....
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
....
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
....
4920
4921
4922
4923
4924
4925
4926



4927
4928
4929
4930
4931
4932
4933
  int rc = SQLITE_OK;

  /* This routine is not called unless a transaction has already been
  ** started.
  */
  assert( pPager->state>=PAGER_RESERVED );

  /* If an error has been previously detected, we should not be
  ** calling this routine.  Repeat the error for robustness.
  */
  if( NEVER(pPager->errCode) )  return pPager->errCode;

  /* Higher-level routines never call this function if database is not
  ** writable.  But check anyway, just for robustness. */
  if( NEVER(pPager->readOnly) ) return SQLITE_PERM;

  assert( !pPager->setMaster );

................................................................................

    if( rc==SQLITE_OK ){
      /* Increment the value just read and write it back to byte 24. */
      change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
      change_counter++;
      put32bits(((char*)pPgHdr->pData)+24, change_counter);

      /* Also store the current database size in bytes 28..31 */
      assert( pPager->dbSizeValid );
      put32bits(((char*)pPgHdr->pData)+28, pPager->dbSize);

      /* Also store the SQLite version number in bytes 96..99 */
      assert( pPager->dbSizeValid );
      put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER);

      /* If running in direct mode, write the contents of page 1 to the file. */
      if( DIRECT_MODE ){
        const void *zBuf = pPgHdr->pData;
................................................................................
  int noSync                      /* True to omit the xSync on the db file */
){
  int rc = SQLITE_OK;             /* Return code */

  /* The dbOrigSize is never set if journal_mode=OFF */
  assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 );

  /* If a prior error occurred, this routine should not be called.  ROLLBACK
  ** is the appropriate response to an error, not COMMIT.  Guard against
  ** coding errors by repeating the prior error. */
  if( NEVER(pPager->errCode) ) return pPager->errCode;

  PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
      pPager->zFilename, zMaster, pPager->dbSize));

  if( MEMDB && pPager->dbModified ){
    /* If this is an in-memory db, or no pages have been written to, or this
    ** function has already been called, it is mostly a no-op.  However, any
................................................................................
int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
  int rc = SQLITE_OK;                       /* Return code */
  int nCurrent = pPager->nSavepoint;        /* Current number of savepoints */

  if( nSavepoint>nCurrent && pPager->useJournal ){
    int ii;                                 /* Iterator variable */
    PagerSavepoint *aNew;                   /* New Pager.aSavepoint array */




    /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
    ** if the allocation fails. Otherwise, zero the new portion in case a 
    ** malloc failure occurs while populating it in the for(...) loop below.
    */
    aNew = (PagerSavepoint *)sqlite3Realloc(
        pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint







|
|

|







 







<
<
<
<







 







|
<
<
|







 







>
>
>







4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
....
4485
4486
4487
4488
4489
4490
4491




4492
4493
4494
4495
4496
4497
4498
....
4562
4563
4564
4565
4566
4567
4568
4569


4570
4571
4572
4573
4574
4575
4576
4577
....
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
  int rc = SQLITE_OK;

  /* This routine is not called unless a transaction has already been
  ** started.
  */
  assert( pPager->state>=PAGER_RESERVED );

  /* If an error has been previously detected, report the same error
  ** again.
  */
  if( pPager->errCode )  return pPager->errCode;

  /* Higher-level routines never call this function if database is not
  ** writable.  But check anyway, just for robustness. */
  if( NEVER(pPager->readOnly) ) return SQLITE_PERM;

  assert( !pPager->setMaster );

................................................................................

    if( rc==SQLITE_OK ){
      /* Increment the value just read and write it back to byte 24. */
      change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
      change_counter++;
      put32bits(((char*)pPgHdr->pData)+24, change_counter);





      /* Also store the SQLite version number in bytes 96..99 */
      assert( pPager->dbSizeValid );
      put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER);

      /* If running in direct mode, write the contents of page 1 to the file. */
      if( DIRECT_MODE ){
        const void *zBuf = pPgHdr->pData;
................................................................................
  int noSync                      /* True to omit the xSync on the db file */
){
  int rc = SQLITE_OK;             /* Return code */

  /* The dbOrigSize is never set if journal_mode=OFF */
  assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 );

  /* If a prior error occurred, report that error again. */


  if( pPager->errCode ) return pPager->errCode;

  PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
      pPager->zFilename, zMaster, pPager->dbSize));

  if( MEMDB && pPager->dbModified ){
    /* If this is an in-memory db, or no pages have been written to, or this
    ** function has already been called, it is mostly a no-op.  However, any
................................................................................
int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
  int rc = SQLITE_OK;                       /* Return code */
  int nCurrent = pPager->nSavepoint;        /* Current number of savepoints */

  if( nSavepoint>nCurrent && pPager->useJournal ){
    int ii;                                 /* Iterator variable */
    PagerSavepoint *aNew;                   /* New Pager.aSavepoint array */

    rc = sqlite3PagerPagecount(pPager, 0);
    if( rc ) return rc;

    /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
    ** if the allocation fails. Otherwise, zero the new portion in case a 
    ** malloc failure occurs while populating it in the for(...) loop below.
    */
    aNew = (PagerSavepoint *)sqlite3Realloc(
        pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint

Changes to test/corrupt2.test.

330
331
332
333
334
335
336

337
338
339
340
341
342
343
...
518
519
520
521
522
523
524

525
526
527
528
529
530
531
532
533
534
535
    DELETE FROM t1 WHERE a = 1;
  } -corrupt {
    set nAppend [expr 1024*207 - [file size corrupt.db]]
    set fd [open corrupt.db r+]
    seek $fd 0 end
    puts -nonewline $fd [string repeat x $nAppend]
    close $fd

  } -test {
    do_test corrupt2-6.4 {
      catchsql { 
        BEGIN EXCLUSIVE;
        COMMIT;
      }
    } {1 {database disk image is malformed}}
................................................................................
      db eval { INSERT INTO t1 SELECT NULL, randstr(50,50) FROM t1 }
    }
  } -corrupt {
    do_test corrupt2-13.1 {
      file size corrupt.db
    } $::sqlite_pending_byte
    hexio_write corrupt.db [expr $::sqlite_pending_byte+1023] 00

  } -test {
    do_test corrupt2-13.2 {
      file size corrupt.db
    } [expr $::sqlite_pending_byte + 1024]
    do_test corrupt2-13.3 {
      catchsql { DELETE FROM t1 WHERE rowid < 30; }
    } {1 {database disk image is malformed}}
  }
}

finish_test







>







 







>











330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
    DELETE FROM t1 WHERE a = 1;
  } -corrupt {
    set nAppend [expr 1024*207 - [file size corrupt.db]]
    set fd [open corrupt.db r+]
    seek $fd 0 end
    puts -nonewline $fd [string repeat x $nAppend]
    close $fd
    hexio_write corrupt.db 28 00000000
  } -test {
    do_test corrupt2-6.4 {
      catchsql { 
        BEGIN EXCLUSIVE;
        COMMIT;
      }
    } {1 {database disk image is malformed}}
................................................................................
      db eval { INSERT INTO t1 SELECT NULL, randstr(50,50) FROM t1 }
    }
  } -corrupt {
    do_test corrupt2-13.1 {
      file size corrupt.db
    } $::sqlite_pending_byte
    hexio_write corrupt.db [expr $::sqlite_pending_byte+1023] 00
    hexio_write corrupt.db 28 00000000
  } -test {
    do_test corrupt2-13.2 {
      file size corrupt.db
    } [expr $::sqlite_pending_byte + 1024]
    do_test corrupt2-13.3 {
      catchsql { DELETE FROM t1 WHERE rowid < 30; }
    } {1 {database disk image is malformed}}
  }
}

finish_test

Changes to test/io.test.

196
197
198
199
200
201
202






203
204
205
206
207
208
209
210
211
212
213
214
215
216



217
218
219
220
221
222
223
224
225
226
227
228

# Test that the journal file is created and sync()d if the transaction
# modifies a single database page and also appends a page to the file.
# Internally, this case is handled differently to the one above. The
# journal file is not actually created until the 'COMMIT' statement
# is executed.
#






do_test io-2.6.1 {
  execsql {
    BEGIN;
    INSERT INTO abc VALUES(9, randstr(1000,1000));
  }
  file exists test.db-journal
} {0}
do_test io-2.6.2 {
  # Create a file at "test.db-journal". This will prevent SQLite from
  # opening the journal for exclusive access. As a result, the COMMIT
  # should fail with SQLITE_CANTOPEN and the transaction rolled back.
  #
  file mkdir test.db-journal
  catchsql { COMMIT }



} {1 {unable to open database file}}
do_test io-2.6.3 {
  file delete -force test.db-journal
  catchsql { COMMIT }
} {1 {cannot commit - no transaction is active}}
do_test io-2.6.4 {
  execsql { SELECT * FROM abc }
} {1 2 3 4 5 6 7 8}

# Test that if the database modification is part of multi-file commit,
# the journal file is always created. In this case, the journal file
# is created during execution of the COMMIT statement, so we have to







>
>
>
>
>
>


|
|









|
>
>
>




|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

# Test that the journal file is created and sync()d if the transaction
# modifies a single database page and also appends a page to the file.
# Internally, this case is handled differently to the one above. The
# journal file is not actually created until the 'COMMIT' statement
# is executed.
#
# Changed 2010-03-27:  The size of the database is now stored in 
# bytes 28..31 and so when a page is added to the database, page 1
# is immediately modified and the journal file immediately comes into
# existance.  To fix this test, the BEGIN is changed into a a
# BEGIN IMMEDIATE and the INSERT is omitted.
#
do_test io-2.6.1 {
  execsql {
    BEGIN IMMEDIATE;
    -- INSERT INTO abc VALUES(9, randstr(1000,1000));
  }
  file exists test.db-journal
} {0}
do_test io-2.6.2 {
  # Create a file at "test.db-journal". This will prevent SQLite from
  # opening the journal for exclusive access. As a result, the COMMIT
  # should fail with SQLITE_CANTOPEN and the transaction rolled back.
  #
  file mkdir test.db-journal
  catchsql {
    INSERT INTO abc VALUES(9, randstr(1000,1000));
    COMMIT
  }
} {1 {unable to open database file}}
do_test io-2.6.3 {
  file delete -force test.db-journal
  catchsql { COMMIT }
} {0 {}}
do_test io-2.6.4 {
  execsql { SELECT * FROM abc }
} {1 2 3 4 5 6 7 8}

# Test that if the database modification is part of multi-file commit,
# the journal file is always created. In this case, the journal file
# is created during execution of the COMMIT statement, so we have to

Changes to test/pragma.test.

313
314
315
316
317
318
319

320
321
322
323
324
325
326
      set in [open test.db r]
      fconfigure $in -translation binary
      puts -nonewline $out [read $in]
      seek $in 0
      puts -nonewline $out [read $in]
      close $in
      close $out

      execsql {REINDEX t2}
      execsql {PRAGMA integrity_check}
    } {ok}
    do_test pragma-3.8.1 {
      execsql {PRAGMA quick_check}
    } {ok}
    do_test pragma-3.9 {







>







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
      set in [open test.db r]
      fconfigure $in -translation binary
      puts -nonewline $out [read $in]
      seek $in 0
      puts -nonewline $out [read $in]
      close $in
      close $out
      hexio_write testerr.db 28 00000000
      execsql {REINDEX t2}
      execsql {PRAGMA integrity_check}
    } {ok}
    do_test pragma-3.8.1 {
      execsql {PRAGMA quick_check}
    } {ok}
    do_test pragma-3.9 {