/ Check-in [83913515]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the "PRAGMA integrity_check" command so that it avoids formatting error message context messages until it actually needs to generate an error message. This avoids much formatting, and hence greatly improves the performance of "PRAGMA integrity_check" in the common case when there are no errors. It also makes the code a little smaller.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 83913515830aa850f9e38406f9422d7e88dcab66
User & Date: drh 2014-09-26 02:41:05
Context
2014-09-27
05:00
Reduce the amount of memcpy() required by defragmentPage(). check-in: 3edab995 user: drh tags: defrag-opt
2014-09-26
18:30
Add an assert() to verify the last-row-id for the database just prior to calling a SQL function. check-in: d026f0c9 user: mistachkin tags: trunk
02:41
Fix the "PRAGMA integrity_check" command so that it avoids formatting error message context messages until it actually needs to generate an error message. This avoids much formatting, and hence greatly improves the performance of "PRAGMA integrity_check" in the common case when there are no errors. It also makes the code a little smaller. check-in: 83913515 user: drh tags: trunk
01:10
If an SQL function makes a recursive call to do an INSERT into the same database, make sure that the last_insert_rowid() for that INSERT is recorded. check-in: e93aecc0 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  7876   7876   
  7877   7877   #ifndef SQLITE_OMIT_INTEGRITY_CHECK
  7878   7878   /*
  7879   7879   ** Append a message to the error message string.
  7880   7880   */
  7881   7881   static void checkAppendMsg(
  7882   7882     IntegrityCk *pCheck,
  7883         -  char *zMsg1,
  7884   7883     const char *zFormat,
  7885   7884     ...
  7886   7885   ){
  7887   7886     va_list ap;
         7887  +  char zBuf[200];
  7888   7888     if( !pCheck->mxErr ) return;
  7889   7889     pCheck->mxErr--;
  7890   7890     pCheck->nErr++;
  7891   7891     va_start(ap, zFormat);
  7892   7892     if( pCheck->errMsg.nChar ){
  7893   7893       sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
  7894   7894     }
  7895         -  if( zMsg1 ){
  7896         -    sqlite3StrAccumAppendAll(&pCheck->errMsg, zMsg1);
         7895  +  if( pCheck->zPfx ){
         7896  +    sqlite3_snprintf(sizeof(zBuf), zBuf, pCheck->zPfx, pCheck->v1, pCheck->v2);
         7897  +    sqlite3StrAccumAppendAll(&pCheck->errMsg, zBuf);
  7897   7898     }
  7898   7899     sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
  7899   7900     va_end(ap);
  7900   7901     if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
  7901   7902       pCheck->mallocFailed = 1;
  7902   7903     }
  7903   7904   }
................................................................................
  7927   7928   ** Add 1 to the reference count for page iPage.  If this is the second
  7928   7929   ** reference to the page, add an error message to pCheck->zErrMsg.
  7929   7930   ** Return 1 if there are 2 or more references to the page and 0 if
  7930   7931   ** if this is the first reference to the page.
  7931   7932   **
  7932   7933   ** Also check that the page number is in bounds.
  7933   7934   */
  7934         -static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){
         7935  +static int checkRef(IntegrityCk *pCheck, Pgno iPage){
  7935   7936     if( iPage==0 ) return 1;
  7936   7937     if( iPage>pCheck->nPage ){
  7937         -    checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage);
         7938  +    checkAppendMsg(pCheck, "invalid page number %d", iPage);
  7938   7939       return 1;
  7939   7940     }
  7940   7941     if( getPageReferenced(pCheck, iPage) ){
  7941         -    checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage);
         7942  +    checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
  7942   7943       return 1;
  7943   7944     }
  7944   7945     setPageReferenced(pCheck, iPage);
  7945   7946     return 0;
  7946   7947   }
  7947   7948   
  7948   7949   #ifndef SQLITE_OMIT_AUTOVACUUM
................................................................................
  7951   7952   ** page iParent, pointer type ptrType. If not, append an error message
  7952   7953   ** to pCheck.
  7953   7954   */
  7954   7955   static void checkPtrmap(
  7955   7956     IntegrityCk *pCheck,   /* Integrity check context */
  7956   7957     Pgno iChild,           /* Child page number */
  7957   7958     u8 eType,              /* Expected pointer map type */
  7958         -  Pgno iParent,          /* Expected pointer map parent page number */
  7959         -  char *zContext         /* Context description (used for error msg) */
         7959  +  Pgno iParent           /* Expected pointer map parent page number */
  7960   7960   ){
  7961   7961     int rc;
  7962   7962     u8 ePtrmapType;
  7963   7963     Pgno iPtrmapParent;
  7964   7964   
  7965   7965     rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
  7966   7966     if( rc!=SQLITE_OK ){
  7967   7967       if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
  7968         -    checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild);
         7968  +    checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
  7969   7969       return;
  7970   7970     }
  7971   7971   
  7972   7972     if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
  7973         -    checkAppendMsg(pCheck, zContext, 
         7973  +    checkAppendMsg(pCheck,
  7974   7974         "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", 
  7975   7975         iChild, eType, iParent, ePtrmapType, iPtrmapParent);
  7976   7976     }
  7977   7977   }
  7978   7978   #endif
  7979   7979   
  7980   7980   /*
................................................................................
  7981   7981   ** Check the integrity of the freelist or of an overflow page list.
  7982   7982   ** Verify that the number of pages on the list is N.
  7983   7983   */
  7984   7984   static void checkList(
  7985   7985     IntegrityCk *pCheck,  /* Integrity checking context */
  7986   7986     int isFreeList,       /* True for a freelist.  False for overflow page list */
  7987   7987     int iPage,            /* Page number for first page in the list */
  7988         -  int N,                /* Expected number of pages in the list */
  7989         -  char *zContext        /* Context for error messages */
         7988  +  int N                 /* Expected number of pages in the list */
  7990   7989   ){
  7991   7990     int i;
  7992   7991     int expected = N;
  7993   7992     int iFirst = iPage;
  7994   7993     while( N-- > 0 && pCheck->mxErr ){
  7995   7994       DbPage *pOvflPage;
  7996   7995       unsigned char *pOvflData;
  7997   7996       if( iPage<1 ){
  7998         -      checkAppendMsg(pCheck, zContext,
         7997  +      checkAppendMsg(pCheck,
  7999   7998            "%d of %d pages missing from overflow list starting at %d",
  8000   7999             N+1, expected, iFirst);
  8001   8000         break;
  8002   8001       }
  8003         -    if( checkRef(pCheck, iPage, zContext) ) break;
         8002  +    if( checkRef(pCheck, iPage) ) break;
  8004   8003       if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){
  8005         -      checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage);
         8004  +      checkAppendMsg(pCheck, "failed to get page %d", iPage);
  8006   8005         break;
  8007   8006       }
  8008   8007       pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
  8009   8008       if( isFreeList ){
  8010   8009         int n = get4byte(&pOvflData[4]);
  8011   8010   #ifndef SQLITE_OMIT_AUTOVACUUM
  8012   8011         if( pCheck->pBt->autoVacuum ){
  8013         -        checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext);
         8012  +        checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0);
  8014   8013         }
  8015   8014   #endif
  8016   8015         if( n>(int)pCheck->pBt->usableSize/4-2 ){
  8017         -        checkAppendMsg(pCheck, zContext,
         8016  +        checkAppendMsg(pCheck,
  8018   8017              "freelist leaf count too big on page %d", iPage);
  8019   8018           N--;
  8020   8019         }else{
  8021   8020           for(i=0; i<n; i++){
  8022   8021             Pgno iFreePage = get4byte(&pOvflData[8+i*4]);
  8023   8022   #ifndef SQLITE_OMIT_AUTOVACUUM
  8024   8023             if( pCheck->pBt->autoVacuum ){
  8025         -            checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext);
         8024  +            checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0);
  8026   8025             }
  8027   8026   #endif
  8028         -          checkRef(pCheck, iFreePage, zContext);
         8027  +          checkRef(pCheck, iFreePage);
  8029   8028           }
  8030   8029           N -= n;
  8031   8030         }
  8032   8031       }
  8033   8032   #ifndef SQLITE_OMIT_AUTOVACUUM
  8034   8033       else{
  8035   8034         /* If this database supports auto-vacuum and iPage is not the last
  8036   8035         ** page in this overflow list, check that the pointer-map entry for
  8037   8036         ** the following page matches iPage.
  8038   8037         */
  8039   8038         if( pCheck->pBt->autoVacuum && N>0 ){
  8040   8039           i = get4byte(pOvflData);
  8041         -        checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext);
         8040  +        checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage);
  8042   8041         }
  8043   8042       }
  8044   8043   #endif
  8045   8044       iPage = get4byte(pOvflData);
  8046   8045       sqlite3PagerUnref(pOvflPage);
  8047   8046     }
  8048   8047   }
................................................................................
  8066   8065   **      7.  Verify that the depth of all children is the same.
  8067   8066   **      8.  Make sure this page is at least 33% full or else it is
  8068   8067   **          the root of the tree.
  8069   8068   */
  8070   8069   static int checkTreePage(
  8071   8070     IntegrityCk *pCheck,  /* Context for the sanity check */
  8072   8071     int iPage,            /* Page number of the page to check */
  8073         -  char *zParentContext, /* Parent context */
  8074   8072     i64 *pnParentMinKey, 
  8075   8073     i64 *pnParentMaxKey
  8076   8074   ){
  8077   8075     MemPage *pPage;
  8078   8076     int i, rc, depth, d2, pgno, cnt;
  8079   8077     int hdr, cellStart;
  8080   8078     int nCell;
  8081   8079     u8 *data;
  8082   8080     BtShared *pBt;
  8083   8081     int usableSize;
  8084         -  char zContext[100];
  8085   8082     char *hit = 0;
  8086   8083     i64 nMinKey = 0;
  8087   8084     i64 nMaxKey = 0;
  8088         -
  8089         -  sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
         8085  +  const char *saved_zPfx = pCheck->zPfx;
         8086  +  int saved_v1 = pCheck->v1;
         8087  +  int saved_v2 = pCheck->v2;
  8090   8088   
  8091   8089     /* Check that the page exists
  8092   8090     */
  8093   8091     pBt = pCheck->pBt;
  8094   8092     usableSize = pBt->usableSize;
  8095   8093     if( iPage==0 ) return 0;
  8096         -  if( checkRef(pCheck, iPage, zParentContext) ) return 0;
         8094  +  if( checkRef(pCheck, iPage) ) return 0;
         8095  +  pCheck->zPfx = "Page %d: ";
         8096  +  pCheck->v1 = iPage;
  8097   8097     if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
  8098         -    checkAppendMsg(pCheck, zContext,
         8098  +    checkAppendMsg(pCheck,
  8099   8099          "unable to get the page. error code=%d", rc);
  8100         -    return 0;
         8100  +    depth = -1;
         8101  +    goto end_of_check;
  8101   8102     }
  8102   8103   
  8103   8104     /* Clear MemPage.isInit to make sure the corruption detection code in
  8104   8105     ** btreeInitPage() is executed.  */
  8105   8106     pPage->isInit = 0;
  8106   8107     if( (rc = btreeInitPage(pPage))!=0 ){
  8107   8108       assert( rc==SQLITE_CORRUPT );  /* The only possible error from InitPage */
  8108         -    checkAppendMsg(pCheck, zContext, 
         8109  +    checkAppendMsg(pCheck,
  8109   8110                      "btreeInitPage() returns error code %d", rc);
  8110   8111       releasePage(pPage);
  8111         -    return 0;
         8112  +    depth = -1;
         8113  +    goto end_of_check;
  8112   8114     }
  8113   8115   
  8114   8116     /* Check out all the cells.
  8115   8117     */
  8116   8118     depth = 0;
  8117   8119     for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
  8118   8120       u8 *pCell;
  8119   8121       u32 sz;
  8120   8122       CellInfo info;
  8121   8123   
  8122   8124       /* Check payload overflow pages
  8123   8125       */
  8124         -    sqlite3_snprintf(sizeof(zContext), zContext,
  8125         -             "On tree page %d cell %d: ", iPage, i);
         8126  +    pCheck->zPfx = "On tree page %d cell %d: ";
         8127  +    pCheck->v1 = iPage;
         8128  +    pCheck->v2 = i;
  8126   8129       pCell = findCell(pPage,i);
  8127   8130       btreeParseCellPtr(pPage, pCell, &info);
  8128   8131       sz = info.nPayload;
  8129   8132       /* For intKey pages, check that the keys are in order.
  8130   8133       */
  8131   8134       if( pPage->intKey ){
  8132   8135         if( i==0 ){
  8133   8136           nMinKey = nMaxKey = info.nKey;
  8134   8137         }else if( info.nKey <= nMaxKey ){
  8135         -        checkAppendMsg(pCheck, zContext, 
         8138  +        checkAppendMsg(pCheck,
  8136   8139              "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
  8137   8140         }
  8138   8141         nMaxKey = info.nKey;
  8139   8142       }
  8140   8143       if( (sz>info.nLocal) 
  8141   8144        && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
  8142   8145       ){
  8143   8146         int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
  8144   8147         Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
  8145   8148   #ifndef SQLITE_OMIT_AUTOVACUUM
  8146   8149         if( pBt->autoVacuum ){
  8147         -        checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext);
         8150  +        checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
  8148   8151         }
  8149   8152   #endif
  8150         -      checkList(pCheck, 0, pgnoOvfl, nPage, zContext);
         8153  +      checkList(pCheck, 0, pgnoOvfl, nPage);
  8151   8154       }
  8152   8155   
  8153   8156       /* Check sanity of left child page.
  8154   8157       */
  8155   8158       if( !pPage->leaf ){
  8156   8159         pgno = get4byte(pCell);
  8157   8160   #ifndef SQLITE_OMIT_AUTOVACUUM
  8158   8161         if( pBt->autoVacuum ){
  8159         -        checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
         8162  +        checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
  8160   8163         }
  8161   8164   #endif
  8162         -      d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0?NULL:&nMaxKey);
         8165  +      d2 = checkTreePage(pCheck, pgno, &nMinKey, i==0?NULL:&nMaxKey);
  8163   8166         if( i>0 && d2!=depth ){
  8164         -        checkAppendMsg(pCheck, zContext, "Child page depth differs");
         8167  +        checkAppendMsg(pCheck, "Child page depth differs");
  8165   8168         }
  8166   8169         depth = d2;
  8167   8170       }
  8168   8171     }
  8169   8172   
  8170   8173     if( !pPage->leaf ){
  8171   8174       pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
  8172         -    sqlite3_snprintf(sizeof(zContext), zContext, 
  8173         -                     "On page %d at right child: ", iPage);
         8175  +    pCheck->zPfx = "On page %d at right child: ";
         8176  +    pCheck->v1 = iPage;
  8174   8177   #ifndef SQLITE_OMIT_AUTOVACUUM
  8175   8178       if( pBt->autoVacuum ){
  8176         -      checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
         8179  +      checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
  8177   8180       }
  8178   8181   #endif
  8179         -    checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell?NULL:&nMaxKey);
         8182  +    checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey);
  8180   8183     }
  8181   8184    
  8182   8185     /* For intKey leaf pages, check that the min/max keys are in order
  8183   8186     ** with any left/parent/right pages.
  8184   8187     */
         8188  +  pCheck->zPfx = "Page %d: ";
         8189  +  pCheck->v1 = iPage;
  8185   8190     if( pPage->leaf && pPage->intKey ){
  8186   8191       /* if we are a left child page */
  8187   8192       if( pnParentMinKey ){
  8188   8193         /* if we are the left most child page */
  8189   8194         if( !pnParentMaxKey ){
  8190   8195           if( nMaxKey > *pnParentMinKey ){
  8191         -          checkAppendMsg(pCheck, zContext, 
         8196  +          checkAppendMsg(pCheck,
  8192   8197                 "Rowid %lld out of order (max larger than parent min of %lld)",
  8193   8198                 nMaxKey, *pnParentMinKey);
  8194   8199           }
  8195   8200         }else{
  8196   8201           if( nMinKey <= *pnParentMinKey ){
  8197         -          checkAppendMsg(pCheck, zContext, 
         8202  +          checkAppendMsg(pCheck,
  8198   8203                 "Rowid %lld out of order (min less than parent min of %lld)",
  8199   8204                 nMinKey, *pnParentMinKey);
  8200   8205           }
  8201   8206           if( nMaxKey > *pnParentMaxKey ){
  8202         -          checkAppendMsg(pCheck, zContext, 
         8207  +          checkAppendMsg(pCheck,
  8203   8208                 "Rowid %lld out of order (max larger than parent max of %lld)",
  8204   8209                 nMaxKey, *pnParentMaxKey);
  8205   8210           }
  8206   8211           *pnParentMinKey = nMaxKey;
  8207   8212         }
  8208   8213       /* else if we're a right child page */
  8209   8214       } else if( pnParentMaxKey ){
  8210   8215         if( nMinKey <= *pnParentMaxKey ){
  8211         -        checkAppendMsg(pCheck, zContext, 
         8216  +        checkAppendMsg(pCheck,
  8212   8217               "Rowid %lld out of order (min less than parent max of %lld)",
  8213   8218               nMinKey, *pnParentMaxKey);
  8214   8219         }
  8215   8220       }
  8216   8221     }
  8217   8222   
  8218   8223     /* Check for complete coverage of the page
  8219   8224     */
  8220   8225     data = pPage->aData;
  8221   8226     hdr = pPage->hdrOffset;
  8222   8227     hit = sqlite3PageMalloc( pBt->pageSize );
         8228  +  pCheck->zPfx = 0;
  8223   8229     if( hit==0 ){
  8224   8230       pCheck->mallocFailed = 1;
  8225   8231     }else{
  8226   8232       int contentOffset = get2byteNotZero(&data[hdr+5]);
  8227   8233       assert( contentOffset<=usableSize );  /* Enforced by btreeInitPage() */
  8228   8234       memset(hit+contentOffset, 0, usableSize-contentOffset);
  8229   8235       memset(hit, 1, contentOffset);
................................................................................
  8233   8239         int pc = get2byte(&data[cellStart+i*2]);
  8234   8240         u32 size = 65536;
  8235   8241         int j;
  8236   8242         if( pc<=usableSize-4 ){
  8237   8243           size = cellSizePtr(pPage, &data[pc]);
  8238   8244         }
  8239   8245         if( (int)(pc+size-1)>=usableSize ){
  8240         -        checkAppendMsg(pCheck, 0, 
         8246  +        pCheck->zPfx = 0;
         8247  +        checkAppendMsg(pCheck,
  8241   8248               "Corruption detected in cell %d on page %d",i,iPage);
  8242   8249         }else{
  8243   8250           for(j=pc+size-1; j>=pc; j--) hit[j]++;
  8244   8251         }
  8245   8252       }
  8246   8253       i = get2byte(&data[hdr+1]);
  8247   8254       while( i>0 ){
................................................................................
  8255   8262         assert( j<=usableSize-4 );   /* Enforced by btreeInitPage() */
  8256   8263         i = j;
  8257   8264       }
  8258   8265       for(i=cnt=0; i<usableSize; i++){
  8259   8266         if( hit[i]==0 ){
  8260   8267           cnt++;
  8261   8268         }else if( hit[i]>1 ){
  8262         -        checkAppendMsg(pCheck, 0,
         8269  +        checkAppendMsg(pCheck,
  8263   8270             "Multiple uses for byte %d of page %d", i, iPage);
  8264   8271           break;
  8265   8272         }
  8266   8273       }
  8267   8274       if( cnt!=data[hdr+7] ){
  8268         -      checkAppendMsg(pCheck, 0, 
         8275  +      checkAppendMsg(pCheck,
  8269   8276             "Fragmentation of %d bytes reported as %d on page %d",
  8270   8277             cnt, data[hdr+7], iPage);
  8271   8278       }
  8272   8279     }
  8273   8280     sqlite3PageFree(hit);
  8274   8281     releasePage(pPage);
         8282  +
         8283  +end_of_check:
         8284  +  pCheck->zPfx = saved_zPfx;
         8285  +  pCheck->v1 = saved_v1;
         8286  +  pCheck->v2 = saved_v2;
  8275   8287     return depth+1;
  8276   8288   }
  8277   8289   #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
  8278   8290   
  8279   8291   #ifndef SQLITE_OMIT_INTEGRITY_CHECK
  8280   8292   /*
  8281   8293   ** This routine does a complete check of the given BTree file.  aRoot[] is
................................................................................
  8308   8320     nRef = sqlite3PagerRefcount(pBt->pPager);
  8309   8321     sCheck.pBt = pBt;
  8310   8322     sCheck.pPager = pBt->pPager;
  8311   8323     sCheck.nPage = btreePagecount(sCheck.pBt);
  8312   8324     sCheck.mxErr = mxErr;
  8313   8325     sCheck.nErr = 0;
  8314   8326     sCheck.mallocFailed = 0;
         8327  +  sCheck.zPfx = 0;
         8328  +  sCheck.v1 = 0;
         8329  +  sCheck.v2 = 0;
  8315   8330     *pnErr = 0;
  8316   8331     if( sCheck.nPage==0 ){
  8317   8332       sqlite3BtreeLeave(p);
  8318   8333       return 0;
  8319   8334     }
  8320   8335   
  8321   8336     sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
................................................................................
  8327   8342     i = PENDING_BYTE_PAGE(pBt);
  8328   8343     if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
  8329   8344     sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
  8330   8345     sCheck.errMsg.useMalloc = 2;
  8331   8346   
  8332   8347     /* Check the integrity of the freelist
  8333   8348     */
         8349  +  sCheck.zPfx = "Main freelist: ";
  8334   8350     checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
  8335         -            get4byte(&pBt->pPage1->aData[36]), "Main freelist: ");
         8351  +            get4byte(&pBt->pPage1->aData[36]));
         8352  +  sCheck.zPfx = 0;
  8336   8353   
  8337   8354     /* Check all the tables.
  8338   8355     */
  8339   8356     for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
  8340   8357       if( aRoot[i]==0 ) continue;
  8341   8358   #ifndef SQLITE_OMIT_AUTOVACUUM
  8342   8359       if( pBt->autoVacuum && aRoot[i]>1 ){
  8343         -      checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
         8360  +      checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
  8344   8361       }
  8345   8362   #endif
  8346         -    checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
         8363  +    sCheck.zPfx = "List of tree roots: ";
         8364  +    checkTreePage(&sCheck, aRoot[i], NULL, NULL);
         8365  +    sCheck.zPfx = 0;
  8347   8366     }
  8348   8367   
  8349   8368     /* Make sure every page in the file is referenced
  8350   8369     */
  8351   8370     for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
  8352   8371   #ifdef SQLITE_OMIT_AUTOVACUUM
  8353   8372       if( getPageReferenced(&sCheck, i)==0 ){
  8354         -      checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
         8373  +      checkAppendMsg(&sCheck, "Page %d is never used", i);
  8355   8374       }
  8356   8375   #else
  8357   8376       /* If the database supports auto-vacuum, make sure no tables contain
  8358   8377       ** references to pointer-map pages.
  8359   8378       */
  8360   8379       if( getPageReferenced(&sCheck, i)==0 && 
  8361   8380          (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
  8362         -      checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
         8381  +      checkAppendMsg(&sCheck, "Page %d is never used", i);
  8363   8382       }
  8364   8383       if( getPageReferenced(&sCheck, i)!=0 && 
  8365   8384          (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
  8366         -      checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i);
         8385  +      checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
  8367   8386       }
  8368   8387   #endif
  8369   8388     }
  8370   8389   
  8371   8390     /* Make sure this analysis did not leave any unref() pages.
  8372   8391     ** This is an internal consistency check; an integrity check
  8373   8392     ** of the integrity check.
  8374   8393     */
  8375   8394     if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){
  8376         -    checkAppendMsg(&sCheck, 0, 
         8395  +    checkAppendMsg(&sCheck,
  8377   8396         "Outstanding page count goes from %d to %d during this analysis",
  8378   8397         nRef, sqlite3PagerRefcount(pBt->pPager)
  8379   8398       );
  8380   8399     }
  8381   8400   
  8382   8401     /* Clean  up and report errors.
  8383   8402     */

Changes to src/btreeInt.h.

   653    653     BtShared *pBt;    /* The tree being checked out */
   654    654     Pager *pPager;    /* The associated pager.  Also accessible by pBt->pPager */
   655    655     u8 *aPgRef;       /* 1 bit per page in the db (see above) */
   656    656     Pgno nPage;       /* Number of pages in the database */
   657    657     int mxErr;        /* Stop accumulating errors when this reaches zero */
   658    658     int nErr;         /* Number of messages written to zErrMsg so far */
   659    659     int mallocFailed; /* A memory allocation error has occurred */
          660  +  const char *zPfx; /* Error message prefix */
          661  +  int v1, v2;       /* Values for up to two %d fields in zPfx */
   660    662     StrAccum errMsg;  /* Accumulate the error message text here */
   661    663   };
   662    664   
   663    665   /*
   664    666   ** Routines to read or write a two- and four-byte big-endian integer values.
   665    667   */
   666    668   #define get2byte(x)   ((x)[0]<<8 | (x)[1])
   667    669   #define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v))
   668    670   #define get4byte sqlite3Get4byte
   669    671   #define put4byte sqlite3Put4byte