If ENABLE_STAT3 is defined but ENABLE_STAT4 is not, have ANALYZE create and populate the sqlite_stat3 table instead of sqlite_stat4.
FossilOrigin-Name: cca8bf4372ab7a0258aa5c9397818415c6cf0abf
This commit is contained in:
parent
86f69d98d2
commit
8ad169abb4
48
manifest
48
manifest
@ -1,5 +1,5 @@
|
||||
C If\sthere\sis\sdata\sin\sboth\sthe\ssqlite_stat4\sand\ssqlite_stat3\stables\sfor\sa\ssingle\sindex,\signore\sthe\ssqlite_stat3\srecords.
|
||||
D 2013-08-12T17:31:32.368
|
||||
C If\sENABLE_STAT3\sis\sdefined\sbut\sENABLE_STAT4\sis\snot,\shave\sANALYZE\screate\sand\spopulate\sthe\ssqlite_stat3\stable\sinstead\sof\ssqlite_stat4.
|
||||
D 2013-08-12T20:14:04.167
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
||||
F src/analyze.c c020f2ff9991412d85d8c5c736097de82c38ea51
|
||||
F src/analyze.c cbd13a1b3c7122729814d34245ce2b4007262f5e
|
||||
F src/attach.c 1816f5a9eea8d2010fc2b22b44f0f63eb3a62704
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 43b348822db3e4cef48b2ae5a445fbeb6c73a165
|
||||
@ -169,7 +169,7 @@ F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2
|
||||
F src/build.c c2e4d057c833b616c6e32e690c29c03ba949b571
|
||||
F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 177fa0cbf28b8deda3f216603beee0b883408a40
|
||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 2317c814866d9aa71fea16b3faf4fdd4d6a49b94
|
||||
F src/expr.c 0bbb44462a19169189b2709fbbd800950521b5ae
|
||||
@ -221,7 +221,7 @@ F src/shell.c 128eb16ccec68509a4a2f1948f2483819bf63425
|
||||
F src/sqlite.h.in bd1451ba1ab681022a53bccc3c39580ba094a3ff
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 646063fc1564842fd8e54eee00f8b8b429e2eb1f
|
||||
F src/sqliteInt.h 35ee14455ae3cb21b166fea7777867a42c60d0d5
|
||||
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 dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
|
||||
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
|
||||
F src/test_config.c 636ecd15a6ba18bf97a590b5a21f47573c8c2b65
|
||||
F src/test_config.c 3d148e338b575bd937f7746824f36a9c6682d238
|
||||
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
@ -283,14 +283,14 @@ F src/vdbeInt.h e9b7c6b165a31a4715c5aa97223d20d265515231
|
||||
F src/vdbeapi.c 4d13580bd058b39623e8fcfc233b7df4b8191e8b
|
||||
F src/vdbeaux.c a6ea36a9dc714e1128a0173249a0532ddcab0489
|
||||
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
|
||||
F src/vdbemem.c b16ba7b3d1ead79c081d1f79e157e6b2efd13ca5
|
||||
F src/vdbemem.c 7ec9a78d6d4b2d4ebb4d3fd9b706065146616019
|
||||
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 c1090a2769c6e47b88aa79cd34f2e763af5282f8
|
||||
F src/where.c d97b5cb215c2e3e5b172b84000d2f3ee67ca0e86
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
@ -301,15 +301,15 @@ F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
|
||||
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
|
||||
F test/alter4.test 8e93bf7a7e6919b14b0c9a6c1e4908bcf21b0165
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/analyze.test 4d08a739c5ec28db93e0465e3b5a468befdf145f
|
||||
F test/analyze3.test ea4cba3277eb89d16dfeada7259ea437e7b00f3b
|
||||
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
F test/analyze3.test 412f690dfe95b337475e3e78a84a85d25f6f125d
|
||||
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 96ac783a56142bbbedb58a7c1eebd1808b49cfae
|
||||
F test/analyze6.test 3c01e084309706a1033f850330ea24f6f7846297
|
||||
F test/analyze7.test c0af22c5e0140e2e4ac556a21c2b6fff58229c98
|
||||
F test/analyze8.test 8d1f76ff1e47c4093bb7be3971ba08fa56dc470d
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test f3afd910c09f7d9b76f853e3f2f2fb169196d0b1
|
||||
F test/analyze9.test 1b419d03407f2a6f4f1485620d54cb3e1bab3a71
|
||||
F test/analyzeA.test 3a24600dd50e4a8815a952e1470ecb610046b069
|
||||
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
@ -321,7 +321,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 cb43e31c14b8f5849d04edd6d3a1f844687cc855
|
||||
F test/auth.test 9bea29041871807d9f289ee679d05d3ed103642f
|
||||
F test/auth2.test a2a371aa6df15f8b0c8109b33d3d7f0f73e4c9aa
|
||||
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
|
||||
F test/autoinc.test bd30d372d00045252f6c2e41b5f41455e1975acf
|
||||
@ -413,7 +413,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 1e64356a8c0407d7aeead201852fc4de9418196a
|
||||
F test/dbstatus.test aee30c3f337e6c217ff06df59fb8fe6e6448dce2
|
||||
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
|
||||
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
|
||||
F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
|
||||
@ -592,7 +592,7 @@ F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||
F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
|
||||
F test/index4.test 2983216eb8c86ee62d9ed7cb206b5cc3331c0026
|
||||
F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33
|
||||
F test/index6.test 5be279e46e5f40e2dcc67d9b2aecdb5b0031db18
|
||||
F test/index6.test d84c03a7c16222b874877e8f4efb2bb7fed5d29e
|
||||
F test/indexedby.test 0e959308707c808515c3a51363f7a9835027108c
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
@ -811,7 +811,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test a653783d985108c4912cc64d341ffbbb55ad2806
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/table.test 03135ef2fd49b2a21894be22afdb3c7de32cecd3
|
||||
F test/table.test 30423211108121884588d24d6776c7f38702ad7b
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
@ -866,7 +866,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 6595eac9c561b0aa46c1e4f4bae3f876acf38ce3
|
||||
F test/tkt-cbd054fa6b.test 06ccd57af3c0c7895d0f7dc844f13c51f8258885
|
||||
F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d
|
||||
F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
|
||||
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
|
||||
@ -1049,7 +1049,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 71aa15cc17cb3343566a2de3aef47d4548610e4d
|
||||
F test/where9.test 74245dea86592a744b758dff2e7daf0a07bade7d
|
||||
F test/whereA.test 24c234263c8fe358f079d5e57d884fb569d2da0a
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
|
||||
@ -1107,7 +1107,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P fa1588adab6759fd3d1be02524aa19a0d1c6adaa
|
||||
R f7aa978164035b98da3c8ba701a7b74c
|
||||
P 2a41736728d83a777ea8112da927cb047ec6684e
|
||||
R ebabceacbf319f11921788de02fa2c3b
|
||||
U dan
|
||||
Z fe069e15f895d55c37e51ff5b63e6804
|
||||
Z 6caae0dd3ca2077b483e5c3e88d20d9e
|
||||
|
@ -1 +1 @@
|
||||
2a41736728d83a777ea8112da927cb047ec6684e
|
||||
cca8bf4372ab7a0258aa5c9397818415c6cf0abf
|
192
src/analyze.c
192
src/analyze.c
@ -140,6 +140,12 @@
|
||||
#ifndef SQLITE_OMIT_ANALYZE
|
||||
#include "sqliteInt.h"
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
# define IsStat3 0
|
||||
#else
|
||||
# define IsStat3 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine generates code that opens the sqlite_stat1 table for
|
||||
** writing with cursor iStatCur. If the library was built with the
|
||||
@ -170,8 +176,10 @@ static void openStatTable(
|
||||
{ "sqlite_stat1", "tbl,idx,stat" },
|
||||
#if defined(SQLITE_ENABLE_STAT4)
|
||||
{ "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
|
||||
{ "sqlite_stat3", 0 },
|
||||
#elif defined(SQLITE_ENABLE_STAT3)
|
||||
{ "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
|
||||
{ "sqlite_stat4", 0 },
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -194,15 +202,17 @@ static void openStatTable(
|
||||
const char *zTab = aTable[i].zName;
|
||||
Table *pStat;
|
||||
if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
|
||||
/* The sqlite_stat[12] 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
|
||||
** because the OpenWrite opcode below will be needing it. */
|
||||
sqlite3NestedParse(pParse,
|
||||
"CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
|
||||
);
|
||||
aRoot[i] = pParse->regRoot;
|
||||
aCreateTbl[i] = OPFLAG_P2ISREG;
|
||||
if( aTable[i].zCols ){
|
||||
/* The sqlite_stat[12] 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
|
||||
** because the OpenWrite opcode below will be needing it. */
|
||||
sqlite3NestedParse(pParse,
|
||||
"CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
|
||||
);
|
||||
aRoot[i] = pParse->regRoot;
|
||||
aCreateTbl[i] = OPFLAG_P2ISREG;
|
||||
}
|
||||
}else{
|
||||
/* The table already exists. If zWhere is not NULL, delete all entries
|
||||
** associated with the table zWhere. If zWhere is NULL, delete the
|
||||
@ -214,14 +224,14 @@ static void openStatTable(
|
||||
"DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
|
||||
);
|
||||
}else{
|
||||
/* The sqlite_stat[12] table already exists. Delete all rows. */
|
||||
/* The sqlite_stat[134] table already exists. Delete all rows. */
|
||||
sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the sqlite_stat[14] tables for writing. */
|
||||
for(i=0; i<ArraySize(aTable); i++){
|
||||
for(i=0; i<ArraySize(aRoot); i++){
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
|
||||
sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
|
||||
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
|
||||
@ -271,7 +281,7 @@ struct Stat4Accum {
|
||||
} *a; /* An array of samples */
|
||||
};
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/*
|
||||
** Implementation of the stat4_init(C,N,S) SQL function. The three parameters
|
||||
** are the number of rows in the table or index (C), the number of columns
|
||||
@ -297,8 +307,8 @@ static void stat4Init(
|
||||
/* Decode the three function arguments */
|
||||
UNUSED_PARAMETER(argc);
|
||||
nRow = (tRowcnt)sqlite3_value_int64(argv[0]);
|
||||
nCol = sqlite3_value_int(argv[1]);
|
||||
mxSample = sqlite3_value_int(argv[2]);
|
||||
nCol = sqlite3_value_int(argv[1]);
|
||||
assert( nCol>1 ); /* >1 because it includes the rowid column */
|
||||
|
||||
/* Allocate the space required for the Stat4Accum object */
|
||||
@ -370,14 +380,16 @@ static void stat4Push(
|
||||
u32 h; /* Hash value for this key */
|
||||
int iMin = p->iMin;
|
||||
int i;
|
||||
u8 isPSample = 0;
|
||||
int nSampleCol; /* Number of fields in samples */
|
||||
u8 isPSample = 0; /* True if this is a periodic sample */
|
||||
u8 doInsert = 0;
|
||||
|
||||
sqlite3_value **aEq = &argv[3];
|
||||
sqlite3_value **aLt = &argv[3+p->nCol];
|
||||
sqlite3_value **aDLt = &argv[3+p->nCol+p->nCol];
|
||||
|
||||
i64 nLt = sqlite3_value_int64(aLt[p->nCol-1]);
|
||||
i64 nLt;
|
||||
i64 nEq;
|
||||
|
||||
UNUSED_PARAMETER(context);
|
||||
UNUSED_PARAMETER(argc);
|
||||
@ -385,6 +397,18 @@ static void stat4Push(
|
||||
assert( argc==(3 + 3*p->nCol) );
|
||||
assert( p->bHaveNonP==0 || p->bHaveP==0 );
|
||||
|
||||
if( IsStat3 ){
|
||||
/* Stat3 builds ignore any call with bNewKey==0. And consider only
|
||||
** the first column of the index keys. */
|
||||
if( bNewKey==0 ) return;
|
||||
nEq = sqlite3_value_int64(aEq[0]);
|
||||
nSampleCol = 1;
|
||||
}else{
|
||||
nEq = 1;
|
||||
nSampleCol = p->nCol;
|
||||
}
|
||||
nLt = sqlite3_value_int64(aLt[nSampleCol-1]);
|
||||
|
||||
if( bNewKey ){
|
||||
p->bHaveP = 0;
|
||||
p->bHaveNonP = 0;
|
||||
@ -394,7 +418,7 @@ static void stat4Push(
|
||||
/* Check if this should be a periodic sample. If this is a periodic
|
||||
** sample and there is already a non-periodic sample for this key,
|
||||
** replace it. */
|
||||
if( (nLt/p->nPSample) != (nLt+1)/p->nPSample ){
|
||||
if( (nLt/p->nPSample) != (nLt+nEq)/p->nPSample ){
|
||||
doInsert = isPSample = 1;
|
||||
if( p->bHaveNonP ){
|
||||
p->nSample--;
|
||||
@ -423,7 +447,7 @@ static void stat4Push(
|
||||
p->bHaveNonP = 1;
|
||||
}else{
|
||||
tRowcnt *aMinEq = p->a[iMin].anEq;
|
||||
for(i=p->nCol-2; i>=0; i--){
|
||||
for(i=(IsStat3 ? 0 : p->nCol-2); i>=0; i--){
|
||||
i64 nEq = sqlite3_value_int64(aEq[i]);
|
||||
if( nEq<aMinEq[i] ) break;
|
||||
if( nEq>aMinEq[i] ){
|
||||
@ -456,12 +480,12 @@ static void stat4Push(
|
||||
pSample->iRowid = rowid;
|
||||
pSample->iHash = h;
|
||||
pSample->isPSample = isPSample;
|
||||
for(i=0; i<p->nCol; i++){
|
||||
for(i=0; i<nSampleCol; i++){
|
||||
pSample->anEq[i] = sqlite3_value_int64(aEq[i]);
|
||||
pSample->anLt[i] = sqlite3_value_int64(aLt[i]);
|
||||
pSample->anDLt[i] = sqlite3_value_int64(aDLt[i])-1;
|
||||
assert( sqlite3_value_int64(aDLt[i])>0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the new minimum */
|
||||
if( p->nSample==p->mxSample ){
|
||||
@ -472,7 +496,7 @@ static void stat4Push(
|
||||
iMin = i;
|
||||
}else{
|
||||
int j;
|
||||
for(j=p->nCol-1; j>=0; j++){
|
||||
for(j=nSampleCol-1; j>=0; j++){
|
||||
i64 iCmp = (p->a[iMin].anEq[j] - p->a[i].anEq[j]);
|
||||
if( iCmp<0 ){ iMin = i; }
|
||||
if( iCmp ) break;
|
||||
@ -533,19 +557,23 @@ static void stat4Get(
|
||||
default: aCnt = p->a[n].anDLt; break;
|
||||
}
|
||||
|
||||
zRet = sqlite3MallocZero(p->nCol * 25);
|
||||
if( zRet==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
if( IsStat3 ){
|
||||
sqlite3_result_int64(context, (i64)aCnt[0]);
|
||||
}else{
|
||||
int i;
|
||||
char *z = zRet;
|
||||
for(i=0; i<p->nCol; i++){
|
||||
sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
|
||||
z += sqlite3Strlen30(z);
|
||||
zRet = sqlite3MallocZero(p->nCol * 25);
|
||||
if( zRet==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
int i;
|
||||
char *z = zRet;
|
||||
for(i=0; i<p->nCol; i++){
|
||||
sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
|
||||
z += sqlite3Strlen30(z);
|
||||
}
|
||||
assert( z[0]=='\0' && z>zRet );
|
||||
z[-1] = '\0';
|
||||
sqlite3_result_text(context, zRet, -1, sqlite3_free);
|
||||
}
|
||||
assert( z[0]=='\0' && z>zRet );
|
||||
z[-1] = '\0';
|
||||
sqlite3_result_text(context, zRet, -1, sqlite3_free);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -591,7 +619,7 @@ static void analyzeOneTable(
|
||||
int regTabname = iMem++; /* Register containing table name */
|
||||
int regIdxname = iMem++; /* Register containing index name */
|
||||
int regStat1 = iMem++; /* The stat column of sqlite_stat1 */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
int regNumEq = regStat1; /* Number of instances. Same as regStat1 */
|
||||
int regNumLt = iMem++; /* Number of keys less than regSample */
|
||||
int regNumDLt = iMem++; /* Number of distinct keys less than regSample */
|
||||
@ -646,7 +674,6 @@ static void analyzeOneTable(
|
||||
int nCol; /* Number of columns indexed by pIdx */
|
||||
KeyInfo *pKey; /* KeyInfo structure for pIdx */
|
||||
int *aChngAddr; /* Array of jump instruction addresses */
|
||||
|
||||
int regPrev; /* First in array of previous values */
|
||||
int regDLte; /* First in array of nDlt registers */
|
||||
int regLt; /* First in array of nLt registers */
|
||||
@ -688,6 +715,7 @@ static void analyzeOneTable(
|
||||
** regEq(0) += 1
|
||||
** Next csr(0)
|
||||
** }while ( csr(0)[0] == regPrev(0) )
|
||||
** if( IsStat3 ) regKeychng = 1
|
||||
**
|
||||
** next_1:
|
||||
** regPrev(1) = csr(1)[1]
|
||||
@ -699,7 +727,7 @@ static void analyzeOneTable(
|
||||
** Next csr(1)
|
||||
** }while ( csr(1)[0..1] == regPrev(0..1) )
|
||||
**
|
||||
** regKeychng = 1
|
||||
** if( IsStat3==0 ) regKeychng = 1
|
||||
** next_row:
|
||||
** regRowid = csr(2)[rowid]
|
||||
** regEq(2) = 1
|
||||
@ -754,12 +782,15 @@ static void analyzeOneTable(
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/* Invoke the stat4_init() function. The arguments are:
|
||||
**
|
||||
** * the number of rows in the index,
|
||||
** * the number of columns in the index including the rowid,
|
||||
** * the recommended number of samples for the stat4 table.
|
||||
**
|
||||
** If this is a stat3 build, the number of columns in the index is
|
||||
** set to 1 (as this is the number of index fields gathered).
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, nCol+1, regStat4+2);
|
||||
@ -830,6 +861,10 @@ static void analyzeOneTable(
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, iDo);
|
||||
sqlite3VdbeResolveLabel(v, iNe);
|
||||
|
||||
if( IsStat3 && i==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regKeychng);
|
||||
}
|
||||
}
|
||||
|
||||
/* This stuff:
|
||||
@ -846,8 +881,10 @@ static void analyzeOneTable(
|
||||
** Next csr(2)
|
||||
** if( eof( csr(2) ) ) goto endOfScan
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regKeychng);
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
if( 0==IsStat3 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regKeychng);
|
||||
}
|
||||
aChngAddr[nCol] =
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur+nCol, regRowid);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEq+nCol);
|
||||
@ -875,7 +912,7 @@ static void analyzeOneTable(
|
||||
|
||||
sqlite3VdbeResolveLabel(v, endOfScan);
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/* Add rows to the sqlite_stat4 table */
|
||||
regLoop = regStat4+1;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, regLoop);
|
||||
@ -886,12 +923,17 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeAddOp1(v, OP_IsNull, regEq+nCol);
|
||||
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, shortJump, regEq+nCol);
|
||||
for(i=0; i<nCol; i++){
|
||||
int iCol = pIdx->aiColumn[i];
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regEq+i);
|
||||
if( IsStat3==0 ){
|
||||
for(i=0; i<nCol; i++){
|
||||
int iCol = pIdx->aiColumn[i];
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regEq+i);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regEq, nCol+1, regSample);
|
||||
sqlite3VdbeChangeP4(v, -1, pIdx->zColAff, 0);
|
||||
}else{
|
||||
int iCol = pIdx->aiColumn[0];
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regSample);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regEq, nCol+1, regSample);
|
||||
sqlite3VdbeChangeP4(v, -1, pIdx->zColAff, 0);
|
||||
|
||||
sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regNumEq);
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)&stat4GetFuncdef, P4_FUNCDEF);
|
||||
@ -1189,7 +1231,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
||||
** and its contents.
|
||||
*/
|
||||
void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
if( pIdx->aSample ){
|
||||
int j;
|
||||
for(j=0; j<pIdx->nSample; j++){
|
||||
@ -1208,62 +1250,7 @@ void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
|
||||
/*
|
||||
** The implementation of the sqlite_record() function. This function accepts
|
||||
** a single argument of any type. The return value is a formatted database
|
||||
** record (a blob) containing the argument value.
|
||||
**
|
||||
** This is used to convert the value stored in the 'sample' column of the
|
||||
** sqlite_stat3 table to the record format SQLite uses internally.
|
||||
*/
|
||||
static void recordFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const int file_format = 1;
|
||||
int iSerial; /* Serial type */
|
||||
int nSerial; /* Bytes of space for iSerial as varint */
|
||||
int nVal; /* Bytes of space required for argv[0] */
|
||||
int nRet;
|
||||
sqlite3 *db;
|
||||
u8 *aRet;
|
||||
|
||||
iSerial = sqlite3VdbeSerialType(argv[0], file_format);
|
||||
nSerial = sqlite3VarintLen(iSerial);
|
||||
nVal = sqlite3VdbeSerialTypeLen(iSerial);
|
||||
db = sqlite3_context_db_handle(context);
|
||||
|
||||
nRet = 1 + nSerial + nVal;
|
||||
aRet = sqlite3DbMallocRaw(db, nRet);
|
||||
if( aRet==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
aRet[0] = nSerial+1;
|
||||
sqlite3PutVarint(&aRet[1], iSerial);
|
||||
sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format);
|
||||
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
|
||||
sqlite3DbFree(db, aRet);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Register built-in functions used to help read ANALYZE data.
|
||||
*/
|
||||
void sqlite3AnalyzeFunctions(void){
|
||||
static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = {
|
||||
FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
|
||||
};
|
||||
int i;
|
||||
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
|
||||
FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs);
|
||||
for(i=0; i<ArraySize(aAnalyzeTableFuncs); i++){
|
||||
sqlite3FuncDefInsert(pHash, &aFunc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/*
|
||||
** Load the content from either the sqlite_stat4 or sqlite_stat3 table
|
||||
** into the relevant Index.aSample[] arrays.
|
||||
@ -1323,6 +1310,7 @@ static int loadStatTbl(
|
||||
nIdxCol = pIdx->nColumn+1;
|
||||
nAvgCol = pIdx->nColumn;
|
||||
}
|
||||
pIdx->nSampleCol = nIdxCol;
|
||||
pIdx->nSample = nSample;
|
||||
nByte = sizeof(IndexSample) * nSample;
|
||||
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
|
||||
@ -1484,7 +1472,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
||||
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
||||
Index *pIdx = sqliteHashData(i);
|
||||
sqlite3DefaultRowEst(pIdx);
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
sqlite3DeleteIndexSamples(db, pIdx);
|
||||
pIdx->aSample = 0;
|
||||
#endif
|
||||
@ -1509,7 +1497,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
||||
|
||||
|
||||
/* Load the statistics from the sqlite_stat4 table. */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
if( rc==SQLITE_OK ){
|
||||
int lookasideEnabled = db->lookaside.bEnabled;
|
||||
db->lookaside.bEnabled = 0;
|
||||
|
@ -117,8 +117,10 @@ static const char * const azCompileOpt[] = {
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
"ENABLE_RTREE",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4)
|
||||
"ENABLE_STAT4",
|
||||
#elif defined(SQLITE_ENABLE_STAT3)
|
||||
"ENABLE_STAT3",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
"ENABLE_UNLOCK_NOTIFY",
|
||||
|
@ -1549,8 +1549,9 @@ struct Index {
|
||||
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
|
||||
unsigned bUnordered:1; /* Use this index for == or IN queries only */
|
||||
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
int nSample; /* Number of elements in aSample[] */
|
||||
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
|
||||
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
|
||||
IndexSample *aSample; /* Samples of the left-most key */
|
||||
#endif
|
||||
|
@ -463,6 +463,11 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
|
||||
Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
|
||||
# if defined(__APPLE__)
|
||||
|
@ -1046,7 +1046,7 @@ int valueFromExpr(
|
||||
** The ifdef here is to enable us to achieve 100% branch test coverage even
|
||||
** when SQLITE_ENABLE_STAT4 is omitted.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
if( op==TK_REGISTER ) op = pExpr->op2;
|
||||
#else
|
||||
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
|
||||
@ -1152,7 +1152,61 @@ int sqlite3ValueFromExpr(
|
||||
return valueFromExpr(db, pExpr, enc, affinity, ppVal, valueNew, (void*)db);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/*
|
||||
** The implementation of the sqlite_record() function. This function accepts
|
||||
** a single argument of any type. The return value is a formatted database
|
||||
** record (a blob) containing the argument value.
|
||||
**
|
||||
** This is used to convert the value stored in the 'sample' column of the
|
||||
** sqlite_stat3 table to the record format SQLite uses internally.
|
||||
*/
|
||||
static void recordFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const int file_format = 1;
|
||||
int iSerial; /* Serial type */
|
||||
int nSerial; /* Bytes of space for iSerial as varint */
|
||||
int nVal; /* Bytes of space required for argv[0] */
|
||||
int nRet;
|
||||
sqlite3 *db;
|
||||
u8 *aRet;
|
||||
|
||||
iSerial = sqlite3VdbeSerialType(argv[0], file_format);
|
||||
nSerial = sqlite3VarintLen(iSerial);
|
||||
nVal = sqlite3VdbeSerialTypeLen(iSerial);
|
||||
db = sqlite3_context_db_handle(context);
|
||||
|
||||
nRet = 1 + nSerial + nVal;
|
||||
aRet = sqlite3DbMallocRaw(db, nRet);
|
||||
if( aRet==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
aRet[0] = nSerial+1;
|
||||
sqlite3PutVarint(&aRet[1], iSerial);
|
||||
sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format);
|
||||
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
|
||||
sqlite3DbFree(db, aRet);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Register built-in functions used to help read ANALYZE data.
|
||||
*/
|
||||
void sqlite3AnalyzeFunctions(void){
|
||||
static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = {
|
||||
FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
|
||||
};
|
||||
int i;
|
||||
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
|
||||
FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs);
|
||||
for(i=0; i<ArraySize(aAnalyzeTableFuncs); i++){
|
||||
sqlite3FuncDefInsert(pHash, &aFunc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** A pointer to an instance of this object is passed as the context
|
||||
** pointer to valueNewStat4() (see below.
|
||||
|
33
src/where.c
33
src/where.c
@ -285,7 +285,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_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
|
||||
#else
|
||||
# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
|
||||
@ -391,7 +391,7 @@ struct WhereLoopBuilder {
|
||||
ExprList *pOrderBy; /* ORDER BY clause */
|
||||
WhereLoop *pNew; /* Template WhereLoop */
|
||||
WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
UnpackedRecord *pRec; /* Probe for stat4 (if required) */
|
||||
int nRecValid; /* Number of valid fields currently in pRec */
|
||||
#endif
|
||||
@ -1789,7 +1789,7 @@ static void exprAnalyze(
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/* 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
|
||||
@ -2397,7 +2397,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
|
||||
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/*
|
||||
** Estimate the location of a particular key among all keys in an
|
||||
** index. Store the results in aStat as follows:
|
||||
@ -2422,7 +2422,7 @@ static void whereKeyStats(
|
||||
int res; /* Result of comparison operation */
|
||||
|
||||
assert( pIdx->nSample>0 );
|
||||
assert( pRec->nField>0 && iCol<=pIdx->nColumn );
|
||||
assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
|
||||
do{
|
||||
iTest = (iMin+i)/2;
|
||||
res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
|
||||
@ -2533,11 +2533,12 @@ static int whereRangeScanEst(
|
||||
int rc = SQLITE_OK;
|
||||
int nOut = (int)*pnOut;
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
Index *p = pBuilder->pNew->u.btree.pIndex;
|
||||
int nEq = pBuilder->pNew->u.btree.nEq;
|
||||
|
||||
if( nEq==pBuilder->nRecValid
|
||||
if( nEq==pBuilder->nRecValid
|
||||
&& nEq<p->nSampleCol
|
||||
&& p->nSample
|
||||
&& OptimizationEnabled(pParse->db, SQLITE_Stat3)
|
||||
){
|
||||
@ -2640,7 +2641,7 @@ static int whereRangeScanEst(
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/*
|
||||
** Estimate the number of rows that will be returned based on
|
||||
** an equality constraint x=VALUE and where that VALUE occurs in
|
||||
@ -2706,7 +2707,7 @@ static int whereEqualScanEst(
|
||||
}
|
||||
#endif /* defined(SQLITE_ENABLE_STAT4) */
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
/*
|
||||
** Estimate the number of rows that will be returned based on
|
||||
** an IN constraint where the right-hand side of the IN operator
|
||||
@ -4296,7 +4297,7 @@ static int whereLoopAddBtreeIndex(
|
||||
rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
|
||||
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
|
||||
int nIn = 0;
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
int nRecValid = pBuilder->nRecValid;
|
||||
assert( pNew->nOut==saved_nOut );
|
||||
if( (pTerm->wtFlags & TERM_VNULL)!=0 && pSrc->pTab->aCol[iCol].notNull ){
|
||||
@ -4366,8 +4367,12 @@ static int whereLoopAddBtreeIndex(
|
||||
assert( pNew->nOut==saved_nOut );
|
||||
whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
if( nInMul==0 && pProbe->nSample && OptimizationEnabled(db, SQLITE_Stat3) ){
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
if( nInMul==0
|
||||
&& pProbe->nSample
|
||||
&& pNew->u.btree.nEq<=pProbe->nSampleCol
|
||||
&& OptimizationEnabled(db, SQLITE_Stat3)
|
||||
){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
tRowcnt nOut = 0;
|
||||
if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){
|
||||
@ -4400,7 +4405,7 @@ static int whereLoopAddBtreeIndex(
|
||||
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
|
||||
}
|
||||
pNew->nOut = saved_nOut;
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
pBuilder->nRecValid = nRecValid;
|
||||
#endif
|
||||
}
|
||||
@ -4631,7 +4636,7 @@ static int whereLoopAddBtree(
|
||||
}
|
||||
|
||||
rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_ENABLE_STAT3)
|
||||
sqlite3Stat4ProbeFree(pBuilder->pRec);
|
||||
pBuilder->nRecValid = 0;
|
||||
pBuilder->pRec = 0;
|
||||
|
@ -288,7 +288,7 @@ do_test analyze-4.3 {
|
||||
} {}
|
||||
|
||||
# Verify that DROP TABLE and DROP INDEX remove entries from the
|
||||
# sqlite_stat1 and sqlite_stat4 tables.
|
||||
# sqlite_stat1, sqlite_stat3 and sqlite_stat4 tables.
|
||||
#
|
||||
do_test analyze-5.0 {
|
||||
execsql {
|
||||
@ -306,12 +306,13 @@ do_test analyze-5.0 {
|
||||
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
|
||||
}
|
||||
} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
|
||||
ifcapable stat4 {
|
||||
ifcapable stat4||stat3 {
|
||||
ifcapable stat4 {set stat sqlite_stat4} else {set stat sqlite_stat3}
|
||||
do_test analyze-5.1 {
|
||||
execsql {
|
||||
SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
|
||||
SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
|
||||
}
|
||||
execsql "
|
||||
SELECT DISTINCT idx FROM $stat ORDER BY 1;
|
||||
SELECT DISTINCT tbl FROM $stat ORDER BY 1;
|
||||
"
|
||||
} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
|
||||
}
|
||||
do_test analyze-5.2 {
|
||||
@ -321,12 +322,12 @@ do_test analyze-5.2 {
|
||||
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
|
||||
}
|
||||
} {t3i1 t3i3 t4i1 t4i2 t3 t4}
|
||||
ifcapable stat4 {
|
||||
ifcapable stat4||stat3 {
|
||||
do_test analyze-5.3 {
|
||||
execsql {
|
||||
SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
|
||||
SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
|
||||
}
|
||||
execsql "
|
||||
SELECT DISTINCT idx FROM $stat ORDER BY 1;
|
||||
SELECT DISTINCT tbl FROM $stat ORDER BY 1;
|
||||
"
|
||||
} {t3i1 t3i3 t4i1 t4i2 t3 t4}
|
||||
}
|
||||
do_test analyze-5.4 {
|
||||
@ -336,12 +337,12 @@ do_test analyze-5.4 {
|
||||
SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
|
||||
}
|
||||
} {t4i1 t4i2 t4}
|
||||
ifcapable stat4 {
|
||||
ifcapable stat4||stat3 {
|
||||
do_test analyze-5.5 {
|
||||
execsql {
|
||||
SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
|
||||
SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
|
||||
}
|
||||
execsql "
|
||||
SELECT DISTINCT idx FROM $stat ORDER BY 1;
|
||||
SELECT DISTINCT tbl FROM $stat ORDER BY 1;
|
||||
"
|
||||
} {t4i1 t4i2 t4}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !stat4 {
|
||||
ifcapable !stat4&&!stat3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
@ -95,8 +95,11 @@ do_test analyze3-1.1.1 {
|
||||
COMMIT;
|
||||
ANALYZE;
|
||||
}
|
||||
execsql {
|
||||
SELECT count(*)>0 FROM sqlite_stat4;
|
||||
|
||||
ifcapable stat4 {
|
||||
execsql { SELECT count(*)>0 FROM sqlite_stat4; }
|
||||
} else {
|
||||
execsql { SELECT count(*)>0 FROM sqlite_stat3; }
|
||||
}
|
||||
} {1}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !stat4 {
|
||||
ifcapable !stat4&&!stat3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
@ -66,20 +66,40 @@ 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 DISTINCT lindex(test_decode(sample),0)
|
||||
FROM sqlite_stat4 WHERE idx='t1u' ORDER BY nlt;
|
||||
}
|
||||
ifcapable stat4 {
|
||||
db eval {
|
||||
SELECT DISTINCT lindex(test_decode(sample),0)
|
||||
FROM sqlite_stat4 WHERE idx='t1u' ORDER BY nlt;
|
||||
}
|
||||
} else {
|
||||
db eval {
|
||||
SELECT sample FROM sqlite_stat3 WHERE idx='t1u' ORDER BY nlt;
|
||||
}
|
||||
}
|
||||
} {alpha bravo charlie delta}
|
||||
|
||||
do_test analyze5-1.1 {
|
||||
db eval {
|
||||
SELECT DISTINCT lower(lindex(test_decode(sample), 0))
|
||||
FROM sqlite_stat4 WHERE idx='t1v' ORDER BY 1
|
||||
ifcapable stat4 {
|
||||
db eval {
|
||||
SELECT DISTINCT lower(lindex(test_decode(sample), 0))
|
||||
FROM sqlite_stat4 WHERE idx='t1v' ORDER BY 1
|
||||
}
|
||||
} else {
|
||||
db eval {
|
||||
SELECT lower(sample) FROM sqlite_stat3 WHERE idx='t1v' ORDER BY 1
|
||||
}
|
||||
}
|
||||
} {alpha bravo charlie delta}
|
||||
do_test analyze5-1.2 {
|
||||
db eval {SELECT idx, count(*) FROM sqlite_stat4 GROUP BY 1 ORDER BY 1}
|
||||
} {t1t 8 t1u 8 t1v 8 t1w 8 t1x 8 t1y 9 t1z 8}
|
||||
ifcapable stat4 {
|
||||
do_test analyze5-1.2 {
|
||||
db eval {SELECT idx, count(*) FROM sqlite_stat4 GROUP BY 1 ORDER BY 1}
|
||||
} {t1t 8 t1u 8 t1v 8 t1w 8 t1x 8 t1y 9 t1z 8}
|
||||
} else {
|
||||
do_test analyze5-1.2 {
|
||||
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
|
||||
#
|
||||
|
@ -17,7 +17,7 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !stat4 {
|
||||
ifcapable !stat4&&!stat3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ 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 stat4 {
|
||||
ifcapable stat4||stat3 {
|
||||
# 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 {
|
||||
@ -98,7 +98,8 @@ ifcapable stat4 {
|
||||
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 {!stat4} {
|
||||
|
||||
ifcapable {!stat4 && !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=?)}}
|
||||
|
@ -16,7 +16,7 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !stat4 {
|
||||
ifcapable !stat4&&!stat3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
@ -61,12 +61,41 @@ proc populate_stat3 {{bDropTable 1}} {
|
||||
db2 close
|
||||
}
|
||||
|
||||
# Populate the stat4 table according to the current contents of the db
|
||||
#
|
||||
proc populate_stat4 {{bDropTable 1}} {
|
||||
sqlite3 db2 test.db
|
||||
execsql { ANALYZE }
|
||||
|
||||
ifcapable stat3 {
|
||||
execsql {
|
||||
PRAGMA writable_schema = on;
|
||||
CREATE TABLE sqlite_stat4(tbl,idx,neq,nlt,ndlt,sample);
|
||||
INSERT INTO sqlite_stat4
|
||||
SELECT tbl, idx, neq, nlt, ndlt, sqlite_record(sample)
|
||||
FROM sqlite_stat3;
|
||||
} db2
|
||||
if {$bDropTable} { execsql {DROP TABLE sqlite_stat3} db2 }
|
||||
execsql { PRAGMA writable_schema = off }
|
||||
}
|
||||
|
||||
# Modify the database schema cookie to ensure that the other connection
|
||||
# reloads the schema.
|
||||
#
|
||||
execsql {
|
||||
CREATE TABLE obscure_tbl_nm(x);
|
||||
DROP TABLE obscure_tbl_nm;
|
||||
} db2
|
||||
db2 close
|
||||
}
|
||||
|
||||
# Populate the stat4 table according to the current contents of the db.
|
||||
# Leave deceptive data in the stat3 table. This data should be ignored
|
||||
# in favour of that from the stat4 table.
|
||||
#
|
||||
proc populate_both {} {
|
||||
populate_stat3 0
|
||||
ifcapable stat4 { populate_stat3 0 }
|
||||
ifcapable stat3 { populate_stat4 0 }
|
||||
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
@ -78,30 +107,9 @@ proc populate_both {} {
|
||||
CREATE TABLE obscure_tbl_nm(x);
|
||||
DROP TABLE obscure_tbl_nm;
|
||||
} db2
|
||||
|
||||
db2 close
|
||||
}
|
||||
|
||||
|
||||
# Populate the stat4 table according to the current contents of the db
|
||||
#
|
||||
proc populate_stat4 {} {
|
||||
execsql { ANALYZE }
|
||||
# ifcapable stat3 {
|
||||
# execsql {
|
||||
# PRAGMA writable_schema = on;
|
||||
# CREATE TABLE sqlite_stat4(tbl,idx,neq,nlt,ndlt,sample);
|
||||
# INSERT INTO sqlite_stat4 SELECT
|
||||
# tbl, idx, nlt, neq, ndlt,
|
||||
# test_extract(sample, 1)
|
||||
# FROM sqlite_stat4;
|
||||
# DROP TABLE sqlite_stat4;
|
||||
# PRAGMA writable_schema = off;
|
||||
# ANALYZE sqlite_master;
|
||||
# }
|
||||
# }
|
||||
}
|
||||
|
||||
foreach {tn analyze_cmd} {
|
||||
1 populate_stat4
|
||||
2 populate_stat3
|
||||
@ -155,6 +163,5 @@ foreach {tn analyze_cmd} {
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -2328,7 +2328,11 @@ ifcapable compound&&subquery {
|
||||
ifcapable stat4 {
|
||||
set stat4 "sqlite_stat4 "
|
||||
} else {
|
||||
set stat4 ""
|
||||
ifcapable stat3 {
|
||||
set stat4 "sqlite_stat3 "
|
||||
} else {
|
||||
set stat4 ""
|
||||
}
|
||||
}
|
||||
do_test auth-5.2 {
|
||||
execsql {
|
||||
|
@ -61,7 +61,7 @@ proc lookaside {db} {
|
||||
}
|
||||
}
|
||||
|
||||
ifcapable stat4 {
|
||||
ifcapable stat4||stat3 {
|
||||
set STAT3 1
|
||||
} else {
|
||||
set STAT3 0
|
||||
|
@ -144,7 +144,7 @@ do_test index6-2.2 {
|
||||
SELECT * FROM t2 WHERE a=5;
|
||||
}
|
||||
} {/.* TABLE t2 USING INDEX t2a1 .*/}
|
||||
ifcapable stat4 {
|
||||
ifcapable stat4||stat3 {
|
||||
do_test index6-2.3stat4 {
|
||||
execsql {
|
||||
EXPLAIN QUERY PLAN
|
||||
|
@ -267,6 +267,7 @@ do_test table-5.2.1 {
|
||||
ANALYZE;
|
||||
DROP TABLE IF EXISTS sqlite_stat1;
|
||||
DROP TABLE IF EXISTS sqlite_stat2;
|
||||
DROP TABLE IF EXISTS sqlite_stat3;
|
||||
DROP TABLE IF EXISTS sqlite_stat4;
|
||||
SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_stat*';
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !stat4 {
|
||||
ifcapable !stat4&&!stat3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
@ -54,18 +54,30 @@ do_test tkt-cbd05-1.1 {
|
||||
}
|
||||
} {10}
|
||||
do_test tkt-cbd05-1.2 {
|
||||
db eval {
|
||||
ANALYZE;
|
||||
db eval { ANALYZE; }
|
||||
ifcapable stat4 {
|
||||
db eval {
|
||||
PRAGMA writable_schema = 1;
|
||||
CREATE VIEW vvv AS
|
||||
SELECT tbl,idx,neq,nlt,ndlt,test_extract(sample,0) AS sample
|
||||
FROM sqlite_stat4;
|
||||
PRAGMA writable_schema = 0;
|
||||
}
|
||||
} else {
|
||||
db eval {
|
||||
CREATE VIEW vvv AS
|
||||
SELECT tbl,idx,neq,nlt,ndlt,sample FROM sqlite_stat3;
|
||||
}
|
||||
}
|
||||
} {}
|
||||
do_test tkt-cbd05-1.3 {
|
||||
execsql {
|
||||
SELECT tbl,idx,group_concat(s(sample),' ')
|
||||
FROM sqlite_stat4
|
||||
FROM vvv
|
||||
WHERE idx = 't1_x'
|
||||
GROUP BY tbl,idx
|
||||
}
|
||||
} {t1 t1_x {... ...A. ...B. ...C. ...D. ...E. ...F. ...G. ...H. ...I.}}
|
||||
} {t1 t1_x { A B C D E F G H I}}
|
||||
|
||||
do_test tkt-cbd05-2.1 {
|
||||
db eval {
|
||||
@ -93,10 +105,10 @@ do_test tkt-cbd05-2.2 {
|
||||
do_test tkt-cbd05-2.3 {
|
||||
execsql {
|
||||
SELECT tbl,idx,group_concat(s(sample),' ')
|
||||
FROM sqlite_stat4
|
||||
FROM vvv
|
||||
WHERE idx = 't1_x'
|
||||
GROUP BY tbl,idx
|
||||
}
|
||||
} {t1 t1_x {... ...A. ...B. ...C. ...D. ...E. ...F. ...G. ...H. ...I.}}
|
||||
} {t1 t1_x { A B C D E F G H I}}
|
||||
|
||||
finish_test
|
||||
|
@ -781,7 +781,7 @@ do_test where9-6.8.2 {
|
||||
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
|
||||
}
|
||||
} {1 {no query solution}}
|
||||
ifcapable stat4 {
|
||||
ifcapable stat4||stat3 {
|
||||
# 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.
|
||||
@ -851,6 +851,11 @@ do_test where9-7.0 {
|
||||
INSERT INTO t6 SELECT * FROM t5;
|
||||
ANALYZE t5;
|
||||
}
|
||||
ifcapable stat3 {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval { DROP TABLE IF EXISTS sqlite_stat3 }
|
||||
db2 close
|
||||
}
|
||||
} {}
|
||||
do_test where9-7.1.1 {
|
||||
count_steps {
|
||||
|
Loading…
Reference in New Issue
Block a user