mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 09:36:46 +00:00
sync up our in tree sqlite with the 3.3.13 official release. Commit to follow to finish this process on the windows build.
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4351 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.328 2006/08/16 16:42:48 drh Exp $
|
||||
** $Id: btree.c,v 1.335 2007/02/10 19:22:36 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@@ -421,7 +421,8 @@ struct BtCursor {
|
||||
*/
|
||||
#if SQLITE_TEST
|
||||
# define TRACE(X) if( sqlite3_btree_trace )\
|
||||
{ sqlite3DebugPrintf X; fflush(stdout); }
|
||||
/* { sqlite3DebugPrintf X; fflush(stdout); } */ \
|
||||
{ printf X; fflush(stdout); }
|
||||
int sqlite3_btree_trace=0; /* True to enable tracing */
|
||||
#else
|
||||
# define TRACE(X)
|
||||
@@ -1039,91 +1040,6 @@ static int ptrmapPutOvfl(MemPage *pPage, int iCell){
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Do sanity checking on a page. Throw an exception if anything is
|
||||
** not right.
|
||||
**
|
||||
** This routine is used for internal error checking only. It is omitted
|
||||
** from most builds.
|
||||
*/
|
||||
#if defined(BTREE_DEBUG) && !defined(NDEBUG) && 0
|
||||
static void _pageIntegrity(MemPage *pPage){
|
||||
int usableSize;
|
||||
u8 *data;
|
||||
int i, j, idx, c, pc, hdr, nFree;
|
||||
int cellOffset;
|
||||
int nCell, cellLimit;
|
||||
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;
|
||||
assert( hdr==(pPage->pgno==1 ? 100 : 0) );
|
||||
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
|
||||
c = pPage->aData[hdr];
|
||||
if( pPage->isInit ){
|
||||
assert( pPage->leaf == ((c & PTF_LEAF)!=0) );
|
||||
assert( pPage->zeroData == ((c & PTF_ZERODATA)!=0) );
|
||||
assert( pPage->leafData == ((c & PTF_LEAFDATA)!=0) );
|
||||
assert( pPage->intKey == ((c & (PTF_INTKEY|PTF_LEAFDATA))!=0) );
|
||||
assert( pPage->hasData ==
|
||||
!(pPage->zeroData || (!pPage->leaf && pPage->leafData)) );
|
||||
assert( pPage->cellOffset==pPage->hdrOffset+12-4*pPage->leaf );
|
||||
assert( pPage->nCell = get2byte(&pPage->aData[hdr+3]) );
|
||||
}
|
||||
data = pPage->aData;
|
||||
memset(used, 0, usableSize);
|
||||
for(i=0; i<hdr+10-pPage->leaf*4; i++) used[i] = 1;
|
||||
nFree = 0;
|
||||
pc = get2byte(&data[hdr+1]);
|
||||
while( pc ){
|
||||
int size;
|
||||
assert( pc>0 && pc<usableSize-4 );
|
||||
size = get2byte(&data[pc+2]);
|
||||
assert( pc+size<=usableSize );
|
||||
nFree += size;
|
||||
for(i=pc; i<pc+size; i++){
|
||||
assert( used[i]==0 );
|
||||
used[i] = 1;
|
||||
}
|
||||
pc = get2byte(&data[pc]);
|
||||
}
|
||||
idx = 0;
|
||||
nCell = get2byte(&data[hdr+3]);
|
||||
cellLimit = get2byte(&data[hdr+5]);
|
||||
assert( pPage->isInit==0
|
||||
|| pPage->nFree==nFree+data[hdr+7]+cellLimit-(cellOffset+2*nCell) );
|
||||
cellOffset = pPage->cellOffset;
|
||||
for(i=0; i<nCell; i++){
|
||||
int size;
|
||||
pc = get2byte(&data[cellOffset+2*i]);
|
||||
assert( pc>0 && pc<usableSize-4 );
|
||||
size = cellSize(pPage, &data[pc]);
|
||||
assert( pc+size<=usableSize );
|
||||
for(j=pc; j<pc+size; j++){
|
||||
assert( used[j]==0 );
|
||||
used[j] = 1;
|
||||
}
|
||||
}
|
||||
for(i=cellOffset+2*nCell; i<cellimit; i++){
|
||||
assert( used[i]==0 );
|
||||
used[i] = 1;
|
||||
}
|
||||
nFree = 0;
|
||||
for(i=0; i<usableSize; i++){
|
||||
assert( used[i]<=1 );
|
||||
if( used[i]==0 ) nFree++;
|
||||
}
|
||||
assert( nFree==data[hdr+7] );
|
||||
sqliteFree(used);
|
||||
}
|
||||
#define pageIntegrity(X) _pageIntegrity(X)
|
||||
#else
|
||||
# define pageIntegrity(X)
|
||||
#endif
|
||||
|
||||
/* A bunch of assert() statements to check the transaction state variables
|
||||
** of handle p (type Btree*) are internally consistent.
|
||||
*/
|
||||
@@ -1430,7 +1346,6 @@ static int initPage(
|
||||
}
|
||||
|
||||
pPage->isInit = 1;
|
||||
pageIntegrity(pPage);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1461,7 +1376,6 @@ static void zeroPage(MemPage *pPage, int flags){
|
||||
pPage->idxShift = 0;
|
||||
pPage->nCell = 0;
|
||||
pPage->isInit = 1;
|
||||
pageIntegrity(pPage);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1636,8 +1550,13 @@ int sqlite3BtreeOpen(
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3pager_read_fileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( pBt->pPager ) sqlite3pager_close(pBt->pPager);
|
||||
if( pBt->pPager ){
|
||||
sqlite3pager_close(pBt->pPager);
|
||||
}
|
||||
sqliteFree(pBt);
|
||||
sqliteFree(p);
|
||||
*ppBtree = 0;
|
||||
@@ -1650,7 +1569,6 @@ int sqlite3BtreeOpen(
|
||||
pBt->pCursor = 0;
|
||||
pBt->pPage1 = 0;
|
||||
pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager);
|
||||
sqlite3pager_read_fileheader(pBt->pPager, sizeof(zDbHeader), zDbHeader);
|
||||
pBt->pageSize = get2byte(&zDbHeader[16]);
|
||||
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|
||||
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
|
||||
@@ -2013,13 +1931,15 @@ static int lockBtreeWithRetry(Btree *pRef){
|
||||
*/
|
||||
static void unlockBtreeIfUnused(BtShared *pBt){
|
||||
if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
|
||||
if( pBt->pPage1->aData==0 ){
|
||||
MemPage *pPage = pBt->pPage1;
|
||||
pPage->aData = &((u8*)pPage)[-pBt->pageSize];
|
||||
pPage->pBt = pBt;
|
||||
pPage->pgno = 1;
|
||||
if( sqlite3pager_refcount(pBt->pPager)>=1 ){
|
||||
if( pBt->pPage1->aData==0 ){
|
||||
MemPage *pPage = pBt->pPage1;
|
||||
pPage->aData = &((u8*)pPage)[-pBt->pageSize];
|
||||
pPage->pBt = pBt;
|
||||
pPage->pgno = 1;
|
||||
}
|
||||
releasePage(pBt->pPage1);
|
||||
}
|
||||
releasePage(pBt->pPage1);
|
||||
pBt->pPage1 = 0;
|
||||
pBt->inStmt = 0;
|
||||
}
|
||||
@@ -2971,7 +2891,6 @@ static int getPayload(
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
pBt = pCur->pBtree->pBt;
|
||||
pPage = pCur->pPage;
|
||||
pageIntegrity(pPage);
|
||||
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
|
||||
getCellInfo(pCur);
|
||||
aPayload = pCur->info.pCell + pCur->info.nHeader;
|
||||
@@ -3109,7 +3028,6 @@ static const unsigned char *fetchPayload(
|
||||
assert( pCur!=0 && pCur->pPage!=0 );
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
pPage = pCur->pPage;
|
||||
pageIntegrity(pPage);
|
||||
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
|
||||
getCellInfo(pCur);
|
||||
aPayload = pCur->info.pCell;
|
||||
@@ -3171,7 +3089,6 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage);
|
||||
if( rc ) return rc;
|
||||
pageIntegrity(pNewPage);
|
||||
pNewPage->idxParent = pCur->idx;
|
||||
pOldPage = pCur->pPage;
|
||||
pOldPage->idxShift = 0;
|
||||
@@ -3219,10 +3136,8 @@ static void moveToParent(BtCursor *pCur){
|
||||
pPage = pCur->pPage;
|
||||
assert( pPage!=0 );
|
||||
assert( !isRootPage(pPage) );
|
||||
pageIntegrity(pPage);
|
||||
pParent = pPage->pParent;
|
||||
assert( pParent!=0 );
|
||||
pageIntegrity(pParent);
|
||||
idxParent = pPage->idxParent;
|
||||
sqlite3pager_ref(pParent->aData);
|
||||
releasePage(pPage);
|
||||
@@ -3252,7 +3167,6 @@ static int moveToRoot(BtCursor *pCur){
|
||||
return rc;
|
||||
}
|
||||
releasePage(pCur->pPage);
|
||||
pageIntegrity(pRoot);
|
||||
pCur->pPage = pRoot;
|
||||
}
|
||||
pCur->idx = 0;
|
||||
@@ -3396,7 +3310,7 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
|
||||
assert( pCur->pPage->nCell==0 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
for(;;){
|
||||
for(;;){
|
||||
int lwr, upr;
|
||||
Pgno chldPg;
|
||||
MemPage *pPage = pCur->pPage;
|
||||
@@ -3406,7 +3320,6 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
|
||||
if( !pPage->intKey && pKey==0 ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
pageIntegrity(pPage);
|
||||
while( lwr<=upr ){
|
||||
void *pCellKey;
|
||||
i64 nCellKey;
|
||||
@@ -3659,14 +3572,14 @@ static int allocatePage(
|
||||
int rc;
|
||||
int n; /* Number of pages on the freelist */
|
||||
int k; /* Number of leaves on the trunk of the freelist */
|
||||
MemPage *pTrunk = 0;
|
||||
MemPage *pPrevTrunk = 0;
|
||||
|
||||
pPage1 = pBt->pPage1;
|
||||
n = get4byte(&pPage1->aData[36]);
|
||||
if( n>0 ){
|
||||
/* There are pages on the freelist. Reuse one of those pages. */
|
||||
MemPage *pTrunk = 0;
|
||||
Pgno iTrunk;
|
||||
MemPage *pPrevTrunk = 0;
|
||||
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
|
||||
@@ -3707,16 +3620,8 @@ static int allocatePage(
|
||||
}
|
||||
rc = getPage(pBt, iTrunk, &pTrunk);
|
||||
if( rc ){
|
||||
releasePage(pPrevTrunk);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* TODO: This should move to after the loop? */
|
||||
rc = sqlite3pager_write(pTrunk->aData);
|
||||
if( rc ){
|
||||
releasePage(pTrunk);
|
||||
releasePage(pPrevTrunk);
|
||||
return rc;
|
||||
pTrunk = 0;
|
||||
goto end_allocate_page;
|
||||
}
|
||||
|
||||
k = get4byte(&pTrunk->aData[4]);
|
||||
@@ -3725,6 +3630,10 @@ static int allocatePage(
|
||||
** So extract the trunk page itself and use it as the newly
|
||||
** allocated page */
|
||||
assert( pPrevTrunk==0 );
|
||||
rc = sqlite3pager_write(pTrunk->aData);
|
||||
if( rc ){
|
||||
goto end_allocate_page;
|
||||
}
|
||||
*pPgno = iTrunk;
|
||||
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
|
||||
*ppPage = pTrunk;
|
||||
@@ -3732,7 +3641,8 @@ 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;
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto end_allocate_page;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
}else if( searchList && nearby==iTrunk ){
|
||||
/* The list is being searched and this trunk page is the page
|
||||
@@ -3741,6 +3651,10 @@ static int allocatePage(
|
||||
assert( *pPgno==iTrunk );
|
||||
*ppPage = pTrunk;
|
||||
searchList = 0;
|
||||
rc = sqlite3pager_write(pTrunk->aData);
|
||||
if( rc ){
|
||||
goto end_allocate_page;
|
||||
}
|
||||
if( k==0 ){
|
||||
if( !pPrevTrunk ){
|
||||
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
|
||||
@@ -3756,26 +3670,26 @@ static int allocatePage(
|
||||
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
|
||||
rc = getPage(pBt, iNewTrunk, &pNewTrunk);
|
||||
if( rc!=SQLITE_OK ){
|
||||
releasePage(pTrunk);
|
||||
releasePage(pPrevTrunk);
|
||||
return rc;
|
||||
goto end_allocate_page;
|
||||
}
|
||||
rc = sqlite3pager_write(pNewTrunk->aData);
|
||||
if( rc!=SQLITE_OK ){
|
||||
releasePage(pNewTrunk);
|
||||
releasePage(pTrunk);
|
||||
releasePage(pPrevTrunk);
|
||||
return rc;
|
||||
goto end_allocate_page;
|
||||
}
|
||||
memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
|
||||
put4byte(&pNewTrunk->aData[4], k-1);
|
||||
memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
|
||||
releasePage(pNewTrunk);
|
||||
if( !pPrevTrunk ){
|
||||
put4byte(&pPage1->aData[32], iNewTrunk);
|
||||
}else{
|
||||
rc = sqlite3pager_write(pPrevTrunk->aData);
|
||||
if( rc ){
|
||||
goto end_allocate_page;
|
||||
}
|
||||
put4byte(&pPrevTrunk->aData[0], iNewTrunk);
|
||||
}
|
||||
releasePage(pNewTrunk);
|
||||
}
|
||||
pTrunk = 0;
|
||||
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
|
||||
@@ -3785,6 +3699,10 @@ static int allocatePage(
|
||||
int closest;
|
||||
Pgno iPage;
|
||||
unsigned char *aData = pTrunk->aData;
|
||||
rc = sqlite3pager_write(aData);
|
||||
if( rc ){
|
||||
goto end_allocate_page;
|
||||
}
|
||||
if( nearby>0 ){
|
||||
int i, dist;
|
||||
closest = 0;
|
||||
@@ -3828,8 +3746,8 @@ static int allocatePage(
|
||||
}
|
||||
}
|
||||
releasePage(pPrevTrunk);
|
||||
pPrevTrunk = 0;
|
||||
}while( searchList );
|
||||
releasePage(pTrunk);
|
||||
}else{
|
||||
/* There are no pages on the freelist, so create a new page at the
|
||||
** end of the file */
|
||||
@@ -3858,6 +3776,10 @@ static int allocatePage(
|
||||
}
|
||||
|
||||
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
|
||||
|
||||
end_allocate_page:
|
||||
releasePage(pTrunk);
|
||||
releasePage(pPrevTrunk);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -4258,7 +4180,6 @@ static int insertCell(
|
||||
put2byte(&data[ins], idx);
|
||||
put2byte(&data[hdr+3], pPage->nCell);
|
||||
pPage->idxShift = 1;
|
||||
pageIntegrity(pPage);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pPage->pBt->autoVacuum ){
|
||||
/* The cell may contain a pointer to an overflow page. If so, write
|
||||
@@ -4998,8 +4919,6 @@ static int balance_nonroot(MemPage *pPage){
|
||||
** But the parent page will always be initialized.
|
||||
*/
|
||||
assert( pParent->isInit );
|
||||
/* assert( pPage->isInit ); // No! pPage might have been added to freelist */
|
||||
/* pageIntegrity(pPage); // No! pPage might have been added to freelist */
|
||||
rc = balance(pParent, 0);
|
||||
|
||||
/*
|
||||
@@ -5971,6 +5890,7 @@ int sqlite3BtreePageDump(Btree *p, int pgno, int recursive){
|
||||
** aResult[7] = Header size in bytes
|
||||
** aResult[8] = Local payload size
|
||||
** aResult[9] = Parent page number
|
||||
** aResult[10]= Page number of the first overflow page
|
||||
**
|
||||
** This routine is used for testing and debugging only.
|
||||
*/
|
||||
@@ -5984,14 +5904,12 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){
|
||||
return rc;
|
||||
}
|
||||
|
||||
pageIntegrity(pPage);
|
||||
assert( pPage->isInit );
|
||||
getTempCursor(pCur, &tmpCur);
|
||||
while( upCnt-- ){
|
||||
moveToParent(&tmpCur);
|
||||
}
|
||||
pPage = tmpCur.pPage;
|
||||
pageIntegrity(pPage);
|
||||
aResult[0] = sqlite3pager_pagenumber(pPage->aData);
|
||||
assert( aResult[0]==pPage->pgno );
|
||||
aResult[1] = tmpCur.idx;
|
||||
@@ -6021,6 +5939,11 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){
|
||||
}else{
|
||||
aResult[9] = pPage->pParent->pgno;
|
||||
}
|
||||
if( tmpCur.info.iOverflow ){
|
||||
aResult[10] = get4byte(&tmpCur.info.pCell[tmpCur.info.iOverflow]);
|
||||
}else{
|
||||
aResult[10] = 0;
|
||||
}
|
||||
releaseTempCursor(&tmpCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -6041,10 +5964,12 @@ Pager *sqlite3BtreePager(Btree *p){
|
||||
typedef struct IntegrityCk IntegrityCk;
|
||||
struct IntegrityCk {
|
||||
BtShared *pBt; /* The tree being checked out */
|
||||
Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
|
||||
int nPage; /* Number of pages in the database */
|
||||
int *anRef; /* Number of times each page is referenced */
|
||||
char *zErrMsg; /* An error message. NULL of no errors seen. */
|
||||
Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
|
||||
int nPage; /* Number of pages in the database */
|
||||
int *anRef; /* Number of times each page is referenced */
|
||||
int mxErr; /* Stop accumulating errors when this reaches zero */
|
||||
char *zErrMsg; /* An error message. NULL if no errors seen. */
|
||||
int nErr; /* Number of messages written to zErrMsg so far */
|
||||
};
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
@@ -6059,6 +5984,9 @@ static void checkAppendMsg(
|
||||
){
|
||||
va_list ap;
|
||||
char *zMsg2;
|
||||
if( !pCheck->mxErr ) return;
|
||||
pCheck->mxErr--;
|
||||
pCheck->nErr++;
|
||||
va_start(ap, zFormat);
|
||||
zMsg2 = sqlite3VMPrintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
@@ -6142,7 +6070,7 @@ static void checkList(
|
||||
int i;
|
||||
int expected = N;
|
||||
int iFirst = iPage;
|
||||
while( N-- > 0 ){
|
||||
while( N-- > 0 && pCheck->mxErr ){
|
||||
unsigned char *pOvfl;
|
||||
if( iPage<1 ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
@@ -6254,7 +6182,7 @@ static int checkTreePage(
|
||||
/* Check out all the cells.
|
||||
*/
|
||||
depth = 0;
|
||||
for(i=0; i<pPage->nCell; i++){
|
||||
for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
|
||||
u8 *pCell;
|
||||
int sz;
|
||||
CellInfo info;
|
||||
@@ -6369,7 +6297,13 @@ static int checkTreePage(
|
||||
** and a pointer to that error message is returned. The calling function
|
||||
** is responsible for freeing the error message when it is done.
|
||||
*/
|
||||
char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
char *sqlite3BtreeIntegrityCheck(
|
||||
Btree *p, /* The btree to be checked */
|
||||
int *aRoot, /* An array of root pages numbers for individual trees */
|
||||
int nRoot, /* Number of entries in aRoot[] */
|
||||
int mxErr, /* Stop reporting errors after this many */
|
||||
int *pnErr /* Write number of errors seen to this variable */
|
||||
){
|
||||
int i;
|
||||
int nRef;
|
||||
IntegrityCk sCheck;
|
||||
@@ -6382,6 +6316,9 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
sCheck.pBt = pBt;
|
||||
sCheck.pPager = pBt->pPager;
|
||||
sCheck.nPage = sqlite3pager_pagecount(sCheck.pPager);
|
||||
sCheck.mxErr = mxErr;
|
||||
sCheck.nErr = 0;
|
||||
*pnErr = 0;
|
||||
if( sCheck.nPage==0 ){
|
||||
unlockBtreeIfUnused(pBt);
|
||||
return 0;
|
||||
@@ -6389,6 +6326,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
|
||||
if( !sCheck.anRef ){
|
||||
unlockBtreeIfUnused(pBt);
|
||||
*pnErr = 1;
|
||||
return sqlite3MPrintf("Unable to malloc %d bytes",
|
||||
(sCheck.nPage+1)*sizeof(sCheck.anRef[0]));
|
||||
}
|
||||
@@ -6406,7 +6344,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
|
||||
/* Check all the tables.
|
||||
*/
|
||||
for(i=0; i<nRoot; i++){
|
||||
for(i=0; i<nRoot && sCheck.mxErr; i++){
|
||||
if( aRoot[i]==0 ) continue;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum && aRoot[i]>1 ){
|
||||
@@ -6418,7 +6356,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
|
||||
/* Make sure every page in the file is referenced
|
||||
*/
|
||||
for(i=1; i<=sCheck.nPage; i++){
|
||||
for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
|
||||
#ifdef SQLITE_OMIT_AUTOVACUUM
|
||||
if( sCheck.anRef[i]==0 ){
|
||||
checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
|
||||
@@ -6451,6 +6389,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
/* Clean up and report errors.
|
||||
*/
|
||||
sqliteFree(sCheck.anRef);
|
||||
*pnErr = sCheck.nErr;
|
||||
return sCheck.zErrMsg;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
@@ -6509,7 +6448,6 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage);
|
||||
if( rc ) break;
|
||||
rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage);
|
||||
if( rc ) break;
|
||||
sqlite3pager_unref(pPage);
|
||||
}
|
||||
for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
|
||||
|
Reference in New Issue
Block a user