SQLite

Check-in [549bae0856]
Login

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

Overview
Comment:Enhance "PRAGMA integrity_check" so that it verifies CHECK constraints.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | integrity-check-improvements
Files: files | file ages | folders
SHA1: 549bae0856004ff65b505175460abd598b30fe57
User & Date: drh 2017-02-22 14:15:37.561
Context
2017-02-22
15:11
Fix integrity_check so that it verifies NOT NULL constraints even for tables that have no indexes. Enhance quick_check so that it verifies NOT NULL and CHECK constraints. (check-in: 5264844b06 user: drh tags: integrity-check-improvements)
14:15
Enhance "PRAGMA integrity_check" so that it verifies CHECK constraints. (check-in: 549bae0856 user: drh tags: integrity-check-improvements)
2017-02-21
21:24
In sqlite3VdbeHalt(), return as soon as possible if Vdbe.magic!=VDBE_MAGIC_RUN. This makes sqlite3_reset() slightly faster in some cases. (check-in: 80adc0cb4e user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/pragma.c.
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
        Table *pTab = sqliteHashData(x);
        Index *pIdx, *pPk;
        Index *pPrior = 0;
        int loopTop;
        int iDataCur, iIdxCur;
        int r1 = -1;

        if( pTab->pIndex==0 ) continue;
        pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
        addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);  /* Stop if out of errors */
        VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
        sqlite3VdbeJumpHere(v, addr);
        sqlite3ExprCacheClear(pParse);
        sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,







|







1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
        Table *pTab = sqliteHashData(x);
        Index *pIdx, *pPk;
        Index *pPrior = 0;
        int loopTop;
        int iDataCur, iIdxCur;
        int r1 = -1;

        if( pTab->pIndex==0 && pTab->pCheck==0 ) continue;
        pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
        addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);  /* Stop if out of errors */
        VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
        sqlite3VdbeJumpHere(v, addr);
        sqlite3ExprCacheClear(pParse);
        sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1512
1513
1514
1515
1516
1517
1518

























1519
1520
1521
1522
1523
1524
1525
                              pTab->aCol[j].zName);
          sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
          sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
          jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
          sqlite3VdbeAddOp0(v, OP_Halt);
          sqlite3VdbeJumpHere(v, jmp2);
          sqlite3VdbeJumpHere(v, jmp3);

























        }
        /* Validate index entries for the current row */
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
          int jmp2, jmp3, jmp4, jmp5;
          int ckUniq = sqlite3VdbeMakeLabel(v);
          if( pPk==pIdx ) continue;
          r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
                              pTab->aCol[j].zName);
          sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
          sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
          jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
          sqlite3VdbeAddOp0(v, OP_Halt);
          sqlite3VdbeJumpHere(v, jmp2);
          sqlite3VdbeJumpHere(v, jmp3);
        }
        /* Verify CHECK constraints */
        if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
          int addrCkFault = sqlite3VdbeMakeLabel(v);
          int addrCkOk = sqlite3VdbeMakeLabel(v);
          ExprList *pCheck = pTab->pCheck;
          char *zErr;
          int k;
          pParse->iSelfTab = iDataCur;
          sqlite3ExprCachePush(pParse);
          for(k=pCheck->nExpr-1; k>0; k--){
            sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
          }
          sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, 
                            SQLITE_JUMPIFNULL);
          sqlite3VdbeResolveLabel(v, addrCkFault);
          sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
          zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
                                pTab->zName);
          sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
          sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
          sqlite3VdbeAddOp2(v, OP_IfPos, 1, addrCkOk); VdbeCoverage(v);
          sqlite3VdbeAddOp0(v, OP_Halt);
          sqlite3VdbeResolveLabel(v, addrCkOk);
          sqlite3ExprCachePop(pParse);
        }
        /* Validate index entries for the current row */
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
          int jmp2, jmp3, jmp4, jmp5;
          int ckUniq = sqlite3VdbeMakeLabel(v);
          if( pPk==pIdx ) continue;
          r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
Changes to test/check.test.
305
306
307
308
309
310
311

312
313




314
315
316
317
318
319
320
321
322
323
  }
} {12 -22}
do_test check-4.8 {
  execsql {
    PRAGMA ignore_check_constraints=ON;
    UPDATE t4 SET x=0, y=1;
    SELECT * FROM t4;

  }
} {0 1}




do_test check-4.9 {
  catchsql {
    PRAGMA ignore_check_constraints=OFF;
    UPDATE t4 SET x=0, y=2;
  }
} {1 {CHECK constraint failed: t4}}
ifcapable vacuum {
  do_test check_4.10 {
    catchsql {
      VACUUM







>

|
>
>
>
>


<







305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
  }
} {12 -22}
do_test check-4.8 {
  execsql {
    PRAGMA ignore_check_constraints=ON;
    UPDATE t4 SET x=0, y=1;
    SELECT * FROM t4;
    PRAGMA integrity_check;
  }
} {0 1 ok}
do_execsql_test check-4.8.1 {
  PRAGMA ignore_check_constraints=OFF;
  PRAGMA integrity_check;
} {{CHECK constraint failed in t4}}
do_test check-4.9 {
  catchsql {

    UPDATE t4 SET x=0, y=2;
  }
} {1 {CHECK constraint failed: t4}}
ifcapable vacuum {
  do_test check_4.10 {
    catchsql {
      VACUUM