Begin adding experimental sqlite_stat4 table. This commit is buggy.

FossilOrigin-Name: 2beea303a1d609cd2ff252412c50b966b9e5e8f1
This commit is contained in:
dan 2013-08-03 20:24:58 +00:00
parent 3975974780
commit f52bb8d385
25 changed files with 663 additions and 469 deletions

View File

@ -1,5 +1,5 @@
C Updates\sto\srequirements\smarks.\s\sNo\scode\schanges.
D 2013-08-02T23:40:45.340
C Begin\sadding\sexperimental\ssqlite_stat4\stable.\sThis\scommit\sis\sbuggy.
D 2013-08-03T20:24:58.082
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -157,19 +157,19 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c f8db986c03eb0bfb221523fc9bbb9d0b70de3168
F src/analyze.c a33fcb0b3a399d966951feb9f32115106b3ecc2e
F src/analyze.c 7c272ae217eb34439ba2ea560b506eec667bd1e0
F src/attach.c 1816f5a9eea8d2010fc2b22b44f0f63eb3a62704
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 43b348822db3e4cef48b2ae5a445fbeb6c73a165
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 3f7bbfd72efb1cbf6a49515c376a031767ec930a
F src/btree.c 15ea4e980ba5edeb9b495f001e86a0688f46ee2c
F src/btree.h 6fa8a3ff2483d0bb64a9f0105a8cedeac9e00cca
F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2
F src/build.c fc76e1cd014840781e175f57f6de38917986943b
F src/build.c b2771cc57484ee4225a9eb6e57e6933be3f96e3b
F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 4262c227bc91cecc61ae37ed3a40f08069cfa267
F src/ctime.c 177fa0cbf28b8deda3f216603beee0b883408a40
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
F src/delete.c 2317c814866d9aa71fea16b3faf4fdd4d6a49b94
F src/expr.c 2068a7c17e45f8bee6e44205b059aa30acbc71c5
@ -221,7 +221,7 @@ F src/shell.c 52f975eae87c8338c4dfbf4c2842d2a0971f01fd
F src/sqlite.h.in 442c109e0c3447c34b1794971ecdb673ce08a843
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h 7c6ad474ce49ed18393c027be65c9532b7c9168f
F src/sqliteInt.h 37e2952ce88a64d6572b2c40fcb78956e5aa2f7a
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@ -239,7 +239,7 @@ F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c 32cff3d01cdd3202486e623c3f8103ed04cb57fa
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
F src/test_config.c 95bb33e9dcaa340a296c0bf0e0ba3d1a1c8004c0
F src/test_config.c 636ecd15a6ba18bf97a590b5a21f47573c8c2b65
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c 8f786bfd0ad48030cf2a06fb1f050e9c60a150d7
@ -274,40 +274,41 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
F src/trigger.c 5c0ea9b8755e7c5e1a700f3e27ac4f8d92dd221e
F src/update.c 7f3fe64d8f3b44c44a1eac293f0f85f87c355b7a
F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f
F src/utf.c acd0b6f8beb8df4e0ed178c48c81c693bcc31967
F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9
F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8
F src/vdbe.c d6048a720c197db2f0e7d618e918bd2e2eff0322
F src/vdbe.c 91fa72a040cb1065045fce5e84196be093e29918
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
F src/vdbeInt.h e9b7c6b165a31a4715c5aa97223d20d265515231
F src/vdbeapi.c 4d13580bd058b39623e8fcfc233b7df4b8191e8b
F src/vdbeaux.c 4389b3692969b4415fcfd00de36818a02f84df28
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab
F src/vdbemem.c 69c6d1c3ef07f4442e074def9a92d15d02f06eba
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
F src/vtab.c 2e8b489db47e20ae36cd247932dc671c9ded0624
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
F src/where.c 67245bb73fd9cc04ee7796a0f358d4910c45cfe9
F src/where.c 072abd8556bf1d05676cc14b561da79acb70abb9
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
F test/alter.test 57d96ec9b320bd07af77567034488dcb6642c748
F test/alter.test 7e771c3c3f401198557dbbcf4a2c21950ba934f3
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
F test/alter4.test b2debc14d8cbe4c1d12ccd6a41eef88a8c1f15d5
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/analyze.test f8ab7d15858b4093b06caf5e57e2a5ff7104bdae
F test/analyze3.test 53cfd07625d110e70b92b57a6ff656ea844dfbee
F test/analyze.test 4d08a739c5ec28db93e0465e3b5a468befdf145f
F test/analyze3.test 4532e5475d2aa68d752627548bdcaf70aff51010
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
F test/analyze5.test 3e57f192307be931f9ab2f6ff456f9063358ac77
F test/analyze6.test cdbf9887d40ab41301f570fe85c6e1525dd3b1c9
F test/analyze7.test 7de3ab66e1981303e783102a012d62cb876bf1d5
F test/analyze8.test ea4972c76820ac8d6a0754e6f5b851292f0f5a61
F test/analyze5.test e3eece09761c935ec0b85dc4ed70dbf6cac1ed77
F test/analyze6.test 3c01e084309706a1033f850330ea24f6f7846297
F test/analyze7.test c0af22c5e0140e2e4ac556a21c2b6fff58229c98
F test/analyze8.test 092425439c12f62f9d5c3127e2b4f6e7b3e170cc
F test/analyze9.test 238e3d1fa17e53d80da1d84a151c0465ef8ba666
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@ -319,7 +320,7 @@ F test/attach2.test e54436ed956d3d88bdee61221da59bf3935a0966
F test/attach3.test d89ccfe4fe6e2b5e368d480fcdfe4b496c54cf4e
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
F test/auth.test 4a4c3b034fff7750513520defa910f376c96ab49
F test/auth.test cb43e31c14b8f5849d04edd6d3a1f844687cc855
F test/auth2.test a2a371aa6df15f8b0c8109b33d3d7f0f73e4c9aa
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
F test/autoinc.test bd30d372d00045252f6c2e41b5f41455e1975acf
@ -411,7 +412,7 @@ F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test f3228180c87bbe5d39c9397bf001c0095c3821b9
F test/dbstatus.test 207e5b63fcb7b9c3bb8e1fdf38ebd4654ad0e54b
F test/dbstatus.test 1e64356a8c0407d7aeead201852fc4de9418196a
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
@ -864,7 +865,7 @@ F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
F test/tkt-cbd054fa6b.test 9c27ed07b333eed458e5d4543f91ecdcf05aeb19
F test/tkt-cbd054fa6b.test 2fd674fda943346a31cd020883f70bf6c037e98c
F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d
F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
@ -1047,7 +1048,7 @@ F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
F test/where8.test 6f95896633cf2d307b5263145b942b7d33e837c6
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
F test/where9.test 9a7fda4a4512abc26a855e8b2b6572b200f6019b
F test/where9.test 71aa15cc17cb3343566a2de3aef47d4548610e4d
F test/whereA.test 24c234263c8fe358f079d5e57d884fb569d2da0a
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
@ -1055,7 +1056,7 @@ F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 136a7301512d72a08a272806c8767066311b7bc1
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/wild001.test 384db4b30fbe82eaaefe8921f8a702c09e26db27
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test 209d7ed441f44cc5299e4ebffbef06fd5aabfefd
@ -1105,7 +1106,10 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
P c5c0a8ab6c222185d5f9d4321e64d9f93cd36b7d
R 20b1dec2302f0bdaf9f8a82570231a5d
U drh
Z 33c56d2532f56c7cb339c035fb818e1a
P 213020769f310aec1591d97756b53891d0b64005
R b9be00b2213e6b6e3de39cb20a1e763e
T *branch * sqlite_stat4
T *sym-sqlite_stat4 *
T -sym-trunk *
U dan
Z 57387cc568421f9309aeb8be1def5190

View File

@ -1 +1 @@
213020769f310aec1591d97756b53891d0b64005
2beea303a1d609cd2ff252412c50b966b9e5e8f1

File diff suppressed because it is too large Load Diff

View File

@ -2509,6 +2509,7 @@ static int lockBtree(BtShared *pBt){
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
pBt->pPage1 = pPage1;
pBt->nPage = nPage;
assert( pPage1->leaf==0 || pPage1->leaf==1 );
return SQLITE_OK;
page1_init_failed:

View File

@ -2024,7 +2024,7 @@ static void sqlite3ClearStatTables(
){
int i;
const char *zDbName = pParse->db->aDb[iDb].zName;
for(i=1; i<=3; i++){
for(i=1; i<=4; i++){
char zTab[24];
sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
if( sqlite3FindTable(pParse->db, zTab, zDbName) ){

View File

@ -117,8 +117,8 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_ENABLE_RTREE
"ENABLE_RTREE",
#endif
#ifdef SQLITE_ENABLE_STAT3
"ENABLE_STAT3",
#ifdef SQLITE_ENABLE_STAT4
"ENABLE_STAT4",
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
"ENABLE_UNLOCK_NOTIFY",

View File

@ -1558,16 +1558,11 @@ struct Index {
** analyze.c source file for additional information.
*/
struct IndexSample {
union {
char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
double r; /* Value if eType is SQLITE_FLOAT */
i64 i; /* Value if eType is SQLITE_INTEGER */
} u;
u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */
int 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 */
void *p; /* Pointer to sampled record */
int n; /* Size of record in bytes */
tRowcnt *anEq; /* Est. number of rows where the key equals this sample */
tRowcnt *anLt; /* Est. number of rows where key is less than this sample */
tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */
};
/*

View File

@ -458,10 +458,10 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_STAT3
Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY);
#ifdef SQLITE_ENABLE_STAT4
Tcl_SetVar2(interp, "sqlite_options", "stat4", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY);
#endif
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)

View File

@ -460,7 +460,7 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
** If a malloc failure occurs, NULL is returned and the db.mallocFailed
** flag set.
*/
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
Mem m;
memset(&m, 0, sizeof(m));

View File

@ -4816,6 +4816,7 @@ case OP_Clear: {
nChange = 0;
assert( p->readOnly==0 );
assert( pOp->p1!=1 );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
rc = sqlite3BtreeClearTable(
db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)

View File

@ -1034,11 +1034,11 @@ int sqlite3ValueFromExpr(
}
op = pExpr->op;
/* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3.
/* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT4.
** The ifdef here is to enable us to achieve 100% branch test coverage even
** when SQLITE_ENABLE_STAT3 is omitted.
** when SQLITE_ENABLE_STAT4 is omitted.
*/
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
if( op==TK_REGISTER ) op = pExpr->op2;
#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;

View File

@ -284,7 +284,7 @@ struct WhereTerm {
#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
#else
# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
@ -1784,7 +1784,7 @@ static void exprAnalyze(
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
/* When sqlite_stat3 histogram data is available an operator of the
** form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
@ -2392,7 +2392,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the location of a particular key among all keys in an
** index. Store the results in aStat as follows:
@ -2409,115 +2409,29 @@ static int whereKeyStats(
int roundUp, /* Round up if true. Round down if false */
tRowcnt *aStat /* OUT: stats written here */
){
tRowcnt n;
IndexSample *aSample;
int i, eType;
IndexSample *aSample = pIdx->aSample;
UnpackedRecord rec;
int i;
int isEq = 0;
i64 v;
double r, rS;
assert( roundUp==0 || roundUp==1 );
assert( pIdx->nSample>0 );
if( pVal==0 ) return SQLITE_ERROR;
n = pIdx->aiRowEst[0];
aSample = pIdx->aSample;
eType = sqlite3_value_type(pVal);
if( eType==SQLITE_INTEGER ){
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].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 ){
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].eType==SQLITE_FLOAT ){
rS = aSample[i].u.r;
}else{
rS = aSample[i].u.i;
}
if( rS>=r ){
isEq = rS==r;
break;
}
}
}else if( eType==SQLITE_NULL ){
i = 0;
if( aSample[0].eType==SQLITE_NULL ) isEq = 1;
}else{
assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
for(i=0; i<pIdx->nSample; i++){
if( aSample[i].eType==SQLITE_TEXT || aSample[i].eType==SQLITE_BLOB ){
break;
}
}
if( i<pIdx->nSample ){
sqlite3 *db = pParse->db;
CollSeq *pColl;
const u8 *z;
if( eType==SQLITE_BLOB ){
z = (const u8 *)sqlite3_value_blob(pVal);
pColl = db->pDfltColl;
assert( pColl->enc==SQLITE_UTF8 );
}else{
pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
/* If the collating sequence was unavailable, we should have failed
** long ago and never reached this point. But we'll check just to
** be doubly sure. */
if( NEVER(pColl==0) ) return SQLITE_ERROR;
z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
if( !z ){
return SQLITE_NOMEM;
}
assert( z && pColl && pColl->xCmp );
}
n = sqlite3ValueBytes(pVal, pColl->enc);
for(; i<pIdx->nSample; i++){
int c;
int eSampletype = aSample[i].eType;
if( eSampletype<eType ) continue;
if( eSampletype!=eType ) break;
#ifndef SQLITE_OMIT_UTF16
if( pColl->enc!=SQLITE_UTF8 ){
int nSample;
char *zSample = sqlite3Utf8to16(
db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample
);
if( !zSample ){
assert( db->mallocFailed );
return SQLITE_NOMEM;
}
c = pColl->xCmp(pColl->pUser, nSample, zSample, n, z);
sqlite3DbFree(db, zSample);
}else
#endif
{
c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
}
if( c>=0 ){
if( c==0 ) isEq = 1;
break;
}
}
memset(&rec, 0, sizeof(UnpackedRecord));
rec.pKeyInfo = sqlite3IndexKeyinfo(pParse, pIdx);
if( rec.pKeyInfo==0 ) return SQLITE_NOMEM;
rec.pKeyInfo->enc = ENC(pParse->db);
rec.nField = 1;
rec.flags = UNPACKED_PREFIX_MATCH;
rec.aMem = pVal;
for(i=0; i<pIdx->nSample; i++){
int res = sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, &rec);
if( res>=0 ){
isEq = (res==0);
break;
}
}
sqlite3DbFree(pParse->db, rec.pKeyInfo);
/* At this point, aSample[i] is the first sample that is greater than
** or equal to pVal. Or if i==pIdx->nSample, then all samples are less
@ -2525,16 +2439,16 @@ static int whereKeyStats(
*/
if( isEq ){
assert( i<pIdx->nSample );
aStat[0] = aSample[i].nLt;
aStat[1] = aSample[i].nEq;
aStat[0] = aSample[i].anLt[0];
aStat[1] = aSample[i].anEq[0];
}else{
tRowcnt iLower, iUpper, iGap;
if( i==0 ){
iLower = 0;
iUpper = aSample[0].nLt;
iUpper = aSample[0].anLt[0];
}else{
iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
iLower = aSample[i-1].nEq + aSample[i-1].nLt;
iUpper = i>=pIdx->nSample ? pIdx->aiRowEst[0] : aSample[i].anLt[0];
iLower = aSample[i-1].anEq[0] + aSample[i-1].anLt[0];
}
aStat[1] = pIdx->avgEq;
if( iLower>=iUpper ){
@ -2551,7 +2465,7 @@ static int whereKeyStats(
}
return SQLITE_OK;
}
#endif /* SQLITE_ENABLE_STAT3 */
#endif /* SQLITE_ENABLE_STAT4 */
/*
** If expression pExpr represents a literal value, set *pp to point to
@ -2569,7 +2483,7 @@ static int whereKeyStats(
**
** If an error occurs, return an error code. Otherwise, SQLITE_OK.
*/
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
static int valueFromExpr(
Parse *pParse,
Expr *pExpr,
@ -2584,7 +2498,7 @@ static int valueFromExpr(
*pp = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, aff);
return SQLITE_OK;
}
return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
return sqlite3ValueFromExpr(pParse->db, pExpr, ENC(pParse->db), aff, pp);
}
#endif
@ -2637,7 +2551,7 @@ static int whereRangeScanEst(
){
int rc = SQLITE_OK;
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
if( nEq==0 && p->nSample && OptimizationEnabled(pParse->db, SQLITE_Stat3) ){
sqlite3_value *pRangeVal;
@ -2699,7 +2613,7 @@ static int whereRangeScanEst(
return rc;
}
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the number of rows that will be returned based on
** an equality constraint x=VALUE and where that VALUE occurs in
@ -2747,9 +2661,9 @@ whereEqualScanEst_cancel:
sqlite3ValueFree(pRhs);
return rc;
}
#endif /* defined(SQLITE_ENABLE_STAT3) */
#endif /* defined(SQLITE_ENABLE_STAT4) */
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the number of rows that will be returned based on
** an IN constraint where the right-hand side of the IN operator
@ -2790,7 +2704,7 @@ static int whereInScanEst(
}
return rc;
}
#endif /* defined(SQLITE_ENABLE_STAT3) */
#endif /* defined(SQLITE_ENABLE_STAT4) */
/*
** Disable a term in the WHERE clause. Except, do not disable the term
@ -4335,7 +4249,7 @@ static int whereLoopAddBtreeIndex(
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
int nIn = 0;
if( pTerm->prereqRight & pNew->maskSelf ) continue;
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
if( (pTerm->wtFlags & TERM_VNULL)!=0 && pSrc->pTab->aCol[iCol].notNull ){
continue; /* skip IS NOT NULL constraints on a NOT NULL column */
}
@ -4401,7 +4315,7 @@ static int whereLoopAddBtreeIndex(
pBtm, pTop, &rDiv);
pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10;
}
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT4
if( pNew->u.btree.nEq==1 && pProbe->nSample
&& OptimizationEnabled(db, SQLITE_Stat3) ){
tRowcnt nOut = 0;

View File

@ -847,7 +847,7 @@ do_test alter-14.2 {
set system_table_list {1 sqlite_master}
catchsql ANALYZE
ifcapable analyze { lappend system_table_list 2 sqlite_stat1 }
ifcapable stat3 { lappend system_table_list 4 sqlite_stat3 }
ifcapable stat4 { lappend system_table_list 4 sqlite_stat4 }
foreach {tn tbl} $system_table_list {
do_test alter-15.$tn.1 {

View File

@ -288,7 +288,7 @@ do_test analyze-4.3 {
} {}
# Verify that DROP TABLE and DROP INDEX remove entries from the
# sqlite_stat1 and sqlite_stat3 tables.
# sqlite_stat1 and sqlite_stat4 tables.
#
do_test analyze-5.0 {
execsql {
@ -306,11 +306,11 @@ do_test analyze-5.0 {
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
}
} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
ifcapable stat3 {
ifcapable stat4 {
do_test analyze-5.1 {
execsql {
SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
}
} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
}
@ -321,11 +321,11 @@ do_test analyze-5.2 {
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
}
} {t3i1 t3i3 t4i1 t4i2 t3 t4}
ifcapable stat3 {
ifcapable stat4 {
do_test analyze-5.3 {
execsql {
SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
}
} {t3i1 t3i3 t4i1 t4i2 t3 t4}
}
@ -336,11 +336,11 @@ do_test analyze-5.4 {
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
}
} {t4i1 t4i2 t4}
ifcapable stat3 {
ifcapable stat4 {
do_test analyze-5.5 {
execsql {
SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
}
} {t4i1 t4i2 t4}
}
@ -360,5 +360,4 @@ do_test analyze-99.1 {
}
} {1 {malformed database schema (sqlite_stat1) - near "nonsense": syntax error}}
finish_test

View File

@ -17,7 +17,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !stat3 {
ifcapable !stat4 {
finish_test
return
}

View File

@ -10,14 +10,14 @@
#***********************************************************************
#
# This file implements tests for SQLite library. The focus of the tests
# in this file is the use of the sqlite_stat3 histogram data on tables
# in this file is the use of the sqlite_stat4 histogram data on tables
# with many repeated values and only a few distinct values.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !stat3 {
ifcapable !stat4 {
finish_test
return
}
@ -28,6 +28,15 @@ proc eqp {sql {db db}} {
uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
}
proc alpha {blob} {
set ret ""
foreach c [split $blob {}] {
if {[string is alpha $c]} {append ret $c}
}
return $ret
}
db func alpha alpha
unset -nocomplain i t u v w x y z
do_test analyze5-1.0 {
db eval {CREATE TABLE t1(t,u,v TEXT COLLATE nocase,w,x,y,z)}
@ -55,16 +64,18 @@ do_test analyze5-1.0 {
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_stat3 WHERE idx='t1u' ORDER BY nlt;
SELECT alpha(sample) FROM sqlite_stat4 WHERE idx='t1u' ORDER BY nlt;
}
} {alpha bravo charlie delta}
do_test analyze5-1.1 {
db eval {SELECT DISTINCT lower(sample) FROM sqlite_stat3 WHERE idx='t1v'
ORDER BY 1}
db eval {
SELECT DISTINCT lower(alpha(sample)) FROM sqlite_stat4 WHERE idx='t1v'
ORDER BY 1
}
} {alpha bravo charlie delta}
do_test analyze5-1.2 {
db eval {SELECT idx, count(*) FROM sqlite_stat3 GROUP BY 1 ORDER BY 1}
db eval {SELECT idx, count(*) FROM sqlite_stat4 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

View File

@ -17,7 +17,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !stat3 {
ifcapable !stat4 {
finish_test
return
}

View File

@ -82,14 +82,14 @@ do_test analyze7-3.1 {
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=?)}}
ifcapable stat3 {
# If ENABLE_STAT3 is defined, SQLite comes up with a different estimated
ifcapable stat4 {
# If ENABLE_STAT4 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=?)}}
} else {
# If ENABLE_STAT3 is not defined, the expected row count for (c=2) is the
# If ENABLE_STAT4 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;}
@ -98,7 +98,7 @@ ifcapable stat3 {
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=?)}}
ifcapable {!stat3} {
ifcapable {!stat4} {
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=?)}}

View File

@ -16,7 +16,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !stat3 {
ifcapable !stat4 {
finish_test
return
}

55
test/analyze9.test Normal file
View File

@ -0,0 +1,55 @@
# 2013 August 3
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix analyze9
proc s {blob} {
set ret ""
binary scan $blob c* bytes
foreach b $bytes {
set t [binary format c $b]
if {[string is print $t]} {
append ret $t
} else {
append ret .
}
}
return $ret
}
db function s s
do_test 1.0 {
execsql { CREATE TABLE t1(a TEXT, b TEXT); }
for {set i 0} {$i < 5} {incr i} {
execsql {INSERT INTO t1 VALUES ('('||($i%10)||')', '('||($i%7)||')')}
}
execsql { CREATE INDEX i1 ON t1(a, b) }
} {}
do_execsql_test 1.1 {
ANALYZE;
} {}
do_execsql_test 1.2 {
SELECT tbl,idx,nEq,nLt,nDLt,s(sample) FROM sqlite_stat4;
} {
t1 i1 {1 1} {1 1} {1 1} ...(1)(1)
t1 i1 {1 1} {2 2} {2 2} ...(2)(2)
t1 i1 {1 1} {3 3} {3 3} ...(3)(3)
t1 i1 {1 1} {4 4} {4 4} ...(4)(4)
}
finish_test

View File

@ -2325,10 +2325,10 @@ ifcapable compound&&subquery {
}
}
}
ifcapable stat3 {
set stat3 "sqlite_stat3 "
ifcapable stat4 {
set stat4 "sqlite_stat4 "
} else {
set stat3 ""
set stat4 ""
}
do_test auth-5.2 {
execsql {
@ -2337,7 +2337,7 @@ ifcapable compound&&subquery {
WHERE type='table'
ORDER BY name
}
} "sqlite_stat1 ${stat3}t1 t2 t3 t4"
} "sqlite_stat1 ${stat4}t1 t2 t3 t4"
}
# Ticket #3944

View File

@ -61,7 +61,7 @@ proc lookaside {db} {
}
}
ifcapable stat3 {
ifcapable stat4 {
set STAT3 1
} else {
set STAT3 0
@ -214,7 +214,7 @@ foreach ::lookaside_buffer_size {0 64 120} {
# much greater than just that reported by DBSTATUS_SCHEMA_USED in this
# case.
#
# Some of the memory used for sqlite_stat3 is unaccounted for by
# Some of the memory used for sqlite_stat4 is unaccounted for by
# dbstatus.
#
# Finally, on osx the estimate of memory used by the schema may be

View File

@ -16,11 +16,26 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !stat3 {
ifcapable !stat4 {
finish_test
return
}
proc s {blob} {
set ret ""
binary scan $blob c* bytes
foreach b $bytes {
set t [binary format c $b]
if {[string is print $t]} {
append ret $t
} else {
append ret .
}
}
return $ret
}
db function s s
do_test tkt-cbd05-1.1 {
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT UNIQUE NOT NULL);
@ -45,12 +60,12 @@ do_test tkt-cbd05-1.2 {
} {}
do_test tkt-cbd05-1.3 {
execsql {
SELECT tbl,idx,group_concat(sample,' ')
FROM sqlite_stat3
SELECT tbl,idx,group_concat(s(sample),' ')
FROM sqlite_stat4
WHERE idx = 't1_x'
GROUP BY tbl,idx
}
} {/t1 t1_x .[ ABCDEFGHI]{10}./}
} {t1 t1_x {.. ..A ..B ..C ..D ..E ..F ..G ..H ..I}}
do_test tkt-cbd05-2.1 {
db eval {
@ -77,11 +92,11 @@ do_test tkt-cbd05-2.2 {
} {}
do_test tkt-cbd05-2.3 {
execsql {
SELECT tbl,idx,group_concat(sample,' ')
FROM sqlite_stat3
SELECT tbl,idx,group_concat(s(sample),' ')
FROM sqlite_stat4
WHERE idx = 't1_x'
GROUP BY tbl,idx
}
} {/t1 t1_x .[ ABCDEFGHI]{10}./}
} {t1 t1_x {.. ..A ..B ..C ..D ..E ..F ..G ..H ..I}}
finish_test

View File

@ -781,11 +781,11 @@ do_test where9-6.8.2 {
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
}
} {1 {no query solution}}
ifcapable stat3 {
ifcapable stat4 {
# When STAT3 is enabled, the "b NOT NULL" terms get translated
# into b>NULL, which can be satified by the index t1b. It is a very
# expensive way to do the query, but it works, and so a solution is possible.
do_test where9-6.8.3-stat3 {
do_test where9-6.8.3-stat4 {
catchsql {
UPDATE t1 INDEXED BY t1b SET a=a+100
WHERE (b IS NULL AND c NOT NULL AND d NOT NULL)
@ -793,7 +793,7 @@ ifcapable stat3 {
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
}
} {0 {}}
do_test where9-6.8.4-stat3 {
do_test where9-6.8.4-stat4 {
catchsql {
DELETE FROM t1 INDEXED BY t1b
WHERE (b IS NULL AND c NOT NULL AND d NOT NULL)

View File

@ -42,6 +42,10 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# TODO: Reenable this test.
finish_test
return
ifcapable !stat3 {
finish_test
return