SQLite

Changes On Branch enhanced-stat1
Login

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

Changes In Branch enhanced-stat1 Excluding Merge-Ins

This is equivalent to a diff from 8d2120c354 to ee34db31a0

2024-01-01
15:49
Improved defenses against deliberately corrupted sqlite_stat1 tables. (Closed-Leaf check-in: ee34db31a0 user: drh tags: enhanced-stat1)
15:35
Fix a harmless compiler warning. (check-in: b5aa1aea38 user: drh tags: enhanced-stat1)
2023-12-31
04:01
Use SQLITE_ENABLE_STAT4 in both the WASM and JNI builds. (check-in: 99d11e6d0a user: stephan tags: trunk)
2023-12-29
19:03
Attempt to improve the ANALYZE command so that it does a better job of detecting lopsided indexes and makes appropriate changes to the sqlite_stat1 table. (check-in: 4b70b94616 user: drh tags: enhanced-stat1)
04:29
Minor doc touchup in the JS bits. (check-in: 8d2120c354 user: stephan tags: trunk)
2023-12-28
21:02
Enable SQLITE_DIRECT_OVERFLOW_READ unless it is specifically disabled using the -DSQLITE_DIRECT_OVERFLOW_READ=0 compile-time option. (check-in: 630604a4e6 user: drh tags: trunk)

Changes to src/analyze.c.
262
263
264
265
266
267
268

269
270
271
272
273
274
275
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276







+







** information.
*/
typedef struct StatAccum StatAccum;
typedef struct StatSample StatSample;
struct StatSample {
  tRowcnt *anEq;                  /* sqlite_stat4.nEq */
  tRowcnt *anDLt;                 /* sqlite_stat4.nDLt */
  tRowcnt *amxEq;                 /* Maximum length run of equal values */
#ifdef SQLITE_ENABLE_STAT4
  tRowcnt *anLt;                  /* sqlite_stat4.nLt */
  union {
    i64 iRowid;                     /* Rowid in main table of the key */
    u8 *aRowid;                     /* Key for WITHOUT ROWID tables */
  } u;
  u32 nRowid;                     /* Sizeof aRowid[] */
421
422
423
424
425
426
427

428
429
430
431
432
433
434
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436







+







  nKeyCol = sqlite3_value_int(argv[1]);
  assert( nKeyCol<=nCol );
  assert( nKeyCol>0 );

  /* Allocate the space required for the StatAccum object */
  n = sizeof(*p) 
    + sizeof(tRowcnt)*nColUp                  /* StatAccum.anEq */
    + sizeof(tRowcnt)*nColUp                  /* StatAccum.amxEq */
    + sizeof(tRowcnt)*nColUp;                 /* StatAccum.anDLt */
#ifdef SQLITE_ENABLE_STAT4
  if( mxSample ){
    n += sizeof(tRowcnt)*nColUp                  /* StatAccum.anLt */
      + sizeof(StatSample)*(nCol+mxSample)       /* StatAccum.aBest[], a[] */
      + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample);
  }
443
444
445
446
447
448
449

450

451
452
453
454
455
456
457
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460







+
-
+







  p->nEst = sqlite3_value_int64(argv[2]);
  p->nRow = 0;
  p->nLimit = sqlite3_value_int64(argv[3]);
  p->nCol = nCol;
  p->nKeyCol = nKeyCol;
  p->nSkipAhead = 0;
  p->current.anDLt = (tRowcnt*)&p[1];
  p->current.amxEq = &p->current.anDLt[nColUp];
  p->current.anEq = &p->current.anDLt[nColUp];
  p->current.anEq = &p->current.amxEq[nColUp];

#ifdef SQLITE_ENABLE_STAT4
  p->mxSample = p->nLimit==0 ? mxSample : 0;
  if( mxSample ){
    u8 *pSpace;                     /* Allocated space not yet assigned */
    int i;                          /* Used to iterate through p->aSample[] */

712
713
714
715
716
717
718
719




720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735



736
737
738
739
740
741
742
715
716
717
718
719
720
721

722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751







-
+
+
+
+
















+
+
+







  UNUSED_PARAMETER( argc );
  UNUSED_PARAMETER( context );
  assert( p->nCol>0 );
  assert( iChng<p->nCol );

  if( p->nRow==0 ){
    /* This is the first call to this function. Do initialization. */
    for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
    for(i=0; i<p->nCol; i++){
      p->current.anEq[i] = 1;
      p->current.amxEq[i] = 1;
    }
  }else{
    /* Second and subsequent calls get processed here */
#ifdef SQLITE_ENABLE_STAT4
    if( p->mxSample ) samplePushPrevious(p, iChng);
#endif

    /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
    ** to the current row of the index. */
    for(i=0; i<iChng; i++){
      p->current.anEq[i]++;
    }
    for(i=iChng; i<p->nCol; i++){
      p->current.anDLt[i]++;
#ifdef SQLITE_ENABLE_STAT4
      if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
#endif
      if( p->current.amxEq[i]<p->current.anEq[i] ){
        p->current.amxEq[i] = p->current.anEq[i];
      }
      p->current.anEq[i] = 1;
    }
  }

  p->nRow++;
#ifdef SQLITE_ENABLE_STAT4
  if( p->mxSample ){
837
838
839
840
841
842
843
844
845
846
847




848
849
850
851
852
853
854

855
856
857

858
859
860


861
862

863

864
865
866
867

















868




869
870













871
872
873
874
875
876
877
846
847
848
849
850
851
852




853
854
855
856
857
858
859
860
861
862

863



864
865
866
867
868
869
870
871
872

873

874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893

894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919







-
-
-
-
+
+
+
+






-
+
-
-
-
+



+
+


+
-
+
-



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+







    ** the index. The first integer in the list is the total number of 
    ** entries in the index. There is one additional integer in the list 
    ** for each indexed column. This additional integer is an estimate of
    ** the number of rows matched by a equality query on the index using
    ** a key with the corresponding number of fields. In other words,
    ** if the index is on columns (a,b) and the sqlite_stat1 value is 
    ** "100 10 2", then SQLite estimates that:
    **
    **   * the index contains 100 rows,
    **   * "WHERE a=?" matches 10 rows, and
    **   * "WHERE a=? AND b=?" matches 2 rows.
    **   |   | |
    **   |   | `--  "WHERE a=? AND b=?" matches approximately 2 rows
    **   |   `----  "WHERE a=?" matches approximately 10 rows
    **   `--------  There are approximately 100 rows in the index total
    **
    ** If D is the count of distinct values and K is the total number of 
    ** rows, then each estimate is usually computed as:
    **
    **        I = (K+D-1)/D
    **
    ** In other words, I is K/D rounded up to the next whole integer.
    ** Adjustments to the I value are made in some cases.  See comments
    ** However, if I is between 1.0 and 1.1 (in other words if I is
    ** close to 1.0 but just a little larger) then do not round up but
    ** instead keep the I value at 1.0.
    ** in-line below.
    */
    sqlite3_str sStat;   /* Text of the constructed "stat" line */
    int i;               /* Loop counter */
    int bUneven = 0;     /* True if the uneven=... argument is needed */
    u64 nRow;            /* Number of rows in the index */

    sqlite3StrAccumInit(&sStat, 0, 0, 0, (p->nKeyCol+1)*100);
    nRow =  p->nSkipAhead ? p->nEst : p->nRow;
    sqlite3_str_appendf(&sStat, "%llu", 
    sqlite3_str_appendf(&sStat, "%llu", nRow);
        p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
    for(i=0; i<p->nKeyCol; i++){
      u64 nDistinct = p->current.anDLt[i] + 1;
      u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
      u64 mx = p->current.amxEq[i];
      if( nDistinct==1 && p->nLimit>0 ){
        /* If we never saw more than a single value in a PRAGMA analysis_limit
        ** search, then set the estimated number of matching rows to the
        ** estimated number of rows in the index. */
        iVal = p->nEst;
      }else if( iVal<mx/10 ){
        /*              ^^-- TUNING: threshold for when var=... is reported.
        ** tag-20231231-01:  Report var=... if the maximum run of identical
        ** values ever reaches or exceeds 10 (or so) times the average run
        ** for any column of the index.
        **
        ** The reporting threshold of 10 is tunable, but if changed, one
        ** should also consider changing the aiRowLogEst adjustment factor at
        ** tag-20231231-02.
        */
        bUneven = 1;
      if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
      }else if( iVal==2 && p->nRow*10 <= nDistinct*11 ){
        /* If the value is less than or equal to 1.1, round it down to 1.0 */
        iVal = 1;
      }
      sqlite3_str_appendf(&sStat, " %llu", iVal);
      assert( p->current.anEq[i] );

    }
    if( bUneven ){
      char cSep = '=';
      sqlite3_str_appendf(&sStat, " var");
      for(i=0; i<p->nKeyCol; i++){
        u64 nDistinct = p->current.anDLt[i] + 1;
        u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
        u64 mx = p->current.amxEq[i];
        int iRatio = mx/iVal;
        sqlite3_str_appendf(&sStat, "%c%d", cSep, iRatio);
        cSep = ',';
      }
    }
    sqlite3ResultStrAccum(context, &sStat);
  }
#ifdef SQLITE_ENABLE_STAT4
  else if( eCall==STAT_GET_ROWID ){
    if( p->iGet<0 ){
      samplePushPrevious(p, 0);
1510
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524
1552
1553
1554
1555
1556
1557
1558

1559
1560
1561
1562
1563
1564
1565
1566







-
+







  tRowcnt v;

#ifdef SQLITE_ENABLE_STAT4
  if( z==0 ) z = "";
#else
  assert( z!=0 );
#endif
  for(i=0; *z && i<nOut; i++){
  for(i=0; i<nOut; i++){
    v = 0;
    while( (c=z[0])>='0' && c<='9' ){
      v = v*10 + c - '0';
      z++;
    }
#ifdef SQLITE_ENABLE_STAT4
    if( aOut ) aOut[i] = v;
1534
1535
1536
1537
1538
1539
1540


1541
1542
1543
1544
1545
1546
1547
1548
1549


































1550
1551
1552
1553
1554
1555
1556
1557
1558










1559
1560
1561
1562
1563
1564
1565
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653







+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+







#ifndef SQLITE_ENABLE_STAT4
  assert( pIndex!=0 ); {
#else
  if( pIndex ){
#endif
    pIndex->bUnordered = 0;
    pIndex->noSkipScan = 0;
    pIndex->bSlow = 0;
    assert( aLog!=0 );
    while( z[0] ){
      if( sqlite3_strglob("unordered*", z)==0 ){
        pIndex->bUnordered = 1;
      }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
        int sz = sqlite3Atoi(z+3);
        if( sz<2 ) sz = 2;
        pIndex->szIdxRow = sqlite3LogEst(sz);
      }else if( sqlite3_strglob("noskipscan*", z)==0 ){
        pIndex->noSkipScan = 1;
      }else if( sqlite3_strglob("var=[0-9]*", z)==0 ){
        /* An argument like "var=N1,N2,...NN" means that the maximum length
        ** run of the same value is Nx times longer than the average for
        ** the X-th column of the index.
        **
        ** For this implementation, go through the iaRowLogEst[] array and
        ** increase each value by 1/10th of the average value, to account
        ** for the variability of the estimate.
        **
        ** tag-20231231-02:  The 1/10th value is tunable.  See the tuning
        ** comment in the body of the loop.  The ANALYZE command only
        ** inserts a var=... argument if one or more of the Nx values is
        ** within the tuning range, so if changing the tuning factor here,
        ** consider also changing it at tag-20232131-01.
        **
        ** The stat column continue to hold the average run length for the
        ** initial integers, for backwards compatibility.
        */
        int jj = 1;
        int kk = 4;
        LogEst mx = aLog[0];
        for(jj=1; sqlite3Isdigit(z[kk]) && jj<nOut; jj++){
          u64 vx = z[kk++] - '0';
          LogEst scale;
          while( sqlite3Isdigit(z[kk]) ){ vx = vx*10 + z[kk++]-'0'; }
          scale = sqlite3LogEst(vx);
          if( scale>33 ){
                /*  ^^----- TUNING --------------vv    See tag 20231231-02 */
            LogEst adjusted = aLog[jj] + scale - 33;
            if( adjusted>mx ) adjusted = mx;
            aLog[jj] = adjusted;
          }
          if( z[kk]==',' ) kk++;
        }
      }
#ifdef SQLITE_ENABLE_COSTMULT
      else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
        pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
      }
#endif
      while( z[0]!=0 && z[0]!=' ' ) z++;
      while( z[0]==' ' ) z++;
    }

    /* Set the bSlow flag if the peak number of rows obtained
    ** from a full equality match is so large that a full table scan
    ** seems likely to be faster than using the index.
    */
    if( aLog[0] > 66                       /* Index has more than 100 rows */
     && aLog[0] <= aLog[pIndex->nKeyCol]   /* And only a single value seen */
    ){
      pIndex->bSlow = 1;
    }
  }
}

/*
** This callback is invoked once for each index when reading the
** sqlite_stat1 table.  
**
1613
1614
1615
1616
1617
1618
1619

1620
1621
1622
1623
1624
1625
1626
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715







+







    pIndex->hasStat1 = 1;
    if( pIndex->pPartIdxWhere==0 ){
      pTable->nRowLogEst = pIndex->aiRowLogEst[0];
      pTable->tabFlags |= TF_HasStat1;
    }
  }else{
    Index fakeIdx;
    memset(&fakeIdx, 0, sizeof(fakeIdx));
    fakeIdx.szIdxRow = pTable->szTabRow;
#ifdef SQLITE_ENABLE_COSTMULT
    fakeIdx.pTable = pTable;
#endif
    decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
    pTable->szTabRow = fakeIdx.szIdxRow;
    pTable->tabFlags |= TF_HasStat1;
Changes to src/pragma.c.
1294
1295
1296
1297
1298
1299
1300












1301
1302
1303


1304

1305
1306
1307
1308

1309
1310
1311
1312
1313


1314







1315

1316
1317
1318
1319
1320




1321
1322
1323
1324
1325
1326
1327
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317

1318
1319
1320
1321

1322
1323
1324
1325
1326

1327
1328
1329
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340


1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351







+
+
+
+
+
+
+
+
+
+
+
+



+
+
-
+



-
+




-
+
+

+
+
+
+
+
+
+
-
+



-
-
+
+
+
+







        );
      }
    }
  }
  break;

#ifdef SQLITE_DEBUG
  /* The output of this pragma is undocumented in the official documentation
  ** because it is subject to change, and we don't want people coming to
  ** rely on it.
  **
  ** Columns:
  **    tbl              Name of a table that is being described
  **    idx              Name of an index (belonging to tbl) being described
  **    wdth             LogEst of the on-disk estimated bytes per row
  **    hght             LogEst of the estimated number of rows
  **    flgs             tabFlags for tables
  **    est              aiRowLogEst[] values for indexes + "slow" flag
  */
  case PragTyp_STATS: {
    Index *pIdx;
    HashElem *i;
    sqlite3_str est;
    sqlite3StrAccumInit(&est, 0, 0, 0, SQLITE_MAX_LENGTH);
    pParse->nMem = 5;
    pParse->nMem = 6;
    sqlite3CodeVerifySchema(pParse, iDb);
    for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
      Table *pTab = sqliteHashData(i);
      sqlite3VdbeMultiLoad(v, 1, "ssiii",
      sqlite3VdbeMultiLoad(v, 1, "ssiiis",
           sqlite3PreferredTableName(pTab->zName),
           0,
           pTab->szTabRow,
           pTab->nRowLogEst,
           pTab->tabFlags);
           pTab->tabFlags,
           0);
      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
        int j;
        est.nChar = 0;
        for(j=1; j<pIdx->nKeyCol+1; j++){
          if( j>1 ) sqlite3_str_append(&est, " ", 1);
          sqlite3_str_appendf(&est, "%d", pIdx->aiRowLogEst[j]);
        }
        if( pIdx->bSlow ) sqlite3_str_append(&est, " slow", 5);
        sqlite3VdbeMultiLoad(v, 2, "siiiX",
        sqlite3VdbeMultiLoad(v, 2, "siiisX",
           pIdx->zName,
           pIdx->szIdxRow,
           pIdx->aiRowLogEst[0],
           pIdx->hasStat1);
        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
           pIdx->hasStat1,
           sqlite3_str_value(&est));
        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
        sqlite3_str_reset(&est);
      }
    }
  }
  break;
#endif

  case PragTyp_INDEX_INFO: if( zRight ){
Changes to src/pragma.h.
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119





























120
121
122
123
124
125
126
127
128









129
130

131
132
133
134
135
136
137
85
86
87
88
89
90
91




























92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120









121
122
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
138







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
+







                           /* table_info reuses 8 */
  /*  15 */ "schema",      /* Used by: table_list */
  /*  16 */ "name",       
  /*  17 */ "type",       
  /*  18 */ "ncol",       
  /*  19 */ "wr",         
  /*  20 */ "strict",     
  /*  21 */ "seqno",       /* Used by: index_xinfo */
  /*  22 */ "cid",        
  /*  23 */ "name",       
  /*  24 */ "desc",       
  /*  25 */ "coll",       
  /*  26 */ "key",        
  /*  27 */ "name",        /* Used by: function_list */
  /*  28 */ "builtin",    
  /*  29 */ "type",       
  /*  30 */ "enc",        
  /*  31 */ "narg",       
  /*  32 */ "flags",      
  /*  33 */ "tbl",         /* Used by: stats */
  /*  34 */ "idx",        
  /*  35 */ "wdth",       
  /*  36 */ "hght",       
  /*  37 */ "flgs",       
  /*  38 */ "seq",         /* Used by: index_list */
  /*  39 */ "name",       
  /*  40 */ "unique",     
  /*  41 */ "origin",     
  /*  42 */ "partial",    
  /*  43 */ "table",       /* Used by: foreign_key_check */
  /*  44 */ "rowid",      
  /*  45 */ "parent",     
  /*  46 */ "fkid",       
                           /* index_info reuses 21 */
  /*  47 */ "seq",         /* Used by: database_list */
  /*  21 */ "tbl",         /* Used by: stats */
  /*  22 */ "idx",        
  /*  23 */ "wdth",       
  /*  24 */ "hght",       
  /*  25 */ "flgs",       
  /*  26 */ "est",        
  /*  27 */ "seqno",       /* Used by: index_xinfo */
  /*  28 */ "cid",        
  /*  29 */ "name",       
  /*  30 */ "desc",       
  /*  31 */ "coll",       
  /*  32 */ "key",        
  /*  33 */ "name",        /* Used by: function_list */
  /*  34 */ "builtin",    
  /*  35 */ "type",       
  /*  36 */ "enc",        
  /*  37 */ "narg",       
  /*  38 */ "flags",      
  /*  39 */ "seq",         /* Used by: index_list */
  /*  40 */ "name",       
  /*  41 */ "unique",     
  /*  42 */ "origin",     
  /*  43 */ "partial",    
  /*  44 */ "table",       /* Used by: foreign_key_check */
  /*  45 */ "rowid",      
  /*  46 */ "parent",     
  /*  47 */ "fkid",       
                           /* index_info reuses 27 */
  /*  48 */ "seq",         /* Used by: database_list */
  /*  48 */ "name",       
  /*  49 */ "file",       
  /*  50 */ "busy",        /* Used by: wal_checkpoint */
  /*  51 */ "log",        
  /*  52 */ "checkpointed",
                           /* collation_list reuses 38 */
  /*  53 */ "database",    /* Used by: lock_status */
  /*  54 */ "status",     
  /*  55 */ "cache_size",  /* Used by: default_cache_size */
  /*  49 */ "name",       
  /*  50 */ "file",       
  /*  51 */ "busy",        /* Used by: wal_checkpoint */
  /*  52 */ "log",        
  /*  53 */ "checkpointed",
                           /* collation_list reuses 39 */
  /*  54 */ "database",    /* Used by: lock_status */
  /*  55 */ "status",     
  /*  56 */ "cache_size",  /* Used by: default_cache_size */
                           /* module_list pragma_list reuses 9 */
  /*  56 */ "timeout",     /* Used by: busy_timeout */
  /*  57 */ "timeout",     /* Used by: busy_timeout */
};

/* Definitions of all built-in pragmas */
typedef struct PragmaName {
  const char *const zName; /* Name of pragma */
  u8 ePragTyp;             /* PragTyp_XXX value */
  u8 mPragFlg;             /* Zero or more PragFlg_XXX values */
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189







-
+







  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_AutoIndex },
#endif
#endif
 {/* zName:     */ "busy_timeout",
  /* ePragTyp:  */ PragTyp_BUSY_TIMEOUT,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 56, 1,
  /* ColNames:  */ 57, 1,
  /* iArg:      */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
 {/* zName:     */ "cache_size",
  /* ePragTyp:  */ PragTyp_CACHE_SIZE,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228







-
+







  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_CkptFullFSync },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
 {/* zName:     */ "collation_list",
  /* ePragTyp:  */ PragTyp_COLLATION_LIST,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 38, 2,
  /* ColNames:  */ 39, 2,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
 {/* zName:     */ "compile_options",
  /* ePragTyp:  */ PragTyp_COMPILE_OPTIONS,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 0, 0,
248
249
250
251
252
253
254
255

256
257
258
259
260
261
262

263
264
265
266
267
268
269
249
250
251
252
253
254
255

256
257
258
259
260
261
262

263
264
265
266
267
268
269
270







-
+






-
+







  /* ColNames:  */ 0, 0,
  /* iArg:      */ BTREE_DATA_VERSION },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
 {/* zName:     */ "database_list",
  /* ePragTyp:  */ PragTyp_DATABASE_LIST,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 47, 3,
  /* ColNames:  */ 48, 3,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
 {/* zName:     */ "default_cache_size",
  /* ePragTyp:  */ PragTyp_DEFAULT_CACHE_SIZE,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
  /* ColNames:  */ 55, 1,
  /* ColNames:  */ 56, 1,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
 {/* zName:     */ "defer_foreign_keys",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300







-
+







  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
 {/* zName:     */ "foreign_key_check",
  /* ePragTyp:  */ PragTyp_FOREIGN_KEY_CHECK,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 43, 4,
  /* ColNames:  */ 44, 4,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
 {/* zName:     */ "foreign_key_list",
  /* ePragTyp:  */ PragTyp_FOREIGN_KEY_LIST,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 0, 8,
328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343







-
+







  /* iArg:      */ SQLITE_FullFSync },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
 {/* zName:     */ "function_list",
  /* ePragTyp:  */ PragTyp_FUNCTION_LIST,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 27, 6,
  /* ColNames:  */ 33, 6,
  /* iArg:      */ 0 },
#endif
#endif
 {/* zName:     */ "hard_heap_limit",
  /* ePragTyp:  */ PragTyp_HARD_HEAP_LIMIT,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 0, 0,
357
358
359
360
361
362
363
364

365
366
367
368
369

370
371
372
373
374

375
376
377
378
379
380
381
358
359
360
361
362
363
364

365
366
367
368
369

370
371
372
373
374

375
376
377
378
379
380
381
382







-
+




-
+




-
+







  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
 {/* zName:     */ "index_info",
  /* ePragTyp:  */ PragTyp_INDEX_INFO,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 21, 3,
  /* ColNames:  */ 27, 3,
  /* iArg:      */ 0 },
 {/* zName:     */ "index_list",
  /* ePragTyp:  */ PragTyp_INDEX_LIST,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 38, 5,
  /* ColNames:  */ 39, 5,
  /* iArg:      */ 0 },
 {/* zName:     */ "index_xinfo",
  /* ePragTyp:  */ PragTyp_INDEX_INFO,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 21, 6,
  /* ColNames:  */ 27, 6,
  /* iArg:      */ 1 },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
 {/* zName:     */ "integrity_check",
  /* ePragTyp:  */ PragTyp_INTEGRITY_CHECK,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 0, 0,
407
408
409
410
411
412
413
414

415
416
417
418
419
420
421
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422







-
+







  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
 {/* zName:     */ "lock_status",
  /* ePragTyp:  */ PragTyp_LOCK_STATUS,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 53, 2,
  /* ColNames:  */ 54, 2,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
 {/* zName:     */ "locking_mode",
  /* ePragTyp:  */ PragTyp_LOCKING_MODE,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_SchemaReq,
  /* ColNames:  */ 0, 0,
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
547
548
549
550
551
552
553

554
555
556
557
558
559
560
561







-
+







  /* iArg:      */ SQLITE_SqlTrace },
#endif
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
 {/* zName:     */ "stats",
  /* ePragTyp:  */ PragTyp_STATS,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
  /* ColNames:  */ 33, 5,
  /* ColNames:  */ 21, 6,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
 {/* zName:     */ "synchronous",
  /* ePragTyp:  */ PragTyp_SYNCHRONOUS,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657
658
659
660
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657
658
659
660
661







-
+











  /* ePragTyp:  */ PragTyp_WAL_AUTOCHECKPOINT,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
 {/* zName:     */ "wal_checkpoint",
  /* ePragTyp:  */ PragTyp_WAL_CHECKPOINT,
  /* ePragFlg:  */ PragFlg_NeedSchema,
  /* ColNames:  */ 50, 3,
  /* ColNames:  */ 51, 3,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "writable_schema",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
/* Number of pragmas: 68 on by default, 78 total. */
Changes to src/sqliteInt.h.
2763
2764
2765
2766
2767
2768
2769

2770
2771
2772
2773
2774
2775
2776
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777







+







  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 bSlow:1;        /* This index is not good for equality lookups */
  unsigned bAscKeyBug:1;   /* True if the bba7b69f9849b5bf bug applies */
  unsigned bHasVCol:1;     /* Index references one or more VIRTUAL columns */
  unsigned bHasExpr:1;     /* Index contains an expression, either a literal
                           ** expression, or a reference to a VIRTUAL column */
#ifdef SQLITE_ENABLE_STAT4
  int nSample;             /* Number of elements in aSample[] */
  int mxSample;            /* Number of slots allocated to aSample[] */
Changes to src/where.c.
2969
2970
2971
2972
2973
2974
2975

2976



2977
2978
2979
2980
2981
2982
2983
2969
2970
2971
2972
2973
2974
2975
2976

2977
2978
2979
2980
2981
2982
2983
2984
2985
2986







+
-
+
+
+







  assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
  if( pNew->wsFlags & WHERE_BTM_LIMIT ){
    opMask = WO_LT|WO_LE;
  }else{
    assert( pNew->u.btree.nBtm==0 );
    opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
  }
  if( pProbe->bUnordered || pProbe->bSlow ){
  if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
    if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
    if( pProbe->bSlow )      opMask &= ~(WO_EQ|WO_IN|WO_IS);
  }

  assert( pNew->u.btree.nEq<pProbe->nColumn );
  assert( pNew->u.btree.nEq<pProbe->nKeyCol
       || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );

  saved_nEq = pNew->u.btree.nEq;
  saved_nBtm = pNew->u.btree.nBtm;
Changes to tool/mkpragmatab.tcl.
243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257







-
+







  TYPE: TABLE_LIST
  FLAG: NeedSchema Result1
  COLS: schema name type ncol wr strict
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)

  NAME: stats
  FLAG: NeedSchema Result0 SchemaReq
  COLS: tbl idx wdth hght flgs
  COLS: tbl idx wdth hght flgs est
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)

  NAME: index_info
  TYPE: INDEX_INFO
  ARG:  0
  FLAG: NeedSchema Result1 SchemaOpt
  COLS: seqno cid name