/ Check-in [8fa923ca]
Login

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

Overview
Comment:Improved detection of malformed records by PRAGMA integrity_check.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | improved-integrity-check
Files: files | file ages | folders
SHA3-256: 8fa923caa1535fc9ebed0214d211fc3d09a015d78afd01f288c215a7980d25f2
User & Date: drh 2017-09-09 20:38:49
Context
2017-09-09
22:46
Simplification and performance improvement to sqlite3_reset(). check-in: b6425d01 user: drh tags: improved-integrity-check
20:38
Improved detection of malformed records by PRAGMA integrity_check. check-in: 8fa923ca user: drh tags: improved-integrity-check
00:51
Fix harmless compiler warnings seen with MSVC. check-in: faa22e29 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pragma.c.

  1545   1545           Index *pIdx, *pPk;
  1546   1546           Index *pPrior = 0;
  1547   1547           int loopTop;
  1548   1548           int iDataCur, iIdxCur;
  1549   1549           int r1 = -1;
  1550   1550   
  1551   1551           if( pTab->tnum<1 ) continue;  /* Skip VIEWs or VIRTUAL TABLEs */
  1552         -        if( pTab->pCheck==0
  1553         -         && (pTab->tabFlags & TF_HasNotNull)==0
  1554         -         && (pTab->pIndex==0 || isQuick)
  1555         -        ){
  1556         -          continue;  /* No additional checks needed for this table */
  1557         -        }
  1558   1552           pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
  1559   1553           sqlite3ExprCacheClear(pParse);
  1560   1554           sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
  1561   1555                                      1, 0, &iDataCur, &iIdxCur);
  1562   1556           sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
  1563   1557           for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
  1564   1558             sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
................................................................................
  1579   1573             zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
  1580   1574                                 pTab->aCol[j].zName);
  1581   1575             sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
  1582   1576             integrityCheckResultRow(v, 3);
  1583   1577             sqlite3VdbeJumpHere(v, jmp2);
  1584   1578           }
  1585   1579           /* Verify CHECK constraints */
  1586         -        sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
  1587   1580           if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
  1588   1581             ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
  1589   1582             if( db->mallocFailed==0 ){
  1590   1583               int addrCkFault = sqlite3VdbeMakeLabel(v);
  1591   1584               int addrCkOk = sqlite3VdbeMakeLabel(v);
  1592   1585               char *zErr;
  1593   1586               int k;
................................................................................
  1605   1598               sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
  1606   1599               integrityCheckResultRow(v, 3);
  1607   1600               sqlite3VdbeResolveLabel(v, addrCkOk);
  1608   1601               sqlite3ExprCachePop(pParse);
  1609   1602             }
  1610   1603             sqlite3ExprListDelete(db, pCheck);
  1611   1604           }
  1612         -        /* Validate index entries for the current row */
  1613         -        for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){
  1614         -          int jmp2, jmp3, jmp4, jmp5;
  1615         -          int ckUniq = sqlite3VdbeMakeLabel(v);
  1616         -          if( pPk==pIdx ) continue;
  1617         -          r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
  1618         -                                       pPrior, r1);
  1619         -          pPrior = pIdx;
  1620         -          sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);  /* increment entry count */
  1621         -          /* Verify that an index entry exists for the current table row */
  1622         -          jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
  1623         -                                      pIdx->nColumn); VdbeCoverage(v);
  1624         -          sqlite3VdbeLoadString(v, 3, "row ");
  1625         -          sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
  1626         -          sqlite3VdbeLoadString(v, 4, " missing from index ");
  1627         -          sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
  1628         -          jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
  1629         -          sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
  1630         -          jmp4 = integrityCheckResultRow(v, 3);
  1631         -          sqlite3VdbeJumpHere(v, jmp2);
  1632         -          /* For UNIQUE indexes, verify that only one entry exists with the
  1633         -          ** current key.  The entry is unique if (1) any column is NULL
  1634         -          ** or (2) the next entry has a different key */
  1635         -          if( IsUniqueIndex(pIdx) ){
  1636         -            int uniqOk = sqlite3VdbeMakeLabel(v);
  1637         -            int jmp6;
  1638         -            int kk;
  1639         -            for(kk=0; kk<pIdx->nKeyCol; kk++){
  1640         -              int iCol = pIdx->aiColumn[kk];
  1641         -              assert( iCol!=XN_ROWID && iCol<pTab->nCol );
  1642         -              if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
  1643         -              sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
  1644         -              VdbeCoverage(v);
         1605  +        if( !isQuick ){ /* Omit the remaining tests for quick_check */
         1606  +          /* Sanity check on record header decoding */
         1607  +          sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
         1608  +          sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
         1609  +          /* Validate index entries for the current row */
         1610  +          for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
         1611  +            int jmp2, jmp3, jmp4, jmp5;
         1612  +            int ckUniq = sqlite3VdbeMakeLabel(v);
         1613  +            if( pPk==pIdx ) continue;
         1614  +            r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
         1615  +                                         pPrior, r1);
         1616  +            pPrior = pIdx;
         1617  +            sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
         1618  +            /* Verify that an index entry exists for the current table row */
         1619  +            jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
         1620  +                                        pIdx->nColumn); VdbeCoverage(v);
         1621  +            sqlite3VdbeLoadString(v, 3, "row ");
         1622  +            sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
         1623  +            sqlite3VdbeLoadString(v, 4, " missing from index ");
         1624  +            sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
         1625  +            jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
         1626  +            sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
         1627  +            jmp4 = integrityCheckResultRow(v, 3);
         1628  +            sqlite3VdbeJumpHere(v, jmp2);
         1629  +            /* For UNIQUE indexes, verify that only one entry exists with the
         1630  +            ** current key.  The entry is unique if (1) any column is NULL
         1631  +            ** or (2) the next entry has a different key */
         1632  +            if( IsUniqueIndex(pIdx) ){
         1633  +              int uniqOk = sqlite3VdbeMakeLabel(v);
         1634  +              int jmp6;
         1635  +              int kk;
         1636  +              for(kk=0; kk<pIdx->nKeyCol; kk++){
         1637  +                int iCol = pIdx->aiColumn[kk];
         1638  +                assert( iCol!=XN_ROWID && iCol<pTab->nCol );
         1639  +                if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
         1640  +                sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
         1641  +                VdbeCoverage(v);
         1642  +              }
         1643  +              jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
         1644  +              sqlite3VdbeGoto(v, uniqOk);
         1645  +              sqlite3VdbeJumpHere(v, jmp6);
         1646  +              sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
         1647  +                                   pIdx->nKeyCol); VdbeCoverage(v);
         1648  +              sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
         1649  +              sqlite3VdbeGoto(v, jmp5);
         1650  +              sqlite3VdbeResolveLabel(v, uniqOk);
  1645   1651               }
  1646         -            jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
  1647         -            sqlite3VdbeGoto(v, uniqOk);
  1648         -            sqlite3VdbeJumpHere(v, jmp6);
  1649         -            sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
  1650         -                                 pIdx->nKeyCol); VdbeCoverage(v);
  1651         -            sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
  1652         -            sqlite3VdbeGoto(v, jmp5);
  1653         -            sqlite3VdbeResolveLabel(v, uniqOk);
         1652  +            sqlite3VdbeJumpHere(v, jmp4);
         1653  +            sqlite3ResolvePartIdxLabel(pParse, jmp3);
  1654   1654             }
  1655         -          sqlite3VdbeJumpHere(v, jmp4);
  1656         -          sqlite3ResolvePartIdxLabel(pParse, jmp3);
  1657   1655           }
  1658   1656           sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
  1659   1657           sqlite3VdbeJumpHere(v, loopTop-1);
  1660   1658   #ifndef SQLITE_OMIT_BTREECOUNT
  1661   1659           if( !isQuick ){
  1662   1660             sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
  1663   1661             for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){