aboutsummaryrefslogtreecommitdiff
path: root/src/btree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/btree.c')
-rw-r--r--src/btree.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/src/btree.c b/src/btree.c
index 68f290720..7754f3a21 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -7411,7 +7411,9 @@ static void checkList(
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
- char *zParentContext /* Parent context */
+ char *zParentContext, /* Parent context */
+ i64 *pnParentMinKey,
+ i64 *pnParentMaxKey
){
MemPage *pPage;
int i, rc, depth, d2, pgno, cnt;
@@ -7422,6 +7424,8 @@ static int checkTreePage(
int usableSize;
char zContext[100];
char *hit = 0;
+ i64 nMinKey = 0;
+ i64 nMaxKey = 0;
sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
@@ -7464,6 +7468,16 @@ static int checkTreePage(
btreeParseCellPtr(pPage, pCell, &info);
sz = info.nData;
if( !pPage->intKey ) sz += (int)info.nKey;
+ /* For intKey pages, check that the keys are in order.
+ */
+ else if( i==0 ) nMinKey = nMaxKey = info.nKey;
+ else{
+ if( info.nKey <= nMaxKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
+ }
+ nMaxKey = info.nKey;
+ }
assert( sz==info.nPayload );
if( (sz>info.nLocal)
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
@@ -7487,25 +7501,62 @@ static int checkTreePage(
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
- d2 = checkTreePage(pCheck, pgno, zContext);
+ d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, zContext, "Child page depth differs");
}
depth = d2;
}
}
+
if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
sqlite3_snprintf(sizeof(zContext), zContext,
"On page %d at right child: ", iPage);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
- checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
+ checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
- checkTreePage(pCheck, pgno, zContext);
+ checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
}
+ /* For intKey leaf pages, check that the min/max keys are in order
+ ** with any left/parent/right pages.
+ */
+ if( pPage->leaf && pPage->intKey ){
+ /* if we are a left child page */
+ if( pnParentMinKey ){
+ /* if we are the left most child page */
+ if( !pnParentMaxKey ){
+ if( nMaxKey > *pnParentMinKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (max larger than parent min of %lld)",
+ nMaxKey, *pnParentMinKey);
+ }
+ }else{
+ if( nMinKey <= *pnParentMinKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (min less than parent min of %lld)",
+ nMinKey, *pnParentMinKey);
+ }
+ if( nMaxKey > *pnParentMaxKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (max larger than parent max of %lld)",
+ nMaxKey, *pnParentMaxKey);
+ }
+ *pnParentMinKey = nMaxKey;
+ }
+ /* else if we're a right child page */
+ } else if( pnParentMaxKey ){
+ if( nMinKey <= *pnParentMaxKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (min less than parent max of %lld)",
+ nMinKey, *pnParentMaxKey);
+ }
+ }
+ }
+
/* Check for complete coverage of the page
*/
data = pPage->aData;
@@ -7529,7 +7580,7 @@ static int checkTreePage(
}
if( (pc+size-1)>=usableSize ){
checkAppendMsg(pCheck, 0,
- "Corruption detected in cell %d on page %d",i,iPage,0);
+ "Corruption detected in cell %d on page %d",i,iPage);
}else{
for(j=pc+size-1; j>=pc; j--) hit[j]++;
}
@@ -7635,7 +7686,7 @@ char *sqlite3BtreeIntegrityCheck(
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
}
#endif
- checkTreePage(&sCheck, aRoot[i], "List of tree roots: ");
+ checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
}
/* Make sure every page in the file is referenced