-C Add\sthe\ssqlite_stat3.nDLT\sfield.\s\sUse\san\slinear\scongruence\sPRNG\sto\schoose\nwhich\ssamples\sto\sselect\sfrom\samong\sthose\swith\sthe\ssame\snEq\sfield.
-D 2011-08-13T15:25:10.607
+C Further\stesting\sand\sbug\sfixing\sfor\ssqlite_stat3.\s\sAdded\sthe\sIndex.avgEq\nfield\sto\sindex\sstatistics.\s\sFixed\sseveral\sproblems\sin\sthe\squery\splanner\nassociated\swith\sstat3.
+D 2011-08-13T19:35:19.088
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 1e6988b3c11dee9bd5edc0c804bd4468d74a9cdc
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c ac80a0f31189f8b4a524ebf661e47e84536ee7f5
-F src/analyze.c 6901cc6e91cc6d4a6b584025f58ec2839783b6c3
+F src/analyze.c c04d95f4dc82b94250c4053ca36cc52b42f257ea
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
F src/btree.c 8c46f0ab69ad9549c75a3a91fed87abdaa743e2f
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
-F src/build.c 4165efa323b4d3678a6b39fddb775627c18e9a80
+F src/build.c cd77ae979219d6363234b506de28c71f217063e1
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 0df87f944b17c17c6b3976a9758d8af2802e1b19
F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd
F src/sqlite.h.in e8eb090406b9a743befff4c387aa3bd5eeae661e
F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93
-F src/sqliteInt.h a4c0124ff6dbbf325002b4a34248cc08453c9739
+F src/sqliteInt.h f491be51e47267ae1454317fbd3438382e60fdb3
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c 24d95b218176bad38ae2abe73197c28d3d6ef9a6
+F src/where.c 118896232fe70b1ac9c2ef2811675d5bef8b9c40
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
F test/alter4.test b2debc14d8cbe4c1d12ccd6a41eef88a8c1f15d5
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
-F test/analyze.test 68b43c1f9cd6ffc3bbb30d27a23712b38c413eca
+F test/analyze.test f8ab7d15858b4093b06caf5e57e2a5ff7104bdae
F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
-F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
+F test/analyze3.test d5e4da00a37b927d83aead50626c254a785c111f
F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
-F test/analyze5.test 1de8d66b11aae5a1453aa042d62e834a476bac9c
+F test/analyze5.test 713354664c5ff1853ab2cbcb740f0cf5cb7c802e
F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290
-F test/analyze7.test 5508e7828164ea0b518ed219bed7320a481863d4
+F test/analyze7.test d3587aa5af75c9048d031b94fceca2534fa75d1d
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test a18a2ce81add84b17b06559e82ad7bb91bc6ddff
-F test/dbstatus.test a719af0f226bd280748a4bb9054c0a5a9fc1b16c
+F test/dbstatus.test 9eb484ba837c6f3f9bbcaecc29e6060a8c3ba6d2
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/stat.test 0997f6a57a35866b14111ed361ed8851ce7978ae
-F test/stat3.test 44cec64164a2f5d86960343a118bc0bdac754f61
+F test/stat3.test 986d735f70ef62a1daf98e8762f35fa3b062c5c3
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
F test/unixexcl.test 9d80a54d86d2261f660758928959368ffc36151e
-F test/unordered.test e81169ce2a8f31b2c6b66af691887e1376ab3ced
+F test/unordered.test f53095cee37851bf30130fa1bf299a8845e837bb
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
F test/uri.test 53de9a2549cbda9c343223236918ef502f6a9051
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262
-P 8225924ea015a0c331b69134139922ec83f989f8
-R 26e2ba931d588fb68b0f6f40c6d0c97e
+P 1dcd24283e6c1cc638eb9ffac434046447f88769
+R d1b65b54090c71db8593e348e48cfb27
U drh
-Z 3074616e4d36d00fd7fabd4dfdb13fe0
+Z 11276de2d321825346f710e3928eda70
-1dcd24283e6c1cc638eb9ffac434046447f88769
\ No newline at end of file
+89b2f70884cad0abdf4c66cb64ecddb2820ded74
\ No newline at end of file
assert( pIdx->nSample==0 );
pIdx->nSample = (u8)nSample;
pIdx->aSample = sqlite3MallocZero( nSample*sizeof(IndexSample) );
+ pIdx->avgEq = pIdx->aiRowEst[1];
if( pIdx->aSample==0 ){
db->mallocFailed = 1;
sqlite3_finalize(pStmt);
sqlite3_finalize(pStmt);
zSql = sqlite3MPrintf(db,
- "SELECT idx,nlt,neq,sample FROM %Q.sqlite_stat3", zDb);
+ "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
if( !zSql ){
return SQLITE_NOMEM;
}
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char *zIndex; /* Index name */
Index *pIdx; /* Pointer to the index object */
+ int i; /* Loop counter */
+ tRowcnt sumEq; /* Sum of the nEq values */
zIndex = (char *)sqlite3_column_text(pStmt, 0);
if( zIndex==0 ) continue;
}
assert( idx<pIdx->nSample );
pSample = &pIdx->aSample[idx];
- pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 1);
- pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 2);
- eType = sqlite3_column_type(pStmt, 3);
+ pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 1);
+ pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 2);
+ pSample->nDLt = (tRowcnt)sqlite3_column_int64(pStmt, 3);
+ if( idx==pIdx->nSample-1 ){
+ if( pSample->nDLt>0 ){
+ for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq;
+ pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt;
+ }
+ if( pIdx->avgEq<=0 ) pIdx->avgEq = 1;
+ }
+ eType = sqlite3_column_type(pStmt, 4);
pSample->eType = (u8)eType;
switch( eType ){
case SQLITE_INTEGER: {
- pSample->u.i = sqlite3_column_int64(pStmt, 3);
+ pSample->u.i = sqlite3_column_int64(pStmt, 4);
break;
}
case SQLITE_FLOAT: {
- pSample->u.r = sqlite3_column_double(pStmt, 3);
+ pSample->u.r = sqlite3_column_double(pStmt, 4);
break;
}
case SQLITE_NULL: {
default: assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); {
const char *z = (const char *)(
(eType==SQLITE_BLOB) ?
- sqlite3_column_blob(pStmt, 3):
- sqlite3_column_text(pStmt, 3)
+ sqlite3_column_blob(pStmt, 4):
+ sqlite3_column_text(pStmt, 4)
);
- int n = sqlite3_column_bytes(pStmt, 2);
+ int n = sqlite3_column_bytes(pStmt, 4);
if( n>0xffff ) n = 0xffff;
pSample->nByte = (u16)n;
if( n < 1){
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
- sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3FkDropTable(pParse, pName, pTab);
sqlite3CodeDropTable(pParse, pTab, iDb, isView);
+ sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
}
exit_drop_table:
u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */
char **azColl; /* Array of collation sequence names for index */
#ifdef SQLITE_ENABLE_STAT3
+ tRowcnt avgEq; /* Average nEq value for key values not in aSample */
IndexSample *aSample; /* Samples of the left-most key */
#endif
};
u16 nByte; /* Size in byte of text or blob. */
tRowcnt nEq; /* Est. number of rows where the key equals this sample */
tRowcnt nLt; /* Est. number of rows where key is less than this sample */
+ tRowcnt nDLt; /* Est. number of distinct keys less than this sample */
};
/*
IndexSample *aSample;
int i, eType;
int isEq = 0;
+ i64 v;
+ double r, rS;
assert( roundUp==0 || roundUp==1 );
if( pVal==0 ) return SQLITE_ERROR;
eType = sqlite3_value_type(pVal);
if( eType==SQLITE_INTEGER ){
- i64 v = sqlite3_value_int64(pVal);
+ v = sqlite3_value_int64(pVal);
+ r = (i64)v;
for(i=0; i<pIdx->nSample; i++){
if( aSample[i].eType==SQLITE_NULL ) continue;
if( aSample[i].eType>=SQLITE_TEXT ) break;
- if( aSample[i].u.i>=v ){
- isEq = aSample[i].u.i==v;
- break;
+ if( aSample[i].eType==SQLITE_INTEGER ){
+ if( aSample[i].u.i>=v ){
+ isEq = aSample[i].u.i==v;
+ break;
+ }
+ }else{
+ assert( aSample[i].eType==SQLITE_FLOAT );
+ if( aSample[i].u.r>=r ){
+ isEq = aSample[i].u.r==r;
+ break;
+ }
}
}
}else if( eType==SQLITE_FLOAT ){
- double r = sqlite3_value_double(pVal);
+ r = sqlite3_value_double(pVal);
for(i=0; i<pIdx->nSample; i++){
if( aSample[i].eType==SQLITE_NULL ) continue;
if( aSample[i].eType>=SQLITE_TEXT ) break;
- if( aSample[i].u.r>=r ){
- isEq = aSample[i].u.r==r;
+ if( aSample[i].eType==SQLITE_FLOAT ){
+ rS = aSample[i].u.r;
+ }else{
+ rS = aSample[i].u.i;
+ }
+ if( rS>=r ){
+ isEq = rS==r;
break;
}
}
if( i==0 ){
iLower = 0;
iUpper = aSample[0].nLt;
- }else if( i>=pIdx->nSample ){
- iUpper = n;
- iLower = aSample[i].nEq + aSample[i].nLt;
}else{
+ iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
iLower = aSample[i-1].nEq + aSample[i-1].nLt;
- iUpper = aSample[i].nLt;
}
- aStat[1] = pIdx->aiRowEst[1];
+ aStat[1] = pIdx->avgEq;
if( iLower>=iUpper ){
iGap = 0;
}else{
int nEq, /* index into p->aCol[] of the range-compared column */
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
- tRowcnt *pRangeDiv /* OUT: Reduce search space by this divisor */
+ double *pRangeDiv /* OUT: Reduce search space by this divisor */
){
int rc = SQLITE_OK;
&& whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
){
iUpper = a[0];
- if( pLower->eOperator==WO_LE ) iUpper += a[1];
+ if( pUpper->eOperator==WO_LE ) iUpper += a[1];
}
sqlite3ValueFree(pRangeVal);
}
if( rc==SQLITE_OK ){
if( iUpper<=iLower ){
- *pRangeDiv = p->aiRowEst[0];
+ *pRangeDiv = (double)p->aiRowEst[0];
}else{
- *pRangeDiv = p->aiRowEst[0]/(iUpper - iLower);
+ *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower);
}
- WHERETRACE(("range scan regions: %u..%u div=%u\n",
- (u32)iLower, (u32)iUpper, (u32)*pRangeDiv));
+ WHERETRACE(("range scan regions: %u..%u div=%g\n",
+ (u32)iLower, (u32)iUpper, *pRangeDiv));
return SQLITE_OK;
}
}
UNUSED_PARAMETER(nEq);
#endif
assert( pLower || pUpper );
- *pRangeDiv = 1;
- if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= 4;
- if( pUpper ) *pRangeDiv *= 4;
+ *pRangeDiv = (double)1;
+ if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4;
+ if( pUpper ) *pRangeDiv *= (double)4;
return rc;
}
int nEq; /* Number of == or IN terms matching index */
int bInEst = 0; /* True if "x IN (SELECT...)" seen */
int nInMul = 1; /* Number of distinct equalities to lookup */
- tRowcnt rangeDiv = 1; /* Estimated reduction in search space */
+ double rangeDiv = (double)1; /* Estimated reduction in search space */
int nBound = 0; /* Number of range constraints seen */
int bSort = !!pOrderBy; /* True if external sort required */
int bDist = !!pDistinct; /* True if index cannot help with DISTINCT */
/* Adjust the number of output rows and downward to reflect rows
** that are excluded by range constraints.
*/
- nRow = nRow/(double)rangeDiv;
+ nRow = nRow/rangeDiv;
if( nRow<1 ) nRow = 1;
/* Experiments run on real SQLite databases show that the time needed
} {}
# Verify that DROP TABLE and DROP INDEX remove entries from the
-# sqlite_stat1 and sqlite_stat2 tables.
+# sqlite_stat1 and sqlite_stat3 tables.
#
do_test analyze-5.0 {
execsql {
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
}
} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
-ifcapable stat2 {
+ifcapable stat3 {
do_test analyze-5.1 {
execsql {
- SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1;
- SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1;
+ SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
}
} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
}
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
}
} {t3i1 t3i3 t4i1 t4i2 t3 t4}
-ifcapable stat2 {
+ifcapable stat3 {
do_test analyze-5.3 {
execsql {
- SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1;
- SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1;
+ SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
}
} {t3i1 t3i3 t4i1 t4i2 t3 t4}
}
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
}
} {t4i1 t4i2 t4}
-ifcapable stat2 {
+ifcapable stat3 {
do_test analyze-5.5 {
execsql {
- SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1;
- SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1;
+ SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
}
} {t4i1 t4i2 t4}
}
do_eqp_test analyze3-1.1.2 {
SELECT sum(y) FROM t1 WHERE x>200 AND x<300
-} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?) (~100 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?) (~179 rows)}}
do_eqp_test analyze3-1.1.3 {
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
-} {0 0 0 {SCAN TABLE t1 (~111 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? and x<?) {~959 rows)}}
do_test analyze3-1.1.4 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
} {}
do_eqp_test analyze3-1.3.2 {
SELECT sum(y) FROM t3 WHERE x>200 AND x<300
-} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?) (~100 rows)}}
+} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?) (~166 rows)}}
do_eqp_test analyze3-1.3.3 {
SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
} {0 0 0 {SCAN TABLE t3 (~111 rows)}}
} {}
do_eqp_test analyze3-2.2 {
SELECT count(a) FROM t1 WHERE b LIKE 'a%'
-} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?) (~30000 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?) (~31250 rows)}}
do_eqp_test analyze3-2.3 {
SELECT count(a) FROM t1 WHERE b LIKE '%a'
} {0 0 0 {SCAN TABLE t1 (~500000 rows)}}
#***********************************************************************
#
# This file implements tests for SQLite library. The focus of the tests
-# in this file is the use of the sqlite_stat2 histogram data on tables
+# in this file is the use of the sqlite_stat3 histogram data on tables
# with many repeated values and only a few distinct values.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-ifcapable !stat2 {
+ifcapable !stat3 {
finish_test
return
}
CREATE INDEX t1y ON t1(y); -- integers 0 and very few 1s
CREATE INDEX t1z ON t1(z); -- integers 0, 1, 2, and 3
ANALYZE;
- SELECT sample FROM sqlite_stat2 WHERE idx='t1u' ORDER BY sampleno;
+ SELECT sample FROM sqlite_stat3 WHERE idx='t1u' ORDER BY nlt;
}
-} {alpha alpha alpha alpha bravo bravo bravo charlie charlie delta}
+} {alpha bravo charlie delta}
+
do_test analyze5-1.1 {
- string tolower \
- [db eval {SELECT sample from sqlite_stat2 WHERE idx='t1v' ORDER BY sampleno}]
-} {alpha alpha alpha alpha bravo bravo bravo charlie charlie delta}
+ db eval {SELECT DISTINCT lower(sample) FROM sqlite_stat3 WHERE idx='t1v'
+ ORDER BY 1}
+} {alpha bravo charlie delta}
do_test analyze5-1.2 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1w' ORDER BY sampleno}
-} {{} 0 0 0 0 1 1 1 2 2}
-do_test analyze5-1.3 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1x' ORDER BY sampleno}
-} {{} {} {} {} 1 1 1 2 2 3}
-do_test analyze5-1.4 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1y' ORDER BY sampleno}
-} {0 0 0 0 0 0 0 0 0 0}
-do_test analyze5-1.5 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1z' ORDER BY sampleno}
-} {0 0 0 0 1 1 1 2 2 3}
-do_test analyze5-1.6 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1t' ORDER BY sampleno}
-} {0.5 0.5 0.5 0.5 1.5 1.5 1.5 2.5 2.5 3.5}
-
+ db eval {SELECT idx, count(*) FROM sqlite_stat3 GROUP BY 1 ORDER BY 1}
+} {t1t 4 t1u 4 t1v 4 t1w 4 t1x 4 t1y 2 t1z 4}
# Verify that range queries generate the correct row count estimates
#
foreach {testid where index rows} {
1 {z>=0 AND z<=0} t1z 400
2 {z>=1 AND z<=1} t1z 300
- 3 {z>=2 AND z<=2} t1z 200
- 4 {z>=3 AND z<=3} t1z 100
- 5 {z>=4 AND z<=4} t1z 50
- 6 {z>=-1 AND z<=-1} t1z 50
- 7 {z>1 AND z<3} t1z 200
+ 3 {z>=2 AND z<=2} t1z 175
+ 4 {z>=3 AND z<=3} t1z 125
+ 5 {z>=4 AND z<=4} t1z 1
+ 6 {z>=-1 AND z<=-1} t1z 1
+ 7 {z>1 AND z<3} t1z 175
8 {z>0 AND z<100} t1z 600
9 {z>=1 AND z<100} t1z 600
10 {z>1 AND z<100} t1z 300
11 {z>=2 AND z<100} t1z 300
- 12 {z>2 AND z<100} t1z 100
- 13 {z>=3 AND z<100} t1z 100
- 14 {z>3 AND z<100} t1z 50
- 15 {z>=4 AND z<100} t1z 50
- 16 {z>=-100 AND z<=-1} t1z 50
+ 12 {z>2 AND z<100} t1z 125
+ 13 {z>=3 AND z<100} t1z 125
+ 14 {z>3 AND z<100} t1z 1
+ 15 {z>=4 AND z<100} t1z 1
+ 16 {z>=-100 AND z<=-1} t1z 1
17 {z>=-100 AND z<=0} t1z 400
- 18 {z>=-100 AND z<0} t1z 50
+ 18 {z>=-100 AND z<0} t1z 1
19 {z>=-100 AND z<=1} t1z 700
20 {z>=-100 AND z<2} t1z 700
- 21 {z>=-100 AND z<=2} t1z 900
- 22 {z>=-100 AND z<3} t1z 900
+ 21 {z>=-100 AND z<=2} t1z 875
+ 22 {z>=-100 AND z<3} t1z 875
31 {z>=0.0 AND z<=0.0} t1z 400
32 {z>=1.0 AND z<=1.0} t1z 300
- 33 {z>=2.0 AND z<=2.0} t1z 200
- 34 {z>=3.0 AND z<=3.0} t1z 100
- 35 {z>=4.0 AND z<=4.0} t1z 50
- 36 {z>=-1.0 AND z<=-1.0} t1z 50
- 37 {z>1.5 AND z<3.0} t1z 200
- 38 {z>0.5 AND z<100} t1z 600
+ 33 {z>=2.0 AND z<=2.0} t1z 175
+ 34 {z>=3.0 AND z<=3.0} t1z 125
+ 35 {z>=4.0 AND z<=4.0} t1z 1
+ 36 {z>=-1.0 AND z<=-1.0} t1z 1
+ 37 {z>1.5 AND z<3.0} t1z 174
+ 38 {z>0.5 AND z<100} t1z 599
39 {z>=1.0 AND z<100} t1z 600
- 40 {z>1.5 AND z<100} t1z 300
+ 40 {z>1.5 AND z<100} t1z 299
41 {z>=2.0 AND z<100} t1z 300
- 42 {z>2.1 AND z<100} t1z 100
- 43 {z>=3.0 AND z<100} t1z 100
- 44 {z>3.2 AND z<100} t1z 50
- 45 {z>=4.0 AND z<100} t1z 50
- 46 {z>=-100 AND z<=-1.0} t1z 50
+ 42 {z>2.1 AND z<100} t1z 124
+ 43 {z>=3.0 AND z<100} t1z 125
+ 44 {z>3.2 AND z<100} t1z 1
+ 45 {z>=4.0 AND z<100} t1z 1
+ 46 {z>=-100 AND z<=-1.0} t1z 1
47 {z>=-100 AND z<=0.0} t1z 400
- 48 {z>=-100 AND z<0.0} t1z 50
+ 48 {z>=-100 AND z<0.0} t1z 1
49 {z>=-100 AND z<=1.0} t1z 700
50 {z>=-100 AND z<2.0} t1z 700
- 51 {z>=-100 AND z<=2.0} t1z 900
- 52 {z>=-100 AND z<3.0} t1z 900
+ 51 {z>=-100 AND z<=2.0} t1z 875
+ 52 {z>=-100 AND z<3.0} t1z 875
- 101 {z=-1} t1z 50
+ 101 {z=-1} t1z 1
102 {z=0} t1z 400
103 {z=1} t1z 300
- 104 {z=2} t1z 200
- 105 {z=3} t1z 100
- 106 {z=4} t1z 50
- 107 {z=-10.0} t1z 50
+ 104 {z=2} t1z 175
+ 105 {z=3} t1z 125
+ 106 {z=4} t1z 1
+ 107 {z=-10.0} t1z 1
108 {z=0.0} t1z 400
109 {z=1.0} t1z 300
- 110 {z=2.0} t1z 200
- 111 {z=3.0} t1z 100
- 112 {z=4.0} t1z 50
- 113 {z=1.5} t1z 50
- 114 {z=2.5} t1z 50
+ 110 {z=2.0} t1z 175
+ 111 {z=3.0} t1z 125
+ 112 {z=4.0} t1z 1
+ 113 {z=1.5} t1z 1
+ 114 {z=2.5} t1z 1
- 201 {z IN (-1)} t1z 50
+ 201 {z IN (-1)} t1z 1
202 {z IN (0)} t1z 400
203 {z IN (1)} t1z 300
- 204 {z IN (2)} t1z 200
- 205 {z IN (3)} t1z 100
- 206 {z IN (4)} t1z 50
- 207 {z IN (0.5)} t1z 50
+ 204 {z IN (2)} t1z 175
+ 205 {z IN (3)} t1z 125
+ 206 {z IN (4)} t1z 1
+ 207 {z IN (0.5)} t1z 1
208 {z IN (0,1)} t1z 700
- 209 {z IN (0,1,2)} t1z 900
+ 209 {z IN (0,1,2)} t1z 875
210 {z IN (0,1,2,3)} {} 100
211 {z IN (0,1,2,3,4,5)} {} 100
- 212 {z IN (1,2)} t1z 500
+ 212 {z IN (1,2)} t1z 475
213 {z IN (2,3)} t1z 300
214 {z=3 OR z=2} t1z 300
- 215 {z IN (-1,3)} t1z 150
- 216 {z=-1 OR z=3} t1z 150
+ 215 {z IN (-1,3)} t1z 126
+ 216 {z=-1 OR z=3} t1z 126
- 300 {y=0} {} 100
- 301 {y=1} t1y 50
- 302 {y=0.1} t1y 50
+ 300 {y=0} t1y 974
+ 301 {y=1} t1y 26
+ 302 {y=0.1} t1y 1
400 {x IS NULL} t1x 400
# Verify that range queries generate the correct row count estimates
#
foreach {testid where index rows} {
- 500 {x IS NULL AND u='charlie'} t1u 20
- 501 {x=1 AND u='charlie'} t1x 5
- 502 {x IS NULL} {} 100
- 503 {x=1} t1x 50
- 504 {x IS NOT NULL} t1x 25
+ 500 {x IS NULL AND u='charlie'} t1u 17
+ 501 {x=1 AND u='charlie'} t1x 1
+ 502 {x IS NULL} t1x 995
+ 503 {x=1} t1x 1
+ 504 {x IS NOT NULL} t1x 2
505 {+x IS NOT NULL} {} 500
506 {upper(x) IS NOT NULL} {} 500
} {
# Verify that the expected index is used with the expected row count
+if {$testid==50299} {breakpoint; set sqlite_where_trace 1}
do_test analyze5-1.${testid}a {
set x [lindex [eqp "SELECT * FROM t1 WHERE $where"] 3]
set idx {}
regexp {~([0-9]+) rows} $x all nrow
list $idx $nrow
} [list $index $rows]
+if {$testid==50299} exit
# Verify that the same result is achieved regardless of whether or not
# the index is used
do_test analyze7-3.2.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~86 rows)}}
-ifcapable stat2 {
- # If ENABLE_STAT2 is defined, SQLite comes up with a different estimated
+ifcapable stat3 {
+ # If ENABLE_STAT3 is defined, SQLite comes up with a different estimated
# row count for (c=2) than it does for (c=?).
do_test analyze7-3.2.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
- } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~51 rows)}}
+ } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~57 rows)}}
} else {
- # If ENABLE_STAT2 is not defined, the expected row count for (c=2) is the
+ # If ENABLE_STAT3 is not defined, the expected row count for (c=2) is the
# same as that for (c=?).
do_test analyze7-3.2.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
do_test analyze7-3.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
-do_test analyze7-3.4 {
- execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
-} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
-do_test analyze7-3.5 {
- execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
-} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+ifcapable {!stat3} {
+ do_test analyze7-3.4 {
+ execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
+ } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
+ do_test analyze7-3.5 {
+ execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
+ } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+}
do_test analyze7-3.6 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?) (~1 rows)}}
}
}
+ifcapable stat3 {
+ set STAT3 1
+} else {
+ set STAT3 0
+}
+
#---------------------------------------------------------------------------
# Run the dbstatus-2 and dbstatus-3 tests with several of different
# lookaside buffer sizes.
CREATE TABLE t2(c, d);
CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
}
- 6 {
+ 6y {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(a,b);
# much greater than just that reported by DBSTATUS_SCHEMA_USED in this
# case.
#
- if {[string match *x $tn] || $AUTOVACUUM} {
+ # Some of the memory used for sqlite_stat3 is unaccounted for by
+ # dbstatus.
+ #
+ if {[string match *x $tn] || $AUTOVACUUM
+ || ([string match *y $tn] && $STAT3)} {
do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
} else {
do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
#
# This file implements regression tests for SQLite library. This file
# implements tests for the extra functionality provided by the ANALYZE
-# command when the library is compiled with SQLITE_ENABLE_STAT2 defined.
+# command when the library is compiled with SQLITE_ENABLE_STAT3 defined.
#
set testdir [file dirname $argv0]
db eval {
PRAGMA writable_schema=ON;
CREATE TABLE sqlite_stat2(tbl,idx,sampleno,sample);
- CREATE TABLE sqlite_stat3(tbl,idx,sampleno,sample,neq,nlt);
+ CREATE TABLE sqlite_stat3(tbl,idx,neq,nlt,ndlt,sample);
SELECT name FROM sqlite_master ORDER BY 1;
}
} {sqlite_stat2 sqlite_stat3}
} {}
foreach idxmode {ordered unordered} {
+ catchsql { DELETE FROM sqlite_stat2 }
+ catchsql { DELETE FROM sqlite_stat3 }
if {$idxmode == "unordered"} {
execsql { UPDATE sqlite_stat1 SET stat = stat || ' unordered' }
- db close
- sqlite3 db test.db
}
+ db close
+ sqlite3 db test.db
foreach {tn sql r(ordered) r(unordered)} {
1 "SELECT * FROM t1 ORDER BY a"
{0 0 0 {SCAN TABLE t1 USING INDEX i1 (~128 rows)}}