SQLite

Check-in [e5456049]
Login

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

Overview
Comment:An UPDATE of a table that is indexed by a constant virtual column that uses the one-pass optimization might cause the table seek to be omitted before reaching row DELETE/INSERT. Fix this by coding an extra OP_Column in that circumstance. Ticket [ec8abb025e78f40c]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e54560495926fbb8a2ce829c677a2dd0066e46b7a8d4ada9d8a34a3426959836
User & Date: drh 2019-12-26 23:16:18
Context
2019-12-26
23:40
If an UPSERT can cause an Abort due to a constraint failure, make sure the query planner knows this. Ticket [7c13db5c3bf74001]. (check-in: f14ce948 user: drh tags: trunk)
23:16
An UPDATE of a table that is indexed by a constant virtual column that uses the one-pass optimization might cause the table seek to be omitted before reaching row DELETE/INSERT. Fix this by coding an extra OP_Column in that circumstance. Ticket [ec8abb025e78f40c] (check-in: e5456049 user: drh tags: trunk)
14:36
Fix an assert() in fts5 that could fail if an xSavepoint() call on another vtab fails. Fix for [167b2aac] . (check-in: a5d7f5d2 user: dan tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/update.c.

796
797
798
799
800
801
802
















803
804
805
806
807
808
809
    if( hasFK ){
      sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
    }

    /* Delete the index entries associated with the current record.  */
    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);

















    /* If changing the rowid value, or if there are foreign key constraints
    ** to process, delete the old record. Otherwise, add a noop OP_Delete
    ** to invoke the pre-update hook.
    **
    ** That (regNew==regnewRowid+1) is true is also important for the 
    ** pre-update hook. If the caller invokes preupdate_new(), the returned
    ** value is copied from memory cell (regNewRowid+1+iCol), where iCol







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







796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
    if( hasFK ){
      sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
    }

    /* Delete the index entries associated with the current record.  */
    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    /* If pTab contains one or more virtual columns, then it is possible
    ** (though unlikely) that no OP_Column opcodes have been run against
    ** the table since the OP_SeekDeferred, meaning that there has not been
    ** a seek against the cursor yet.  The OP_Delete opcode and OP_Insert
    ** opcodes that follow will be needing this seek, so code a bogus
    ** OP_Column just to make sure the seek has been done.
    ** See ticket ec8abb025e78f40c 2019-12-26
    */
    if( eOnePass!=ONEPASS_OFF && (pTab->tabFlags & TF_HasVirtual)!=0 ){
      int r1 = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp3(v, OP_Column, iDataCur, 0, r1);
      sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
    }
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */

    /* If changing the rowid value, or if there are foreign key constraints
    ** to process, delete the old record. Otherwise, add a noop OP_Delete
    ** to invoke the pre-update hook.
    **
    ** That (regNew==regnewRowid+1) is true is also important for the 
    ** pre-update hook. If the caller invokes preupdate_new(), the returned
    ** value is copied from memory cell (regNewRowid+1+iCol), where iCol

Changes to test/gencol1.test.

464
465
466
467
468
469
470














471
472
473
474
475
  SELECT a FROM t1 WHERE b='DEF' AND a='def';
} {DEF}
do_execsql_test gencol1-17.50 {
  CREATE INDEX t1bca ON t1(b,c,a);
  SELECT a FROM t1 WHERE b='DEF' AND a='def';
} {DEF}



















finish_test







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





464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  SELECT a FROM t1 WHERE b='DEF' AND a='def';
} {DEF}
do_execsql_test gencol1-17.50 {
  CREATE INDEX t1bca ON t1(b,c,a);
  SELECT a FROM t1 WHERE b='DEF' AND a='def';
} {DEF}

# 2019-12-26 ticket ec8abb025e78f40c
# An index on a virtual column with a constant value (why would anybody
# ever do such a thing?) can cause problems for a one-pass DELETE.
#
reset_db
do_execsql_test gencol1-18.10 {
  CREATE TABLE t0(c0 UNIQUE AS(0), c1, c2);
  INSERT INTO t0(c1) VALUES(0);
  SELECT * FROM t0;
} {0 0 {}}
do_execsql_test gencol1-18.20 {
  UPDATE t0 SET c1=0, c2=0 WHERE c0>=0;
  SELECT * FROM t0;
} {0 0 0}




finish_test