The unified diff between revisions [83b5270b..] and [5587f68e..] is displayed below. It can also be downloaded as a raw diff.
This diff has been restricted to the following files: 'sqlite/btree.c'
#
#
# patch "sqlite/btree.c"
# from [d2e09ebf755bfd665727133361b22c6a915b12d7]
# to [236126155d5607da945d33514218cbec762d887e]
#
============================================================
--- sqlite/btree.c d2e09ebf755bfd665727133361b22c6a915b12d7
+++ sqlite/btree.c 236126155d5607da945d33514218cbec762d887e
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.261 2005/05/24 20:19:58 drh Exp $
+** $Id: btree.c,v 1.269 2005/09/17 15:20:27 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -234,8 +234,19 @@ typedef struct MemPage MemPage;
/*
** This is a magic string that appears at the beginning of every
** SQLite database in order to identify the file as a real database.
-** 123456789 123456 */
-static const char zMagicHeader[] = "SQLite format 3";
+**
+** You can change this value at compile-time by specifying a
+** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
+** header must be exactly 16 bytes including the zero-terminator so
+** the string itself should be 15 characters long. If you change
+** the header, then your custom library will not be able to read
+** databases generated by the standard tools and the standard tools
+** will not be able to read databases created by your custom library.
+*/
+#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
+# define SQLITE_FILE_HEADER "SQLite format 3"
+#endif
+static const char zMagicHeader[] = SQLITE_FILE_HEADER;
/*
** Page type flags. An ORed combination of these flags appear as the
@@ -483,7 +494,7 @@ static int ptrmapPut(Btree *pBt, Pgno ke
assert( pBt->autoVacuum );
if( key==0 ){
- return SQLITE_CORRUPT;
+ return SQLITE_CORRUPT_BKPT;
}
iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key);
rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
@@ -529,7 +540,7 @@ static int ptrmapGet(Btree *pBt, Pgno ke
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
sqlite3pager_unref(pPtrmap);
- if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT;
+ if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;
return SQLITE_OK;
}
@@ -1019,7 +1030,7 @@ static int initPage(
assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] );
if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
/* The parent page should never change unless the file is corrupt */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
if( pPage->isInit ) return SQLITE_OK;
if( pPage->pParent==0 && pParent!=0 ){
@@ -1037,11 +1048,11 @@ static int initPage(
pPage->nCell = get2byte(&data[hdr+3]);
if( pPage->nCell>MX_CELL(pBt) ){
/* To many cells for a single page. The page must be corrupt */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){
/* All pages must have at least one cell, except for root pages */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
/* Compute the total free space on the page */
@@ -1051,13 +1062,13 @@ static int initPage(
int next, size;
if( pc>usableSize-4 ){
/* Free block is off the page */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
if( next>0 && next<=pc+size+3 ){
/* Free blocks must be in accending order */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
nFree += size;
pc = next;
@@ -1065,7 +1076,7 @@ static int initPage(
pPage->nFree = nFree;
if( nFree>=usableSize ){
/* Free space cannot exceed total page size */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
pPage->isInit = 1;
@@ -1135,7 +1146,7 @@ static int getAndInitPage(
){
int rc;
if( pgno==0 ){
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
rc = getPage(pBt, pgno, ppPage);
if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
@@ -1334,6 +1345,15 @@ int sqlite3BtreeSetSafetyLevel(Btree *pB
}
#endif
+/*
+** Return TRUE if the given btree is set to safety level 1. In other
+** words, return TRUE if no sync() occurs on the disk files.
+*/
+int sqlite3BtreeSyncDisabled(Btree *pBt){
+ assert( pBt && pBt->pPager );
+ return sqlite3pager_nosync(pBt->pPager);
+}
+
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Change the default pages size and the number of reserved bytes per page.
@@ -1595,8 +1615,6 @@ int sqlite3BtreeBeginTrans(Btree *pBt, i
*/
int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
int rc = SQLITE_OK;
- int busy = 0;
- BusyHandler *pH;
/* If the btree is already in a write-transaction, or it
** is already in a read-transaction and a read-transaction
@@ -1630,9 +1648,7 @@ int sqlite3BtreeBeginTrans(Btree *pBt, i
unlockBtreeIfUnused(pBt);
}
}while( rc==SQLITE_BUSY && pBt->inTrans==TRANS_NONE &&
- (pH = pBt->pBusyHandler)!=0 &&
- pH->xFunc && pH->xFunc(pH->pArg, busy++)
- );
+ sqlite3InvokeBusyHandler(pBt->pBusyHandler) );
return rc;
}
@@ -1698,7 +1714,7 @@ static int modifyPagePointer(MemPage *pP
if( eType==PTRMAP_OVERFLOW2 ){
/* The pointer is always the first 4 bytes of the page in this case. */
if( get4byte(pPage->aData)!=iFrom ){
- return SQLITE_CORRUPT;
+ return SQLITE_CORRUPT_BKPT;
}
put4byte(pPage->aData, iTo);
}else{
@@ -1731,7 +1747,7 @@ static int modifyPagePointer(MemPage *pP
if( i==nCell ){
if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
- return SQLITE_CORRUPT;
+ return SQLITE_CORRUPT_BKPT;
}
put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
}
@@ -1844,7 +1860,7 @@ static int autoVacuumCommit(Btree *pBt,
assert( pBt->autoVacuum );
if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){
- return SQLITE_CORRUPT;
+ return SQLITE_CORRUPT_BKPT;
}
/* Figure out how many free-pages are in the database. If there are no
@@ -1859,7 +1875,7 @@ static int autoVacuumCommit(Btree *pBt,
origSize = sqlite3pager_pagecount(pPager);
nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pgsz, origSize)+pgsz/5)/(pgsz/5);
finSize = origSize - nFreeList - nPtrMap;
- if( origSize>PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){
+ if( origSize>=PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){
finSize--;
if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){
finSize--;
@@ -1882,7 +1898,7 @@ static int autoVacuumCommit(Btree *pBt,
rc = ptrmapGet(pBt, iDbPage, &eType, &iPtrPage);
if( rc!=SQLITE_OK ) goto autovacuum_out;
if( eType==PTRMAP_ROOTPAGE ){
- rc = SQLITE_CORRUPT;
+ rc = SQLITE_CORRUPT_BKPT;
goto autovacuum_out;
}
@@ -2398,7 +2414,7 @@ static int getPayload(
}
if( amt>0 ){
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
return SQLITE_OK;
}
@@ -2416,7 +2432,7 @@ int sqlite3BtreeKey(BtCursor *pCur, u32
assert( pCur->isValid );
assert( pCur->pPage!=0 );
if( pCur->pPage->intKey ){
- return SQLITE_CORRUPT;
+ return SQLITE_CORRUPT_BKPT;
}
assert( pCur->pPage->intKey==0 );
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
@@ -2465,13 +2481,11 @@ static const unsigned char *fetchPayload
){
unsigned char *aPayload;
MemPage *pPage;
- Btree *pBt;
u32 nKey;
int nLocal;
assert( pCur!=0 && pCur->pPage!=0 );
assert( pCur->isValid );
- pBt = pCur->pBt;
pPage = pCur->pPage;
pageIntegrity(pPage);
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
@@ -2538,7 +2552,7 @@ static int moveToChild(BtCursor *pCur, u
pCur->idx = 0;
pCur->info.nSize = 0;
if( pNewPage->nCell<1 ){
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
return SQLITE_OK;
}
@@ -2569,7 +2583,6 @@ static void moveToParent(BtCursor *pCur)
** the largest cell index.
*/
static void moveToParent(BtCursor *pCur){
- Pgno oldPgno;
MemPage *pParent;
MemPage *pPage;
int idxParent;
@@ -2584,7 +2597,6 @@ static void moveToParent(BtCursor *pCur)
pageIntegrity(pParent);
idxParent = pPage->idxParent;
sqlite3pager_ref(pParent->aData);
- oldPgno = pPage->pgno;
releasePage(pPage);
pCur->pPage = pParent;
pCur->info.nSize = 0;
@@ -2749,7 +2761,7 @@ int sqlite3BtreeMoveto(BtCursor *pCur, c
lwr = 0;
upr = pPage->nCell-1;
if( !pPage->intKey && pKey==0 ){
- return SQLITE_CORRUPT;
+ return SQLITE_CORRUPT_BKPT;
}
pageIntegrity(pPage);
while( lwr<=upr ){
@@ -3034,7 +3046,7 @@ static int allocatePage(
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
}else if( k>pBt->usableSize/4 - 8 ){
/* Value of k is out of range. Database corruption */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
#ifndef SQLITE_OMIT_AUTOVACUUM
}else if( searchList && nearby==iTrunk ){
/* The list is being searched and this trunk page is the page
@@ -3109,7 +3121,7 @@ static int allocatePage(
*pPgno = iPage;
if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){
/* Free page off the end of the file */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ return SQLITE_CORRUPT_BKPT;
}
TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
": %d more free pages\n",
@@ -3250,7 +3262,7 @@ static int clearCell(MemPage *pPage, uns
while( ovflPgno!=0 ){
MemPage *pOvfl;
if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){
- return SQLITE_CORRUPT;
+ return SQLITE_CORRUPT_BKPT;
}
rc = getPage(pBt, ovflPgno, &pOvfl);
if( rc ) return rc;
@@ -3595,17 +3607,19 @@ static void assemblePage(
data = pPage->aData;
hdr = pPage->hdrOffset;
put2byte(&data[hdr+3], nCell);
- cellbody = allocateSpace(pPage, totalSize);
- assert( cellbody>0 );
- assert( pPage->nFree >= 2*nCell );
- pPage->nFree -= 2*nCell;
- for(i=0; i<nCell; i++){
- put2byte(&data[cellptr], cellbody);
- memcpy(&data[cellbody], apCell[i], aSize[i]);
- cellptr += 2;
- cellbody += aSize[i];
+ if( nCell ){
+ cellbody = allocateSpace(pPage, totalSize);
+ assert( cellbody>0 );
+ assert( pPage->nFree >= 2*nCell );
+ pPage->nFree -= 2*nCell;
+ for(i=0; i<nCell; i++){
+ put2byte(&data[cellptr], cellbody);
+ memcpy(&data[cellbody], apCell[i], aSize[i]);
+ cellptr += 2;
+ cellbody += aSize[i];
+ }
+ assert( cellbody==pPage->pBt->usableSize );
}
- assert( cellbody==pPage->pBt->usableSize );
pPage->nCell = nCell;
}
@@ -3809,7 +3823,7 @@ static int balance_nonroot(MemPage *pPag
/*
** A special case: If a new entry has just been inserted into a
** table (that is, a btree with integer keys and all data at the leaves)
- ** an the new entry is the right-most entry in the tree (it has the
+ ** and the new entry is the right-most entry in the tree (it has the
** largest key) then use the special balance_quick() routine for
** balancing. balance_quick() is much faster and results in a tighter
** packing of data in the common case.
@@ -4082,8 +4096,13 @@ static int balance_nonroot(MemPage *pPag
szNew[i] = szRight;
szNew[i-1] = szLeft;
}
- assert( cntNew[0]>0 );
+ /* Either we found one or more cells (cntnew[0])>0) or we are the
+ ** a virtual root page. A virtual root page is when the real root
+ ** page is page 1 and we are the only child of that page.
+ */
+ assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) );
+
/*
** Allocate k new pages. Reuse old pages where possible.
*/
@@ -4171,7 +4190,7 @@ static int balance_nonroot(MemPage *pPag
assert( j<nMaxCells );
assert( pNew->pgno==pgnoNew[i] );
assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
- assert( pNew->nCell>0 );
+ assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) );
assert( pNew->nOverflow==0 );
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -4649,7 +4668,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
rc = sqlite3BtreeNext(&leafCur, ¬Used);
if( rc!=SQLITE_OK ){
if( rc!=SQLITE_NOMEM ){
- rc = SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ rc = SQLITE_CORRUPT_BKPT;
}
}
if( rc==SQLITE_OK ){
@@ -4835,7 +4854,7 @@ static int clearDatabasePage(
int i;
if( pgno>sqlite3pager_pagecount(pBt->pPager) ){
- return SQLITE_CORRUPT;
+ return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, pgno, &pPage, pParent);
@@ -5457,7 +5476,7 @@ static int checkTreePage(
u8 *data;
BtCursor cur;
Btree *pBt;
- int maxLocal, usableSize;
+ int usableSize;
char zContext[100];
char *hit;
@@ -5474,7 +5493,6 @@ static int checkTreePage(
"unable to get the page. error code=%d", rc);
return 0;
}
- maxLocal = pPage->leafData ? pBt->maxLeaf : pBt->maxLocal;
if( (rc = initPage(pPage, pParent))!=0 ){
checkAppendMsg(pCheck, zContext, "initPage() returns error code %d", rc);
releasePage(pPage);
@@ -5721,7 +5739,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, B
*/
int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
int rc = SQLITE_OK;
- Pgno i, nPage, nToPage;
+ Pgno i, nPage, nToPage, iSkip;
if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){
return SQLITE_ERROR;
@@ -5729,8 +5747,10 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, B
if( pBtTo->pCursor ) return SQLITE_BUSY;
nToPage = sqlite3pager_pagecount(pBtTo->pPager);
nPage = sqlite3pager_pagecount(pBtFrom->pPager);
+ iSkip = PENDING_BYTE_PAGE(pBtTo);
for(i=1; rc==SQLITE_OK && i<=nPage; i++){
void *pPage;
+ if( i==iSkip ) continue;
rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage);
if( rc ) break;
rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage);
@@ -5739,6 +5759,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, B
}
for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
void *pPage;
+ if( i==iSkip ) continue;
rc = sqlite3pager_get(pBtTo->pPager, i, &pPage);
if( rc ) break;
rc = sqlite3pager_write(pPage);