SQLite

Check-in [13c8c60b]
Login

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

Overview
Comment:Fix byte-code register allocation in ANALYZE for STAT4 when there multiple indexes with differing numbers of columns.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | branch-3.41
Files: files | file ages | folders
SHA3-256: 13c8c60bb6b4447b52895dd63a4dffafa23b0aa05f37ce8d78896b638b385db6
User & Date: drh 2023-03-24 17:01:29
References
2023-03-25
18:33
The fix at [13c8c60bb6b4447b] was incomplete in that it failed to clear the reusable register cache that might contain registers in the STAT4 buffer region. This additional change corrects the problem. (check-in: 671bf6f5 user: drh tags: branch-3.41)
Context
2023-03-24
20:39
Fix the handling of indexed expressions in an outer query that appear as corelated values inside an aggregate function within a subquery. (check-in: 76b90f26 user: drh tags: branch-3.41)
17:01
Fix byte-code register allocation in ANALYZE for STAT4 when there multiple indexes with differing numbers of columns. (check-in: 13c8c60b user: drh tags: branch-3.41)
16:57
Fix byte-code register allocation in ANALYZE for STAT4 when there multiple indexes with differing numbers of columns. forum post bc39e531e5. This problem arose when expression indexes were added by check-in [2131a5ca53f0e9b0]. (check-in: 2bf5413d user: drh tags: trunk)
2023-03-23
10:58
The attempt to bring STAT4 up to 100% MC/DC at [55a26c67ed4a3a93] and at [168fa2fb22b8c1ad] are incorrect. Back them out and replace them with a simple NEVER() macro. Error reported by forum post dc4854437b. (check-in: 76e683c5 user: drh tags: branch-3.41)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/analyze.c.

990
991
992
993
994
995
996



997
998
999
1000
1001
1002
1003
1004
1005
  int regRowid = iMem++;       /* Rowid argument passed to stat_push() */
  int regTemp = iMem++;        /* Temporary use register */
  int regTemp2 = iMem++;       /* Second temporary use register */
  int regTabname = iMem++;     /* Register containing table name */
  int regIdxname = iMem++;     /* Register containing index name */
  int regStat1 = iMem++;       /* Value for the stat column of sqlite_stat1 */
  int regPrev = iMem;          /* MUST BE LAST (see below) */



#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  Table *pStat1 = 0; 
#endif

  pParse->nMem = MAX(pParse->nMem, iMem);
  v = sqlite3GetVdbe(pParse);
  if( v==0 || NEVER(pTab==0) ){
    return;
  }







>
>
>

|







990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  int regRowid = iMem++;       /* Rowid argument passed to stat_push() */
  int regTemp = iMem++;        /* Temporary use register */
  int regTemp2 = iMem++;       /* Second temporary use register */
  int regTabname = iMem++;     /* Register containing table name */
  int regIdxname = iMem++;     /* Register containing index name */
  int regStat1 = iMem++;       /* Value for the stat column of sqlite_stat1 */
  int regPrev = iMem;          /* MUST BE LAST (see below) */
#ifdef SQLITE_ENABLE_STAT4
  int doOnce = 1;              /* Flag for a one-time computation */
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  Table *pStat1 = 0;
#endif

  pParse->nMem = MAX(pParse->nMem, iMem);
  v = sqlite3GetVdbe(pParse);
  if( v==0 || NEVER(pTab==0) ){
    return;
  }
1272
1273
1274
1275
1276
1277
1278
















1279


1280
1281
1282
1283
1284
1285
1286
      int regSample = regStat1+3;
      int regCol = regStat1+4;
      int regSampleRowid = regCol + nCol;
      int addrNext;
      int addrIsNull;
      u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;

















      pParse->nMem = MAX(pParse->nMem, regCol+nCol);



      addrNext = sqlite3VdbeCurrentAddr(v);
      callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid);
      addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
      VdbeCoverage(v);
      callStatGet(pParse, regStat, STAT_GET_NEQ, regEq);
      callStatGet(pParse, regStat, STAT_GET_NLT, regLt);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>







1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
      int regSample = regStat1+3;
      int regCol = regStat1+4;
      int regSampleRowid = regCol + nCol;
      int addrNext;
      int addrIsNull;
      u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;

      if( doOnce ){
        int mxCol = nCol;
        Index *pX;

        /* Compute the maximum number of columns in any index */
        for(pX=pTab->pIndex; pX; pX=pX->pNext){
          int nColX;                     /* Number of columns in pX */
          if( !HasRowid(pTab) && IsPrimaryKeyIndex(pX) ){
            nColX = pX->nKeyCol;
          }else{
            nColX = pX->nColumn;
          }
          if( nColX>mxCol ) mxCol = nColX;
        }

        /* Allocate space to compute results for the largest index */
        pParse->nMem = MAX(pParse->nMem, regCol+mxCol);
        doOnce = 0;
      }

      addrNext = sqlite3VdbeCurrentAddr(v);
      callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid);
      addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
      VdbeCoverage(v);
      callStatGet(pParse, regStat, STAT_GET_NEQ, regEq);
      callStatGet(pParse, regStat, STAT_GET_NLT, regLt);

Changes to test/analyzeE.test.

246
247
248
249
250
251
252


























253
254
  PRAGMA encoding = 'UTF-16';
  CREATE TABLE t0 (c1 TEXT);
  INSERT INTO t0 VALUES ('');
  CREATE INDEX i0 ON t0(c1);
  ANALYZE;
  SELECT * FROM t0 WHERE t0.c1 BETWEEN '' AND (ABS(''));
} {{}}



























finish_test







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


246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  PRAGMA encoding = 'UTF-16';
  CREATE TABLE t0 (c1 TEXT);
  INSERT INTO t0 VALUES ('');
  CREATE INDEX i0 ON t0(c1);
  ANALYZE;
  SELECT * FROM t0 WHERE t0.c1 BETWEEN '' AND (ABS(''));
} {{}}

# 2023-03-24 https://sqlite.org/forum/forumpost/bc39e531e5
#
reset_db
do_execsql_test analyzeE-6.0 {
  CREATE TABLE t1(x);
  CREATE INDEX i1 ON t1(x,x,x,x,x||2);
  CREATE INDEX i2 ON t1(1<2);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
    INSERT INTO t1(x) SELECT x FROM c;
  ANALYZE;
} {}
do_execsql_test analyzeE-6.1 {
  SELECT count(*)>1 FROM sqlite_stat4 WHERE idx='i2' AND neq='1000 1';
} 1
do_execsql_test analyzeE-6.2 {
  SELECT count(*) FROM sqlite_stat4 WHERE idx='i2' AND neq<>'1000 1';
} 0
do_execsql_test analyzeE-6.3 {
  SELECT count(*)>1 FROM sqlite_stat4 WHERE idx='i1' AND neq='1 1 1 1 1 1';
} 1
do_execsql_test analyzeE-6.4 {
  SELECT count(*) FROM sqlite_stat4 WHERE idx='i1' AND neq<>'1 1 1 1 1 1';
} 0



finish_test