aboutsummaryrefslogtreecommitdiff
path: root/src/btree.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2004-09-03 18:38:44 +0000
committerdrh <drh@noemail.net>2004-09-03 18:38:44 +0000
commit2e38c32b673501ec072c625331a0c991f193f30d (patch)
tree0deac32b7ec976f7a4d4be0f6082edcaa558e04f /src/btree.c
parent2c7e56798b06d55650a19a08b3ad2889fe712ca5 (diff)
downloadsqlite-2e38c32b673501ec072c625331a0c991f193f30d.tar.gz
sqlite-2e38c32b673501ec072c625331a0c991f193f30d.zip
Modify btree.c so that is allocates big data structures using malloc()
instead of allocating from the stack. Stack allocations cause problems for embedded systems and pthreads implementations that only allocate a limited amount of stack space. (CVS 1937) FossilOrigin-Name: 4595292f936bdbec10734f42682824e91ff71d11
Diffstat (limited to 'src/btree.c')
-rw-r--r--src/btree.c226
1 files changed, 138 insertions, 88 deletions
diff --git a/src/btree.c b/src/btree.c
index 75343d1a2..354d36866 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.185 2004/09/01 16:12:25 drh Exp $
+** $Id: btree.c,v 1.186 2004/09/03 18:38:45 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -214,13 +214,13 @@
/* The following value is the maximum cell size assuming a maximum page
** size give above.
*/
-#define MX_CELL_SIZE (SQLITE_MAX_PAGE_SIZE-8)
+#define MX_CELL_SIZE(pBt) (pBt->pageSize-8)
/* The maximum number of cells on a single page of the database. This
** assumes a minimum cell size of 3 bytes. Such small cells will be
** exceedingly rare, but they are possible.
*/
-#define MX_CELL ((SQLITE_MAX_PAGE_SIZE-8)/3)
+#define MX_CELL(pBt) ((pBt->pageSize-8)/3)
/* Forward declarations */
typedef struct MemPage MemPage;
@@ -527,8 +527,10 @@ static void _pageIntegrity(MemPage *pPage){
int i, j, idx, c, pc, hdr, nFree;
int cellOffset;
int nCell, cellLimit;
- u8 used[SQLITE_MAX_PAGE_SIZE];
+ u8 *used;
+ used = sqliteMallocRaw( pPage->pBt->pageSize );
+ if( used==0 ) return;
usableSize = pPage->pBt->usableSize;
assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] );
hdr = pPage->hdrOffset;
@@ -589,6 +591,7 @@ static void _pageIntegrity(MemPage *pPage){
if( used[i]==0 ) nFree++;
}
assert( nFree==data[hdr+7] );
+ sqliteFree(used);
}
#define pageIntegrity(X) _pageIntegrity(X)
#else
@@ -600,7 +603,7 @@ static void _pageIntegrity(MemPage *pPage){
** beginning of the page and all free space is collected
** into one big FreeBlk at the end of the page.
*/
-static void defragmentPage(MemPage *pPage){
+static int defragmentPage(MemPage *pPage){
int i; /* Loop counter */
int pc; /* Address of a i-th cell */
int addr; /* Offset of first byte after cell pointer array */
@@ -610,13 +613,15 @@ static void defragmentPage(MemPage *pPage){
int cellOffset; /* Offset to the cell pointer array */
int brk; /* Offset to the cell content area */
int nCell; /* Number of cells on the page */
- unsigned char *data; /* The page data */
- unsigned char temp[SQLITE_MAX_PAGE_SIZE]; /* Temp area for cell content */
+ unsigned char *data; /* The page data */
+ unsigned char *temp; /* Temp area for cell content */
assert( sqlite3pager_iswriteable(pPage->aData) );
assert( pPage->pBt!=0 );
assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
assert( pPage->nOverflow==0 );
+ temp = sqliteMalloc( pPage->pBt->pageSize );
+ if( temp==0 ) return SQLITE_NOMEM;
data = pPage->aData;
hdr = pPage->hdrOffset;
cellOffset = pPage->cellOffset;
@@ -643,6 +648,8 @@ static void defragmentPage(MemPage *pPage){
data[hdr+7] = 0;
addr = cellOffset+2*nCell;
memset(&data[addr], 0, brk-addr);
+ sqliteFree(temp);
+ return SQLITE_OK;
}
/*
@@ -702,7 +709,7 @@ static int allocateSpace(MemPage *pPage, int nByte){
nCell = get2byte(&data[hdr+3]);
cellOffset = pPage->cellOffset;
if( nFrag>=60 || cellOffset + 2*nCell > top - nByte ){
- defragmentPage(pPage);
+ if( defragmentPage(pPage) ) return 0;
top = get2byte(&data[hdr+5]);
}
top -= nByte;
@@ -819,15 +826,17 @@ static int initPage(
int i; /* Loop counter */
int hdr; /* Offset to beginning of page header */
u8 *data; /* Equal to pPage->aData */
+ Btree *pBt; /* The main btree structure */
int usableSize; /* Amount of usable space on each page */
int cellOffset; /* Offset from start of page to first cell pointer */
int nFree; /* Number of unused bytes on the page */
int top; /* First byte of the cell content area */
- assert( pPage->pBt!=0 );
- assert( pParent==0 || pParent->pBt==pPage->pBt );
+ pBt = pPage->pBt;
+ assert( pBt!=0 );
+ assert( pParent==0 || pParent->pBt==pBt );
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
- assert( pPage->aData == &((unsigned char*)pPage)[-pPage->pBt->pageSize] );
+ 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 */
@@ -842,11 +851,11 @@ static int initPage(
decodeFlags(pPage, data[hdr]);
pPage->nOverflow = 0;
pPage->idxShift = 0;
- usableSize = pPage->pBt->usableSize;
+ usableSize = pBt->usableSize;
pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
top = get2byte(&data[hdr+5]);
pPage->nCell = get2byte(&data[hdr+3]);
- if( pPage->nCell>MX_CELL ){
+ if( pPage->nCell>MX_CELL(pBt) ){
/* To many cells for a single page. The page must be corrupt */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
}
@@ -1218,7 +1227,7 @@ static int lockBtree(Btree *pBt){
if( pBt->minLocal>pBt->maxLocal || pBt->maxLocal<0 ){
goto page1_init_failed;
}
- assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE );
+ assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
pBt->pPage1 = pPage1;
pBt->pageSizeFixed = 1;
return SQLITE_OK;
@@ -2916,6 +2925,7 @@ static int balance_nonroot(MemPage *pPage){
int pageFlags; /* Value of pPage->aData[0] */
int subtotal; /* Subtotal of bytes in cells on one page */
int iSpace = 0; /* First unused byte of aSpace[] */
+ int mxCellPerPage; /* Maximum number of cells in one page */
MemPage *apOld[NB]; /* pPage and up to two siblings */
Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */
MemPage *apCopy[NB]; /* Private copies of apOld[] pages */
@@ -2925,10 +2935,10 @@ static int balance_nonroot(MemPage *pPage){
u8 *apDiv[NB]; /* Divider cells in pParent */
int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */
int szNew[NB+2]; /* Combined size of cells place on i-th page */
- u8 *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */
- int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */
- u8 aCopy[NB][SQLITE_MAX_PAGE_SIZE+sizeof(MemPage)]; /* Space for apCopy[] */
- u8 aSpace[SQLITE_MAX_PAGE_SIZE*5]; /* Space to copies of divider cells */
+ u8 **apCell; /* All cells begin balanced */
+ int *szCell; /* Local size of all cells in apCell[] */
+ u8 *aCopy[NB]; /* Space for holding data of apCopy[] */
+ u8 *aSpace; /* Space to hold copies of dividers cells */
/*
** Find the parent page.
@@ -2940,6 +2950,25 @@ static int balance_nonroot(MemPage *pPage){
sqlite3pager_write(pParent->aData);
assert( pParent );
TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
+
+ /*
+ ** Allocate space for memory structures
+ */
+ mxCellPerPage = MX_CELL(pBt);
+ apCell = sqliteMallocRaw(
+ (mxCellPerPage+2)*NB*(sizeof(u8*)+sizeof(int))
+ + sizeof(MemPage)*NB
+ + pBt->pageSize*(5+NB)
+ );
+ if( apCell==0 ){
+ return SQLITE_NOMEM;
+ }
+ szCell = (int*)&apCell[(mxCellPerPage+2)*NB];
+ aCopy[0] = (u8*)&szCell[(mxCellPerPage+2)*NB];
+ for(i=1; i<NB; i++){
+ aCopy[i] = &aCopy[i-1][pBt->pageSize+sizeof(MemPage)];
+ }
+ aSpace = &aCopy[NB-1][pBt->pageSize+sizeof(MemPage)];
/*
** Find the cell in the parent page whose left child points back
@@ -3010,7 +3039,7 @@ static int balance_nonroot(MemPage *pPage){
** process of being overwritten.
*/
for(i=0; i<nOld; i++){
- MemPage *p = apCopy[i] = (MemPage*)&aCopy[i+1][-(int)sizeof(MemPage)];
+ MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->pageSize];
p->aData = &((u8*)p)[-pBt->pageSize];
memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage));
p->aData = &((u8*)p)[-pBt->pageSize];
@@ -3057,7 +3086,7 @@ static int balance_nonroot(MemPage *pPage){
szCell[nCell] = sz;
pTemp = &aSpace[iSpace];
iSpace += sz;
- assert( iSpace<=sizeof(aSpace) );
+ assert( iSpace<=pBt->pageSize*5 );
memcpy(pTemp, apDiv[i], sz);
apCell[nCell] = pTemp+leafCorrection;
dropCell(pParent, nxDiv, sz);
@@ -3241,13 +3270,13 @@ static int balance_nonroot(MemPage *pPage){
pCell = &aSpace[iSpace];
fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz);
iSpace += sz;
- assert( iSpace<=sizeof(aSpace) );
+ assert( iSpace<=pBt->pageSize*5 );
pTemp = 0;
}else{
pCell -= 4;
pTemp = &aSpace[iSpace];
iSpace += sz;
- assert( iSpace<=sizeof(aSpace) );
+ assert( iSpace<=pBt->pageSize*5 );
}
insertCell(pParent, nxDiv, pCell, sz, pTemp);
put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno);
@@ -3290,6 +3319,7 @@ static int balance_nonroot(MemPage *pPage){
** Cleanup before returning.
*/
balance_cleanup:
+ sqliteFree(apCell);
for(i=0; i<nOld; i++){
releasePage(apOld[i]);
}
@@ -3310,12 +3340,19 @@ balance_cleanup:
static int balance_shallower(MemPage *pPage){
MemPage *pChild; /* The only child page of pPage */
Pgno pgnoChild; /* Page number for pChild */
- int rc; /* Return code from subprocedures */
- u8 *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */
- int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */
+ int rc = SQLITE_OK; /* Return code from subprocedures */
+ Btree *pBt; /* The main BTree structure */
+ int mxCellPerPage; /* Maximum number of cells per page */
+ u8 **apCell; /* All cells from pages being balanced */
+ int *szCell; /* Local size of all cells */
assert( pPage->pParent==0 );
assert( pPage->nCell==0 );
+ pBt = pPage->pBt;
+ mxCellPerPage = MX_CELL(pBt);
+ apCell = sqliteMallocRaw( mxCellPerPage*(sizeof(u8*)+sizeof(int)) );
+ if( apCell==0 ) return SQLITE_NOMEM;
+ szCell = (int*)&apCell[mxCellPerPage];
if( pPage->leaf ){
/* The table is completely empty */
TRACE(("BALANCE: empty table %d\n", pPage->pgno));
@@ -3336,10 +3373,10 @@ static int balance_shallower(MemPage *pPage){
assert( pgnoChild>0 );
assert( pgnoChild<=sqlite3pager_pagecount(pPage->pBt->pPager) );
rc = getPage(pPage->pBt, pgnoChild, &pChild);
- if( rc ) return rc;
+ if( rc ) goto end_shallow_balance;
if( pPage->pgno==1 ){
rc = initPage(pChild, pPage);
- if( rc ) return rc;
+ if( rc ) goto end_shallow_balance;
assert( pChild->nOverflow==0 );
if( pChild->nFree>=100 ){
/* The child information will fit on the root page, so do the
@@ -3371,7 +3408,9 @@ static int balance_shallower(MemPage *pPage){
reparentChildPages(pPage);
releasePage(pChild);
}
- return SQLITE_OK;
+end_shallow_balance:
+ sqliteFree(apCell);
+ return rc;
}
@@ -3492,7 +3531,7 @@ int sqlite3BtreeInsert(
MemPage *pPage;
Btree *pBt = pCur->pBt;
unsigned char *oldCell;
- unsigned char newCell[MX_CELL_SIZE];
+ unsigned char *newCell = 0;
if( pCur->status ){
return pCur->status; /* A rollback destroyed this cursor */
@@ -3519,10 +3558,12 @@ int sqlite3BtreeInsert(
assert( pPage->isInit );
rc = sqlite3pager_write(pPage->aData);
if( rc ) return rc;
+ newCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) );
+ if( newCell==0 ) return SQLITE_NOMEM;
rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, &szNew);
- if( rc ) return rc;
+ if( rc ) goto end_insert;
assert( szNew==cellSizePtr(pPage, newCell) );
- assert( szNew<=sizeof(newCell) );
+ assert( szNew<=MX_CELL_SIZE(pBt) );
if( loc==0 && pCur->isValid ){
int szOld;
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
@@ -3532,7 +3573,7 @@ int sqlite3BtreeInsert(
}
szOld = cellSizePtr(pPage, oldCell);
rc = clearCell(pPage, oldCell);
- if( rc ) return rc;
+ if( rc ) goto end_insert;
dropCell(pPage, pCur->idx, szOld);
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
@@ -3546,6 +3587,8 @@ int sqlite3BtreeInsert(
/* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
/* fflush(stdout); */
moveToRoot(pCur);
+end_insert:
+ sqliteFree(newCell);
return rc;
}
@@ -3597,7 +3640,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
unsigned char *pNext;
int szNext;
int notUsed;
- unsigned char tempCell[MX_CELL_SIZE];
+ unsigned char *tempCell;
assert( !pPage->leafData );
getTempCursor(pCur, &leafCur);
rc = sqlite3BtreeNext(&leafCur, &notUsed);
@@ -3614,10 +3657,13 @@ int sqlite3BtreeDelete(BtCursor *pCur){
dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell));
pNext = findCell(leafCur.pPage, leafCur.idx);
szNext = cellSizePtr(leafCur.pPage, pNext);
- assert( sizeof(tempCell)>=szNext+4 );
+ assert( MX_CELL_SIZE(pBt)>=szNext+4 );
+ tempCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) );
+ if( tempCell==0 ) return SQLITE_NOMEM;
insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell);
put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild);
rc = balance(pPage);
+ sqliteFree(tempCell);
if( rc ) return rc;
dropCell(leafCur.pPage, leafCur.idx, szNext);
rc = balance(leafCur.pPage);
@@ -4013,7 +4059,18 @@ struct IntegrityCk {
/*
** Append a message to the error message string.
*/
-static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
+static void checkAppendMsg(
+ IntegrityCk *pCheck,
+ char *zMsg1,
+ const char *zFormat,
+ ...
+){
+ va_list ap;
+ char *zMsg2;
+ va_start(ap, zFormat);
+ zMsg2 = sqlite3VMPrintf(zFormat, ap);
+ va_end(ap);
+ if( zMsg1==0 ) zMsg1 = "";
if( pCheck->zErrMsg ){
char *zOld = pCheck->zErrMsg;
pCheck->zErrMsg = 0;
@@ -4022,6 +4079,7 @@ static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
}else{
sqlite3SetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0);
}
+ sqliteFree(zMsg2);
}
/*
@@ -4035,15 +4093,11 @@ static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
if( iPage==0 ) return 1;
if( iPage>pCheck->nPage || iPage<0 ){
- char zBuf[100];
- sprintf(zBuf, "invalid page number %d", iPage);
- checkAppendMsg(pCheck, zContext, zBuf);
+ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage);
return 1;
}
if( pCheck->anRef[iPage]==1 ){
- char zBuf[100];
- sprintf(zBuf, "2nd reference to page %d", iPage);
- checkAppendMsg(pCheck, zContext, zBuf);
+ checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage);
return 1;
}
return (pCheck->anRef[iPage]++)>1;
@@ -4063,26 +4117,24 @@ static void checkList(
int i;
int expected = N;
int iFirst = iPage;
- char zMsg[100];
while( N-- > 0 ){
unsigned char *pOvfl;
if( iPage<1 ){
- sprintf(zMsg, "%d of %d pages missing from overflow list starting at %d",
+ checkAppendMsg(pCheck, zContext,
+ "%d of %d pages missing from overflow list starting at %d",
N+1, expected, iFirst);
- checkAppendMsg(pCheck, zContext, zMsg);
break;
}
if( checkRef(pCheck, iPage, zContext) ) break;
if( sqlite3pager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){
- sprintf(zMsg, "failed to get page %d", iPage);
- checkAppendMsg(pCheck, zContext, zMsg);
+ checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage);
break;
}
if( isFreeList ){
int n = get4byte(&pOvfl[4]);
if( n>pCheck->pBt->usableSize/4-8 ){
- sprintf(zMsg, "freelist leaf count too big on page %d", iPage);
- checkAppendMsg(pCheck, zContext, zMsg);
+ checkAppendMsg(pCheck, zContext,
+ "freelist leaf count too big on page %d", iPage);
N--;
}else{
for(i=0; i<n; i++){
@@ -4132,9 +4184,8 @@ static int checkTreePage(
BtCursor cur;
Btree *pBt;
int maxLocal, usableSize;
- char zMsg[100];
char zContext[100];
- char hit[SQLITE_MAX_PAGE_SIZE];
+ char *hit;
/* Check that the page exists
*/
@@ -4143,14 +4194,13 @@ static int checkTreePage(
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
if( (rc = getPage(pBt, (Pgno)iPage, &pPage))!=0 ){
- sprintf(zMsg, "unable to get the page. error code=%d", rc);
- checkAppendMsg(pCheck, zContext, zMsg);
+ checkAppendMsg(pCheck, zContext,
+ "unable to get the page. error code=%d", rc);
return 0;
}
maxLocal = pPage->leafData ? pBt->maxLeaf : pBt->maxLocal;
if( (rc = initPage(pPage, pParent))!=0 ){
- sprintf(zMsg, "initPage() returns error code %d", rc);
- checkAppendMsg(pCheck, zContext, zMsg);
+ checkAppendMsg(pCheck, zContext, "initPage() returns error code %d", rc);
releasePage(pPage);
return 0;
}
@@ -4197,36 +4247,40 @@ static int checkTreePage(
*/
data = pPage->aData;
hdr = pPage->hdrOffset;
- memset(hit, 0, usableSize);
- memset(hit, 1, get2byte(&data[hdr+5]));
- nCell = get2byte(&data[hdr+3]);
- cellStart = hdr + 12 - 4*pPage->leaf;
- for(i=0; i<nCell; i++){
- int pc = get2byte(&data[cellStart+i*2]);
- int size = cellSizePtr(pPage, &data[pc]);
- int j;
- for(j=pc+size-1; j>=pc; j--) hit[j]++;
- }
- for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000; cnt++){
- int size = get2byte(&data[i+2]);
- int j;
- for(j=i+size-1; j>=i; j--) hit[j]++;
- i = get2byte(&data[i]);
- }
- for(i=cnt=0; i<usableSize; i++){
- if( hit[i]==0 ){
- cnt++;
- }else if( hit[i]>1 ){
- sprintf(zMsg, "Multiple uses for byte %d of page %d", i, iPage);
- checkAppendMsg(pCheck, zMsg, 0);
- break;
+ hit = sqliteMalloc( usableSize );
+ if( hit ){
+ memset(hit, 1, get2byte(&data[hdr+5]));
+ nCell = get2byte(&data[hdr+3]);
+ cellStart = hdr + 12 - 4*pPage->leaf;
+ for(i=0; i<nCell; i++){
+ int pc = get2byte(&data[cellStart+i*2]);
+ int size = cellSizePtr(pPage, &data[pc]);
+ int j;
+ for(j=pc+size-1; j>=pc; j--) hit[j]++;
+ }
+ for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000;
+ cnt++){
+ int size = get2byte(&data[i+2]);
+ int j;
+ for(j=i+size-1; j>=i; j--) hit[j]++;
+ i = get2byte(&data[i]);
+ }
+ for(i=cnt=0; i<usableSize; i++){
+ if( hit[i]==0 ){
+ cnt++;
+ }else if( hit[i]>1 ){
+ checkAppendMsg(pCheck, 0,
+ "Multiple uses for byte %d of page %d", i, iPage);
+ break;
+ }
+ }
+ if( cnt!=data[hdr+7] ){
+ checkAppendMsg(pCheck, 0,
+ "Fragmented space is %d byte reported as %d on page %d",
+ cnt, data[hdr+7], iPage);
}
}
- if( cnt!=data[hdr+7] ){
- sprintf(zMsg, "Fragmented space is %d byte reported as %d on page %d",
- cnt, data[hdr+7], iPage);
- checkAppendMsg(pCheck, zMsg, 0);
- }
+ sqliteFree(hit);
releasePage(pPage);
return depth+1;
@@ -4282,9 +4336,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
*/
for(i=1; i<=sCheck.nPage; i++){
if( sCheck.anRef[i]==0 ){
- char zBuf[100];
- sprintf(zBuf, "Page %d is never used", i);
- checkAppendMsg(&sCheck, zBuf, 0);
+ checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
}
}
@@ -4292,12 +4344,10 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
*/
unlockBtreeIfUnused(pBt);
if( nRef != *sqlite3pager_stats(pBt->pPager) ){
- char zBuf[100];
- sprintf(zBuf,
+ checkAppendMsg(&sCheck, 0,
"Outstanding page count goes from %d to %d during this analysis",
nRef, *sqlite3pager_stats(pBt->pPager)
);
- checkAppendMsg(&sCheck, zBuf, 0);
}
/* Clean up and report errors.