SQLite

Check-in [f7aadfab]
Login

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

Overview
Comment:Disable index seek optimizations on REINDEX when the order of primary keys in the index differs from the main table. Fix for ticket [bba7b69f9849b5bf11b4].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: f7aadfab3bb8eb8eb2cd62dc8a6823538387b3329f1efc23ef75482488109478
User & Date: drh 2019-05-14 00:43:13
Context
2019-05-14
11:33
Fix an assert() and potential buffer overrun in fts5 that could occur if the database was corrupt. (check-in: 8be8bd0d user: dan tags: trunk)
00:43
Disable index seek optimizations on REINDEX when the order of primary keys in the index differs from the main table. Fix for ticket [bba7b69f9849b5bf11b4]. (check-in: f7aadfab user: drh tags: trunk)
2019-05-13
11:52
Fix an assert() failure in fts5 that could occur when processing a corrupt database. (check-in: f158c048 user: dan tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

1924
1925
1926
1927
1928
1929
1930




1931
1932
1933
1934
1935
1936
1937
    }
    if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
    for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
      if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){
        testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
        pIdx->aiColumn[j] = pPk->aiColumn[i];
        pIdx->azColl[j] = pPk->azColl[i];




        j++;
      }
    }
    assert( pIdx->nColumn>=pIdx->nKeyCol+n );
    assert( pIdx->nColumn>=j );
  }








>
>
>
>







1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
    }
    if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
    for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
      if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){
        testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
        pIdx->aiColumn[j] = pPk->aiColumn[i];
        pIdx->azColl[j] = pPk->azColl[i];
        if( pPk->aSortOrder[i] ){
          /* See ticket https://www.sqlite.org/src/info/bba7b69f9849b5bf */
          pIdx->bAscKeyBug = 1;
        }
        j++;
      }
    }
    assert( pIdx->nColumn>=pIdx->nKeyCol+n );
    assert( pIdx->nColumn>=j );
  }

3045
3046
3047
3048
3049
3050
3051








3052

3053
3054
3055
3056
3057
3058
3059
                         pIndex->nKeyCol); VdbeCoverage(v);
    sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
    sqlite3VdbeJumpHere(v, j2);
  }else{
    addr2 = sqlite3VdbeCurrentAddr(v);
  }
  sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);








  sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);

  sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
  sqlite3VdbeJumpHere(v, addr1);

  sqlite3VdbeAddOp1(v, OP_Close, iTab);







>
>
>
>
>
>
>
>
|
>







3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
                         pIndex->nKeyCol); VdbeCoverage(v);
    sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
    sqlite3VdbeJumpHere(v, j2);
  }else{
    addr2 = sqlite3VdbeCurrentAddr(v);
  }
  sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
  if( !pIndex->bAscKeyBug ){
    /* This OP_SeekEnd opcode makes index insert for a REINDEX go much
    ** faster by avoiding unnecessary seeks.  But the optimization does
    ** not work for UNIQUE constraint indexes on WITHOUT ROWID tables
    ** with DESC primary keys, since those indexes have there keys in
    ** a different order from the main table.
    ** See ticket: https://www.sqlite.org/src/info/bba7b69f9849b5bf
    */
    sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
  }
  sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
  sqlite3VdbeJumpHere(v, addr1);

  sqlite3VdbeAddOp1(v, OP_Close, iTab);

Changes to src/sqliteInt.h.

2249
2250
2251
2252
2253
2254
2255

2256
2257
2258
2259
2260
2261
2262
  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
  unsigned uniqNotNull:1;  /* True if UNIQUE and NOT NULL for all columns */
  unsigned isResized:1;    /* True if resizeIndexObject() has been called */
  unsigned isCovering:1;   /* True if this is a covering index */
  unsigned noSkipScan:1;   /* Do not try to use skip-scan if true */
  unsigned hasStat1:1;     /* aiRowLogEst values come from sqlite_stat1 */
  unsigned bNoQuery:1;     /* Do not use this index to optimize queries */

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  int nSample;             /* Number of elements in aSample[] */
  int nSampleCol;          /* Size of IndexSample.anEq[] and so on */
  tRowcnt *aAvgEq;         /* Average nEq values for keys not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
  tRowcnt *aiRowEst;       /* Non-logarithmic stat1 data for this index */
  tRowcnt nRowEst0;        /* Non-logarithmic number of rows in the index */







>







2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
  unsigned uniqNotNull:1;  /* True if UNIQUE and NOT NULL for all columns */
  unsigned isResized:1;    /* True if resizeIndexObject() has been called */
  unsigned isCovering:1;   /* True if this is a covering index */
  unsigned noSkipScan:1;   /* Do not try to use skip-scan if true */
  unsigned hasStat1:1;     /* aiRowLogEst values come from sqlite_stat1 */
  unsigned bNoQuery:1;     /* Do not use this index to optimize queries */
  unsigned bAscKeyBug:1;   /* True if the bba7b69f9849b5bf bug applies */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  int nSample;             /* Number of elements in aSample[] */
  int nSampleCol;          /* Size of IndexSample.anEq[] and so on */
  tRowcnt *aAvgEq;         /* Average nEq values for keys not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
  tRowcnt *aiRowEst;       /* Non-logarithmic stat1 data for this index */
  tRowcnt nRowEst0;        /* Non-logarithmic number of rows in the index */

Changes to test/without_rowid1.test.

395
396
397
398
399
400
401










402
403
do_execsql_test 11.1 {
  CREATE TABLE t11(a TEXT PRIMARY KEY, b INT) WITHOUT ROWID;
  CREATE INDEX t11a ON t11(a COLLATE NOCASE);
  INSERT INTO t11(a,b) VALUES ('A',1),('a',2);
  PRAGMA integrity_check;
  SELECT a FROM t11 ORDER BY a COLLATE binary;
} {ok A a}










  
finish_test







>
>
>
>
>
>
>
>
>
>


395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
do_execsql_test 11.1 {
  CREATE TABLE t11(a TEXT PRIMARY KEY, b INT) WITHOUT ROWID;
  CREATE INDEX t11a ON t11(a COLLATE NOCASE);
  INSERT INTO t11(a,b) VALUES ('A',1),('a',2);
  PRAGMA integrity_check;
  SELECT a FROM t11 ORDER BY a COLLATE binary;
} {ok A a}

# 2019-05-13 ticket https://www.sqlite.org/src/info/bba7b69f9849b5b
do_execsql_test 12.1 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0 (c0 INTEGER PRIMARY KEY DESC, c1 UNIQUE DEFAULT NULL) WITHOUT ROWID;
  INSERT INTO t0(c0) VALUES (1), (2), (3), (4), (5);
  REINDEX;
  PRAGMA integrity_check;
} {ok}

  
finish_test