Add support for PRAGMA analyze_limit and approximate analysis.

FossilOrigin-Name: 812547525d35df975f40cbbeb604cc9cd2dec809c1ca083cbb139fe59ffa1d73
This commit is contained in:
drh
2020-05-02 03:46:32 +00:00
12 changed files with 235 additions and 165 deletions
+16 -16
View File
@@ -1,5 +1,5 @@
C Merge\sthe\sbytecode\sand\stables_used\stable-valued\sfunctions.\s\sRequires\n-DSQLITE_ENABLE_BYTECODE_VTAB\sat\scompile-time.
D 2020-05-02T00:31:00.975
C Add\ssupport\sfor\sPRAGMA\sanalyze_limit\sand\sapproximate\sanalysis.
D 2020-05-02T03:46:32.798
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -468,19 +468,19 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c fa2c3be9b0ebecfafb7062072a0ae6eda126d3e5a9fd51b2eded5acd95dc783c
F src/analyze.c 831bb090988477a00d3b4c000746e1b0454dcc93b10b793e6ebe1c47f25d193a
F src/analyze.c f71fb976b1bc8e62320e4932f979e56f535237b1579e07b392b22f9a1ccbba42
F src/attach.c ff2daea0fe62080192e3f262670e4f61f5a86c1e7bea9cec34e960fe79852aa1
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 02376eb7d49ccf31b53c2504f045ad74687c142a5c15ca837516e59e737867dc
F src/btree.h 32672fa1aa74a7e9ab3aae822f94ffc8e732b1eb005988dc2283f91dc7573398
F src/btree.c 3383ad76753193c3529318ba30db41747663639428d2f6cb7cbcd8034d4a99cd
F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a
F src/btreeInt.h 887cdd2ea7f4a65143074a8a7c8928b0546f8c18dda3c06a408ce7992cbab0c0
F src/build.c ec6c0bda1e43ef55e5f5121a77ba19fac51fc6585f95ce2da795bcedcf6e8f36
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 6892999ee100bd72b64f84dd7a8f737817d72872648705fbf8ed9575e1f1dd1a
F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6
F src/date.c b29b349d277e3d579dcc295b24c0a2caed83fd8f090a9f7cbe6070c0fd662384
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 793deaf88a0904f88285d93d6713c636d55ede0ffd9f08d10f4ea825531d367f
@@ -526,19 +526,19 @@ F src/parse.y c8eff38606f443d5ba245263fa7abc05e4116d95656e050c4b78e9bfbf931add
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
F src/pragma.c 5fd004b89c77319008ddff6d65dcc83ccca9584d3048f4f66b108b5906a20dba
F src/pragma.h 9473160d220416456b40f27323bb4b316d4e4e08ffbf8bf88c5f7045d49c38e5
F src/pragma.c 85f763714b192cc26a236e3ec020a9155fe8da248af21eae86c0d1f0f49a0753
F src/pragma.h 8168e588536bffd95319451f34e9a754dc37d205ebe433031a7813c5b286beae
F src/prepare.c 8d4d6c8aa6afefc48027c54b41cdf134b4d6bc2fc4badbe483ad7fd9e1728a28
F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c d36a2b1639e1c33d7b508abfd3452a63e7fd81737f6f3940bfef085fca6f21f4
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c c310de94bf67315054587c18a16e7a3e3dc3a98dc79168f0c2b776548d43f6cd
F src/select.c 1720bff2168491ca79af81a03bd18c0383f61d845c6e17caff9d25aabc4ab435
F src/shell.c.in cf2d24f54412c06e5fb34af7fabc748651125e1dceac29b740e91f06d23447b6
F src/sqlite.h.in b20d5dc52765ff82f3701395a7e670611ddf138ee0ae84482452ad3a0b5f24b5
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197
F src/sqliteInt.h 0f3848c46310d197246003f052985b72d1cdbfc0b31e069db76cb5231062fa1d
F src/sqliteInt.h 1f6909cd268d1cda2f04914d150997b17afd8ff7e5cf1930cc1f88d337a49f74
F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032
F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -605,7 +605,7 @@ F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
F src/utf.c 95fb6e03a5ca679045c5adccd05380f0addccabef5911abddcb06af069500ab7
F src/util.c 3b6cedf7a0c69bd6e1acce832873952d416212d6293b18d03064e07d7a9b5118
F src/vacuum.c f25d3b39681595e321a8a4e7fca3e5971cb14a401213d0742c9bf7d4ce8c2a1a
F src/vdbe.c 972999395eee88702091fb5d50cf4effd07889c371807d222a7f517388e6378e
F src/vdbe.c f55fe7dbffae72e1cd5861e9ea3b55d50b70d863eebce3aebf11e1271ceae796
F src/vdbe.h 07b8c636a87df8b6e58f29d6badd7f10d5844353deff1d7c88ed1c2bfe3bbd35
F src/vdbeInt.h 571413068b5ac07e2ed8ca7a02fa529622fd5455ae6981498376e5e492d2e5ef
F src/vdbeapi.c d176ee7251d5344de7bb2a0d2dd0fe536834e5843d9bc2389e0f5cdcd5374141
@@ -1796,7 +1796,7 @@ F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a89
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl 62663c65d9191aada624a787e1ee3420f268a3c27999ad0ffb77a6918ddc1e52
F tool/mkpragmatab.tcl d348a4bf71ac068bddf89326562071cbbd962273d88f9b5e5d622f3e73b78bdf
F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1863,8 +1863,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 853703cd6d44d6dd48ef5eda6523e374b8ebdf7c338ddaad31c15a40a8b3fd9b baa720e4a88f268ed95337daab5f434fd3263b00f09101cddc6424765bf3b722
R 8a6312f86dfd0f2dc1b9dbd32625eb27
T +closed baa720e4a88f268ed95337daab5f434fd3263b00f09101cddc6424765bf3b722
P d09bcce37f1eaf084e3b07eb4a23653ea1f370cdd290ce3875408186adf87022 77a55c394d2c313a5710229bee9262457dcfc6620e6500f9f526c5f6acf87cef
R 4ed29fc45141d3045a102a3aecbc1dee
T +closed 77a55c394d2c313a5710229bee9262457dcfc6620e6500f9f526c5f6acf87cef
U drh
Z 757d78e9720a98d9f46cefa09a4228d8
Z 44d724364acf9e8bd25af4207bb5887c
+1 -1
View File
@@ -1 +1 @@
d09bcce37f1eaf084e3b07eb4a23653ea1f370cdd290ce3875408186adf87022
812547525d35df975f40cbbeb604cc9cd2dec809c1ca083cbb139fe59ffa1d73
+131 -84
View File
@@ -188,6 +188,11 @@ static void openStatTable(
Vdbe *v = sqlite3GetVdbe(pParse);
int aRoot[ArraySize(aTable)];
u8 aCreateTbl[ArraySize(aTable)];
#ifdef SQLITE_ENABLE_STAT4
const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1;
#else
const int nToOpen = 1;
#endif
if( v==0 ) return;
assert( sqlite3BtreeHoldsAllMutexes(db) );
@@ -200,8 +205,9 @@ static void openStatTable(
for(i=0; i<ArraySize(aTable); i++){
const char *zTab = aTable[i].zName;
Table *pStat;
aCreateTbl[i] = 0;
if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
if( aTable[i].zCols ){
if( i<nToOpen ){
/* The sqlite_statN table does not exist. Create it. Note that a
** side-effect of the CREATE TABLE statement is to leave the rootpage
** of the new table in register pParse->regRoot. This is important
@@ -217,7 +223,6 @@ static void openStatTable(
** associated with the table zWhere. If zWhere is NULL, delete the
** entire contents of the table. */
aRoot[i] = pStat->tnum;
aCreateTbl[i] = 0;
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
if( zWhere ){
sqlite3NestedParse(pParse,
@@ -236,7 +241,7 @@ static void openStatTable(
}
/* Open the sqlite_stat[134] tables for writing. */
for(i=0; aTable[i].zCols; i++){
for(i=0; i<nToOpen; i++){
assert( i<ArraySize(aTable) );
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
@@ -275,9 +280,12 @@ struct StatSample {
};
struct StatAccum {
sqlite3 *db; /* Database connection, for malloc() */
tRowcnt nRow; /* Number of rows in the entire table */
tRowcnt nEst; /* Estimated number of rows */
tRowcnt nRow; /* Number of rows visited so far */
int nLimit; /* Analysis row-scan limit */
int nCol; /* Number of columns in index + pk/rowid */
int nKeyCol; /* Number of index columns w/o the pk/rowid */
u8 nSkipAhead; /* Number of times of skip-ahead */
StatSample current; /* Current row as a StatSample */
#ifdef SQLITE_ENABLE_STAT4
tRowcnt nPSample; /* How often to do a periodic sample */
@@ -357,27 +365,28 @@ static void sampleCopy(StatAccum *p, StatSample *pTo, StatSample *pFrom){
static void statAccumDestructor(void *pOld){
StatAccum *p = (StatAccum*)pOld;
#ifdef SQLITE_ENABLE_STAT4
int i;
for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
sampleClear(p->db, &p->current);
if( p->mxSample ){
int i;
for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
sampleClear(p->db, &p->current);
}
#endif
sqlite3DbFree(p->db, p);
}
/*
** Implementation of the stat_init(N,K,C) SQL function. The three parameters
** Implementation of the stat_init(N,K,C,L) SQL function. The four parameters
** are:
** N: The number of columns in the index including the rowid/pk (note 1)
** K: The number of columns in the index excluding the rowid/pk.
** C: The number of rows in the index (note 2)
** C: Estimated number of rows in the index
** L: A limit on the number of rows to scan, or 0 for no-limit
**
** Note 1: In the special case of the covering index that implements a
** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
** total number of columns in the table.
**
** Note 2: C is only used for STAT4.
**
** For indexes on ordinary rowid tables, N==K+1. But for indexes on
** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
** PRIMARY KEY of the table. The covering index that implements the
@@ -398,9 +407,10 @@ static void statInit(
int nKeyCol; /* Number of key columns */
int nColUp; /* nCol rounded up for alignment */
int n; /* Bytes of space to allocate */
sqlite3 *db; /* Database connection */
sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */
#ifdef SQLITE_ENABLE_STAT4
int mxSample = SQLITE_STAT4_SAMPLES;
/* Maximum number of samples. 0 if STAT4 data is not collected */
int mxSample = OptimizationEnabled(db,SQLITE_Stat4) ?SQLITE_STAT4_SAMPLES :0;
#endif
/* Decode the three function arguments */
@@ -415,13 +425,14 @@ static void statInit(
/* Allocate the space required for the StatAccum object */
n = sizeof(*p)
+ sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
+ sizeof(tRowcnt)*nColUp /* StatAccum.anDLt */
+ sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
#ifdef SQLITE_ENABLE_STAT4
+ sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
+ sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
if( mxSample ){
n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
+ sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample);
}
#endif
;
db = sqlite3_context_db_handle(context);
p = sqlite3DbMallocZero(db, n);
if( p==0 ){
@@ -430,20 +441,23 @@ static void statInit(
}
p->db = db;
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.anEq = &p->current.anDLt[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[] */
p->iGet = -1;
p->mxSample = mxSample;
p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
p->nPSample = (tRowcnt)(p->nEst/(mxSample/3+1) + 1);
p->current.anLt = &p->current.anEq[nColUp];
p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
@@ -471,7 +485,7 @@ static void statInit(
sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
}
static const FuncDef statInitFuncdef = {
2+IsStat4, /* nArg */
4, /* nArg */
SQLITE_UTF8, /* funcFlags */
0, /* pUserData */
0, /* pNext */
@@ -675,10 +689,13 @@ static void samplePushPrevious(StatAccum *p, int iChng){
** R Rowid for the current row. Might be a key record for
** WITHOUT ROWID tables.
**
** This SQL function always returns NULL. It's purpose it to accumulate
** statistical data and/or samples in the StatAccum object about the
** index being analyzed. The stat_get() SQL function will later be used to
** extract relevant information for constructing the sqlite_statN tables.
** The purpose of this routine is to collect statistical data and/or
** samples from the index being analyzed into the StatAccum object.
** The stat_get() SQL function will be used afterwards to
** retrieve the information gathered.
**
** This SQL function usually returns NULL, but might return an integer
** if it wants the byte-code to do special processing.
**
** The R parameter is only used for STAT4
*/
@@ -704,7 +721,7 @@ static void statPush(
}else{
/* Second and subsequent calls get processed here */
#ifdef SQLITE_ENABLE_STAT4
samplePushPrevious(p, iChng);
if( p->mxSample ) samplePushPrevious(p, iChng);
#endif
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
@@ -715,26 +732,25 @@ static void statPush(
for(i=iChng; i<p->nCol; i++){
p->current.anDLt[i]++;
#ifdef SQLITE_ENABLE_STAT4
p->current.anLt[i] += p->current.anEq[i];
if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
#endif
p->current.anEq[i] = 1;
}
}
p->nRow++;
#ifdef SQLITE_ENABLE_STAT4
if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
}else{
sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
sqlite3_value_blob(argv[2]));
}
p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
#endif
#ifdef SQLITE_ENABLE_STAT4
{
tRowcnt nLt = p->current.anLt[p->nCol-1];
if( p->mxSample ){
tRowcnt nLt;
if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
}else{
sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
sqlite3_value_blob(argv[2]));
}
p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
nLt = p->current.anLt[p->nCol-1];
/* Check if this is to be a periodic sample. If so, add it. */
if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
p->current.isPSample = 1;
@@ -750,9 +766,14 @@ static void statPush(
sampleCopy(p, &p->aBest[i], &p->current);
}
}
}
}else
#endif
if( p->nLimit && p->nRow>p->nLimit*(p->nSkipAhead+1) ){
p->nSkipAhead++;
sqlite3_result_int(context, p->current.anDLt[0]>0);
}
}
static const FuncDef statPushFuncdef = {
2+IsStat4, /* nArg */
SQLITE_UTF8, /* funcFlags */
@@ -804,6 +825,7 @@ static void statGet(
|| eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
|| eCall==STAT_GET_NDLT
);
assert( eCall==STAT_GET_STAT1 || p->mxSample );
if( eCall==STAT_GET_STAT1 )
#else
assert( argc==1 );
@@ -839,7 +861,8 @@ static void statGet(
return;
}
sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
sqlite3_snprintf(24, zRet, "%llu",
p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
z = zRet + sqlite3Strlen30(zRet);
for(i=0; i<p->nKeyCol; i++){
u64 nDistinct = p->current.anDLt[i] + 1;
@@ -915,16 +938,16 @@ static const FuncDef statGetFuncdef = {
{0}
};
static void callStatGet(Parse *pParse, int regStat4, int iParam, int regOut){
static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){
#ifdef SQLITE_ENABLE_STAT4
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat4+1);
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat+1);
#elif SQLITE_DEBUG
assert( iParam==STAT_GET_STAT1 );
#else
UNUSED_PARAMETER( iParam );
#endif
assert( regOut!=regStat4 && regOut!=regStat4+1 );
sqlite3VdbeAddFunctionCall(pParse, 0, regStat4, regOut, 1+IsStat4,
assert( regOut!=regStat && regOut!=regStat+1 );
sqlite3VdbeAddFunctionCall(pParse, 0, regStat, regOut, 1+IsStat4,
&statGetFuncdef, 0);
}
@@ -950,12 +973,11 @@ static void analyzeOneTable(
int iDb; /* Index of database containing pTab */
u8 needTableCnt = 1; /* True to count the table */
int regNewRowid = iMem++; /* Rowid for the inserted record */
int regStat4 = iMem++; /* Register to hold StatAccum object */
int regStat = iMem++; /* Register to hold StatAccum object */
int regChng = iMem++; /* Index of changed index field */
#ifdef SQLITE_ENABLE_STAT4
int regRowid = iMem++; /* Rowid argument passed to stat_push() */
#endif
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 */
@@ -1083,17 +1105,26 @@ static void analyzeOneTable(
** (1) the number of columns in the index including the rowid
** (or for a WITHOUT ROWID table, the number of PK columns),
** (2) the number of columns in the key without the rowid/pk
** (3) the number of rows in the index,
**
**
** The third argument is only used for STAT4
** (3) estimated number of rows in the index,
*/
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1);
assert( regRowid==regStat+2 );
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid);
#ifdef SQLITE_ENABLE_STAT4
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
if( OptimizationEnabled(db, SQLITE_Stat4) ){
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regTemp);
addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
VdbeCoverage(v);
}else
#endif
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
sqlite3VdbeAddFunctionCall(pParse, 0, regStat4+1, regStat4, 2+IsStat4,
{
addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, 1);
}
assert( regTemp2==regStat+4 );
sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4,
&statInitFuncdef, 0);
/* Implementation of the following:
@@ -1104,8 +1135,6 @@ static void analyzeOneTable(
** goto next_push_0;
**
*/
addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
addrNextRow = sqlite3VdbeCurrentAddr(v);
@@ -1138,6 +1167,7 @@ static void analyzeOneTable(
char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
aGotoChng[i] =
sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
@@ -1158,6 +1188,7 @@ static void analyzeOneTable(
for(i=0; i<nColTest; i++){
sqlite3VdbeJumpHere(v, aGotoChng[i]);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
}
sqlite3VdbeResolveLabel(v, endDistinctTest);
sqlite3DbFree(db, aGotoChng);
@@ -1171,30 +1202,46 @@ static void analyzeOneTable(
** if !eof(csr) goto next_row;
*/
#ifdef SQLITE_ENABLE_STAT4
assert( regRowid==(regStat4+2) );
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
int j, k, regKey;
regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
assert( k>=0 && k<pIdx->nColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
if( OptimizationEnabled(db, SQLITE_Stat4) ){
assert( regRowid==(regStat+2) );
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
int j, k, regKey;
regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
assert( k>=0 && k<pIdx->nColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
}
#endif
assert( regChng==(regStat4+1) );
sqlite3VdbeAddFunctionCall(pParse, 1, regStat4, regTemp, 2+IsStat4,
&statPushFuncdef, 0);
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
assert( regChng==(regStat+1) );
{
sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4,
&statPushFuncdef, 0);
if( db->nAnalysisLimit ){
int j1, j2, j3;
j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); VdbeCoverage(v);
j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); VdbeCoverage(v);
j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1);
VdbeCoverage(v);
sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, j2);
sqlite3VdbeJumpHere(v, j3);
}else{
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
}
}
/* Add the entry to the stat1 table. */
callStatGet(pParse, regStat4, STAT_GET_STAT1, regStat1);
callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1);
assert( "BBB"[0]==SQLITE_AFF_TEXT );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
@@ -1206,7 +1253,7 @@ static void analyzeOneTable(
/* Add the entries to the stat4 table. */
#ifdef SQLITE_ENABLE_STAT4
{
if( OptimizationEnabled(db, SQLITE_Stat4) && db->nAnalysisLimit==0 ){
int regEq = regStat1;
int regLt = regStat1+1;
int regDLt = regStat1+2;
@@ -1220,12 +1267,12 @@ static void analyzeOneTable(
pParse->nMem = MAX(pParse->nMem, regCol+nCol);
addrNext = sqlite3VdbeCurrentAddr(v);
callStatGet(pParse, regStat4, STAT_GET_ROWID, regSampleRowid);
callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid);
addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
VdbeCoverage(v);
callStatGet(pParse, regStat4, STAT_GET_NEQ, regEq);
callStatGet(pParse, regStat4, STAT_GET_NLT, regLt);
callStatGet(pParse, regStat4, STAT_GET_NDLT, regDLt);
callStatGet(pParse, regStat, STAT_GET_NEQ, regEq);
callStatGet(pParse, regStat, STAT_GET_NLT, regLt);
callStatGet(pParse, regStat, STAT_GET_NDLT, regDLt);
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
VdbeCoverage(v);
for(i=0; i<nCol; i++){
-2
View File
@@ -9512,7 +9512,6 @@ int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
return rc;
}
#ifndef SQLITE_OMIT_BTREECOUNT
/*
** The first argument, pCur, is a cursor opened on some b-tree. Count the
** number of entries in the b-tree and write the result to *pnEntry.
@@ -9585,7 +9584,6 @@ int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
/* An error has occurred. Return an error code. */
return rc;
}
#endif
/*
** Return the pager associated with a BTree. This routine is used for
-2
View File
@@ -336,9 +336,7 @@ int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
int sqlite3BtreeCursorIsValidNN(BtCursor*);
#ifndef SQLITE_OMIT_BTREECOUNT
int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
#endif
#ifdef SQLITE_TEST
int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
-3
View File
@@ -514,9 +514,6 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_BLOB_LITERAL
"OMIT_BLOB_LITERAL",
#endif
#if SQLITE_OMIT_BTREECOUNT
"OMIT_BTREECOUNT",
#endif
#if SQLITE_OMIT_CAST
"OMIT_CAST",
#endif
+19 -2
View File
@@ -1729,7 +1729,6 @@ void sqlite3Pragma(
}
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
if( !isQuick ){
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
@@ -1743,7 +1742,6 @@ void sqlite3Pragma(
sqlite3VdbeJumpHere(v, addr);
}
}
#endif /* SQLITE_OMIT_BTREECOUNT */
}
}
{
@@ -2178,6 +2176,25 @@ void sqlite3Pragma(
break;
}
/*
** PRAGMA analysis_limit
** PRAGMA analysis_limit = N
**
** Configure the maximum number of rows that ANALYZE will examine
** in each index that it looks at. Return the new limit.
*/
case PragTyp_ANALYSIS_LIMIT: {
sqlite3_int64 N;
if( zRight
&& sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
&& N>=0
){
db->nAnalysisLimit = (int)(N&0x7fffffff);
}
returnSingleInt(v, db->nAnalysisLimit);
break;
}
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
+50 -44
View File
@@ -6,49 +6,50 @@
/* The various pragma types */
#define PragTyp_ACTIVATE_EXTENSIONS 0
#define PragTyp_HEADER_VALUE 1
#define PragTyp_AUTO_VACUUM 2
#define PragTyp_FLAG 3
#define PragTyp_BUSY_TIMEOUT 4
#define PragTyp_CACHE_SIZE 5
#define PragTyp_CACHE_SPILL 6
#define PragTyp_CASE_SENSITIVE_LIKE 7
#define PragTyp_COLLATION_LIST 8
#define PragTyp_COMPILE_OPTIONS 9
#define PragTyp_DATA_STORE_DIRECTORY 10
#define PragTyp_DATABASE_LIST 11
#define PragTyp_DEFAULT_CACHE_SIZE 12
#define PragTyp_ENCODING 13
#define PragTyp_FOREIGN_KEY_CHECK 14
#define PragTyp_FOREIGN_KEY_LIST 15
#define PragTyp_FUNCTION_LIST 16
#define PragTyp_HARD_HEAP_LIMIT 17
#define PragTyp_INCREMENTAL_VACUUM 18
#define PragTyp_INDEX_INFO 19
#define PragTyp_INDEX_LIST 20
#define PragTyp_INTEGRITY_CHECK 21
#define PragTyp_JOURNAL_MODE 22
#define PragTyp_JOURNAL_SIZE_LIMIT 23
#define PragTyp_LOCK_PROXY_FILE 24
#define PragTyp_LOCKING_MODE 25
#define PragTyp_PAGE_COUNT 26
#define PragTyp_MMAP_SIZE 27
#define PragTyp_MODULE_LIST 28
#define PragTyp_OPTIMIZE 29
#define PragTyp_PAGE_SIZE 30
#define PragTyp_PRAGMA_LIST 31
#define PragTyp_SECURE_DELETE 32
#define PragTyp_SHRINK_MEMORY 33
#define PragTyp_SOFT_HEAP_LIMIT 34
#define PragTyp_SYNCHRONOUS 35
#define PragTyp_TABLE_INFO 36
#define PragTyp_TEMP_STORE 37
#define PragTyp_TEMP_STORE_DIRECTORY 38
#define PragTyp_THREADS 39
#define PragTyp_WAL_AUTOCHECKPOINT 40
#define PragTyp_WAL_CHECKPOINT 41
#define PragTyp_LOCK_STATUS 42
#define PragTyp_STATS 43
#define PragTyp_ANALYSIS_LIMIT 1
#define PragTyp_HEADER_VALUE 2
#define PragTyp_AUTO_VACUUM 3
#define PragTyp_FLAG 4
#define PragTyp_BUSY_TIMEOUT 5
#define PragTyp_CACHE_SIZE 6
#define PragTyp_CACHE_SPILL 7
#define PragTyp_CASE_SENSITIVE_LIKE 8
#define PragTyp_COLLATION_LIST 9
#define PragTyp_COMPILE_OPTIONS 10
#define PragTyp_DATA_STORE_DIRECTORY 11
#define PragTyp_DATABASE_LIST 12
#define PragTyp_DEFAULT_CACHE_SIZE 13
#define PragTyp_ENCODING 14
#define PragTyp_FOREIGN_KEY_CHECK 15
#define PragTyp_FOREIGN_KEY_LIST 16
#define PragTyp_FUNCTION_LIST 17
#define PragTyp_HARD_HEAP_LIMIT 18
#define PragTyp_INCREMENTAL_VACUUM 19
#define PragTyp_INDEX_INFO 20
#define PragTyp_INDEX_LIST 21
#define PragTyp_INTEGRITY_CHECK 22
#define PragTyp_JOURNAL_MODE 23
#define PragTyp_JOURNAL_SIZE_LIMIT 24
#define PragTyp_LOCK_PROXY_FILE 25
#define PragTyp_LOCKING_MODE 26
#define PragTyp_PAGE_COUNT 27
#define PragTyp_MMAP_SIZE 28
#define PragTyp_MODULE_LIST 29
#define PragTyp_OPTIMIZE 30
#define PragTyp_PAGE_SIZE 31
#define PragTyp_PRAGMA_LIST 32
#define PragTyp_SECURE_DELETE 33
#define PragTyp_SHRINK_MEMORY 34
#define PragTyp_SOFT_HEAP_LIMIT 35
#define PragTyp_SYNCHRONOUS 36
#define PragTyp_TABLE_INFO 37
#define PragTyp_TEMP_STORE 38
#define PragTyp_TEMP_STORE_DIRECTORY 39
#define PragTyp_THREADS 40
#define PragTyp_WAL_AUTOCHECKPOINT 41
#define PragTyp_WAL_CHECKPOINT 42
#define PragTyp_LOCK_STATUS 43
#define PragTyp_STATS 44
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -139,6 +140,11 @@ static const PragmaName aPragmaName[] = {
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
{/* zName: */ "analysis_limit",
/* ePragTyp: */ PragTyp_ANALYSIS_LIMIT,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "application_id",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
@@ -639,4 +645,4 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
/* Number of pragmas: 66 on by default, 76 total. */
/* Number of pragmas: 67 on by default, 77 total. */
+1 -4
View File
@@ -6663,7 +6663,6 @@ int sqlite3Select(
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
#ifndef SQLITE_OMIT_BTREECOUNT
Table *pTab;
if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
/* If isSimpleCount() returns a pointer to a Table structure, then
@@ -6721,9 +6720,7 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
explainSimpleCount(pParse, pTab, pBest);
}else
#endif /* SQLITE_OMIT_BTREECOUNT */
{
}else{
int regAcc = 0; /* "populate accumulators" flag */
/* If there are accumulator registers but no min() or max() functions
+1
View File
@@ -1539,6 +1539,7 @@ struct sqlite3 {
BusyHandler busyHandler; /* Busy callback */
Db aDbStatic[2]; /* Static space for the 2 default backends */
Savepoint *pSavepoint; /* List of active savepoints */
int nAnalysisLimit; /* Number of index rows to ANALYZE */
int busyTimeout; /* Busy handler timeout, in msec */
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
+13 -7
View File
@@ -3187,13 +3187,16 @@ case OP_MakeRecord: {
break;
}
/* Opcode: Count P1 P2 * * *
/* Opcode: Count P1 P2 p3 * *
** Synopsis: r[P2]=count()
**
** Store the number of entries (an integer value) in the table or index
** opened by cursor P1 in register P2
** opened by cursor P1 in register P2.
**
** If P3==0, then an exact count is obtained, which involves visiting
** every btree page of the table. But if P3 is non-zero, an estimate
** is returned based on the current cursor position.
*/
#ifndef SQLITE_OMIT_BTREECOUNT
case OP_Count: { /* out2 */
i64 nEntry;
BtCursor *pCrsr;
@@ -3201,14 +3204,17 @@ case OP_Count: { /* out2 */
assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
assert( pCrsr );
nEntry = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
if( rc ) goto abort_due_to_error;
if( pOp->p3 ){
nEntry = sqlite3BtreeRowCountEst(pCrsr);
}else{
nEntry = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
if( rc ) goto abort_due_to_error;
}
pOut = out2Prerelease(p, pOp);
pOut->u.i = nEntry;
goto check_for_interrupt;
}
#endif
/* Opcode: Savepoint P1 * * P4 *
**
+3
View File
@@ -382,6 +382,9 @@ set pragma_def {
NAME: threads
FLAG: Result0
NAME: analysis_limit
FLAG: Result0
NAME: optimize
FLAG: Result1 NeedSchema