From 6876dccbfe1cc8cbbb7a5ba1d7126dde82a34dee Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 26 Apr 2018 18:34:26 +0000 Subject: [PATCH 01/60] The previous fix for ticket [d85fffd6ffe856092ed8da] in check-in [0a514e62ad1ebe5c12da8dae] did not completely address the probably in that it only worked for cases where the OP_SCopy that loaded the register was the last instruction in the sequence for the expression, which is not necessarily the case for expressions like CASE...END. This revision prevents the registered that will be recomputed from being cached in the first place. FossilOrigin-Name: 9fd0faf517993587d2f54212638545fc85fbbc84a031bcfae8c1e5894825d83b --- manifest | 21 ++++++++++----------- manifest.uuid | 2 +- src/update.c | 12 ++++++------ src/vdbe.h | 1 - src/vdbeaux.c | 6 ------ test/trigger1.test | 6 ++++++ 6 files changed, 23 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index d319175a99..83c1301534 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sprocessing\san\s"ORDER\sBY\s...\sLIMIT"\sthat\sdoes\snot\suse\san\sindex,\scheck\nwhether\sor\snot\sa\srecord\smay\sappear\sin\sthe\sfinal\sresult\sset\sbefore\sadding\sit\sto\nthe\stemp\sb-tree\sused\sfor\ssorting. -D 2018-04-26T17:43:35.709 +C The\sprevious\sfix\sfor\sticket\s[d85fffd6ffe856092ed8da]\sin\scheck-in\s\n[0a514e62ad1ebe5c12da8dae]\sdid\snot\scompletely\saddress\sthe\nprobably\sin\sthat\sit\sonly\sworked\sfor\scases\swhere\sthe\sOP_SCopy\sthat\sloaded\nthe\sregister\swas\sthe\slast\sinstruction\sin\sthe\ssequence\sfor\sthe\sexpression,\swhich\nis\snot\snecessarily\sthe\scase\sfor\sexpressions\slike\sCASE...END.\s\sThis\srevision\nprevents\sthe\sregistered\sthat\swill\sbe\srecomputed\sfrom\sbeing\scached\sin\sthe\sfirst\nplace. +D 2018-04-26T18:34:26.853 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -557,16 +557,16 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97 F src/treeview.c 6cea286ca9af8b126dae9714799265353387244eba0d451c3cc2cd60946cc4c7 F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995 -F src/update.c 75ac1102d791d999ca918d7b3dced4b3023fb0ed1167a4b11591c5bc3cfbb439 +F src/update.c 5be2f501ddc704fc04183bdb28b25eab930bb8553d973429a089ec94fa85cf2b F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5 F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55 -F src/vdbe.h fff31fb658cf1aac5a2fb4d06f8d16589aef38a906e78a1565a78b8c5df7fc0a +F src/vdbe.h 574ce9a0d57b026fc93ac379a339b8d391977f335ab4176a7e21ba902e9184bd F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858 -F src/vdbeaux.c b82ca213e6b5461ef773beb76a2cfb720b301372dd4797007eb13ef6cf6f18c4 +F src/vdbeaux.c 944bae5207bbce456c466d01dcf2aac3ad49c957325d35c0ba7de882d3e5c25c F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f @@ -1477,7 +1477,7 @@ F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76 F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94 F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677 -F test/trigger1.test 254eb5245c472af5fd5a6d8c321f7af97b8532db2eff7a24c31ac67155a12c27 +F test/trigger1.test 17e4b43e656c4b354df2357634a6ba887990f510c43629f4feca30e3338d2a61 F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359 @@ -1725,8 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0a514e62ad1ebe5c12da8daed429ae2f9d9910471d3c5cef3b6870bdadfefca1 71bf91c218334381b1b4bdba6a093e623b62e17f3e8550e154a11f0cb0b404f3 -R 4228df14b2641be536d92a6cbe9f519e -T +closed 71bf91c218334381b1b4bdba6a093e623b62e17f3e8550e154a11f0cb0b404f3 -U dan -Z 8a2a73a40bbf3e885ec761eb0e674078 +P 0fcfc36ceb820fc70136b799a0405fe92e50646e697be2872bbe9a53a05ed5a9 +R 678fd436c8bb55088cd3e5add9e902ed +U drh +Z f084b8f7ac201c9b316a44eacae3d476 diff --git a/manifest.uuid b/manifest.uuid index 9db48c2532..cf4cf4ab2e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0fcfc36ceb820fc70136b799a0405fe92e50646e697be2872bbe9a53a05ed5a9 \ No newline at end of file +9fd0faf517993587d2f54212638545fc85fbbc84a031bcfae8c1e5894825d83b \ No newline at end of file diff --git a/src/update.c b/src/update.c index d098df820d..913fc2dd7a 100644 --- a/src/update.c +++ b/src/update.c @@ -602,12 +602,6 @@ void sqlite3Update( j = aXRef[i]; if( j>=0 ){ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); - if( tmask&TRIGGER_BEFORE ){ - /* Must preserve copied values even in case the original is - ** reloaded in the After-BEFORE-trigger-reload-loop below. - ** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28 */ - sqlite3VdbeSwapOpcode(v, -1, OP_SCopy, OP_Copy); - } }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){ /* This branch loads the value of a column that will not be changed ** into a register. This is done if there are no BEFORE triggers, or @@ -617,6 +611,12 @@ void sqlite3Update( testcase( i==31 ); testcase( i==32 ); sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); + if( tmask & TRIGGER_BEFORE ){ + /* This value will be recomputed in After-BEFORE-trigger-reload-loop + ** below, so make sure that it is not cached and reused. + ** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */ + sqlite3ExprCacheRemove(pParse, regNew+i, 1); + } }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); } diff --git a/src/vdbe.h b/src/vdbe.h index 6dcf2e4dd2..60525a9e9e 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -200,7 +200,6 @@ void sqlite3VdbeEndCoroutine(Vdbe*,int); VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); -void sqlite3VdbeSwapOpcode(Vdbe*, u32 addr, u8, u8); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index aff08ea3e6..be092b98b7 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -843,12 +843,6 @@ void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; } -/* Change the opcode to iNew if it was previously iOld */ -void sqlite3VdbeSwapOpcode(Vdbe *p, u32 addr, u8 iOld, u8 iNew){ - VdbeOp *pOp = sqlite3VdbeGetOp(p,addr); - if( pOp->opcode==iOld ) pOp->opcode = iNew; -} - /* ** Change the P2 operand of instruction addr so that it points to ** the address of the next instruction to be coded. diff --git a/test/trigger1.test b/test/trigger1.test index f3a0e62977..8946cd85c9 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -761,5 +761,11 @@ do_execsql_test trigger1-19.0 { UPDATE t19 SET c=b WHERE a=1; SELECT * FROM t19; } {1 2 2} +do_execsql_test trigger1-19.1 { + DELETE FROM t19; + INSERT INTO t19(a,b,c) VALUES(1,2,3); + UPDATE t19 SET c=CASE WHEN b=2 THEN b ELSE b+99 END WHERE a=1; + SELECT * FROM t19; +} {1 2 2} finish_test From ef9e3d78f25f02b6ecc8f092ef6a7f6647cd60dc Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 27 Apr 2018 15:17:08 +0000 Subject: [PATCH 02/60] Enhance the comments in the templatevtab.c implementation. FossilOrigin-Name: 05f6278a02e5cde89f76ced5af7d508e26576d7291dad7ee9e06b1a3be516cb0 --- ext/misc/templatevtab.c | 34 +++++++++++++++++++++++++--------- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/ext/misc/templatevtab.c b/ext/misc/templatevtab.c index 31929a28ba..95b5f60cab 100644 --- a/ext/misc/templatevtab.c +++ b/ext/misc/templatevtab.c @@ -10,40 +10,45 @@ ** ************************************************************************* ** -** This file implements a template virtual-table implementation. +** This file implements a template virtual-table. ** Developers can make a copy of this file as a baseline for writing ** new virtual tables and/or table-valued functions. ** ** Steps for writing a new virtual table implementation: ** -** (1) Make a copy of this file. Prehaps "mynewvtab.c" +** (1) Make a copy of this file. Perhaps call it "mynewvtab.c" ** ** (2) Replace this header comment with something appropriate for ** the new virtual table ** ** (3) Change every occurrence of "templatevtab" to some other string ** appropriate for the new virtual table. Ideally, the new string -** should be the basename of the source file: "mynewvtab". +** should be the basename of the source file: "mynewvtab". Also +** globally change "TEMPLATEVTAB" to "MYNEWVTAB". ** ** (4) Run a test compilation to make sure the unmodified virtual ** table works. ** -** (5) Begin making changes to make the new virtual table do what you -** want it to do. -** -** (6) Ensure that all the "FIXME" comments in the file have been dealt -** with. +** (5) Begin making incremental changes, testing as you go, to evolve +** the new virtual table to do what you want it to do. ** ** This template is minimal, in the sense that it uses only the required ** methods on the sqlite3_module object. As a result, templatevtab is ** a read-only and eponymous-only table. Those limitation can be removed ** by adding new methods. +** +** This template implements an eponymous-only virtual table with a rowid and +** two columns named "a" and "b". The table as 10 rows with fixed integer +** values. Usage example: +** +** SELECT rowid, a, b FROM templatevtab; */ #if !defined(SQLITEINT_H) #include "sqlite3ext.h" #endif SQLITE_EXTENSION_INIT1 #include +#include /* templatevtab_vtab is a subclass of sqlite3_vtab which is ** underlying representation of the virtual table @@ -92,6 +97,9 @@ static int templatevtabConnect( rc = sqlite3_declare_vtab(db, "CREATE TABLE x(a,b)" ); + /* For convenience, define symbolic names for the index to each column. */ +#define TEMPLATEVTAB_A 0 +#define TEMPLATEVTAB_B 1 if( rc==SQLITE_OK ){ pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; @@ -151,7 +159,15 @@ static int templatevtabColumn( int i /* Which column to return */ ){ templatevtab_cursor *pCur = (templatevtab_cursor*)cur; - sqlite3_result_int(ctx, (i+1)*1000 + pCur->iRowid); + switch( i ){ + case TEMPLATEVTAB_A: + sqlite3_result_int(ctx, 1000 + pCur->iRowid); + break; + default: + assert( i==TEMPLATEVTAB_B ); + sqlite3_result_int(ctx, 2000 + pCur->iRowid); + break; + } return SQLITE_OK; } diff --git a/manifest b/manifest index 83c1301534..cb3e447750 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sprevious\sfix\sfor\sticket\s[d85fffd6ffe856092ed8da]\sin\scheck-in\s\n[0a514e62ad1ebe5c12da8dae]\sdid\snot\scompletely\saddress\sthe\nprobably\sin\sthat\sit\sonly\sworked\sfor\scases\swhere\sthe\sOP_SCopy\sthat\sloaded\nthe\sregister\swas\sthe\slast\sinstruction\sin\sthe\ssequence\sfor\sthe\sexpression,\swhich\nis\snot\snecessarily\sthe\scase\sfor\sexpressions\slike\sCASE...END.\s\sThis\srevision\nprevents\sthe\sregistered\sthat\swill\sbe\srecomputed\sfrom\sbeing\scached\sin\sthe\sfirst\nplace. -D 2018-04-26T18:34:26.853 +C Enhance\sthe\scomments\sin\sthe\stemplatevtab.c\simplementation. +D 2018-04-27T15:17:08.924 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -297,7 +297,7 @@ F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5 F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74 F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11 -F ext/misc/templatevtab.c 52b9363de0ae4a695728a52769a2e2dab8a0a2db77ca753ad9e1a0d0f32d1f89 +F ext/misc/templatevtab.c 8251b31011dd00fc38e739c78c234c930be42b3b274bbe0493b79cd40db02a9e F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/unionvtab.c 0b3173f69b8899da640a13a345dc5ef1400199405f738abe6145b2454195b8ff F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 @@ -1725,7 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0fcfc36ceb820fc70136b799a0405fe92e50646e697be2872bbe9a53a05ed5a9 -R 678fd436c8bb55088cd3e5add9e902ed +P 9fd0faf517993587d2f54212638545fc85fbbc84a031bcfae8c1e5894825d83b +R 408ce2695c1a501e1640fcd4bee57806 U drh -Z f084b8f7ac201c9b316a44eacae3d476 +Z 4384bff1ecbee30802e6ddd37b479122 diff --git a/manifest.uuid b/manifest.uuid index cf4cf4ab2e..839311ed43 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9fd0faf517993587d2f54212638545fc85fbbc84a031bcfae8c1e5894825d83b \ No newline at end of file +05f6278a02e5cde89f76ced5af7d508e26576d7291dad7ee9e06b1a3be516cb0 \ No newline at end of file From 0ef54fa6e875c97429aaefb22781a4e2478dd7c4 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 27 Apr 2018 16:35:44 +0000 Subject: [PATCH 03/60] Fix a test script error causing tests to fail in soak.test. FossilOrigin-Name: 462b52b121c1882e0eca819bc30c0f6e94d7fdd60047d2c32adeff3a1eb70546 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/fuzz_malloc.test | 10 ++++++++-- test/soak.test | 4 ++-- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index cb3e447750..71e96eabe0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\scomments\sin\sthe\stemplatevtab.c\simplementation. -D 2018-04-27T15:17:08.924 +C Fix\sa\stest\sscript\serror\scausing\stests\sto\sfail\sin\ssoak.test. +D 2018-04-27T16:35:44.321 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -938,7 +938,7 @@ F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b -F test/fuzz_malloc.test cf82eab3d93cd3e38b2d53c13c6739ff4cd5b1c31c2c45edd0bcee78e7060c2b +F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79 F test/fuzzcheck.c 5eb86c6ac96833ee622f45bf47e8045999c1b4b10d05e4eb809894a4b39f2f84 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 @@ -1257,7 +1257,7 @@ F test/snapshot.test 85735bd997a4f6d710140c28fd860519a299649f F test/snapshot2.test 925e42427e923262db63c9d7155183f889e3e99feaedec4075f659e51608344f F test/snapshot3.test 9719443594a04778861bd20d12596c5f880af177d6cd62f111da3198cafc6096 F test/snapshot_fault.test 52c5e97ebd218846a8ae2da4d147d3e77d71f963 -F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f +F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0 @@ -1725,7 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9fd0faf517993587d2f54212638545fc85fbbc84a031bcfae8c1e5894825d83b -R 408ce2695c1a501e1640fcd4bee57806 -U drh -Z 4384bff1ecbee30802e6ddd37b479122 +P 05f6278a02e5cde89f76ced5af7d508e26576d7291dad7ee9e06b1a3be516cb0 +R ce6b5d477950780636718aaaaed16610 +U dan +Z 1e8f0b656d8a36cb9e04758d22e86e0c diff --git a/manifest.uuid b/manifest.uuid index 839311ed43..b2a304a8d4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -05f6278a02e5cde89f76ced5af7d508e26576d7291dad7ee9e06b1a3be516cb0 \ No newline at end of file +462b52b121c1882e0eca819bc30c0f6e94d7fdd60047d2c32adeff3a1eb70546 \ No newline at end of file diff --git a/test/fuzz_malloc.test b/test/fuzz_malloc.test index b01b9d7ae4..531da55c1a 100644 --- a/test/fuzz_malloc.test +++ b/test/fuzz_malloc.test @@ -57,10 +57,16 @@ proc do_fuzzy_malloc_test {testname args} { incr jj set ::sql [subst $::fuzzyopts(-template)] # puts fuzyy-sql=\[$::sql\]; flush stdout - foreach {rc res} [catchsql "$::sql"] {} + foreach {rc ::fmtres} [catchsql "$::sql"] {} if {$rc==0} { set nErr1 [set_test_counter errors] - do_malloc_test $testname-$ii -sqlbody $::sql -sqlprep $::prep + do_faultsim_test $testname-$ii -faults oom* -body { + execsql $::sql + } -test { + if {$testrc && $testresult!="datatype mismatch"} { + faultsim_test_result {0 {}} + } + } if {[set_test_counter errors]>$nErr1} { puts "Previous fuzzy-sql=\[$::sql\]" flush stdout diff --git a/test/soak.test b/test/soak.test index c457dec4a9..e8535a1456 100644 --- a/test/soak.test +++ b/test/soak.test @@ -67,12 +67,12 @@ set SOAKTESTS { set G(isquick) 1 -set soak_starttime [clock seconds] +set soak_starttime [clock_seconds] set soak_finishtime [expr {$soak_starttime + $TIMEOUT}] # Loop until the timeout is reached or an error occurs. # -for {set iRun 0} {[clock seconds] < $soak_finishtime} {incr iRun} { +for {set iRun 0} {[clock_seconds] < $soak_finishtime} {incr iRun} { set iIdx [expr {$iRun % [llength $SOAKTESTS]}] source [file join $testdir [lindex $SOAKTESTS $iIdx]] From 03db962ab5f5007435cc926a50e8ba3f11c385e5 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 27 Apr 2018 18:05:01 +0000 Subject: [PATCH 04/60] Update test script fts3expr4.test so that it always creates fts3 tokenizers in the "en_US" locality. FossilOrigin-Name: 576a8f69ae25883f752e58953624e9f7126db998bebaa1f07f7c2ec47aaecabe --- ext/fts3/fts3.c | 2 +- ext/fts3/fts3Int.h | 2 +- ext/fts3/fts3_expr.c | 87 ++++++++++++++++++-------------------------- manifest | 18 ++++----- manifest.uuid | 2 +- test/fts3expr4.test | 3 +- 6 files changed, 50 insertions(+), 64 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index f5145426e0..93776d004f 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -3963,7 +3963,7 @@ int sqlite3Fts3Init(sqlite3 *db){ #ifdef SQLITE_TEST if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ExprInitTestInterface(db); + rc = sqlite3Fts3ExprInitTestInterface(db, pHash); } #endif diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index c3cab9d821..077bad7f54 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -584,7 +584,7 @@ int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, ); void sqlite3Fts3ExprFree(Fts3Expr *); #ifdef SQLITE_TEST -int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); +int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); int sqlite3Fts3InitTerm(sqlite3 *db); #endif diff --git a/ext/fts3/fts3_expr.c b/ext/fts3/fts3_expr.c index 788e5021ec..3e9c2daae3 100644 --- a/ext/fts3/fts3_expr.c +++ b/ext/fts3/fts3_expr.c @@ -1108,34 +1108,6 @@ void sqlite3Fts3ExprFree(Fts3Expr *pDel){ #include -/* -** Function to query the hash-table of tokenizers (see README.tokenizers). -*/ -static int queryTestTokenizer( - sqlite3 *db, - const char *zName, - const sqlite3_tokenizer_module **pp -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?)"; - - *pp = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ - memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); - } - } - - return sqlite3_finalize(pStmt); -} - /* ** Return a pointer to a buffer containing a text representation of the ** expression passed as the first argument. The buffer is obtained from @@ -1203,7 +1175,8 @@ static char *exprToString(Fts3Expr *pExpr, char *zBuf){ ** ** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2'); */ -static void fts3ExprTest( +static void fts3ExprTestCommon( + int bRebalance, sqlite3_context *context, int argc, sqlite3_value **argv @@ -1219,6 +1192,9 @@ static void fts3ExprTest( Fts3Expr *pExpr; char *zBuf = 0; sqlite3 *db = sqlite3_context_db_handle(context); + Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context); + const char *zTokenizer = 0; + char *zErr = 0; if( argc<3 ){ sqlite3_result_error(context, @@ -1227,24 +1203,18 @@ static void fts3ExprTest( return; } - rc = queryTestTokenizer(db, - (const char *)sqlite3_value_text(argv[0]), &pModule); - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - }else if( !pModule ){ - sqlite3_result_error(context, "No such tokenizer module", -1); - goto exprtest_out; + zTokenizer = sqlite3_value_text(argv[0]); + rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_error(context, zErr, -1); + } + sqlite3_free(zErr); + return; } - rc = pModule->xCreate(0, 0, &pTokenizer); - assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - } - pTokenizer->pModule = pModule; - zExpr = (const char *)sqlite3_value_text(argv[1]); nExpr = sqlite3_value_bytes(argv[1]); nCol = argc-2; @@ -1257,7 +1227,7 @@ static void fts3ExprTest( azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); } - if( sqlite3_user_data(context) ){ + if( bRebalance ){ char *zDummy = 0; rc = sqlite3Fts3ExprParse( pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy @@ -1283,23 +1253,38 @@ static void fts3ExprTest( sqlite3Fts3ExprFree(pExpr); exprtest_out: - if( pModule && pTokenizer ){ - rc = pModule->xDestroy(pTokenizer); + if( pTokenizer ){ + rc = pTokenizer->pModule->xDestroy(pTokenizer); } sqlite3_free(azCol); } +static void fts3ExprTest( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + fts3ExprTestCommon(0, context, argc, argv); +} +static void fts3ExprTestRebalance( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + fts3ExprTestCommon(1, context, argc, argv); +} + /* ** Register the query expression parser test function fts3_exprtest() ** with database connection db. */ -int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ +int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){ int rc = sqlite3_create_function( - db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0 + db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0 ); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", - -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0 + -1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0 ); } return rc; diff --git a/manifest b/manifest index 71e96eabe0..df2c9b0e22 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stest\sscript\serror\scausing\stests\sto\sfail\sin\ssoak.test. -D 2018-04-27T16:35:44.321 +C Update\stest\sscript\sfts3expr4.test\sso\sthat\sit\salways\screates\sfts3\stokenizers\sin\nthe\s"en_US"\slocality. +D 2018-04-27T18:05:01.487 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -78,11 +78,11 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c f1c58503bc81c3dab1a70b25e146878ae40fccc716fd7c9b817995b661bc896f +F ext/fts3/fts3.c b577921c7e56ea27893da06691f15721801375ebd411a0e24ec5f6fec3c572c3 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a +F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5 F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 -F ext/fts3/fts3_expr.c dfd571a24412779ac01f25c01d888c6ef7b2d0ef +F ext/fts3/fts3_expr.c 84c827c8adc8d5fffb3cd3632feba543c18e479bc8ae115d555fc641a7436c9d F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60 F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652 @@ -887,7 +887,7 @@ F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851 F test/fts3expr.test 9466627007804d855bf9df2a0cfb3dac23686fdc F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8 -F test/fts3expr4.test c39a15d676b14fc439d9bf845aa7bddcf4a74dc3 +F test/fts3expr4.test cac5dd815fe6b5921741abdccdde3b7f50b86394de91e13308ee7986859c4a9f F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49 F test/fts3fault.test 9fb7d6266a38806de841f7244bac1b0fe3a1477184bbb10b172d19d2ca6ad692 F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0 @@ -1725,7 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 05f6278a02e5cde89f76ced5af7d508e26576d7291dad7ee9e06b1a3be516cb0 -R ce6b5d477950780636718aaaaed16610 +P 462b52b121c1882e0eca819bc30c0f6e94d7fdd60047d2c32adeff3a1eb70546 +R 330eca5f95eacfc2db564f6137a9dfe2 U dan -Z 1e8f0b656d8a36cb9e04758d22e86e0c +Z a32eb6502eb10fd4922091ca79205291 diff --git a/manifest.uuid b/manifest.uuid index b2a304a8d4..4ebdf5064e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -462b52b121c1882e0eca819bc30c0f6e94d7fdd60047d2c32adeff3a1eb70546 \ No newline at end of file +576a8f69ae25883f752e58953624e9f7126db998bebaa1f07f7c2ec47aaecabe \ No newline at end of file diff --git a/test/fts3expr4.test b/test/fts3expr4.test index 9fc22c1172..1bf039e55f 100644 --- a/test/fts3expr4.test +++ b/test/fts3expr4.test @@ -29,7 +29,8 @@ proc test_fts3expr {tokenizer expr} { } proc do_icu_expr_test {tn expr res} { - uplevel [list do_test $tn [list test_fts3expr icu $expr] [list {*}$res]] + set res2 [list {*}$res] + uplevel [list do_test $tn [list test_fts3expr "icu en_US" $expr] $res2] } proc do_simple_expr_test {tn expr res} { From 95d5ae19d1d3515429e1811e615657099aefb001 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 27 Apr 2018 22:42:37 +0000 Subject: [PATCH 05/60] Document and expose sqlite3_win32_set_directory() function for use on Win32. FossilOrigin-Name: cbce7180ee664367ee8fc1f8af703eb7845bb58ade6870cc3b7608dcbe5952b3 --- manifest | 19 +++++++++++-------- manifest.uuid | 2 +- src/os_win.c | 26 +++++++------------------- src/sqlite.h.in | 27 +++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index df2c9b0e22..8223929867 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\stest\sscript\sfts3expr4.test\sso\sthat\sit\salways\screates\sfts3\stokenizers\sin\nthe\s"en_US"\slocality. -D 2018-04-27T18:05:01.487 +C Document\sand\sexpose\ssqlite3_win32_set_directory()\sfunction\sfor\suse\son\sWin32. +D 2018-04-27T22:42:37.415 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -477,7 +477,7 @@ F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 2b53b0b8ddc580db096252c721729e5f5f2f355b4fc056f8f3fb328aeb3c9e8a -F src/os_win.c eb03c6d52f893bcd7fdd4c6006674c13c1b5e49543fec98d605201af2997171c +F src/os_win.c a8f39484f3b9162250f510bcceb2826638c00847c9c271b770289f672ebe5372 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 @@ -494,7 +494,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c daf07d8defce3311f9e69f1280a874d78bc1d16c305f6aa689640f7afa02842f F src/shell.c.in d63f06c870ec1761ea98bd1cae651ff0ea6beadf8be892105dabd913f94cb3da -F src/sqlite.h.in 8e70752a57597c08f64f3d49fc1fc46926b862d2e23b038b0d23b9cc748d88ea +F src/sqlite.h.in cce7da74536701fa72a65f3127f9fd698ed107d22b2d542e8d1c47ba7b15cf83 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d F src/sqliteInt.h c1deb023eb117b4437a69d8c5a753deb36581f1933015cd262ad32b45c4d8431 @@ -1725,7 +1725,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 462b52b121c1882e0eca819bc30c0f6e94d7fdd60047d2c32adeff3a1eb70546 -R 330eca5f95eacfc2db564f6137a9dfe2 -U dan -Z a32eb6502eb10fd4922091ca79205291 +P 576a8f69ae25883f752e58953624e9f7126db998bebaa1f07f7c2ec47aaecabe +R aa1ef23de768d8b20858596899c9b5a8 +T *branch * win32dir +T *sym-win32dir * +T -sym-trunk * +U mistachkin +Z fc8c1c84b4f3c1bc834f88386ed5cafe diff --git a/manifest.uuid b/manifest.uuid index 4ebdf5064e..a21f2d822b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -576a8f69ae25883f752e58953624e9f7126db998bebaa1f07f7c2ec47aaecabe \ No newline at end of file +cbce7180ee664367ee8fc1f8af703eb7845bb58ade6870cc3b7608dcbe5952b3 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 534426977f..df97f928ea 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -315,22 +315,6 @@ struct winVfsAppData { # define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD))) #endif -/* - * The value used with sqlite3_win32_set_directory() to specify that - * the data directory should be changed. - */ -#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE -# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1) -#endif - -/* - * The value used with sqlite3_win32_set_directory() to specify that - * the temporary directory should be changed. - */ -#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE -# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2) -#endif - /* * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the * various Win32 API heap functions instead of our own. @@ -1933,7 +1917,10 @@ char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ ** argument is the name of the directory to use. The return value will be ** SQLITE_OK if successful. */ -int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ +int sqlite3_win32_set_directory( + unsigned long type, /* Identifier for directory being set or reset */ + void *zValue /* New value for directory being set or reset */ +){ char **ppDirectory = 0; #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -1949,9 +1936,10 @@ int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ ); assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); if( ppDirectory ){ + LPCWSTR zStrValue = zValue; char *zValueUtf8 = 0; - if( zValue && zValue[0] ){ - zValueUtf8 = winUnicodeToUtf8(zValue); + if( zStrValue && zStrValue[0] ){ + zValueUtf8 = winUnicodeToUtf8(zStrValue); if ( zValueUtf8==0 ){ return SQLITE_NOMEM_BKPT; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 4d84bf3eb6..643528a870 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5509,6 +5509,33 @@ SQLITE_EXTERN char *sqlite3_temp_directory; */ SQLITE_EXTERN char *sqlite3_data_directory; +/* +** CAPI3REF: Win32 Specific Interface +** +** These interfaces are available only on Windows. The +** [sqlite3_win32_set_directory] interface is used to set the value associated +** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to +** zValue, depending on the value of the type parameter. The zValue parameter +** should be NULL to cause the previous value to be freed via [sqlite3_free]; +** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] +** prior to being used. The [sqlite3_win32_set_directory] interface returns +** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, +** or [SQLITE_NOMEM] if memory could not be allocated. +*/ +int sqlite3_win32_set_directory( + unsigned long type, /* Identifier for directory being set or reset */ + void *zValue /* New value for directory being set or reset */ +); + +/* +** CAPI3REF: Win32 Directory Types +** +** These macros are only available on Windows. They define the allowed values +** for the type argument to the [sqlite3_win32_set_directory] interface. +*/ +#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 +#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 + /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} From 0314cf3aa5e9174123d6d8da4e1bbc4bf9b3d78b Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 28 Apr 2018 01:27:09 +0000 Subject: [PATCH 06/60] Add the "PRAGMA reset_database=ON|OFF" command. When on, it causes the database to appear to be empty, causing the next transaction to reset it to an empty database. FossilOrigin-Name: 02e1a13c1f04bb72599b98f51240c78d0d050de264fef5808fd97db3f4c16dac --- manifest | 25 ++++++++++++++----------- manifest.uuid | 2 +- src/btree.c | 7 +++++++ src/pragma.h | 7 ++++++- src/prepare.c | 3 +++ src/sqliteInt.h | 1 + tool/mkpragmatab.tcl | 5 +++++ 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index df2c9b0e22..6a573c3c65 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\stest\sscript\sfts3expr4.test\sso\sthat\sit\salways\screates\sfts3\stokenizers\sin\nthe\s"en_US"\slocality. -D 2018-04-27T18:05:01.487 +C Add\sthe\s"PRAGMA\sreset_database=ON|OFF"\scommand.\s\sWhen\son,\sit\scauses\sthe\ndatabase\sto\sappear\sto\sbe\sempty,\scausing\sthe\snext\stransaction\sto\sreset\sit\sto\nan\sempty\sdatabase. +D 2018-04-28T01:27:09.774 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -433,7 +433,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 9eb9531c65346bbfccf5325384b7db1849daf4db6601dcfe21ba5c5b20623b64 +F src/btree.c fa7da0a5584e5182b92536bc4b7622a154a468997a075d5901345efb79a05ffe F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c c4227d058d52c24ffce2d33cd3a11234d8e8603901243cdb5165eddf64ee2177 @@ -486,8 +486,8 @@ F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69 -F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 -F src/prepare.c d16cb8a553c09bc0c46c33f8e0add77c8f755cfb4681ca5101aaff3a04df9625 +F src/pragma.h f1e9f51dcd93188cd0b2eb8a616eaf3e79e17c3279f68aec8d0bd49546dcb909 +F src/prepare.c 1492a2bed7bc5770c5850404f09bf887a67d4580985b8cee37bdab2ea809f479 F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 @@ -497,7 +497,7 @@ F src/shell.c.in d63f06c870ec1761ea98bd1cae651ff0ea6beadf8be892105dabd913f94cb3d F src/sqlite.h.in 8e70752a57597c08f64f3d49fc1fc46926b862d2e23b038b0d23b9cc748d88ea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d -F src/sqliteInt.h c1deb023eb117b4437a69d8c5a753deb36581f1933015cd262ad32b45c4d8431 +F src/sqliteInt.h 8ac0138eae10337b745b03dad0124fd63ae911c0503e795729503e7fc6234d57 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1658,7 +1658,7 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6 F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa -F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd +F tool/mkpragmatab.tcl c2efde2e98beee55f04679cac652a1a6291b6e47e3b0c5b86f53b84c174d9b5e F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 @@ -1725,7 +1725,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 462b52b121c1882e0eca819bc30c0f6e94d7fdd60047d2c32adeff3a1eb70546 -R 330eca5f95eacfc2db564f6137a9dfe2 -U dan -Z a32eb6502eb10fd4922091ca79205291 +P 576a8f69ae25883f752e58953624e9f7126db998bebaa1f07f7c2ec47aaecabe +R 20267b33ec4093cbd8eada610413a5f9 +T *branch * reset-database +T *sym-reset-database * +T -sym-trunk * +U drh +Z 6b0d829800a54a9640942b2a1f1f52ea diff --git a/manifest.uuid b/manifest.uuid index 4ebdf5064e..429266b2c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -576a8f69ae25883f752e58953624e9f7126db998bebaa1f07f7c2ec47aaecabe \ No newline at end of file +02e1a13c1f04bb72599b98f51240c78d0d050de264fef5808fd97db3f4c16dac \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 402503916d..700138efca 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2972,6 +2972,10 @@ static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){ # define setDefaultSyncFlag(pBt,safety_level) #endif +/* Forward declaration */ +static int newDatabase(BtShared*); + + /* ** Get a reference to pPage1 of the database file. This will ** also acquire a readlock on that file. @@ -3003,6 +3007,9 @@ static int lockBtree(BtShared *pBt){ if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ nPage = nPageFile; } + if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){ + nPage = 0; + } if( nPage>0 ){ u32 pageSize; u32 usableSize; diff --git a/src/pragma.h b/src/pragma.h index c9ece2dc87..a1695ff98b 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -506,6 +506,11 @@ static const PragmaName aPragmaName[] = { /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + {/* zName: */ "reset_database", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, + /* ColNames: */ 0, 0, + /* iArg: */ SQLITE_WriteSchema|SQLITE_ResetDatabase }, {/* zName: */ "reverse_unordered_selects", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, @@ -646,4 +651,4 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_WriteSchema }, #endif }; -/* Number of pragmas: 60 on by default, 77 total. */ +/* Number of pragmas: 61 on by default, 78 total. */ diff --git a/src/prepare.c b/src/prepare.c index c13f88d28b..971b8024e8 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -216,6 +216,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ for(i=0; ipBt, i+1, (u32 *)&meta[i]); } + if( (db->flags & SQLITE_ResetDatabase)!=0 ){ + memset(meta, 0, sizeof(meta)); + } pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; /* If opening a non-empty database, check the text encoding. For the diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8ad15109a8..c700c261b8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1506,6 +1506,7 @@ struct sqlite3 { #define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */ #define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/ #define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */ +#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ /* Flags used only if debugging */ #ifdef SQLITE_DEBUG diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index 1bfbeb7c58..690edaff23 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -123,6 +123,11 @@ set pragma_def { ARG: SQLITE_WriteSchema IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) + NAME: reset_database + TYPE: FLAG + ARG: SQLITE_WriteSchema|SQLITE_ResetDatabase + IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) + NAME: read_uncommitted TYPE: FLAG ARG: SQLITE_ReadUncommit From c1e1ffeafb8d2617741c123bfb3f5ea4f1f2d8f4 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 28 Apr 2018 01:44:27 +0000 Subject: [PATCH 07/60] Add comments about the intended use of the sqlite3_data_directory variable as it pertains to the sqlite3_win32_set_directory function. FossilOrigin-Name: d11c419756ce28fcc1f58df6bbe59a3d8d19d0441970aa7bfa216ba915ceddf5 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/sqlite.h.in | 5 ++++- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 8223929867..974c276e5a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Document\sand\sexpose\ssqlite3_win32_set_directory()\sfunction\sfor\suse\son\sWin32. -D 2018-04-27T22:42:37.415 +C Add\scomments\sabout\sthe\sintended\suse\sof\sthe\ssqlite3_data_directory\svariable\sas\sit\spertains\sto\sthe\ssqlite3_win32_set_directory\sfunction. +D 2018-04-28T01:44:27.125 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -494,7 +494,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c daf07d8defce3311f9e69f1280a874d78bc1d16c305f6aa689640f7afa02842f F src/shell.c.in d63f06c870ec1761ea98bd1cae651ff0ea6beadf8be892105dabd913f94cb3da -F src/sqlite.h.in cce7da74536701fa72a65f3127f9fd698ed107d22b2d542e8d1c47ba7b15cf83 +F src/sqlite.h.in c3b1782d1a290253b37ebc999c42e894ff8aa9f76526b2938df2f8939d20de39 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d F src/sqliteInt.h c1deb023eb117b4437a69d8c5a753deb36581f1933015cd262ad32b45c4d8431 @@ -1725,10 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 576a8f69ae25883f752e58953624e9f7126db998bebaa1f07f7c2ec47aaecabe -R aa1ef23de768d8b20858596899c9b5a8 -T *branch * win32dir -T *sym-win32dir * -T -sym-trunk * +P cbce7180ee664367ee8fc1f8af703eb7845bb58ade6870cc3b7608dcbe5952b3 +R 789673b5ae135eb7ca65c7e275b34852 U mistachkin -Z fc8c1c84b4f3c1bc834f88386ed5cafe +Z 1983bc8c557ea2b496209ea5d099867c diff --git a/manifest.uuid b/manifest.uuid index a21f2d822b..45b7a8a9c4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cbce7180ee664367ee8fc1f8af703eb7845bb58ade6870cc3b7608dcbe5952b3 \ No newline at end of file +d11c419756ce28fcc1f58df6bbe59a3d8d19d0441970aa7bfa216ba915ceddf5 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 643528a870..877528c686 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5520,7 +5520,10 @@ SQLITE_EXTERN char *sqlite3_data_directory; ** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] ** prior to being used. The [sqlite3_win32_set_directory] interface returns ** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, -** or [SQLITE_NOMEM] if memory could not be allocated. +** or [SQLITE_NOMEM] if memory could not be allocated. The value of the +** [sqlite3_data_directory] variable is intended to act as a replacement for +** the current directory on the sub-platforms of Win32 where that concept is +** not present, e.g. WinRT and UWP. */ int sqlite3_win32_set_directory( unsigned long type, /* Identifier for directory being set or reset */ From 6bfd973ce67980e5d09c8adfc465767297193573 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 28 Apr 2018 04:10:55 +0000 Subject: [PATCH 08/60] Fix compiler warnings in FTS3. FossilOrigin-Name: de508e831a43f02c3b354a24ea34798da03c163bae5521c852c9ddd252723739 --- ext/fts3/fts3_expr.c | 4 +--- manifest | 17 ++++++++--------- manifest.uuid | 2 +- test/fts3expr.test | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/ext/fts3/fts3_expr.c b/ext/fts3/fts3_expr.c index 3e9c2daae3..9f42b44a71 100644 --- a/ext/fts3/fts3_expr.c +++ b/ext/fts3/fts3_expr.c @@ -1181,7 +1181,6 @@ static void fts3ExprTestCommon( int argc, sqlite3_value **argv ){ - sqlite3_tokenizer_module const *pModule = 0; sqlite3_tokenizer *pTokenizer = 0; int rc; char **azCol = 0; @@ -1191,7 +1190,6 @@ static void fts3ExprTestCommon( int ii; Fts3Expr *pExpr; char *zBuf = 0; - sqlite3 *db = sqlite3_context_db_handle(context); Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context); const char *zTokenizer = 0; char *zErr = 0; @@ -1203,7 +1201,7 @@ static void fts3ExprTestCommon( return; } - zTokenizer = sqlite3_value_text(argv[0]); + zTokenizer = (const char*)sqlite3_value_text(argv[0]); rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ){ diff --git a/manifest b/manifest index 5dd3d7ec9b..c11ff8e955 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Document\sand\sexpose\ssqlite3_win32_set_directory()\sfunction\sfor\suse\son\sWin32. -D 2018-04-28T01:46:22.766 +C Fix\scompiler\swarnings\sin\sFTS3. +D 2018-04-28T04:10:55.343 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -82,7 +82,7 @@ F ext/fts3/fts3.c b577921c7e56ea27893da06691f15721801375ebd411a0e24ec5f6fec3c572 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5 F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 -F ext/fts3/fts3_expr.c 84c827c8adc8d5fffb3cd3632feba543c18e479bc8ae115d555fc641a7436c9d +F ext/fts3/fts3_expr.c 3b1dbceddd8622599f3cc2626897667fe40487aaa1676707d6c37ec5a8422fc1 F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60 F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652 @@ -884,7 +884,7 @@ F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468 F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297 F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851 -F test/fts3expr.test 9466627007804d855bf9df2a0cfb3dac23686fdc +F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c77e526 F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8 F test/fts3expr4.test cac5dd815fe6b5921741abdccdde3b7f50b86394de91e13308ee7986859c4a9f @@ -1725,8 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 576a8f69ae25883f752e58953624e9f7126db998bebaa1f07f7c2ec47aaecabe d11c419756ce28fcc1f58df6bbe59a3d8d19d0441970aa7bfa216ba915ceddf5 -R 789673b5ae135eb7ca65c7e275b34852 -T +closed d11c419756ce28fcc1f58df6bbe59a3d8d19d0441970aa7bfa216ba915ceddf5 -U mistachkin -Z 9dd13bb2cb42def20613b95feb0b21f4 +P 7626b593405ca720e371b9f698b72b499b7c829bfe00f758140bc542cf970689 +R bc4e19febfa29f170cd1236e27a6cd06 +U drh +Z f3d84a2a64c7f56d5340275e017905e0 diff --git a/manifest.uuid b/manifest.uuid index ed421b7d0a..d3c11fcd81 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7626b593405ca720e371b9f698b72b499b7c829bfe00f758140bc542cf970689 \ No newline at end of file +de508e831a43f02c3b354a24ea34798da03c163bae5521c852c9ddd252723739 \ No newline at end of file diff --git a/test/fts3expr.test b/test/fts3expr.test index b186a157d1..2fd19201b6 100644 --- a/test/fts3expr.test +++ b/test/fts3expr.test @@ -409,7 +409,7 @@ do_test fts3expr-5.1 { } {1 {Usage: fts3_exprtest(tokenizer, expr, col1, ...}} do_test fts3expr-5.2 { catchsql { SELECT fts3_exprtest('doesnotexist', 'a b', 'c') } -} {1 {No such tokenizer module}} +} {1 {unknown tokenizer: doesnotexist}} do_test fts3expr-5.3 { catchsql { SELECT fts3_exprtest('simple', 'a b OR', 'c') } } {1 {Error parsing expression}} From 1efa8023a1741fb79152f360e5c10392ccff8f6b Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 28 Apr 2018 04:16:43 +0000 Subject: [PATCH 09/60] Prevent deep recursions on nested COLLATE operators. FossilOrigin-Name: 6e098ee415f1a530e17a942c9ba51d67c25a3ebff6b97377b7858d0b10bcec92 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/expr.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index c11ff8e955..2c7add29f1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scompiler\swarnings\sin\sFTS3. -D 2018-04-28T04:10:55.343 +C Prevent\sdeep\srecursions\son\snested\sCOLLATE\soperators. +D 2018-04-28T04:16:43.197 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -444,7 +444,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c b0f90749e22d5e41a12dbf940f4811138cf97da54b46b737089b93eb64a2896f -F src/expr.c 4a39bc2a9a3d825571519a1910ecfe3d4b6d596e775c9ed7cef7497ea06140ac +F src/expr.c 5c9a6dc7f56d245d7bb82ba36fdba2ca3bdd1881b61ee60293dd98c766742cd9 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c 94f42cba2cc1c34aeaa441022ba0170ec3fec4bba54db4e0ded085c6dc0fdc51 @@ -1725,7 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7626b593405ca720e371b9f698b72b499b7c829bfe00f758140bc542cf970689 -R bc4e19febfa29f170cd1236e27a6cd06 +P de508e831a43f02c3b354a24ea34798da03c163bae5521c852c9ddd252723739 +R 8fd56e6836e3af3199f94071c5426607 U drh -Z f3d84a2a64c7f56d5340275e017905e0 +Z 830b9867ea719a4d0d43e83e413c3907 diff --git a/manifest.uuid b/manifest.uuid index d3c11fcd81..e414a12482 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -de508e831a43f02c3b354a24ea34798da03c163bae5521c852c9ddd252723739 \ No newline at end of file +6e098ee415f1a530e17a942c9ba51d67c25a3ebff6b97377b7858d0b10bcec92 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 03fad6cc52..2d4a14c8d0 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3551,6 +3551,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ return 0; } +expr_code_doover: if( pExpr==0 ){ op = TK_NULL; }else{ @@ -4011,7 +4012,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_SPAN: case TK_COLLATE: case TK_UPLUS: { - return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + pExpr = pExpr->pLeft; + goto expr_code_doover; } case TK_TRIGGER: { From 7df011969cd56cee9336770b6ad9c4828e33a3b6 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 28 Apr 2018 12:43:16 +0000 Subject: [PATCH 10/60] Add the SQLITE_DBCONFIG_RESET_DATABASE control as a replacement for the reset_database pragma. Resetting the database should be hard enough to do that it cannot be done by accident. FossilOrigin-Name: ff836cb8b0377c5970ecb2b797702e2b5d208eda443ecbd55f4c238a3094b28a --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/main.c | 1 + src/pragma.h | 7 +------ src/shell.c.in | 31 ++++++++++++++++++++++++++++++- src/sqlite.h.in | 18 +++++++++++++++++- src/test1.c | 2 ++ tool/mkpragmatab.tcl | 5 ----- 8 files changed, 63 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index ac68d1340d..c1c89e3df3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\supdates\sfrom\strunk. -D 2018-04-28T11:22:53.232 +C Add\sthe\sSQLITE_DBCONFIG_RESET_DATABASE\scontrol\sas\sa\sreplacement\sfor\nthe\sreset_database\spragma.\s\sResetting\sthe\sdatabase\sshould\sbe\shard\senough\nto\sdo\sthat\sit\scannot\sbe\sdone\sby\saccident. +D 2018-04-28T12:43:16.798 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -456,7 +456,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 33a2c72b6182e8ddf697d604cc087c77ff5fc512a32b8b624641d41b390e249e F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302 -F src/main.c f579a7a1e6a602cf752ee910ef541481124bac9dfa7db720e698efdf5521bfd3 +F src/main.c b56b2d62d5d11e3f5100b25fca34c13c62a0fe73941f6873454a7fa8a454170d F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -486,15 +486,15 @@ F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69 -F src/pragma.h f1e9f51dcd93188cd0b2eb8a616eaf3e79e17c3279f68aec8d0bd49546dcb909 +F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/prepare.c 1492a2bed7bc5770c5850404f09bf887a67d4580985b8cee37bdab2ea809f479 F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c daf07d8defce3311f9e69f1280a874d78bc1d16c305f6aa689640f7afa02842f -F src/shell.c.in d63f06c870ec1761ea98bd1cae651ff0ea6beadf8be892105dabd913f94cb3da -F src/sqlite.h.in c3b1782d1a290253b37ebc999c42e894ff8aa9f76526b2938df2f8939d20de39 +F src/shell.c.in 54b902ab7d840f60ddfabc13124c85d4980342c88aff7679f2cc25f67c21ade7 +F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d F src/sqliteInt.h 8ac0138eae10337b745b03dad0124fd63ae911c0503e795729503e7fc6234d57 @@ -502,7 +502,7 @@ F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce -F src/test1.c b2df6d7ed8ecb53680f7040163ba92b50c471ed8104d128c88c8e969a107887f +F src/test1.c 51aa5f3030217ca45eb62e90944838794d4faaae7a8f60e0330ae01f30bc997b F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6 @@ -1658,7 +1658,7 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6 F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa -F tool/mkpragmatab.tcl c2efde2e98beee55f04679cac652a1a6291b6e47e3b0c5b86f53b84c174d9b5e +F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 @@ -1725,7 +1725,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 02e1a13c1f04bb72599b98f51240c78d0d050de264fef5808fd97db3f4c16dac 6e098ee415f1a530e17a942c9ba51d67c25a3ebff6b97377b7858d0b10bcec92 -R 64a2fea94a3cb75b3548d8498e78db38 +P 94877e495c563f101b51cd8891ca7665c7aab87ff526157f1dc1781e0a2a5d87 +R edbc587ec4dfbdf46b4ab916ffe47e60 U drh -Z 4ef7f8352ba19719f819fb6bff3896fa +Z a8923b606a37e52c49b354dd2843de00 diff --git a/manifest.uuid b/manifest.uuid index a1012dd290..40baa607c4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -94877e495c563f101b51cd8891ca7665c7aab87ff526157f1dc1781e0a2a5d87 \ No newline at end of file +ff836cb8b0377c5970ecb2b797702e2b5d208eda443ecbd55f4c238a3094b28a \ No newline at end of file diff --git a/src/main.c b/src/main.c index 442067a14e..d23f9afcfa 100644 --- a/src/main.c +++ b/src/main.c @@ -834,6 +834,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, + { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ diff --git a/src/pragma.h b/src/pragma.h index a1695ff98b..c9ece2dc87 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -506,11 +506,6 @@ static const PragmaName aPragmaName[] = { /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "reset_database", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_WriteSchema|SQLITE_ResetDatabase }, {/* zName: */ "reverse_unordered_selects", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, @@ -651,4 +646,4 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_WriteSchema }, #endif }; -/* Number of pragmas: 61 on by default, 78 total. */ +/* Number of pragmas: 60 on by default, 77 total. */ diff --git a/src/shell.c.in b/src/shell.c.in index c0e5c7a75c..e759921ab6 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3340,6 +3340,7 @@ static char zHelp[] = ".check GLOB Fail if output since .testcase does not match\n" ".clone NEWDB Clone data into NEWDB from the existing database\n" ".databases List names and files of attached databases\n" + ".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n" ".dbinfo ?DB? Show status information about the database\n" ".dump ?TABLE? ... Dump the database in an SQL text format\n" " If TABLE specified, only dump tables matching\n" @@ -5782,7 +5783,35 @@ static int do_meta_command(char *zLine, ShellState *p){ } }else - if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ + if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ + static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = { + { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, + { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, + { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, + { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, + { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, + { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, + { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, + { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, + }; + int ii, v; + open_db(p, 0); + for(ii=0; ii1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; + if( nArg>=3 ){ + sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); + } + sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); + utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); + if( nArg>1 ) break; + } + if( nArg>1 && ii==ArraySize(aDbConfig) ){ + utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); + utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); + } + }else + + if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){ rc = shell_dbinfo_command(p, nArg, azArg); }else diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 877528c686..696b3cb2db 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2112,6 +2112,21 @@ struct sqlite3_mem_methods { ** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if ** it is not disabled, 1 if it is. ** +** +**
SQLITE_DBCONFIG_RESET_DATABASE
+**
Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run +** [VACUUM] in order to reset a database back to an empty database +** with no schema and no content. The following process works even for +** a badly corrupted database file: +**
    +**
  1. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); +**
  2. [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); +**
  3. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); +**
+** Because resetting a database is destructive and irreversible, the +** process requires the use of this obscure API and multiple steps to help +** ensure that it does not happen by accident. +**
** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -2123,7 +2138,8 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1008 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes diff --git a/src/test1.c b/src/test1.c index 0f139ceba5..f2511d259a 100644 --- a/src/test1.c +++ b/src/test1.c @@ -7418,6 +7418,8 @@ static int SQLITE_TCLAPI test_sqlite3_db_config( { "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, { "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG }, + { "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP }, + { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, }; int i; int v; diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index 690edaff23..1bfbeb7c58 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -123,11 +123,6 @@ set pragma_def { ARG: SQLITE_WriteSchema IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) - NAME: reset_database - TYPE: FLAG - ARG: SQLITE_WriteSchema|SQLITE_ResetDatabase - IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) - NAME: read_uncommitted TYPE: FLAG ARG: SQLITE_ReadUncommit From 2b137d65f5a087382a6875109dc890b1b2ae3fdc Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 28 Apr 2018 18:20:01 +0000 Subject: [PATCH 11/60] Fix an RBU problem causing spurious SQLITE_CONSTRAINT errors when restarting an RBU update in which more than one source table writes to a single target database table. FossilOrigin-Name: 564ae8297d417ba4b7978e430d41f125007177673163f6ed9adc3a3974f73d24 --- ext/rbu/rbu1.test | 1 + ext/rbu/rbu_common.tcl | 16 +++++++ ext/rbu/rbusplit.test | 95 ++++++++++++++++++++++++++++++++++++++++++ ext/rbu/sqlite3rbu.c | 20 +++++++-- manifest | 19 +++++---- manifest.uuid | 2 +- 6 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 ext/rbu/rbusplit.test diff --git a/ext/rbu/rbu1.test b/ext/rbu/rbu1.test index cd41728886..1d16c1cd0a 100644 --- a/ext/rbu/rbu1.test +++ b/ext/rbu/rbu1.test @@ -139,6 +139,7 @@ foreach {tn3 create_vfs destroy_vfs} { foreach {tn2 cmd} { 1 run_rbu 2 step_rbu 3 step_rbu_uri 4 step_rbu_state + 5 step_rbu_legacy } { foreach {tn schema} { 1 { diff --git a/ext/rbu/rbu_common.tcl b/ext/rbu/rbu_common.tcl index b216fe0858..2b263b7660 100644 --- a/ext/rbu/rbu_common.tcl +++ b/ext/rbu/rbu_common.tcl @@ -70,6 +70,22 @@ proc step_rbu {target rbu} { set rc } +proc step_rbu_legacy {target rbu} { + while 1 { + sqlite3rbu rbu $target $rbu + set state [rbu state] + check_prestep_state $target $state + set rc [rbu step] + check_poststep_state $rc $target $state + rbu close + if {$rc != "SQLITE_OK"} break + sqlite3 tmpdb $rbu + tmpdb eval { DELETE FROM rbu_state WHERE k==10 } + tmpdb close + } + set rc +} + proc do_rbu_vacuum_test {tn step} { forcedelete state.db uplevel [list do_test $tn.1 { diff --git a/ext/rbu/rbusplit.test b/ext/rbu/rbusplit.test new file mode 100644 index 0000000000..678f388dcf --- /dev/null +++ b/ext/rbu/rbusplit.test @@ -0,0 +1,95 @@ +# 2018 April 28 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# + +source [file join [file dirname [info script]] rbu_common.tcl] +set ::testprefix rbusplit + +db close +sqlite3_shutdown +sqlite3_config_uri 1 + +autoinstall_test_functions + +proc build_db {db} { + $db eval { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE TABLE t2(a PRIMARY KEY, b, c); + + CREATE INDEX t1c ON t1(c); + } +} + +proc build_rbu {filename} { + forcedelete $filename + sqlite3 dbRbu $filename + dbRbu eval { + CREATE TABLE data0_t1(a, b, c, rbu_control); + CREATE TABLE data1_t1(a, b, c, rbu_control); + CREATE TABLE data2_t1(a, b, c, rbu_control); + CREATE TABLE data3_t1(a, b, c, rbu_control); + + CREATE TABLE data_t2(a, b, c, rbu_control); + + INSERT INTO data0_t1 VALUES(1, 1, 1, 0); + INSERT INTO data0_t1 VALUES(2, 2, 2, 0); + INSERT INTO data0_t1 VALUES(3, 3, 3, 0); + INSERT INTO data0_t1 VALUES(4, 4, 4, 0); + INSERT INTO data1_t1 VALUES(5, 5, 5, 0); + INSERT INTO data1_t1 VALUES(6, 6, 6, 0); + INSERT INTO data1_t1 VALUES(7, 7, 7, 0); + INSERT INTO data1_t1 VALUES(8, 8, 8, 0); + INSERT INTO data3_t1 VALUES(9, 9, 9, 0); + + INSERT INTO data_t2 VALUES(1, 1, 1, 0); + INSERT INTO data_t2 VALUES(2, 2, 2, 0); + INSERT INTO data_t2 VALUES(3, 3, 3, 0); + INSERT INTO data_t2 VALUES(4, 4, 4, 0); + INSERT INTO data_t2 VALUES(5, 5, 5, 0); + INSERT INTO data_t2 VALUES(6, 6, 6, 0); + INSERT INTO data_t2 VALUES(7, 7, 7, 0); + INSERT INTO data_t2 VALUES(8, 8, 8, 0); + INSERT INTO data_t2 VALUES(9, 9, 9, 0); + } + + dbRbu close +} + +foreach {tn cmd} { + 1 run_rbu + 2 step_rbu +} { + reset_db + build_db db + build_rbu testrbu.db + + do_test 1.$tn.1 { + $cmd test.db testrbu.db + } {SQLITE_DONE} + do_execsql_test 1.$tn.1 { + SELECT * FROM t1; + } { + 1 1 1 2 2 2 3 3 3 4 4 4 + 5 5 5 6 6 6 7 7 7 8 8 8 + 9 9 9 + } + do_execsql_test 1.$tn.2 { + SELECT * FROM t2; + } { + 1 1 1 2 2 2 3 3 3 4 4 4 + 5 5 5 6 6 6 7 7 7 8 8 8 + 9 9 9 + } +} + +finish_test + diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index a3d54f91e5..065b13c7fa 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -153,6 +153,10 @@ ** ** RBU_STATE_OALSZ: ** Valid if STAGE==1. The size in bytes of the *-oal file. +** +** RBU_STATE_DATATBL: +** Only valid if STAGE==1. The RBU database name of the table +** currently being read. */ #define RBU_STATE_STAGE 1 #define RBU_STATE_TBL 2 @@ -163,6 +167,7 @@ #define RBU_STATE_COOKIE 7 #define RBU_STATE_OALSZ 8 #define RBU_STATE_PHASEONESTEP 9 +#define RBU_STATE_DATATBL 10 #define RBU_STAGE_OAL 1 #define RBU_STAGE_MOVE 2 @@ -205,6 +210,7 @@ typedef sqlite3_int64 i64; struct RbuState { int eStage; char *zTbl; + char *zDataTbl; char *zIdx; i64 iWalCksum; int nRow; @@ -2268,6 +2274,7 @@ static sqlite3 *rbuOpenDbhandle( static void rbuFreeState(RbuState *p){ if( p ){ sqlite3_free(p->zTbl); + sqlite3_free(p->zDataTbl); sqlite3_free(p->zIdx); sqlite3_free(p); } @@ -2338,6 +2345,10 @@ static RbuState *rbuLoadState(sqlite3rbu *p){ pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); break; + case RBU_STATE_DATATBL: + pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); + break; + default: rc = SQLITE_CORRUPT; break; @@ -3112,7 +3123,8 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){ "(%d, %lld), " "(%d, %lld), " "(%d, %lld), " - "(%d, %lld) ", + "(%d, %lld), " + "(%d, %Q) ", p->zStateDb, RBU_STATE_STAGE, eStage, RBU_STATE_TBL, p->objiter.zTbl, @@ -3122,7 +3134,8 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){ RBU_STATE_CKPT, p->iWalCksum, RBU_STATE_COOKIE, (i64)pFd->iCookie, RBU_STATE_OALSZ, p->iOalSz, - RBU_STATE_PHASEONESTEP, p->nPhaseOneStep + RBU_STATE_PHASEONESTEP, p->nPhaseOneStep, + RBU_STATE_DATATBL, p->objiter.zDataTbl ) ); assert( pInsert==0 || rc==SQLITE_OK ); @@ -3378,7 +3391,8 @@ static void rbuSetupOal(sqlite3rbu *p, RbuState *pState){ while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup || rbuStrCompare(pIter->zIdx, pState->zIdx) - || rbuStrCompare(pIter->zTbl, pState->zTbl) + || (pState->zDataTbl==0 && rbuStrCompare(pIter->zTbl, pState->zTbl)) + || (pState->zDataTbl && rbuStrCompare(pIter->zDataTbl, pState->zDataTbl)) )){ rc = rbuObjIterNext(p, pIter); } diff --git a/manifest b/manifest index afe199c78d..952b5b561d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_DBCONFIG_RESET_DATABASE\scontrol\sfor\sresetting\sa\scorrupt\ndatabase\sfile\swithout\sclosing\sany\sdatabase\sconnections.\s\sAdded\sthe\n".dbconfig"\scommand\sto\sthe\sCLI. -D 2018-04-28T13:21:00.131 +C Fix\san\sRBU\sproblem\scausing\sspurious\sSQLITE_CONSTRAINT\serrors\swhen\srestarting\nan\sRBU\supdate\sin\swhich\smore\sthan\sone\ssource\stable\swrites\sto\sa\ssingle\starget\ndatabase\stable. +D 2018-04-28T18:20:01.187 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -308,7 +308,7 @@ F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/misc/zipfile.c c4de8f0ad446ce4a49aae11ff7b771cd7af60d7136c0bcfb53da1475b9075e79 F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64 F ext/rbu/rbu.c 4ae41f01d78dfae2204a63bcf39d5eb3548d039b094c29eec9a8d6683a66a5d3 -F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842 +F ext/rbu/rbu1.test 41123c64e8c88bd14eb7d3f8562f37fa87aaeb154b1eade2881de21d3504be55 F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702 F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16 @@ -323,7 +323,7 @@ F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af F ext/rbu/rbuA.test 4e58e46e60d4064248614c43303d71f1b18cc804dd834ce6a913b3861828b28d F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2 F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831 -F ext/rbu/rbu_common.tcl ebb8d81f44dc20e360cff1f34eb2ad0def33128805c5b36afcc44ab338509589 +F ext/rbu/rbu_common.tcl acfb7fbbaf8d46a9f6f6a5ec795616c84d705e1565d918afe43f0ff53ea0efa5 F ext/rbu/rbucollate.test 86d6fc9b8f59a27b7b5a6e20b5e29816d338a0dbdea8c54bfcc549a0d437f3ea F ext/rbu/rbucrash.test 61470d977a06a0abc2ec35b05d82a1d7d87d10f4ffabad14c1c231edc942ad66 F ext/rbu/rbucrash2.test b2ecbdd7bb72c88bd217c65bd00dafa07f7f2d4d @@ -338,10 +338,11 @@ F ext/rbu/rbumulti.test 2cf153ab3d5861ff26517dc6cbaec430787a59f1d50e8771fe7a7529 F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 +F ext/rbu/rbusplit.test 69271c790732b28bd465551d80b0a9a3f074e189896ee8490ce56d22078c124d F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1 F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8 F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa -F ext/rbu/sqlite3rbu.c f6e9ca388b5d4680fbf266a4d10a21aec11d6baf48f6d06fd53f6b205fad959f +F ext/rbu/sqlite3rbu.c f438fea899d15d13ff3e3133242b9e378c37b5a3d76add8c342c68bdd65c6819 F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2 F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15 @@ -1725,7 +1726,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6e098ee415f1a530e17a942c9ba51d67c25a3ebff6b97377b7858d0b10bcec92 ff836cb8b0377c5970ecb2b797702e2b5d208eda443ecbd55f4c238a3094b28a -R edbc587ec4dfbdf46b4ab916ffe47e60 -U drh -Z 995979318a529c573ca1f05b93ed22e0 +P a200a49edeaca5a787a3036070f7ced3cb6e9495f8afe7b74d5cde02c79b20dc +R a57111df9a8d9421276a0abc4d9ce2ed +U dan +Z ad185b98451d11b0164183c41426fb3b diff --git a/manifest.uuid b/manifest.uuid index d123b5ff6b..996f9ff769 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a200a49edeaca5a787a3036070f7ced3cb6e9495f8afe7b74d5cde02c79b20dc \ No newline at end of file +564ae8297d417ba4b7978e430d41f125007177673163f6ed9adc3a3974f73d24 \ No newline at end of file From b57e3ec5d8f034b345221a25b7892fe55feb65ac Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 28 Apr 2018 19:08:02 +0000 Subject: [PATCH 12/60] Test cases added for SQLITE_DBCONFIG_RESET_DATABASE. FossilOrigin-Name: 08665a9e2e50a0a1e62529884cf65f8090debe89a306a3904b53268729ab5ad5 --- manifest | 13 +++-- manifest.uuid | 2 +- test/resetdb.test | 138 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 test/resetdb.test diff --git a/manifest b/manifest index 952b5b561d..64af0212bc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sRBU\sproblem\scausing\sspurious\sSQLITE_CONSTRAINT\serrors\swhen\srestarting\nan\sRBU\supdate\sin\swhich\smore\sthan\sone\ssource\stable\swrites\sto\sa\ssingle\starget\ndatabase\stable. -D 2018-04-28T18:20:01.187 +C Test\scases\sadded\sfor\sSQLITE_DBCONFIG_RESET_DATABASE. +D 2018-04-28T19:08:02.897 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -1170,6 +1170,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/releasetest.tcl 5f15ab8056799e9a6e26a310d49236d2e774d6a30d0ec74601e18d4ce146b79c x +F test/resetdb.test 7fda92e443233208ec5e1825b176a9df63fb5bf962248e08b76eb4296c630cdf F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5 @@ -1726,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a200a49edeaca5a787a3036070f7ced3cb6e9495f8afe7b74d5cde02c79b20dc -R a57111df9a8d9421276a0abc4d9ce2ed -U dan -Z ad185b98451d11b0164183c41426fb3b +P 564ae8297d417ba4b7978e430d41f125007177673163f6ed9adc3a3974f73d24 +R f62951ddf79b7c70897c7cedc3fc5902 +U drh +Z d48406f4893f856e5db8717a8971e33f diff --git a/manifest.uuid b/manifest.uuid index 996f9ff769..c789d5b903 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -564ae8297d417ba4b7978e430d41f125007177673163f6ed9adc3a3974f73d24 \ No newline at end of file +08665a9e2e50a0a1e62529884cf65f8090debe89a306a3904b53268729ab5ad5 \ No newline at end of file diff --git a/test/resetdb.test b/test/resetdb.test new file mode 100644 index 0000000000..05e456a8d0 --- /dev/null +++ b/test/resetdb.test @@ -0,0 +1,138 @@ +# 2018-04-28 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# Test cases for SQLITE_DBCONFIG_RESET_DATABASE +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix resetdb + +ifcapable !vtab||!compound { + finish_test + return +} + +# Create a sample database +do_execsql_test 100 { + PRAGMA page_size=4096; + CREATE TABLE t1(a,b); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20) + INSERT INTO t1(a,b) SELECT x, randomblob(300) FROM c; + CREATE INDEX t1a ON t1(a); + CREATE INDEX t1b ON t1(b); + SELECT sum(a), sum(length(b)) FROM t1; + PRAGMA integrity_check; + PRAGMA journal_mode; + PRAGMA page_count; +} {210 6000 ok delete 8} + +# Verify that the same content is seen from a separate database connection +sqlite3 db2 test.db +do_test 110 { + execsql { + SELECT sum(a), sum(length(b)) FROM t1; + PRAGMA integrity_check; + PRAGMA journal_mode; + PRAGMA page_count; + } db2 +} {210 6000 ok delete 8} + +do_test 200 { + # Thoroughly corrupt the database file by overwriting the first + # page with randomness. + catchsql { + UPDATE sqlite_dbpage SET data=randomblob(4096) WHERE pgno=1; + PRAGMA quick_check; + } +} {1 {unsupported file format}} +do_test 201 { + catchsql { + PRAGMA quick_check; + } db2 +} {1 {unsupported file format}} + +do_test 210 { + # Reset the database file using SQLITE_DBCONFIG_RESET_DATABASE + sqlite3_db_config db RESET_DB 1 + db eval VACUUM + sqlite3_db_config db RESET_DB 0 + + # Verify that the reset took, even on the separate database connection + catchsql { + PRAGMA page_count; + PRAGMA page_size; + PRAGMA quick_check; + PRAGMA journal_mode; + } db2 +} {0 {1 4096 ok delete}} + +# Delete the old connections and database and start over again +# with a different page size and in WAL mode. +# +db close +db2 close +forcedelete test.db +sqlite3 db test.db +do_execsql_test 300 { + PRAGMA page_size=8192; + PRAGMA journal_mode=WAL; + CREATE TABLE t1(a,b); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20) + INSERT INTO t1(a,b) SELECT x, randomblob(1300) FROM c; + CREATE INDEX t1a ON t1(a); + CREATE INDEX t1b ON t1(b); + SELECT sum(a), sum(length(b)) FROM t1; + PRAGMA integrity_check; + PRAGMA journal_mode; + PRAGMA page_size; + PRAGMA page_count; +} {wal 210 26000 ok wal 8192 12} +sqlite3 db2 test.db +do_test 310 { + execsql { + SELECT sum(a), sum(length(b)) FROM t1; + PRAGMA integrity_check; + PRAGMA journal_mode; + PRAGMA page_size; + PRAGMA page_count; + } db2 +} {210 26000 ok wal 8192 12} + +# Corrupt the database again +do_catchsql_test 320 { + UPDATE sqlite_dbpage SET data=randomblob(8192) WHERE pgno=1; + PRAGMA quick_check +} {1 {file is not a database}} + +do_test 330 { + catchsql { + PRAGMA quick_check + } db2 +} {1 {file is not a database}} + +# Reset the database yet again. Verify that the page size and +# journal mode are preserved. +# +do_test 400 { + sqlite3_db_config db RESET_DB 1 + db eval VACUUM + sqlite3_db_config db RESET_DB 0 + catchsql { + PRAGMA page_count; + PRAGMA page_size; + PRAGMA journal_mode; + PRAGMA quick_check; + } db2 +} {0 {1 8192 wal ok}} +db2 close + + +finish_test From bbd4ae5a2fccdc243431d911f1e07274008c106c Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 30 Apr 2018 19:32:49 +0000 Subject: [PATCH 13/60] Defer loading result column values into registers on an ORDER BY LIMIT until we know that the LIMIT does not exclude the current row. FossilOrigin-Name: ce4ef46058f4aaea6623a41255a2e4b69bb24f16a287391df48f6bacdb4c4989 --- manifest | 17 +++--- manifest.uuid | 2 +- src/select.c | 149 ++++++++++++++++++++++++++++++++++++++++-------- src/sqliteInt.h | 7 +-- 4 files changed, 139 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index 64af0212bc..8204174977 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\scases\sadded\sfor\sSQLITE_DBCONFIG_RESET_DATABASE. -D 2018-04-28T19:08:02.897 +C Defer\sloading\sresult\scolumn\svalues\sinto\sregisters\son\san\sORDER\sBY\sLIMIT\suntil\nwe\sknow\sthat\sthe\sLIMIT\sdoes\snot\sexclude\sthe\scurrent\srow. +D 2018-04-30T19:32:49.040 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -493,12 +493,12 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c daf07d8defce3311f9e69f1280a874d78bc1d16c305f6aa689640f7afa02842f +F src/select.c 170834c5b9710676b192fc9b0fe0cf7970250b1a72b396435deb923f3670a58f F src/shell.c.in 54b902ab7d840f60ddfabc13124c85d4980342c88aff7679f2cc25f67c21ade7 F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d -F src/sqliteInt.h 8ac0138eae10337b745b03dad0124fd63ae911c0503e795729503e7fc6234d57 +F src/sqliteInt.h 3e354edb3090e31b51593e21ae54c541330987cfd87d69d86adf6e4d186408ca F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1727,7 +1727,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 564ae8297d417ba4b7978e430d41f125007177673163f6ed9adc3a3974f73d24 -R f62951ddf79b7c70897c7cedc3fc5902 +P 08665a9e2e50a0a1e62529884cf65f8090debe89a306a3904b53268729ab5ad5 +R 4667c6ddbdfa5ae61d508da23236434a +T *branch * faster-order-by-limit +T *sym-faster-order-by-limit * +T -sym-trunk * U drh -Z d48406f4893f856e5db8717a8971e33f +Z 8bfebc9ee79b135d90912539998ba9b3 diff --git a/manifest.uuid b/manifest.uuid index c789d5b903..2981900123 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -08665a9e2e50a0a1e62529884cf65f8090debe89a306a3904b53268729ab5ad5 \ No newline at end of file +ce4ef46058f4aaea6623a41255a2e4b69bb24f16a287391df48f6bacdb4c4989 \ No newline at end of file diff --git a/src/select.c b/src/select.c index ac313d0288..52dc2f94d6 100644 --- a/src/select.c +++ b/src/select.c @@ -78,6 +78,7 @@ struct SortCtx { int nKey; /* Number of PK columns for table pTab (>=1) */ } aDefer[4]; #endif + struct RowLoadInfo *pDeferredRowLoad; /* Deferred row loading info or NULL */ }; #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ @@ -536,6 +537,62 @@ static KeyInfo *keyInfoFromExprList( int nExtra /* Add this many extra columns to the end */ ); +/* +** An instance of this object holds information (beyond pParse and pSelect) +** needed to load the next result row that is to be added to the sorter. +*/ +typedef struct RowLoadInfo RowLoadInfo; +struct RowLoadInfo { + int regResult; /* Store results in array of registers here */ + u8 ecelFlags; /* Flag argument to ExprCodeExprList() */ +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + ExprList *pExtra; /* Extra columns needed by sorter refs */ + int regExtraResult; /* Where to load the extra columns */ +#endif +}; + +/* +** This routine does the work of loading query data into an array of +** registers so that it can be added to the sorter. +*/ +static void innerLoopLoadRow( + Parse *pParse, /* Statement under construction */ + Select *pSelect, /* The query being coded */ + RowLoadInfo *pInfo /* Info needed to complete the row load */ +){ + sqlite3ExprCodeExprList(pParse, pSelect->pEList, pInfo->regResult, + 0, pInfo->ecelFlags); +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + if( pInfo->pExtra ){ + sqlite3ExprCodeExprList(pParse, pInfo->pExtra, pInfo->regExtraResult, 0, 0); + sqlite3ExprListDelete(pParse->db, pInfo->pExtra); + } +#endif +} + +/* +** Code the OP_MakeRecord instruction that generates the entry to be +** added into the sorter. +** +** Return the register in which the result is stored. +*/ +static int makeSorterRecord( + Parse *pParse, + SortCtx *pSort, + Select *pSelect, + int regBase, + int nBase +){ + int nOBSat = pSort->nOBSat; + Vdbe *v = pParse->pVdbe; + int regOut = ++pParse->nMem; + if( pSort->pDeferredRowLoad ){ + innerLoopLoadRow(pParse, pSelect, pSort->pDeferredRowLoad); + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regOut); + return regOut; +} + /* ** Generate code that will push the record in registers regData ** through regData+nData-1 onto the sorter. @@ -546,7 +603,7 @@ static void pushOntoSorter( Select *pSelect, /* The whole SELECT statement */ int regData, /* First register holding data to be sorted */ int regOrigData, /* First register holding data before packing */ - int nData, /* Number of elements in the data array */ + int nData, /* Number of elements in the regData data array */ int nPrefixReg /* No. of reg prior to regData available for use */ ){ Vdbe *v = pParse->pVdbe; /* Stmt under construction */ @@ -554,16 +611,31 @@ static void pushOntoSorter( int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ int nBase = nExpr + bSeq + nData; /* Fields in sorter record */ int regBase; /* Regs for sorter record */ - int regRecord = ++pParse->nMem; /* Assembled sorter record */ + int regRecord = 0; /* Assembled sorter record */ int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ int op; /* Opcode to add sorter record to sorter */ int iLimit; /* LIMIT counter */ + int iSkip = 0; /* End of the sorter insert loop */ assert( bSeq==0 || bSeq==1 ); + + /* Three cases: + ** (1) The data to be sorted has already been packed into a Record + ** by a prior OP_MakeRecord. In this case nData==1 and regData + ** will be completely unrelated to regOrigData. + ** (2) All output columns are included in the sort record. In that + ** case regData==regOrigData. + ** (3) Some output columns are omitted from the sort record due to + ** the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the + ** SQLITE_ECEL_OMITREF optimization. In that case, regOrigData==0 + ** to prevent this routine from trying to copy values that might + ** not exist. + */ assert( nData==1 || regData==regOrigData || regOrigData==0 ); + if( nPrefixReg ){ assert( nPrefixReg==nExpr+bSeq ); - regBase = regData - nExpr - bSeq; + regBase = regData - nPrefixReg; }else{ regBase = pParse->nMem + 1; pParse->nMem += nBase; @@ -587,7 +659,7 @@ static void pushOntoSorter( int nKey; /* Number of sorting key columns, including OP_Sequence */ KeyInfo *pKI; /* Original KeyInfo on the sorter table */ - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat,regRecord); + regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); regPrevKey = pParse->nMem+1; pParse->nMem += pSort->nOBSat; nKey = nExpr - pSort->nOBSat + bSeq; @@ -638,17 +710,16 @@ static void pushOntoSorter( ** of the outer loop. */ int iCsr = pSort->iECursor; - int iJmp = sqlite3VdbeCurrentAddr(v)+5+(nOBSat<=0)+pSort->bOrderedInnerLoop; - assert( pSort->bOrderedInnerLoop==0 || pSort->bOrderedInnerLoop==1 ); sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0); - sqlite3VdbeAddOp4Int(v, OP_IdxLE, iCsr, iJmp, regBase+nOBSat, nExpr-nOBSat); + iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE, + iCsr, 0, regBase+nOBSat, nExpr-nOBSat); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_Delete, iCsr); } - if( nOBSat<=0 ){ - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat,regRecord); + if( regRecord==0 ){ + regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); } if( pSort->sortFlags & SORTFLAG_UseSorter ){ op = OP_SorterInsert; @@ -657,6 +728,11 @@ static void pushOntoSorter( } sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, regBase+nOBSat, nBase-nOBSat); + if( iSkip ){ + assert( pSort->bOrderedInnerLoop==0 || pSort->bOrderedInnerLoop==1 ); + sqlite3VdbeChangeP2(v, iSkip, + sqlite3VdbeCurrentAddr(v) + pSort->bOrderedInnerLoop); + } } /* @@ -742,9 +818,6 @@ static void selectExprDefer( Table *pTab = pExpr->pTab; if( pExpr->op==TK_COLUMN && pTab && !IsVirtual(pTab) && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) -#if 0 - && pTab->pSchema && pTab->pSelect==0 && !IsVirtual(pTab) -#endif ){ int j; for(j=0; jiSDParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ int nPrefixReg = 0; /* Number of extra registers before regResult */ + RowLoadInfo sRowLoadInfo; /* Info for deferred row loading */ /* Usually, regResult is the first cell in an array of memory cells ** containing the current result row. In this case regOrig is set to the @@ -863,7 +937,8 @@ static void selectInnerLoop( /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ - u8 ecelFlags; + u8 ecelFlags; /* "ecel" is an abbreviation of "ExprCodeExprList" */ + ExprList *pEList; if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ ecelFlags = SQLITE_ECEL_DUP; }else{ @@ -877,6 +952,7 @@ static void selectInnerLoop( ** This allows the p->pEList field to be omitted from the sorted record, ** saving space and CPU cycles. */ ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); + for(i=pSort->nOBSat; ipOrderBy->nExpr; i++){ int j; if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ @@ -897,20 +973,46 @@ static void selectInnerLoop( pParse->nMem += pExtra->nExpr; } #endif - regOrig = 0; + + /* Adjust nResultCol to account for columns that are omitted + ** from the sorter by the optimizations in this branch */ + pEList = p->pEList; + for(i=0; inExpr; i++){ + if( pEList->a[i].u.x.iOrderByCol>0 +#ifdef SQLITE_ENABLE_SORTER_REFERENCES + || pEList->a[i].bSorterRef +#endif + ){ + nResultCol--; + regOrig = 0; + } + } + + testcase( regOrig ); + testcase( eDest==SRT_Set ); + testcase( eDest==SRT_Mem ); + testcase( eDest==SRT_Coroutine ); + testcase( eDest==SRT_Output ); assert( eDest==SRT_Set || eDest==SRT_Mem || eDest==SRT_Coroutine || eDest==SRT_Output ); } - nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult, - 0,ecelFlags); + sRowLoadInfo.regResult = regResult; + sRowLoadInfo.ecelFlags = ecelFlags; #ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( pExtra ){ - nResultCol += sqlite3ExprCodeExprList( - pParse, pExtra, regResult + nResultCol, 0, 0 - ); - sqlite3ExprListDelete(pParse->db, pExtra); - } + sRowLoadInfo.pExtra = pExtra; + sRowLoadInfo.regExtraResult = regResult + nResultCol; + if( pExtra ) nResultCol += pExtra->nExpr; #endif + if( p->iLimit + && (ecelFlags & SQLITE_ECEL_OMITREF)!=0 + && nPrefixReg>0 + ){ + assert( pSort!=0 ); + assert( hasDistinct==0 ); + pSort->pDeferredRowLoad = &sRowLoadInfo; + }else{ + innerLoopLoadRow(pParse, p, &sRowLoadInfo); + } } /* If the DISTINCT keyword was present on the SELECT statement @@ -1026,7 +1128,8 @@ static void selectInnerLoop( } #endif if( pSort ){ - pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); + assert( regResult==regOrig ); + pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg); }else{ int r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c700c261b8..8d59de99e7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2759,11 +2759,8 @@ struct Upsert { ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** -** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. -** If there is a LIMIT clause, the parser sets nLimit to the value of the -** limit and nOffset to the value of the offset (or 0 if there is not -** offset). But later on, nLimit and nOffset become the memory locations -** in the VDBE that record the limit and offset counters. +** See the header comment on the computeLimitRegisters() routine for a +** detailed description of the meaning of the iLimit and iOffset fields. ** ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. ** These addresses must be stored so that we can go back and fill in From 8c2e6c5fe0424a4a5c8370beb16feb71a38c6d78 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 1 May 2018 18:39:31 +0000 Subject: [PATCH 14/60] The SQLITE_ALLOW_SQLITE_MASTER_INDEX compile-time option allows a CREATE INDEX statement against the sqlite_master table. Once created, the index works, and is usable by legacy instances of SQLite. FossilOrigin-Name: 853f3163597b9946c0cbeb808ea6fd33a0cf48ae6b8f4459c4165db377f33a9e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/build.c | 6 +++++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 64af0212bc..b0cba4a28b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\scases\sadded\sfor\sSQLITE_DBCONFIG_RESET_DATABASE. -D 2018-04-28T19:08:02.897 +C The\sSQLITE_ALLOW_SQLITE_MASTER_INDEX\scompile-time\soption\sallows\sa\sCREATE\sINDEX\nstatement\sagainst\sthe\ssqlite_master\stable.\s\sOnce\screated,\sthe\sindex\sworks,\sand\nis\susable\sby\slegacy\sinstances\sof\sSQLite. +D 2018-05-01T18:39:31.984 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -437,7 +437,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c fa7da0a5584e5182b92536bc4b7622a154a468997a075d5901345efb79a05ffe F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 -F src/build.c c4227d058d52c24ffce2d33cd3a11234d8e8603901243cdb5165eddf64ee2177 +F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 564ae8297d417ba4b7978e430d41f125007177673163f6ed9adc3a3974f73d24 -R f62951ddf79b7c70897c7cedc3fc5902 +P 08665a9e2e50a0a1e62529884cf65f8090debe89a306a3904b53268729ab5ad5 +R 65d0d1f1b897970475b65cf976ea92c3 U drh -Z d48406f4893f856e5db8717a8971e33f +Z fbedda4f45c8a34310211b3e1037138b diff --git a/manifest.uuid b/manifest.uuid index c789d5b903..0bfeabe2c0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -08665a9e2e50a0a1e62529884cf65f8090debe89a306a3904b53268729ab5ad5 \ No newline at end of file +853f3163597b9946c0cbeb808ea6fd33a0cf48ae6b8f4459c4165db377f33a9e \ No newline at end of file diff --git a/src/build.c b/src/build.c index 9eb28572dc..de3da04db8 100644 --- a/src/build.c +++ b/src/build.c @@ -3024,7 +3024,11 @@ void sqlite3CreateIndex( #if SQLITE_USER_AUTHENTICATION && sqlite3UserAuthTable(pTab->zName)==0 #endif - && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){ +#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX + && sqlite3StrICmp(&pTab->zName[7],"master")!=0 +#endif + && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 + ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } From e2ca99c907a783f6c347af0c25507839c5cac0e9 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 May 2018 00:33:43 +0000 Subject: [PATCH 15/60] Begin reengineering the EXPLAIN QUERY PLAN function to provide more intuitive output. FossilOrigin-Name: 70b48a7972dfbb44af3ccd8ccd830e984bec88d80a78b3566a5de86a16e7fc14 --- manifest | 27 +++++++------- manifest.uuid | 2 +- src/expr.c | 36 +++++-------------- src/select.c | 94 +++++++++++++++++-------------------------------- src/shell.c.in | 66 ++++++++++++++++------------------ src/sqliteInt.h | 8 ++--- src/vdbe.h | 16 ++++++++- src/vdbeaux.c | 43 ++++++++++++++++++++++ src/wherecode.c | 6 ++-- 9 files changed, 151 insertions(+), 147 deletions(-) diff --git a/manifest b/manifest index b0cba4a28b..c552ff2a44 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sSQLITE_ALLOW_SQLITE_MASTER_INDEX\scompile-time\soption\sallows\sa\sCREATE\sINDEX\nstatement\sagainst\sthe\ssqlite_master\stable.\s\sOnce\screated,\sthe\sindex\sworks,\sand\nis\susable\sby\slegacy\sinstances\sof\sSQLite. -D 2018-05-01T18:39:31.984 +C Begin\sreengineering\sthe\sEXPLAIN\sQUERY\sPLAN\sfunction\sto\sprovide\smore\nintuitive\soutput. +D 2018-05-02T00:33:43.157 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -445,7 +445,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c b0f90749e22d5e41a12dbf940f4811138cf97da54b46b737089b93eb64a2896f -F src/expr.c 5c9a6dc7f56d245d7bb82ba36fdba2ca3bdd1881b61ee60293dd98c766742cd9 +F src/expr.c 1757b6896ac542df8a90c0e00badc752abd90e04a852b7a947e33e94ee1fb46d F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c 94f42cba2cc1c34aeaa441022ba0170ec3fec4bba54db4e0ded085c6dc0fdc51 @@ -493,12 +493,12 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c daf07d8defce3311f9e69f1280a874d78bc1d16c305f6aa689640f7afa02842f -F src/shell.c.in 54b902ab7d840f60ddfabc13124c85d4980342c88aff7679f2cc25f67c21ade7 +F src/select.c 8481fa6ec8bb3b24465da8e81438d4d85056d69232f501c153ab8402409c8619 +F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d -F src/sqliteInt.h 8ac0138eae10337b745b03dad0124fd63ae911c0503e795729503e7fc6234d57 +F src/sqliteInt.h 337e4fe0a9e3bef575699bd0063ac2dcc31b73c905206d5425d442fe7fbb2798 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -564,10 +564,10 @@ F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5 F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55 -F src/vdbe.h 574ce9a0d57b026fc93ac379a339b8d391977f335ab4176a7e21ba902e9184bd +F src/vdbe.h dc29bf94721964da367debfc4472f5546e910b26f66850a8936ae4db174699d8 F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858 -F src/vdbeaux.c 944bae5207bbce456c466d01dcf2aac3ad49c957325d35c0ba7de882d3e5c25c +F src/vdbeaux.c 58129ae46be079613df5c2c3714d80a78605415bfa10c9528634c7c2d2147727 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f @@ -579,7 +579,7 @@ F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f F src/where.c 7a1c5555c00bcf49c677472ae83bb49bf24c8d8e9a060d475e86dee39be2fb3a F src/whereInt.h 2610cb87dd95509995b63decc674c60f2757697a206cfe0c085ee53d9c43cfff -F src/wherecode.c 3cb591fe7323e1bfd49059d75fcab75e383dfcf16a51c0e4f9368ac1b93e291b +F src/wherecode.c 13b831d258ab8468cb0469a882f0778632b55d787f329751e50d92b8133ea594 F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1727,7 +1727,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 08665a9e2e50a0a1e62529884cf65f8090debe89a306a3904b53268729ab5ad5 -R 65d0d1f1b897970475b65cf976ea92c3 +P 853f3163597b9946c0cbeb808ea6fd33a0cf48ae6b8f4459c4165db377f33a9e +R 4157eb92d30294276c327d965c794c5a +T *branch * rework-EQP +T *sym-rework-EQP * +T -sym-trunk * U drh -Z fbedda4f45c8a34310211b3e1037138b +Z 60e64f1bce0fa6f0f61a0e5e536f0823 diff --git a/manifest.uuid b/manifest.uuid index 0bfeabe2c0..14555151db 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -853f3163597b9946c0cbeb808ea6fd33a0cf48ae6b8f4459c4165db377f33a9e \ No newline at end of file +70b48a7972dfbb44af3ccd8ccd830e984bec88d80a78b3566a5de86a16e7fc14 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 2d4a14c8d0..f2f1a86105 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2410,11 +2410,8 @@ int sqlite3FindInIndex( if( colUsed==(MASKBIT(nExpr)-1) ){ /* If we reach this point, that means the index pIdx is usable */ int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); -#ifndef SQLITE_OMIT_EXPLAIN - sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0, - sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName), - P4_DYNAMIC); -#endif + ExplainQueryPlan((pParse, 0, + "USING INDEX %s FOR IN-OPERATOR",pIdx->zName)); sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); @@ -2646,17 +2643,10 @@ int sqlite3CodeSubselect( Select *pSelect = pExpr->x.pSelect; ExprList *pEList = pSelect->pEList; -#ifndef SQLITE_OMIT_EXPLAIN - if( pParse->explain==2 ){ - char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %sLIST SUBQUERY %d", - jmpIfDynamic>=0?"":"CORRELATED ", - pParse->iNextSelectId - ); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, - P4_DYNAMIC); - } -#endif - + ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY", + jmpIfDynamic>=0?"":"CORRELATED " + )); + ExplainQueryPlanSetId(pParse, pSelect); assert( !isRowid ); /* If the LHS and RHS of the IN operator do not match, that ** error will have been caught long before we reach this point. */ @@ -2777,18 +2767,10 @@ int sqlite3CodeSubselect( assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); assert( ExprHasProperty(pExpr, EP_xIsSelect) ); -#ifndef SQLITE_OMIT_EXPLAIN - if( pParse->explain==2 ){ - char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %sSCALAR SUBQUERY %d", - jmpIfDynamic>=0?"":"CORRELATED ", - pParse->iNextSelectId - ); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, - P4_DYNAMIC); - } -#endif - pSel = pExpr->x.pSelect; + ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY", + jmpIfDynamic>=0?"":"CORRELATED ")); + ExplainQueryPlanSetId(pParse, pSel); nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); pParse->nMem += nReg; diff --git a/src/select.c b/src/select.c index ac313d0288..debafd1500 100644 --- a/src/select.c +++ b/src/select.c @@ -21,7 +21,7 @@ /***/ int sqlite3SelectTrace = 0; # define SELECTTRACE(K,P,S,X) \ if(sqlite3SelectTrace&(K)) \ - sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->iSelectId,(S)),\ + sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->addrExplain,(S)),\ sqlite3DebugPrintf X #else # define SELECTTRACE(K,P,S,X) @@ -147,6 +147,9 @@ Select *sqlite3SelectNew( pNew->iOffset = 0; #if SELECTTRACE_ENABLED pNew->zSelName[0] = 0; +#endif +#if SELECTTRACE_ENABLED || !defined(SQLITE_OMIT_EXPLAIN) + pNew->iSelectId = 0; #endif pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; @@ -1293,11 +1296,7 @@ static const char *selectOpName(int id){ ** is determined by the zUsage argument. */ static void explainTempTable(Parse *pParse, const char *zUsage){ - if( pParse->explain==2 ){ - Vdbe *v = pParse->pVdbe; - char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); - } + ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage)); } /* @@ -1321,11 +1320,10 @@ static void explainTempTable(Parse *pParse, const char *zUsage){ ** is a no-op. Otherwise, it adds a single row of output to the EQP result, ** where the caption is of one of the two forms: ** -** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)" -** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)" +** "COMPOSITE (op)" +** "COMPOSITE USING TEMP B-TREE (op)" ** -** where iSub1 and iSub2 are the integers passed as the corresponding -** function parameters, and op is the text representation of the parameter +** where op is the text representation of the parameter ** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT, ** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is ** false, or the second form if it is true. @@ -1333,23 +1331,15 @@ static void explainTempTable(Parse *pParse, const char *zUsage){ static void explainComposite( Parse *pParse, /* Parse context */ int op, /* One of TK_UNION, TK_EXCEPT etc. */ - int iSub1, /* Subquery id 1 */ - int iSub2, /* Subquery id 2 */ int bUseTmp /* True if a temp table was used */ ){ assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL ); - if( pParse->explain==2 ){ - Vdbe *v = pParse->pVdbe; - char *zMsg = sqlite3MPrintf( - pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2, - bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op) - ); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); - } + ExplainQueryPlan((pParse, 1, "COMPOUND %s(%s)", + bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op))); } #else /* No-op versions of the explainXXX() functions and macros. */ -# define explainComposite(v,w,x,y,z) +# define explainComposite(v,y,z) #endif /* @@ -2474,10 +2464,6 @@ static int multiSelect( SelectDest dest; /* Alternative data destination */ Select *pDelete = 0; /* Chain of simple selects to delete */ sqlite3 *db; /* Database connection */ -#ifndef SQLITE_OMIT_EXPLAIN - int iSub1 = 0; /* EQP id of left-hand query */ - int iSub2 = 0; /* EQP id of right-hand query */ -#endif /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. @@ -2532,6 +2518,7 @@ static int multiSelect( /* Generate code for the left and right SELECT statements. */ + explainComposite(pParse, p->op, p->op!=TK_ALL); switch( p->op ){ case TK_ALL: { int addr = 0; @@ -2540,7 +2527,6 @@ static int multiSelect( pPrior->iLimit = p->iLimit; pPrior->iOffset = p->iOffset; pPrior->pLimit = p->pLimit; - explainSetInteger(iSub1, pParse->iNextSelectId); rc = sqlite3Select(pParse, pPrior, &dest); p->pLimit = 0; if( rc ){ @@ -2557,7 +2543,6 @@ static int multiSelect( p->iLimit, p->iOffset+1, p->iOffset); } } - explainSetInteger(iSub2, pParse->iNextSelectId); rc = sqlite3Select(pParse, p, &dest); testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; @@ -2609,7 +2594,6 @@ static int multiSelect( */ assert( !pPrior->pOrderBy ); sqlite3SelectDestInit(&uniondest, priorOp, unionTab); - explainSetInteger(iSub1, pParse->iNextSelectId); rc = sqlite3Select(pParse, pPrior, &uniondest); if( rc ){ goto multi_select_end; @@ -2627,7 +2611,6 @@ static int multiSelect( pLimit = p->pLimit; p->pLimit = 0; uniondest.eDest = op; - explainSetInteger(iSub2, pParse->iNextSelectId); rc = sqlite3Select(pParse, p, &uniondest); testcase( rc!=SQLITE_OK ); /* Query flattening in sqlite3Select() might refill p->pOrderBy. @@ -2690,7 +2673,6 @@ static int multiSelect( /* Code the SELECTs to our left into temporary table "tab1". */ sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); - explainSetInteger(iSub1, pParse->iNextSelectId); rc = sqlite3Select(pParse, pPrior, &intersectdest); if( rc ){ goto multi_select_end; @@ -2705,7 +2687,6 @@ static int multiSelect( pLimit = p->pLimit; p->pLimit = 0; intersectdest.iSDParm = tab2; - explainSetInteger(iSub2, pParse->iNextSelectId); rc = sqlite3Select(pParse, p, &intersectdest); testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; @@ -2737,7 +2718,7 @@ static int multiSelect( } } - explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL); + ExplainQueryPlanPop(pParse); /* Compute collating sequences used by ** temporary tables needed to implement the compound select. @@ -3076,10 +3057,6 @@ static int multiSelectOrderBy( ExprList *pOrderBy; /* The ORDER BY clause */ int nOrderBy; /* Number of terms in the ORDER BY clause */ int *aPermute; /* Mapping from ORDER BY terms to result set columns */ -#ifndef SQLITE_OMIT_EXPLAIN - int iSub1; /* EQP id of left-hand query */ - int iSub2; /* EQP id of right-hand query */ -#endif assert( p->pOrderBy!=0 ); assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ @@ -3198,6 +3175,8 @@ static int multiSelectOrderBy( regOutB = ++pParse->nMem; sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); + explainComposite(pParse, p->op, 0); + /* Generate a coroutine to evaluate the SELECT statement to the ** left of the compound operator - the "A" select. @@ -3206,7 +3185,6 @@ static int multiSelectOrderBy( addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; - explainSetInteger(iSub1, pParse->iNextSelectId); sqlite3Select(pParse, pPrior, &destA); sqlite3VdbeEndCoroutine(v, regAddrA); sqlite3VdbeJumpHere(v, addr1); @@ -3221,7 +3199,6 @@ static int multiSelectOrderBy( savedOffset = p->iOffset; p->iLimit = regLimitB; p->iOffset = 0; - explainSetInteger(iSub2, pParse->iNextSelectId); sqlite3Select(pParse, p, &destB); p->iLimit = savedLimit; p->iOffset = savedOffset; @@ -3333,7 +3310,7 @@ static int multiSelectOrderBy( /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ - explainComposite(pParse, p->op, iSub1, iSub2, 0); + ExplainQueryPlanPop(pParse); return pParse->nErr!=0; } #endif @@ -5121,14 +5098,11 @@ static void explainSimpleCount( ){ if( pParse->explain==2 ){ int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx))); - char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s", + sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s", pTab->zName, bCover ? " USING COVERING INDEX " : "", bCover ? pIdx->zName : "" ); - sqlite3VdbeAddOp4( - pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC - ); } } #else @@ -5341,22 +5315,21 @@ int sqlite3Select( ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ u8 minMaxFlag; /* Flag for min/max queries */ -#ifndef SQLITE_OMIT_EXPLAIN - int iRestoreSelectId = pParse->iSelectId; - pParse->iSelectId = pParse->iNextSelectId++; -#endif - db = pParse->db; + v = sqlite3GetVdbe(pParse); if( p==0 || db->mallocFailed || pParse->nErr ){ return 1; } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); -#if SELECTTRACE_ENABLED #ifndef SQLITE_OMIT_EXPLAIN - p->iSelectId = pParse->iSelectId; + if( p->iSelectId==0 && pParse->addrExplain ){ + ExplainQueryPlan((pParse, 1, "SUBQUERY")); + p->iSelectId = pParse->addrExplain; + } #endif - SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->iSelectId)); +#if SELECTTRACE_ENABLED + SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain)); if( sqlite3SelectTrace & 0x100 ){ sqlite3TreeViewSelect(0, p, 0); } @@ -5393,10 +5366,6 @@ int sqlite3Select( } #endif - /* Get a pointer the VDBE under construction, allocating a new VDBE if one - ** does not already exist */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto select_end; if( pDest->eDest==SRT_Output ){ generateColumnNames(pParse, p); } @@ -5491,11 +5460,11 @@ int sqlite3Select( rc = multiSelect(pParse, p, pDest); #if SELECTTRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end compound-select processing\n")); - if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){ + if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ sqlite3TreeViewSelect(0, p, 0); } #endif - explainSetInteger(pParse->iSelectId, iRestoreSelectId); + sqlite3VdbeExplainPop(pParse); return rc; } #endif @@ -5607,7 +5576,8 @@ int sqlite3Select( VdbeComment((v, "%s", pItem->pTab->zName)); pItem->addrFillSub = addrTop; sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); - explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); + ExplainQueryPlan((pParse, 1, "CO-ROUTINE %p", pSub)); + ExplainQueryPlanSetId(pParse, pSub); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowLogEst = pSub->nSelectRow; pItem->fg.viaCoroutine = 1; @@ -5642,12 +5612,12 @@ int sqlite3Select( pPrior = isSelfJoinView(pTabList, pItem); if( pPrior ){ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); - explainSetInteger(pItem->iSelectId, pPrior->iSelectId); assert( pPrior->pSelect!=0 ); pSub->nSelectRow = pPrior->pSelect->nSelectRow; }else{ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); - explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); + ExplainQueryPlan((pParse, 1, "MATERIALIZE %p", pSub)); + ExplainQueryPlanSetId(pParse,pSub); sqlite3Select(pParse, pSub, &dest); } pItem->pTab->nRowLogEst = pSub->nSelectRow; @@ -6285,10 +6255,10 @@ select_end: sqlite3DbFree(db, sAggInfo.aFunc); #if SELECTTRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end processing\n")); - if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){ + if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ sqlite3TreeViewSelect(0, p, 0); } #endif - explainSetInteger(pParse->iSelectId, iRestoreSelectId); + ExplainQueryPlanPop(pParse); return rc; } diff --git a/src/shell.c.in b/src/shell.c.in index e759921ab6..7675b3832d 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -981,7 +981,8 @@ struct ExpertInfo { /* A single line in the EQP output */ typedef struct EQPGraphRow EQPGraphRow; struct EQPGraphRow { - int iSelectId; /* The SelectID for this row */ + int iEqpId; /* ID for this row */ + int iParentId; /* ID of the parent row */ EQPGraphRow *pNext; /* Next row in sequence */ char zText[1]; /* Text to display for this row */ }; @@ -1003,6 +1004,7 @@ struct ShellState { sqlite3 *db; /* The database */ u8 autoExplain; /* Automatically turn on .explain mode */ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ + u8 autoEQPtest; /* autoEQP is in test mode */ u8 statsOn; /* True to display memory stats before each finalize */ u8 scanstatsOn; /* True to display scan stats before each finalize */ u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ @@ -1053,10 +1055,10 @@ struct ShellState { /* Allowed values for ShellState.autoEQP */ -#define AUTOEQP_off 0 -#define AUTOEQP_on 1 -#define AUTOEQP_trigger 2 -#define AUTOEQP_full 3 +#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */ +#define AUTOEQP_on 1 /* Automatic EQP is on */ +#define AUTOEQP_trigger 2 /* On and also show plans for triggers */ +#define AUTOEQP_full 3 /* Show full EXPLAIN */ /* Allowed values for ShellState.openMode */ @@ -1667,12 +1669,16 @@ static int wsToEol(const char *z){ /* ** Add a new entry to the EXPLAIN QUERY PLAN data */ -static void eqp_append(ShellState *p, int iSelectId, const char *zText){ +static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){ EQPGraphRow *pNew; int nText = strlen30(zText); + if( p->autoEQPtest ){ + utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); + } pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); if( pNew==0 ) shell_out_of_memory(); - pNew->iSelectId = iSelectId; + pNew->iEqpId = iEqpId; + pNew->iParentId = p2; memcpy(pNew->zText, zText, nText+1); pNew->pNext = 0; if( p->sGraph.pLast ){ @@ -1696,46 +1702,29 @@ static void eqp_reset(ShellState *p){ memset(&p->sGraph, 0, sizeof(p->sGraph)); } -/* Return the next EXPLAIN QUERY PLAN line with iSelectId that occurs after +/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after ** pOld, or return the first such line if pOld is NULL */ -static EQPGraphRow *eqp_next_row(ShellState *p, int iSelectId, EQPGraphRow *pOld){ +static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){ EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow; - while( pRow && pRow->iSelectId!=iSelectId ) pRow = pRow->pNext; + while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; return pRow; } -/* Render a single level of the graph shell having iSelectId. Called +/* Render a single level of the graph that has iEqpId as its parent. Called ** recursively to render sublevels. */ -static void eqp_render_level(ShellState *p, int iSelectId){ +static void eqp_render_level(ShellState *p, int iEqpId){ EQPGraphRow *pRow, *pNext; - int i; int n = strlen30(p->sGraph.zPrefix); char *z; - for(pRow = eqp_next_row(p, iSelectId, 0); pRow; pRow = pNext){ - pNext = eqp_next_row(p, iSelectId, pRow); + for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ + pNext = eqp_next_row(p, iEqpId, pRow); z = pRow->zText; utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z); - if( nsGraph.zPrefix)-7 && (z = strstr(z, " SUBQUER"))!=0 ){ + if( nsGraph.zPrefix)-7 ){ memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); - if( strncmp(z, " SUBQUERY ", 9)==0 && (i = atoi(z+10))>iSelectId ){ - eqp_render_level(p, i); - }else if( strncmp(z, " SUBQUERIES ", 12)==0 ){ - i = atoi(z+12); - if( i>iSelectId ){ - utf8_printf(p->out, "%s|--SUBQUERY %d\n", p->sGraph.zPrefix, i); - memcpy(&p->sGraph.zPrefix[n+3],"| ",4); - eqp_render_level(p, i); - } - z = strstr(z, " AND "); - if( z && (i = atoi(z+5))>iSelectId ){ - p->sGraph.zPrefix[n+3] = 0; - utf8_printf(p->out, "%s`--SUBQUERY %d\n", p->sGraph.zPrefix, i); - memcpy(&p->sGraph.zPrefix[n+3]," ",4); - eqp_render_level(p, i); - } - } + eqp_render_level(p, pRow->iEqpId); p->sGraph.zPrefix[n] = 0; } } @@ -2114,7 +2103,7 @@ static int shell_callback( break; } case MODE_EQP: { - eqp_append(p, atoi(azArg[0]), azArg[3]); + eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]); break; } } @@ -2956,9 +2945,10 @@ static int shell_exec( if( rc==SQLITE_OK ){ while( sqlite3_step(pExplain)==SQLITE_ROW ){ const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3); - int iSelectId = sqlite3_column_int(pExplain, 0); + int iEqpId = sqlite3_column_int(pExplain, 0); + int iParentId = sqlite3_column_int(pExplain, 1); if( zEQPLine[0]=='-' ) eqp_render(pArg); - eqp_append(pArg, iSelectId, zEQPLine); + eqp_append(pArg, iEqpId, iParentId, zEQPLine); } eqp_render(pArg); } @@ -5914,10 +5904,14 @@ static int do_meta_command(char *zLine, ShellState *p){ if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ if( nArg==2 ){ + p->autoEQPtest = 0; if( strcmp(azArg[1],"full")==0 ){ p->autoEQP = AUTOEQP_full; }else if( strcmp(azArg[1],"trigger")==0 ){ p->autoEQP = AUTOEQP_trigger; + }else if( strcmp(azArg[1],"test")==0 ){ + p->autoEQP = AUTOEQP_on; + p->autoEQPtest = 1; }else{ p->autoEQP = (u8)booleanValue(azArg[1]); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c700c261b8..f313baaec7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2609,9 +2609,6 @@ struct SrcList { unsigned viaCoroutine :1; /* Implemented as a co-routine */ unsigned isRecursive :1; /* True for recursive reference in WITH */ } fg; -#ifndef SQLITE_OMIT_EXPLAIN - u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ -#endif int iCursor; /* The VDBE cursor number used to access this table */ Expr *pOn; /* The ON clause of a join */ IdList *pUsing; /* The USING clause of a join */ @@ -2783,6 +2780,8 @@ struct Select { int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ #if SELECTTRACE_ENABLED char zSelName[12]; /* Symbolic name of this SELECT use for debugging */ +#endif +#if defined(SQLITETRACE_ENABLED) || !defined(SQLITE_OMIT_EXPLAIN) u32 iSelectId; /* EXPLAIN QUERY PLAN select ID */ #endif int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ @@ -3095,8 +3094,7 @@ struct Parse { #endif int nHeight; /* Expression tree height of current sub-select */ #ifndef SQLITE_OMIT_EXPLAIN - int iSelectId; /* ID of current select for EXPLAIN output */ - int iNextSelectId; /* Next available select ID for EXPLAIN output */ + int addrExplain; /* Address of current OP_Explain opcode */ #endif VList *pVList; /* Mapping between variable names and numbers */ Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ diff --git a/src/vdbe.h b/src/vdbe.h index 60525a9e9e..b7f44ca913 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -197,7 +197,21 @@ void sqlite3VdbeEndCoroutine(Vdbe*,int); # define sqlite3VdbeVerifyNoMallocRequired(A,B) # define sqlite3VdbeVerifyNoResultRow(A) #endif -VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); +VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); +#ifndef SQLITE_OMIT_EXPLAIN + void sqlite3VdbeExplain(Parse*,u8,const char*,...); + void sqlite3VdbeExplainPop(Parse*); + int sqlite3VdbeExplainParent(Parse*); +# define ExplainQueryPlan(P) sqlite3VdbeExplain P +# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P) +# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P) +# define ExplainQueryPlanSetId(P,S) (S)->iSelectId=(P)->addrExplain +#else +# define ExplainQueryPlan(P) +# define ExplainQueryPlanPop(P) +# define ExplainQueryPlanParent(P) 0 +# define ExplainQueryPlanSetId(P,S) +#endif void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index be092b98b7..5a7b354cb9 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -303,6 +303,49 @@ int sqlite3VdbeAddOp4Dup8( return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); } +#ifndef SQLITE_OMIT_EXPLAIN +/* +** Return the address of the current EXPLAIN QUERY PLAN baseline. +** 0 means "none". +*/ +int sqlite3VdbeExplainParent(Parse *pParse){ + VdbeOp *pOp; + if( pParse->addrExplain==0 ) return 0; + pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain); + return pOp->p2; +} + +/* +** Add a new OP_Explain opcode. +** +** If the bPush flag is true, then make this opcode the parent for +** subsequent Explains until sqlite3VdbeExplainPop() is called. +*/ +void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ + if( pParse->explain==2 ){ + char *zMsg; + Vdbe *v = pParse->pVdbe; + va_list ap; + int iThis; + va_start(ap, zFmt); + zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap); + va_end(ap); + v = pParse->pVdbe; + iThis = v->nOp; + sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0, + zMsg, P4_DYNAMIC); + if( bPush) pParse->addrExplain = iThis; + } +} + +/* +** Pop the EXPLAIN QUERY PLAN stack one level. +*/ +void sqlite3VdbeExplainPop(Parse *pParse){ + pParse->addrExplain = sqlite3VdbeExplainParent(pParse); +} +#endif /* SQLITE_OMIT_EXPLAIN */ + /* ** Add an OP_ParseSchema opcode. This routine is broken out from ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees diff --git a/src/wherecode.c b/src/wherecode.c index 818a7a208b..c1987d6b08 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -134,7 +134,6 @@ int sqlite3WhereExplainOneScan( struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; Vdbe *v = pParse->pVdbe; /* VM being constructed */ sqlite3 *db = pParse->db; /* Database handle */ - int iId = pParse->iSelectId; /* Select id (left-most output column) */ int isSearch; /* True for a SEARCH. False for SCAN. */ WhereLoop *pLoop; /* The controlling WhereLoop object */ u32 flags; /* Flags that describe this loop */ @@ -153,7 +152,7 @@ int sqlite3WhereExplainOneScan( sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); if( pItem->pSelect ){ - sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); + sqlite3XPrintf(&str, " SUBQUERY %p", pItem->pSelect); }else{ sqlite3XPrintf(&str, " TABLE %s", pItem->zName); } @@ -214,7 +213,8 @@ int sqlite3WhereExplainOneScan( } #endif zMsg = sqlite3StrAccumFinish(&str); - ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC); + ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), + pParse->addrExplain, 0, zMsg,P4_DYNAMIC); } return ret; } From c631ded5e886df1aad0a82806f4b66e740acce12 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 May 2018 02:22:22 +0000 Subject: [PATCH 16/60] Improvements to the EQP display for compound select statements. FossilOrigin-Name: 699a77e479010a331b0423f157a2fbfc373688e3d0d04ae5e64376c00cb3d488 --- manifest | 15 +++++------- manifest.uuid | 2 +- src/select.c | 64 ++++++++++++++++++++++----------------------------- 3 files changed, 34 insertions(+), 47 deletions(-) diff --git a/manifest b/manifest index c552ff2a44..bcec88827f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Begin\sreengineering\sthe\sEXPLAIN\sQUERY\sPLAN\sfunction\sto\sprovide\smore\nintuitive\soutput. -D 2018-05-02T00:33:43.157 +C Improvements\sto\sthe\sEQP\sdisplay\sfor\scompound\sselect\sstatements. +D 2018-05-02T02:22:22.993 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -493,7 +493,7 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 8481fa6ec8bb3b24465da8e81438d4d85056d69232f501c153ab8402409c8619 +F src/select.c 41962df2f21593db4eb5e0d7d8f15848b9ebd3ffed9b7584677033a8db37223b F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1727,10 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 853f3163597b9946c0cbeb808ea6fd33a0cf48ae6b8f4459c4165db377f33a9e -R 4157eb92d30294276c327d965c794c5a -T *branch * rework-EQP -T *sym-rework-EQP * -T -sym-trunk * +P 70b48a7972dfbb44af3ccd8ccd830e984bec88d80a78b3566a5de86a16e7fc14 +R 21b35e2f4fb3267c4b0452fc48ac12e8 U drh -Z 60e64f1bce0fa6f0f61a0e5e536f0823 +Z 26b206c16e8cc64ca80991a86c32cf32 diff --git a/manifest.uuid b/manifest.uuid index 14555151db..59502e34a1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -70b48a7972dfbb44af3ccd8ccd830e984bec88d80a78b3566a5de86a16e7fc14 \ No newline at end of file +699a77e479010a331b0423f157a2fbfc373688e3d0d04ae5e64376c00cb3d488 \ No newline at end of file diff --git a/src/select.c b/src/select.c index debafd1500..49744a9dc3 100644 --- a/src/select.c +++ b/src/select.c @@ -1314,33 +1314,6 @@ static void explainTempTable(Parse *pParse, const char *zUsage){ # define explainSetInteger(y,z) #endif -#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT) -/* -** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function -** is a no-op. Otherwise, it adds a single row of output to the EQP result, -** where the caption is of one of the two forms: -** -** "COMPOSITE (op)" -** "COMPOSITE USING TEMP B-TREE (op)" -** -** where op is the text representation of the parameter -** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT, -** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is -** false, or the second form if it is true. -*/ -static void explainComposite( - Parse *pParse, /* Parse context */ - int op, /* One of TK_UNION, TK_EXCEPT etc. */ - int bUseTmp /* True if a temp table was used */ -){ - assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL ); - ExplainQueryPlan((pParse, 1, "COMPOUND %s(%s)", - bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op))); -} -#else -/* No-op versions of the explainXXX() functions and macros. */ -# define explainComposite(v,y,z) -#endif /* ** If the inner loop was generated using a non-null pOrderBy argument, @@ -2516,9 +2489,16 @@ static int multiSelect( return multiSelectOrderBy(pParse, p, pDest); }else +#ifndef SQLITE_OMIT_EXPLAIN + if( pPrior->pPrior==0 ){ + ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); + ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); + ExplainQueryPlanSetId(pParse, pPrior); + } +#endif + /* Generate code for the left and right SELECT statements. */ - explainComposite(pParse, p->op, p->op!=TK_ALL); switch( p->op ){ case TK_ALL: { int addr = 0; @@ -2543,6 +2523,8 @@ static int multiSelect( p->iLimit, p->iOffset+1, p->iOffset); } } + ExplainQueryPlan((pParse, 1, "UNION ALL")); + ExplainQueryPlanSetId(pParse, p); rc = sqlite3Select(pParse, p, &dest); testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; @@ -2611,6 +2593,9 @@ static int multiSelect( pLimit = p->pLimit; p->pLimit = 0; uniondest.eDest = op; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + selectOpName(p->op))); + ExplainQueryPlanSetId(pParse, p); rc = sqlite3Select(pParse, p, &uniondest); testcase( rc!=SQLITE_OK ); /* Query flattening in sqlite3Select() might refill p->pOrderBy. @@ -2687,6 +2672,9 @@ static int multiSelect( pLimit = p->pLimit; p->pLimit = 0; intersectdest.iSDParm = tab2; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + selectOpName(p->op))); + ExplainQueryPlanSetId(pParse, p); rc = sqlite3Select(pParse, p, &intersectdest); testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; @@ -2718,7 +2706,11 @@ static int multiSelect( } } - ExplainQueryPlanPop(pParse); +#ifndef SQLITE_OMIT_EXPLAIN + if( p->pNext==0 ){ + ExplainQueryPlanPop(pParse); + } +#endif /* Compute collating sequences used by ** temporary tables needed to implement the compound select. @@ -3175,8 +3167,8 @@ static int multiSelectOrderBy( regOutB = ++pParse->nMem; sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); - explainComposite(pParse, p->op, 0); + ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op))); /* Generate a coroutine to evaluate the SELECT statement to the ** left of the compound operator - the "A" select. @@ -3185,6 +3177,8 @@ static int multiSelectOrderBy( addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; + ExplainQueryPlan((pParse, 1, "LEFT")); + ExplainQueryPlanSetId(pParse, pPrior); sqlite3Select(pParse, pPrior, &destA); sqlite3VdbeEndCoroutine(v, regAddrA); sqlite3VdbeJumpHere(v, addr1); @@ -3199,6 +3193,8 @@ static int multiSelectOrderBy( savedOffset = p->iOffset; p->iLimit = regLimitB; p->iOffset = 0; + ExplainQueryPlan((pParse, 1, "RIGHT")); + ExplainQueryPlanSetId(pParse, p); sqlite3Select(pParse, p, &destB); p->iLimit = savedLimit; p->iOffset = savedOffset; @@ -5322,12 +5318,6 @@ int sqlite3Select( } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); -#ifndef SQLITE_OMIT_EXPLAIN - if( p->iSelectId==0 && pParse->addrExplain ){ - ExplainQueryPlan((pParse, 1, "SUBQUERY")); - p->iSelectId = pParse->addrExplain; - } -#endif #if SELECTTRACE_ENABLED SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain)); if( sqlite3SelectTrace & 0x100 ){ @@ -5464,7 +5454,7 @@ int sqlite3Select( sqlite3TreeViewSelect(0, p, 0); } #endif - sqlite3VdbeExplainPop(pParse); + if( p->pNext==0 ) ExplainQueryPlanPop(pParse); return rc; } #endif From 07430a8caf78e0fcd1956227d99f51ad6c57bec7 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 2 May 2018 03:01:50 +0000 Subject: [PATCH 17/60] Add sqlite3_win32_set_directory8() and sqlite3_win32_set_directory16() functions. FossilOrigin-Name: 22089ea2bbea93eb1da7f08344789a5455077169443e40025f053d2a117f1c08 --- manifest | 16 +++++++------- manifest.uuid | 2 +- src/os_win.c | 55 +++++++++++++++++++++++++++++++++++++------------ src/sqlite.h.in | 7 ++++++- 4 files changed, 57 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index b0cba4a28b..4e45d3d6a4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sSQLITE_ALLOW_SQLITE_MASTER_INDEX\scompile-time\soption\sallows\sa\sCREATE\sINDEX\nstatement\sagainst\sthe\ssqlite_master\stable.\s\sOnce\screated,\sthe\sindex\sworks,\sand\nis\susable\sby\slegacy\sinstances\sof\sSQLite. -D 2018-05-01T18:39:31.984 +C Add\ssqlite3_win32_set_directory8()\sand\ssqlite3_win32_set_directory16()\sfunctions. +D 2018-05-02T03:01:50.355 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -478,7 +478,7 @@ F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 2b53b0b8ddc580db096252c721729e5f5f2f355b4fc056f8f3fb328aeb3c9e8a -F src/os_win.c a8f39484f3b9162250f510bcceb2826638c00847c9c271b770289f672ebe5372 +F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388 @@ -495,7 +495,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c daf07d8defce3311f9e69f1280a874d78bc1d16c305f6aa689640f7afa02842f F src/shell.c.in 54b902ab7d840f60ddfabc13124c85d4980342c88aff7679f2cc25f67c21ade7 -F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea +F src/sqlite.h.in 469aed42e75193b7f5d88d812befa961c04746869475f96fcf434c9f67079f66 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d F src/sqliteInt.h 8ac0138eae10337b745b03dad0124fd63ae911c0503e795729503e7fc6234d57 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 08665a9e2e50a0a1e62529884cf65f8090debe89a306a3904b53268729ab5ad5 -R 65d0d1f1b897970475b65cf976ea92c3 -U drh -Z fbedda4f45c8a34310211b3e1037138b +P 853f3163597b9946c0cbeb808ea6fd33a0cf48ae6b8f4459c4165db377f33a9e +R 7d36afb40ceca70451bc2c1787c2fa2c +U mistachkin +Z c462fe799d29c04b823cce6378b0f174 diff --git a/manifest.uuid b/manifest.uuid index 0bfeabe2c0..125fcca9d9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -853f3163597b9946c0cbeb808ea6fd33a0cf48ae6b8f4459c4165db377f33a9e \ No newline at end of file +22089ea2bbea93eb1da7f08344789a5455077169443e40025f053d2a117f1c08 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index df97f928ea..3eb2f3c612 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -1911,15 +1911,12 @@ char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ } /* -** This function sets the data directory or the temporary directory based on -** the provided arguments. The type argument must be 1 in order to set the -** data directory or 2 in order to set the temporary directory. The zValue -** argument is the name of the directory to use. The return value will be -** SQLITE_OK if successful. +** This function is the same as sqlite3_win32_set_directory (below); however, +** it accepts a UTF-8 string. */ -int sqlite3_win32_set_directory( +int sqlite3_win32_set_directory8( unsigned long type, /* Identifier for directory being set or reset */ - void *zValue /* New value for directory being set or reset */ + const char *zValue /* New value for directory being set or reset */ ){ char **ppDirectory = 0; #ifndef SQLITE_OMIT_AUTOINIT @@ -1936,21 +1933,53 @@ int sqlite3_win32_set_directory( ); assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); if( ppDirectory ){ - LPCWSTR zStrValue = zValue; - char *zValueUtf8 = 0; - if( zStrValue && zStrValue[0] ){ - zValueUtf8 = winUnicodeToUtf8(zStrValue); - if ( zValueUtf8==0 ){ + char *zCopy = 0; + if( zValue && zValue[0] ){ + zCopy = sqlite3_mprintf("%s", zValue); + if ( zCopy==0 ){ return SQLITE_NOMEM_BKPT; } } sqlite3_free(*ppDirectory); - *ppDirectory = zValueUtf8; + *ppDirectory = zCopy; return SQLITE_OK; } return SQLITE_ERROR; } +/* +** This function is the same as sqlite3_win32_set_directory (below); however, +** it accepts a UTF-16 string. +*/ +int sqlite3_win32_set_directory16( + unsigned long type, /* Identifier for directory being set or reset */ + const void *zValue /* New value for directory being set or reset */ +){ + int rc; + char *zUtf8 = 0; + if( zValue ){ + zUtf8 = sqlite3_win32_unicode_to_utf8(zValue); + if( zUtf8==0 ) return SQLITE_NOMEM_BKPT; + } + rc = sqlite3_win32_set_directory8(type, zUtf8); + if( zUtf8 ) sqlite3_free(zUtf8); + return rc; +} + +/* +** This function sets the data directory or the temporary directory based on +** the provided arguments. The type argument must be 1 in order to set the +** data directory or 2 in order to set the temporary directory. The zValue +** argument is the name of the directory to use. The return value will be +** SQLITE_OK if successful. +*/ +int sqlite3_win32_set_directory( + unsigned long type, /* Identifier for directory being set or reset */ + void *zValue /* New value for directory being set or reset */ +){ + return sqlite3_win32_set_directory16(type, zValue); +} + /* ** The return value of winGetLastErrorMsg ** is zero if the error message fits in the buffer, or non-zero diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 696b3cb2db..e7bc6191cc 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5539,12 +5539,17 @@ SQLITE_EXTERN char *sqlite3_data_directory; ** or [SQLITE_NOMEM] if memory could not be allocated. The value of the ** [sqlite3_data_directory] variable is intended to act as a replacement for ** the current directory on the sub-platforms of Win32 where that concept is -** not present, e.g. WinRT and UWP. +** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and +** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the +** sqlite3_win32_set_directory interface except the string parameter must be +** UTF-8 or UTF-16, respectively. */ int sqlite3_win32_set_directory( unsigned long type, /* Identifier for directory being set or reset */ void *zValue /* New value for directory being set or reset */ ); +int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); +int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); /* ** CAPI3REF: Win32 Directory Types From fa5c69f5cb57778e5ced0490e2eda4498437b596 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 2 May 2018 08:12:22 +0000 Subject: [PATCH 18/60] Fix a problem in the xBestIndex method of the closure extension causing it to allocate non-contiguous argvIndex values in some cases (an "xBestIndex malfunction" error). FossilOrigin-Name: 0c67150749cb3d067e14b2dcac9c3489e0f14bd18c0387f1d9bc93d21fc96fe5 --- ext/misc/closure.c | 18 ++++++++++++------ manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/closure01.test | 19 +++++++++++++++++++ 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/ext/misc/closure.c b/ext/misc/closure.c index 510c46ec90..74bffc7708 100644 --- a/ext/misc/closure.c +++ b/ext/misc/closure.c @@ -826,17 +826,12 @@ static int closureBestIndex( int iPlan = 0; int i; int idx = 1; - int seenMatch = 0; const struct sqlite3_index_constraint *pConstraint; closure_vtab *pVtab = (closure_vtab*)pTab; double rCost = 10000000.0; pConstraint = pIdxInfo->aConstraint; for(i=0; inConstraint; i++, pConstraint++){ - if( pConstraint->iColumn==CLOSURE_COL_ROOT - && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - seenMatch = 1; - } if( pConstraint->usable==0 ) continue; if( (iPlan & 1)==0 && pConstraint->iColumn==CLOSURE_COL_ROOT @@ -893,6 +888,18 @@ static int closureBestIndex( ** or else the result is an empty set. */ iPlan = 0; } + if( (iPlan&1)==0 ){ + /* If there is no usable "root=?" term, then set the index-type to 0. + ** Also clear any argvIndex variables already set. This is necessary + ** to prevent the core from throwing an "xBestIndex malfunction error" + ** error (because the argvIndex values are not contiguously assigned + ** starting from 1). */ + rCost *= 1e30; + for(i=0; inConstraint; i++, pConstraint++){ + pIdxInfo->aConstraintUsage[i].argvIndex = 0; + } + iPlan = 0; + } pIdxInfo->idxNum = iPlan; if( pIdxInfo->nOrderBy==1 && pIdxInfo->aOrderBy[0].iColumn==CLOSURE_COL_ID @@ -900,7 +907,6 @@ static int closureBestIndex( ){ pIdxInfo->orderByConsumed = 1; } - if( seenMatch && (iPlan&1)==0 ) rCost *= 1e30; pIdxInfo->estimatedCost = rCost; return SQLITE_OK; diff --git a/manifest b/manifest index 4e45d3d6a4..f0aff63579 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssqlite3_win32_set_directory8()\sand\ssqlite3_win32_set_directory16()\sfunctions. -D 2018-05-02T03:01:50.355 +C Fix\sa\sproblem\sin\sthe\sxBestIndex\smethod\sof\sthe\sclosure\sextension\scausing\sit\sto\nallocate\snon-contiguous\sargvIndex\svalues\sin\ssome\scases\s(an\s"xBestIndex\nmalfunction"\serror). +D 2018-05-02T08:12:22.566 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -271,7 +271,7 @@ F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a2 F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7 F ext/misc/btreeinfo.c 78c8c57d325185ccc04b7679e5b020e34a4d9c87453e6b7ac943d0a26cee3256 F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005 -F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704 +F ext/misc/closure.c fe928228e8dfb2f00227311c203ccba9c2e5561f4f6de6da87e5b4a30cd8af15 F ext/misc/completion.c e75b8886a2531f9a7ec02dab5f179bb37e6bd46b5da7665a6cbf2dfbe2daa483 F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189 F ext/misc/csv.c d1e324fac3f87f818d684a3d752d1ef76dbcd4fc0db6746ac4034c19d0bcda21 @@ -684,7 +684,7 @@ F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa385 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a F test/close.test 799ea4599d2f5704b0a30f477d17c2c760d8523fa5d0c8be4a7df2a8cad787d8 -F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4 +F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846 F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 853f3163597b9946c0cbeb808ea6fd33a0cf48ae6b8f4459c4165db377f33a9e -R 7d36afb40ceca70451bc2c1787c2fa2c -U mistachkin -Z c462fe799d29c04b823cce6378b0f174 +P 22089ea2bbea93eb1da7f08344789a5455077169443e40025f053d2a117f1c08 +R 4366c3e52bbd0f10fc2d8dde8b988b3b +U dan +Z d8568d2c99d0406cb3f7adcc92b802b9 diff --git a/manifest.uuid b/manifest.uuid index 125fcca9d9..02f59e9ef9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -22089ea2bbea93eb1da7f08344789a5455077169443e40025f053d2a117f1c08 \ No newline at end of file +0c67150749cb3d067e14b2dcac9c3489e0f14bd18c0387f1d9bc93d21fc96fe5 \ No newline at end of file diff --git a/test/closure01.test b/test/closure01.test index 213ef4e966..ee3f2dd1d0 100644 --- a/test/closure01.test +++ b/test/closure01.test @@ -273,4 +273,23 @@ do_execsql_test 5.1 { ORDER BY id; } {8 9 10 11 12 13 14 15} +#------------------------------------------------------------------------- +# At one point the following join query was causing a malfunction in +# xBestIndex. +# +do_execsql_test 6.0 { + CREATE TABLE t4 ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + parent_id INTEGER + ); + CREATE VIRTUAL TABLE vt4 USING transitive_closure ( + idcolumn=id, parentcolumn=parent_id, tablename=t4 + ); +} + +do_execsql_test 6.1 { + SELECT * FROM t4, vt4 WHERE t4.id = vt4.root AND vt4.id=4 AND vt4.depth=2; +} + finish_test From 03c3905f94be896702293266bee7cef9dcbae68e Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 May 2018 14:24:34 +0000 Subject: [PATCH 19/60] Fix a dangling-else problem that was causing recursive CTEs to malfunction. Begin fixing test cases to work with the new EQP output. FossilOrigin-Name: 82ca44b82fed6814c84440ba8bfaa019488ab956e84ac165180e2fcece6facb2 --- manifest | 26 +-- manifest.uuid | 2 +- src/prepare.c | 2 +- src/select.c | 412 ++++++++++++++++++++++--------------------- src/sqliteInt.h | 3 +- src/wherecode.c | 2 +- test/analyze3.test | 30 ++-- test/analyze9.test | 42 ++--- test/eqp.test | 428 +++++++++++++++++++++++++++------------------ test/tester.tcl | 75 +++++++- 10 files changed, 590 insertions(+), 432 deletions(-) diff --git a/manifest b/manifest index bcec88827f..c23605c90a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\sEQP\sdisplay\sfor\scompound\sselect\sstatements. -D 2018-05-02T02:22:22.993 +C Fix\sa\sdangling-else\sproblem\sthat\swas\scausing\srecursive\sCTEs\sto\smalfunction.\nBegin\sfixing\stest\scases\sto\swork\swith\sthe\snew\sEQP\soutput. +D 2018-05-02T14:24:34.656 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -488,17 +488,17 @@ F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69 F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 -F src/prepare.c 1492a2bed7bc5770c5850404f09bf887a67d4580985b8cee37bdab2ea809f479 +F src/prepare.c 95a9dba7a5d032039a77775188cb3b6fb17f2fa1a0b7cd915b30b4b823383ffa F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 41962df2f21593db4eb5e0d7d8f15848b9ebd3ffed9b7584677033a8db37223b +F src/select.c e66bb89e00608e50fa03939d5d86213a302487e8b78e0960b646be9ea0ac2f3e F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d -F src/sqliteInt.h 337e4fe0a9e3bef575699bd0063ac2dcc31b73c905206d5425d442fe7fbb2798 +F src/sqliteInt.h 4095263176d49601f27086b7e66ca541923b72a909187923e3b45e60511cfe2a F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -579,7 +579,7 @@ F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f F src/where.c 7a1c5555c00bcf49c677472ae83bb49bf24c8d8e9a060d475e86dee39be2fb3a F src/whereInt.h 2610cb87dd95509995b63decc674c60f2757697a206cfe0c085ee53d9c43cfff -F src/wherecode.c 13b831d258ab8468cb0469a882f0778632b55d787f329751e50d92b8133ea594 +F src/wherecode.c 3368f0797a4b166e0773a4137d270d92ddcbce91618b11d1e9f11f7c39f33068 F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -595,13 +595,13 @@ F test/alter4.test b6d7b86860111864f6cddb54af313f5862dda23b F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df -F test/analyze3.test 8b3ef8ba6d1096b76c40e0925c0fe51e700d2b779cdda40914580de3f9b9d80f +F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8 F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213 F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82 -F test/analyze9.test dac0bdc7eab965b9ad639ca83564d98717aaf13ce5a776f23d9a3680238cecd8 +F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54 F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70 F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 @@ -791,7 +791,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473 F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6 F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020 -F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2 +F test/eqp.test 0d06518e010ca5f02bd56b6a45fb70514a29c7eb97d244d72826d164477cfb1e F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9 F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3 @@ -1316,7 +1316,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637 F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc -F test/tester.tcl 94901a4625d9a2229666dd5c44120ddf7f0fb639470710ef74a4cefc7b039e07 +F test/tester.tcl aa7558f20fcf7dd9151325f849d9103bd450235093bc078073bf0f080991e3c4 F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 70b48a7972dfbb44af3ccd8ccd830e984bec88d80a78b3566a5de86a16e7fc14 -R 21b35e2f4fb3267c4b0452fc48ac12e8 +P 699a77e479010a331b0423f157a2fbfc373688e3d0d04ae5e64376c00cb3d488 +R 5835567753900691e5cf824409193ffc U drh -Z 26b206c16e8cc64ca80991a86c32cf32 +Z eb3edd9f2f9ef18dad6eafce24ad9bb2 diff --git a/manifest.uuid b/manifest.uuid index 59502e34a1..92377ae8f2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -699a77e479010a331b0423f157a2fbfc373688e3d0d04ae5e64376c00cb3d488 \ No newline at end of file +82ca44b82fed6814c84440ba8bfaa019488ab956e84ac165180e2fcece6facb2 \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index 971b8024e8..c745f45a5a 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -616,7 +616,7 @@ static int sqlite3Prepare( if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ static const char * const azColName[] = { "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", - "selectid", "order", "from", "detail" + "id", "parent", "notused", "detail" }; int iFirst, mx; if( sParse.explain==2 ){ diff --git a/src/select.c b/src/select.c index 49744a9dc3..d9b80f6080 100644 --- a/src/select.c +++ b/src/select.c @@ -2487,231 +2487,237 @@ static int multiSelect( */ if( p->pOrderBy ){ return multiSelectOrderBy(pParse, p, pDest); - }else + }else{ #ifndef SQLITE_OMIT_EXPLAIN - if( pPrior->pPrior==0 ){ - ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); - ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); - ExplainQueryPlanSetId(pParse, pPrior); - } + if( p->pNext==0 ){ + ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); + } + if( pPrior->pPrior==0 ){ + ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); + ExplainQueryPlanSetId(pParse, pPrior); + } #endif - /* Generate code for the left and right SELECT statements. - */ - switch( p->op ){ - case TK_ALL: { - int addr = 0; - int nLimit; - assert( !pPrior->pLimit ); - pPrior->iLimit = p->iLimit; - pPrior->iOffset = p->iOffset; - pPrior->pLimit = p->pLimit; - rc = sqlite3Select(pParse, pPrior, &dest); - p->pLimit = 0; - if( rc ){ - goto multi_select_end; - } - p->pPrior = 0; - p->iLimit = pPrior->iLimit; - p->iOffset = pPrior->iOffset; - if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); - VdbeComment((v, "Jump ahead if LIMIT reached")); - if( p->iOffset ){ - sqlite3VdbeAddOp3(v, OP_OffsetLimit, - p->iLimit, p->iOffset+1, p->iOffset); + /* Generate code for the left and right SELECT statements. + */ + switch( p->op ){ + case TK_ALL: { + int addr = 0; + int nLimit; + assert( !pPrior->pLimit ); + pPrior->iLimit = p->iLimit; + pPrior->iOffset = p->iOffset; + pPrior->pLimit = p->pLimit; + rc = sqlite3Select(pParse, pPrior, &dest); + p->pLimit = 0; + if( rc ){ + goto multi_select_end; } + p->pPrior = 0; + p->iLimit = pPrior->iLimit; + p->iOffset = pPrior->iOffset; + if( p->iLimit ){ + addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); + VdbeComment((v, "Jump ahead if LIMIT reached")); + if( p->iOffset ){ + sqlite3VdbeAddOp3(v, OP_OffsetLimit, + p->iLimit, p->iOffset+1, p->iOffset); + } + } + ExplainQueryPlan((pParse, 1, "UNION ALL")); + ExplainQueryPlanSetId(pParse, p); + rc = sqlite3Select(pParse, p, &dest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + if( pPrior->pLimit + && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit) + && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) + ){ + p->nSelectRow = sqlite3LogEst((u64)nLimit); + } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } + break; } - ExplainQueryPlan((pParse, 1, "UNION ALL")); - ExplainQueryPlanSetId(pParse, p); - rc = sqlite3Select(pParse, p, &dest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - if( pPrior->pLimit - && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit) - && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) - ){ - p->nSelectRow = sqlite3LogEst((u64)nLimit); - } - if( addr ){ - sqlite3VdbeJumpHere(v, addr); - } - break; - } - case TK_EXCEPT: - case TK_UNION: { - int unionTab; /* Cursor number of the temporary table holding result */ - u8 op = 0; /* One of the SRT_ operations to apply to self */ - int priorOp; /* The SRT_ operation to apply to prior selects */ - Expr *pLimit; /* Saved values of p->nLimit */ - int addr; - SelectDest uniondest; - - testcase( p->op==TK_EXCEPT ); - testcase( p->op==TK_UNION ); - priorOp = SRT_Union; - if( dest.eDest==priorOp ){ - /* We can reuse a temporary table generated by a SELECT to our - ** right. + case TK_EXCEPT: + case TK_UNION: { + int unionTab; /* Cursor number of the temp table holding result */ + u8 op = 0; /* One of the SRT_ operations to apply to self */ + int priorOp; /* The SRT_ operation to apply to prior selects */ + Expr *pLimit; /* Saved values of p->nLimit */ + int addr; + SelectDest uniondest; + + testcase( p->op==TK_EXCEPT ); + testcase( p->op==TK_UNION ); + priorOp = SRT_Union; + if( dest.eDest==priorOp ){ + /* We can reuse a temporary table generated by a SELECT to our + ** right. + */ + assert( p->pLimit==0 ); /* Not allowed on leftward elements */ + unionTab = dest.iSDParm; + }else{ + /* We will need to create our own temporary table to hold the + ** intermediate results. + */ + unionTab = pParse->nTab++; + assert( p->pOrderBy==0 ); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); + } + + /* Code the SELECT statements to our left */ - assert( p->pLimit==0 ); /* Not allowed on leftward elements */ - unionTab = dest.iSDParm; - }else{ - /* We will need to create our own temporary table to hold the - ** intermediate results. + assert( !pPrior->pOrderBy ); + sqlite3SelectDestInit(&uniondest, priorOp, unionTab); + rc = sqlite3Select(pParse, pPrior, &uniondest); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT statement */ - unionTab = pParse->nTab++; + if( p->op==TK_EXCEPT ){ + op = SRT_Except; + }else{ + assert( p->op==TK_UNION ); + op = SRT_Union; + } + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + uniondest.eDest = op; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + selectOpName(p->op))); + ExplainQueryPlanSetId(pParse, p); + rc = sqlite3Select(pParse, p, &uniondest); + testcase( rc!=SQLITE_OK ); + /* Query flattening in sqlite3Select() might refill p->pOrderBy. + ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ + sqlite3ExprListDelete(db, p->pOrderBy); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->pOrderBy = 0; + if( p->op==TK_UNION ){ + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + } + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + p->iLimit = 0; + p->iOffset = 0; + + /* Convert the data in the temporary table into whatever form + ** it is that we currently need. + */ + assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); + if( dest.eDest!=priorOp ){ + int iCont, iBreak, iStart; + assert( p->pEList ); + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); + iStart = sqlite3VdbeCurrentAddr(v); + selectInnerLoop(pParse, p, unionTab, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + } + break; + } + default: assert( p->op==TK_INTERSECT ); { + int tab1, tab2; + int iCont, iBreak, iStart; + Expr *pLimit; + int addr; + SelectDest intersectdest; + int r1; + + /* INTERSECT is different from the others since it requires + ** two temporary tables. Hence it has its own case. Begin + ** by allocating the tables we will need. + */ + tab1 = pParse->nTab++; + tab2 = pParse->nTab++; assert( p->pOrderBy==0 ); - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); assert( p->addrOpenEphm[0] == -1 ); p->addrOpenEphm[0] = addr; findRightmost(p)->selFlags |= SF_UsesEphemeral; assert( p->pEList ); - } - - /* Code the SELECT statements to our left - */ - assert( !pPrior->pOrderBy ); - sqlite3SelectDestInit(&uniondest, priorOp, unionTab); - rc = sqlite3Select(pParse, pPrior, &uniondest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT statement - */ - if( p->op==TK_EXCEPT ){ - op = SRT_Except; - }else{ - assert( p->op==TK_UNION ); - op = SRT_Union; - } - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - uniondest.eDest = op; - ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", - selectOpName(p->op))); - ExplainQueryPlanSetId(pParse, p); - rc = sqlite3Select(pParse, p, &uniondest); - testcase( rc!=SQLITE_OK ); - /* Query flattening in sqlite3Select() might refill p->pOrderBy. - ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ - sqlite3ExprListDelete(db, p->pOrderBy); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->pOrderBy = 0; - if( p->op==TK_UNION ){ - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - } - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - p->iLimit = 0; - p->iOffset = 0; - - /* Convert the data in the temporary table into whatever form - ** it is that we currently need. - */ - assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); - if( dest.eDest!=priorOp ){ - int iCont, iBreak, iStart; + + /* Code the SELECTs to our left into temporary table "tab1". + */ + sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); + rc = sqlite3Select(pParse, pPrior, &intersectdest); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT into temporary table "tab2" + */ + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + intersectdest.iSDParm = tab2; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + selectOpName(p->op))); + ExplainQueryPlanSetId(pParse, p); + rc = sqlite3Select(pParse, p, &intersectdest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + if( p->nSelectRow>pPrior->nSelectRow ){ + p->nSelectRow = pPrior->nSelectRow; + } + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + + /* Generate code to take the intersection of the two temporary + ** tables. + */ assert( p->pEList ); iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); - iStart = sqlite3VdbeCurrentAddr(v); - selectInnerLoop(pParse, p, unionTab, + sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); + r1 = sqlite3GetTempReg(pParse); + iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); + sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); + VdbeCoverage(v); + sqlite3ReleaseTempReg(pParse, r1); + selectInnerLoop(pParse, p, tab1, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); + sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); + break; } - break; } - default: assert( p->op==TK_INTERSECT ); { - int tab1, tab2; - int iCont, iBreak, iStart; - Expr *pLimit; - int addr; - SelectDest intersectdest; - int r1; - - /* INTERSECT is different from the others since it requires - ** two temporary tables. Hence it has its own case. Begin - ** by allocating the tables we will need. - */ - tab1 = pParse->nTab++; - tab2 = pParse->nTab++; - assert( p->pOrderBy==0 ); - - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); - assert( p->addrOpenEphm[0] == -1 ); - p->addrOpenEphm[0] = addr; - findRightmost(p)->selFlags |= SF_UsesEphemeral; - assert( p->pEList ); - - /* Code the SELECTs to our left into temporary table "tab1". - */ - sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); - rc = sqlite3Select(pParse, pPrior, &intersectdest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT into temporary table "tab2" - */ - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); - assert( p->addrOpenEphm[1] == -1 ); - p->addrOpenEphm[1] = addr; - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - intersectdest.iSDParm = tab2; - ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", - selectOpName(p->op))); - ExplainQueryPlanSetId(pParse, p); - rc = sqlite3Select(pParse, p, &intersectdest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - - /* Generate code to take the intersection of the two temporary - ** tables. - */ - assert( p->pEList ); - iBreak = sqlite3VdbeMakeLabel(v); - iCont = sqlite3VdbeMakeLabel(v); - computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); - r1 = sqlite3GetTempReg(pParse); - iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); - sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); - sqlite3ReleaseTempReg(pParse, r1); - selectInnerLoop(pParse, p, tab1, - 0, 0, &dest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); - sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); - sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); - break; + + #ifndef SQLITE_OMIT_EXPLAIN + if( p->pNext==0 ){ + ExplainQueryPlanPop(pParse); } + #endif } - -#ifndef SQLITE_OMIT_EXPLAIN - if( p->pNext==0 ){ - ExplainQueryPlanPop(pParse); - } -#endif - + /* Compute collating sequences used by ** temporary tables needed to implement the compound select. ** Attach the KeyInfo structure to all temporary tables. @@ -5566,7 +5572,7 @@ int sqlite3Select( VdbeComment((v, "%s", pItem->pTab->zName)); pItem->addrFillSub = addrTop; sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); - ExplainQueryPlan((pParse, 1, "CO-ROUTINE %p", pSub)); + ExplainQueryPlan((pParse, 1, "CO-ROUTINE 0x%p", pSub)); ExplainQueryPlanSetId(pParse, pSub); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowLogEst = pSub->nSelectRow; @@ -5606,7 +5612,7 @@ int sqlite3Select( pSub->nSelectRow = pPrior->pSelect->nSelectRow; }else{ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); - ExplainQueryPlan((pParse, 1, "MATERIALIZE %p", pSub)); + ExplainQueryPlan((pParse, 1, "MATERIALIZE 0x%p", pSub)); ExplainQueryPlanSetId(pParse,pSub); sqlite3Select(pParse, pSub, &dest); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f313baaec7..74a08c0308 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2823,8 +2823,7 @@ struct Select { #define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */ #define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */ #define SF_IncludeHidden 0x20000 /* Include hidden columns in output */ -#define SF_ComplexResult 0x40000 /* Result set contains subquery or function */ - +#define SF_ComplexResult 0x40000 /* Result contains subquery or function */ /* ** The results of a SELECT can be distributed in several ways, as defined diff --git a/src/wherecode.c b/src/wherecode.c index c1987d6b08..7f9933fad8 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -152,7 +152,7 @@ int sqlite3WhereExplainOneScan( sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); if( pItem->pSelect ){ - sqlite3XPrintf(&str, " SUBQUERY %p", pItem->pSelect); + sqlite3XPrintf(&str, " SUBQUERY 0x%p", pItem->pSelect); }else{ sqlite3XPrintf(&str, " TABLE %s", pItem->zName); } diff --git a/test/analyze3.test b/test/analyze3.test index 3e721a0877..b7b324a868 100644 --- a/test/analyze3.test +++ b/test/analyze3.test @@ -118,10 +118,10 @@ do_execsql_test analyze3-1.1.x { # do_eqp_test analyze3-1.1.2 { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x? AND x0 AND x<1100 -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} # 2017-06-26: Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables # the use of bound parameters by STAT4 @@ -131,27 +131,27 @@ unset -nocomplain l unset -nocomplain u do_eqp_test analyze3-1.1.3.100 { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x? AND x$l AND x<$u -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x? AND x$l AND x<$u -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} db cache flush sqlite3_db_config db ENABLE_QPSG 1 do_eqp_test analyze3-1.1.3.103 { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x? AND x$l AND x<$u -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} do_test analyze3-1.1.4 { sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 } @@ -201,10 +201,10 @@ do_execsql_test analyze3-2.1.x { } {200 990} do_eqp_test analyze3-1.2.2 { SELECT sum(y) FROM t2 WHERE x>1 AND x<2 -} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x? AND x0 AND x<99 -} {0 0 0 {SCAN TABLE t2}} +} {SCAN TABLE t2} do_test analyze3-1.2.4 { sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 } @@ -253,10 +253,10 @@ do_execsql_test analyze3-1.3.x { } {99 1000} do_eqp_test analyze3-1.3.2 { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 -} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x? AND x0 AND x<1100 -} {0 0 0 {SCAN TABLE t3}} +} {SCAN TABLE t3} do_test analyze3-1.3.4 { sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 } @@ -308,10 +308,10 @@ do_test analyze3-2.1 { } {} do_eqp_test analyze3-2.2 { SELECT count(a) FROM t1 WHERE b LIKE 'a%' -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b? AND b 'w' AND c = 13; -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}} +} {SEARCH TABLE t1 USING INDEX i2 (c=?)} #----------------------------------------------------------------------------- # 2015-04-20. diff --git a/test/analyze9.test b/test/analyze9.test index 7c69806f89..75a02653d1 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -987,7 +987,8 @@ do_eqp_test 21.3 { reset_db do_execsql_test 22.0 { CREATE TABLE t3(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID; -} + SELECT * FROM t3; +} {} do_execsql_test 22.1 { WITH r(x) AS ( SELECT 1 @@ -1055,15 +1056,11 @@ do_eqp_test 23.1 { -- Formerly used index i41. But i41 is not a covering index whereas -- the PRIMARY KEY is a covering index, and so as of 2017-10-15, the -- PRIMARY KEY is preferred. -} { - 0 0 0 {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a? AND b? AND b=? term. Better than # (a<20) but not as good as (a<10). do_eqp_test 25.4.1 { SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60) - } { - 0 0 0 {SEARCH TABLE t6 USING INDEX aa (a? AND b? AND b25 AND z=?; -} { - 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)} -} +} {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)} finish_test diff --git a/test/eqp.test b/test/eqp.test index c955a80c21..d25814628b 100644 --- a/test/eqp.test +++ b/test/eqp.test @@ -43,78 +43,102 @@ do_execsql_test 1.1 { do_eqp_test 1.2 { SELECT * FROM t2, t1 WHERE t1.a=1 OR t1.b=2; } { - 0 0 1 {SEARCH TABLE t1 USING INDEX i1 (a=?)} - 0 0 1 {SEARCH TABLE t1 USING INDEX i2 (b=?)} - 0 1 0 {SCAN TABLE t2} + QUERY PLAN + |--SEARCH TABLE t1 USING INDEX i1 (a=?) + |--SEARCH TABLE t1 USING INDEX i2 (b=?) + `--SCAN TABLE t2 } do_eqp_test 1.3 { SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2; } { - 0 0 0 {SCAN TABLE t2} - 0 1 1 {SEARCH TABLE t1 USING INDEX i1 (a=?)} - 0 1 1 {SEARCH TABLE t1 USING INDEX i2 (b=?)} + QUERY PLAN + |--SCAN TABLE t2 + |--SEARCH TABLE t1 USING INDEX i1 (a=?) + `--SEARCH TABLE t1 USING INDEX i2 (b=?) } do_eqp_test 1.3 { SELECT a FROM t1 ORDER BY a } { - 0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1} + QUERY PLAN + `--SCAN TABLE t1 USING COVERING INDEX i1 } do_eqp_test 1.4 { SELECT a FROM t1 ORDER BY +a } { - 0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE t1 USING COVERING INDEX i1 + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 1.5 { SELECT a FROM t1 WHERE a=4 } { - 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)} + QUERY PLAN + `--SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) } do_eqp_test 1.6 { SELECT DISTINCT count(*) FROM t3 GROUP BY a; } { - 0 0 0 {SCAN TABLE t3} - 0 0 0 {USE TEMP B-TREE FOR GROUP BY} - 0 0 0 {USE TEMP B-TREE FOR DISTINCT} + QUERY PLAN + |--SCAN TABLE t3 + |--USE TEMP B-TREE FOR GROUP BY + `--USE TEMP B-TREE FOR DISTINCT } do_eqp_test 1.7 { SELECT * FROM t3 JOIN (SELECT 1) } { - 0 0 1 {SCAN SUBQUERY 1} - 0 1 0 {SCAN TABLE t3} + QUERY PLAN + |--MATERIALIZE xxxxxx + |--SCAN SUBQUERY xxxxxx + `--SCAN TABLE t3 } do_eqp_test 1.8 { SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2) } { - 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)} - 0 0 1 {SCAN SUBQUERY 1} - 0 1 0 {SCAN TABLE t3} + QUERY PLAN + |--MATERIALIZE xxxxxx + | `--COMPOUND QUERY + | |--LEFT-MOST SUBQUERY + | `--UNION USING TEMP B-TREE + |--SCAN SUBQUERY xxxxxx + `--SCAN TABLE t3 } do_eqp_test 1.9 { SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17) } { - 3 0 0 {SCAN TABLE t3} - 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)} - 0 0 1 {SCAN SUBQUERY 1} - 0 1 0 {SCAN TABLE t3} + QUERY PLAN + |--MATERIALIZE xxxxxx + | `--COMPOUND QUERY + | |--LEFT-MOST SUBQUERY + | `--EXCEPT USING TEMP B-TREE + | `--SCAN TABLE t3 + |--SCAN SUBQUERY xxxxxx + `--SCAN TABLE t3 } do_eqp_test 1.10 { SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17) } { - 3 0 0 {SCAN TABLE t3} - 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)} - 0 0 1 {SCAN SUBQUERY 1} - 0 1 0 {SCAN TABLE t3} + QUERY PLAN + |--MATERIALIZE xxxxxx + | `--COMPOUND QUERY + | |--LEFT-MOST SUBQUERY + | `--INTERSECT USING TEMP B-TREE + | `--SCAN TABLE t3 + |--SCAN SUBQUERY xxxxxx + `--SCAN TABLE t3 } do_eqp_test 1.11 { SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17) } { - 3 0 0 {SCAN TABLE t3} - 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)} - 0 0 1 {SCAN SUBQUERY 1} - 0 1 0 {SCAN TABLE t3} + QUERY PLAN + |--MATERIALIZE xxxxxx + | `--COMPOUND QUERY + | |--LEFT-MOST SUBQUERY + | `--UNION ALL + | `--SCAN TABLE t3 + |--SCAN SUBQUERY xxxxxx + `--SCAN TABLE t3 } #------------------------------------------------------------------------- @@ -129,48 +153,58 @@ do_execsql_test 2.1 { } det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {USE TEMP B-TREE FOR GROUP BY} - 0 0 0 {USE TEMP B-TREE FOR DISTINCT} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE t1 + |--USE TEMP B-TREE FOR GROUP BY + |--USE TEMP B-TREE FOR DISTINCT + `--USE TEMP B-TREE FOR ORDER BY } det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" { - 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} - 0 0 0 {USE TEMP B-TREE FOR DISTINCT} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE t2 USING COVERING INDEX t2i1 + |--USE TEMP B-TREE FOR DISTINCT + `--USE TEMP B-TREE FOR ORDER BY } det 2.2.3 "SELECT DISTINCT * FROM t1" { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {USE TEMP B-TREE FOR DISTINCT} + QUERY PLAN + |--SCAN TABLE t1 + `--USE TEMP B-TREE FOR DISTINCT } det 2.2.4 "SELECT DISTINCT * FROM t1, t2" { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SCAN TABLE t2} - 0 0 0 {USE TEMP B-TREE FOR DISTINCT} + QUERY PLAN + |--SCAN TABLE t1 + |--SCAN TABLE t2 + `--USE TEMP B-TREE FOR DISTINCT } det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SCAN TABLE t2} - 0 0 0 {USE TEMP B-TREE FOR DISTINCT} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE t1 + |--SCAN TABLE t2 + |--USE TEMP B-TREE FOR DISTINCT + `--USE TEMP B-TREE FOR ORDER BY } det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" { - 0 0 1 {SCAN TABLE t2 USING COVERING INDEX t2i1} - 0 1 0 {SCAN TABLE t1} + QUERY PLAN + |--SCAN TABLE t2 USING COVERING INDEX t2i1 + `--SCAN TABLE t1 } det 2.3.1 "SELECT max(x) FROM t2" { - 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1} + QUERY PLAN + `--SEARCH TABLE t2 USING COVERING INDEX t2i1 } det 2.3.2 "SELECT min(x) FROM t2" { - 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1} + QUERY PLAN + `--SEARCH TABLE t2 USING COVERING INDEX t2i1 } det 2.3.3 "SELECT min(x), max(x) FROM t2" { - 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} + QUERY PLAN + `--SCAN TABLE t2 USING COVERING INDEX t2i1 } det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" { - 0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + `--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) } @@ -181,40 +215,46 @@ det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" { do_eqp_test 3.1.1 { SELECT (SELECT x FROM t1 AS sub) FROM t1; } { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {EXECUTE SCALAR SUBQUERY 1} - 1 0 0 {SCAN TABLE t1 AS sub} + QUERY PLAN + |--SCAN TABLE t1 + `--SCALAR SUBQUERY + `--SCAN TABLE t1 AS sub } do_eqp_test 3.1.2 { SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub); } { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {EXECUTE SCALAR SUBQUERY 1} - 1 0 0 {SCAN TABLE t1 AS sub} + QUERY PLAN + |--SCAN TABLE t1 + `--SCALAR SUBQUERY + `--SCAN TABLE t1 AS sub } do_eqp_test 3.1.3 { SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y); } { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {EXECUTE SCALAR SUBQUERY 1} - 1 0 0 {SCAN TABLE t1 AS sub} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE t1 + `--SCALAR SUBQUERY + |--SCAN TABLE t1 AS sub + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 3.1.4 { SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x); } { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {EXECUTE SCALAR SUBQUERY 1} - 1 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} + QUERY PLAN + |--SCAN TABLE t1 + `--SCALAR SUBQUERY + `--SCAN TABLE t2 USING COVERING INDEX t2i1 } det 3.2.1 { SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 0 0 0 {SCAN SUBQUERY 1} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--CO-ROUTINE xxxxxx + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + |--SCAN SUBQUERY xxxxxx + `--USE TEMP B-TREE FOR ORDER BY } det 3.2.2 { SELECT * FROM @@ -222,34 +262,40 @@ det 3.2.2 { (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2 ORDER BY x2.y LIMIT 5 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 2 0 0 {SCAN TABLE t2 USING INDEX t2i1} - 0 0 0 {SCAN SUBQUERY 1 AS x1} - 0 1 1 {SCAN SUBQUERY 2 AS x2} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--MATERIALIZE xxxxxx + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + |--MATERIALIZE xxxxxx + | `--SCAN TABLE t2 USING INDEX t2i1 + |--SCAN SUBQUERY xxxxxx AS x1 + |--SCAN SUBQUERY xxxxxx AS x2 + `--USE TEMP B-TREE FOR ORDER BY } det 3.3.1 { SELECT * FROM t1 WHERE y IN (SELECT y FROM t2) } { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {EXECUTE LIST SUBQUERY 1} - 1 0 0 {SCAN TABLE t2} + QUERY PLAN + |--SCAN TABLE t1 + `--LIST SUBQUERY + `--SCAN TABLE t2 } det 3.3.2 { SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x) } { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1} - 1 0 0 {SCAN TABLE t2} + QUERY PLAN + |--SCAN TABLE t1 + `--CORRELATED LIST SUBQUERY + `--SCAN TABLE t2 } det 3.3.3 { SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x) } { - 0 0 0 {SCAN TABLE t1} - 0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 1} - 1 0 0 {SCAN TABLE t2} + QUERY PLAN + |--SCAN TABLE t1 + `--CORRELATED SCALAR SUBQUERY + `--SCAN TABLE t2 } #------------------------------------------------------------------------- @@ -258,119 +304,158 @@ det 3.3.3 { do_eqp_test 4.1.1 { SELECT * FROM t1 UNION ALL SELECT * FROM t2 } { - 1 0 0 {SCAN TABLE t1} - 2 0 0 {SCAN TABLE t2} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)} + QUERY PLAN + `--COMPOUND QUERY + |--LEFT-MOST SUBQUERY + | `--SCAN TABLE t1 + `--UNION ALL + `--SCAN TABLE t2 } do_eqp_test 4.1.2 { SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 2 0 0 {SCAN TABLE t2} - 2 0 0 {USE TEMP B-TREE FOR ORDER BY} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)} + QUERY PLAN + `--MERGE (UNION ALL) + |--LEFT + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + `--RIGHT + |--SCAN TABLE t2 + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 4.1.3 { SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 2 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 2 0 0 {SCAN TABLE t2} - 2 0 0 {USE TEMP B-TREE FOR ORDER BY} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)} + QUERY PLAN + `--MERGE (UNION) + |--LEFT + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + `--RIGHT + |--SCAN TABLE t2 + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 4.1.4 { SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 2 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 2 0 0 {SCAN TABLE t2} - 2 0 0 {USE TEMP B-TREE FOR ORDER BY} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)} + QUERY PLAN + `--MERGE (INTERSECT) + |--LEFT + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + `--RIGHT + |--SCAN TABLE t2 + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 4.1.5 { SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 2 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 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)} + QUERY PLAN + `--MERGE (EXCEPT) + |--LEFT + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + `--RIGHT + |--SCAN TABLE t2 + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 4.2.2 { SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 1 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 2 0 0 {SCAN TABLE t2 USING INDEX t2i1} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)} + QUERY PLAN + `--MERGE (UNION ALL) + |--LEFT + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + `--RIGHT + `--SCAN TABLE t2 USING INDEX t2i1 } do_eqp_test 4.2.3 { SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 2 0 0 {SCAN TABLE t2 USING INDEX t2i1} - 2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)} + QUERY PLAN + `--MERGE (UNION) + |--LEFT + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + `--RIGHT + |--SCAN TABLE t2 USING INDEX t2i1 + `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_eqp_test 4.2.4 { SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 2 0 0 {SCAN TABLE t2 USING INDEX t2i1} - 2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)} + QUERY PLAN + `--MERGE (INTERSECT) + |--LEFT + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + `--RIGHT + |--SCAN TABLE t2 USING INDEX t2i1 + `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_eqp_test 4.2.5 { SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1 } { - 1 0 0 {SCAN TABLE t1} - 1 0 0 {USE TEMP B-TREE FOR ORDER BY} - 2 0 0 {SCAN TABLE t2 USING INDEX t2i1} - 2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)} + QUERY PLAN + `--MERGE (EXCEPT) + |--LEFT + | |--SCAN TABLE t1 + | `--USE TEMP B-TREE FOR ORDER BY + `--RIGHT + |--SCAN TABLE t2 USING INDEX t2i1 + `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_eqp_test 4.3.1 { SELECT x FROM t1 UNION SELECT x FROM t2 } { - 1 0 0 {SCAN TABLE t1} - 2 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)} + QUERY PLAN + `--COMPOUND QUERY + |--LEFT-MOST SUBQUERY + | `--SCAN TABLE t1 + `--UNION USING TEMP B-TREE + `--SCAN TABLE t2 USING COVERING INDEX t2i1 } do_eqp_test 4.3.2 { SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 } { - 2 0 0 {SCAN TABLE t1} - 3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} - 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)} - 4 0 0 {SCAN TABLE t1} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 4 USING TEMP B-TREE (UNION)} + QUERY PLAN + `--COMPOUND QUERY + |--LEFT-MOST SUBQUERY + | `--SCAN TABLE t1 + |--UNION USING TEMP B-TREE + | `--SCAN TABLE t2 USING COVERING INDEX t2i1 + `--UNION USING TEMP B-TREE + `--SCAN TABLE t1 } do_eqp_test 4.3.3 { SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1 } { - 2 0 0 {SCAN TABLE t1} - 2 0 0 {USE TEMP B-TREE FOR ORDER BY} - 3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} - 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION)} - 4 0 0 {SCAN TABLE t1} - 4 0 0 {USE TEMP B-TREE FOR ORDER BY} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 4 (UNION)} + QUERY PLAN + `--MERGE (UNION) + |--LEFT + | `--MERGE (UNION) + | |--LEFT + | | |--SCAN TABLE t1 + | | `--USE TEMP B-TREE FOR ORDER BY + | `--RIGHT + | `--SCAN TABLE t2 USING COVERING INDEX t2i1 + `--RIGHT + |--SCAN TABLE t1 + `--USE TEMP B-TREE FOR ORDER BY } +if 0 { #------------------------------------------------------------------------- # This next block of tests verifies that the examples on the # lang_explain.html page are correct. # drop_all_tables -# EVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b +# XVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b # FROM t1 WHERE a=1; # 0|0|0|SCAN TABLE t1 # @@ -379,7 +464,7 @@ det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" { 0 0 0 {SCAN TABLE t1} } -# EVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a); +# XVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a); # sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1; # 0|0|0|SEARCH TABLE t1 USING INDEX i1 # @@ -388,7 +473,7 @@ det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" { 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)} } -# EVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b); +# XVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b); # sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1; # 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) # @@ -397,7 +482,7 @@ det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" { 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)} } -# EVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN +# XVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN # SELECT t1.*, t2.* 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 @@ -408,7 +493,7 @@ det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" { 0 1 1 {SCAN TABLE t2} } -# EVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN +# XVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN # SELECT t1.*, t2.* 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 @@ -418,7 +503,7 @@ det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" { 0 1 0 {SCAN TABLE t2} } -# EVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b); +# XVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b); # sqlite> EXPLAIN QUERY PLAN SELECT * 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=?) @@ -429,7 +514,7 @@ det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" { 0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)} } -# EVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN +# XVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN # SELECT c, d FROM t2 ORDER BY c; # 0|0|0|SCAN TABLE t2 # 0|0|0|USE TEMP B-TREE FOR ORDER BY @@ -439,7 +524,7 @@ det 5.7 "SELECT c, d FROM t2 ORDER BY c" { 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } -# EVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c); +# XVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c); # sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c; # 0|0|0|SCAN TABLE t2 USING INDEX i4 # @@ -448,7 +533,7 @@ det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" { 0 0 0 {SCAN TABLE t2 USING INDEX i4} } -# EVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT +# XVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT # (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2; # 0|0|0|SCAN TABLE t2 # 0|0|0|EXECUTE SCALAR SUBQUERY 1 @@ -466,7 +551,7 @@ det 5.9 { 2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)} } -# EVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN +# XVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN # SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x; # 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2 # 0|0|0|SCAN SUBQUERY 1 @@ -480,7 +565,7 @@ det 5.10 { 0 0 0 {USE TEMP B-TREE FOR GROUP BY} } -# EVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN +# XVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN # SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1; # 0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?) # 0|1|1|SCAN TABLE t1 @@ -490,7 +575,7 @@ det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" { 0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2} } -# EVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN +# XVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN # SELECT a FROM t1 UNION SELECT c FROM t2; # 1|0|0|SCAN TABLE t1 # 2|0|0|SCAN TABLE t2 @@ -502,7 +587,7 @@ det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" { 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)} } -# EVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN +# XVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN # SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1; # 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2 # 2|0|0|SCAN TABLE t2 2|0|0|USE TEMP B-TREE FOR ORDER BY @@ -515,7 +600,6 @@ det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" { 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)} } - if {![nonzero_reserved_bytes]} { #------------------------------------------------------------------------- # The following tests - eqp-6.* - test that the example C code on @@ -557,6 +641,7 @@ if {![nonzero_reserved_bytes]} { 0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT) }] } +} #------------------------------------------------------------------------- # The following tests - eqp-7.* - test that queries that use the OP_Count @@ -571,11 +656,13 @@ do_execsql_test 7.0 { } det 7.1 "SELECT count(*) FROM t1" { - 0 0 0 {SCAN TABLE t1} + QUERY PLAN + `--SCAN TABLE t1 } det 7.2 "SELECT count(*) FROM t2" { - 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1} + QUERY PLAN + `--SCAN TABLE t2 USING COVERING INDEX i1 } do_execsql_test 7.3 { @@ -593,11 +680,13 @@ db close sqlite3 db test.db det 7.4 "SELECT count(*) FROM t1" { - 0 0 0 {SCAN TABLE t1} + QUERY PLAN + `--SCAN TABLE t1 } det 7.5 "SELECT count(*) FROM t2" { - 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1} + QUERY PLAN + `--SCAN TABLE t2 USING COVERING INDEX i1 } #------------------------------------------------------------------------- @@ -612,31 +701,38 @@ do_execsql_test 8.0 { } det 8.1.1 "SELECT * FROM t2" { - 0 0 0 {SCAN TABLE t2} + QUERY PLAN + `--SCAN TABLE t2 } det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" { - 0 0 0 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?) } det 8.1.3 "SELECT count(*) FROM t2" { - 0 0 0 {SCAN TABLE t2} + QUERY PLAN + `--SCAN TABLE t2 } det 8.2.1 "SELECT * FROM t1" { - 0 0 0 {SCAN TABLE t1} + QUERY PLAN + `--SCAN TABLE t1 } det 8.2.2 "SELECT * FROM t1 WHERE b=?" { - 0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)} + QUERY PLAN + `--SEARCH TABLE t1 USING PRIMARY KEY (b=?) } det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" { - 0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)} + QUERY PLAN + `--SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?) } det 8.2.4 "SELECT count(*) FROM t1" { - 0 0 0 {SCAN TABLE t1} + QUERY PLAN + `--SCAN TABLE t1 } diff --git a/test/tester.tcl b/test/tester.tcl index 6021ce72be..3642cea47c 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -959,10 +959,81 @@ proc do_timed_execsql_test {testname sql {result {}}} { uplevel do_test [list $testname] [list "execsql_timed {$sql}"]\ [list [list {*}$result]] } -proc do_eqp_test {name sql res} { - uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res] + +# Run an EXPLAIN QUERY PLAN $sql in database "db". Then rewrite the output +# as an ASCII-art graph and return a string that is that graph. +# +# Hexadecimal literals in the output text are converted into "xxxxxx" since those +# literals are pointer values that might very from one run of the test to the +# next, yet we want the output to be consistent. +# +proc query_plan_graph {sql} { + db eval "EXPLAIN QUERY PLAN $sql" { + set dx($id) $detail + lappend cx($parent) $id + } + set a "\n QUERY PLAN\n" + append a [append_graph " " dx cx 0] + return [regsub -all { 0x[A-F0-9]+\y} $a { xxxxxx}] } +# Helper routine for [query_plan_graph SQL]: +# +# Output rows of the graph that are children of $level. +# +# prefix: Prepend to every output line +# +# dxname: Name of an array variable that stores text describe +# The description for $id is $dx($id) +# +# cxname: Name of an array variable holding children of item. +# Children of $id are $cx($id) +# +# level: Render all lines that are children of $level +# +proc append_graph {prefix dxname cxname level} { + upvar $dxname dx $cxname cx + set a "" + set x $cx($level) + set n [llength $x] + for {set i 0} {$i<$n} {incr i} { + set id [lindex $x $i] + if {$i==$n-1} { + set p1 "`--" + set p2 " " + } else { + set p1 "|--" + set p2 "| " + } + append a $prefix$p1$dx($id)\n + if {[info exists cx($id)]} { + append a [append_graph "$prefix$p2" dx cx $id] + } + } + return $a +} + +# Do an EXPLAIN QUERY PLAN test on input $sql with expected results $res +# +# If $res begins with a "\s+QUERY PLAN\n" then it is assumed to be the +# complete graph which must match the output of [query_plan_graph $sql] +# exactly. +# +# If $res does not begin with "\s+QUERY PLAN\n" then take it is a string +# that must be found somewhere in the query plan output. +# +proc do_eqp_test {name sql res} { + if {[regexp {^\s+QUERY PLAN\n} $res]} { + uplevel do_test $name [list [list query_plan_graph $sql]] [list $res] + } else { + if {[string index $res 0]!="/"} { + set res "/*$res*/" + } + uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res] + } +} + + #------------------------------------------------------------------------- # Usage: do_select_tests PREFIX ?SWITCHES? TESTLIST # From 85a40ebc03676fd5b774fad42ae7a88d419fe4dc Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 May 2018 15:00:26 +0000 Subject: [PATCH 20/60] Prevent VACUUM from running any commands in sqlite_master.sql other than CREATE statements. That is all that should be there anyhow. This fixes a problem discovered by OSSFuzz. Test cases in TH3. FossilOrigin-Name: ab0d99d0b5edece4c639baa47ce1ca2c02774cb2515e5b7f36d9bd312ccd3310 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vacuum.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index f0aff63579..866465edaf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\sthe\sxBestIndex\smethod\sof\sthe\sclosure\sextension\scausing\sit\sto\nallocate\snon-contiguous\sargvIndex\svalues\sin\ssome\scases\s(an\s"xBestIndex\nmalfunction"\serror). -D 2018-05-02T08:12:22.566 +C Prevent\sVACUUM\sfrom\srunning\sany\scommands\sin\ssqlite_master.sql\sother\sthan\nCREATE\sstatements.\s\sThat\sis\sall\sthat\sshould\sbe\sthere\sanyhow.\s\sThis\sfixes\na\sproblem\sdiscovered\sby\sOSSFuzz.\s\sTest\scases\sin\sTH3. +D 2018-05-02T15:00:26.033 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -562,7 +562,7 @@ F src/update.c 5be2f501ddc704fc04183bdb28b25eab930bb8553d973429a089ec94fa85cf2b F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 -F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5 +F src/vacuum.c 593498d6d1f1f3c5561c1476132d3b03af33881ff9f27ce4e48d4ba60be3615d F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55 F src/vdbe.h 574ce9a0d57b026fc93ac379a339b8d391977f335ab4176a7e21ba902e9184bd F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 22089ea2bbea93eb1da7f08344789a5455077169443e40025f053d2a117f1c08 -R 4366c3e52bbd0f10fc2d8dde8b988b3b -U dan -Z d8568d2c99d0406cb3f7adcc92b802b9 +P 0c67150749cb3d067e14b2dcac9c3489e0f14bd18c0387f1d9bc93d21fc96fe5 +R 05ae73916277803fcebbb023b759986c +U drh +Z 0a57dfa0969cac36c6f9349555316be2 diff --git a/manifest.uuid b/manifest.uuid index 02f59e9ef9..1f86bdd5bb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c67150749cb3d067e14b2dcac9c3489e0f14bd18c0387f1d9bc93d21fc96fe5 \ No newline at end of file +ab0d99d0b5edece4c639baa47ce1ca2c02774cb2515e5b7f36d9bd312ccd3310 \ No newline at end of file diff --git a/src/vacuum.c b/src/vacuum.c index c7a14a675d..103aee0bd4 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -247,7 +247,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ rc = execSqlF(db, pzErrMsg, "SELECT sql FROM \"%w\".sqlite_master" " WHERE type='table'AND name<>'sqlite_sequence'" - " AND coalesce(rootpage,1)>0", + " AND coalesce(rootpage,1)>0 AND sql LIKE 'CREATE%%'", zDbMain ); if( rc!=SQLITE_OK ) goto end_of_vacuum; From 84a01debf9cd527e422d4bc3cbd0149b8a3b9e34 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 May 2018 16:13:48 +0000 Subject: [PATCH 21/60] Improved EQP output for recursive CTEs and multi-value VALUES clauses. FossilOrigin-Name: f2f525548c65f89f55cbe91da8a21512dedc6f7b68b58b7906d653e800a2963a --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 5 +++++ src/where.c | 1 + 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index c23605c90a..bc6fd620e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sdangling-else\sproblem\sthat\swas\scausing\srecursive\sCTEs\sto\smalfunction.\nBegin\sfixing\stest\scases\sto\swork\swith\sthe\snew\sEQP\soutput. -D 2018-05-02T14:24:34.656 +C Improved\sEQP\soutput\sfor\srecursive\sCTEs\sand\smulti-value\sVALUES\sclauses. +D 2018-05-02T16:13:48.365 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -493,7 +493,7 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c e66bb89e00608e50fa03939d5d86213a302487e8b78e0960b646be9ea0ac2f3e +F src/select.c 29294be54b5ef53e3359d37b394dc0077f5a594f9d07f06c5eabd1e3830abd9f F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -577,7 +577,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0 F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f -F src/where.c 7a1c5555c00bcf49c677472ae83bb49bf24c8d8e9a060d475e86dee39be2fb3a +F src/where.c aa94ef44ef36763817ca952e68c03db7eee5e2d4f1f0c3a98823a58c074157bd F src/whereInt.h 2610cb87dd95509995b63decc674c60f2757697a206cfe0c085ee53d9c43cfff F src/wherecode.c 3368f0797a4b166e0773a4137d270d92ddcbce91618b11d1e9f11f7c39f33068 F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 699a77e479010a331b0423f157a2fbfc373688e3d0d04ae5e64376c00cb3d488 -R 5835567753900691e5cf824409193ffc +P 82ca44b82fed6814c84440ba8bfaa019488ab956e84ac165180e2fcece6facb2 +R 3f4d92e6f36c13f28acf97e5748fc904 U drh -Z eb3edd9f2f9ef18dad6eafce24ad9bb2 +Z d63cca701f2753aa768f8453fb7efc49 diff --git a/manifest.uuid b/manifest.uuid index 92377ae8f2..ef75472325 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -82ca44b82fed6814c84440ba8bfaa019488ab956e84ac165180e2fcece6facb2 \ No newline at end of file +f2f525548c65f89f55cbe91da8a21512dedc6f7b68b58b7906d653e800a2963a \ No newline at end of file diff --git a/src/select.c b/src/select.c index d9b80f6080..76dfef912a 100644 --- a/src/select.c +++ b/src/select.c @@ -2290,6 +2290,8 @@ static void generateWithRecursiveQuery( /* Store the results of the setup-query in Queue. */ pSetup->pNext = 0; + ExplainQueryPlan((pParse, 1, "SETUP")); + ExplainQueryPlanSetId(pParse, pSetup); rc = sqlite3Select(pParse, pSetup, &destQueue); pSetup->pNext = p; if( rc ) goto end_of_recursive_query; @@ -2324,6 +2326,8 @@ static void generateWithRecursiveQuery( sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); }else{ p->pPrior = 0; + ExplainQueryPlan((pParse, 1, "RECURSIVE STEP")); + ExplainQueryPlanSetId(pParse, p); sqlite3Select(pParse, p, &destQueue); assert( p->pPrior==0 ); p->pPrior = pSetup; @@ -2383,6 +2387,7 @@ static int multiSelectValues( p = p->pPrior; nRow++; }while(1); + ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROWS", nRow)); while( p ){ pPrior = p->pPrior; p->pPrior = 0; diff --git a/src/where.c b/src/where.c index 1d4fa7b4b9..d76d9f81e2 100644 --- a/src/where.c +++ b/src/where.c @@ -4592,6 +4592,7 @@ WhereInfo *sqlite3WhereBegin( if( wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } + ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); }else{ /* Assign a bit from the bitmask to every term in the FROM clause. ** From b3f0276b9e4fd6465aaefa6e527d3f7a19a59b8c Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 May 2018 18:00:17 +0000 Subject: [PATCH 22/60] Fix test cases so that they work with the new EXPLAIN QUERY PLAN output format. Only some of the cases have been fixed. This is an incremental check-in. FossilOrigin-Name: 5f0e803e33aa557865d5fc830d9202d628de9a94c9757058ca48f1a560702cd3 --- ext/fts5/test/fts5plan.test | 27 ++++--- manifest | 92 +++++++++++----------- manifest.uuid | 2 +- src/where.c | 2 +- test/analyzeA.test | 16 ++-- test/analyzeD.test | 16 +--- test/analyzeF.test | 4 +- test/autoindex3.test | 5 +- test/bestindex1.test | 25 +++--- test/bestindex2.test | 43 +++++----- test/bestindex3.test | 23 +++--- test/bigmmap.test | 12 +-- test/cost.test | 84 +++++++++----------- test/coveridxscan.test | 9 +-- test/fts3join.test | 8 +- test/fts3query.test | 20 +++-- test/index6.test | 5 +- test/index7.test | 5 +- test/indexedby.test | 151 ++++++++++++++++++------------------ test/indexexpr2.test | 18 +++-- test/join2.test | 47 +++++------ test/join5.test | 13 ++-- test/mallocK.test | 9 ++- test/orderby1.test | 5 +- test/rollback2.test | 4 +- test/rowvalue.test | 10 +-- test/rowvalue4.test | 88 ++++++++++----------- test/scanstatus.test | 12 +-- test/selectA.test | 13 ++-- test/skipscan2.test | 2 +- test/skipscan6.test | 13 +--- test/tkt-385a5b56b9.test | 21 +++-- test/tkt-b75a9ca6b0.test | 22 +++--- test/tpch01.test | 12 ++- test/unordered.test | 29 ++++--- test/where7.test | 13 ++-- test/where9.test | 77 +++++++++--------- test/whereG.test | 20 ++--- test/whereI.test | 10 ++- test/whereJ.test | 8 +- test/with1.test | 12 ++- test/with3.test | 48 +++++++----- test/without_rowid1.test | 12 +-- 43 files changed, 527 insertions(+), 540 deletions(-) diff --git a/ext/fts5/test/fts5plan.test b/ext/fts5/test/fts5plan.test index a7b70f5b73..de6ab90761 100644 --- a/ext/fts5/test/fts5plan.test +++ b/ext/fts5/test/fts5plan.test @@ -29,38 +29,37 @@ do_execsql_test 1.0 { do_eqp_test 1.1 { SELECT * FROM t1, f1 WHERE f1 MATCH t1.x } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:} + QUERY PLAN + |--SCAN TABLE t1 + `--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537: } do_eqp_test 1.2 { SELECT * FROM t1, f1 WHERE f1 > t1.x } { - 0 0 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:} - 0 1 0 {SCAN TABLE t1} + QUERY PLAN + |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0: + `--SCAN TABLE t1 } do_eqp_test 1.3 { SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff } { - 0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537: + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 1.4 { SELECT * FROM f1 ORDER BY rank } { - 0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0: + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 1.5 { SELECT * FROM f1 WHERE rank MATCH ? -} { - 0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:} -} - - - +} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2: finish_test diff --git a/manifest b/manifest index bc6fd620e6..3863052746 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sEQP\soutput\sfor\srecursive\sCTEs\sand\smulti-value\sVALUES\sclauses. -D 2018-05-02T16:13:48.365 +C Fix\stest\scases\sso\sthat\sthey\swork\swith\sthe\snew\sEXPLAIN\sQUERY\sPLAN\soutput\nformat.\s\sOnly\ssome\sof\sthe\scases\shave\sbeen\sfixed.\s\sThis\sis\san\sincremental\ncheck-in. +D 2018-05-02T18:00:17.259 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -187,7 +187,7 @@ F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c27 F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1 F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b -F ext/fts5/test/fts5plan.test e30e8378441114ef6977a3dc24ecd203caa670d782124dfc9a6e9af09f7abc4d +F ext/fts5/test/fts5plan.test b932afb6248a21d2eb1696d2dc40eeb580ea1da79b383adb1a4f7d613fbdd4ec F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15 F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457 F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056 @@ -577,7 +577,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0 F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f -F src/where.c aa94ef44ef36763817ca952e68c03db7eee5e2d4f1f0c3a98823a58c074157bd +F src/where.c 8265aec8b13c19c9971b0012b004a8d18384dad619a07616c0a9f04401326451 F src/whereInt.h 2610cb87dd95509995b63decc674c60f2757697a206cfe0c085ee53d9c43cfff F src/wherecode.c 3368f0797a4b166e0773a4137d270d92ddcbce91618b11d1e9f11f7c39f33068 F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a @@ -602,12 +602,12 @@ F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82 F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54 -F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a +F test/analyzeA.test 22a892d67bd2223126335b99774cce56ba91122cfe82446d2927afc43ad667dc F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70 F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 -F test/analyzeD.test 42af58de25a6436502e43006e9e59e2d71bcb0cf +F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d -F test/analyzeF.test f423125b557f11ad71bb29765ef9c34b6dcf4ab7 +F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49 F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b @@ -628,7 +628,7 @@ F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e188 F test/autoinc.test 83aad64411583aac9ff0b629159ab4662029ab4e3f47090fce4efd132b304484 F test/autoindex1.test 788d0894aa3aee1220036d20696e98733fb7ca02265cb1e801700177120c1aeb F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df -F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972 +F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990 F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9 @@ -644,15 +644,15 @@ F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c -F test/bestindex1.test a9b831613b46baae213798cd3a71257833d5d3d2692e0e50c7ff0c3fbaeb0200 -F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060 -F test/bestindex3.test 578b6a52dab819e63f28e3640e04b32c85aed320 +F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a +F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928 +F test/bestindex3.test dfa5bcb1ae2f96463fb4106308908c8ed7348312de3519d981e632a0a2b6cd43 F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455 F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc -F test/bigmmap.test abe819e6e1ac1db0c3bfe364ff58889d96e7896b2bbc8bdf1afc77cdeb7d7a9b +F test/bigmmap.test 31dad31573638bd32de866cdefd11843f75685be4ba6aec1a47918f098f1899b F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747 F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2 F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483 @@ -723,9 +723,9 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454 F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4 F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4 F test/corruptK.test 91550557849244a9904f4e090052e3f2c1c3f1106840d58b00ffaa3a8c2d3fc0 -F test/cost.test 1eedbfd868f806f3fa08ff072b04cf270dcf61c8 +F test/cost.test dadd9905a9f34631a1821ff3d1b3e571ebad8afcd14ba0dca6d0818d9fd91237 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c -F test/coveridxscan.test b629e896b14df2f000a99b8d170d80589c46562c +F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418 @@ -893,7 +893,7 @@ F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49 F test/fts3fault.test 9fb7d6266a38806de841f7244bac1b0fe3a1477184bbb10b172d19d2ca6ad692 F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0 F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 -F test/fts3join.test 69aeb460d0ea17527a2b1b8d24ce18f29c7f207a7261867a2618f639c8020459 +F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166 F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6 F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a F test/fts3misc.test ba03a83b831555cfd18c6c862b24b70a53ce7497fe55077f7c4b7c9ce83c2eed @@ -901,7 +901,7 @@ F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905 F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2 F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce -F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170 +F test/fts3query.test ca5dffabdfe9aef2ebcc89e02ce515898f86f8c30a365283831c53e0e08e5821 F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99 F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0 F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e @@ -980,13 +980,13 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407 F test/index3.test 81bc47890b8abfb181bc35f8d10b56c069803386 F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6 F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 -F test/index6.test b4fc812290067a578b98bb2667b676db89e202a7 -F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb +F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a617d +F test/index7.test 72b59b8ddc5c13f4962886b4011eb9975014317d17ef36c6297921362fb7dd98 F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 -F test/indexedby.test faa585e315e868f09bce0eb39c41d6134649b13d2801638294d3ae616edf1609 +F test/indexedby.test 5a4a451412e3723b36214f2f98acc4ecbb7fd67fd11bbe9fa46ffb6e18cfd987 F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e -F test/indexexpr2.test 13247bac49143196556eb3f65e97ef301bd3e993f4511558b5db322ddc370ea6 +F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371 @@ -1009,10 +1009,10 @@ F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b F test/istrue.test 62372ad3ddcc5d0eb8ff9097dcb0aad8961bf1b9cb45ba634f6e284695126f9a F test/join.test 2ad9d7fe10e0cc06bc7803c22e5533be11cdadbc592f5f95d789a873b57a5a66 -F test/join2.test f5ea0fd3b0a441c8e439706339dcd17cec63a896a755c04a30bfd442ecce1190 +F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 -F test/join5.test 000a18e9ccc9fc716e550eb2337729d3aee99031d0ddd9682f6b7d73aa99b924 +F test/join5.test 196e0cbb552dd91815a43b5a26b64d40bdf9ff881c7a8413821dbd5f7154e3f8 F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4 @@ -1065,7 +1065,7 @@ F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb F test/mallocI.test 6c23a71df077fa5d387be90e7e669c5b368ca38a F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e -F test/mallocK.test 27cb5566a6e5f2d76f9d4aa2eca45524401fd61e +F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c083707ab F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134 F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f @@ -1118,7 +1118,7 @@ F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 F test/optfuzz-db01.c a0c256905c8ac79f9a5de2f374a3d9f757bef0dca2a238dc7c10cc8a38031834 F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041 F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1 -F test/orderby1.test 4d22a7c75f6a83fc1f188cc7bb5192285fdf2552 +F test/orderby1.test c4bbefbdbc0b9c6046c88d3c996ab81b41f799c0885b3e656c02f9295c4773ba F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04 F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99 F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4 @@ -1173,15 +1173,15 @@ F test/releasetest.tcl 5f15ab8056799e9a6e26a310d49236d2e774d6a30d0ec74601e18d4ce F test/resetdb.test 7fda92e443233208ec5e1825b176a9df63fb5bf962248e08b76eb4296c630cdf F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa -F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5 +F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6 F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d -F test/rowvalue.test 32861d6a933ded868035f2ec79aeb993a2a46eb7a6d282ae13415a4c2e369463 +F test/rowvalue.test ef851a80f7e6de93b51caca9e4b6b7d2dcd540bbcca7d51860e80435b8b4c0de F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256 -F test/rowvalue4.test 4b556d7de161a0dd8cff095c336e913986398bea +F test/rowvalue4.test cbd1cead27a797d11ec93301fd801c89e97eb1809b3d984b7f16a3876e362eac F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6 F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087 F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8 @@ -1197,7 +1197,7 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7 F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2 -F test/scanstatus.test 1ba0e2ee25dcd1d55ec770803b19832cffaecbf0b15d376807759ebeed3669b0 +F test/scanstatus.test d14842d0a2757ee059bcffa365746453d60952ba1077980c9a348a9fefbd232a F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38 @@ -1215,7 +1215,7 @@ F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0 F test/select7.test f659f231489349e8c5734e610803d7654207318f F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95 -F test/selectA.test 101e722370ac6e84978c2958b8931c78b10a1709 +F test/selectA.test b8a590f6493cad5b0bb4dfe1709bf7dcda0b6c40bb4caf32d1e36a89eebc8fc5 F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25 F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3 F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394 @@ -1251,10 +1251,10 @@ F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329 F test/skipscan1.test 8ab5d2c7c5cd3fe7f172d366e6e74e887cb33cb4 -F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a +F test/skipscan2.test ef143c6e4a5ba4f19c1d1e3f517811f7942bdf2142736cc568feb34e0b5fb763 F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2 -F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b +F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7 F test/snapshot.test 85735bd997a4f6d710140c28fd860519a299649f F test/snapshot2.test 925e42427e923262db63c9d7155183f889e3e99feaedec4075f659e51608344f F test/snapshot3.test 9719443594a04778861bd20d12596c5f880af177d6cd62f111da3198cafc6096 @@ -1337,7 +1337,7 @@ F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0 F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28 F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58 F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d -F test/tkt-385a5b56b9.test c0a06ada41d7f06b1686da0e718553f853771d1e +F test/tkt-385a5b56b9.test 5204a7cba0e28c99df0acbf95af5e1af4d32965a7a14de6eccebf949607618b1 F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678 F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7 F test/tkt-3a77c9714e.test b08bca26de1140bdf004a37716582a43d7bd8be8 @@ -1370,7 +1370,7 @@ F test/tkt-a8a0d2996a.test 76662ff0622c90e7ce7bbcb4d9e1129acddf877d17c3489f2da7f F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550 F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0 F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3 -F test/tkt-b75a9ca6b0.test 97cc2d5eeaf82799eb42138c0a1ff64370238ce4 +F test/tkt-b75a9ca6b0.test 1bc0381538fd21f96a10dbabc10ffc51b5b2e5f412d34bae571273ca784003d7 F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877 F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898 F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d @@ -1471,7 +1471,7 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd F test/tkt4018.test 18dbc6617f7a4b90e938d1bd6d26ad18daafaf08 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 -F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4 +F test/tpch01.test 7c4eb8cdd79c568f46d344b3e789c9fdb8a766d112871352704861f3fca32a2a F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983 F test/trace3.test 1dff966888773ff1bfea01c080caf15417892b3f998408fe920c4791f7337144 @@ -1508,7 +1508,7 @@ F test/unionvtabfault.test 26b6854d5aef9005cd630513025690bff1b7378ae9c97b81e2a3c F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264 F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2 F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 -F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8 +F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981 F test/update.test 1148de8d913e9817717990603aadeca07aab9ddbb10a30f167cbfd8d3a3ccb60 F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e F test/upsert1.test d587db593f131e112a98a05685c418e0eacc28df5905403e4ca04cd74c39a3fc @@ -1588,19 +1588,19 @@ F test/where3.test 54cdeb02157acc979de41530b804ae7b09552bf1 F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b -F test/where7.test f520bcec2c3d12dc4615623b06b2aec7c2d67e94 +F test/where7.test 9bfbfdf0ee238f15a6eea29060f4bb22e8b43b724efe67fd8bf6febfbe54429d F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f -F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2 +F test/where9.test 74f9dfddb42016d13b6ab0f6c943d7b993da9b2f7303faa2d465e02e340c2b5e F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4 F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6 F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89 -F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501 +F test/whereG.test 0158783235a6dd82fc0e37652b8522b186b9510594ac0a4bff0c4101b4396a52 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 -F test/whereI.test eab5b226bbc344ac70d7dc09b963a064860ae6d7 -F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767 +F test/whereI.test 0f30efab13000309f340cada83f5cf888814de0d056431fb2f0251a91c58becf +F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3 @@ -1611,12 +1611,12 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/with1.test ca08e291249a810a2ec9b72ceef5575e07d5925b360fcf6652ae6fe06ac4dced +F test/with1.test 6b98f6f2adef8909b171d0d1e3b0439e3f4d4b75be94533aaddf7f15fe002e16 F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab -F test/with3.test e71604a0e53cba82bc04c703987cb1d6751ec0b6 +F test/with3.test 2829c3de40a9e18d13f35f8f1670f549d26a4778acbd82a3454ad9b0a07de40b F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205 F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 -F test/without_rowid1.test 1cb47a1a5ba5b2946f18703fabf9fb2a237b0a8180538793ecbaed834d0df765 +F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid3.test 2724c787a51a5dce09d078453a758117b4b728f1 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 82ca44b82fed6814c84440ba8bfaa019488ab956e84ac165180e2fcece6facb2 -R 3f4d92e6f36c13f28acf97e5748fc904 +P f2f525548c65f89f55cbe91da8a21512dedc6f7b68b58b7906d653e800a2963a +R c2fb03c3c8d3bca714f50d297b15ed28 U drh -Z d63cca701f2753aa768f8453fb7efc49 +Z 275fa11767369a8ceab0cb6be2ece9b6 diff --git a/manifest.uuid b/manifest.uuid index ef75472325..7d9d7d3318 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f2f525548c65f89f55cbe91da8a21512dedc6f7b68b58b7906d653e800a2963a \ No newline at end of file +5f0e803e33aa557865d5fc830d9202d628de9a94c9757058ca48f1a560702cd3 \ No newline at end of file diff --git a/src/where.c b/src/where.c index d76d9f81e2..1145a554a5 100644 --- a/src/where.c +++ b/src/where.c @@ -4592,7 +4592,7 @@ WhereInfo *sqlite3WhereBegin( if( wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } - ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); + /* ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); */ }else{ /* Assign a bit from the bitmask to every term in the FROM clause. ** diff --git a/test/analyzeA.test b/test/analyzeA.test index a2da10edff..afcbe84b83 100644 --- a/test/analyzeA.test +++ b/test/analyzeA.test @@ -136,10 +136,10 @@ foreach {tn analyze_cmd} { do_eqp_test 1.$tn.2.5 { SELECT * FROM t1 WHERE b = 31 AND c = 0; - } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}} + } {SEARCH TABLE t1 USING INDEX t1b (b=?)} do_eqp_test 1.$tn.2.6 { SELECT * FROM t1 WHERE b = 125 AND c = 16; - } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?)}} + } {SEARCH TABLE t1 USING INDEX t1c (c=?)} do_execsql_test 1.$tn.3.1 { SELECT count(*) FROM t1 WHERE b BETWEEN 0 AND 50 @@ -156,31 +156,31 @@ foreach {tn analyze_cmd} { do_eqp_test 1.$tn.3.5 { SELECT * FROM t1 WHERE b BETWEEN 0 AND 50 AND c BETWEEN 0 AND 50 - } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b? AND b? AND c? AND c? AND b? AND b? AND b? AND b? AND c? AND c? AND c? AND c 34; } { - 0 0 1 {SEARCH TABLE v USING INDEX ve (e>?)} - 0 1 0 {SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)} + QUERY PLAN + |--SEARCH TABLE v USING INDEX ve (e>?) + `--SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?) } diff --git a/test/bestindex1.test b/test/bestindex1.test index 5857e7f002..1d79c73166 100644 --- a/test/bestindex1.test +++ b/test/bestindex1.test @@ -51,15 +51,11 @@ do_execsql_test 1.0 { do_eqp_test 1.1 { SELECT * FROM x1 WHERE a = 'abc' -} { - 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} -} +} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} do_eqp_test 1.2 { SELECT * FROM x1 WHERE a IN ('abc', 'def'); -} { - 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} -} +} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} #------------------------------------------------------------------------- # @@ -144,21 +140,24 @@ foreach {tn mode} { } {1 4} set plan(use) { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%' + `--USE TEMP B-TREE FOR ORDER BY } set plan(omit) { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%' + `--USE TEMP B-TREE FOR ORDER BY } set plan(use2) { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x + `--USE TEMP B-TREE FOR ORDER BY } do_eqp_test 2.2.$mode.6 { SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid - } $plan($mode) + } [string map {"\n " "\n"} $plan($mode)] } # 2016-04-09. diff --git a/test/bestindex2.test b/test/bestindex2.test index 8bc3fbc323..c17665f6f5 100644 --- a/test/bestindex2.test +++ b/test/bestindex2.test @@ -89,40 +89,40 @@ do_execsql_test 1.0 { do_eqp_test 1.1 { SELECT * FROM t1 WHERE a='abc' -} { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)} -} +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)} + do_eqp_test 1.2 { SELECT * FROM t1 WHERE a='abc' AND b='def' -} { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)} -} +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)} + do_eqp_test 1.3 { SELECT * FROM t1 WHERE a='abc' AND a='def' -} { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)} -} +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)} + do_eqp_test 1.4 { SELECT * FROM t1,t2 WHERE c=a } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} - 0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0: + `--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?) } do_eqp_test 1.5 { SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} - 0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} - 0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0: + |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?) + `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?) } do_eqp_test 1.6 { SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} - 0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} - 0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0: + |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?) + `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?) } do_execsql_test 1.7.1 { @@ -132,10 +132,11 @@ do_eqp_test 1.7.2 { SELECT * FROM x1 CROSS JOIN t1, t2, t3 WHERE t1.a = t2.c AND t1.b = t3.e } { - 0 0 0 {SCAN TABLE x1} - 0 1 1 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} - 0 2 2 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} - 0 3 3 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)} + QUERY PLAN + |--SCAN TABLE x1 + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0: + |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?) + `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?) } finish_test diff --git a/test/bestindex3.test b/test/bestindex3.test index 70c60d66dd..3e9fb4f968 100644 --- a/test/bestindex3.test +++ b/test/bestindex3.test @@ -79,28 +79,26 @@ do_execsql_test 1.0 { do_eqp_test 1.1 { SELECT * FROM t1 WHERE a LIKE 'abc'; -} { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?} -} +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?} do_eqp_test 1.2 { SELECT * FROM t1 WHERE a = 'abc'; -} { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?} -} +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?} do_eqp_test 1.3 { SELECT * FROM t1 WHERE a = 'abc' OR b = 'def'; } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?} - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ? + `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ? } do_eqp_test 1.4 { SELECT * FROM t1 WHERE a LIKE 'abc%' OR b = 'def'; } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?} - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ? + `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ? } do_execsql_test 1.5 { @@ -148,8 +146,9 @@ ifcapable !icu { do_eqp_test 2.2 { SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def' } { - 0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x>? AND x? AND x? AND b? AND b? AND x? AND x? AND b? AND b=950 AND b<=1010) OR (b IS NULL AND c NOT NULL) ORDER BY a } { - 0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b? AND b 5; EXPLAIN QUERY PLAN SELECT * FROM v2 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}} +} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/} do_execsql_test indexedby-5.2 { EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}} +} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/} do_test indexedby-5.3 { execsql { DROP INDEX i1 } catchsql { SELECT * FROM v2 } @@ -216,12 +215,12 @@ do_test indexedby-5.5 { # Test that "NOT INDEXED" may use the rowid index, but not others. # -do_execsql_test indexedby-6.1 { - EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 10 ORDER BY rowid -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}} -do_execsql_test indexedby-6.2 { - EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid -} {0 0 0 {SCAN TABLE t1}} +do_eqp_test indexedby-6.1 { + SELECT * FROM t1 WHERE b = 10 ORDER BY rowid +} {SEARCH TABLE t1 USING INDEX i2 (b=?)} +do_eqp_test indexedby-6.2 { + SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid +} {SCAN TABLE t1} # EVIDENCE-OF: R-40297-14464 The INDEXED BY phrase forces the SQLite # query planner to use a particular named index on a DELETE, SELECT, or @@ -229,44 +228,42 @@ do_execsql_test indexedby-6.2 { # # Test that "INDEXED BY" can be used in a DELETE statement. # -do_execsql_test indexedby-7.1 { - EXPLAIN QUERY PLAN DELETE FROM t1 WHERE a = 5 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}} -do_execsql_test indexedby-7.2 { - EXPLAIN QUERY PLAN DELETE FROM t1 NOT INDEXED WHERE a = 5 -} {0 0 0 {SCAN TABLE t1}} -do_execsql_test indexedby-7.3 { - EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}} -do_execsql_test indexedby-7.4 { - EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}} -do_execsql_test indexedby-7.5 { - EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}} +do_eqp_test indexedby-7.1 { + DELETE FROM t1 WHERE a = 5 +} {SEARCH TABLE t1 USING INDEX i1 (a=?)} +do_eqp_test indexedby-7.2 { + DELETE FROM t1 NOT INDEXED WHERE a = 5 +} {SCAN TABLE t1} +do_eqp_test indexedby-7.3 { + DELETE FROM t1 INDEXED BY i1 WHERE a = 5 +} {SEARCH TABLE t1 USING INDEX i1 (a=?)} +do_eqp_test indexedby-7.4 { + DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10 +} {SEARCH TABLE t1 USING INDEX i1 (a=?)} +do_eqp_test indexedby-7.5 { + DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10 +} {SEARCH TABLE t1 USING INDEX i2 (b=?)} do_test indexedby-7.6 { catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5} } {1 {no query solution}} # Test that "INDEXED BY" can be used in an UPDATE statement. # -do_execsql_test indexedby-8.1 { - EXPLAIN QUERY PLAN UPDATE t1 SET rowid=rowid+1 WHERE a = 5 -} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}} -do_execsql_test indexedby-8.2 { - EXPLAIN QUERY PLAN UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 -} {0 0 0 {SCAN TABLE t1}} -do_execsql_test indexedby-8.3 { - EXPLAIN QUERY PLAN UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 -} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}} -do_execsql_test indexedby-8.4 { - EXPLAIN QUERY PLAN +do_eqp_test indexedby-8.1 { + UPDATE t1 SET rowid=rowid+1 WHERE a = 5 +} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)} +do_eqp_test indexedby-8.2 { + UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 +} {SCAN TABLE t1} +do_eqp_test indexedby-8.3 { + UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 +} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)} +do_eqp_test indexedby-8.4 { UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}} -do_execsql_test indexedby-8.5 { - EXPLAIN QUERY PLAN +} {SEARCH TABLE t1 USING INDEX i1 (a=?)} +do_eqp_test indexedby-8.5 { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10 -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}} +} {SEARCH TABLE t1 USING INDEX i2 (b=?)} do_test indexedby-8.6 { catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5} } {1 {no query solution}} @@ -341,7 +338,7 @@ do_execsql_test 11.4 { } {1 1 3} do_eqp_test 11.5 { SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3.0'; -} {0 0 0 {SEARCH TABLE x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}} +} {SEARCH TABLE x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)} do_execsql_test 11.6 { CREATE TABLE x2(c INTEGER PRIMARY KEY, a, b TEXT); @@ -362,7 +359,7 @@ do_execsql_test 11.9 { } {1 1 3} do_eqp_test 11.10 { SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0'; -} {0 0 0 {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}} +} {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)} #------------------------------------------------------------------------- # Check INDEXED BY works (throws an exception) with partial indexes that diff --git a/test/indexexpr2.test b/test/indexexpr2.test index 037db0420a..aed887a848 100644 --- a/test/indexexpr2.test +++ b/test/indexexpr2.test @@ -91,10 +91,11 @@ ifcapable json1 { WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL GROUP BY json_extract(x, '$.b') COLLATE nocase ORDER BY json_extract(x, '$.b') COLLATE nocase; - } { - 0 0 0 {SCAN TABLE t2} - 0 0 0 {USE TEMP B-TREE FOR GROUP BY} - } + } [string map {"\n " \n} { + QUERY PLAN + |--SCAN TABLE t2 + `--USE TEMP B-TREE FOR GROUP BY + }] do_execsql_test 3.3.2 { CREATE INDEX i3 ON t3(json_extract(x, '$.a'), json_extract(x, '$.b')); @@ -105,10 +106,11 @@ ifcapable json1 { WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL GROUP BY json_extract(x, '$.b') COLLATE nocase ORDER BY json_extract(x, '$.b') COLLATE nocase; - } { - 0 0 0 {SEARCH TABLE t3 USING INDEX i3 (=?)} - 0 0 0 {USE TEMP B-TREE FOR GROUP BY} - } + } [string map {"\n " \n} { + QUERY PLAN + |--SEARCH TABLE t3 USING INDEX i3 (=?) + `--USE TEMP B-TREE FOR GROUP BY + }] } do_execsql_test 3.4.0 { diff --git a/test/join2.test b/test/join2.test index b5b9e6be10..5a70573e0e 100644 --- a/test/join2.test +++ b/test/join2.test @@ -112,15 +112,17 @@ do_execsql_test 3.0 { do_eqp_test 3.1 { SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_1 USING (k3); } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + |--SCAN TABLE t1 + `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?) } do_eqp_test 3.2 { SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_2 USING (k3); } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + |--SCAN TABLE t1 + `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?) } #------------------------------------------------------------------------- @@ -158,15 +160,17 @@ do_execsql_test 4.1.4 { do_eqp_test 4.1.5 { SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2); } { - 0 0 0 {SCAN TABLE c1} - 0 1 1 {SEARCH TABLE c2 USING INTEGER PRIMARY KEY (rowid=?)} - 0 2 2 {SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + |--SCAN TABLE c1 + |--SEARCH TABLE c2 USING INTEGER PRIMARY KEY (rowid=?) + `--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?) } do_eqp_test 4.1.6 { SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1); } { - 0 0 0 {SCAN TABLE c1} - 0 1 2 {SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + |--SCAN TABLE c1 + `--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?) } do_execsql_test 4.2.0 { @@ -203,15 +207,17 @@ do_execsql_test 4.2.4 { do_eqp_test 4.2.5 { SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2); } { - 0 0 0 {SCAN TABLE c1} - 0 1 1 {SEARCH TABLE c2 USING INDEX sqlite_autoindex_c2_1 (k=?)} - 0 2 2 {SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)} + QUERY PLAN + |--SCAN TABLE c1 + |--SEARCH TABLE c2 USING INDEX sqlite_autoindex_c2_1 (k=?) + `--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?) } do_eqp_test 4.2.6 { SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1); } { - 0 0 0 {SCAN TABLE c1} - 0 1 2 {SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)} + QUERY PLAN + |--SCAN TABLE c1 + `--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?) } # 2017-11-23 (Thanksgiving day) @@ -245,14 +251,11 @@ do_execsql_test 5.0 { } do_eqp_test 5.1 { SELECT s1.a FROM s1 left join s2 using (a); -} { - 0 0 0 {SCAN TABLE s1} -} +} {SCAN TABLE s1} + do_eqp_test 5.2 { SELECT s1.a FROM s1 left join s3 using (a); -} { - 0 0 0 {SCAN TABLE s1} -} +} {SCAN TABLE s1} do_execsql_test 6.0 { CREATE TABLE u1(a INTEGER PRIMARY KEY, b, c); @@ -261,9 +264,7 @@ do_execsql_test 6.0 { } do_eqp_test 6.1 { SELECT u2.* FROM u2 LEFT JOIN u1 ON( u1.a=u2.a AND u1.b=u2.b AND u1.c=u2.c ); -} { - 0 0 0 {SCAN TABLE u2} -} +} {SCAN TABLE u2} db close sqlite3 db :memory: diff --git a/test/join5.test b/test/join5.test index 12fe56cb92..043c626d41 100644 --- a/test/join5.test +++ b/test/join5.test @@ -264,9 +264,10 @@ do_eqp_test 7.2 { t2.x = t1.x AND (t2.y=? OR (t2.y=? AND t2.z IS NOT NULL)) ); } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)} - 0 1 1 {SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)} + QUERY PLAN + |--SCAN TABLE t1 + |--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?) + `--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?) } do_execsql_test 7.3 { @@ -285,9 +286,9 @@ do_execsql_test 7.3 { do_eqp_test 7.4 { SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?); } { - 0 0 0 {SCAN TABLE t3} - 0 1 1 {SEARCH TABLE t4 USING INDEX t4xz (x=?)} + QUERY PLAN + |--SCAN TABLE t3 + `--SEARCH TABLE t4 USING INDEX t4xz (x=?) } finish_test - diff --git a/test/mallocK.test b/test/mallocK.test index 45ee7905c3..139644d834 100644 --- a/test/mallocK.test +++ b/test/mallocK.test @@ -121,10 +121,11 @@ do_execsql_test 6.0 { ifcapable stat4 { do_eqp_test 6.1 { SELECT DISTINCT c FROM t3 WHERE b BETWEEN '.xx..' AND '.xxxx'; - } { - 0 0 0 {SEARCH TABLE t3 USING INDEX i3 (ANY(a) AND b>? AND b? AND b (2, 1)" {2 2 2 3 3 3 4 4 4} - "0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)}" + "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)" 5 "SELECT * FROM xy WHERE (i, j) > ('2', 1)" {2 2 2 3 3 3 4 4 4} - "0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)}" + "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)" } { do_eqp_test 7.$tn.1 $sql $eqp diff --git a/test/rowvalue4.test b/test/rowvalue4.test index 2e6a28c230..ce025fc923 100644 --- a/test/rowvalue4.test +++ b/test/rowvalue4.test @@ -184,34 +184,33 @@ ifcapable stat4 { ANALYZE; } - do_eqp_test 3.1.1 { SELECT * FROM c1 WHERE a=1 AND c=2 } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c=?)} - } - do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c=?)} - } - do_eqp_test 3.1.3 { SELECT * FROM c1 WHERE a=1 AND b>'l' AND c=2 } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=? AND b>?)} - } + do_eqp_test 3.1.1 { SELECT * FROM c1 WHERE a=1 AND c=2 } \ + {SEARCH TABLE c1 USING INDEX c1cd (c=?)} + + do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } \ + {SEARCH TABLE c1 USING INDEX c1cd (c=?)} + + do_eqp_test 3.1.3 { SELECT * FROM c1 WHERE a=1 AND b>'l' AND c=2 } \ + {SEARCH TABLE c1 USING INDEX c1ab (a=? AND b>?)} + + do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } \ + {SEARCH TABLE c1 USING INDEX c1cd (c>?)} + + do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } \ + {SEARCH TABLE c1 USING INDEX c1ab (a=?)} + + do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } \ + {SEARCH TABLE c1 USING INDEX c1ab (a=?)} + + do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } \ + {SEARCH TABLE c1 USING INDEX c1ab (a=?)} + + do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } \ + {SEARCH TABLE c1 USING INDEX c1cd ((c,d)>(?,?))} + + do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } \ + {SEARCH TABLE c1 USING INDEX c1ab (a=?)} - do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c>?)} - } - do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)} - } - do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)} - } - do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)} - } - do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1cd ((c,d)>(?,?))} - } - do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } { - 0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)} - } } #------------------------------------------------------------------------ @@ -234,11 +233,12 @@ do_eqp_test 5.1 { (a, b) IN (SELECT x, y FROM d1) AND (c) IN (SELECT y FROM d1) } { - 0 0 0 {SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?)} - 0 0 0 {EXECUTE LIST SUBQUERY 1} - 1 0 0 {SCAN TABLE d1} - 0 0 0 {EXECUTE LIST SUBQUERY 2} - 2 0 0 {SCAN TABLE d1} + QUERY PLAN + |--SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?) + |--LIST SUBQUERY + | `--SCAN TABLE d1 + `--LIST SUBQUERY + `--SCAN TABLE d1 } do_execsql_test 6.0 { @@ -249,31 +249,23 @@ do_execsql_test 6.0 { do_eqp_test 6.1 { SELECT * FROM e1 WHERE (a, b) > (?, ?) -} { - 0 0 0 {SEARCH TABLE e1 USING INDEX e1ab ((a,b)>(?,?))} -} +} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)>(?,?))} + do_eqp_test 6.2 { SELECT * FROM e1 WHERE (a, b) < (?, ?) -} { - 0 0 0 {SEARCH TABLE e1 USING INDEX e1ab ((a,b)<(?,?))} -} +} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)<(?,?))} + do_eqp_test 6.3 { SELECT * FROM e1 WHERE c = ? AND (d, e) > (?, ?) -} { - 0 0 0 {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))} -} +} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))} + do_eqp_test 6.4 { SELECT * FROM e1 WHERE c = ? AND (d, e) < (?, ?) -} { - 0 0 0 {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))} -} +} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))} do_eqp_test 6.5 { SELECT * FROM e1 WHERE (d, e) BETWEEN (?, ?) AND (?, ?) AND c = ? -} { - 0 0 0 - {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))} -} +} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))} #------------------------------------------------------------------------- diff --git a/test/scanstatus.test b/test/scanstatus.test index fdd6476ae9..778a0c911e 100644 --- a/test/scanstatus.test +++ b/test/scanstatus.test @@ -328,7 +328,7 @@ do_scanstatus_test 5.2.2 { do_eqp_test 5.3.1 { SELECT count(*) FROM t2 WHERE y = 'j'; -} {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}} +} {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)} do_execsql_test 5.3.2 { SELECT count(*) FROM t2 WHERE y = 'j'; } {19} @@ -340,8 +340,9 @@ do_scanstatus_test 5.3.3 { do_eqp_test 5.4.1 { SELECT count(*) FROM t1, t2 WHERE y = c; } { - 0 0 0 {SCAN TABLE t1 USING COVERING INDEX t1bc} - 0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)} + QUERY PLAN + |--SCAN TABLE t1 USING COVERING INDEX t1bc + `--SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?) } do_execsql_test 5.4.2 { SELECT count(*) FROM t1, t2 WHERE y = c; @@ -356,8 +357,9 @@ do_scanstatus_test 5.4.3 { do_eqp_test 5.5.1 { SELECT count(*) FROM t1, t3 WHERE y = c; } { - 0 0 1 {SCAN TABLE t3} - 0 1 0 {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)} + QUERY PLAN + |--SCAN TABLE t3 + `--SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?) } do_execsql_test 5.5.2 { SELECT count(*) FROM t1, t3 WHERE y = c; diff --git a/test/selectA.test b/test/selectA.test index 78d04be15d..838e5f4323 100644 --- a/test/selectA.test +++ b/test/selectA.test @@ -1336,11 +1336,14 @@ do_eqp_test 4.1.2 { SELECT a, b FROM t4 WHERE f()==f() ORDER BY 1,2 } { - 1 0 0 {SCAN TABLE t5 USING INDEX i2} - 1 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY} - 2 0 0 {SCAN TABLE t4 USING INDEX i1} - 2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY} - 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)} + QUERY PLAN + `--MERGE (UNION ALL) + |--LEFT + | |--SCAN TABLE t5 USING INDEX i2 + | `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY + `--RIGHT + |--SCAN TABLE t4 USING INDEX i1 + `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_execsql_test 4.1.3 { diff --git a/test/skipscan2.test b/test/skipscan2.test index a42ff2d057..df526b1dd3 100644 --- a/test/skipscan2.test +++ b/test/skipscan2.test @@ -199,7 +199,7 @@ do_test skipscan2-3.2 { } {} do_eqp_test skipscan2-3.3eqp { SELECT * FROM t3 WHERE b=42; -} {0 0 0 {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}} +} {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)} finish_test diff --git a/test/skipscan6.test b/test/skipscan6.test index 026c4d7b00..a53be1d952 100644 --- a/test/skipscan6.test +++ b/test/skipscan6.test @@ -179,22 +179,13 @@ do_execsql_test 3.0 { # do_eqp_test 3.1 { SELECT * FROM t3 WHERE a = ? AND c = ? -} { - 0 0 0 {SEARCH TABLE t3 USING INDEX t3_a (a=?)} -} +} {SEARCH TABLE t3 USING INDEX t3_a (a=?)} # The same query on table t2. This should use index "t2_a", for the # same reason. At one point though, it was mistakenly using a skip-scan. # do_eqp_test 3.2 { SELECT * FROM t2 WHERE a = ? AND c = ? -} { - 0 0 0 {SEARCH TABLE t2 USING INDEX t2_a (a=?)} -} - -finish_test - - - +} {SEARCH TABLE t2 USING INDEX t2_a (a=?)} finish_test diff --git a/test/tkt-385a5b56b9.test b/test/tkt-385a5b56b9.test index 1338435ed6..22a9b38daf 100644 --- a/test/tkt-385a5b56b9.test +++ b/test/tkt-385a5b56b9.test @@ -34,20 +34,17 @@ do_execsql_test 2.0 { CREATE UNIQUE INDEX t2y ON t2(y); } -do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } { - 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2x} -} +do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } \ + {SCAN TABLE t2 USING COVERING INDEX t2x} -do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } { - 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2y} -} +do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } \ + {SCAN TABLE t2 USING COVERING INDEX t2y} -do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } { - 0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?)} -} +do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } \ + {SEARCH TABLE t2 USING INDEX t2y (y=?)} + +do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } \ + {SEARCH TABLE t2 USING INDEX t2x (x=?)} -do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } { - 0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x=?)} -} finish_test diff --git a/test/tkt-b75a9ca6b0.test b/test/tkt-b75a9ca6b0.test index 0c81a534da..8fceb436c2 100644 --- a/test/tkt-b75a9ca6b0.test +++ b/test/tkt-b75a9ca6b0.test @@ -32,41 +32,41 @@ do_execsql_test 1.1 { CREATE INDEX i1 ON t1(x, y); } -set idxscan {0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}} -set tblscan {0 0 0 {SCAN TABLE t1}} -set grpsort {0 0 0 {USE TEMP B-TREE FOR GROUP BY}} -set sort {0 0 0 {USE TEMP B-TREE FOR ORDER BY}} +set idxscan {SCAN TABLE t1 USING COVERING INDEX i1} +set tblscan {SCAN TABLE t1} +set grpsort {USE TEMP B-TREE FOR GROUP BY} +set sort {USE TEMP B-TREE FOR ORDER BY} foreach {tn q res eqp} [subst -nocommands { 1 "SELECT * FROM t1 GROUP BY x, y ORDER BY x,y" {1 3 2 2 3 1} {$idxscan} 2 "SELECT * FROM t1 GROUP BY x, y ORDER BY x" - {1 3 2 2 3 1} {$idxscan $sort} + {1 3 2 2 3 1} {$idxscan*$sort} 3 "SELECT * FROM t1 GROUP BY y, x ORDER BY y, x" - {3 1 2 2 1 3} {$idxscan $sort} + {3 1 2 2 1 3} {$idxscan*$sort} 4 "SELECT * FROM t1 GROUP BY x ORDER BY x" {1 3 2 2 3 1} {$idxscan} 5 "SELECT * FROM t1 GROUP BY y ORDER BY y" - {3 1 2 2 1 3} {$tblscan $grpsort} + {3 1 2 2 1 3} {$tblscan*$grpsort} 6 "SELECT * FROM t1 GROUP BY y ORDER BY x" - {1 3 2 2 3 1} {$tblscan $grpsort $sort} + {1 3 2 2 3 1} {$tblscan*$grpsort*$sort} 7 "SELECT * FROM t1 GROUP BY x, y ORDER BY x, y DESC" - {1 3 2 2 3 1} {$idxscan $sort} + {1 3 2 2 3 1} {$idxscan*$sort} 8 "SELECT * FROM t1 GROUP BY x, y ORDER BY x DESC, y DESC" - {3 1 2 2 1 3} {$idxscan $sort} + {3 1 2 2 1 3} {$idxscan*$sort} 9 "SELECT * FROM t1 GROUP BY x, y ORDER BY x ASC, y ASC" {1 3 2 2 3 1} {$idxscan} 10 "SELECT * FROM t1 GROUP BY x, y ORDER BY x COLLATE nocase, y" - {1 3 2 2 3 1} {$idxscan $sort} + {1 3 2 2 3 1} {$idxscan*$sort} }] { do_execsql_test 1.$tn.1 $q $res diff --git a/test/tpch01.test b/test/tpch01.test index ce48f8ec23..0e51b82b08 100644 --- a/test/tpch01.test +++ b/test/tpch01.test @@ -165,7 +165,7 @@ do_test tpch01-1.1 { order by o_year;}] set ::eqpres -} {/0 0 0 {SEARCH TABLE part USING INDEX bootleg_pti .P_TYPE=..} 0 1 2 {SEARCH TABLE lineitem USING INDEX lpki2 .L_PARTKEY=..}.*/} +} {/*SEARCH TABLE part USING INDEX bootleg_pti *SEARCH TABLE lineitem USING INDEX lpki2*/} do_test tpch01-1.1b { set ::eqpres } {/.* customer .* nation AS n1 .*/} @@ -187,6 +187,14 @@ group by c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment order by revenue desc; -} {0 0 1 {SEARCH TABLE orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE? AND O_ORDERDATE 100" - {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}} - {0 0 0 {SCAN TABLE t1}} + {SEARCH TABLE t1 USING INDEX i1 (a>?)} + {SCAN TABLE t1} 3 "SELECT * FROM t1 WHERE a = ? ORDER BY rowid" - {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}} - {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY}} + {SEARCH TABLE t1 USING INDEX i1 (a=?)} + {SEARCH TABLE t1 USING INDEX i1 (a=?)*USE TEMP B-TREE FOR ORDER BY} 4 "SELECT max(a) FROM t1" - {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1}} - {0 0 0 {SEARCH TABLE t1}} + {SEARCH TABLE t1 USING COVERING INDEX i1} + {SEARCH TABLE t1} 5 "SELECT group_concat(b) FROM t1 GROUP BY a" - {0 0 0 {SCAN TABLE t1 USING INDEX i1}} - {0 0 0 {SCAN TABLE t1} 0 0 0 {USE TEMP B-TREE FOR GROUP BY}} + {SCAN TABLE t1 USING INDEX i1} + {SCAN TABLE t1*USE TEMP B-TREE FOR GROUP BY} 6 "SELECT * FROM t1 WHERE a = ?" - {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}} - {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}} + {SEARCH TABLE t1 USING INDEX i1 (a=?)} + {SEARCH TABLE t1 USING INDEX i1 (a=?)} 7 "SELECT count(*) FROM t1" - {0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}} - {0 0 0 {SCAN TABLE t1}} + {SCAN TABLE t1 USING COVERING INDEX i1} + {SCAN TABLE t1} } { do_eqp_test 1.$idxmode.$tn $sql $r($idxmode) } diff --git a/test/where7.test b/test/where7.test index 00cf5eb278..983418ae2f 100644 --- a/test/where7.test +++ b/test/where7.test @@ -23341,8 +23341,8 @@ do_execsql_test where7-3.1 { CREATE INDEX t302_c3 on t302(c3); CREATE INDEX t302_c8_c3 on t302(c8, c3); CREATE INDEX t302_c5 on t302(c5); - - EXPLAIN QUERY PLAN +} +do_eqp_test where7-3.2 { SELECT t302.c1 FROM t302 JOIN t301 ON t302.c8 = +t301.c8 WHERE t302.c2 = 19571 @@ -23351,10 +23351,11 @@ do_execsql_test where7-3.1 { OR t301.c8 = 1407424651264000) ORDER BY t302.c5 LIMIT 200; } { - 0 0 1 {SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?)} - 0 0 1 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)} - 0 1 0 {SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?) + |--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?) + |--SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?) + `--USE TEMP B-TREE FOR ORDER BY } finish_test diff --git a/test/where9.test b/test/where9.test index d073074d43..c04c17fa95 100644 --- a/test/where9.test +++ b/test/where9.test @@ -357,25 +357,25 @@ do_test where9-2.8 { ifcapable explain { - do_execsql_test where9-3.1 { - EXPLAIN QUERY PLAN + do_eqp_test where9-3.1 { SELECT t2.a FROM t1, t2 WHERE t1.a=80 AND ((t1.c=t2.c AND t1.d=t2.d) OR t1.f=t2.f) - } { - 0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)} - 0 1 1 {SEARCH TABLE t2 USING INDEX t2d (d=?)} - 0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)} - } - do_execsql_test where9-3.2 { - EXPLAIN QUERY PLAN + } [string map {"\n " \n} { + QUERY PLAN + |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) + |--SEARCH TABLE t2 USING INDEX t2d (d=?) + `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) + }] + do_eqp_test where9-3.2 { SELECT coalesce(t2.a,9999) FROM t1 LEFT JOIN t2 ON (t1.c+1=t2.c AND t1.d=t2.d) OR (t1.f||'x')=t2.f WHERE t1.a=80 - } { - 0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)} - 0 1 1 {SEARCH TABLE t2 USING INDEX t2d (d=?)} - 0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)} - } + } [string map {"\n " \n} { + QUERY PLAN + |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) + |--SEARCH TABLE t2 USING INDEX t2d (d=?) + `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) + }] } # Make sure that INDEXED BY and multi-index OR clauses play well with @@ -446,35 +446,30 @@ do_test where9-4.8 { } } {1 {no query solution}} -ifcapable explain { - # The (c=31031 OR d IS NULL) clause is preferred over b>1000 because - # the former is an equality test which is expected to return fewer rows. - # - do_execsql_test where9-5.1 { - EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL) - } { - 0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?)} - 0 0 0 {SEARCH TABLE t1 USING INDEX t1d (d=?)} - } - - # In contrast, b=1000 is preferred over any OR-clause. - # - do_execsql_test where9-5.2 { - EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b=1000 AND (c=31031 OR d IS NULL) - } { - 0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)} - } - - # Likewise, inequalities in an AND are preferred over inequalities in - # an OR. - # - do_execsql_test where9-5.3 { - EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>1000 AND (c>=31031 OR d IS NULL) - } { - 0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>?)} - } +# The (c=31031 OR d IS NULL) clause is preferred over b>1000 because +# the former is an equality test which is expected to return fewer rows. +# +do_eqp_test where9-5.1 { + SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL) +} { + QUERY PLAN + |--SEARCH TABLE t1 USING INDEX t1c (c=?) + `--SEARCH TABLE t1 USING INDEX t1d (d=?) } +# In contrast, b=1000 is preferred over any OR-clause. +# +do_eqp_test where9-5.2 { + SELECT a FROM t1 WHERE b=1000 AND (c=31031 OR d IS NULL) +} {SEARCH TABLE t1 USING INDEX t1b (b=?)} + +# Likewise, inequalities in an AND are preferred over inequalities in +# an OR. +# +do_eqp_test where9-5.3 { + SELECT a FROM t1 WHERE b>1000 AND (c>=31031 OR d IS NULL) +} {SEARCH TABLE t1 USING INDEX t1b (b>?)} + ############################################################################ # Make sure OR-clauses work correctly on UPDATE and DELETE statements. diff --git a/test/whereG.test b/test/whereG.test index 110ed5dbd4..d2e6a4ee96 100644 --- a/test/whereG.test +++ b/test/whereG.test @@ -66,7 +66,7 @@ do_eqp_test whereG-1.1 { WHERE unlikely(cname LIKE '%bach%') AND composer.cid=track.cid AND album.aid=track.aid; -} {/.*composer.*track.*album.*/} +} {composer*track*album} do_execsql_test whereG-1.2 { SELECT DISTINCT aname FROM album, composer, track @@ -195,13 +195,13 @@ do_execsql_test 5.1 { } do_eqp_test 5.1.2 { SELECT * FROM t1 WHERE a>? -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}} +} {SEARCH TABLE t1 USING INDEX i1 (a>?)} do_eqp_test 5.1.3 { SELECT * FROM t1 WHERE likelihood(a>?, 0.9) -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} do_eqp_test 5.1.4 { SELECT * FROM t1 WHERE likely(a>?) -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} do_test 5.2 { for {set i 0} {$i < 100} {incr i} { @@ -212,23 +212,23 @@ do_test 5.2 { } {} do_eqp_test 5.2.2 { SELECT * FROM t1 WHERE likelihood(b>?, 0.01) -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (ANY(a) AND b>?)}} +} {SEARCH TABLE t1 USING INDEX i1 (ANY(a) AND b>?)} do_eqp_test 5.2.3 { SELECT * FROM t1 WHERE likelihood(b>?, 0.9) -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} do_eqp_test 5.2.4 { SELECT * FROM t1 WHERE likely(b>?) -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} do_eqp_test 5.3.1 { SELECT * FROM t1 WHERE a=? -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}} +} {SEARCH TABLE t1 USING INDEX i1 (a=?)} do_eqp_test 5.3.2 { SELECT * FROM t1 WHERE likelihood(a=?, 0.9) -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} do_eqp_test 5.3.3 { SELECT * FROM t1 WHERE likely(a=?) -} {0 0 0 {SCAN TABLE t1}} +} {SCAN TABLE t1} # 2015-06-18 # Ticket [https://www.sqlite.org/see/tktview/472f0742a1868fb58862bc588ed70] diff --git a/test/whereI.test b/test/whereI.test index 29b08549be..73dd9009aa 100644 --- a/test/whereI.test +++ b/test/whereI.test @@ -29,8 +29,9 @@ do_execsql_test 1.0 { do_eqp_test 1.1 { SELECT a FROM t1 WHERE b='b' OR c='x' } { - 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b=?)} - 0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)} + QUERY PLAN + |--SEARCH TABLE t1 USING INDEX i1 (b=?) + `--SEARCH TABLE t1 USING INDEX i2 (c=?) } do_execsql_test 1.2 { @@ -57,8 +58,9 @@ do_execsql_test 2.0 { do_eqp_test 2.1 { SELECT a FROM t2 WHERE b='b' OR c='x' } { - 0 0 0 {SEARCH TABLE t2 USING INDEX i3 (b=?)} - 0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)} + QUERY PLAN + |--SEARCH TABLE t2 USING INDEX i3 (b=?) + `--SEARCH TABLE t2 USING INDEX i4 (c=?) } do_execsql_test 2.2 { diff --git a/test/whereJ.test b/test/whereJ.test index 48924d0fcf..af6ffafb3f 100644 --- a/test/whereJ.test +++ b/test/whereJ.test @@ -402,9 +402,7 @@ do_eqp_test 3.4 { a = 4 AND b BETWEEN 20 AND 80 -- Matches 80 rows AND c BETWEEN 150 AND 160 -- Matches 10 rows -} { - 0 0 0 {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c? AND c? AND b? AND b? -} {/*USING INDEX i45 (b=? AND a>?)*/} +} {USING INDEX i45 (b=? AND a>?)} do_execsql_test 5.2 { SELECT * FROM t45 WHERE b='two' AND a>4 @@ -257,11 +257,11 @@ do_execsql_test 5.4 { } set queries { - 1 2 "c = 5 AND a = 1" {/*i46 (c=? AND a=?)*/} - 2 6 "c = 4 AND a < 3" {/*i46 (c=? AND a= 3" {/*i46 (c=? AND a>?)*/} - 4 1 "c = 2 AND a = 1 AND b<10" {/*i46 (c=? AND a=? AND b5" {/*i46 (c=? AND a=? AND b>?)*/} + 1 2 "c = 5 AND a = 1" {i46 (c=? AND a=?)} + 2 6 "c = 4 AND a < 3" {i46 (c=? AND a= 3" {i46 (c=? AND a>?)} + 4 1 "c = 2 AND a = 1 AND b<10" {i46 (c=? AND a=? AND b5" {i46 (c=? AND a=? AND b>?)} } foreach {tn cnt where eqp} $queries { From cdf88760daac8660a5c8c882fcddd3678cadb726 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 2 May 2018 19:42:33 +0000 Subject: [PATCH 23/60] More test case updates. Tests are all running now. FossilOrigin-Name: dab5e5294813891469660cceb211ac1a1e526715bb57dcdbb1ab90321e6a4dad --- ext/expert/expert1.test | 50 +++++++-------- ext/expert/sqlite3expert.c | 10 ++- ext/fts5/test/fts5plan.test | 2 +- ext/rtree/rtree6.test | 30 +++++---- ext/rtree/rtreeC.test | 118 ++++++++++++++++++++++-------------- manifest | 46 +++++++------- manifest.uuid | 2 +- test/analyze4.test | 2 +- test/analyze6.test | 30 +++++---- test/analyze7.test | 32 +++++----- test/analyze8.test | 22 +++---- test/autoindex1.test | 57 +++++++++-------- test/autoindex5.test | 5 +- test/bestindex3.test | 10 +-- test/e_createtable.test | 6 +- test/fts3aux1.test | 50 +++++++++------ test/selectD.test | 2 +- test/tkt-78e04e52ea.test | 10 ++- test/tkt3442.test | 31 +++------- test/where3.test | 60 +++++++++--------- 20 files changed, 307 insertions(+), 268 deletions(-) diff --git a/ext/expert/expert1.test b/ext/expert/expert1.test index cb928f13e5..1eab80e070 100644 --- a/ext/expert/expert1.test +++ b/ext/expert/expert1.test @@ -95,7 +95,7 @@ do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } { SELECT * FROM t1 } { (no new indexes) - 0|0|0|SCAN TABLE t1 + SCAN TABLE t1 } do_setup_rec_test $tn.2 { @@ -104,7 +104,7 @@ do_setup_rec_test $tn.2 { SELECT * FROM t1 WHERE b>?; } { CREATE INDEX t1_idx_00000062 ON t1(b); - 0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?) + SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?) } do_setup_rec_test $tn.3 { @@ -113,7 +113,7 @@ do_setup_rec_test $tn.3 { SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ? } { CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE); - 0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b? AND b? AND b? AND bzSql ); while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){ - int iSelectid = sqlite3_column_int(pExplain, 0); - int iOrder = sqlite3_column_int(pExplain, 1); - int iFrom = sqlite3_column_int(pExplain, 2); + /* int iId = sqlite3_column_int(pExplain, 0); */ + /* int iParent = sqlite3_column_int(pExplain, 1); */ + /* int iNotUsed = sqlite3_column_int(pExplain, 2); */ const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3); int nDetail = STRLEN(zDetail); int i; @@ -1152,9 +1152,7 @@ int idxFindIndexes( } } - pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%d|%d|%d|%s\n", - iSelectid, iOrder, iFrom, zDetail - ); + pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail); } for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ diff --git a/ext/fts5/test/fts5plan.test b/ext/fts5/test/fts5plan.test index de6ab90761..8f57e39a81 100644 --- a/ext/fts5/test/fts5plan.test +++ b/ext/fts5/test/fts5plan.test @@ -60,6 +60,6 @@ do_eqp_test 1.4 { do_eqp_test 1.5 { SELECT * FROM f1 WHERE rank MATCH ? -} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2: +} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:} finish_test diff --git a/ext/rtree/rtree6.test b/ext/rtree/rtree6.test index 406604810b..6800b4bb10 100644 --- a/ext/rtree/rtree6.test +++ b/ext/rtree/rtree6.test @@ -74,42 +74,48 @@ do_test rtree6-1.5 { do_eqp_test rtree6.2.1 { SELECT * FROM t1,t2 WHERE k=+ii AND x1<10 } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0} - 0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0 + `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?) } do_eqp_test rtree6.2.2 { SELECT * FROM t1,t2 WHERE k=ii AND x1<10 } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0} - 0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0 + `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?) } do_eqp_test rtree6.2.3 { SELECT * FROM t1,t2 WHERE k=ii } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:} - 0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2: + `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?) } do_eqp_test rtree6.2.4.1 { SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10 } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1} - 0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1 + `--SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?) } do_eqp_test rtree6.2.4.2 { SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10 } { - 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1} - 0 1 1 {SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)} + QUERY PLAN + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1 + `--SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?) } do_eqp_test rtree6.2.5 { SELECT * FROM t1,t2 WHERE k=ii AND x1=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y } { - 0 0 1 {SCAN TABLE t} - 0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} + QUERY PLAN + |--SCAN TABLE t + `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0 } do_eqp_test 1.2 { SELECT * FROM t, r_tree WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y } { - 0 0 0 {SCAN TABLE t} - 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} + QUERY PLAN + |--SCAN TABLE t + `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0 } do_eqp_test 1.3 { SELECT * FROM t, r_tree WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y } { - 0 0 0 {SCAN TABLE t} - 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} + QUERY PLAN + |--SCAN TABLE t + `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0 } do_eqp_test 1.5 { SELECT * FROM t, r_tree } { - 0 0 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:} - 0 1 0 {SCAN TABLE t} + QUERY PLAN + |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2: + `--SCAN TABLE t } do_execsql_test 2.0 { @@ -82,31 +86,35 @@ do_eqp_test 2.1 { SELECT * FROM r_tree, t WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y } { - 0 0 1 {SCAN TABLE t} - 0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} + QUERY PLAN + |--SCAN TABLE t + `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0 } do_eqp_test 2.2 { SELECT * FROM t, r_tree WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y } { - 0 0 0 {SCAN TABLE t} - 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} + QUERY PLAN + |--SCAN TABLE t + `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0 } do_eqp_test 2.3 { SELECT * FROM t, r_tree WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y } { - 0 0 0 {SCAN TABLE t} - 0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0} + QUERY PLAN + |--SCAN TABLE t + `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0 } do_eqp_test 2.5 { SELECT * FROM t, r_tree } { - 0 0 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:} - 0 1 0 {SCAN TABLE t} + QUERY PLAN + |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2: + `--SCAN TABLE t } #------------------------------------------------------------------------- @@ -119,20 +127,25 @@ do_execsql_test 3.1 { } do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SCAN TABLE t2} + QUERY PLAN + |--SCAN TABLE t1 + `--SCAN TABLE t2 } do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } { - 0 0 0 {SCAN TABLE t2} 0 1 1 {SCAN TABLE t1} + QUERY PLAN + |--SCAN TABLE t2 + `--SCAN TABLE t1 } do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SCAN TABLE t3 VIRTUAL TABLE INDEX 2:} + QUERY PLAN + |--SCAN TABLE t1 + `--SCAN TABLE t3 VIRTUAL TABLE INDEX 2: } do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } { - 0 0 0 {SCAN TABLE t3 VIRTUAL TABLE INDEX 2:} - 0 1 1 {SCAN TABLE t1} + QUERY PLAN + |--SCAN TABLE t3 VIRTUAL TABLE INDEX 2: + `--SCAN TABLE t1 } #-------------------------------------------------------------------- @@ -189,8 +202,9 @@ do_rtree_integrity_test 5.1.1 rt do_eqp_test 5.2 { SELECT * FROM t1, rt WHERE x==id; } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:} + QUERY PLAN + |--SCAN TABLE t1 + `--SCAN TABLE rt VIRTUAL TABLE INDEX 1: } # Now create enough ANALYZE data to tell SQLite that virtual table "rt" @@ -205,8 +219,9 @@ sqlite3 db test.db do_eqp_test 5.4 { SELECT * FROM t1, rt WHERE x==id; } { - 0 0 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:} - 0 1 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)} + QUERY PLAN + |--SCAN TABLE rt VIRTUAL TABLE INDEX 2: + `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?) } # Delete the ANALYZE data. "t1" should be the outer loop again. @@ -217,8 +232,9 @@ sqlite3 db test.db do_eqp_test 5.6 { SELECT * FROM t1, rt WHERE x==id; } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:} + QUERY PLAN + |--SCAN TABLE t1 + `--SCAN TABLE rt VIRTUAL TABLE INDEX 1: } # This time create and attach a database that contains ANALYZE data for @@ -241,8 +257,9 @@ do_test 5.7 { do_eqp_test 5.8 { SELECT * FROM t1, rt WHERE x==id; } { - 0 0 0 {SCAN TABLE t1} - 0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:} + QUERY PLAN + |--SCAN TABLE t1 + `--SCAN TABLE rt VIRTUAL TABLE INDEX 1: } #-------------------------------------------------------------------- @@ -299,9 +316,9 @@ do_execsql_test 7.0 { } -proc do_eqp_execsql_test {tn sql res} { - set query "EXPLAIN QUERY PLAN $sql ; $sql " - uplevel [list do_execsql_test $tn $query $res] +proc do_eqp_execsql_test {tn sql res1 res2} { + do_eqp_test $tn.1 $sql $res1 + do_execsql_test $tn.2 $sql $res2 } do_eqp_execsql_test 7.1 { @@ -309,9 +326,11 @@ do_eqp_execsql_test 7.1 { ON (y1 BETWEEN ymin AND ymax) WHERE (x1 BETWEEN xmin AND xmax); } { - 0 0 0 {SCAN TABLE xdir} - 0 1 2 {SCAN TABLE ydir} - 0 2 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1} + QUERY PLAN + |--SCAN TABLE xdir + |--SCAN TABLE ydir + `--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1 +} { 2 4 } @@ -320,10 +339,11 @@ do_eqp_execsql_test 7.2 { ON (y1 BETWEEN ymin AND ymax) WHERE (x1 BETWEEN xmin AND xmax); } { - 0 0 0 {SCAN TABLE xdir} - 0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1} - 0 2 2 {SCAN TABLE ydir} - + QUERY PLAN + |--SCAN TABLE xdir + |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1 + `--SCAN TABLE ydir +} { 5 1 2 7 12 14 {} 5 2 2 7 8 12 10 5 4 5 5 10 10 10 @@ -334,9 +354,11 @@ do_eqp_execsql_test 7.3 { ON (y1 BETWEEN ymin AND ymax) WHERE (x1 BETWEEN xmin AND xmax); } { - 0 0 0 {SCAN TABLE xdir} - 0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1} - 0 2 2 {SCAN TABLE ydir} + QUERY PLAN + |--SCAN TABLE xdir + |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1 + `--SCAN TABLE ydir +} { 2 4 } @@ -345,9 +367,11 @@ do_eqp_execsql_test 7.4 { ON (y1 BETWEEN ymin AND ymax) WHERE (x1 BETWEEN xmin AND xmax); } { - 0 0 1 {SCAN TABLE xdir} - 0 1 0 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1} - 0 2 2 {SCAN TABLE ydir} + QUERY PLAN + |--SCAN TABLE xdir + |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1 + `--SCAN TABLE ydir +} { 2 4 } diff --git a/manifest b/manifest index 3863052746..18897a018a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stest\scases\sso\sthat\sthey\swork\swith\sthe\snew\sEXPLAIN\sQUERY\sPLAN\soutput\nformat.\s\sOnly\ssome\sof\sthe\scases\shave\sbeen\sfixed.\s\sThis\sis\san\sincremental\ncheck-in. -D 2018-05-02T18:00:17.259 +C More\stest\scase\supdates.\s\sTests\sare\sall\srunning\snow. +D 2018-05-02T19:42:33.079 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -44,8 +44,8 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74 F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3 F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4 -F ext/expert/expert1.test 00fb67256755a5194dab3d462f8ed3ad4640b4731fe465e5e28cea42c59ce05e -F ext/expert/sqlite3expert.c 1dfa561e64dc0f89d56b96e6afda87468c34b43604c2df50c47e3f4362778fb2 +F ext/expert/expert1.test 81c8834822181d009c08b18d2afb3b0fce8167a8bbbf23496a0e598d2b21623d +F ext/expert/sqlite3expert.c 95fdee74be2912d962951d984f1123e55d3f44bd643da7a48ff6ea9426a47f69 F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811 F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72 F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e @@ -187,7 +187,7 @@ F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c27 F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1 F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b -F ext/fts5/test/fts5plan.test b932afb6248a21d2eb1696d2dc40eeb580ea1da79b383adb1a4f7d613fbdd4ec +F ext/fts5/test/fts5plan.test 00dc4c974938b509db7cb3680407f068ee6e9cc824f492f68cb741a7b679fe41 F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15 F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457 F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056 @@ -362,13 +362,13 @@ F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e5 F ext/rtree/rtree3.test 2cafe8265d1ff28f206fce88d114f208349df482 F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142 -F ext/rtree/rtree6.test 916a641d2beac01b9880871ff07612d56c1e466190a27c82ab36ffd58be03b9f +F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4 F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5 F ext/rtree/rtree8.test 649f5a37ec656028a4a32674b9b1183104285a7625a09d2a8f52a1cef72c93f2 F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776 F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9 -F ext/rtree/rtreeC.test d9d06dda1aee68b4dc227dfcc899f335f8b621e9d1920ee3d4e5dab8ccd71db7 +F ext/rtree/rtreeC.test 55e40c4bd9735d9944280f0e664f39374e71bcd9cd3fe4e82786d20b48017fb5 F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9 F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331 @@ -596,11 +596,11 @@ F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8 -F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213 +F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 -F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f -F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f -F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82 +F test/analyze6.test 7b2667b879976ac4b90d8df80d5456328684f1f6f6fdef9469d6e53401f2f469 +F test/analyze7.test a37f4d9cb699a8af068ae02df1bb08bf844df8e98a92a8126cbff89e226879d8 +F test/analyze8.test e32a970564271114786703750e6939cf81dea4b8580874e38e9213ee092f6936 F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54 F test/analyzeA.test 22a892d67bd2223126335b99774cce56ba91122cfe82446d2927afc43ad667dc F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70 @@ -626,11 +626,11 @@ F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1 F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49 F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec F test/autoinc.test 83aad64411583aac9ff0b629159ab4662029ab4e3f47090fce4efd132b304484 -F test/autoindex1.test 788d0894aa3aee1220036d20696e98733fb7ca02265cb1e801700177120c1aeb +F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0 F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf -F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990 +F test/autoindex5.test 5f0135dc3b266277b8c1904624439097d8e8020dd7197eda13fda23c35c21a05 F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4 F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e @@ -646,7 +646,7 @@ F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928 -F test/bestindex3.test dfa5bcb1ae2f96463fb4106308908c8ed7348312de3519d981e632a0a2b6cd43 +F test/bestindex3.test 92a34c82f1ae245ef71f8c999f50a9dccd097a310cb070244c7b5cd0d2e07d73 F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455 F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c @@ -766,7 +766,7 @@ F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145 F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14 F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579 -F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844 +F test/e_createtable.test ef30054d1e4cec4d1da2ffcebcc15f1ded3ed7ae80f009019485be973f449917 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5 @@ -869,7 +869,7 @@ F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18 F test/fts3ao.test c416d50c4fdb6f32a15205b3d0a49eb74fcea92feb66b531a83c904770de5ff1 F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1 F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9 -F test/fts3aux1.test 24b8a69e342a6684e3929408b245cdf5de0d45f8094108fa0a57cd007228963d +F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6 F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491 F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958 @@ -1218,7 +1218,7 @@ F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95 F test/selectA.test b8a590f6493cad5b0bb4dfe1709bf7dcda0b6c40bb4caf32d1e36a89eebc8fc5 F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25 F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3 -F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394 +F test/selectD.test cfa9f27dbdbeaf2d021d26c79b6c790d8f26e5506d50117c7696d3e136d6d9e7 F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3 F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840 @@ -1352,7 +1352,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 1b2e6bf4f1d9887b216b6da774e5f25915ec8118 +F test/tkt-78e04e52ea.test 1b5be1bac961833a9fd70fe50738cb4064822c61f82c54f7d488435ec806ea62 F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18 F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8 @@ -1435,7 +1435,7 @@ F test/tkt3346.test 6f67c3ed7db94dfc5df4f5f0b63809a1f611e01a F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812 -F test/tkt3442.test 53840ec5325bb94544792aad4c20476f81dc26b1 +F test/tkt3442.test a1fc47c669e651d16494de3ff349bcb53281456f2ca02c8bc14220b6044bbfe8 F test/tkt3457.test 5651e2cbb94645b677ec663160b9e192b87b7d365aecdfb24e19f749575a6fc2 F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19 F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218 @@ -1584,7 +1584,7 @@ F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 F test/where.test f19ea3fa31c425b04af42c8b192a5b595ee84498df8d27dcd79ec043b25fbbfb F test/where2.test 478d2170637b9211f593120648858593bf2445a1 -F test/where3.test 54cdeb02157acc979de41530b804ae7b09552bf1 +F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f2f525548c65f89f55cbe91da8a21512dedc6f7b68b58b7906d653e800a2963a -R c2fb03c3c8d3bca714f50d297b15ed28 +P 5f0e803e33aa557865d5fc830d9202d628de9a94c9757058ca48f1a560702cd3 +R 082b82ad611d4d87c26221d79d5fbd45 U drh -Z 275fa11767369a8ceab0cb6be2ece9b6 +Z 58923cc0a63a66a0c06aeccf7817dd66 diff --git a/manifest.uuid b/manifest.uuid index 7d9d7d3318..f082081d38 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5f0e803e33aa557865d5fc830d9202d628de9a94c9757058ca48f1a560702cd3 \ No newline at end of file +dab5e5294813891469660cceb211ac1a1e526715bb57dcdbb1ab90321e6a4dad \ No newline at end of file diff --git a/test/analyze4.test b/test/analyze4.test index 974ed89a86..9fc98aa8f2 100644 --- a/test/analyze4.test +++ b/test/analyze4.test @@ -38,7 +38,7 @@ do_test analyze4-1.0 { # Should choose the t1a index since it is more specific than t1b. db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} # Verify that the t1b index shows that it does not narrow down the # search any at all. diff --git a/test/analyze6.test b/test/analyze6.test index 31ace8eda5..34d00f56ec 100644 --- a/test/analyze6.test +++ b/test/analyze6.test @@ -61,14 +61,18 @@ do_test analyze6-1.0 { # do_test analyze6-1.1 { eqp {SELECT count(*) FROM ev, cat WHERE x=y} -} {0 0 1 {SCAN TABLE cat USING COVERING INDEX catx} 0 1 0 {SEARCH TABLE ev USING COVERING INDEX evy (y=?)}} +} {/*SCAN TABLE cat USING COVERING INDEX catx*SEARCH TABLE ev USING COVERING INDEX evy (y=?)*/} # The same plan is chosen regardless of the order of the tables in the # FROM clause. # -do_test analyze6-1.2 { - eqp {SELECT count(*) FROM cat, ev WHERE x=y} -} {0 0 0 {SCAN TABLE cat USING COVERING INDEX catx} 0 1 1 {SEARCH TABLE ev USING COVERING INDEX evy (y=?)}} +do_eqp_test analyze6-1.2 { + SELECT count(*) FROM cat, ev WHERE x=y +} { + QUERY PLAN + |--SCAN TABLE cat USING COVERING INDEX catx + `--SEARCH TABLE ev USING COVERING INDEX evy (y=?) +} # Ticket [83ea97620bd3101645138b7b0e71c12c5498fe3d] 2011-03-30 @@ -82,26 +86,26 @@ do_test analyze6-2.1 { ANALYZE; } eqp {SELECT * FROM t201 WHERE z=5} -} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}} +} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/} do_test analyze6-2.2 { eqp {SELECT * FROM t201 WHERE y=5} -} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}} +} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/} do_test analyze6-2.3 { eqp {SELECT * FROM t201 WHERE x=5} -} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}} +} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/} do_test analyze6-2.4 { execsql { INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5); ANALYZE t201; } eqp {SELECT * FROM t201 WHERE z=5} -} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}} +} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/} do_test analyze6-2.5 { eqp {SELECT * FROM t201 WHERE y=5} -} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}} +} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/} do_test analyze6-2.6 { eqp {SELECT * FROM t201 WHERE x=5} -} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}} +} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/} do_test analyze6-2.7 { execsql { INSERT INTO t201 VALUES(4,5,7); @@ -111,12 +115,12 @@ do_test analyze6-2.7 { ANALYZE t201; } eqp {SELECT * FROM t201 WHERE z=5} -} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}} +} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/} do_test analyze6-2.8 { eqp {SELECT * FROM t201 WHERE y=5} -} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}} +} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/} do_test analyze6-2.9 { eqp {SELECT * FROM t201 WHERE x=5} -} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}} +} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/} finish_test diff --git a/test/analyze7.test b/test/analyze7.test index 76664546a5..d6da6c1510 100644 --- a/test/analyze7.test +++ b/test/analyze7.test @@ -37,13 +37,13 @@ do_test analyze7-1.0 { WHERE value BETWEEN 1 AND 256; EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123; } -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} do_test analyze7-1.1 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/} do_test analyze7-1.2 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/} # Run an analyze on one of the three indices. Verify that this # effects the row-count estimate on the one query that uses that @@ -53,20 +53,20 @@ do_test analyze7-2.0 { execsql {ANALYZE t1a;} db cache flush execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} do_test analyze7-2.1 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/} do_test analyze7-2.2 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/} # Verify that since the query planner now things that t1a is more # selective than t1b, it prefers to use t1a. # do_test analyze7-2.3 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} # Run an analysis on another of the three indices. Verify that this # new analysis works and does not disrupt the previous analysis. @@ -75,40 +75,40 @@ do_test analyze7-3.0 { execsql {ANALYZE t1cd;} db cache flush; execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} do_test analyze7-3.1 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/} 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=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/} 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 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;} - } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}} + } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/} } else { # If ENABLE_STAT4 is not defined, the expected row count for (c=2) is the # same as that for (c=?). do_test analyze7-3.2.3 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;} - } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}} + } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/} } 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=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} 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=?)}} + } {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/} do_test analyze7-3.5 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123} - } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} + } {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} } do_test analyze7-3.6 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)*/} finish_test diff --git a/test/analyze8.test b/test/analyze8.test index 1079e68080..daa83ef427 100644 --- a/test/analyze8.test +++ b/test/analyze8.test @@ -61,25 +61,25 @@ do_test 1.0 { # do_test 1.1 { eqp {SELECT * FROM t1 WHERE a=100 AND b=55} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/} do_test 1.2 { eqp {SELECT * FROM t1 WHERE a=99 AND b=55} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} do_test 1.3 { eqp {SELECT * FROM t1 WHERE a=101 AND b=55} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} do_test 1.4 { eqp {SELECT * FROM t1 WHERE a=100 AND b=56} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/} do_test 1.5 { eqp {SELECT * FROM t1 WHERE a=99 AND b=56} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} do_test 1.6 { eqp {SELECT * FROM t1 WHERE a=101 AND b=56} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/} do_test 2.1 { eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b? AND b? AND b? AND b? AND c? AND c? AND c? AND c? AND owner_change_date? AND owner_change_date? AND x? AND x10" - {0 0 0 {SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)}} + {/*SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/} } # EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a diff --git a/test/fts3aux1.test b/test/fts3aux1.test index 9bbed53c45..c7e1ac1a5c 100644 --- a/test/fts3aux1.test +++ b/test/fts3aux1.test @@ -105,10 +105,10 @@ db func rec rec # do_execsql_test 2.1.1.1 { EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term='braid' -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:} } +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 1:*/} do_execsql_test 2.1.1.2 { EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid' -} {0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}} +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/} # Now show that using "term='braid'" means the virtual table returns # only 1 row to SQLite, but "+term='braid'" means all 19 are returned. @@ -154,24 +154,24 @@ do_execsql_test 2.1.5 { SELECT * FROM terms WHERE term=NULL } {} do_execsql_test 2.2.1.1 { EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term>'brain' -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 2:} } +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 2:*/} do_execsql_test 2.2.1.2 { EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain' -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} } +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/} do_execsql_test 2.2.1.3 { EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term<'brain' -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 4:} } +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 4:*/} do_execsql_test 2.2.1.4 { EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain' -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} } +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/} do_execsql_test 2.2.1.5 { EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term BETWEEN 'brags' AND 'brain' -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 6:} } +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 6:*/} do_execsql_test 2.2.1.6 { EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term BETWEEN 'brags' AND 'brain' -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} } +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/} do_test 2.2.2.1 { set cnt 0 @@ -335,8 +335,9 @@ foreach {tn sort orderby} { 9 1 "ORDER BY occurrences DESC" } { - set res [list 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}] - if {$sort} { lappend res 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } + set res {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} + if {$sort} { append res {*USE TEMP B-TREE FOR ORDER BY} } + set res "/*$res*/" set sql "SELECT * FROM terms $orderby" do_execsql_test 2.3.1.$tn "EXPLAIN QUERY PLAN $sql" $res @@ -403,39 +404,48 @@ do_execsql_test 4.1 { INSERT INTO x3 SELECT term FROM terms WHERE col = '*'; } -proc do_plansql_test {tn sql r} { - uplevel do_execsql_test $tn [list "EXPLAIN QUERY PLAN $sql ; $sql"] [list $r] +proc do_plansql_test {tn sql r1 r2} { + do_eqp_test $tn.eqp $sql $r1 + do_execsql_test $tn $sql $r2 } do_plansql_test 4.2 { SELECT y FROM x2, terms WHERE y = term AND col = '*' } { - 0 0 0 {SCAN TABLE x2} - 0 1 1 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:} + QUERY PLAN + |--SCAN TABLE x2 + `--SCAN TABLE terms VIRTUAL TABLE INDEX 1: +} { a b c d e f g h i j k l } do_plansql_test 4.3 { SELECT y FROM terms, x2 WHERE y = term AND col = '*' } { - 0 0 1 {SCAN TABLE x2} - 0 1 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:} + QUERY PLAN + |--SCAN TABLE x2 + `--SCAN TABLE terms VIRTUAL TABLE INDEX 1: +} { a b c d e f g h i j k l } do_plansql_test 4.4 { SELECT y FROM x3, terms WHERE y = term AND col = '*' } { - 0 0 1 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} - 0 1 0 {SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)} + QUERY PLAN + |--SCAN TABLE terms VIRTUAL TABLE INDEX 0: + `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?) +} { a b c d e f g h i j k l } do_plansql_test 4.5 { SELECT y FROM terms, x3 WHERE y = term AND occurrences>1 AND col = '*' } { - 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} - 0 1 1 {SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)} + QUERY PLAN + |--SCAN TABLE terms VIRTUAL TABLE INDEX 0: + `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?) +} { a k l } diff --git a/test/selectD.test b/test/selectD.test index 89f999eb6d..a95eb82167 100644 --- a/test/selectD.test +++ b/test/selectD.test @@ -169,6 +169,6 @@ do_execsql_test selectD-4.1 { WHERE x1.d>5 GROUP BY x1.d) AS x2 ON t41.b=x2.d; -} {/.*SEARCH SUBQUERY 1 AS x2 USING AUTOMATIC.*/} +} {/*SEARCH SUBQUERY 0x* AS x2 USING AUTOMATIC*/} finish_test diff --git a/test/tkt-78e04e52ea.test b/test/tkt-78e04e52ea.test index 963ecf18d1..47a1093dd8 100644 --- a/test/tkt-78e04e52ea.test +++ b/test/tkt-78e04e52ea.test @@ -41,10 +41,8 @@ do_test tkt-78e04-1.3 { } } {} do_test tkt-78e04-1.4 { - execsql { - EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1abc%'; - } -} {0 0 0 {SCAN TABLE USING COVERING INDEX i1}} + db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1abc%';} +} {/*SCAN TABLE USING COVERING INDEX i1*/} do_test tkt-78e04-1.5 { execsql { DROP TABLE ""; @@ -57,12 +55,12 @@ do_test tkt-78e04-2.1 { CREATE INDEX "" ON t2(x); EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=5; } -} {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX (x=?)}} +} {/*SEARCH TABLE t2 USING COVERING INDEX (x=?)*/} do_test tkt-78e04-2.2 { execsql { DROP INDEX ""; EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=2; } -} {0 0 0 {SCAN TABLE t2}} +} {/*SCAN TABLE t2*/} finish_test diff --git a/test/tkt3442.test b/test/tkt3442.test index ee9169ce2c..98a5e371c1 100644 --- a/test/tkt3442.test +++ b/test/tkt3442.test @@ -34,35 +34,24 @@ do_test tkt3442-1.1 { } } {} - -# Explain Query Plan -# -proc EQP {sql} { - uplevel "execsql {EXPLAIN QUERY PLAN $sql}" -} - - # These tests perform an EXPLAIN QUERY PLAN on both versions of the # SELECT referenced in ticket #3442 (both '5000' and "5000") # and verify that the query plan is the same. # -ifcapable explain { - do_test tkt3442-1.2 { - EQP { SELECT node FROM listhash WHERE id='5000' LIMIT 1; } - } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}} - do_test tkt3442-1.3 { - EQP { SELECT node FROM listhash WHERE id="5000" LIMIT 1; } - } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}} -} +do_eqp_test tkt3442-1.2 { + SELECT node FROM listhash WHERE id='5000' LIMIT 1; +} {SEARCH TABLE listhash USING INDEX ididx (id=?)} +do_eqp_test tkt3442-1.3 { + SELECT node FROM listhash WHERE id="5000" LIMIT 1; +} {SEARCH TABLE listhash USING INDEX ididx (id=?)} # Some extra tests testing other permutations of 5000. # -ifcapable explain { - do_test tkt3442-1.4 { - EQP { SELECT node FROM listhash WHERE id=5000 LIMIT 1; } - } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}} -} +do_eqp_test tkt3442-1.4 { + SELECT node FROM listhash WHERE id=5000 LIMIT 1; +} {SEARCH TABLE listhash USING INDEX ididx (id=?)} + do_test tkt3442-1.5 { catchsql { SELECT node FROM listhash WHERE id=[5000] LIMIT 1; diff --git a/test/where3.test b/test/where3.test index 6edbe2bcad..4d4ea3ee68 100644 --- a/test/where3.test +++ b/test/where3.test @@ -235,17 +235,20 @@ do_execsql_test where3-3.0 { CREATE TABLE t302(x, y); INSERT INTO t302 VALUES(4,5); ANALYZE; - explain query plan SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y; -} { - 0 0 0 {SCAN TABLE t302} - 0 1 1 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)} } -do_execsql_test where3-3.1 { - explain query plan +do_eqp_test where3-3.0a { + SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y; +} { + QUERY PLAN + |--SCAN TABLE t302 + `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?) +} +do_eqp_test where3-3.1 { SELECT * FROM t301, t302 WHERE t302.x=5 AND t301.a=t302.y; } { - 0 0 1 {SCAN TABLE t302} - 0 1 0 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)} + QUERY PLAN + |--SCAN TABLE t302 + `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?) } do_execsql_test where3-3.2 { SELECT * FROM t301 WHERE c=3 AND a IS NULL; @@ -308,8 +311,8 @@ do_execsql_test where3-5.0 { CREATE INDEX bbb_111 ON bbb (fk, type); CREATE INDEX bbb_222 ON bbb (parent, position); CREATE INDEX bbb_333 ON bbb (fk, lastModified); - - EXPLAIN QUERY PLAN +} +do_eqp_test where3-5.0a { SELECT bbb.title AS tag_title FROM aaa JOIN bbb ON bbb.id = aaa.parent WHERE aaa.fk = 'constant' @@ -317,12 +320,12 @@ do_execsql_test where3-5.0 { AND bbb.parent = 4 ORDER BY bbb.title COLLATE NOCASE ASC; } { - 0 0 0 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)} - 0 1 1 {SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?) + |--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?) + `--USE TEMP B-TREE FOR ORDER BY } -do_execsql_test where3-5.1 { - EXPLAIN QUERY PLAN +do_eqp_test where3-5.1 { SELECT bbb.title AS tag_title FROM aaa JOIN aaa AS bbb ON bbb.id = aaa.parent WHERE aaa.fk = 'constant' @@ -330,12 +333,12 @@ do_execsql_test where3-5.1 { AND bbb.parent = 4 ORDER BY bbb.title COLLATE NOCASE ASC; } { - 0 0 0 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)} - 0 1 1 {SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?) + |--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?) + `--USE TEMP B-TREE FOR ORDER BY } -do_execsql_test where3-5.2 { - EXPLAIN QUERY PLAN +do_eqp_test where3-5.2 { SELECT bbb.title AS tag_title FROM bbb JOIN aaa ON bbb.id = aaa.parent WHERE aaa.fk = 'constant' @@ -343,12 +346,12 @@ do_execsql_test where3-5.2 { AND bbb.parent = 4 ORDER BY bbb.title COLLATE NOCASE ASC; } { - 0 0 1 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)} - 0 1 0 {SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?) + |--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?) + `--USE TEMP B-TREE FOR ORDER BY } -do_execsql_test where3-5.3 { - EXPLAIN QUERY PLAN +do_eqp_test where3-5.3 { SELECT bbb.title AS tag_title FROM aaa AS bbb JOIN aaa ON bbb.id = aaa.parent WHERE aaa.fk = 'constant' @@ -356,9 +359,10 @@ do_execsql_test where3-5.3 { AND bbb.parent = 4 ORDER BY bbb.title COLLATE NOCASE ASC; } { - 0 0 1 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)} - 0 1 0 {SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)} - 0 0 0 {USE TEMP B-TREE FOR ORDER BY} + QUERY PLAN + |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?) + |--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?) + `--USE TEMP B-TREE FOR ORDER BY } # Name resolution with NATURAL JOIN and USING From fa16f5d9d660dbf58cac70c2ae297d611103885c Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 01:37:13 +0000 Subject: [PATCH 24/60] Enhance EXPLAIN QUERY PLAN to report the generation of constant rows using VALUES or just a SELECT without FROM. FossilOrigin-Name: c75eee69fa8a9b56ee58a4cc539e80cc982f43390dc3a357344d58479dd89a41 --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/select.c | 15 ++++++--------- src/where.c | 2 +- test/eqp.test | 6 ++++++ test/orderby1.test | 9 ++++++--- test/with1.test | 1 + test/with3.test | 3 +++ 8 files changed, 35 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index 18897a018a..a51339acd3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\stest\scase\supdates.\s\sTests\sare\sall\srunning\snow. -D 2018-05-02T19:42:33.079 +C Enhance\sEXPLAIN\sQUERY\sPLAN\sto\sreport\sthe\sgeneration\sof\sconstant\srows\susing\nVALUES\sor\sjust\sa\sSELECT\swithout\sFROM. +D 2018-05-03T01:37:13.698 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -493,7 +493,7 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 29294be54b5ef53e3359d37b394dc0077f5a594f9d07f06c5eabd1e3830abd9f +F src/select.c e612d71bc58cad38f06c9ebb9e71fa2a9f643d5775f220388b7ba17df5fe21e3 F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -577,7 +577,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0 F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f -F src/where.c 8265aec8b13c19c9971b0012b004a8d18384dad619a07616c0a9f04401326451 +F src/where.c aa94ef44ef36763817ca952e68c03db7eee5e2d4f1f0c3a98823a58c074157bd F src/whereInt.h 2610cb87dd95509995b63decc674c60f2757697a206cfe0c085ee53d9c43cfff F src/wherecode.c 3368f0797a4b166e0773a4137d270d92ddcbce91618b11d1e9f11f7c39f33068 F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a @@ -791,7 +791,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473 F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6 F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020 -F test/eqp.test 0d06518e010ca5f02bd56b6a45fb70514a29c7eb97d244d72826d164477cfb1e +F test/eqp.test 2ac18a1d6aa0a0a8f0eea1cc0ba7d63391e2f968a47f59643f889c7c87d238a4 F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9 F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3 @@ -1118,7 +1118,7 @@ F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 F test/optfuzz-db01.c a0c256905c8ac79f9a5de2f374a3d9f757bef0dca2a238dc7c10cc8a38031834 F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041 F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1 -F test/orderby1.test c4bbefbdbc0b9c6046c88d3c996ab81b41f799c0885b3e656c02f9295c4773ba +F test/orderby1.test bb8535f52c42e91cfa110622ccff70597e531198bb4b033185ad84c11522ab1b F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04 F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99 F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4 @@ -1611,9 +1611,9 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/with1.test 6b98f6f2adef8909b171d0d1e3b0439e3f4d4b75be94533aaddf7f15fe002e16 +F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96 F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab -F test/with3.test 2829c3de40a9e18d13f35f8f1670f549d26a4778acbd82a3454ad9b0a07de40b +F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205 F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5f0e803e33aa557865d5fc830d9202d628de9a94c9757058ca48f1a560702cd3 -R 082b82ad611d4d87c26221d79d5fbd45 +P dab5e5294813891469660cceb211ac1a1e526715bb57dcdbb1ab90321e6a4dad +R 53c64522178e60b44f774331a15b70e5 U drh -Z 58923cc0a63a66a0c06aeccf7817dd66 +Z 33f2e8b7048beb839b528a03308b5edb diff --git a/manifest.uuid b/manifest.uuid index f082081d38..4dc52e5fa5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dab5e5294813891469660cceb211ac1a1e526715bb57dcdbb1ab90321e6a4dad \ No newline at end of file +c75eee69fa8a9b56ee58a4cc539e80cc982f43390dc3a357344d58479dd89a41 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 76dfef912a..14e485b2b3 100644 --- a/src/select.c +++ b/src/select.c @@ -2373,10 +2373,9 @@ static int multiSelectValues( Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ ){ - Select *pPrior; - Select *pRightmost = p; int nRow = 1; int rc = 0; + int bShowAll = p->pLimit==0; assert( p->selFlags & SF_MultiValue ); do{ assert( p->selFlags & SF_Values ); @@ -2385,15 +2384,13 @@ static int multiSelectValues( if( p->pPrior==0 ) break; assert( p->pPrior->pNext==p ); p = p->pPrior; - nRow++; + nRow += bShowAll; }while(1); - ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROWS", nRow)); + ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow, + nRow==1 ? "" : "S")); while( p ){ - pPrior = p->pPrior; - p->pPrior = 0; - rc = sqlite3Select(pParse, p, pDest); - p->pPrior = pPrior; - if( rc || pRightmost->pLimit ) break; + selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1); + if( !bShowAll ) break; p->nSelectRow = nRow; p = p->pNext; } diff --git a/src/where.c b/src/where.c index 1145a554a5..d76d9f81e2 100644 --- a/src/where.c +++ b/src/where.c @@ -4592,7 +4592,7 @@ WhereInfo *sqlite3WhereBegin( if( wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } - /* ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); */ + ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); }else{ /* Assign a bit from the bitmask to every term in the FROM clause. ** diff --git a/test/eqp.test b/test/eqp.test index d25814628b..4638c34aa4 100644 --- a/test/eqp.test +++ b/test/eqp.test @@ -89,6 +89,7 @@ do_eqp_test 1.7 { } { QUERY PLAN |--MATERIALIZE xxxxxx + | `--SCAN CONSTANT ROW |--SCAN SUBQUERY xxxxxx `--SCAN TABLE t3 } @@ -99,7 +100,9 @@ do_eqp_test 1.8 { |--MATERIALIZE xxxxxx | `--COMPOUND QUERY | |--LEFT-MOST SUBQUERY + | | `--SCAN CONSTANT ROW | `--UNION USING TEMP B-TREE + | `--SCAN CONSTANT ROW |--SCAN SUBQUERY xxxxxx `--SCAN TABLE t3 } @@ -110,6 +113,7 @@ do_eqp_test 1.9 { |--MATERIALIZE xxxxxx | `--COMPOUND QUERY | |--LEFT-MOST SUBQUERY + | | `--SCAN CONSTANT ROW | `--EXCEPT USING TEMP B-TREE | `--SCAN TABLE t3 |--SCAN SUBQUERY xxxxxx @@ -122,6 +126,7 @@ do_eqp_test 1.10 { |--MATERIALIZE xxxxxx | `--COMPOUND QUERY | |--LEFT-MOST SUBQUERY + | | `--SCAN CONSTANT ROW | `--INTERSECT USING TEMP B-TREE | `--SCAN TABLE t3 |--SCAN SUBQUERY xxxxxx @@ -135,6 +140,7 @@ do_eqp_test 1.11 { |--MATERIALIZE xxxxxx | `--COMPOUND QUERY | |--LEFT-MOST SUBQUERY + | | `--SCAN CONSTANT ROW | `--UNION ALL | `--SCAN TABLE t3 |--SCAN SUBQUERY xxxxxx diff --git a/test/orderby1.test b/test/orderby1.test index 3983ff5db3..13bd7bfb5a 100644 --- a/test/orderby1.test +++ b/test/orderby1.test @@ -454,9 +454,12 @@ do_test 4.0 { # No sorting of queries that omit the FROM clause. # -do_execsql_test 5.0 { - EXPLAIN QUERY PLAN SELECT 5 ORDER BY 1 -} {} +do_eqp_test 5.0 { + SELECT 5 ORDER BY 1 +} { + QUERY PLAN + `--SCAN CONSTANT ROW +} do_execsql_test 5.1 { EXPLAIN QUERY PLAN SELECT 5 UNION ALL SELECT 3 ORDER BY 1 } {~/B-TREE/} diff --git a/test/with1.test b/test/with1.test index f1a0625049..f8965399fc 100644 --- a/test/with1.test +++ b/test/with1.test @@ -1005,6 +1005,7 @@ do_eqp_test 19.1b { } { QUERY PLAN |--MATERIALIZE xxxxxx + | `--SCAN CONSTANT ROW |--SCAN SUBQUERY xxxxxx `--SCAN SUBQUERY xxxxxx } diff --git a/test/with3.test b/test/with3.test index d13544cfa0..de150b1fc1 100644 --- a/test/with3.test +++ b/test/with3.test @@ -83,6 +83,7 @@ ifcapable analyze { QUERY PLAN |--MATERIALIZE xxxxxx | |--SETUP + | | `--SCAN CONSTANT ROW | `--RECURSIVE STEP | `--SCAN TABLE cnt |--SCAN SUBQUERY xxxxxx @@ -96,6 +97,7 @@ ifcapable analyze { QUERY PLAN |--MATERIALIZE xxxxxx | |--SETUP + | | `--SCAN CONSTANT ROW | `--RECURSIVE STEP | `--SCAN TABLE cnt |--SCAN TABLE y1 @@ -117,6 +119,7 @@ do_eqp_test 3.2.2 { QUERY PLAN |--MATERIALIZE xxxxxx | |--SETUP + | | |--SCAN CONSTANT ROW | | `--SCALAR SUBQUERY | | `--SCAN TABLE w2 | `--RECURSIVE STEP From 3de5d16cf7df698599136d4a6695c97dbb603c2d Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 03:59:02 +0000 Subject: [PATCH 25/60] The sqlite3BtreeInsert() routine tries to overwrite an existing cell with modified content if the new content is the same size. Pages are only dirtied if they change. This prototype works some, but still has issues. FossilOrigin-Name: 489451b378819621537231c1c8a07704437e11c1f5384fd53b09f3977d2213a4 --- manifest | 15 ++++++---- manifest.uuid | 2 +- src/btree.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 866465edaf..734d14e6c0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Prevent\sVACUUM\sfrom\srunning\sany\scommands\sin\ssqlite_master.sql\sother\sthan\nCREATE\sstatements.\s\sThat\sis\sall\sthat\sshould\sbe\sthere\sanyhow.\s\sThis\sfixes\na\sproblem\sdiscovered\sby\sOSSFuzz.\s\sTest\scases\sin\sTH3. -D 2018-05-02T15:00:26.033 +C The\ssqlite3BtreeInsert()\sroutine\stries\sto\soverwrite\san\sexisting\scell\swith\nmodified\scontent\sif\sthe\snew\scontent\sis\sthe\ssame\ssize.\s\sPages\sare\sonly\sdirtied\nif\sthey\schange.\s\sThis\sprototype\sworks\ssome,\sbut\sstill\shas\sissues. +D 2018-05-03T03:59:02.523 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,7 +434,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c fa7da0a5584e5182b92536bc4b7622a154a468997a075d5901345efb79a05ffe +F src/btree.c d1b1bd0602381cd668fefdc21bb376083d34a202c7f978ddd6cdfe8b576880fa F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e @@ -1727,7 +1727,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0c67150749cb3d067e14b2dcac9c3489e0f14bd18c0387f1d9bc93d21fc96fe5 -R 05ae73916277803fcebbb023b759986c +P ab0d99d0b5edece4c639baa47ce1ca2c02774cb2515e5b7f36d9bd312ccd3310 +R d19653c30e874527a8180a99ea6a4aad +T *branch * cell-overwrite-prototype +T *sym-cell-overwrite-prototype * +T -sym-trunk * U drh -Z 0a57dfa0969cac36c6f9349555316be2 +Z 4db008fe8cce4e65f98c2fd1a101b30c diff --git a/manifest.uuid b/manifest.uuid index 1f86bdd5bb..44cef5c9c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ab0d99d0b5edece4c639baa47ce1ca2c02774cb2515e5b7f36d9bd312ccd3310 \ No newline at end of file +489451b378819621537231c1c8a07704437e11c1f5384fd53b09f3977d2213a4 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 700138efca..0a8c172212 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8152,6 +8152,83 @@ static int balance(BtCursor *pCur){ return rc; } +/* Overwrite content from pX into pDest. Only do the write if the +** content is different from what is already there. +*/ +static int btreeOverwriteContent( + MemPage *pPage, /* MemPage on which writing will occur */ + u8 *pDest, /* Pointer to the place to start writing */ + const BtreePayload *pX, /* Source of data to write */ + int iOffset, /* Offset of first byte to write */ + int iAmt /* Number of bytes to be written */ +){ + int nData = pX->nData - iOffset; + if( nData<=0 ){ + /* Overwritting with zeros */ + int i; + for(i=0; ipDbPage); + if( rc ) return rc; + memset(pDest + i, 0, iAmt - i); + } + }else{ + if( nDatapData) + iOffset, iAmt)!=0 ){ + int rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt); + } + } + return SQLITE_OK; +} + +/* +** Overwrite the cell that cursor pCur is pointing to with fresh content +** contained in pX. +*/ +static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ + int iOffset; /* Next byte of pX->pData to write */ + int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */ + int rc; /* Return code */ + MemPage *pPage = pCur->pPage; /* Page being written */ + BtShared *pBt; /* Btree */ + Pgno ovflPgno; /* Next overflow page to write */ + u32 ovflPageSize; /* Size to write on overflow page */ + + /* Overwrite the local portion first */ + rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX, + 0, pCur->info.nLocal); + if( rc ) return rc; + if( pCur->info.nLocal==nTotal ) return SQLITE_OK; + + /* Now overwrite the overflow pages */ + iOffset = pCur->info.nLocal; + ovflPgno = get4byte(pCur->info.pPayload + iOffset); + pBt = pPage->pBt; + ovflPageSize = pBt->usableSize - 4; + do{ + rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); + if( rc ) return rc; + if( iOffset+ovflPageSize>nTotal ){ + ovflPgno = get4byte(pPage->aData + ovflPageSize); + }else{ + ovflPageSize = nTotal - iOffset; + } + rc = btreeOverwriteContent(pPage, pPage->aData, pX, + iOffset, ovflPageSize); + if( rc ) return rc; + iOffset += ovflPageSize; + sqlite3PagerUnref(pPage->pDbPage); + }while( iOffsetcurFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ + /* The current is currently pointing to the entry that is to be + ** overwritten */ + if( pCur->info.nPayload==pX->nData+pX->nZero ){ + return btreeOverwriteCell(pCur, pX); + } loc = 0; }else if( loc==0 ){ rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc); From 9b03192e15b45ac1d448b958be6d35d1ea9cf9ff Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 12:57:48 +0000 Subject: [PATCH 26/60] Bug fixes in the overwrite optimization. FossilOrigin-Name: 0cb6cd2a6a596afaa1cca6c5f5abc2ea75d04f254c7debaf36ecd6a90b66aed6 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/btree.c | 6 +++--- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 734d14e6c0..210a679733 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\ssqlite3BtreeInsert()\sroutine\stries\sto\soverwrite\san\sexisting\scell\swith\nmodified\scontent\sif\sthe\snew\scontent\sis\sthe\ssame\ssize.\s\sPages\sare\sonly\sdirtied\nif\sthey\schange.\s\sThis\sprototype\sworks\ssome,\sbut\sstill\shas\sissues. -D 2018-05-03T03:59:02.523 +C Bug\sfixes\sin\sthe\soverwrite\soptimization. +D 2018-05-03T12:57:48.671 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,7 +434,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c d1b1bd0602381cd668fefdc21bb376083d34a202c7f978ddd6cdfe8b576880fa +F src/btree.c 7216dac5e870868de7429e71727fb87cca8057fd01814c18df2e59a5d00d20d5 F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e @@ -1727,10 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ab0d99d0b5edece4c639baa47ce1ca2c02774cb2515e5b7f36d9bd312ccd3310 -R d19653c30e874527a8180a99ea6a4aad -T *branch * cell-overwrite-prototype -T *sym-cell-overwrite-prototype * -T -sym-trunk * +P 489451b378819621537231c1c8a07704437e11c1f5384fd53b09f3977d2213a4 +R b89660c58e0d48e704d46836e0da0214 U drh -Z 4db008fe8cce4e65f98c2fd1a101b30c +Z 41261a1ee8ebfd1f0c3b6e3f166f7f4d diff --git a/manifest.uuid b/manifest.uuid index 44cef5c9c1..88b683be02 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -489451b378819621537231c1c8a07704437e11c1f5384fd53b09f3977d2213a4 \ No newline at end of file +0cb6cd2a6a596afaa1cca6c5f5abc2ea75d04f254c7debaf36ecd6a90b66aed6 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 0a8c172212..e920d89026 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8215,12 +8215,12 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ do{ rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); if( rc ) return rc; - if( iOffset+ovflPageSize>nTotal ){ - ovflPgno = get4byte(pPage->aData + ovflPageSize); + if( iOffset+ovflPageSizeaData); }else{ ovflPageSize = nTotal - iOffset; } - rc = btreeOverwriteContent(pPage, pPage->aData, pX, + rc = btreeOverwriteContent(pPage, pPage->aData+4, pX, iOffset, ovflPageSize); if( rc ) return rc; iOffset += ovflPageSize; From 4f84e9c7e24ceddc645e19491b35d64ec47974f8 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 13:56:23 +0000 Subject: [PATCH 27/60] Add more corruption checking to the cell overwrite logic. FossilOrigin-Name: 58d14afe1e1288d114ea213458b3121e0a95670887861928858b7f143c76f789 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 6 ++++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 210a679733..709d2da340 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Bug\sfixes\sin\sthe\soverwrite\soptimization. -D 2018-05-03T12:57:48.671 +C Add\smore\scorruption\schecking\sto\sthe\scell\soverwrite\slogic. +D 2018-05-03T13:56:23.121 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,7 +434,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 7216dac5e870868de7429e71727fb87cca8057fd01814c18df2e59a5d00d20d5 +F src/btree.c ffaf0f6524095774527460de0ffe362fb463fed2ceecf79acbd93ad517a6f26d F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 489451b378819621537231c1c8a07704437e11c1f5384fd53b09f3977d2213a4 -R b89660c58e0d48e704d46836e0da0214 +P 0cb6cd2a6a596afaa1cca6c5f5abc2ea75d04f254c7debaf36ecd6a90b66aed6 +R 8c38a5f8c55025ab9be63aa068eb2853 U drh -Z 41261a1ee8ebfd1f0c3b6e3f166f7f4d +Z 78d645c2f5a7df7e355a3c554b462bfa diff --git a/manifest.uuid b/manifest.uuid index 88b683be02..c5cf856b0a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0cb6cd2a6a596afaa1cca6c5f5abc2ea75d04f254c7debaf36ecd6a90b66aed6 \ No newline at end of file +58d14afe1e1288d114ea213458b3121e0a95670887861928858b7f143c76f789 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index e920d89026..041c88c763 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8201,6 +8201,9 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ Pgno ovflPgno; /* Next overflow page to write */ u32 ovflPageSize; /* Size to write on overflow page */ + if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){ + return SQLITE_CORRUPT_BKPT; + } /* Overwrite the local portion first */ rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX, 0, pCur->info.nLocal); @@ -8215,6 +8218,9 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ do{ rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); if( rc ) return rc; + if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){ + return SQLITE_CORRUPT_BKPT; + } if( iOffset+ovflPageSizeaData); }else{ From da65fc6e329324f0c50165d48c232def3d44140b Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 14:07:18 +0000 Subject: [PATCH 28/60] The BtCursor.info fields are only valid if info.nSize!=0. FossilOrigin-Name: 54c537eead5b08104cfaf0d5b1e2706e53d6f74be2ca02e06229024fd889fc94 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 709d2da340..fb7c6552f6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\smore\scorruption\schecking\sto\sthe\scell\soverwrite\slogic. -D 2018-05-03T13:56:23.121 +C The\sBtCursor.info\sfields\sare\sonly\svalid\sif\sinfo.nSize!=0. +D 2018-05-03T14:07:18.080 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,7 +434,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c ffaf0f6524095774527460de0ffe362fb463fed2ceecf79acbd93ad517a6f26d +F src/btree.c edb3c69a73cf7c0286dbe040b0ea7069e606e54fd1ee60bbe1e63e56fba0e2b7 F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0cb6cd2a6a596afaa1cca6c5f5abc2ea75d04f254c7debaf36ecd6a90b66aed6 -R 8c38a5f8c55025ab9be63aa068eb2853 +P 58d14afe1e1288d114ea213458b3121e0a95670887861928858b7f143c76f789 +R b073d403d1ba3bd03f4d3e8e8927a6d3 U drh -Z 78d645c2f5a7df7e355a3c554b462bfa +Z e6a7ba3bea7a5cce16673df821a14231 diff --git a/manifest.uuid b/manifest.uuid index c5cf856b0a..6323573dea 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -58d14afe1e1288d114ea213458b3121e0a95670887861928858b7f143c76f789 \ No newline at end of file +54c537eead5b08104cfaf0d5b1e2706e53d6f74be2ca02e06229024fd889fc94 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 041c88c763..3811c59de7 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8335,7 +8335,7 @@ int sqlite3BtreeInsert( if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ /* The current is currently pointing to the entry that is to be ** overwritten */ - if( pCur->info.nPayload==pX->nData+pX->nZero ){ + if( pCur->info.nSize!=0 && pCur->info.nPayload==pX->nData+pX->nZero ){ return btreeOverwriteCell(pCur, pX); } loc = 0; From d5aa9262a68b04ec0874cd6659dff85e023f30dc Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 16:56:06 +0000 Subject: [PATCH 29/60] Fix various error handling conditions on the cell overwrite optimization. Fix a test case so that it works with the new optimization. FossilOrigin-Name: f89b54f41405ed7e28132f66b8a0c690a087c2412c8f55790c2beabb0b521645 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 21 ++++++++++++--------- test/pager1.test | 2 +- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index fb7c6552f6..481534c358 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sBtCursor.info\sfields\sare\sonly\svalid\sif\sinfo.nSize!=0. -D 2018-05-03T14:07:18.080 +C Fix\svarious\serror\shandling\sconditions\son\sthe\scell\soverwrite\soptimization.\nFix\sa\stest\scase\sso\sthat\sit\sworks\swith\sthe\snew\soptimization. +D 2018-05-03T16:56:06.556 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,7 +434,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c edb3c69a73cf7c0286dbe040b0ea7069e606e54fd1ee60bbe1e63e56fba0e2b7 +F src/btree.c 8faf9ebbecb98f05d75f203fdb2421e47a60f1edef3192af8fc7691cb979895c F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e @@ -1131,7 +1131,7 @@ F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03 F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17 F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f -F test/pager1.test f596d3bd53ce96e1d87d44d223d2ae6c8867dd782c425e5eb28b5721fa6aaa97 +F test/pager1.test a32ce299ed01ffb06e84a3af467ae1f3389786b316f40c4359f442c79144736b F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370 F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 58d14afe1e1288d114ea213458b3121e0a95670887861928858b7f143c76f789 -R b073d403d1ba3bd03f4d3e8e8927a6d3 +P 54c537eead5b08104cfaf0d5b1e2706e53d6f74be2ca02e06229024fd889fc94 +R e3474d8063bbcdfd90a9f2049be513c8 U drh -Z e6a7ba3bea7a5cce16673df821a14231 +Z a88b0406803dcfd2b3d768953d03cd3c diff --git a/manifest.uuid b/manifest.uuid index 6323573dea..2ad022bdcb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -54c537eead5b08104cfaf0d5b1e2706e53d6f74be2ca02e06229024fd889fc94 \ No newline at end of file +f89b54f41405ed7e28132f66b8a0c690a087c2412c8f55790c2beabb0b521645 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 3811c59de7..9dc91fe982 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8176,7 +8176,9 @@ static int btreeOverwriteContent( if( nDatapData) + iOffset, iAmt)!=0 ){ @@ -8219,18 +8221,19 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); if( rc ) return rc; if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){ - return SQLITE_CORRUPT_BKPT; - } - if( iOffset+ovflPageSizeaData); + rc = SQLITE_CORRUPT_BKPT; }else{ - ovflPageSize = nTotal - iOffset; + if( iOffset+ovflPageSizeaData); + }else{ + ovflPageSize = nTotal - iOffset; + } + rc = btreeOverwriteContent(pPage, pPage->aData+4, pX, + iOffset, ovflPageSize); } - rc = btreeOverwriteContent(pPage, pPage->aData+4, pX, - iOffset, ovflPageSize); + sqlite3PagerUnref(pPage->pDbPage); if( rc ) return rc; iOffset += ovflPageSize; - sqlite3PagerUnref(pPage->pDbPage); }while( iOffset 15000 } {1} From 4d79983ca5a10382584bfcaaea1263130333b6e4 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 19:47:14 +0000 Subject: [PATCH 30/60] Optimizations to the new EQP framework. FossilOrigin-Name: 956fef361a795bd081d8e23ce4075dc8aafcee63ab7275d13b657b529d185b30 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/expr.c | 2 -- src/select.c | 17 +---------------- src/sqliteInt.h | 3 --- src/treeview.c | 4 ++-- src/vdbe.h | 2 -- 7 files changed, 14 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index a51339acd3..c007b73237 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sEXPLAIN\sQUERY\sPLAN\sto\sreport\sthe\sgeneration\sof\sconstant\srows\susing\nVALUES\sor\sjust\sa\sSELECT\swithout\sFROM. -D 2018-05-03T01:37:13.698 +C Optimizations\sto\sthe\snew\sEQP\sframework. +D 2018-05-03T19:47:14.896 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -445,7 +445,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c b0f90749e22d5e41a12dbf940f4811138cf97da54b46b737089b93eb64a2896f -F src/expr.c 1757b6896ac542df8a90c0e00badc752abd90e04a852b7a947e33e94ee1fb46d +F src/expr.c af4a81a385277510bfc56df87c25d76fc365f98c33bc8797c4a8d84b88e31013 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c 94f42cba2cc1c34aeaa441022ba0170ec3fec4bba54db4e0ded085c6dc0fdc51 @@ -493,12 +493,12 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c e612d71bc58cad38f06c9ebb9e71fa2a9f643d5775f220388b7ba17df5fe21e3 +F src/select.c 75ae3000bef42ea6a7271cf49f6bc5e94bdbf73026ddea251f2a8b6cf14960fd F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 F src/sqlite.h.in d669de545f18f2f01362de02e309cd7f15185958c71bac8f53cd5438b46d2bea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d -F src/sqliteInt.h 4095263176d49601f27086b7e66ca541923b72a909187923e3b45e60511cfe2a +F src/sqliteInt.h 7fbd839f07d873a877375138f2681453232e2e2de8f48be65888e295cd05ced3 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -556,7 +556,7 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97 -F src/treeview.c 6cea286ca9af8b126dae9714799265353387244eba0d451c3cc2cd60946cc4c7 +F src/treeview.c 06dd506b1dcef01c5882a4189bc79afe2660dd992702f81cd7d003425a99cfbc F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995 F src/update.c 5be2f501ddc704fc04183bdb28b25eab930bb8553d973429a089ec94fa85cf2b F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 @@ -564,7 +564,7 @@ F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5 F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55 -F src/vdbe.h dc29bf94721964da367debfc4472f5546e910b26f66850a8936ae4db174699d8 +F src/vdbe.h d970d9738efdd09cb2df73e3a40856e7df13e88a3486789c49fcdd322c9eb8a2 F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858 F src/vdbeaux.c 58129ae46be079613df5c2c3714d80a78605415bfa10c9528634c7c2d2147727 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P dab5e5294813891469660cceb211ac1a1e526715bb57dcdbb1ab90321e6a4dad -R 53c64522178e60b44f774331a15b70e5 +P c75eee69fa8a9b56ee58a4cc539e80cc982f43390dc3a357344d58479dd89a41 +R ba11e840f6b4dabe2ff8e2cc2c44e56d U drh -Z 33f2e8b7048beb839b528a03308b5edb +Z 9f22c447b8f96bef0e022f4dc0cb4f93 diff --git a/manifest.uuid b/manifest.uuid index 4dc52e5fa5..e64df66110 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c75eee69fa8a9b56ee58a4cc539e80cc982f43390dc3a357344d58479dd89a41 \ No newline at end of file +956fef361a795bd081d8e23ce4075dc8aafcee63ab7275d13b657b529d185b30 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index f2f1a86105..6aff83a256 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2646,7 +2646,6 @@ int sqlite3CodeSubselect( ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY", jmpIfDynamic>=0?"":"CORRELATED " )); - ExplainQueryPlanSetId(pParse, pSelect); assert( !isRowid ); /* If the LHS and RHS of the IN operator do not match, that ** error will have been caught long before we reach this point. */ @@ -2770,7 +2769,6 @@ int sqlite3CodeSubselect( pSel = pExpr->x.pSelect; ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY", jmpIfDynamic>=0?"":"CORRELATED ")); - ExplainQueryPlanSetId(pParse, pSel); nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); pParse->nMem += nReg; diff --git a/src/select.c b/src/select.c index 14e485b2b3..065cdf7519 100644 --- a/src/select.c +++ b/src/select.c @@ -147,9 +147,6 @@ Select *sqlite3SelectNew( pNew->iOffset = 0; #if SELECTTRACE_ENABLED pNew->zSelName[0] = 0; -#endif -#if SELECTTRACE_ENABLED || !defined(SQLITE_OMIT_EXPLAIN) - pNew->iSelectId = 0; #endif pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; @@ -2291,7 +2288,6 @@ static void generateWithRecursiveQuery( /* Store the results of the setup-query in Queue. */ pSetup->pNext = 0; ExplainQueryPlan((pParse, 1, "SETUP")); - ExplainQueryPlanSetId(pParse, pSetup); rc = sqlite3Select(pParse, pSetup, &destQueue); pSetup->pNext = p; if( rc ) goto end_of_recursive_query; @@ -2327,7 +2323,6 @@ static void generateWithRecursiveQuery( }else{ p->pPrior = 0; ExplainQueryPlan((pParse, 1, "RECURSIVE STEP")); - ExplainQueryPlanSetId(pParse, p); sqlite3Select(pParse, p, &destQueue); assert( p->pPrior==0 ); p->pPrior = pSetup; @@ -2492,12 +2487,9 @@ static int multiSelect( }else{ #ifndef SQLITE_OMIT_EXPLAIN - if( p->pNext==0 ){ - ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); - } if( pPrior->pPrior==0 ){ + ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); - ExplainQueryPlanSetId(pParse, pPrior); } #endif @@ -2528,7 +2520,6 @@ static int multiSelect( } } ExplainQueryPlan((pParse, 1, "UNION ALL")); - ExplainQueryPlanSetId(pParse, p); rc = sqlite3Select(pParse, p, &dest); testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; @@ -2599,7 +2590,6 @@ static int multiSelect( uniondest.eDest = op; ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", selectOpName(p->op))); - ExplainQueryPlanSetId(pParse, p); rc = sqlite3Select(pParse, p, &uniondest); testcase( rc!=SQLITE_OK ); /* Query flattening in sqlite3Select() might refill p->pOrderBy. @@ -2678,7 +2668,6 @@ static int multiSelect( intersectdest.iSDParm = tab2; ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", selectOpName(p->op))); - ExplainQueryPlanSetId(pParse, p); rc = sqlite3Select(pParse, p, &intersectdest); testcase( rc!=SQLITE_OK ); pDelete = p->pPrior; @@ -3186,7 +3175,6 @@ static int multiSelectOrderBy( VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; ExplainQueryPlan((pParse, 1, "LEFT")); - ExplainQueryPlanSetId(pParse, pPrior); sqlite3Select(pParse, pPrior, &destA); sqlite3VdbeEndCoroutine(v, regAddrA); sqlite3VdbeJumpHere(v, addr1); @@ -3202,7 +3190,6 @@ static int multiSelectOrderBy( p->iLimit = regLimitB; p->iOffset = 0; ExplainQueryPlan((pParse, 1, "RIGHT")); - ExplainQueryPlanSetId(pParse, p); sqlite3Select(pParse, p, &destB); p->iLimit = savedLimit; p->iOffset = savedOffset; @@ -5575,7 +5562,6 @@ int sqlite3Select( pItem->addrFillSub = addrTop; sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); ExplainQueryPlan((pParse, 1, "CO-ROUTINE 0x%p", pSub)); - ExplainQueryPlanSetId(pParse, pSub); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowLogEst = pSub->nSelectRow; pItem->fg.viaCoroutine = 1; @@ -5615,7 +5601,6 @@ int sqlite3Select( }else{ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); ExplainQueryPlan((pParse, 1, "MATERIALIZE 0x%p", pSub)); - ExplainQueryPlanSetId(pParse,pSub); sqlite3Select(pParse, pSub, &dest); } pItem->pTab->nRowLogEst = pSub->nSelectRow; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 74a08c0308..751174d6f4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2780,9 +2780,6 @@ struct Select { int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ #if SELECTTRACE_ENABLED char zSelName[12]; /* Symbolic name of this SELECT use for debugging */ -#endif -#if defined(SQLITETRACE_ENABLED) || !defined(SQLITE_OMIT_EXPLAIN) - u32 iSelectId; /* EXPLAIN QUERY PLAN select ID */ #endif int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ SrcList *pSrc; /* The FROM clause */ diff --git a/src/treeview.c b/src/treeview.c index 51fa7f06ca..562743e9d8 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -141,10 +141,10 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ do{ #if SELECTTRACE_ENABLED sqlite3TreeViewLine(pView, - "SELECT%s%s (%s/%d/%p) selFlags=0x%x nSelectRow=%d", + "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), - p->zSelName, p->iSelectId, p, p->selFlags, + p->zSelName, p, p->selFlags, (int)p->nSelectRow ); #else diff --git a/src/vdbe.h b/src/vdbe.h index b7f44ca913..3177570a01 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -205,12 +205,10 @@ VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); # define ExplainQueryPlan(P) sqlite3VdbeExplain P # define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P) # define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P) -# define ExplainQueryPlanSetId(P,S) (S)->iSelectId=(P)->addrExplain #else # define ExplainQueryPlan(P) # define ExplainQueryPlanPop(P) # define ExplainQueryPlanParent(P) 0 -# define ExplainQueryPlanSetId(P,S) #endif void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); From 34b27edc80d922537ed0a152e5cba023dd4e2532 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 21:51:30 +0000 Subject: [PATCH 31/60] Improved security for VACUUM. This check-in combines the fixes of [ab0d99d0b5ede] and [27754b74ddf646] in a way that is less likely to to be broken by future changes. FossilOrigin-Name: 260fc696538b195e8decabaab46771f664fb829b539efa86fb0b8170db01fa0a --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/vacuum.c | 14 ++++++++++---- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 04373ccc95..0e24703e4b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Overhaul\sof\sEXPLAIN\sQUERY\sPLAN.\sThe\soutput\sis\snow\sin\sthe\sform\sof\sa\stree.\nMore\sdetails\sof\sthe\squery\splan\sare\sshown,\sand\swhat\sis\sshown\sis\struer\sto\swhat\nactually\shappens. -D 2018-05-03T19:56:50.453 +C Improved\ssecurity\sfor\sVACUUM.\s\sThis\scheck-in\scombines\sthe\sfixes\nof\s[ab0d99d0b5ede]\sand\s[27754b74ddf646]\sin\sa\sway\sthat\sis\sless\slikely\sto\nto\sbe\sbroken\sby\sfuture\schanges. +D 2018-05-03T21:51:30.697 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -562,7 +562,7 @@ F src/update.c 5be2f501ddc704fc04183bdb28b25eab930bb8553d973429a089ec94fa85cf2b F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 -F src/vacuum.c 593498d6d1f1f3c5561c1476132d3b03af33881ff9f27ce4e48d4ba60be3615d +F src/vacuum.c 37730af7540033135909ecaee3667dddec043293428d8718546d0d64ba4a5025 F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55 F src/vdbe.h d970d9738efdd09cb2df73e3a40856e7df13e88a3486789c49fcdd322c9eb8a2 F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 @@ -1727,8 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ab0d99d0b5edece4c639baa47ce1ca2c02774cb2515e5b7f36d9bd312ccd3310 956fef361a795bd081d8e23ce4075dc8aafcee63ab7275d13b657b529d185b30 -R 067c5aa8ed93f027a9f18eeeee2f55ff -T +closed 956fef361a795bd081d8e23ce4075dc8aafcee63ab7275d13b657b529d185b30 +P ff01bbdabc4b9db3db8b928979442c91b32d72082158e4f5fe62ae51a73649d2 +R 89cb977cf2a7974b23a1ffc22bfe7f69 U drh -Z b328f3a1ea4d4f9e8fb3fe9715c4ed00 +Z b164f882a3399333cea7fc0c8706c738 diff --git a/manifest.uuid b/manifest.uuid index db0983069a..425caf4338 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ff01bbdabc4b9db3db8b928979442c91b32d72082158e4f5fe62ae51a73649d2 \ No newline at end of file +260fc696538b195e8decabaab46771f664fb829b539efa86fb0b8170db01fa0a \ No newline at end of file diff --git a/src/vacuum.c b/src/vacuum.c index 103aee0bd4..fe295147c5 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -39,8 +39,14 @@ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); - assert( sqlite3_strnicmp(zSubSql,"SELECT",6)!=0 || CORRUPT_DB ); - if( zSubSql && zSubSql[0]!='S' ){ + /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX, + ** or INSERT. Historically there have been attacks that first + ** corrupt the sqlite_master.sql field with other kinds of statements + ** then run VACUUM to get those statements to execute at inappropriate + ** times. */ + if( zSubSql + && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0) + ){ rc = execSql(db, pzErrMsg, zSubSql); if( rc!=SQLITE_OK ) break; } @@ -247,13 +253,13 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ rc = execSqlF(db, pzErrMsg, "SELECT sql FROM \"%w\".sqlite_master" " WHERE type='table'AND name<>'sqlite_sequence'" - " AND coalesce(rootpage,1)>0 AND sql LIKE 'CREATE%%'", + " AND coalesce(rootpage,1)>0", zDbMain ); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = execSqlF(db, pzErrMsg, "SELECT sql FROM \"%w\".sqlite_master" - " WHERE type='index' AND length(sql)>10", + " WHERE type='index'", zDbMain ); if( rc!=SQLITE_OK ) goto end_of_vacuum; From 5e8b9853dacc844dfe7fc9a5f363350627644390 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 May 2018 22:52:56 +0000 Subject: [PATCH 32/60] Fix a branch that has become unreachable due to recent enhancements. FossilOrigin-Name: 81ab5e0d106fb9f2de80d17c8167d8542c6721b8d7ec69c43e1571c2dcadeddd --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 0e24703e4b..6986fa5d3f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\ssecurity\sfor\sVACUUM.\s\sThis\scheck-in\scombines\sthe\sfixes\nof\s[ab0d99d0b5ede]\sand\s[27754b74ddf646]\sin\sa\sway\sthat\sis\sless\slikely\sto\nto\sbe\sbroken\sby\sfuture\schanges. -D 2018-05-03T21:51:30.697 +C Fix\sa\sbranch\sthat\shas\sbecome\sunreachable\sdue\sto\srecent\senhancements. +D 2018-05-03T22:52:56.038 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -493,7 +493,7 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 75ae3000bef42ea6a7271cf49f6bc5e94bdbf73026ddea251f2a8b6cf14960fd +F src/select.c c937eb1fc32417fb0be022ab8372dd27ff8138242a8d377724996d817258bd8a F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 F src/sqlite.h.in 469aed42e75193b7f5d88d812befa961c04746869475f96fcf434c9f67079f66 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ff01bbdabc4b9db3db8b928979442c91b32d72082158e4f5fe62ae51a73649d2 -R 89cb977cf2a7974b23a1ffc22bfe7f69 +P 260fc696538b195e8decabaab46771f664fb829b539efa86fb0b8170db01fa0a +R 9efc9c5b7f70976e1122ef5263d6cddb U drh -Z b164f882a3399333cea7fc0c8706c738 +Z f48c0146f4c18019bae878d6a3510a09 diff --git a/manifest.uuid b/manifest.uuid index 425caf4338..dbcc29393e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -260fc696538b195e8decabaab46771f664fb829b539efa86fb0b8170db01fa0a \ No newline at end of file +81ab5e0d106fb9f2de80d17c8167d8542c6721b8d7ec69c43e1571c2dcadeddd \ No newline at end of file diff --git a/src/select.c b/src/select.c index 065cdf7519..612ee7664d 100644 --- a/src/select.c +++ b/src/select.c @@ -1760,7 +1760,7 @@ static void generateColumnNames( } #endif - if( pParse->colNamesSet || db->mallocFailed ) return; + if( pParse->colNamesSet ) return; /* Column names are determined by the left-most term of a compound select */ while( pSelect->pPrior ) pSelect = pSelect->pPrior; SELECTTRACE(1,pParse,pSelect,("generating column names\n")); From 5d72d9245d1d8c8d5ce2ac1528318ceb8c570898 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 May 2018 00:39:43 +0000 Subject: [PATCH 33/60] Make a separate limb in the EXPLAIN QUERY PLAN output for the various lines associated with the OR-optimization. FossilOrigin-Name: 75ac7b4e4fd0811ca80c719badacff207e0bbd00ac64dde3b3d4ec676fad472d --- ext/expert/expert1.test | 5 +++-- manifest | 29 ++++++++++++++--------------- manifest.uuid | 2 +- src/wherecode.c | 2 ++ test/bestindex3.test | 15 +++++++++------ test/cost.test | 17 ++++++++++------- test/eqp.test | 10 ++++++---- test/join5.test | 5 +++-- test/where7.test | 5 +++-- test/where9.test | 15 +++++++++------ test/whereI.test | 10 ++++++---- 11 files changed, 66 insertions(+), 49 deletions(-) diff --git a/ext/expert/expert1.test b/ext/expert/expert1.test index 1eab80e070..6db6944083 100644 --- a/ext/expert/expert1.test +++ b/ext/expert/expert1.test @@ -242,8 +242,9 @@ do_setup_rec_test $tn.12.1 { } { CREATE INDEX t7_idx_00000062 ON t7(b); CREATE INDEX t7_idx_00000061 ON t7(a); - SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?) - SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?) + MULTI-INDEX OR + SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?) + SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?) } # rowid terms. diff --git a/manifest b/manifest index 10dd58464e..d74d678251 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sORDER\sBY\sLIMIT\squeries,\stry\sto\sevaluate\sthe\sORDER\sBY\sterms\sfirst,\sand\sit\nit\sbecomes\sclear\sthat\sthe\srow\swill\snot\scome\sin\sunder\sthe\sLIMIT,\sthen\sskip\nevaluation\sof\sthe\sother\scolumns. -D 2018-05-03T23:20:06.057 +C Make\sa\sseparate\slimb\sin\sthe\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\sthe\svarious\slines\nassociated\swith\sthe\sOR-optimization. +D 2018-05-04T00:39:43.856 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -44,7 +44,7 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74 F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3 F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4 -F ext/expert/expert1.test 81c8834822181d009c08b18d2afb3b0fce8167a8bbbf23496a0e598d2b21623d +F ext/expert/expert1.test 87e54effda905d991edfe4bcd28098460a568246129ab7263f71b25420ea727f F ext/expert/sqlite3expert.c 95fdee74be2912d962951d984f1123e55d3f44bd643da7a48ff6ea9426a47f69 F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811 F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72 @@ -579,7 +579,7 @@ F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f F src/where.c aa94ef44ef36763817ca952e68c03db7eee5e2d4f1f0c3a98823a58c074157bd F src/whereInt.h 2610cb87dd95509995b63decc674c60f2757697a206cfe0c085ee53d9c43cfff -F src/wherecode.c 3368f0797a4b166e0773a4137d270d92ddcbce91618b11d1e9f11f7c39f33068 +F src/wherecode.c 300f945eb4552fb82ccf237b34dccb22f47522882faa9adcc04388e6e3f1d4b0 F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -646,7 +646,7 @@ F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928 -F test/bestindex3.test 92a34c82f1ae245ef71f8c999f50a9dccd097a310cb070244c7b5cd0d2e07d73 +F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455 F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c @@ -723,7 +723,7 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454 F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4 F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4 F test/corruptK.test 91550557849244a9904f4e090052e3f2c1c3f1106840d58b00ffaa3a8c2d3fc0 -F test/cost.test dadd9905a9f34631a1821ff3d1b3e571ebad8afcd14ba0dca6d0818d9fd91237 +F test/cost.test b37db8a10d467a69e71a9f3d40bbb266c2f587742b37c6912f6e3f7185a0e216 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f @@ -791,7 +791,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473 F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6 F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020 -F test/eqp.test 2ac18a1d6aa0a0a8f0eea1cc0ba7d63391e2f968a47f59643f889c7c87d238a4 +F test/eqp.test 4fd69d25f21d8679f5fce13e639975879d89abf6acce4bd9cede133b7482aba7 F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9 F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3 @@ -1012,7 +1012,7 @@ F test/join.test 2ad9d7fe10e0cc06bc7803c22e5533be11cdadbc592f5f95d789a873b57a5a6 F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 -F test/join5.test 196e0cbb552dd91815a43b5a26b64d40bdf9ff881c7a8413821dbd5f7154e3f8 +F test/join5.test 5a2da0c3ea852a7063d3e72fc7d5a04a6de5ef6e6d85092582f69033f7459adc F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4 @@ -1588,9 +1588,9 @@ F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcd F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b -F test/where7.test 9bfbfdf0ee238f15a6eea29060f4bb22e8b43b724efe67fd8bf6febfbe54429d +F test/where7.test e579da972eb3372edc9de850efc221848c763f9e4feafc8426d84a4453b92b23 F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f -F test/where9.test 74f9dfddb42016d13b6ab0f6c943d7b993da9b2f7303faa2d465e02e340c2b5e +F test/where9.test ad2ddb339d10d324763c3da60502b8631f15a2397b869192fbd4e82f40e167d3 F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4 F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6 @@ -1599,7 +1599,7 @@ F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89 F test/whereG.test 0158783235a6dd82fc0e37652b8522b186b9510594ac0a4bff0c4101b4396a52 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 -F test/whereI.test 0f30efab13000309f340cada83f5cf888814de0d056431fb2f0251a91c58becf +F test/whereI.test b7769ee8dbefd987fb266715fee887f05f9ff180016b06fca7fa402df739193b F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 @@ -1727,8 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 81ab5e0d106fb9f2de80d17c8167d8542c6721b8d7ec69c43e1571c2dcadeddd ce4ef46058f4aaea6623a41255a2e4b69bb24f16a287391df48f6bacdb4c4989 -R df0ac85de3cdeeeca99ef241c3f826a6 -T +closed ce4ef46058f4aaea6623a41255a2e4b69bb24f16a287391df48f6bacdb4c4989 +P c381f0ea57002a264fd958b28e4921cb9c9e73a10fb592f6bb64e6bc9bd16d39 +R 7ee652618bc90464537faa57c51e2376 U drh -Z e934c97462a3a7876abf79aae9b0d67e +Z 3b006aad05b3a8fada8579b5e6d167ef diff --git a/manifest.uuid b/manifest.uuid index 7d6d9e2a00..49b9590029 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c381f0ea57002a264fd958b28e4921cb9c9e73a10fb592f6bb64e6bc9bd16d39 \ No newline at end of file +75ac7b4e4fd0811ca80c719badacff207e0bbd00ac64dde3b3d4ec676fad472d \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index 7f9933fad8..df45bd73e5 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1934,6 +1934,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( ** sub-WHERE clause is to to invoke the main loop body as a subroutine. */ wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); + ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR")); for(ii=0; iinTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ @@ -2054,6 +2055,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( } } } + ExplainQueryPlanPop(pParse); pLevel->u.pCovidx = pCov; if( pCov ) pLevel->iIdxCur = iCovCur; if( pAndExpr ){ diff --git a/test/bestindex3.test b/test/bestindex3.test index 32734ef1a0..4b125d4df0 100644 --- a/test/bestindex3.test +++ b/test/bestindex3.test @@ -89,16 +89,18 @@ do_eqp_test 1.3 { SELECT * FROM t1 WHERE a = 'abc' OR b = 'def'; } { QUERY PLAN - |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ? - `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ? + `--MULTI-INDEX OR + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ? + `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ? } do_eqp_test 1.4 { SELECT * FROM t1 WHERE a LIKE 'abc%' OR b = 'def'; } { QUERY PLAN - |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ? - `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ? + `--MULTI-INDEX OR + |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ? + `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ? } do_execsql_test 1.5 { @@ -147,8 +149,9 @@ ifcapable !icu { SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def' } [string map {"\n " \n} { QUERY PLAN - |--SEARCH TABLE t2 USING INDEX t2x (x>? AND x? AND x? AND b? AND b? AND b? AND b?) `--USE TEMP B-TREE FOR ORDER BY } diff --git a/test/where9.test b/test/where9.test index c04c17fa95..87f5c15615 100644 --- a/test/where9.test +++ b/test/where9.test @@ -363,8 +363,9 @@ ifcapable explain { } [string map {"\n " \n} { QUERY PLAN |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) - |--SEARCH TABLE t2 USING INDEX t2d (d=?) - `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) + `--MULTI-INDEX OR + |--SEARCH TABLE t2 USING INDEX t2d (d=?) + `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) }] do_eqp_test where9-3.2 { SELECT coalesce(t2.a,9999) @@ -373,8 +374,9 @@ ifcapable explain { } [string map {"\n " \n} { QUERY PLAN |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) - |--SEARCH TABLE t2 USING INDEX t2d (d=?) - `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) + `--MULTI-INDEX OR + |--SEARCH TABLE t2 USING INDEX t2d (d=?) + `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) }] } @@ -453,8 +455,9 @@ do_eqp_test where9-5.1 { SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL) } { QUERY PLAN - |--SEARCH TABLE t1 USING INDEX t1c (c=?) - `--SEARCH TABLE t1 USING INDEX t1d (d=?) + `--MULTI-INDEX OR + |--SEARCH TABLE t1 USING INDEX t1c (c=?) + `--SEARCH TABLE t1 USING INDEX t1d (d=?) } # In contrast, b=1000 is preferred over any OR-clause. diff --git a/test/whereI.test b/test/whereI.test index 73dd9009aa..d08e62c376 100644 --- a/test/whereI.test +++ b/test/whereI.test @@ -30,8 +30,9 @@ do_eqp_test 1.1 { SELECT a FROM t1 WHERE b='b' OR c='x' } { QUERY PLAN - |--SEARCH TABLE t1 USING INDEX i1 (b=?) - `--SEARCH TABLE t1 USING INDEX i2 (c=?) + `--MULTI-INDEX OR + |--SEARCH TABLE t1 USING INDEX i1 (b=?) + `--SEARCH TABLE t1 USING INDEX i2 (c=?) } do_execsql_test 1.2 { @@ -59,8 +60,9 @@ do_eqp_test 2.1 { SELECT a FROM t2 WHERE b='b' OR c='x' } { QUERY PLAN - |--SEARCH TABLE t2 USING INDEX i3 (b=?) - `--SEARCH TABLE t2 USING INDEX i4 (c=?) + `--MULTI-INDEX OR + |--SEARCH TABLE t2 USING INDEX i3 (b=?) + `--SEARCH TABLE t2 USING INDEX i4 (c=?) } do_execsql_test 2.2 { From e632ae796af794c442bd6365fd37eb1f72cf537e Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 May 2018 04:49:55 +0000 Subject: [PATCH 34/60] For the amalgamation-tarball, enable FTS5 and JSON1 by default and provide a new --enable-debug option that actives debugging facilities. FossilOrigin-Name: 03edecaf9dcfc927aa60c2a17590a432b17de1647d480d277b4aafc8018c2d20 --- autoconf/Makefile.am | 2 +- autoconf/configure.ac | 20 ++++++++++++++++---- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am index db246924fe..8abf15a7f9 100644 --- a/autoconf/Makefile.am +++ b/autoconf/Makefile.am @@ -1,5 +1,5 @@ -AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE +AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE @DEBUG_FLAGS@ lib_LTLIBRARIES = libsqlite3.la libsqlite3_la_SOURCES = sqlite3.c diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 2680becbb0..8ba221891a 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -115,8 +115,8 @@ AC_SUBST(DYNAMIC_EXTENSION_FLAGS) # --enable-fts5 # AC_ARG_ENABLE(fts5, [AS_HELP_STRING( - [--enable-fts5], [include fts5 support [default=no]])], - [], [enable_fts5=no]) + [--enable-fts5], [include fts5 support [default=yes]])], + [], [enable_fts5=yes]) if test x"$enable_fts5" = "xyes"; then AC_SEARCH_LIBS(log, m) FTS5_FLAGS=-DSQLITE_ENABLE_FTS5 @@ -128,8 +128,8 @@ AC_SUBST(FTS5_FLAGS) # --enable-json1 # AC_ARG_ENABLE(json1, [AS_HELP_STRING( - [--enable-json1], [include json1 support [default=no]])], - [], [enable_json1=no]) + [--enable-json1], [include json1 support [default=yes]])], + [], [enable_json1=yes]) if test x"$enable_json1" = "xyes"; then JSON1_FLAGS=-DSQLITE_ENABLE_JSON1 fi @@ -148,6 +148,18 @@ fi AC_SUBST(SESSION_FLAGS) #----------------------------------------------------------------------- +#----------------------------------------------------------------------- +# --enable-debug +# +AC_ARG_ENABLE(debug, [AS_HELP_STRING( + [--enable-debug], [build with debugging features enabled [default=no]])], + [], [enable_session=no]) +if test x"$enable_debug" = "xyes"; then + DEBUG_FLAGS="-DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE" +fi +AC_SUBST(DEBUG_FLAGS) +#----------------------------------------------------------------------- + #----------------------------------------------------------------------- # --enable-static-shell # diff --git a/manifest b/manifest index d74d678251..020df1ace2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\sa\sseparate\slimb\sin\sthe\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\sthe\svarious\slines\nassociated\swith\sthe\sOR-optimization. -D 2018-05-04T00:39:43.856 +C For\sthe\samalgamation-tarball,\senable\sFTS5\sand\sJSON1\sby\sdefault\sand\nprovide\sa\snew\s--enable-debug\soption\sthat\sactives\sdebugging\sfacilities. +D 2018-05-04T04:49:55.408 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -12,11 +12,11 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 -F autoconf/Makefile.am 2c274948734e03c51790ff51468f91db8d570bcca864284d9c6d6e777264cd7e +F autoconf/Makefile.am f8c274ee0022cb6d48ff103ab6c6b0733c41b3b02cb8566228dfd602f701e0c2 F autoconf/Makefile.msc 6a46d0659d6e4a25346102bcba40a7fb4b0b8b2dc4faabdf0187488c6dd580d6 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 -F autoconf/configure.ac 18fca06f884213be062dd5e07c5297079cc45893d9cd3f522ce426e715033e3d +F autoconf/configure.ac 5f6cf281ae675685335ce7f43f8c2d59d3ac8ba4174a57b8e83097c5e10dcf4e F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c381f0ea57002a264fd958b28e4921cb9c9e73a10fb592f6bb64e6bc9bd16d39 -R 7ee652618bc90464537faa57c51e2376 +P 75ac7b4e4fd0811ca80c719badacff207e0bbd00ac64dde3b3d4ec676fad472d +R 74880026e25b8db18c05670aad508c79 U drh -Z 3b006aad05b3a8fada8579b5e6d167ef +Z b5c68263fba58051d7215e48b06b8ab2 diff --git a/manifest.uuid b/manifest.uuid index 49b9590029..469ae3514f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -75ac7b4e4fd0811ca80c719badacff207e0bbd00ac64dde3b3d4ec676fad472d \ No newline at end of file +03edecaf9dcfc927aa60c2a17590a432b17de1647d480d277b4aafc8018c2d20 \ No newline at end of file From e3d511c078ecf3ccc2e2fcd945e0a2bd3616220b Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 May 2018 18:32:11 +0000 Subject: [PATCH 35/60] Fix requirements marks. No code changes. FossilOrigin-Name: 7fdad122a21e4b01bd678198fd5131dc32febe3af366bd6368505398255f9822 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/e_createtable.test | 4 ++-- test/indexedby.test | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 020df1ace2..bbf7559348 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C For\sthe\samalgamation-tarball,\senable\sFTS5\sand\sJSON1\sby\sdefault\sand\nprovide\sa\snew\s--enable-debug\soption\sthat\sactives\sdebugging\sfacilities. -D 2018-05-04T04:49:55.408 +C Fix\srequirements\smarks.\s\sNo\scode\schanges. +D 2018-05-04T18:32:11.376 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -766,7 +766,7 @@ F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145 F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14 F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579 -F test/e_createtable.test ef30054d1e4cec4d1da2ffcebcc15f1ded3ed7ae80f009019485be973f449917 +F test/e_createtable.test e1c4512b9e15fe7bedbbfc0c6daac8a4af65f32dc3c48310b0135b5735857b26 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5 @@ -984,7 +984,7 @@ F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a6 F test/index7.test 72b59b8ddc5c13f4962886b4011eb9975014317d17ef36c6297921362fb7dd98 F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 -F test/indexedby.test 5a4a451412e3723b36214f2f98acc4ecbb7fd67fd11bbe9fa46ffb6e18cfd987 +F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 75ac7b4e4fd0811ca80c719badacff207e0bbd00ac64dde3b3d4ec676fad472d -R 74880026e25b8db18c05670aad508c79 +P 03edecaf9dcfc927aa60c2a17590a432b17de1647d480d277b4aafc8018c2d20 +R 4f52e7dcc458ba7f262595157e6a17d1 U drh -Z b5c68263fba58051d7215e48b06b8ab2 +Z 0166ce191b6e6f7de3de6a7872e950dc diff --git a/manifest.uuid b/manifest.uuid index 469ae3514f..08c40ca527 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -03edecaf9dcfc927aa60c2a17590a432b17de1647d480d277b4aafc8018c2d20 \ No newline at end of file +7fdad122a21e4b01bd678198fd5131dc32febe3af366bd6368505398255f9822 \ No newline at end of file diff --git a/test/e_createtable.test b/test/e_createtable.test index dae9307313..65cb7f2935 100644 --- a/test/e_createtable.test +++ b/test/e_createtable.test @@ -656,11 +656,11 @@ do_createtable_tests 2.1 -tclquery { 5 "CREATE TABLE x1 AS SELECT count(a) AS a, max(b) FROM t1" {a max(b)} } -# EVIDENCE-OF: R-37111-22855 The declared type of each column is +# EVIDENCE-OF: R-55407-45319 The declared type of each column is # determined by the expression affinity of the corresponding expression # in the result set of the SELECT statement, as follows: Expression # Affinity Column Declared Type TEXT "TEXT" NUMERIC "NUM" INTEGER "INT" -# REAL "REAL" NONE "" (empty string) +# REAL "REAL" BLOB (a.k.a "NONE") "" (empty string) # do_createtable_tests 2.2 -tclquery { table_column_decltypes x1 diff --git a/test/indexedby.test b/test/indexedby.test index 836da80e53..8624b10c75 100644 --- a/test/indexedby.test +++ b/test/indexedby.test @@ -59,7 +59,7 @@ do_eqp_test indexedby-1.4 { # SQL view. Also test that specifying an index that does not exist or # is attached to a different table is detected as an error. # -# EVIDENCE-OF: R-07004-11522 -- syntax diagram qualified-table-name +# X-EVIDENCE-OF: R-07004-11522 -- syntax diagram qualified-table-name # # EVIDENCE-OF: R-58230-57098 The "INDEXED BY index-name" phrase # specifies that the named index must be used in order to look up values From 6fcf83a50334a4bea413c8e078e28ba11e956cd8 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 May 2018 01:23:28 +0000 Subject: [PATCH 36/60] Fix a slightly incorrect corruption detection branch in the btree logic. FossilOrigin-Name: 9191ff670cb7f36e0b2dac4a22888679b639845687aef8edcc3c05e35ba71eda --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index bbf7559348..d6da0b8eb1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\srequirements\smarks.\s\sNo\scode\schanges. -D 2018-05-04T18:32:11.376 +C Fix\sa\sslightly\sincorrect\scorruption\sdetection\sbranch\sin\sthe\sbtree\slogic. +D 2018-05-05T01:23:28.506 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,7 +434,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c fa7da0a5584e5182b92536bc4b7622a154a468997a075d5901345efb79a05ffe +F src/btree.c 79982b0779c27e5ccde8c3e540f14b4e82586d6ec0394a7eb08be72d20c3e894 F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 03edecaf9dcfc927aa60c2a17590a432b17de1647d480d277b4aafc8018c2d20 -R 4f52e7dcc458ba7f262595157e6a17d1 +P 7fdad122a21e4b01bd678198fd5131dc32febe3af366bd6368505398255f9822 +R c749c0665814a70e6af52cc6400bfbb1 U drh -Z 0166ce191b6e6f7de3de6a7872e950dc +Z e525a0897d0f2a68d316a072398c9145 diff --git a/manifest.uuid b/manifest.uuid index 08c40ca527..062607e404 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7fdad122a21e4b01bd678198fd5131dc32febe3af366bd6368505398255f9822 \ No newline at end of file +9191ff670cb7f36e0b2dac4a22888679b639845687aef8edcc3c05e35ba71eda \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 700138efca..a3794b3f2f 100644 --- a/src/btree.c +++ b/src/btree.c @@ -6226,7 +6226,9 @@ static int clearCell( if( pInfo->nLocal==pInfo->nPayload ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } - if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ + testcase( pCell + pInfo->nSize == pPage->aDataEnd ); + testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd ); + if( pCell + pInfo->nSize > pPage->aDataEnd ){ /* Cell extends past end of page */ return SQLITE_CORRUPT_PAGE(pPage); } From c6f36fa33ad4d2f8642331516ba1a7ed7af60b1b Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 May 2018 16:50:35 +0000 Subject: [PATCH 37/60] In an ORDER BY LIMIT, make sure the ORDER BY expression evaluator does not try to reuse values from the result set if the result set has not yet be computed. This fixes a bug in the recent deferred-row loading optimization, check-in [c381f0ea57002a264fd958b28e]. OSSFuzz discovered the problem. FossilOrigin-Name: 5d61e75f32de09c81dbe844443209f063cccb005d60b846900de5b023643fc3b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 8 +++++--- test/orderby1.test | 10 ++++++++++ 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index d6da0b8eb1..6ea3748e5f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sslightly\sincorrect\scorruption\sdetection\sbranch\sin\sthe\sbtree\slogic. -D 2018-05-05T01:23:28.506 +C In\san\sORDER\sBY\sLIMIT,\smake\ssure\sthe\sORDER\sBY\sexpression\sevaluator\sdoes\snot\ntry\sto\sreuse\svalues\sfrom\sthe\sresult\sset\sif\sthe\sresult\sset\shas\snot\syet\nbe\scomputed.\s\sThis\sfixes\sa\sbug\sin\sthe\srecent\sdeferred-row\sloading\s\noptimization,\scheck-in\s[c381f0ea57002a264fd958b28e].\nOSSFuzz\sdiscovered\sthe\sproblem. +D 2018-05-05T16:50:35.778 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -493,7 +493,7 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c bf9185f40cbb98a1342c0149f66dff3fbadf262081305519927523b4ec7b876e +F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 F src/sqlite.h.in 469aed42e75193b7f5d88d812befa961c04746869475f96fcf434c9f67079f66 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1118,7 +1118,7 @@ F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 F test/optfuzz-db01.c a0c256905c8ac79f9a5de2f374a3d9f757bef0dca2a238dc7c10cc8a38031834 F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041 F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1 -F test/orderby1.test bb8535f52c42e91cfa110622ccff70597e531198bb4b033185ad84c11522ab1b +F test/orderby1.test e4501f54721f804ca56922e253403ac6775f88e9f07569994ce99212b3ca5b10 F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04 F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99 F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7fdad122a21e4b01bd678198fd5131dc32febe3af366bd6368505398255f9822 -R c749c0665814a70e6af52cc6400bfbb1 +P 9191ff670cb7f36e0b2dac4a22888679b639845687aef8edcc3c05e35ba71eda +R a56d2b47132e721ba501356936c97e91 U drh -Z e525a0897d0f2a68d316a072398c9145 +Z 1741a532a82a49137514437ac680f600 diff --git a/manifest.uuid b/manifest.uuid index 062607e404..0b9467a81c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9191ff670cb7f36e0b2dac4a22888679b639845687aef8edcc3c05e35ba71eda \ No newline at end of file +5d61e75f32de09c81dbe844443209f063cccb005d60b846900de5b023643fc3b \ No newline at end of file diff --git a/src/select.c b/src/select.c index c5d4612032..3818ef5170 100644 --- a/src/select.c +++ b/src/select.c @@ -627,9 +627,10 @@ static void pushOntoSorter( ** case regData==regOrigData. ** (3) Some output columns are omitted from the sort record due to ** the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the - ** SQLITE_ECEL_OMITREF optimization. In that case, regOrigData==0 - ** to prevent this routine from trying to copy values that might - ** not exist. + ** SQLITE_ECEL_OMITREF optimization, or due to the + ** SortCtx.pDeferredRowLoad optimiation. In any of these cases + ** regOrigData is 0 to prevent this routine from trying to copy + ** values that might not yet exist. */ assert( nData==1 || regData==regOrigData || regOrigData==0 ); @@ -1010,6 +1011,7 @@ static void selectInnerLoop( assert( pSort!=0 ); assert( hasDistinct==0 ); pSort->pDeferredRowLoad = &sRowLoadInfo; + regOrig = 0; }else{ innerLoopLoadRow(pParse, p, &sRowLoadInfo); } diff --git a/test/orderby1.test b/test/orderby1.test index 13bd7bfb5a..836ca4b83b 100644 --- a/test/orderby1.test +++ b/test/orderby1.test @@ -548,5 +548,15 @@ do_execsql_test 9.0 { SELECT (SELECT x||y FROM t2, t1 ORDER BY x, y); } {13} +# Problem found by OSSFuzz on 2018-05-05. This was caused by a new +# optimization that had not been previously released. +# +do_execsql_test 10.0 { + CREATE TABLE t10(a,b); + INSERT INTO t10 VALUES(1,2),(8,9),(3,4),(5,4),(0,7); + CREATE INDEX t10b ON t10(b); + SELECT b, rowid, '^' FROM t10 ORDER BY b, a LIMIT 4; +} {2 1 ^ 4 3 ^ 4 4 ^ 7 5 ^} + finish_test From 60208c34bb9de22efd746480ab45d6c2620e394a Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 7 May 2018 02:50:38 +0000 Subject: [PATCH 38/60] Backout change [05fee1a21ea398f1e4d6f1cf3] because it does not take into account the LD_LIBRARY_PATH environment variable used by dl_open(). FossilOrigin-Name: b348d1193a7a3ed4d3e656b6cc95a41f87eae29222e0723850a5eb5ffabffd00 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/loadext.c | 4 +--- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 6ea3748e5f..75de358840 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\san\sORDER\sBY\sLIMIT,\smake\ssure\sthe\sORDER\sBY\sexpression\sevaluator\sdoes\snot\ntry\sto\sreuse\svalues\sfrom\sthe\sresult\sset\sif\sthe\sresult\sset\shas\snot\syet\nbe\scomputed.\s\sThis\sfixes\sa\sbug\sin\sthe\srecent\sdeferred-row\sloading\s\noptimization,\scheck-in\s[c381f0ea57002a264fd958b28e].\nOSSFuzz\sdiscovered\sthe\sproblem. -D 2018-05-05T16:50:35.778 +C Backout\schange\s[05fee1a21ea398f1e4d6f1cf3]\sbecause\sit\sdoes\snot\stake\sinto\naccount\sthe\sLD_LIBRARY_PATH\senvironment\svariable\sused\sby\sdl_open(). +D 2018-05-07T02:50:38.426 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -456,7 +456,7 @@ F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 33a2c72b6182e8ddf697d604cc087c77ff5fc512a32b8b624641d41b390e249e F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e -F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302 +F src/loadext.c 5b89b8ca83a2f8d1f0f8c577ca45beff2e6f9124a3204600da8e22ce8b499649 F src/main.c b56b2d62d5d11e3f5100b25fca34c13c62a0fe73941f6873454a7fa8a454170d F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9191ff670cb7f36e0b2dac4a22888679b639845687aef8edcc3c05e35ba71eda -R a56d2b47132e721ba501356936c97e91 +P 5d61e75f32de09c81dbe844443209f063cccb005d60b846900de5b023643fc3b +R b7e54ff139c007de5ac3db8f0e73a2f9 U drh -Z 1741a532a82a49137514437ac680f600 +Z 77e1a082dc787694600210821f90bcd3 diff --git a/manifest.uuid b/manifest.uuid index 0b9467a81c..a119648e0b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5d61e75f32de09c81dbe844443209f063cccb005d60b846900de5b023643fc3b \ No newline at end of file +b348d1193a7a3ed4d3e656b6cc95a41f87eae29222e0723850a5eb5ffabffd00 \ No newline at end of file diff --git a/src/loadext.c b/src/loadext.c index cf58237bf9..04c12958a9 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -500,10 +500,8 @@ static int sqlite3LoadExtension( #if SQLITE_OS_UNIX || SQLITE_OS_WIN for(ii=0; ii Date: Mon, 7 May 2018 11:29:59 +0000 Subject: [PATCH 39/60] Fix harmless compiler warnings in the cell-overwrite logic. FossilOrigin-Name: 3e11dc3183bc3e8ec49af244a8e8b3e07d12f7a2e59028b2bf64ce0ab589a91f --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 9 +++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index a19a336799..363640929f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\senhancements\sfrom\strunk. -D 2018-05-04T19:18:27.186 +C Fix\sharmless\scompiler\swarnings\sin\sthe\scell-overwrite\slogic. +D 2018-05-07T11:29:59.385 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,7 +434,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 8faf9ebbecb98f05d75f203fdb2421e47a60f1edef3192af8fc7691cb979895c +F src/btree.c b4ca692c0c557bba653412a0c3347f0e5c140e759f0d8349383b7de7281ad99e F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f89b54f41405ed7e28132f66b8a0c690a087c2412c8f55790c2beabb0b521645 7fdad122a21e4b01bd678198fd5131dc32febe3af366bd6368505398255f9822 -R df1e682f55c594c022a81ad6cca73208 +P 9650f71b82ca1b3759e776bbd8a2e8ca61c51f80038e37c9c9a675a8c13b0b06 +R 0f12e4904e55641cfcfe9534f6ff08d6 U drh -Z 23057790a24d7f2fdd5e77d4df41fcee +Z eb245c54fb26ccb37327155d2c7d476e diff --git a/manifest.uuid b/manifest.uuid index da787b2962..adb6239ec1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9650f71b82ca1b3759e776bbd8a2e8ca61c51f80038e37c9c9a675a8c13b0b06 \ No newline at end of file +3e11dc3183bc3e8ec49af244a8e8b3e07d12f7a2e59028b2bf64ce0ab589a91f \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 9dc91fe982..6dcd435325 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8214,6 +8214,8 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ /* Now overwrite the overflow pages */ iOffset = pCur->info.nLocal; + assert( nTotal>=0 ); + assert( iOffset>=0 ); ovflPgno = get4byte(pCur->info.pPayload + iOffset); pBt = pPage->pBt; ovflPageSize = pBt->usableSize - 4; @@ -8223,7 +8225,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){ rc = SQLITE_CORRUPT_BKPT; }else{ - if( iOffset+ovflPageSizeaData); }else{ ovflPageSize = nTotal - iOffset; @@ -8338,7 +8340,10 @@ int sqlite3BtreeInsert( if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ /* The current is currently pointing to the entry that is to be ** overwritten */ - if( pCur->info.nSize!=0 && pCur->info.nPayload==pX->nData+pX->nZero ){ + assert( pX->nData>=0 && pX->nZero>=0 ); + if( pCur->info.nSize!=0 + && pCur->info.nPayload==(u32)pX->nData+pX->nZero + ){ return btreeOverwriteCell(pCur, pX); } loc = 0; From e2188f0b0f16292391b72e081a71b29263c8f15b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 7 May 2018 11:37:34 +0000 Subject: [PATCH 40/60] Fix harmless compiler warnings associated with the new EXPLAIN QUERY PLAN logic. FossilOrigin-Name: 374d8e264487b0437a8d995ced1bc026a92d495a2d0568f65f033e9ebe11d0e2 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/shell.c.in | 2 +- src/where.c | 2 +- src/whereInt.h | 4 +--- src/wherecode.c | 4 +--- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index 75de358840..5ce3d3060f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Backout\schange\s[05fee1a21ea398f1e4d6f1cf3]\sbecause\sit\sdoes\snot\stake\sinto\naccount\sthe\sLD_LIBRARY_PATH\senvironment\svariable\sused\sby\sdl_open(). -D 2018-05-07T02:50:38.426 +C Fix\sharmless\scompiler\swarnings\sassociated\swith\sthe\snew\sEXPLAIN\sQUERY\sPLAN\slogic. +D 2018-05-07T11:37:34.277 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -494,7 +494,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 -F src/shell.c.in 29309f2ab656c8817fbc3b7910b9af8464557b91cba75277a03669399c8e2730 +F src/shell.c.in e41979d8bf60d3e27220bf4b4adc819254e1d24ce176089a8d14c96228efd961 F src/sqlite.h.in 469aed42e75193b7f5d88d812befa961c04746869475f96fcf434c9f67079f66 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d @@ -577,9 +577,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0 F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f -F src/where.c aa94ef44ef36763817ca952e68c03db7eee5e2d4f1f0c3a98823a58c074157bd -F src/whereInt.h 2610cb87dd95509995b63decc674c60f2757697a206cfe0c085ee53d9c43cfff -F src/wherecode.c 300f945eb4552fb82ccf237b34dccb22f47522882faa9adcc04388e6e3f1d4b0 +F src/where.c d89b1aa56a75a572cd60ad27ec0fe5958d5f98b0f4391a89c72811287be7c439 +F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53 +F src/wherecode.c 414ec42097b295febcae9c8803cf627580ad9005de1d8bc3afad3d3127f0eb86 F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5d61e75f32de09c81dbe844443209f063cccb005d60b846900de5b023643fc3b -R b7e54ff139c007de5ac3db8f0e73a2f9 +P b348d1193a7a3ed4d3e656b6cc95a41f87eae29222e0723850a5eb5ffabffd00 +R d09bdc73f56d4d80e2806c4c66a4e25a U drh -Z 77e1a082dc787694600210821f90bcd3 +Z 7e3b1491b97d0e22d20f39d7466da090 diff --git a/manifest.uuid b/manifest.uuid index a119648e0b..a55df92ede 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b348d1193a7a3ed4d3e656b6cc95a41f87eae29222e0723850a5eb5ffabffd00 \ No newline at end of file +374d8e264487b0437a8d995ced1bc026a92d495a2d0568f65f033e9ebe11d0e2 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 7675b3832d..73db9f8e93 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1722,7 +1722,7 @@ static void eqp_render_level(ShellState *p, int iEqpId){ pNext = eqp_next_row(p, iEqpId, pRow); z = pRow->zText; utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z); - if( nsGraph.zPrefix)-7 ){ + if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){ memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); eqp_render_level(p, pRow->iEqpId); p->sGraph.zPrefix[n] = 0; diff --git a/src/where.c b/src/where.c index d76d9f81e2..0965f4170f 100644 --- a/src/where.c +++ b/src/where.c @@ -4988,7 +4988,7 @@ WhereInfo *sqlite3WhereBegin( } #endif addrExplain = sqlite3WhereExplainOneScan( - pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags + pParse, pTabList, pLevel, wctrlFlags ); pLevel->addrBody = sqlite3VdbeCurrentAddr(v); notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady); diff --git a/src/whereInt.h b/src/whereInt.h index 90929576e0..4b6213af31 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -467,12 +467,10 @@ int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - int iLevel, /* Value for "level" column of output */ - int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ); #else -# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0 +# define sqlite3WhereExplainOneScan(u,v,w,x) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS void sqlite3WhereAddScanStatus( diff --git a/src/wherecode.c b/src/wherecode.c index df45bd73e5..9a0227a871 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -122,8 +122,6 @@ int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - int iLevel, /* Value for "level" column of output */ - int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ){ int ret = 0; @@ -1956,7 +1954,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( pSubWInfo ){ WhereLoop *pSubLoop; int addrExplain = sqlite3WhereExplainOneScan( - pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 + pParse, pOrTab, &pSubWInfo->a[0], 0 ); sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); From d720d394d0b85ebd26f316ea1e34477db2574405 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 7 May 2018 17:27:04 +0000 Subject: [PATCH 41/60] Improved comments on the cell-overwrite optimization code. FossilOrigin-Name: a4fe966da2fc479b18bf521ff596000410af3a611f7d8723d126795e595ccf22 --- manifest | 13 +++++---- manifest.uuid | 2 +- src/btree.c | 73 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index 6862957f3f..8b8e5d6d37 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C On\san\sUPDATE,\stry\sto\soverwrite\san\sexisting\sbtree\scell\swith\sthe\smodified\ncontent,\sif\sthe\sold\sand\snew\scell\sare\sthe\ssame\ssize.\s\sUse\smemcmp()\sfirst\nto\savoid\sdirtying\spages\sthat\sare\sunchanged. -D 2018-05-07T11:48:22.641 +C Improved\scomments\son\sthe\scell-overwrite\soptimization\scode. +D 2018-05-07T17:27:04.995 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,7 +434,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 6be0267a7da8ca04c466094ca9d9a8a26333e175cff794afe5138aeec0cdb7c2 +F src/btree.c 7b21976dc09778f05af0e085c40b735467ffdcea64bd07dace3f12ca0a2defce F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e @@ -1727,8 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 374d8e264487b0437a8d995ced1bc026a92d495a2d0568f65f033e9ebe11d0e2 3e11dc3183bc3e8ec49af244a8e8b3e07d12f7a2e59028b2bf64ce0ab589a91f -R 891ce8c2c78f1f487f80460b8c248fd0 -T +closed 3e11dc3183bc3e8ec49af244a8e8b3e07d12f7a2e59028b2bf64ce0ab589a91f +P 5887d8beb502ad62689d31b850f46ab50831a1e9db36adf20d55ad45619d207e +R e6599f47435d4296a22afaa3f1649f4a U drh -Z 7955ef5d032aea210d99e8bc24e906bc +Z 8048adc03c51022109ca997ec38e8ad8 diff --git a/manifest.uuid b/manifest.uuid index 3fa7a09c8a..91ceb15d7a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5887d8beb502ad62689d31b850f46ab50831a1e9db36adf20d55ad45619d207e \ No newline at end of file +a4fe966da2fc479b18bf521ff596000410af3a611f7d8723d126795e595ccf22 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4d83d2e4de..60635172c4 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8332,43 +8332,70 @@ int sqlite3BtreeInsert( invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0); /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing - ** to a row with the same key as the new entry being inserted. */ - assert( (flags & BTREE_SAVEPOSITION)==0 || - ((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) ); + ** to a row with the same key as the new entry being inserted. + */ +#ifdef SQLITE_DEBUG + if( flags & BTREE_SAVEPOSITION ){ + assert( pCur->curFlags & BTCF_ValidNKey ); + assert( pX->nKey==pCur->info.nKey ); + assert( pCur->info.nSize!=0 ); + assert( loc==0 ); + } +#endif - /* If the cursor is currently on the last row and we are appending a - ** new row onto the end, set the "loc" to avoid an unnecessary - ** btreeMoveto() call */ + /* On the other hand, BTREE_SAVEPOSITION==0 does not imply + ** that the cursor is not pointing to a row to be overwritten. + ** So do a complete check. + */ if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ - /* The current is currently pointing to the entry that is to be + /* The cursor is pointing to the entry that is to be ** overwritten */ assert( pX->nData>=0 && pX->nZero>=0 ); if( pCur->info.nSize!=0 && pCur->info.nPayload==(u32)pX->nData+pX->nZero ){ + /* New entry is the same size as the old. Do an overwrite */ return btreeOverwriteCell(pCur, pX); } - loc = 0; + assert( loc==0 ); }else if( loc==0 ){ + /* The cursor is *not* pointing to the cell to be overwritten, nor + ** to an adjacent cell. Move the cursor so that it is pointing either + ** to the cell to be overwritten or an adjacent cell. + */ rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc); if( rc ) return rc; } - }else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ - if( pX->nMem ){ - UnpackedRecord r; - r.pKeyInfo = pCur->pKeyInfo; - r.aMem = pX->aMem; - r.nField = pX->nMem; - r.default_rc = 0; - r.errCode = 0; - r.r1 = 0; - r.r2 = 0; - r.eqSeen = 0; - rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); - }else{ - rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); + }else{ + /* This is an index or a WITHOUT ROWID table */ + + /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing + ** to a row with the same key as the new entry being inserted. + */ + assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 ); + + /* If the cursor is not already pointing either to the cell to be + ** overwritten, or if a new cell is being inserted, if the cursor is + ** not pointing to an immediately adjacent cell, then move the cursor + ** so that it does. + */ + if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ + if( pX->nMem ){ + UnpackedRecord r; + r.pKeyInfo = pCur->pKeyInfo; + r.aMem = pX->aMem; + r.nField = pX->nMem; + r.default_rc = 0; + r.errCode = 0; + r.r1 = 0; + r.r2 = 0; + r.eqSeen = 0; + rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); + }else{ + rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); + } + if( rc ) return rc; } - if( rc ) return rc; } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); From 89ee229810878e22d13e49c383e65038c054f5c6 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 7 May 2018 18:41:19 +0000 Subject: [PATCH 42/60] Activate the cell-overwrite optimization for index b-trees. FossilOrigin-Name: a68697d10ef17d452c8279181186faad7bc54e3a35858a336552f717449065ea --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 16 ++++++++++++++++ src/btree.h | 21 ++++++++++++++++++--- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 8b8e5d6d37..1db4fc0b69 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\scomments\son\sthe\scell-overwrite\soptimization\scode. -D 2018-05-07T17:27:04.995 +C Activate\sthe\scell-overwrite\soptimization\sfor\sindex\sb-trees. +D 2018-05-07T18:41:19.103 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -434,8 +434,8 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 7b21976dc09778f05af0e085c40b735467ffdcea64bd07dace3f12ca0a2defce -F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 +F src/btree.c abedb349c6624d3efa699b4431d5ef679838236527c694444b38ed48c494b39b +F src/btree.h 448f15b98ea85dcf7e4eb76f731cadb89636c676ad25dfaac6de77cd66556598 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/build.c 0c2be5839f22aa2938f217c6c6c2120d9fc96872a546a37541a8271541cb355e F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a @@ -1727,7 +1727,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5887d8beb502ad62689d31b850f46ab50831a1e9db36adf20d55ad45619d207e -R e6599f47435d4296a22afaa3f1649f4a +P a4fe966da2fc479b18bf521ff596000410af3a611f7d8723d126795e595ccf22 +R 69af7d477dcc78b7b8e926f0c6facd33 U drh -Z 8048adc03c51022109ca997ec38e8ad8 +Z 8d5036c02e569f6033a8ae94d4ec5845 diff --git a/manifest.uuid b/manifest.uuid index 91ceb15d7a..3d79611a88 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a4fe966da2fc479b18bf521ff596000410af3a611f7d8723d126795e595ccf22 \ No newline at end of file +a68697d10ef17d452c8279181186faad7bc54e3a35858a336552f717449065ea \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 60635172c4..2faa40820e 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8396,6 +8396,22 @@ int sqlite3BtreeInsert( } if( rc ) return rc; } + + /* If the cursor is currently pointing to an entry to be overwritten + ** and the new content is the same as as the old, then use the + ** overwrite optimization. + */ + if( loc==0 ){ + getCellInfo(pCur); + if( pCur->info.nKey==pX->nKey ){ + BtreePayload x2; + x2.pData = pX->pKey; + x2.nData = pX->nKey; + x2.nZero = 0; + return btreeOverwriteCell(pCur, &x2); + } + } + } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); diff --git a/src/btree.h b/src/btree.h index e8e114bd2a..b5bf9f7564 100644 --- a/src/btree.h +++ b/src/btree.h @@ -259,13 +259,28 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags); ** entry in either an index or table btree. ** ** Index btrees (used for indexes and also WITHOUT ROWID tables) contain -** an arbitrary key and no data. These btrees have pKey,nKey set to their -** key and pData,nData,nZero set to zero. +** an arbitrary key and no data. These btrees have pKey,nKey set to the +** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem +** fields give an array of Mem objects that are a decomposition of the key. +** The nMem field might be zero, indicating that no decomposition is available. ** ** Table btrees (used for rowid tables) contain an integer rowid used as ** the key and passed in the nKey field. The pKey field is zero. ** pData,nData hold the content of the new entry. nZero extra zero bytes ** are appended to the end of the content when constructing the entry. +** The aMem,nMem fields are uninitialized for table btrees. +** +** Field usage summary: +** +** Table BTrees Index Btrees +** +** pKey always NULL encoded key +** nKey the ROWID length of pKey +** pData data not used +** aMem not used decomposed key value +** nMem not used entries in aMem +** nData length of pData not used +** nZero extra zeros after pData not used ** ** This object is used to pass information into sqlite3BtreeInsert(). The ** same information used to be passed as five separate parameters. But placing @@ -276,7 +291,7 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags); struct BtreePayload { const void *pKey; /* Key content for indexes. NULL for tables */ sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ - const void *pData; /* Data for tables. NULL for indexes */ + const void *pData; /* Data for tables. */ sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */ u16 nMem; /* Number of aMem[] value. Might be zero */ int nData; /* Size of pData. 0 if none. */ From 5ecf9039b0b0680c163e36c80ad3a92eaf2a8326 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 May 2018 12:49:53 +0000 Subject: [PATCH 43/60] Fuzz test cases for UPSERT. FossilOrigin-Name: fd11fbd21893d520de5a2249f825ecb5839fa4943f5c207e9e9bf8b52f4e2695 --- Makefile.in | 3 ++- Makefile.msc | 3 ++- main.mk | 3 ++- manifest | 19 ++++++++++--------- manifest.uuid | 2 +- test/fuzzcheck.c | 36 ++++++++++++++++++++++++------------ test/fuzzdata6.db | Bin 0 -> 1785856 bytes 7 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 test/fuzzdata6.db diff --git a/Makefile.in b/Makefile.in index a3ec869643..ac84fe832c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -572,7 +572,8 @@ FUZZDATA = \ $(TOP)/test/fuzzdata2.db \ $(TOP)/test/fuzzdata3.db \ $(TOP)/test/fuzzdata4.db \ - $(TOP)/test/fuzzdata5.db + $(TOP)/test/fuzzdata5.db \ + $(TOP)/test/fuzzdata6.db # Standard options to testfixture # diff --git a/Makefile.msc b/Makefile.msc index 50119d8361..8513996b6a 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1599,7 +1599,8 @@ FUZZDATA = \ $(TOP)\test\fuzzdata2.db \ $(TOP)\test\fuzzdata3.db \ $(TOP)\test\fuzzdata4.db \ - $(TOP)\test\fuzzdata5.db + $(TOP)\test\fuzzdata5.db \ + $(TOP)\test\fuzzdata6.db # <> # Additional compiler options for the shell. These are only effective diff --git a/main.mk b/main.mk index b590b79cb1..8dc423c5b5 100644 --- a/main.mk +++ b/main.mk @@ -501,7 +501,8 @@ FUZZDATA = \ $(TOP)/test/fuzzdata2.db \ $(TOP)/test/fuzzdata3.db \ $(TOP)/test/fuzzdata4.db \ - $(TOP)/test/fuzzdata5.db + $(TOP)/test/fuzzdata5.db \ + $(TOP)/test/fuzzdata6.db # Standard options to testfixture # diff --git a/manifest b/manifest index 1db4fc0b69..eb997c914d 100644 --- a/manifest +++ b/manifest @@ -1,10 +1,10 @@ -C Activate\sthe\scell-overwrite\soptimization\sfor\sindex\sb-trees. -D 2018-05-07T18:41:19.103 +C Fuzz\stest\scases\sfor\sUPSERT. +D 2018-05-08T12:49:53.757 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea -F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 +F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 59179295f6a9b433e3f59a6dc2fcf6db6fcac35d92015294beb5d27f2924ebb9 +F Makefile.msc 681fb88cccf1fd58c0b9648f6a09b75332206ef72ca76012ad11699c320cec5f F README.md 7764d56778d567913ef11c82da9ab94aefa0826f7c243351e4e2d7adaef6f373 F VERSION b7c9d1d11cb70ef8e90cfcf3c944aa58a9f801cc2ad487eebb0a110c16dfc2df F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -415,7 +415,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 068618fe288bf9d93091b808be73e26a93fb2db8435328cc5760f9dd35ba168b +F main.mk 3f50dfe5cb4257c1aca96e417636ed51bc2561e71d31a21e9ccdf66feb912f43 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -940,12 +940,13 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79 -F test/fuzzcheck.c 5eb86c6ac96833ee622f45bf47e8045999c1b4b10d05e4eb809894a4b39f2f84 +F test/fuzzcheck.c ee575af6aaf2895a747592377719fb41f372407ef2026724f2bd16ff2985bbda F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21 F test/fuzzdata5.db 9f0cdcc5c6e83b90cf9ae343bd07f684d2da2de7 +F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 @@ -1727,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a4fe966da2fc479b18bf521ff596000410af3a611f7d8723d126795e595ccf22 -R 69af7d477dcc78b7b8e926f0c6facd33 +P a68697d10ef17d452c8279181186faad7bc54e3a35858a336552f717449065ea +R 1614ac69cf68c4d847f0ba99f9a25462 U drh -Z 8d5036c02e569f6033a8ae94d4ec5845 +Z 407f037ea974d860203a22f1c66f9cc1 diff --git a/manifest.uuid b/manifest.uuid index 3d79611a88..9a55fdbd56 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a68697d10ef17d452c8279181186faad7bc54e3a35858a336552f717449065ea \ No newline at end of file +fd11fbd21893d520de5a2249f825ecb5839fa4943f5c207e9e9bf8b52f4e2695 \ No newline at end of file diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index 01efc82ee5..2ad382859b 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -720,11 +720,13 @@ static void rebuild_database(sqlite3 *db){ "BEGIN;\n" "CREATE TEMP TABLE dbx AS SELECT DISTINCT dbcontent FROM db;\n" "DELETE FROM db;\n" - "INSERT INTO db(dbid, dbcontent) SELECT NULL, dbcontent FROM dbx ORDER BY 2;\n" + "INSERT INTO db(dbid, dbcontent) " + " SELECT NULL, dbcontent FROM dbx ORDER BY 2;\n" "DROP TABLE dbx;\n" "CREATE TEMP TABLE sx AS SELECT DISTINCT sqltext FROM xsql;\n" "DELETE FROM xsql;\n" - "INSERT INTO xsql(sqlid,sqltext) SELECT NULL, sqltext FROM sx ORDER BY 2;\n" + "INSERT INTO xsql(sqlid,sqltext) " + " SELECT NULL, sqltext FROM sx ORDER BY 2;\n" "DROP TABLE sx;\n" "COMMIT;\n" "PRAGMA page_size=1024;\n" @@ -807,7 +809,7 @@ static void showHelp(void){ " -q|--quiet Reduced output\n" " --limit-mem N Limit memory used by test SQLite instance to N bytes\n" " --limit-vdbe Panic if any test runs for more than 100,000 cycles\n" -" --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n" +" --load-sql ARGS... Load SQL scripts fron files into SOURCE-DB\n" " --load-db ARGS... Load template databases from files into SOURCE_DB\n" " -m TEXT Add a description to the database\n" " --native-vfs Use the native VFS for initially empty database files\n" @@ -827,7 +829,7 @@ int main(int argc, char **argv){ int quietFlag = 0; /* True if --quiet or -q */ int verboseFlag = 0; /* True if --verbose or -v */ char *zInsSql = 0; /* SQL statement for --load-db or --load-sql */ - int iFirstInsArg = 0; /* First argv[] to use for --load-db or --load-sql */ + int iFirstInsArg = 0; /* First argv[] for --load-db or --load-sql */ sqlite3 *db = 0; /* The open database connection */ sqlite3_stmt *pStmt; /* A prepared statement */ int rc; /* Result code from SQLite interface calls */ @@ -847,9 +849,9 @@ int main(int argc, char **argv){ int iSrcDb; /* Loop over all source databases */ int nTest = 0; /* Total number of tests performed */ char *zDbName = ""; /* Appreviated name of a source database */ - const char *zFailCode = 0; /* Value of the TEST_FAILURE environment variable */ + const char *zFailCode = 0; /* Value of the TEST_FAILURE env variable */ int cellSzCkFlag = 0; /* --cell-size-check */ - int sqlFuzz = 0; /* True for SQL fuzz testing. False for DB fuzz */ + int sqlFuzz = 0; /* True for SQL fuzz. False for DB fuzz */ int iTimeout = 120; /* Default 120-second timeout */ int nMem = 0; /* Memory limit */ int nMemThisDb = 0; /* Memory limit set by the CONFIG table */ @@ -860,12 +862,14 @@ int main(int argc, char **argv){ int ossFuzzThisDb = 0; /* ossFuzz value for this particular database */ int nativeMalloc = 0; /* Turn off MEMSYS3/5 and lookaside if true */ sqlite3_vfs *pDfltVfs; /* The default VFS */ + int openFlags; /* Flags for sqlite3_open_v2() */ iBegin = timeOfDay(); #ifdef __unix__ signal(SIGALRM, timeoutHandler); #endif g.zArgv0 = argv[0]; + openFlags = SQLITE_OPEN_READONLY; zFailCode = getenv("TEST_FAILURE"); pDfltVfs = sqlite3_vfs_find(0); inmemVfsRegister(1); @@ -906,18 +910,21 @@ int main(int argc, char **argv){ vdbeLimitFlag = 1; }else if( strcmp(z,"load-sql")==0 ){ - zInsSql = "INSERT INTO xsql(sqltext) VALUES(CAST(readfile(?1) AS text))"; + zInsSql = "INSERT INTO xsql(sqltext)VALUES(CAST(readfile(?1) AS text))"; iFirstInsArg = i+1; + openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; break; }else if( strcmp(z,"load-db")==0 ){ zInsSql = "INSERT INTO db(dbcontent) VALUES(readfile(?1))"; iFirstInsArg = i+1; + openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; break; }else if( strcmp(z,"m")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); zMsg = argv[++i]; + openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; }else if( strcmp(z,"native-malloc")==0 ){ nativeMalloc = 1; @@ -938,6 +945,7 @@ int main(int argc, char **argv){ }else if( strcmp(z,"rebuild")==0 ){ rebuildFlag = 1; + openFlags = SQLITE_OPEN_READWRITE; }else if( strcmp(z,"result-trace")==0 ){ runFlags |= SQL_OUTPUT; @@ -983,7 +991,7 @@ int main(int argc, char **argv){ /* Process each source database separately */ for(iSrcDb=0; iSrcDbzName); + openFlags, pDfltVfs->zName); if( rc ){ fatalError("cannot open source database %s - %s", azSrcDb[iSrcDb], sqlite3_errmsg(db)); @@ -1014,7 +1022,8 @@ int main(int argc, char **argv){ /* If the CONFIG(name,value) table exists, read db-specific settings ** from that table */ if( sqlite3_table_column_metadata(db,0,"config",0,0,0,0,0,0)==SQLITE_OK ){ - rc = sqlite3_prepare_v2(db, "SELECT name, value FROM config", -1, &pStmt, 0); + rc = sqlite3_prepare_v2(db, "SELECT name, value FROM config", + -1, &pStmt, 0); if( rc ) fatalError("cannot prepare query of CONFIG table: %s", sqlite3_errmsg(db)); while( SQLITE_ROW==sqlite3_step(pStmt) ){ @@ -1053,7 +1062,8 @@ int main(int argc, char **argv){ } sqlite3_finalize(pStmt); rc = sqlite3_exec(db, "COMMIT", 0, 0, 0); - if( rc ) fatalError("cannot commit the transaction: %s", sqlite3_errmsg(db)); + if( rc ) fatalError("cannot commit the transaction: %s", + sqlite3_errmsg(db)); rebuild_database(db); sqlite3_close(db); return 0; @@ -1197,7 +1207,8 @@ int main(int argc, char **argv){ sqlite3_randomness(0,0); if( ossFuzzThisDb ){ #ifndef SQLITE_OSS_FUZZ - fatalError("--oss-fuzz not supported: recompile with -DSQLITE_OSS_FUZZ"); + fatalError("--oss-fuzz not supported: recompile" + " with -DSQLITE_OSS_FUZZ"); #else extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t); LLVMFuzzerTestOneInput((const uint8_t*)pSql->a, (size_t)pSql->sz); @@ -1216,7 +1227,8 @@ int main(int argc, char **argv){ setAlarm(iTimeout); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( sqlFuzz || vdbeLimitFlag ){ - sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag); + sqlite3_progress_handler(db, 100000, progressHandler, + &vdbeLimitFlag); } #endif do{ diff --git a/test/fuzzdata6.db b/test/fuzzdata6.db new file mode 100644 index 0000000000000000000000000000000000000000..b1424c21e4194f352629d4d08b7b88d16ea0d1ee GIT binary patch literal 1785856 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 literal 0 HcmV?d00001 From f2cf412a0a17bb20869bb29f82b7f763c17a4730 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 May 2018 13:03:31 +0000 Subject: [PATCH 44/60] Fix a harmless compiler warning in fuzzcheck. Add new OSSFuzz test cases to the test case library. FossilOrigin-Name: d2619746cb233f4be127a77988548dd1d90eebddf0d0ac9107913b240553e5d0 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/fuzzcheck.c | 14 +++++++------- test/fuzzdata5.db | Bin 6964224 -> 7195648 bytes 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index eb997c914d..a782d84718 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fuzz\stest\scases\sfor\sUPSERT. -D 2018-05-08T12:49:53.757 +C Fix\sa\sharmless\scompiler\swarning\sin\sfuzzcheck.\s\sAdd\snew\sOSSFuzz\stest\scases\nto\sthe\stest\scase\slibrary. +D 2018-05-08T13:03:31.809 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -940,12 +940,12 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79 -F test/fuzzcheck.c ee575af6aaf2895a747592377719fb41f372407ef2026724f2bd16ff2985bbda +F test/fuzzcheck.c 3885207dc217c4dcdb2de4a3cb169a263afeef51ab9bd0ba8567289f0a19a470 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21 -F test/fuzzdata5.db 9f0cdcc5c6e83b90cf9ae343bd07f684d2da2de7 +F test/fuzzdata5.db 117d821cde02e30a687f6361a34b98e6e0b05062df523cfee163c58564403b68 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 @@ -1728,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a68697d10ef17d452c8279181186faad7bc54e3a35858a336552f717449065ea -R 1614ac69cf68c4d847f0ba99f9a25462 +P fd11fbd21893d520de5a2249f825ecb5839fa4943f5c207e9e9bf8b52f4e2695 +R 341265b3833d05f56ac0f5a3c8e3d52d U drh -Z 407f037ea974d860203a22f1c66f9cc1 +Z a9f407a471f5847cacaf3cf8ae748002 diff --git a/manifest.uuid b/manifest.uuid index 9a55fdbd56..30835e6856 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fd11fbd21893d520de5a2249f825ecb5839fa4943f5c207e9e9bf8b52f4e2695 \ No newline at end of file +d2619746cb233f4be127a77988548dd1d90eebddf0d0ac9107913b240553e5d0 \ No newline at end of file diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index 2ad382859b..05d944758e 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -862,14 +862,14 @@ int main(int argc, char **argv){ int ossFuzzThisDb = 0; /* ossFuzz value for this particular database */ int nativeMalloc = 0; /* Turn off MEMSYS3/5 and lookaside if true */ sqlite3_vfs *pDfltVfs; /* The default VFS */ - int openFlags; /* Flags for sqlite3_open_v2() */ + int openFlags4Data; /* Flags for sqlite3_open_v2() */ iBegin = timeOfDay(); #ifdef __unix__ signal(SIGALRM, timeoutHandler); #endif g.zArgv0 = argv[0]; - openFlags = SQLITE_OPEN_READONLY; + openFlags4Data = SQLITE_OPEN_READONLY; zFailCode = getenv("TEST_FAILURE"); pDfltVfs = sqlite3_vfs_find(0); inmemVfsRegister(1); @@ -912,19 +912,19 @@ int main(int argc, char **argv){ if( strcmp(z,"load-sql")==0 ){ zInsSql = "INSERT INTO xsql(sqltext)VALUES(CAST(readfile(?1) AS text))"; iFirstInsArg = i+1; - openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; + openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; break; }else if( strcmp(z,"load-db")==0 ){ zInsSql = "INSERT INTO db(dbcontent) VALUES(readfile(?1))"; iFirstInsArg = i+1; - openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; + openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; break; }else if( strcmp(z,"m")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); zMsg = argv[++i]; - openFlags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; + openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; }else if( strcmp(z,"native-malloc")==0 ){ nativeMalloc = 1; @@ -945,7 +945,7 @@ int main(int argc, char **argv){ }else if( strcmp(z,"rebuild")==0 ){ rebuildFlag = 1; - openFlags = SQLITE_OPEN_READWRITE; + openFlags4Data = SQLITE_OPEN_READWRITE; }else if( strcmp(z,"result-trace")==0 ){ runFlags |= SQL_OUTPUT; @@ -991,7 +991,7 @@ int main(int argc, char **argv){ /* Process each source database separately */ for(iSrcDb=0; iSrcDbzName); + openFlags4Data, pDfltVfs->zName); if( rc ){ fatalError("cannot open source database %s - %s", azSrcDb[iSrcDb], sqlite3_errmsg(db)); diff --git a/test/fuzzdata5.db b/test/fuzzdata5.db index 4645b1921b32d1b4a8255c69904eb968a023ca77..55089e1f566ec467506221de1dc2fd1aa6c508a7 100644 GIT binary patch delta 357096 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 delta 125181 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 B`hfrd From 4c54045372857367140cf07262185a2ccfac36fb Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 May 2018 23:17:36 +0000 Subject: [PATCH 45/60] Correctly format the STAT1 and STAT4 content in the output from the ".fullschema" command in the CLI. Fix for ticket [e63a34a0045832dc850367552]. FossilOrigin-Name: 0c3f128fd7d5738a8e9da706f5f30aa1985ef5efab70ddaad28ef6b641b04f4a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index a782d84718..509c95fbc1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sharmless\scompiler\swarning\sin\sfuzzcheck.\s\sAdd\snew\sOSSFuzz\stest\scases\nto\sthe\stest\scase\slibrary. -D 2018-05-08T13:03:31.809 +C Correctly\sformat\sthe\sSTAT1\sand\sSTAT4\scontent\sin\sthe\soutput\sfrom\sthe\n".fullschema"\scommand\sin\sthe\sCLI.\s\sFix\sfor\sticket\n[e63a34a0045832dc850367552]. +D 2018-05-08T23:17:36.373 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -494,7 +494,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 -F src/shell.c.in e41979d8bf60d3e27220bf4b4adc819254e1d24ce176089a8d14c96228efd961 +F src/shell.c.in df233d5556008e330570da3dc4aa837af1df01d95ca5a15beb67b8515302c36a F src/sqlite.h.in 469aed42e75193b7f5d88d812befa961c04746869475f96fcf434c9f67079f66 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d @@ -1728,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fd11fbd21893d520de5a2249f825ecb5839fa4943f5c207e9e9bf8b52f4e2695 -R 341265b3833d05f56ac0f5a3c8e3d52d +P d2619746cb233f4be127a77988548dd1d90eebddf0d0ac9107913b240553e5d0 +R 2f0b370ed5b99064180863fcf7e84b82 U drh -Z a9f407a471f5847cacaf3cf8ae748002 +Z a0a528b6dadf41d36c530fbf78ec0f01 diff --git a/manifest.uuid b/manifest.uuid index 30835e6856..8389cbd1d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d2619746cb233f4be127a77988548dd1d90eebddf0d0ac9107913b240553e5d0 \ No newline at end of file +0c3f128fd7d5738a8e9da706f5f30aa1985ef5efab70ddaad28ef6b641b04f4a \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 73db9f8e93..1ea24fe592 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -6000,11 +6000,11 @@ static int do_meta_command(char *zLine, ShellState *p){ callback, &data, &zErrMsg); data.cMode = data.mode = MODE_Insert; data.zDestTable = "sqlite_stat1"; - shell_exec(p, "SELECT * FROM sqlite_stat1", &zErrMsg); + shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg); data.zDestTable = "sqlite_stat3"; - shell_exec(p, "SELECT * FROM sqlite_stat3", &zErrMsg); + shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg); data.zDestTable = "sqlite_stat4"; - shell_exec(p, "SELECT * FROM sqlite_stat4", &zErrMsg); + shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg); raw_printf(p->out, "ANALYZE sqlite_master;\n"); } }else From 721e8539c38b9221543183305c6e7f2bb2b76833 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 9 May 2018 10:11:44 +0000 Subject: [PATCH 46/60] Fix a typo in a comment used for documentation. No code changes. FossilOrigin-Name: b866693e6a50b5c41ca54b56bb20753efb94980ad3365c511cccf23ac43a1c23 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 509c95fbc1..bd55b8eb82 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Correctly\sformat\sthe\sSTAT1\sand\sSTAT4\scontent\sin\sthe\soutput\sfrom\sthe\n".fullschema"\scommand\sin\sthe\sCLI.\s\sFix\sfor\sticket\n[e63a34a0045832dc850367552]. -D 2018-05-08T23:17:36.373 +C Fix\sa\stypo\sin\sa\scomment\sused\sfor\sdocumentation.\s\sNo\scode\schanges. +D 2018-05-09T10:11:44.774 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -495,7 +495,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 F src/shell.c.in df233d5556008e330570da3dc4aa837af1df01d95ca5a15beb67b8515302c36a -F src/sqlite.h.in 469aed42e75193b7f5d88d812befa961c04746869475f96fcf434c9f67079f66 +F src/sqlite.h.in 90953956babca76c5462487d9f08df6f3d5cc61c12f5f21a668e4fcc069ac03c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d F src/sqliteInt.h 4b98a37f27033ca887f2027f9a60636625fb2a4a9ef1b96c17f0db8fd951891f @@ -1728,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d2619746cb233f4be127a77988548dd1d90eebddf0d0ac9107913b240553e5d0 -R 2f0b370ed5b99064180863fcf7e84b82 +P 0c3f128fd7d5738a8e9da706f5f30aa1985ef5efab70ddaad28ef6b641b04f4a +R 2c62d3beecc0dc62689392fea52a44aa U drh -Z a0a528b6dadf41d36c530fbf78ec0f01 +Z 9f515593856c1a56e94f7a12690a8e77 diff --git a/manifest.uuid b/manifest.uuid index 8389cbd1d6..34975b2b23 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c3f128fd7d5738a8e9da706f5f30aa1985ef5efab70ddaad28ef6b641b04f4a \ No newline at end of file +b866693e6a50b5c41ca54b56bb20753efb94980ad3365c511cccf23ac43a1c23 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index e7bc6191cc..1074342be6 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7113,7 +7113,7 @@ int sqlite3_test_control(int op, ...); ** using keywords as identifiers. Common techniques used to avoid keyword ** name collisions include: **