1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Simplification of PRAGMA integrity_check logic. Make sure that the depth

of the right-most subtree is correct.  Size reduction and performance increase,
with no change in output.

FossilOrigin-Name: 550705fcb64e7ad637686e47cabe2621d65851bf
This commit is contained in:
drh
2015-07-01 17:53:49 +00:00
parent 94a3115daa
commit e05b3f8f0b
6 changed files with 50 additions and 58 deletions

View File

@@ -1,5 +1,5 @@
C Fix\ssome\sharmless\scompiler\swarnings. C Simplification\sof\sPRAGMA\sintegrity_check\slogic.\s\sMake\ssure\sthat\sthe\sdepth\nof\sthe\sright-most\ssubtree\sis\scorrect.\s\sSize\sreduction\sand\sperformance\sincrease,\nwith\sno\schange\sin\soutput.
D 2015-07-01T04:08:40.538 D 2015-07-01T17:53:49.435
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 285a0a234ed7610d431d91671c136098c2bd86a9 F Makefile.in 285a0a234ed7610d431d91671c136098c2bd86a9
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -269,9 +269,9 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3 F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 075ce6ddce9e66277c898f5b6a44a8a7c61c8125 F src/btree.c e283de2f9da7ec5e47bedcd442a66a671aa2e118
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h c54d380cb262549c4176e0d665518cc1a3861bdf F src/btreeInt.h 2ad754dd4528baa8d0946a593cc373b890bf859e
F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70 F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
@@ -314,8 +314,8 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc
F src/os_win.c 27cc135e2d0b8b1e2e4944db1e2669a6a18fa0f8 F src/os_win.c 27cc135e2d0b8b1e2e4944db1e2669a6a18fa0f8
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 922d8ea28387b79a117488da06ee84f77d50d71e F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77 F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8 F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0 F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
@@ -1364,7 +1364,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 59ad912c4c1f858e04d27b1b8f25581a5f6e5daf P 307195c8709d7fd2a642baa8011eb0c88cfdc0ac
R 71a875c7f3b6312a533d9c1fd4d005d9 R 1440540aa3867982699c114f203dbd2b
U drh U drh
Z 39cb6954bdcd951136843b690dd37c51 Z 4a2c86e34c201f78bc5202943cc67b23

View File

@@ -1 +1 @@
307195c8709d7fd2a642baa8011eb0c88cfdc0ac 550705fcb64e7ad637686e47cabe2621d65851bf

View File

@@ -8924,14 +8924,10 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
** **
** 1. Make sure that cells and freeblocks do not overlap ** 1. Make sure that cells and freeblocks do not overlap
** but combine to completely cover the page. ** but combine to completely cover the page.
** NO 2. Make sure cell keys are in order. ** 2. Make sure integer cell keys are in order.
** NO 3. Make sure no key is less than or equal to zLowerBound. ** 3. Check the integrity of overflow pages.
** NO 4. Make sure no key is greater than or equal to zUpperBound. ** 4. Recursively call checkTreePage on all children.
** 5. Check the integrity of overflow pages. ** 5. Verify that the depth of all children is the same.
** 6. Recursively call checkTreePage on all children.
** 7. Verify that the depth of all children is the same.
** 8. Make sure this page is at least 33% full or else it is
** the root of the tree.
*/ */
static int checkTreePage( static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */ IntegrityCk *pCheck, /* Context for the sanity check */
@@ -8939,7 +8935,7 @@ static int checkTreePage(
i64 *pnParentMinKey, i64 *pnParentMinKey,
i64 *pnParentMaxKey i64 *pnParentMaxKey
){ ){
MemPage *pPage; MemPage *pPage = 0;
int i, rc, depth, d2, pgno, cnt; int i, rc, depth, d2, pgno, cnt;
int hdr, cellStart; int hdr, cellStart;
int nCell; int nCell;
@@ -8976,7 +8972,6 @@ static int checkTreePage(
assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */ assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */
checkAppendMsg(pCheck, checkAppendMsg(pCheck,
"btreeInitPage() returns error code %d", rc); "btreeInitPage() returns error code %d", rc);
releasePage(pPage);
depth = -1; depth = -1;
goto end_of_check; goto end_of_check;
} }
@@ -8984,6 +8979,7 @@ static int checkTreePage(
/* Check out all the cells. /* Check out all the cells.
*/ */
depth = 0; depth = 0;
pCheck->zPfx = "On tree page %d cell %d: ";
for(i=0; i<pPage->nCell && pCheck->mxErr; i++){ for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
u8 *pCell; u8 *pCell;
u32 sz; u32 sz;
@@ -8991,8 +8987,6 @@ static int checkTreePage(
/* Check payload overflow pages /* Check payload overflow pages
*/ */
pCheck->zPfx = "On tree page %d cell %d: ";
pCheck->v1 = iPage;
pCheck->v2 = i; pCheck->v2 = i;
pCell = findCell(pPage,i); pCell = findCell(pPage,i);
pPage->xParseCell(pPage, pCell, &info); pPage->xParseCell(pPage, pCell, &info);
@@ -9041,20 +9035,21 @@ static int checkTreePage(
if( !pPage->leaf ){ if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
pCheck->zPfx = "On page %d at right child: "; pCheck->zPfx = "On page %d at right child: ";
pCheck->v1 = iPage;
#ifndef SQLITE_OMIT_AUTOVACUUM #ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){ if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
} }
#endif #endif
checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey); d2 = checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey);
if( d2!=depth && iPage!=1 ){
checkAppendMsg(pCheck, "Child page depth differs");
}
} }
/* For intKey leaf pages, check that the min/max keys are in order /* For intKey leaf pages, check that the min/max keys are in order
** with any left/parent/right pages. ** with any left/parent/right pages.
*/ */
pCheck->zPfx = "Page %d: "; pCheck->zPfx = "Page %d: ";
pCheck->v1 = iPage;
if( pPage->leaf && pPage->intKey ){ if( pPage->leaf && pPage->intKey ){
/* if we are a left child page */ /* if we are a left child page */
if( pnParentMinKey ){ if( pnParentMinKey ){
@@ -9092,14 +9087,12 @@ static int checkTreePage(
*/ */
data = pPage->aData; data = pPage->aData;
hdr = pPage->hdrOffset; hdr = pPage->hdrOffset;
heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); heap = pCheck->heap;
heap[0] = 0;
pCheck->zPfx = 0; pCheck->zPfx = 0;
if( heap==0 ){ {
pCheck->mallocFailed = 1;
}else{
int contentOffset = get2byteNotZero(&data[hdr+5]); int contentOffset = get2byteNotZero(&data[hdr+5]);
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
heap[0] = 0;
btreeHeapInsert(heap, contentOffset-1); btreeHeapInsert(heap, contentOffset-1);
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
** number of cells on the page. */ ** number of cells on the page. */
@@ -9167,10 +9160,9 @@ static int checkTreePage(
cnt, data[hdr+7], iPage); cnt, data[hdr+7], iPage);
} }
} }
sqlite3PageFree(heap);
releasePage(pPage);
end_of_check: end_of_check:
releasePage(pPage);
pCheck->zPfx = saved_zPfx; pCheck->zPfx = saved_zPfx;
pCheck->v1 = saved_v1; pCheck->v1 = saved_v1;
pCheck->v2 = saved_v2; pCheck->v2 = saved_v2;
@@ -9200,14 +9192,14 @@ char *sqlite3BtreeIntegrityCheck(
int *pnErr /* Write number of errors seen to this variable */ int *pnErr /* Write number of errors seen to this variable */
){ ){
Pgno i; Pgno i;
int nRef; VVA_ONLY( int nRef );
IntegrityCk sCheck; IntegrityCk sCheck;
BtShared *pBt = p->pBt; BtShared *pBt = p->pBt;
char zErr[100]; char zErr[100];
sqlite3BtreeEnter(p); sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
nRef = sqlite3PagerRefcount(pBt->pPager); assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 );
sCheck.pBt = pBt; sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager; sCheck.pPager = pBt->pPager;
sCheck.nPage = btreePagecount(sCheck.pBt); sCheck.nPage = btreePagecount(sCheck.pBt);
@@ -9217,21 +9209,26 @@ char *sqlite3BtreeIntegrityCheck(
sCheck.zPfx = 0; sCheck.zPfx = 0;
sCheck.v1 = 0; sCheck.v1 = 0;
sCheck.v2 = 0; sCheck.v2 = 0;
*pnErr = 0; sCheck.aPgRef = 0;
sCheck.heap = 0;
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
if( sCheck.nPage==0 ){ if( sCheck.nPage==0 ){
sqlite3BtreeLeave(p); goto integrity_ck_cleanup;
return 0;
} }
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
if( !sCheck.aPgRef ){ if( !sCheck.aPgRef ){
*pnErr = 1; sCheck.mallocFailed = 1;
sqlite3BtreeLeave(p); goto integrity_ck_cleanup;
return 0;
} }
sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
if( sCheck.heap==0 ){
sCheck.mallocFailed = 1;
goto integrity_ck_cleanup;
}
i = PENDING_BYTE_PAGE(pBt); i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
/* Check the integrity of the freelist /* Check the integrity of the freelist
*/ */
@@ -9249,9 +9246,7 @@ char *sqlite3BtreeIntegrityCheck(
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
} }
#endif #endif
sCheck.zPfx = "List of tree roots: ";
checkTreePage(&sCheck, aRoot[i], NULL, NULL); checkTreePage(&sCheck, aRoot[i], NULL, NULL);
sCheck.zPfx = 0;
} }
/* Make sure every page in the file is referenced /* Make sure every page in the file is referenced
@@ -9276,28 +9271,20 @@ char *sqlite3BtreeIntegrityCheck(
#endif #endif
} }
/* Make sure this analysis did not leave any unref() pages.
** This is an internal consistency check; an integrity check
** of the integrity check.
*/
if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){
checkAppendMsg(&sCheck,
"Outstanding page count goes from %d to %d during this analysis",
nRef, sqlite3PagerRefcount(pBt->pPager)
);
}
/* Clean up and report errors. /* Clean up and report errors.
*/ */
sqlite3BtreeLeave(p); integrity_ck_cleanup:
sqlite3PageFree(sCheck.heap);
sqlite3_free(sCheck.aPgRef); sqlite3_free(sCheck.aPgRef);
if( sCheck.mallocFailed ){ if( sCheck.mallocFailed ){
sqlite3StrAccumReset(&sCheck.errMsg); sqlite3StrAccumReset(&sCheck.errMsg);
*pnErr = sCheck.nErr+1; sCheck.nErr++;
return 0;
} }
*pnErr = sCheck.nErr; *pnErr = sCheck.nErr;
if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg);
/* Make sure this analysis did not leave any unref() pages. */
assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
sqlite3BtreeLeave(p);
return sqlite3StrAccumFinish(&sCheck.errMsg); return sqlite3StrAccumFinish(&sCheck.errMsg);
} }
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #endif /* SQLITE_OMIT_INTEGRITY_CHECK */

View File

@@ -682,6 +682,7 @@ struct IntegrityCk {
const char *zPfx; /* Error message prefix */ const char *zPfx; /* Error message prefix */
int v1, v2; /* Values for up to two %d fields in zPfx */ int v1, v2; /* Values for up to two %d fields in zPfx */
StrAccum errMsg; /* Accumulate the error message text here */ StrAccum errMsg; /* Accumulate the error message text here */
u32 *heap; /* Min-heap used for analyzing cell coverage */
}; };
/* /*

View File

@@ -6387,12 +6387,14 @@ u8 sqlite3PagerIsreadonly(Pager *pPager){
return pPager->readOnly; return pPager->readOnly;
} }
#ifdef SQLITE_DEBUG
/* /*
** Return the number of references to the pager. ** Return the number of references to the pager.
*/ */
int sqlite3PagerRefcount(Pager *pPager){ int sqlite3PagerRefcount(Pager *pPager){
return sqlite3PcacheRefCount(pPager->pPCache); return sqlite3PcacheRefCount(pPager->pPCache);
} }
#endif
/* /*
** Return the approximate number of bytes of memory currently ** Return the approximate number of bytes of memory currently

View File

@@ -173,7 +173,9 @@ int sqlite3PagerSharedLock(Pager *pPager);
/* Functions used to query pager state and configuration. */ /* Functions used to query pager state and configuration. */
u8 sqlite3PagerIsreadonly(Pager*); u8 sqlite3PagerIsreadonly(Pager*);
u32 sqlite3PagerDataVersion(Pager*); u32 sqlite3PagerDataVersion(Pager*);
int sqlite3PagerRefcount(Pager*); #ifdef SQLITE_DEBUG
int sqlite3PagerRefcount(Pager*);
#endif
int sqlite3PagerMemUsed(Pager*); int sqlite3PagerMemUsed(Pager*);
const char *sqlite3PagerFilename(Pager*, int); const char *sqlite3PagerFilename(Pager*, int);
const sqlite3_vfs *sqlite3PagerVfs(Pager*); const sqlite3_vfs *sqlite3PagerVfs(Pager*);