/ Check-in [41cc8e3d]
Login

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

Overview
Comment:Add missing VdbeCoverage() macro. Fix an off-by-one error in partial index handling. New test cases. Ticket [c1e19e12046d23fe]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 41cc8e3dab998f7efc898d18837ca7fdac94ea3f89954990c5231456bf725fee
User & Date: drh 2019-10-26 01:43:14
Context
2019-10-26
12:27
Overnight, OSSFuzz helpfully pointed out a potential use-after-free bug in yesterdays changes, involving continued use of a pointer after the memory pointed to had been realloc()-ed. Thanks Google. check-in: c422afb5 user: drh tags: trunk
01:43
Add missing VdbeCoverage() macro. Fix an off-by-one error in partial index handling. New test cases. Ticket [c1e19e12046d23fe] check-in: 41cc8e3d user: drh tags: trunk
00:04
If replace triggers are run during uniqueness checking, then rerun all uniqueness checks a second time using the ABORT algorithm. Fix for ticket [c1e19e12046d23fe] check-in: fbac0c65 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/insert.c.

1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
....
1918
1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
          ** checks have run, if and only if one or more replace triggers
          ** fired. */
          sqlite3VdbeResolveLabel(v, lblRecheckOk);
          lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
          if( pIdx->pPartIdxWhere ){
            /* Bypass the recheck if this partial index is not defined
            ** for the current row */
            sqlite3VdbeAddOp2(v, OP_IsNull, regIdx, lblRecheckOk);
            VdbeCoverage(v);
          }
          /* Copy the constraint check code from above, except change
          ** the constraint-ok jump destination to be the address of
          ** the next retest block */
          pOp = sqlite3VdbeGetOp(v, addrConflictCk);
          while( nConflictCk>0 && !db->mallocFailed ){
................................................................................
            }else{
              p2 = pOp->p2;
            }
            if( pOp->opcode!=OP_IdxRowid ){
              sqlite3VdbeAddOp4(v, pOp->opcode, pOp->p1, p2, pOp->p3,
                                pOp->p4.z, pOp->p4type);
              sqlite3VdbeChangeP5(v, pOp->p5);

            }
            nConflictCk--;
            pOp++;
          }
          /* If the retest fails, issue an abort */
          sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);








|







 







>







1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
....
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
          ** checks have run, if and only if one or more replace triggers
          ** fired. */
          sqlite3VdbeResolveLabel(v, lblRecheckOk);
          lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
          if( pIdx->pPartIdxWhere ){
            /* Bypass the recheck if this partial index is not defined
            ** for the current row */
            sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk);
            VdbeCoverage(v);
          }
          /* Copy the constraint check code from above, except change
          ** the constraint-ok jump destination to be the address of
          ** the next retest block */
          pOp = sqlite3VdbeGetOp(v, addrConflictCk);
          while( nConflictCk>0 && !db->mallocFailed ){
................................................................................
            }else{
              p2 = pOp->p2;
            }
            if( pOp->opcode!=OP_IdxRowid ){
              sqlite3VdbeAddOp4(v, pOp->opcode, pOp->p1, p2, pOp->p3,
                                pOp->p4.z, pOp->p4type);
              sqlite3VdbeChangeP5(v, pOp->p5);
              VdbeCoverageIf(v, p2!=pOp->p2 );
            }
            nConflictCk--;
            pOp++;
          }
          /* If the retest fails, issue an abort */
          sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);

Changes to test/insert.test.

511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
...
538
539
540
541
542
543
544









































545














546

547
  CREATE TABLE p1(a, b UNIQUE);
  CREATE TABLE c1(c, d REFERENCES p1(b) ON DELETE CASCADE);
  CREATE TRIGGER tr6 AFTER DELETE ON c1 BEGIN
    INSERT INTO p1 VALUES(4, 1);
  END;
  INSERT INTO p1 VALUES(1, 1);
  INSERT INTO c1 VALUES(2, 1);
  REPLACE INTO p1 VALUES(3, 1);
} {1 {UNIQUE constraint failed: p1.b}}
integrity_check insert-16.7

# 2019-10-25 ticket c1e19e12046d23fe
do_catchsql_test insert-17.1 {
  PRAGMA temp.recursive_triggers = true;
  DROP TABLE IF EXISTS t0;
................................................................................
  INSERT INTO t1(a,b,c) VALUES(1,1,1),(2,2,2),(3,3,3),(4,4,4);
  CREATE TRIGGER "r17.3" AFTER DELETE ON t1 WHEN OLD.c<>3 BEGIN
    INSERT INTO t1(rowid,a,b,c) VALUES(100,100,100,3);
  END;
  REPLACE INTO t1(rowid,a,b,c) VALUES(200,1,2,3);
} {1 {UNIQUE constraint failed: t1.c}}
integrity_check insert-17.4


























































finish_test







|







 







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

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

>

511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
...
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
  CREATE TABLE p1(a, b UNIQUE);
  CREATE TABLE c1(c, d REFERENCES p1(b) ON DELETE CASCADE);
  CREATE TRIGGER tr6 AFTER DELETE ON c1 BEGIN
    INSERT INTO p1 VALUES(4, 1);
  END;
  INSERT INTO p1 VALUES(1, 1);
  INSERT INTO c1 VALUES(2, 1);
  REPLACE INTO p1 VALUES(3, 1);2
} {1 {UNIQUE constraint failed: p1.b}}
integrity_check insert-16.7

# 2019-10-25 ticket c1e19e12046d23fe
do_catchsql_test insert-17.1 {
  PRAGMA temp.recursive_triggers = true;
  DROP TABLE IF EXISTS t0;
................................................................................
  INSERT INTO t1(a,b,c) VALUES(1,1,1),(2,2,2),(3,3,3),(4,4,4);
  CREATE TRIGGER "r17.3" AFTER DELETE ON t1 WHEN OLD.c<>3 BEGIN
    INSERT INTO t1(rowid,a,b,c) VALUES(100,100,100,3);
  END;
  REPLACE INTO t1(rowid,a,b,c) VALUES(200,1,2,3);
} {1 {UNIQUE constraint failed: t1.c}}
integrity_check insert-17.4
do_execsql_test insert-17.5 {
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
  CREATE UNIQUE INDEX t2b ON t2(b);
  INSERT INTO t2(a,b) VALUES(1,1),(2,2),(3,3),(4,4);
  CREATE TABLE fire(x);
  CREATE TRIGGER t2r1 AFTER DELETE ON t2 BEGIN
    INSERT INTO fire VALUES(old.a);
  END;
  UPDATE OR REPLACE t2 SET a=4, b=3 WHERE a=1;
  SELECT *, 'x' FROM t2 ORDER BY a;
} {2 2 x 4 3 x}
do_execsql_test insert-17.6 {
  SELECT x FROM fire ORDER BY x;
} {3 4}
do_execsql_test insert-17.7 {
  DELETE FROM t2;
  DELETE FROM fire;
  INSERT INTO t2(a,b) VALUES(1,1),(2,2),(3,3),(4,4);
  UPDATE OR REPLACE t2 SET a=1, b=3 WHERE a=1;
  SELECT *, 'x' FROM t2 ORDER BY a;
} {1 3 x 2 2 x 4 4 x}
do_execsql_test insert-17.8 {
  SELECT x FROM fire ORDER BY x;
} {3}
do_execsql_test insert-17.10 {
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b INT, c INT, d INT);
  CREATE UNIQUE INDEX t3bpi ON t3(b) WHERE c<=d;
  CREATE UNIQUE INDEX t3d ON t3(d);
  INSERT INTO t3(a,b,c,d) VALUES(1,1,1,1),(2,1,3,2),(3,4,5,6);
  CREATE TRIGGER t3r1 AFTER DELETE ON t3 BEGIN
    SELECT 'hi';
  END;
  REPLACE INTO t3(a,b,c,d) VALUES(4,4,8,9);
} {}
do_execsql_test insert-17.11 {
  SELECT *, 'x' FROM t3 ORDER BY a;
} {1 1 1 1 x 2 1 3 2 x 4 4 8 9 x}
do_execsql_test insert-17.12 {
  REPLACE INTO t3(a,b,c,d) VALUES(5,1,11,2);
  SELECT *, 'x' FROM t3 ORDER BY a;
} {1 1 1 1 x 4 4 8 9 x 5 1 11 2 x}

do_execsql_test insert-17.13 {
  DELETE FROM t3;
  INSERT INTO t3(a,b,c,d) VALUES(1,1,1,1),(2,1,3,2),(3,4,5,6);
  DROP TRIGGER t3r1;
  CREATE TRIGGER t3r1 AFTER DELETE ON t3 BEGIN
    INSERT INTO t3(b,c,d) VALUES(old.b,old.c,old.d);
  END;
} {}
do_catchsql_test insert-17.14 {
  REPLACE INTO t3(a,b,c,d) VALUES(4,4,8,9);
} {1 {UNIQUE constraint failed: t3.b}}
do_catchsql_test insert-17.15 {
  REPLACE INTO t3(a,b,c,d) VALUES(5,1,11,2);
} {1 {UNIQUE constraint failed: t3.d}}


finish_test