Estimate row sizes for tables and indices and use those estimates during
query planning. Enhance the index_info pragma to show the estimated row sizes and to show the estimated row size for the main table as well. Allow an alternative row size estimate to be specified in the sqlite_stat1 table. FossilOrigin-Name: d27b88b8c2705f444f794096c719e6f38a792165
This commit is contained in:
commit
3d8b2395b3
50
manifest
50
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\scompilation\sissue\swith\sMSVC.
|
||||
D 2013-10-07T21:49:16.905
|
||||
C Estimate\srow\ssizes\sfor\stables\sand\sindices\sand\suse\sthose\sestimates\sduring\nquery\splanning.\s\sEnhance\sthe\sindex_info\spragma\sto\sshow\sthe\sestimated\srow\nsizes\sand\sto\sshow\sthe\sestimated\srow\ssize\sfor\sthe\smain\stable\sas\swell.\s\sAllow\nan\salternative\srow\ssize\sestimate\sto\sbe\sspecified\sin\sthe\ssqlite_stat1\stable.
|
||||
D 2013-10-10T12:38:11.216
|
||||
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 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
||||
F src/analyze.c d322972af09e3f8debb45f420dfe3ded142b108b
|
||||
F src/analyze.c 4383cd3ceeb1c93de4b142b11761e85294ce2c41
|
||||
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
|
||||
@ -166,13 +166,13 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c d5720cbb21ae56e7e5b07847e05e5b203818acac
|
||||
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
|
||||
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
||||
F src/build.c 834fa4bb0fa936c39336c52f5aacc659035d973e
|
||||
F src/build.c 3da02c07b0f198a11ce3766cd34eac311656f1e8
|
||||
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||
F src/date.c 65196e95e69f36993659bd7781abe7c2f1994739
|
||||
F src/delete.c 45788c5e48734f2af4acd75a876466e5b9838e34
|
||||
F src/expr.c 1017f482217e093ecdaca91e8666681e83733252
|
||||
F src/expr.c e7338ccffdc391c53ba2d51c5eb6a2f5299e040e
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b
|
||||
F src/func.c 2c47b65e6e00e3e9374942f28254faf8adafe398
|
||||
@ -210,18 +210,18 @@ F src/parse.y a97566d6da75075589a7c716d1bda14b586cf8da
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
||||
F src/pragma.c b65c8273162818095cfd2dd37bbbf791710de560
|
||||
F src/pragma.c f4ff6e29c316d06bf7dffca0c8cee7c229cae42e
|
||||
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
|
||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||
F src/resolve.c 7459801d02997b07e8b8da85ef255392ba1d022b
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c 2d71af95ee534afee69f5649ecf54180a9d8704b
|
||||
F src/select.c 15127b54cc11defb2cddef6914e1f384501a61c4
|
||||
F src/shell.c 5ee50ca3e35453bbd6ccdf1bdd0f6bbe9738e9fb
|
||||
F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 50f51427e7afd2803c9b8380d34069ae212a0f4c
|
||||
F src/sqliteInt.h 5dbfc960fb39dbb55ba16697f453b03cd759b04a
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -233,7 +233,7 @@ F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
|
||||
F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013
|
||||
F src/test6.c a437f76f9874d2563352a7e6cd0d43217663c220
|
||||
F src/test7.c 126b886b53f0358b92aba9b81d3fcbfbe9a93cd6
|
||||
F src/test8.c 7ee77ea522ae34aa691dfe407139dec80d4fc039
|
||||
F src/test8.c c7aab1d9fbbf54fc33d43b73aa24aa55f9eaf534
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
|
||||
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
@ -275,7 +275,7 @@ F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
|
||||
F src/trigger.c ba0a883cd536b7dfdd4df3733001f5372a4299da
|
||||
F src/update.c f5182157f5d0d0a97bc5f5e3c9bdba0dfbe08f08
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/util.c 7f3e35432d6888d1e770c488c35bd98970c44eec
|
||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||
F src/vacuum.c f313bc97123a4dd4bfd3f50a00c4d44c08a5b1b7
|
||||
F src/vdbe.c 56e648f5ba9a91810caf216857adfed9039cd174
|
||||
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
||||
@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
|
||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||
F src/where.c d8c2c5ff3af348870cb56d4a577a51625640563d
|
||||
F src/where.c 8dd4cb208b9b70beeb9da7dbcd9b8b8b08261ed7
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
@ -306,7 +306,7 @@ F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
F test/analyze3.test 412f690dfe95b337475e3e78a84a85d25f6f125d
|
||||
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab
|
||||
F test/analyze6.test d31defa011a561b938b4608d3538c1b4e0b5e92c
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
||||
F test/analyze9.test 1b9b7e9a096d1536f03d9ad7b72f638ef5669347
|
||||
@ -437,7 +437,7 @@ F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||
F test/e_insert.test 291e056e1a442a5e5166a989a8a03a46e38225ca
|
||||
F test/e_reindex.test e175794fc41f8e8aef34772e87a7d7b7a9251dd3
|
||||
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
||||
F test/e_select.test f2358d074bd82240bc79a8348f284a2a8909dc1f
|
||||
F test/e_select.test d3226cb94fae4af3f198e68e71f655e106d0be47
|
||||
F test/e_select2.test 22c660a7becf0712c95e1ca1b2d9e716a1261460
|
||||
F test/e_update.test bea00499e43ee1da77b03cdb0b20c7c864c1ec5a
|
||||
F test/e_uri.test a2c92d80093a7efdcfbb11093651cbea87097b6b
|
||||
@ -446,7 +446,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
|
||||
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test d9e7ad4e7bd36d976f1b631f76e6e6ea090c41a0
|
||||
F test/eqp.test 57c6c604c2807fb5531731c5323133453c24afac
|
||||
F test/errmsg.test 050717f1c6a5685de9c79f5f9f6b83d7c592f73a
|
||||
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
|
||||
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
|
||||
@ -724,7 +724,7 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
|
||||
F test/permutations.test 72f4f8881d388163ddbbeec0a6ed812e863ea2e6
|
||||
F test/pragma.test 5e7de6c32a5d764f09437d2025f07e4917b9e178
|
||||
F test/pragma.test 5c6e8ae9eaa9a505cc1035b51f7f0da9805092c7
|
||||
F test/pragma2.test 224f0381f9411a78ae685cac24c13656a62021b7
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
|
||||
@ -761,7 +761,7 @@ F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
|
||||
F test/schema5.test 0103e4c0313b3725b5ae5600bdca53006ab53db3
|
||||
F test/securedel.test 87a2561151af1f1e349071a89fdd77059f50113c
|
||||
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test deba017eed9daa5af33de868676c997e7eebb931
|
||||
F test/select1.test fc2a61f226a649393664ad54bc5376631801517c
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test 00179be44e531fe04c1c3f15df216439dff2519d
|
||||
@ -810,7 +810,7 @@ F test/spellfix.test 8c40b169b104086d8795781f670ba3c786d6d8be
|
||||
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
|
||||
F test/stat.test be8d477306006ec696bc86757cfb34bec79447ce
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
F test/subquery.test 3b97763ada8b3a4092d2c80db3ebc0e7870e7eaf
|
||||
F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9
|
||||
F test/subquery2.test 91e1e364072aeff431d1f9689b15147e421d88c7
|
||||
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
@ -856,7 +856,7 @@ F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
|
||||
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
|
||||
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
|
||||
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
|
||||
F test/tkt-78e04e52ea.test 787b70cfb0488c356266bb8d5ad8a657f9efceb8
|
||||
F test/tkt-78e04e52ea.test b0190d3375cf88b97d32188149cc99ccf22f556b
|
||||
F test/tkt-7a31705a7e6.test e75a2bba4eec801b92c8040eb22096ac6d35e844
|
||||
F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18
|
||||
F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
|
||||
@ -1050,8 +1050,8 @@ F test/walro.test 6cc247a0cc9b36aeea2057dd28a922a1cdfbd630
|
||||
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
|
||||
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
|
||||
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
|
||||
F test/where.test 8d66dfbfd4d12816f74f854dbf67dee492c06267
|
||||
F test/where2.test 76d5346f7edb2a6a0442dcf3e9d088ac6903e0b5
|
||||
F test/where.test 701a633ed16c661cd597b9d504b485197a0f49d7
|
||||
F test/where2.test ed6baa9420a109d8be683dbef5d153d186f3690b
|
||||
F test/where3.test d28c51f257e60be30f74308fa385ceeddfb54a6e
|
||||
F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
@ -1085,6 +1085,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c 323e54ac86fb2393f9950219224e304620d2fb12
|
||||
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/logest.c 7ad625cac3d54012b27d468b7af6612f78b9ba75
|
||||
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
|
||||
F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
@ -1119,9 +1120,8 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P 0aca31e1514b3df254c049b4251bcb199831681a
|
||||
R d3aa6a286a3048275a719f5e0f524038
|
||||
U mistachkin
|
||||
Z c61ccb89f30c9bc6ea7f451bc07fd5fb
|
||||
P 36d64dc36f18c166b2c93c43579fa3bbb5cd545f e97d7d3044aa6c5e21d1faab7d5e709d92faa261
|
||||
R 57860f2afd769aeffdd11c615e695d0a
|
||||
U drh
|
||||
Z 2546d871db6bcc36ea3db39835f90b3e
|
||||
|
@ -1 +1 @@
|
||||
36d64dc36f18c166b2c93c43579fa3bbb5cd545f
|
||||
d27b88b8c2705f444f794096c719e6f38a792165
|
@ -743,12 +743,12 @@ static void statGet(
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3_snprintf(24, zRet, "%lld", p->nRow);
|
||||
sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
|
||||
z = zRet + sqlite3Strlen30(zRet);
|
||||
for(i=0; i<(p->nCol-1); i++){
|
||||
i64 nDistinct = p->current.anDLt[i] + 1;
|
||||
i64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
|
||||
sqlite3_snprintf(24, z, " %lld", iVal);
|
||||
u64 nDistinct = p->current.anDLt[i] + 1;
|
||||
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
|
||||
sqlite3_snprintf(24, z, " %llu", iVal);
|
||||
z += sqlite3Strlen30(z);
|
||||
assert( p->current.anEq[i] );
|
||||
}
|
||||
@ -789,7 +789,7 @@ static void statGet(
|
||||
int i;
|
||||
char *z = zRet;
|
||||
for(i=0; i<p->nCol; i++){
|
||||
sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
|
||||
sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
|
||||
z += sqlite3Strlen30(z);
|
||||
}
|
||||
assert( z[0]=='\0' && z>zRet );
|
||||
@ -1250,18 +1250,16 @@ struct analysisInfo {
|
||||
** the array aOut[].
|
||||
*/
|
||||
static void decodeIntArray(
|
||||
char *zIntArray,
|
||||
int nOut,
|
||||
tRowcnt *aOut,
|
||||
int *pbUnordered
|
||||
char *zIntArray, /* String containing int array to decode */
|
||||
int nOut, /* Number of slots in aOut[] */
|
||||
tRowcnt *aOut, /* Store integers here */
|
||||
Index *pIndex /* Handle extra flags for this index, if not NULL */
|
||||
){
|
||||
char *z = zIntArray;
|
||||
int c;
|
||||
int i;
|
||||
tRowcnt v;
|
||||
|
||||
assert( pbUnordered==0 || *pbUnordered==0 );
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
if( z==0 ) z = "";
|
||||
#else
|
||||
@ -1276,8 +1274,19 @@ static void decodeIntArray(
|
||||
aOut[i] = v;
|
||||
if( *z==' ' ) z++;
|
||||
}
|
||||
if( pbUnordered && strcmp(z, "unordered")==0 ){
|
||||
*pbUnordered = 1;
|
||||
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
assert( pIndex!=0 );
|
||||
#else
|
||||
if( pIndex )
|
||||
#endif
|
||||
{
|
||||
if( strcmp(z, "unordered")==0 ){
|
||||
pIndex->bUnordered = 1;
|
||||
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
|
||||
int v32 = 0;
|
||||
sqlite3GetInt32(z+3, &v32);
|
||||
pIndex->szIdxRow = sqlite3LogEst(v32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1316,12 +1325,13 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
||||
z = argv[2];
|
||||
|
||||
if( pIndex ){
|
||||
int bUnordered = 0;
|
||||
decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst,&bUnordered);
|
||||
decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst, pIndex);
|
||||
if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
|
||||
pIndex->bUnordered = bUnordered;
|
||||
}else{
|
||||
decodeIntArray((char*)z, 1, &pTable->nRowEst, 0);
|
||||
Index fakeIdx;
|
||||
fakeIdx.szIdxRow = pTable->szTabRow;
|
||||
decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx);
|
||||
pTable->szTabRow = fakeIdx.szIdxRow;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
89
src/build.c
89
src/build.c
@ -879,7 +879,7 @@ void sqlite3StartTable(
|
||||
pTable->iPKey = -1;
|
||||
pTable->pSchema = db->aDb[iDb].pSchema;
|
||||
pTable->nRef = 1;
|
||||
pTable->nRowEst = 1000000;
|
||||
pTable->nRowEst = 1048576;
|
||||
assert( pParse->pNewTable==0 );
|
||||
pParse->pNewTable = pTable;
|
||||
|
||||
@ -1026,6 +1026,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
|
||||
** be called next to set pCol->affinity correctly.
|
||||
*/
|
||||
pCol->affinity = SQLITE_AFF_NONE;
|
||||
pCol->szEst = 1;
|
||||
p->nCol++;
|
||||
}
|
||||
|
||||
@ -1067,15 +1068,18 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
|
||||
** If none of the substrings in the above table are found,
|
||||
** SQLITE_AFF_NUMERIC is returned.
|
||||
*/
|
||||
char sqlite3AffinityType(const char *zIn){
|
||||
char sqlite3AffinityType(const char *zIn, u8 *pszEst){
|
||||
u32 h = 0;
|
||||
char aff = SQLITE_AFF_NUMERIC;
|
||||
const char *zChar = 0;
|
||||
|
||||
if( zIn ) while( zIn[0] ){
|
||||
if( zIn==0 ) return aff;
|
||||
while( zIn[0] ){
|
||||
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
|
||||
zIn++;
|
||||
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
|
||||
aff = SQLITE_AFF_TEXT;
|
||||
aff = SQLITE_AFF_TEXT;
|
||||
zChar = zIn;
|
||||
}else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
|
||||
aff = SQLITE_AFF_TEXT;
|
||||
}else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
|
||||
@ -1083,6 +1087,7 @@ char sqlite3AffinityType(const char *zIn){
|
||||
}else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
|
||||
&& (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
|
||||
aff = SQLITE_AFF_NONE;
|
||||
if( zIn[0]=='(' ) zChar = zIn;
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
}else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
|
||||
&& aff==SQLITE_AFF_NUMERIC ){
|
||||
@ -1100,6 +1105,28 @@ char sqlite3AffinityType(const char *zIn){
|
||||
}
|
||||
}
|
||||
|
||||
/* If pszEst is not NULL, store an estimate of the field size. The
|
||||
** estimate is scaled so that the size of an integer is 1. */
|
||||
if( pszEst ){
|
||||
*pszEst = 1; /* default size is approx 4 bytes */
|
||||
if( aff<=SQLITE_AFF_NONE ){
|
||||
if( zChar ){
|
||||
while( zChar[0] ){
|
||||
if( sqlite3Isdigit(zChar[0]) ){
|
||||
int v;
|
||||
sqlite3GetInt32(zChar, &v);
|
||||
v = v/4 + 1;
|
||||
if( v>255 ) v = 255;
|
||||
*pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */
|
||||
break;
|
||||
}
|
||||
zChar++;
|
||||
}
|
||||
}else{
|
||||
*pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/
|
||||
}
|
||||
}
|
||||
}
|
||||
return aff;
|
||||
}
|
||||
|
||||
@ -1121,7 +1148,7 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){
|
||||
pCol = &p->aCol[p->nCol-1];
|
||||
assert( pCol->zType==0 );
|
||||
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
|
||||
pCol->affinity = sqlite3AffinityType(pCol->zType);
|
||||
pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1469,7 +1496,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
|
||||
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
|
||||
len = sqlite3Strlen30(zType);
|
||||
assert( pCol->affinity==SQLITE_AFF_NONE
|
||||
|| pCol->affinity==sqlite3AffinityType(zType) );
|
||||
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
|
||||
memcpy(&zStmt[k], zType, len);
|
||||
k += len;
|
||||
assert( k<=n );
|
||||
@ -1478,6 +1505,34 @@ static char *createTableStmt(sqlite3 *db, Table *p){
|
||||
return zStmt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Estimate the total row width for a table.
|
||||
*/
|
||||
static void estimateTableWidth(Table *pTab){
|
||||
unsigned wTable = 0;
|
||||
const Column *pTabCol;
|
||||
int i;
|
||||
for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){
|
||||
wTable += pTabCol->szEst;
|
||||
}
|
||||
if( pTab->iPKey<0 ) wTable++;
|
||||
pTab->szTabRow = sqlite3LogEst(wTable*4);
|
||||
}
|
||||
|
||||
/*
|
||||
** Estimate the average size of a row for an index.
|
||||
*/
|
||||
static void estimateIndexWidth(Index *pIdx){
|
||||
unsigned wIndex = 1;
|
||||
int i;
|
||||
const Column *aCol = pIdx->pTable->aCol;
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
assert( pIdx->aiColumn[i]>=0 && pIdx->aiColumn[i]<pIdx->pTable->nCol );
|
||||
wIndex += aCol[pIdx->aiColumn[i]].szEst;
|
||||
}
|
||||
pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called to report the final ")" that terminates
|
||||
** a CREATE TABLE statement.
|
||||
@ -1504,9 +1559,10 @@ void sqlite3EndTable(
|
||||
Token *pEnd, /* The final ')' token in the CREATE TABLE */
|
||||
Select *pSelect /* Select from a "CREATE ... AS SELECT" */
|
||||
){
|
||||
Table *p;
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb;
|
||||
Table *p; /* The new table */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
int iDb; /* Database in which the table lives */
|
||||
Index *pIdx; /* An implied index of the table */
|
||||
|
||||
if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
|
||||
return;
|
||||
@ -1526,6 +1582,12 @@ void sqlite3EndTable(
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_CHECK) */
|
||||
|
||||
/* Estimate the average row size for the table and for all implied indices */
|
||||
estimateTableWidth(p);
|
||||
for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
estimateIndexWidth(pIdx);
|
||||
}
|
||||
|
||||
/* If the db->init.busy is 1 it means we are reading the SQL off the
|
||||
** "sqlite_master" or "sqlite_temp_master" table on the disk.
|
||||
** So do not write to the disk again. Extract the root page number
|
||||
@ -2484,9 +2546,10 @@ Index *sqlite3CreateIndex(
|
||||
int iDb; /* Index of the database that is being written */
|
||||
Token *pName = 0; /* Unqualified name of the index to create */
|
||||
struct ExprList_item *pListItem; /* For looping over pList */
|
||||
int nCol;
|
||||
int nExtra = 0;
|
||||
char *zExtra;
|
||||
const Column *pTabCol; /* A column in the table */
|
||||
int nCol; /* Number of columns */
|
||||
int nExtra = 0; /* Space allocated for zExtra[] */
|
||||
char *zExtra; /* Extra space after the Index object */
|
||||
|
||||
assert( pParse->nErr==0 ); /* Never called with prior errors */
|
||||
if( db->mallocFailed || IN_DECLARE_VTAB ){
|
||||
@ -2713,7 +2776,6 @@ Index *sqlite3CreateIndex(
|
||||
*/
|
||||
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
|
||||
const char *zColName = pListItem->zName;
|
||||
Column *pTabCol;
|
||||
int requestedSortOrder;
|
||||
char *zColl; /* Collation sequence name */
|
||||
|
||||
@ -2750,6 +2812,7 @@ Index *sqlite3CreateIndex(
|
||||
if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
|
||||
}
|
||||
sqlite3DefaultRowEst(pIndex);
|
||||
if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
|
||||
|
||||
if( pTab==pParse->pNewTable ){
|
||||
/* This routine has been called to create an automatic index as a
|
||||
|
@ -41,7 +41,7 @@ char sqlite3ExprAffinity(Expr *pExpr){
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
if( op==TK_CAST ){
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
return sqlite3AffinityType(pExpr->u.zToken);
|
||||
return sqlite3AffinityType(pExpr->u.zToken, 0);
|
||||
}
|
||||
#endif
|
||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
|
||||
@ -2461,7 +2461,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
int aff, to_op;
|
||||
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
aff = sqlite3AffinityType(pExpr->u.zToken);
|
||||
aff = sqlite3AffinityType(pExpr->u.zToken, 0);
|
||||
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
|
||||
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
|
||||
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
|
||||
@ -3128,7 +3128,7 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
case TK_CAST: {
|
||||
/* Expressions of the form: CAST(pLeft AS token) */
|
||||
const char *zAff = "unk";
|
||||
switch( sqlite3AffinityType(pExpr->u.zToken) ){
|
||||
switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
|
||||
case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
|
||||
case SQLITE_AFF_NONE: zAff = "NONE"; break;
|
||||
case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
|
||||
|
38
src/pragma.c
38
src/pragma.c
@ -1453,26 +1453,30 @@ void sqlite3Pragma(
|
||||
case PragTyp_INDEX_LIST: if( zRight ){
|
||||
Index *pIdx;
|
||||
Table *pTab;
|
||||
int i;
|
||||
pTab = sqlite3FindTable(db, zRight, zDb);
|
||||
if( pTab ){
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
pIdx = pTab->pIndex;
|
||||
if( pIdx ){
|
||||
int i = 0;
|
||||
sqlite3VdbeSetNumCols(v, 3);
|
||||
pParse->nMem = 3;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
|
||||
while(pIdx){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
|
||||
++i;
|
||||
pIdx = pIdx->pNext;
|
||||
}
|
||||
sqlite3VdbeSetNumCols(v, 4);
|
||||
pParse->nMem = 4;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "avgrowsize", SQLITE_STATIC);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, 3);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer,
|
||||
(int)sqlite3LogEstToInt(pTab->szTabRow), 4);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
|
||||
for(pIdx=pTab->pIndex, i=1; pIdx; pIdx=pIdx->pNext, i++){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer,
|
||||
(int)sqlite3LogEstToInt(pIdx->szIdxRow), 4);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
112
src/select.c
112
src/select.c
@ -1061,6 +1061,9 @@ static void generateSortTail(
|
||||
** Return a pointer to a string containing the 'declaration type' of the
|
||||
** expression pExpr. The string may be treated as static by the caller.
|
||||
**
|
||||
** Also try to estimate the size of the returned value and return that
|
||||
** result in *pEstWidth.
|
||||
**
|
||||
** The declaration type is the exact datatype definition extracted from the
|
||||
** original CREATE TABLE statement if the expression is a column. The
|
||||
** declaration type for a ROWID field is INTEGER. Exactly when an expression
|
||||
@ -1074,21 +1077,36 @@ static void generateSortTail(
|
||||
** SELECT abc FROM (SELECT col AS abc FROM tbl);
|
||||
**
|
||||
** The declaration type for any expression other than a column is NULL.
|
||||
**
|
||||
** This routine has either 3 or 6 parameters depending on whether or not
|
||||
** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
|
||||
*/
|
||||
static const char *columnType(
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
|
||||
static const char *columnTypeImpl(
|
||||
NameContext *pNC,
|
||||
Expr *pExpr,
|
||||
const char **pzOriginDb,
|
||||
const char **pzOriginTab,
|
||||
const char **pzOriginCol
|
||||
const char **pzOrigDb,
|
||||
const char **pzOrigTab,
|
||||
const char **pzOrigCol,
|
||||
u8 *pEstWidth
|
||||
){
|
||||
char const *zOrigDb = 0;
|
||||
char const *zOrigTab = 0;
|
||||
char const *zOrigCol = 0;
|
||||
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
|
||||
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
|
||||
static const char *columnTypeImpl(
|
||||
NameContext *pNC,
|
||||
Expr *pExpr,
|
||||
u8 *pEstWidth
|
||||
){
|
||||
#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
|
||||
char const *zType = 0;
|
||||
char const *zOriginDb = 0;
|
||||
char const *zOriginTab = 0;
|
||||
char const *zOriginCol = 0;
|
||||
int j;
|
||||
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
|
||||
u8 estWidth = 1;
|
||||
|
||||
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
|
||||
switch( pExpr->op ){
|
||||
case TK_AGG_COLUMN:
|
||||
case TK_COLUMN: {
|
||||
@ -1149,25 +1167,35 @@ static const char *columnType(
|
||||
sNC.pSrcList = pS->pSrc;
|
||||
sNC.pNext = pNC;
|
||||
sNC.pParse = pNC->pParse;
|
||||
zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
|
||||
zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
|
||||
}
|
||||
}else if( ALWAYS(pTab->pSchema) ){
|
||||
/* A real table */
|
||||
assert( !pS );
|
||||
if( iCol<0 ) iCol = pTab->iPKey;
|
||||
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
if( iCol<0 ){
|
||||
zType = "INTEGER";
|
||||
zOriginCol = "rowid";
|
||||
zOrigCol = "rowid";
|
||||
}else{
|
||||
zType = pTab->aCol[iCol].zType;
|
||||
zOriginCol = pTab->aCol[iCol].zName;
|
||||
zOrigCol = pTab->aCol[iCol].zName;
|
||||
estWidth = pTab->aCol[iCol].szEst;
|
||||
}
|
||||
zOriginTab = pTab->zName;
|
||||
zOrigTab = pTab->zName;
|
||||
if( pNC->pParse ){
|
||||
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
|
||||
zOriginDb = pNC->pParse->db->aDb[iDb].zName;
|
||||
zOrigDb = pNC->pParse->db->aDb[iDb].zName;
|
||||
}
|
||||
#else
|
||||
if( iCol<0 ){
|
||||
zType = "INTEGER";
|
||||
}else{
|
||||
zType = pTab->aCol[iCol].zType;
|
||||
estWidth = pTab->aCol[iCol].szEst;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1184,18 +1212,21 @@ static const char *columnType(
|
||||
sNC.pSrcList = pS->pSrc;
|
||||
sNC.pNext = pNC;
|
||||
sNC.pParse = pNC->pParse;
|
||||
zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
|
||||
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( pzOriginDb ){
|
||||
assert( pzOriginTab && pzOriginCol );
|
||||
*pzOriginDb = zOriginDb;
|
||||
*pzOriginTab = zOriginTab;
|
||||
*pzOriginCol = zOriginCol;
|
||||
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
if( pzOrigDb ){
|
||||
assert( pzOrigTab && pzOrigCol );
|
||||
*pzOrigDb = zOrigDb;
|
||||
*pzOrigTab = zOrigTab;
|
||||
*pzOrigCol = zOrigCol;
|
||||
}
|
||||
#endif
|
||||
if( pEstWidth ) *pEstWidth = estWidth;
|
||||
return zType;
|
||||
}
|
||||
|
||||
@ -1221,7 +1252,7 @@ static void generateColumnTypes(
|
||||
const char *zOrigDb = 0;
|
||||
const char *zOrigTab = 0;
|
||||
const char *zOrigCol = 0;
|
||||
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
|
||||
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
|
||||
|
||||
/* The vdbe must make its own copy of the column-type and other
|
||||
** column specific strings, in case the schema is reset before this
|
||||
@ -1231,11 +1262,11 @@ static void generateColumnTypes(
|
||||
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
|
||||
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
|
||||
#else
|
||||
zType = columnType(&sNC, p, 0, 0, 0);
|
||||
zType = columnType(&sNC, p, 0, 0, 0, 0);
|
||||
#endif
|
||||
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_DECLTYPE */
|
||||
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1424,8 +1455,7 @@ static int selectColumnsFromExprList(
|
||||
*/
|
||||
static void selectAddColumnTypeAndCollation(
|
||||
Parse *pParse, /* Parsing contexts */
|
||||
int nCol, /* Number of columns */
|
||||
Column *aCol, /* List of columns */
|
||||
Table *pTab, /* Add column type information to this table */
|
||||
Select *pSelect /* SELECT used to determine types and collations */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
@ -1435,17 +1465,19 @@ static void selectAddColumnTypeAndCollation(
|
||||
int i;
|
||||
Expr *p;
|
||||
struct ExprList_item *a;
|
||||
u64 szAll = 0;
|
||||
|
||||
assert( pSelect!=0 );
|
||||
assert( (pSelect->selFlags & SF_Resolved)!=0 );
|
||||
assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
|
||||
assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
|
||||
if( db->mallocFailed ) return;
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
sNC.pSrcList = pSelect->pSrc;
|
||||
a = pSelect->pEList->a;
|
||||
for(i=0, pCol=aCol; i<nCol; i++, pCol++){
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
p = a[i].pExpr;
|
||||
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
|
||||
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
|
||||
szAll += pCol->szEst;
|
||||
pCol->affinity = sqlite3ExprAffinity(p);
|
||||
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
|
||||
pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
@ -1453,6 +1485,7 @@ static void selectAddColumnTypeAndCollation(
|
||||
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
|
||||
}
|
||||
}
|
||||
pTab->szTabRow = sqlite3LogEst(szAll*4);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1480,9 +1513,9 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
|
||||
assert( db->lookaside.bEnabled==0 );
|
||||
pTab->nRef = 1;
|
||||
pTab->zName = 0;
|
||||
pTab->nRowEst = 1000000;
|
||||
pTab->nRowEst = 1048576;
|
||||
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
|
||||
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
|
||||
selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
|
||||
pTab->iPKey = -1;
|
||||
if( db->mallocFailed ){
|
||||
sqlite3DeleteTable(db, pTab);
|
||||
@ -3394,11 +3427,11 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
|
||||
if( pTab==0 ) return WRC_Abort;
|
||||
pTab->nRef = 1;
|
||||
pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
|
||||
pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
|
||||
while( pSel->pPrior ){ pSel = pSel->pPrior; }
|
||||
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
|
||||
pTab->iPKey = -1;
|
||||
pTab->nRowEst = 1000000;
|
||||
pTab->nRowEst = 1048576;
|
||||
pTab->tabFlags |= TF_Ephemeral;
|
||||
#endif
|
||||
}else{
|
||||
@ -3682,7 +3715,7 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
|
||||
Select *pSel = pFrom->pSelect;
|
||||
assert( pSel );
|
||||
while( pSel->pPrior ) pSel = pSel->pPrior;
|
||||
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
|
||||
selectAddColumnTypeAndCollation(pParse, pTab, pSel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4597,13 +4630,7 @@ int sqlite3Select(
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
||||
|
||||
/* Search for the index that has the least amount of columns. If
|
||||
** there is such an index, and it has less columns than the table
|
||||
** does, then we can assume that it consumes less space on disk and
|
||||
** will therefore be cheaper to scan to determine the query result.
|
||||
** In this case set iRoot to the root page number of the index b-tree
|
||||
** and pKeyInfo to the KeyInfo structure required to navigate the
|
||||
** index.
|
||||
/* Search for the index that has the lowest scan cost.
|
||||
**
|
||||
** (2011-04-15) Do not do a full scan of an unordered index.
|
||||
**
|
||||
@ -4614,13 +4641,14 @@ int sqlite3Select(
|
||||
*/
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( pIdx->bUnordered==0
|
||||
&& pIdx->szIdxRow<pTab->szTabRow
|
||||
&& pIdx->pPartIdxWhere==0
|
||||
&& (!pBest || pIdx->nColumn<pBest->nColumn)
|
||||
&& (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
|
||||
){
|
||||
pBest = pIdx;
|
||||
}
|
||||
}
|
||||
if( pBest && pBest->nColumn<pTab->nCol ){
|
||||
if( pBest ){
|
||||
iRoot = pBest->tnum;
|
||||
pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
|
||||
}
|
||||
|
@ -470,6 +470,31 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
|
||||
typedef u32 tRowcnt; /* 32-bit is the default */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Estimated quantities used for query planning are stored as 16-bit
|
||||
** logarithms. For quantity X, the value stored is 10*log2(X). This
|
||||
** gives a possible range of values of approximately 1.0e986 to 1e-986.
|
||||
** But the allowed values are "grainy". Not every value is representable.
|
||||
** For example, quantities 16 and 17 are both represented by a LogEst
|
||||
** of 40. However, since LogEst quantatites are suppose to be estimates,
|
||||
** not exact values, this imprecision is not a problem.
|
||||
**
|
||||
** "LogEst" is short for "Logarithimic Estimate".
|
||||
**
|
||||
** Examples:
|
||||
** 1 -> 0 20 -> 43 10000 -> 132
|
||||
** 2 -> 10 25 -> 46 25000 -> 146
|
||||
** 3 -> 16 100 -> 66 1000000 -> 199
|
||||
** 4 -> 20 1000 -> 99 1048576 -> 200
|
||||
** 10 -> 33 1024 -> 100 4294967296 -> 320
|
||||
**
|
||||
** The LogEst can be negative to indicate fractional values.
|
||||
** Examples:
|
||||
**
|
||||
** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
|
||||
*/
|
||||
typedef INT16_TYPE LogEst;
|
||||
|
||||
/*
|
||||
** Macros to determine whether the machine is big or little endian,
|
||||
** evaluated at runtime.
|
||||
@ -1197,7 +1222,8 @@ struct Column {
|
||||
char *zColl; /* Collating sequence. If NULL, use the default */
|
||||
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
|
||||
char affinity; /* One of the SQLITE_AFF_... values */
|
||||
u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
|
||||
u8 szEst; /* Estimated size of this column. INT==1 */
|
||||
u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
|
||||
};
|
||||
|
||||
/* Allowed values for Column.colFlags:
|
||||
@ -1361,6 +1387,7 @@ struct Table {
|
||||
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
|
||||
i16 nCol; /* Number of columns in this table */
|
||||
u16 nRef; /* Number of pointers to this Table */
|
||||
LogEst szTabRow; /* Estimated size of each table row in bytes */
|
||||
u8 tabFlags; /* Mask of TF_* values */
|
||||
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
|
||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||
@ -1472,7 +1499,7 @@ struct FKey {
|
||||
#define OE_SetDflt 8 /* Set the foreign key value to its default */
|
||||
#define OE_Cascade 9 /* Cascade the changes */
|
||||
|
||||
#define OE_Default 99 /* Do whatever the default action is */
|
||||
#define OE_Default 10 /* Do whatever the default action is */
|
||||
|
||||
|
||||
/*
|
||||
@ -1559,6 +1586,7 @@ struct Index {
|
||||
char **azColl; /* Array of collation sequence names for index */
|
||||
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
|
||||
int tnum; /* DB Page containing root of this index */
|
||||
LogEst szIdxRow; /* Estimated average row size in bytes */
|
||||
u16 nColumn; /* Number of columns in table used by this index */
|
||||
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
|
||||
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
|
||||
@ -2965,6 +2993,12 @@ int sqlite3Atoi(const char*);
|
||||
int sqlite3Utf16ByteLen(const void *pData, int nChar);
|
||||
int sqlite3Utf8CharLen(const char *pData, int nByte);
|
||||
u32 sqlite3Utf8Read(const u8**);
|
||||
LogEst sqlite3LogEst(u64);
|
||||
LogEst sqlite3LogEstAdd(LogEst,LogEst);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
LogEst sqlite3LogEstFromDouble(double);
|
||||
#endif
|
||||
u64 sqlite3LogEstToInt(LogEst);
|
||||
|
||||
/*
|
||||
** Routines to read and write variable-length integers. These used to
|
||||
@ -3081,7 +3115,7 @@ void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
|
||||
void sqlite3AlterFinishAddColumn(Parse *, Token *);
|
||||
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
|
||||
CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
|
||||
char sqlite3AffinityType(const char*);
|
||||
char sqlite3AffinityType(const char*, u8*);
|
||||
void sqlite3Analyze(Parse*, Token*, Token*);
|
||||
int sqlite3InvokeBusyHandler(BusyHandler*);
|
||||
int sqlite3FindDb(sqlite3*, Token*);
|
||||
|
@ -265,6 +265,7 @@ static int getIndexArray(
|
||||
while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
const char *zIdx = (const char *)sqlite3_column_text(pStmt, 1);
|
||||
sqlite3_stmt *pStmt2 = 0;
|
||||
if( zIdx==0 ) continue;
|
||||
zSql = sqlite3_mprintf("PRAGMA index_info(%s)", zIdx);
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
|
77
src/util.c
77
src/util.c
@ -1208,3 +1208,80 @@ void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Find (an approximate) sum of two LogEst values. This computation is
|
||||
** not a simple "+" operator because LogEst is stored as a logarithmic
|
||||
** value.
|
||||
**
|
||||
*/
|
||||
LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
|
||||
static const unsigned char x[] = {
|
||||
10, 10, /* 0,1 */
|
||||
9, 9, /* 2,3 */
|
||||
8, 8, /* 4,5 */
|
||||
7, 7, 7, /* 6,7,8 */
|
||||
6, 6, 6, /* 9,10,11 */
|
||||
5, 5, 5, /* 12-14 */
|
||||
4, 4, 4, 4, /* 15-18 */
|
||||
3, 3, 3, 3, 3, 3, /* 19-24 */
|
||||
2, 2, 2, 2, 2, 2, 2, /* 25-31 */
|
||||
};
|
||||
if( a>=b ){
|
||||
if( a>b+49 ) return a;
|
||||
if( a>b+31 ) return a+1;
|
||||
return a+x[a-b];
|
||||
}else{
|
||||
if( b>a+49 ) return b;
|
||||
if( b>a+31 ) return b+1;
|
||||
return b+x[b-a];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert an integer into a LogEst. In other words, compute a
|
||||
** good approximatation for 10*log2(x).
|
||||
*/
|
||||
LogEst sqlite3LogEst(u64 x){
|
||||
static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
|
||||
LogEst y = 40;
|
||||
if( x<8 ){
|
||||
if( x<2 ) return 0;
|
||||
while( x<8 ){ y -= 10; x <<= 1; }
|
||||
}else{
|
||||
while( x>255 ){ y += 40; x >>= 4; }
|
||||
while( x>15 ){ y += 10; x >>= 1; }
|
||||
}
|
||||
return a[x&7] + y - 10;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
** Convert a double into a LogEst
|
||||
** In other words, compute an approximation for 10*log2(x).
|
||||
*/
|
||||
LogEst sqlite3LogEstFromDouble(double x){
|
||||
u64 a;
|
||||
LogEst e;
|
||||
assert( sizeof(x)==8 && sizeof(a)==8 );
|
||||
if( x<=1 ) return 0;
|
||||
if( x<=2000000000 ) return sqlite3LogEst((u64)x);
|
||||
memcpy(&a, &x, 8);
|
||||
e = (a>>52) - 1022;
|
||||
return e*10;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
/*
|
||||
** Convert a LogEst into an integer.
|
||||
*/
|
||||
u64 sqlite3LogEstToInt(LogEst x){
|
||||
u64 n;
|
||||
if( x<10 ) return 1;
|
||||
n = x%10;
|
||||
x /= 10;
|
||||
if( n>=5 ) n -= 2;
|
||||
else if( n>=1 ) n -= 1;
|
||||
if( x>=3 ) return (n+8)<<(x-3);
|
||||
return (n+8)>>(3-x);
|
||||
}
|
||||
|
266
src/where.c
266
src/where.c
@ -48,26 +48,6 @@ typedef struct WhereScan WhereScan;
|
||||
typedef struct WhereOrCost WhereOrCost;
|
||||
typedef struct WhereOrSet WhereOrSet;
|
||||
|
||||
/*
|
||||
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
|
||||
** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
|
||||
** (Virtual tables can return a larger cost, but let's assume they do not.)
|
||||
** So all costs can be stored in a 16-bit integer without risk
|
||||
** of overflow.
|
||||
**
|
||||
** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
|
||||
** Instead, a close estimate is used. Any value of X=1 is stored as 0.
|
||||
** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
|
||||
** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
|
||||
**
|
||||
** The tool/wherecosttest.c source file implements a command-line program
|
||||
** that will convert WhereCosts to integers, convert integers to WhereCosts
|
||||
** and do addition and multiplication on WhereCost values. The wherecosttest
|
||||
** command-line program is a useful utility to have around when working with
|
||||
** this module.
|
||||
*/
|
||||
typedef short int WhereCost;
|
||||
|
||||
/*
|
||||
** This object contains information needed to implement a single nested
|
||||
** loop in WHERE clause.
|
||||
@ -132,9 +112,9 @@ struct WhereLoop {
|
||||
#endif
|
||||
u8 iTab; /* Position in FROM clause of table for this loop */
|
||||
u8 iSortIdx; /* Sorting index number. 0==None */
|
||||
WhereCost rSetup; /* One-time setup cost (ex: create transient index) */
|
||||
WhereCost rRun; /* Cost of running each loop */
|
||||
WhereCost nOut; /* Estimated number of output rows */
|
||||
LogEst rSetup; /* One-time setup cost (ex: create transient index) */
|
||||
LogEst rRun; /* Cost of running each loop */
|
||||
LogEst nOut; /* Estimated number of output rows */
|
||||
union {
|
||||
struct { /* Information for internal btree tables */
|
||||
int nEq; /* Number of equality constraints */
|
||||
@ -164,8 +144,8 @@ struct WhereLoop {
|
||||
*/
|
||||
struct WhereOrCost {
|
||||
Bitmask prereq; /* Prerequisites */
|
||||
WhereCost rRun; /* Cost of running this subquery */
|
||||
WhereCost nOut; /* Number of outputs for this subquery */
|
||||
LogEst rRun; /* Cost of running this subquery */
|
||||
LogEst nOut; /* Number of outputs for this subquery */
|
||||
};
|
||||
|
||||
/* The WhereOrSet object holds a set of possible WhereOrCosts that
|
||||
@ -203,8 +183,8 @@ static int whereLoopResize(sqlite3*, WhereLoop*, int);
|
||||
struct WherePath {
|
||||
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
|
||||
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
|
||||
WhereCost nRow; /* Estimated number of rows generated by this path */
|
||||
WhereCost rCost; /* Total cost of this path */
|
||||
LogEst nRow; /* Estimated number of rows generated by this path */
|
||||
LogEst rCost; /* Total cost of this path */
|
||||
u8 isOrdered; /* True if this path satisfies ORDER BY */
|
||||
u8 isOrderedValid; /* True if the isOrdered field is valid */
|
||||
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
|
||||
@ -270,7 +250,7 @@ struct WhereTerm {
|
||||
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
|
||||
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
|
||||
} u;
|
||||
WhereCost truthProb; /* Probability of truth for this expression */
|
||||
LogEst truthProb; /* Probability of truth for this expression */
|
||||
u16 eOperator; /* A WO_xx value describing <op> */
|
||||
u8 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u8 nChild; /* Number of children that must disable us */
|
||||
@ -418,7 +398,7 @@ struct WhereInfo {
|
||||
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
|
||||
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
||||
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
||||
WhereCost nRowOut; /* Estimated number of output rows */
|
||||
LogEst nRowOut; /* Estimated number of output rows */
|
||||
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
|
||||
u8 bOBSat; /* ORDER BY satisfied by indices */
|
||||
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
|
||||
@ -478,26 +458,11 @@ struct WhereInfo {
|
||||
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
|
||||
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
|
||||
|
||||
|
||||
/* Convert a WhereCost value (10 times log2(X)) into its integer value X.
|
||||
** A rough approximation is used. The value returned is not exact.
|
||||
*/
|
||||
static u64 whereCostToInt(WhereCost x){
|
||||
u64 n;
|
||||
if( x<10 ) return 1;
|
||||
n = x%10;
|
||||
x /= 10;
|
||||
if( n>=5 ) n -= 2;
|
||||
else if( n>=1 ) n -= 1;
|
||||
if( x>=3 ) return (n+8)<<(x-3);
|
||||
return (n+8)>>(3-x);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the estimated number of output rows from a WHERE clause
|
||||
*/
|
||||
u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
|
||||
return whereCostToInt(pWInfo->nRowOut);
|
||||
return sqlite3LogEstToInt(pWInfo->nRowOut);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -559,8 +524,8 @@ static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
|
||||
static int whereOrInsert(
|
||||
WhereOrSet *pSet, /* The WhereOrSet to be updated */
|
||||
Bitmask prereq, /* Prerequisites of the new entry */
|
||||
WhereCost rRun, /* Run-cost of the new entry */
|
||||
WhereCost nOut /* Number of outputs for the new entry */
|
||||
LogEst rRun, /* Run-cost of the new entry */
|
||||
LogEst nOut /* Number of outputs for the new entry */
|
||||
){
|
||||
u16 i;
|
||||
WhereOrCost *p;
|
||||
@ -645,9 +610,6 @@ static void whereClauseClear(WhereClause *pWC){
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static WhereCost whereCost(tRowcnt x);
|
||||
|
||||
/*
|
||||
** Add a single new WhereTerm entry to the WhereClause object pWC.
|
||||
** The new WhereTerm object is constructed from Expr p and with wtFlags.
|
||||
@ -690,7 +652,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
|
||||
}
|
||||
pTerm = &pWC->a[idx = pWC->nTerm++];
|
||||
if( p && ExprHasProperty(p, EP_Unlikely) ){
|
||||
pTerm->truthProb = whereCost(p->iTable) - 99;
|
||||
pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
|
||||
}else{
|
||||
pTerm->truthProb = -1;
|
||||
}
|
||||
@ -1954,75 +1916,12 @@ static int isDistinctRedundant(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Find (an approximate) sum of two WhereCosts. This computation is
|
||||
** not a simple "+" operator because WhereCost is stored as a logarithmic
|
||||
** value.
|
||||
**
|
||||
*/
|
||||
static WhereCost whereCostAdd(WhereCost a, WhereCost b){
|
||||
static const unsigned char x[] = {
|
||||
10, 10, /* 0,1 */
|
||||
9, 9, /* 2,3 */
|
||||
8, 8, /* 4,5 */
|
||||
7, 7, 7, /* 6,7,8 */
|
||||
6, 6, 6, /* 9,10,11 */
|
||||
5, 5, 5, /* 12-14 */
|
||||
4, 4, 4, 4, /* 15-18 */
|
||||
3, 3, 3, 3, 3, 3, /* 19-24 */
|
||||
2, 2, 2, 2, 2, 2, 2, /* 25-31 */
|
||||
};
|
||||
if( a>=b ){
|
||||
if( a>b+49 ) return a;
|
||||
if( a>b+31 ) return a+1;
|
||||
return a+x[a-b];
|
||||
}else{
|
||||
if( b>a+49 ) return b;
|
||||
if( b>a+31 ) return b+1;
|
||||
return b+x[b-a];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert an integer into a WhereCost. In other words, compute a
|
||||
** good approximatation for 10*log2(x).
|
||||
*/
|
||||
static WhereCost whereCost(tRowcnt x){
|
||||
static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
|
||||
WhereCost y = 40;
|
||||
if( x<8 ){
|
||||
if( x<2 ) return 0;
|
||||
while( x<8 ){ y -= 10; x <<= 1; }
|
||||
}else{
|
||||
while( x>255 ){ y += 40; x >>= 4; }
|
||||
while( x>15 ){ y += 10; x >>= 1; }
|
||||
}
|
||||
return a[x&7] + y - 10;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
** Convert a double (as received from xBestIndex of a virtual table)
|
||||
** into a WhereCost. In other words, compute an approximation for
|
||||
** 10*log2(x).
|
||||
*/
|
||||
static WhereCost whereCostFromDouble(double x){
|
||||
u64 a;
|
||||
WhereCost e;
|
||||
assert( sizeof(x)==8 && sizeof(a)==8 );
|
||||
if( x<=1 ) return 0;
|
||||
if( x<=2000000000 ) return whereCost((tRowcnt)x);
|
||||
memcpy(&a, &x, 8);
|
||||
e = (a>>52) - 1022;
|
||||
return e*10;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
/*
|
||||
** Estimate the logarithm of the input value to base 2.
|
||||
*/
|
||||
static WhereCost estLog(WhereCost N){
|
||||
WhereCost x = whereCost(N);
|
||||
static LogEst estLog(LogEst N){
|
||||
LogEst x = sqlite3LogEst(N);
|
||||
return x>33 ? x - 33 : 0;
|
||||
}
|
||||
|
||||
@ -2535,7 +2434,7 @@ static void whereKeyStats(
|
||||
**
|
||||
** then nEq is set to 0.
|
||||
**
|
||||
** When this function is called, *pnOut is set to the whereCost() of the
|
||||
** When this function is called, *pnOut is set to the sqlite3LogEst() of the
|
||||
** number of rows that the index scan is expected to visit without
|
||||
** considering the range constraints. If nEq is 0, this is the number of
|
||||
** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
|
||||
@ -2551,15 +2450,15 @@ static int whereRangeScanEst(
|
||||
WhereLoopBuilder *pBuilder,
|
||||
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 */
|
||||
WhereCost *pnOut /* IN/OUT: Number of rows visited */
|
||||
WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int nOut = (int)*pnOut;
|
||||
WhereCost nNew;
|
||||
int nOut = pLoop->nOut;
|
||||
int nEq = pLoop->u.btree.nEq;
|
||||
LogEst nNew;
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
Index *p = pBuilder->pNew->u.btree.pIndex;
|
||||
int nEq = pBuilder->pNew->u.btree.nEq;
|
||||
Index *p = pLoop->u.btree.pIndex;
|
||||
|
||||
if( p->nSample>0
|
||||
&& nEq==pBuilder->nRecValid
|
||||
@ -2640,14 +2539,14 @@ static int whereRangeScanEst(
|
||||
pBuilder->pRec = pRec;
|
||||
if( rc==SQLITE_OK ){
|
||||
if( iUpper>iLower ){
|
||||
nNew = whereCost(iUpper - iLower);
|
||||
nNew = sqlite3LogEst(iUpper - iLower);
|
||||
}else{
|
||||
nNew = 10; assert( 10==whereCost(2) );
|
||||
nNew = 10; assert( 10==sqlite3LogEst(2) );
|
||||
}
|
||||
if( nNew<nOut ){
|
||||
nOut = nNew;
|
||||
}
|
||||
*pnOut = (WhereCost)nOut;
|
||||
pLoop->nOut = (LogEst)nOut;
|
||||
WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
|
||||
(u32)iLower, (u32)iUpper, nOut));
|
||||
return SQLITE_OK;
|
||||
@ -2662,16 +2561,16 @@ static int whereRangeScanEst(
|
||||
** A BETWEEN operator, therefore, reduces the search space 16-fold */
|
||||
nNew = nOut;
|
||||
if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
|
||||
nNew -= 20; assert( 20==whereCost(4) );
|
||||
nNew -= 20; assert( 20==sqlite3LogEst(4) );
|
||||
nOut--;
|
||||
}
|
||||
if( pUpper ){
|
||||
nNew -= 20; assert( 20==whereCost(4) );
|
||||
nNew -= 20; assert( 20==sqlite3LogEst(4) );
|
||||
nOut--;
|
||||
}
|
||||
if( nNew<10 ) nNew = 10;
|
||||
if( nNew<nOut ) nOut = nNew;
|
||||
*pnOut = (WhereCost)nOut;
|
||||
pLoop->nOut = (LogEst)nOut;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -4315,7 +4214,7 @@ static int whereLoopAddBtreeIndex(
|
||||
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
|
||||
struct SrcList_item *pSrc, /* FROM clause term being analyzed */
|
||||
Index *pProbe, /* An index on pSrc */
|
||||
WhereCost nInMul /* log(Number of iterations due to IN) */
|
||||
LogEst nInMul /* log(Number of iterations due to IN) */
|
||||
){
|
||||
WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
|
||||
Parse *pParse = pWInfo->pParse; /* Parsing context */
|
||||
@ -4328,11 +4227,11 @@ static int whereLoopAddBtreeIndex(
|
||||
u16 saved_nLTerm; /* Original value of pNew->nLTerm */
|
||||
int saved_nEq; /* Original value of pNew->u.btree.nEq */
|
||||
u32 saved_wsFlags; /* Original value of pNew->wsFlags */
|
||||
WhereCost saved_nOut; /* Original value of pNew->nOut */
|
||||
LogEst saved_nOut; /* Original value of pNew->nOut */
|
||||
int iCol; /* Index of the column in the table */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
WhereCost nRowEst; /* Estimated index selectivity */
|
||||
WhereCost rLogSize; /* Logarithm of table size */
|
||||
LogEst nRowEst; /* Estimated index selectivity */
|
||||
LogEst rLogSize; /* Logarithm of table size */
|
||||
WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
|
||||
|
||||
pNew = pBuilder->pNew;
|
||||
@ -4352,7 +4251,7 @@ static int whereLoopAddBtreeIndex(
|
||||
assert( pNew->u.btree.nEq<=pProbe->nColumn );
|
||||
if( pNew->u.btree.nEq < pProbe->nColumn ){
|
||||
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
|
||||
nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
|
||||
nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
|
||||
if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
|
||||
}else{
|
||||
iCol = -1;
|
||||
@ -4366,7 +4265,7 @@ static int whereLoopAddBtreeIndex(
|
||||
saved_prereq = pNew->prereq;
|
||||
saved_nOut = pNew->nOut;
|
||||
pNew->rSetup = 0;
|
||||
rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
|
||||
rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
|
||||
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
|
||||
int nIn = 0;
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
@ -4393,10 +4292,10 @@ static int whereLoopAddBtreeIndex(
|
||||
pNew->wsFlags |= WHERE_COLUMN_IN;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
|
||||
nIn = 46; assert( 46==whereCost(25) );
|
||||
nIn = 46; assert( 46==sqlite3LogEst(25) );
|
||||
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
|
||||
/* "x IN (value, value, ...)" */
|
||||
nIn = whereCost(pExpr->x.pList->nExpr);
|
||||
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
|
||||
}
|
||||
pNew->rRun += nIn;
|
||||
pNew->u.btree.nEq++;
|
||||
@ -4418,7 +4317,7 @@ static int whereLoopAddBtreeIndex(
|
||||
pNew->wsFlags |= WHERE_COLUMN_NULL;
|
||||
pNew->u.btree.nEq++;
|
||||
/* TUNING: IS NULL selects 2 rows */
|
||||
nIn = 10; assert( 10==whereCost(2) );
|
||||
nIn = 10; assert( 10==sqlite3LogEst(2) );
|
||||
pNew->nOut = nRowEst + nInMul + nIn;
|
||||
}else if( pTerm->eOperator & (WO_GT|WO_GE) ){
|
||||
testcase( pTerm->eOperator & WO_GT );
|
||||
@ -4438,7 +4337,7 @@ static int whereLoopAddBtreeIndex(
|
||||
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
|
||||
/* Adjust nOut and rRun for STAT3 range values */
|
||||
assert( pNew->nOut==saved_nOut );
|
||||
whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
|
||||
whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
if( nInMul==0
|
||||
@ -4458,7 +4357,7 @@ static int whereLoopAddBtreeIndex(
|
||||
}
|
||||
assert( nOut==0 || rc==SQLITE_OK );
|
||||
if( nOut ){
|
||||
nOut = whereCost(nOut);
|
||||
nOut = sqlite3LogEst(nOut);
|
||||
pNew->nOut = MIN(nOut, saved_nOut);
|
||||
}
|
||||
}
|
||||
@ -4466,10 +4365,10 @@ static int whereLoopAddBtreeIndex(
|
||||
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
|
||||
/* Each row involves a step of the index, then a binary search of
|
||||
** the main table */
|
||||
pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10);
|
||||
}
|
||||
/* Step cost for each output row */
|
||||
pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
|
||||
whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
|
||||
rc = whereLoopInsert(pBuilder, pNew);
|
||||
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
|
||||
@ -4569,14 +4468,16 @@ static int whereLoopAddBtree(
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int iSortIdx = 1; /* Index number */
|
||||
int b; /* A boolean value */
|
||||
WhereCost rSize; /* number of rows in the table */
|
||||
WhereCost rLogSize; /* Logarithm of the number of rows in the table */
|
||||
LogEst rSize; /* number of rows in the table */
|
||||
LogEst rLogSize; /* Logarithm of the number of rows in the table */
|
||||
WhereClause *pWC; /* The parsed WHERE clause */
|
||||
Table *pTab; /* Table being queried */
|
||||
|
||||
pNew = pBuilder->pNew;
|
||||
pWInfo = pBuilder->pWInfo;
|
||||
pTabList = pWInfo->pTabList;
|
||||
pSrc = pTabList->a + pNew->iTab;
|
||||
pTab = pSrc->pTab;
|
||||
pWC = pBuilder->pWC;
|
||||
assert( !IsVirtual(pSrc->pTab) );
|
||||
|
||||
@ -4594,8 +4495,8 @@ static int whereLoopAddBtree(
|
||||
sPk.aiColumn = &aiColumnPk;
|
||||
sPk.aiRowEst = aiRowEstPk;
|
||||
sPk.onError = OE_Replace;
|
||||
sPk.pTable = pSrc->pTab;
|
||||
aiRowEstPk[0] = pSrc->pTab->nRowEst;
|
||||
sPk.pTable = pTab;
|
||||
aiRowEstPk[0] = pTab->nRowEst;
|
||||
aiRowEstPk[1] = 1;
|
||||
pFirst = pSrc->pTab->pIndex;
|
||||
if( pSrc->notIndexed==0 ){
|
||||
@ -4605,7 +4506,7 @@ static int whereLoopAddBtree(
|
||||
}
|
||||
pProbe = &sPk;
|
||||
}
|
||||
rSize = whereCost(pSrc->pTab->nRowEst);
|
||||
rSize = sqlite3LogEst(pTab->nRowEst);
|
||||
rLogSize = estLog(rSize);
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
@ -4630,13 +4531,13 @@ static int whereLoopAddBtree(
|
||||
/* TUNING: One-time cost for computing the automatic index is
|
||||
** approximately 7*N*log2(N) where N is the number of rows in
|
||||
** the table being indexed. */
|
||||
pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) );
|
||||
pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
|
||||
/* TUNING: Each index lookup yields 20 rows in the table. This
|
||||
** is more than the usual guess of 10 rows, since we have no way
|
||||
** of knowning how selective the index will ultimately be. It would
|
||||
** not be unreasonable to make this value much larger. */
|
||||
pNew->nOut = 43; assert( 43==whereCost(20) );
|
||||
pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
|
||||
pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
|
||||
pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
|
||||
pNew->wsFlags = WHERE_AUTO_INDEX;
|
||||
pNew->prereq = mExtra | pTerm->prereqRight;
|
||||
rc = whereLoopInsert(pBuilder, pNew);
|
||||
@ -4670,10 +4571,8 @@ static int whereLoopAddBtree(
|
||||
pNew->iSortIdx = b ? iSortIdx : 0;
|
||||
/* TUNING: Cost of full table scan is 3*(N + log2(N)).
|
||||
** + The extra 3 factor is to encourage the use of indexed lookups
|
||||
** over full scans. A smaller constant 2 is used for covering
|
||||
** index scans so that a covering index scan will be favored over
|
||||
** a table scan. */
|
||||
pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
|
||||
** over full scans. FIXME */
|
||||
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
|
||||
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
|
||||
rc = whereLoopInsert(pBuilder, pNew);
|
||||
pNew->nOut = rSize;
|
||||
@ -4686,6 +4585,7 @@ static int whereLoopAddBtree(
|
||||
if( b
|
||||
|| ( m==0
|
||||
&& pProbe->bUnordered==0
|
||||
&& pProbe->szIdxRow<pTab->szTabRow
|
||||
&& (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
|
||||
&& sqlite3GlobalConfig.bUseCis
|
||||
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
|
||||
@ -4693,15 +4593,13 @@ static int whereLoopAddBtree(
|
||||
){
|
||||
pNew->iSortIdx = b ? iSortIdx : 0;
|
||||
if( m==0 ){
|
||||
/* TUNING: Cost of a covering index scan is 2*(N + log2(N)).
|
||||
** + The extra 2 factor is to encourage the use of indexed lookups
|
||||
** over index scans. A table scan uses a factor of 3 so that
|
||||
** index scans are favored over table scans.
|
||||
** + If this covering index might also help satisfy the ORDER BY
|
||||
** clause, then the cost is fudged down slightly so that this
|
||||
** index is favored above other indices that have no hope of
|
||||
** helping with the ORDER BY. */
|
||||
pNew->rRun = 10 + whereCostAdd(rSize,rLogSize) - b;
|
||||
/* TUNING: Cost of a covering index scan is K*(N + log2(N)).
|
||||
** + The extra factor K of between 1.1 and 3.0 that depends
|
||||
** on the relative sizes of the table and the index. K
|
||||
** is smaller for smaller indices, thus favoring them.
|
||||
*/
|
||||
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
|
||||
(15*pProbe->szIdxRow)/pTab->szTabRow;
|
||||
}else{
|
||||
assert( b!=0 );
|
||||
/* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
|
||||
@ -4879,9 +4777,9 @@ static int whereLoopAddVirtual(
|
||||
pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
|
||||
&& pIdxInfo->orderByConsumed);
|
||||
pNew->rSetup = 0;
|
||||
pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
|
||||
pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
|
||||
/* TUNING: Every virtual table query returns 25 rows */
|
||||
pNew->nOut = 46; assert( 46==whereCost(25) );
|
||||
pNew->nOut = 46; assert( 46==sqlite3LogEst(25) );
|
||||
whereLoopInsert(pBuilder, pNew);
|
||||
if( pNew->u.vtab.needFree ){
|
||||
sqlite3_free(pNew->u.vtab.idxStr);
|
||||
@ -4918,6 +4816,8 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
pWCEnd = pWC->a + pWC->nTerm;
|
||||
pNew = pBuilder->pNew;
|
||||
memset(&sSum, 0, sizeof(sSum));
|
||||
pItem = pWInfo->pTabList->a + pNew->iTab;
|
||||
iCur = pItem->iCursor;
|
||||
|
||||
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
|
||||
if( (pTerm->eOperator & WO_OR)!=0
|
||||
@ -4929,8 +4829,6 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
int once = 1;
|
||||
int i, j;
|
||||
|
||||
pItem = pWInfo->pTabList->a + pNew->iTab;
|
||||
iCur = pItem->iCursor;
|
||||
sSubBuild = *pBuilder;
|
||||
sSubBuild.pOrderBy = 0;
|
||||
sSubBuild.pOrSet = &sCur;
|
||||
@ -4971,8 +4869,8 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
for(i=0; i<sPrev.n; i++){
|
||||
for(j=0; j<sCur.n; j++){
|
||||
whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
|
||||
whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
|
||||
whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
|
||||
sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
|
||||
sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5310,7 +5208,7 @@ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
|
||||
** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
|
||||
** error occurs.
|
||||
*/
|
||||
static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
int mxChoice; /* Maximum number of simultaneous paths tracked */
|
||||
int nLoop; /* Number of terms in the join */
|
||||
Parse *pParse; /* Parsing context */
|
||||
@ -5318,11 +5216,11 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
int iLoop; /* Loop counter over the terms of the join */
|
||||
int ii, jj; /* Loop counters */
|
||||
int mxI = 0; /* Index of next entry to replace */
|
||||
WhereCost rCost; /* Cost of a path */
|
||||
WhereCost nOut; /* Number of outputs */
|
||||
WhereCost mxCost = 0; /* Maximum cost of a set of paths */
|
||||
WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */
|
||||
WhereCost rSortCost; /* Cost to do a sort */
|
||||
LogEst rCost; /* Cost of a path */
|
||||
LogEst nOut; /* Number of outputs */
|
||||
LogEst mxCost = 0; /* Maximum cost of a set of paths */
|
||||
LogEst mxOut = 0; /* Maximum nOut value on the set of paths */
|
||||
LogEst rSortCost; /* Cost to do a sort */
|
||||
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
|
||||
WherePath *aFrom; /* All nFrom paths at the previous level */
|
||||
WherePath *aTo; /* The nTo best paths at the current level */
|
||||
@ -5359,7 +5257,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
** TUNING: Do not let the number of iterations go above 25. If the cost
|
||||
** of computing an automatic index is not paid back within the first 25
|
||||
** rows, then do not use the automatic index. */
|
||||
aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) );
|
||||
aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
|
||||
nFrom = 1;
|
||||
|
||||
/* Precompute the cost of sorting the final result set, if the caller
|
||||
@ -5368,8 +5266,10 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
if( pWInfo->pOrderBy==0 || nRowEst==0 ){
|
||||
aFrom[0].isOrderedValid = 1;
|
||||
}else{
|
||||
/* TUNING: Estimated cost of sorting is N*log2(N) where N is the
|
||||
** number of output rows. */
|
||||
/* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
|
||||
** number of output rows. The 48 is the expected size of a row to sort.
|
||||
** FIXME: compute a better estimate of the 48 multiplier based on the
|
||||
** result set expressions. */
|
||||
rSortCost = nRowEst + estLog(nRowEst);
|
||||
WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
|
||||
}
|
||||
@ -5389,8 +5289,8 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
|
||||
/* At this point, pWLoop is a candidate to be the next loop.
|
||||
** Compute its cost */
|
||||
rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rCost = whereCostAdd(rCost, pFrom->rCost);
|
||||
rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
|
||||
nOut = pFrom->nRow + pWLoop->nOut;
|
||||
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
|
||||
if( !isOrderedValid ){
|
||||
@ -5404,7 +5304,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
case 0: /* No. pFrom+pWLoop will require a separate sort */
|
||||
isOrdered = 0;
|
||||
isOrderedValid = 1;
|
||||
rCost = whereCostAdd(rCost, rSortCost);
|
||||
rCost = sqlite3LogEstAdd(rCost, rSortCost);
|
||||
break;
|
||||
default: /* Cannot tell yet. Try again on the next iteration */
|
||||
break;
|
||||
@ -5611,7 +5511,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
||||
pLoop->nLTerm = 1;
|
||||
pLoop->u.btree.nEq = 1;
|
||||
/* TUNING: Cost of a rowid lookup is 10 */
|
||||
pLoop->rRun = 33; /* 33==whereCost(10) */
|
||||
pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
|
||||
}else{
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
assert( pLoop->aLTermSpace==pLoop->aLTerm );
|
||||
@ -5634,12 +5534,12 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
||||
pLoop->u.btree.nEq = j;
|
||||
pLoop->u.btree.pIndex = pIdx;
|
||||
/* TUNING: Cost of a unique index lookup is 15 */
|
||||
pLoop->rRun = 39; /* 39==whereCost(15) */
|
||||
pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( pLoop->wsFlags ){
|
||||
pLoop->nOut = (WhereCost)1;
|
||||
pLoop->nOut = (LogEst)1;
|
||||
pWInfo->a[0].pWLoop = pLoop;
|
||||
pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
|
||||
pWInfo->a[0].iTabCur = iCur;
|
||||
|
@ -30,14 +30,14 @@ proc eqp {sql {db db}} {
|
||||
|
||||
do_test analyze6-1.0 {
|
||||
db eval {
|
||||
CREATE TABLE cat(x INT);
|
||||
CREATE TABLE cat(x INT, yz TEXT);
|
||||
CREATE UNIQUE INDEX catx ON cat(x);
|
||||
/* Give cat 16 unique integers */
|
||||
INSERT INTO cat VALUES(1);
|
||||
INSERT INTO cat VALUES(2);
|
||||
INSERT INTO cat SELECT x+2 FROM cat;
|
||||
INSERT INTO cat SELECT x+4 FROM cat;
|
||||
INSERT INTO cat SELECT x+8 FROM cat;
|
||||
INSERT INTO cat(x) VALUES(1);
|
||||
INSERT INTO cat(x) VALUES(2);
|
||||
INSERT INTO cat(x) SELECT x+2 FROM cat;
|
||||
INSERT INTO cat(x) SELECT x+4 FROM cat;
|
||||
INSERT INTO cat(x) SELECT x+8 FROM cat;
|
||||
|
||||
CREATE TABLE ev(y INT);
|
||||
CREATE INDEX evy ON ev(y);
|
||||
|
@ -450,17 +450,17 @@ do_join_test e_select-1.4.1.4 {
|
||||
# left-hand and right-hand datasets.
|
||||
#
|
||||
do_join_test e_select-1.4.2.1 {
|
||||
SELECT * FROM x2 %JOIN% x3
|
||||
SELECT * FROM x2 %JOIN% x3 ORDER BY +c, +f
|
||||
} [list -60.06 {} {} -39.24 {} encompass -1 \
|
||||
-60.06 {} {} presenting 51 reformation dignified \
|
||||
-60.06 {} {} conducting -87.24 37.56 {} \
|
||||
-60.06 {} {} coldest -96 dramatists 82.3 \
|
||||
-60.06 {} {} alerting {} -93.79 {} \
|
||||
-60.06 {} {} coldest -96 dramatists 82.3 \
|
||||
-60.06 {} {} conducting -87.24 37.56 {} \
|
||||
-60.06 {} {} presenting 51 reformation dignified \
|
||||
-58 {} 1.21 -39.24 {} encompass -1 \
|
||||
-58 {} 1.21 presenting 51 reformation dignified \
|
||||
-58 {} 1.21 conducting -87.24 37.56 {} \
|
||||
-58 {} 1.21 coldest -96 dramatists 82.3 \
|
||||
-58 {} 1.21 alerting {} -93.79 {} \
|
||||
-58 {} 1.21 coldest -96 dramatists 82.3 \
|
||||
-58 {} 1.21 conducting -87.24 37.56 {} \
|
||||
-58 {} 1.21 presenting 51 reformation dignified \
|
||||
]
|
||||
# TODO: Come back and add a few more like the above.
|
||||
|
||||
|
@ -33,11 +33,11 @@ set testprefix eqp
|
||||
proc det {args} { uplevel do_eqp_test $args }
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t1(a INT, b INT, ex TEXT);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
CREATE INDEX i2 ON t1(b);
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE TABLE t3(a, b);
|
||||
CREATE TABLE t2(a INT, b INT, ex TEXT);
|
||||
CREATE TABLE t3(a INT, b INT, ex TEXT);
|
||||
}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
@ -122,9 +122,9 @@ do_eqp_test 1.11 {
|
||||
#
|
||||
drop_all_tables
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t1(x INT, y INT, ex TEXT);
|
||||
|
||||
CREATE TABLE t2(x, y);
|
||||
CREATE TABLE t2(x INT, y INT, ex TEXT);
|
||||
CREATE INDEX t2i1 ON t2(x);
|
||||
}
|
||||
|
||||
@ -374,7 +374,7 @@ drop_all_tables
|
||||
# FROM t1 WHERE a=1;
|
||||
# 0|0|0|SCAN TABLE t1
|
||||
#
|
||||
do_execsql_test 5.1.0 { CREATE TABLE t1(a, b) }
|
||||
do_execsql_test 5.1.0 { CREATE TABLE t1(a INT, b INT, ex TEXT) }
|
||||
det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
@ -402,8 +402,8 @@ det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {
|
||||
# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
|
||||
# 0|1|1|SCAN TABLE t2
|
||||
#
|
||||
do_execsql_test 5.4.0 {CREATE TABLE t2(c, d)}
|
||||
det 5.4.1 "SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
|
||||
do_execsql_test 5.4.0 {CREATE TABLE t2(c INT, d INT, ex TEXT)}
|
||||
det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
|
||||
0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
|
||||
0 1 1 {SCAN TABLE t2}
|
||||
}
|
||||
@ -413,7 +413,7 @@ det 5.4.1 "SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
|
||||
# 0|0|1|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
|
||||
# 0|1|0|SCAN TABLE t2
|
||||
#
|
||||
det 5.5 "SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
|
||||
det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
|
||||
0 0 1 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
|
||||
0 1 0 {SCAN TABLE t2}
|
||||
}
|
||||
@ -424,7 +424,7 @@ det 5.5 "SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
|
||||
# 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
|
||||
#
|
||||
do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}
|
||||
det 5.6.1 "SELECT * FROM t1 WHERE a=1 OR b=2" {
|
||||
det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" {
|
||||
0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
|
||||
}
|
||||
@ -485,7 +485,7 @@ det 5.10 {
|
||||
# 0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?)
|
||||
# 0|1|1|SCAN TABLE t1
|
||||
#
|
||||
det 5.11 "SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1" {
|
||||
det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
|
||||
0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2}
|
||||
}
|
||||
@ -496,7 +496,7 @@ det 5.11 "SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1" {
|
||||
# 2|0|0|SCAN TABLE t2
|
||||
# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
|
||||
#
|
||||
det 5.12 "SELECT a FROM t1 UNION SELECT c FROM t2" {
|
||||
det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" {
|
||||
1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
|
||||
2 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
|
||||
@ -509,7 +509,7 @@ det 5.12 "SELECT a FROM t1 UNION SELECT c FROM t2" {
|
||||
# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
|
||||
#
|
||||
det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
|
||||
1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
|
||||
1 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
2 0 0 {SCAN TABLE t2}
|
||||
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
|
||||
@ -548,7 +548,7 @@ proc do_peqp_test {tn sql res} {
|
||||
}
|
||||
|
||||
do_peqp_test 6.1 {
|
||||
SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1
|
||||
SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
|
||||
} [string trimleft {
|
||||
1 0 0 SCAN TABLE t1 USING COVERING INDEX i2
|
||||
2 0 0 SCAN TABLE t2
|
||||
@ -563,8 +563,8 @@ do_peqp_test 6.1 {
|
||||
drop_all_tables
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE TABLE t1(a INT, b INT, ex CHAR(100));
|
||||
CREATE TABLE t2(a INT, b INT, ex CHAR(100));
|
||||
CREATE INDEX i1 ON t2(a);
|
||||
}
|
||||
|
||||
@ -577,12 +577,12 @@ det 7.2 "SELECT count(*) FROM t2" {
|
||||
}
|
||||
|
||||
do_execsql_test 7.3 {
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1(a,b) VALUES(1, 2);
|
||||
INSERT INTO t1(a,b) VALUES(3, 4);
|
||||
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
INSERT INTO t2 VALUES(5, 6);
|
||||
INSERT INTO t2(a,b) VALUES(1, 2);
|
||||
INSERT INTO t2(a,b) VALUES(3, 4);
|
||||
INSERT INTO t2(a,b) VALUES(5, 6);
|
||||
|
||||
ANALYZE;
|
||||
}
|
||||
|
@ -574,7 +574,7 @@ ifcapable {foreignkey} {
|
||||
execsql {
|
||||
pragma index_list(t3);
|
||||
}
|
||||
} {0 sqlite_autoindex_t3_1 1}
|
||||
} {/0 {} 1 \d+ 1 sqlite_autoindex_t3_1 1 \d+/}
|
||||
}
|
||||
ifcapable {!foreignkey} {
|
||||
execsql {CREATE TABLE t3(a,b UNIQUE)}
|
||||
@ -647,7 +647,7 @@ do_test pragma-7.1.1 {
|
||||
execsql {
|
||||
pragma index_list(t3);
|
||||
}
|
||||
} {0 t3i1 0 1 sqlite_autoindex_t3_1 1}
|
||||
} {/0 {} 1 \d+ 1 t3i1 0 \d+ 2 sqlite_autoindex_t3_1 1 \d+/}
|
||||
do_test pragma-7.1.2 {
|
||||
execsql {
|
||||
pragma index_list(t3_bogus);
|
||||
@ -1661,7 +1661,7 @@ do_test 23.3 {
|
||||
CREATE INDEX i3 ON t1(d,b,c);
|
||||
}
|
||||
db2 eval {PRAGMA index_list(t1)}
|
||||
} {0 i3 0 1 i2 0 2 i1 0}
|
||||
} {/0 {} 1 \d+ 1 i3 0 \d+ 2 i2 0 \d+ 3 i1 0 \d+/}
|
||||
do_test 23.4 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN e;
|
||||
|
@ -542,7 +542,7 @@ do_test select1-6.9.7 {
|
||||
set x [execsql2 {
|
||||
SELECT * FROM test1 a, (select 5, 6) LIMIT 1
|
||||
}]
|
||||
regsub -all {subquery_[0-9a-fA-F]+_} $x {subquery} x
|
||||
regsub -all {sq_[0-9a-fA-F_]+} $x {subquery} x
|
||||
set x
|
||||
} {a.f1 11 a.f2 22 sqlite_subquery.5 5 sqlite_subquery.6 6}
|
||||
do_test select1-6.9.8 {
|
||||
|
@ -245,7 +245,7 @@ do_test subquery-2.5.3.2 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT * FROM t4 WHERE x IN (SELECT a FROM t3);
|
||||
}
|
||||
} {/SCAN TABLE t4 /}
|
||||
} {~/t4i/}
|
||||
do_test subquery-2.5.4 {
|
||||
execsql {
|
||||
DROP TABLE t3;
|
||||
|
@ -18,23 +18,23 @@ source $testdir/tester.tcl
|
||||
|
||||
do_test tkt-78e04-1.0 {
|
||||
execsql {
|
||||
CREATE TABLE ""("" UNIQUE);
|
||||
CREATE TABLE ""("" UNIQUE, x CHAR(100));
|
||||
CREATE TABLE t2(x);
|
||||
INSERT INTO "" VALUES(1);
|
||||
INSERT INTO ""("") VALUES(1);
|
||||
INSERT INTO t2 VALUES(2);
|
||||
SELECT * FROM "", t2;
|
||||
}
|
||||
} {1 2}
|
||||
} {1 {} 2}
|
||||
do_test tkt-78e04-1.1 {
|
||||
catchsql {
|
||||
INSERT INTO "" VALUES(1);
|
||||
INSERT INTO ""("") VALUES(1);
|
||||
}
|
||||
} {1 {column is not unique}}
|
||||
do_test tkt-78e04-1.2 {
|
||||
execsql {
|
||||
PRAGMA table_info("");
|
||||
}
|
||||
} {0 {} {} 0 {} 0}
|
||||
} {0 {} {} 0 {} 0 1 x CHAR(100) 0 {} 0}
|
||||
do_test tkt-78e04-1.3 {
|
||||
execsql {
|
||||
CREATE INDEX i1 ON ""("" COLLATE nocase);
|
||||
@ -42,7 +42,7 @@ do_test tkt-78e04-1.3 {
|
||||
} {}
|
||||
do_test tkt-78e04-1.4 {
|
||||
execsql {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM "" WHERE "" LIKE 'abc%';
|
||||
EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE 'abc%';
|
||||
}
|
||||
} {0 0 0 {SCAN TABLE USING COVERING INDEX i1}}
|
||||
do_test tkt-78e04-1.5 {
|
||||
|
@ -1125,9 +1125,9 @@ do_test where-13.12 {
|
||||
if {[permutation] != "no_optimization"} {
|
||||
do_test where-14.1 {
|
||||
execsql {
|
||||
CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT UNIQUE);
|
||||
INSERT INTO t8 VALUES(1,'one');
|
||||
INSERT INTO t8 VALUES(4,'four');
|
||||
CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT UNIQUE, c CHAR(100));
|
||||
INSERT INTO t8(a,b) VALUES(1,'one');
|
||||
INSERT INTO t8(a,b) VALUES(4,'four');
|
||||
}
|
||||
cksort {
|
||||
SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, y.b
|
||||
|
@ -314,9 +314,9 @@ if {[permutation] != "no_optimization"} {
|
||||
#
|
||||
do_test where2-6.7 {
|
||||
execsql {
|
||||
CREATE TABLE t2249a(a TEXT UNIQUE);
|
||||
CREATE TABLE t2249a(a TEXT UNIQUE, x CHAR(100));
|
||||
CREATE TABLE t2249b(b INTEGER);
|
||||
INSERT INTO t2249a VALUES('0123');
|
||||
INSERT INTO t2249a(a) VALUES('0123');
|
||||
INSERT INTO t2249b VALUES(123);
|
||||
}
|
||||
queryplan {
|
||||
@ -324,7 +324,7 @@ do_test where2-6.7 {
|
||||
-- will attempt to convert to NUMERIC before the comparison.
|
||||
-- They will thus compare equal.
|
||||
--
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b;
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b;
|
||||
}
|
||||
} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.9 {
|
||||
@ -332,13 +332,13 @@ do_test where2-6.9 {
|
||||
-- The + operator removes affinity from the rhs. No conversions
|
||||
-- occur and the comparison is false. The result is an empty set.
|
||||
--
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b;
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b;
|
||||
}
|
||||
} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.9.2 {
|
||||
# The same thing but with the expression flipped around.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a
|
||||
}
|
||||
} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.10 {
|
||||
@ -346,32 +346,32 @@ do_test where2-6.10 {
|
||||
-- Use + on both sides of the comparison to disable indices
|
||||
-- completely. Make sure we get the same result.
|
||||
--
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE +a=+b;
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +a=+b;
|
||||
}
|
||||
} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.11 {
|
||||
# This will not attempt the OR optimization because of the a=b
|
||||
# comparison.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello';
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello';
|
||||
}
|
||||
} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.11.2 {
|
||||
# Permutations of the expression terms.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello';
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello';
|
||||
}
|
||||
} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.11.3 {
|
||||
# Permutations of the expression terms.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a;
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a;
|
||||
}
|
||||
} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.11.4 {
|
||||
# Permutations of the expression terms.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a;
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a;
|
||||
}
|
||||
} {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
ifcapable explain&&subquery {
|
||||
@ -385,7 +385,7 @@ ifcapable explain&&subquery {
|
||||
# the OR optimization to be used again. The result is now an empty
|
||||
# set, the same as in where2-6.9.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello';
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello';
|
||||
}
|
||||
} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.12.2 {
|
||||
@ -393,7 +393,7 @@ ifcapable explain&&subquery {
|
||||
# the OR optimization to be used again. The result is now an empty
|
||||
# set, the same as in where2-6.9.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a;
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a;
|
||||
}
|
||||
} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.12.3 {
|
||||
@ -401,14 +401,14 @@ ifcapable explain&&subquery {
|
||||
# the OR optimization to be used again. The result is now an empty
|
||||
# set, the same as in where2-6.9.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello';
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello';
|
||||
}
|
||||
} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.13 {
|
||||
# The addition of +a on the second term disabled the OR optimization.
|
||||
# But we should still get the same empty-set result as in where2-6.9.
|
||||
queryplan {
|
||||
SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello';
|
||||
SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello';
|
||||
}
|
||||
} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
|
||||
}
|
||||
@ -417,7 +417,7 @@ ifcapable explain&&subquery {
|
||||
# to make sure the OR optimizer can recognize them all.
|
||||
do_test where2-6.20 {
|
||||
queryplan {
|
||||
SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a
|
||||
SELECT x.a, y.a FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a
|
||||
}
|
||||
} {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
|
||||
ifcapable explain&&subquery {
|
||||
@ -428,17 +428,20 @@ ifcapable explain&&subquery {
|
||||
#
|
||||
do_test where2-6.21 {
|
||||
queryplan {
|
||||
SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a OR y.a='hello'
|
||||
SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
|
||||
WHERE x.a=y.a OR y.a='hello'
|
||||
}
|
||||
} {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.22 {
|
||||
queryplan {
|
||||
SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE y.a=x.a OR y.a='hello'
|
||||
SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
|
||||
WHERE y.a=x.a OR y.a='hello'
|
||||
}
|
||||
} {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
|
||||
do_test where2-6.23 {
|
||||
queryplan {
|
||||
SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE y.a='hello' OR x.a=y.a
|
||||
SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
|
||||
WHERE y.a='hello' OR x.a=y.a
|
||||
}
|
||||
} {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
|
||||
}
|
||||
@ -703,7 +706,7 @@ do_test where2-11.4 {
|
||||
# the OR clause scores slightly better on an inner loop.
|
||||
if {[permutation] != "no_optimization"} {
|
||||
do_execsql_test where2-12.1 {
|
||||
CREATE TABLE t12(x INTEGER PRIMARY KEY, y);
|
||||
CREATE TABLE t12(x INTEGER PRIMARY KEY, y INT, z CHAR(100));
|
||||
CREATE INDEX t12y ON t12(y);
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a.x, b.x
|
||||
|
@ -10,39 +10,42 @@
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains a simple command-line utility for converting from
|
||||
** integers and WhereCost values and back again and for doing simple
|
||||
** arithmetic operations (multiple and add) on WhereCost values.
|
||||
** integers and LogEst values and back again and for doing simple
|
||||
** arithmetic operations (multiple and add) on LogEst values.
|
||||
**
|
||||
** Usage:
|
||||
**
|
||||
** ./wherecosttest ARGS
|
||||
** ./LogEst ARGS
|
||||
**
|
||||
** Arguments:
|
||||
**
|
||||
** 'x' Multiple the top two elements of the stack
|
||||
** '+' Add the top two elements of the stack
|
||||
** NUM Convert NUM from integer to WhereCost and push onto the stack
|
||||
** ^NUM Interpret NUM as a WhereCost and push onto stack.
|
||||
** NUM Convert NUM from integer to LogEst and push onto the stack
|
||||
** ^NUM Interpret NUM as a LogEst and push onto stack.
|
||||
**
|
||||
** Examples:
|
||||
**
|
||||
** To convert 123 from WhereCost to integer:
|
||||
** To convert 123 from LogEst to integer:
|
||||
**
|
||||
** ./wherecosttest ^123
|
||||
** ./LogEst ^123
|
||||
**
|
||||
** To convert 123456 from integer to WhereCost:
|
||||
** To convert 123456 from integer to LogEst:
|
||||
**
|
||||
** ./wherecosttest 123456
|
||||
** ./LogEst 123456
|
||||
**
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
typedef unsigned short int WhereCost; /* 10 times log2() */
|
||||
typedef short int LogEst; /* 10 times log2() */
|
||||
|
||||
WhereCost whereCostMultiply(WhereCost a, WhereCost b){ return a+b; }
|
||||
WhereCost whereCostAdd(WhereCost a, WhereCost b){
|
||||
LogEst logEstMultiply(LogEst a, LogEst b){ return a+b; }
|
||||
LogEst logEstAdd(LogEst a, LogEst b){
|
||||
static const unsigned char x[] = {
|
||||
10, 10, /* 0,1 */
|
||||
9, 9, /* 2,3 */
|
||||
@ -54,14 +57,14 @@ WhereCost whereCostAdd(WhereCost a, WhereCost b){
|
||||
3, 3, 3, 3, 3, 3, /* 19-24 */
|
||||
2, 2, 2, 2, 2, 2, 2, /* 25-31 */
|
||||
};
|
||||
if( a<b ){ WhereCost t = a; a = b; b = t; }
|
||||
if( a<b ){ LogEst t = a; a = b; b = t; }
|
||||
if( a>b+49 ) return a;
|
||||
if( a>b+31 ) return a+1;
|
||||
return a+x[a-b];
|
||||
}
|
||||
WhereCost whereCostFromInteger(int x){
|
||||
static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
|
||||
WhereCost y = 40;
|
||||
LogEst logEstFromInteger(sqlite3_uint64 x){
|
||||
static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
|
||||
LogEst y = 40;
|
||||
if( x<8 ){
|
||||
if( x<2 ) return 0;
|
||||
while( x<8 ){ y -= 10; x <<= 1; }
|
||||
@ -71,8 +74,8 @@ WhereCost whereCostFromInteger(int x){
|
||||
}
|
||||
return a[x&7] + y - 10;
|
||||
}
|
||||
static unsigned long int whereCostToInt(WhereCost x){
|
||||
unsigned long int n;
|
||||
static sqlite3_uint64 logEstToInt(LogEst x){
|
||||
sqlite3_uint64 n;
|
||||
if( x<10 ) return 1;
|
||||
n = x%10;
|
||||
x /= 10;
|
||||
@ -81,31 +84,58 @@ static unsigned long int whereCostToInt(WhereCost x){
|
||||
if( x>=3 ) return (n+8)<<(x-3);
|
||||
return (n+8)>>(3-x);
|
||||
}
|
||||
static LogEst logEstFromDouble(double x){
|
||||
sqlite3_uint64 a;
|
||||
LogEst e;
|
||||
assert( sizeof(x)==8 && sizeof(a)==8 );
|
||||
if( x<=0.0 ) return -32768;
|
||||
if( x<1.0 ) return -logEstFromDouble(1/x);
|
||||
if( x<1024.0 ) return logEstFromInteger((sqlite3_uint64)(1024.0*x)) - 100;
|
||||
if( x<=2000000000.0 ) return logEstFromInteger((sqlite3_uint64)x);
|
||||
memcpy(&a, &x, 8);
|
||||
e = (a>>52) - 1022;
|
||||
return e*10;
|
||||
}
|
||||
|
||||
int isFloat(const char *z){
|
||||
while( z[0] ){
|
||||
if( z[0]=='.' || z[0]=='E' || z[0]=='e' ) return 1;
|
||||
z++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int i;
|
||||
int n = 0;
|
||||
WhereCost a[100];
|
||||
LogEst a[100];
|
||||
for(i=1; i<argc; i++){
|
||||
const char *z = argv[i];
|
||||
if( z[0]=='+' ){
|
||||
if( n>=2 ){
|
||||
a[n-2] = whereCostAdd(a[n-2],a[n-1]);
|
||||
a[n-2] = logEstAdd(a[n-2],a[n-1]);
|
||||
n--;
|
||||
}
|
||||
}else if( z[0]=='x' ){
|
||||
if( n>=2 ){
|
||||
a[n-2] = whereCostMultiply(a[n-2],a[n-1]);
|
||||
a[n-2] = logEstMultiply(a[n-2],a[n-1]);
|
||||
n--;
|
||||
}
|
||||
}else if( z[0]=='^' ){
|
||||
a[n++] = atoi(z+1);
|
||||
}else if( isFloat(z) ){
|
||||
a[n++] = logEstFromDouble(atof(z));
|
||||
}else{
|
||||
a[n++] = whereCostFromInteger(atoi(z));
|
||||
a[n++] = logEstFromInteger(atoi(z));
|
||||
}
|
||||
}
|
||||
for(i=n-1; i>=0; i--){
|
||||
printf("%d (%lu)\n", a[i], whereCostToInt(a[i]));
|
||||
if( a[i]<0 ){
|
||||
printf("%d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i]));
|
||||
}else{
|
||||
sqlite3_uint64 x = logEstToInt(a[i]+100)*100/1024;
|
||||
printf("%d (%lld.%02lld)\n", a[i], x/100, x%100);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user