From e603ab00eee7002704ace0cafe072b91d909d37e Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 7 Apr 2022 19:06:31 +0000 Subject: [PATCH] Enhance the EXPLAIN output formatting in the CLI so that the subroutine that implements the loop body for the multi-index OR optimization is indented. FossilOrigin-Name: c2965fea9df7076b235d3eadaf84f0a36242476d0329030b0e57557b66e2540c --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/shell.c.in | 8 ++++++-- src/vdbe.c | 10 +++++++++- src/wherecode.c | 8 ++++++++ 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index d1b23d0aac..66ed4df0ca 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\s".testctrl\soptimizations\s0x400000"\scommand\sdisables\sthe\sgeneration\sof\nOP_ReleaseReg\sopcodes.\s\sOP_ReleaseReg\sopcodes\sare\susually\sonly\sgenerated\sfor\nSQLITE_DEBUG\sbuilds\sand\sare\sused\sto\sverify\sthat\sregisters\sare\sdescoped\npropertly.\s\sBut\sthey\scan\sget\sin\sthe\sway\sof\scode\sunderstanding\swhen\sstudying\nbytecode\sdumps.\s\sSo\sthis\snew\soptimization\ssetting\sis\sprovided\sto\ntemporarily\sturn\sOP_ReleaseReg\sopcodes\soff. -D 2022-04-07T18:17:56.434 +C Enhance\sthe\sEXPLAIN\soutput\sformatting\sin\sthe\sCLI\sso\sthat\sthe\ssubroutine\sthat\nimplements\sthe\sloop\sbody\sfor\sthe\smulti-index\sOR\soptimization\sis\sindented. +D 2022-04-07T19:06:31.719 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -553,7 +553,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 18d99e7146852d6064559561769fcca0743eb32b14a97da6dbed373a30ee0e76 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c d6c04eb93395024af80f61a8c278a33c2a0333aeb7d57bb6aa737a6f1c4af4b8 -F src/shell.c.in 18832612e74c92bbd25d88e1f92685f66589262f68cca1001d2a43bd6dd0ed60 +F src/shell.c.in 1a8fbf932ecd582b1a5f66c1e8294f92c30d954616f5c7cc54c9623fcdbb028d F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e @@ -624,7 +624,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 602fe229f32a96ceccae4f40824129669582096f7c355f53dbac156c9fecef23 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c 4d8f5b013e1ad47240e9822217a4ac76041afd2667dcbefd26f598fe45f729a5 +F src/vdbe.c eefc5a96938cc113a95e36a42b626bf594a7f0b8bb56ae299accbbf015b973cd F src/vdbe.h 89f5edb1422c8783a0b29db836e409876f2b3e847f78e2b21b1fbcc48a93f85f F src/vdbeInt.h 5f3d0abcf30c2b7a6672ad4386f18be0fca9c9b2cefe18f85a2e3df74f2613bf F src/vdbeapi.c 354c893f1500cf524cc45c32879b9c68893a28b77e3442c24668d6afe4236217 @@ -641,7 +641,7 @@ F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c a2483d4fe7cde88638cd3140dd5d6ee3dc0c80d3b3fe20322a8d08dc451f97ae F src/whereInt.h 15d2975c3b4c193c78c26674400a840da8647fe1777ae3b026e2d15937b38a03 -F src/wherecode.c 555f598a9ddad81761f084710fdb4f8733fe31bc14cd6b19f8ca4274a7eaa04c +F src/wherecode.c 6292d7bf2d751b1ce68139a70e5468dd6615a9a9dab5b5e61c0053836723bb7a F src/whereexpr.c 612f58f5f6e3e3bb94d10e2c56672ade8bbf94d4a928d3edb4e84e2ed3c00dca F src/window.c 42a71595263dbd8ef8248218e4fc7d4b5ddccece52146ad48e079342d93f6f8f F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1945,8 +1945,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 201569e09b000919ccb463bd581fb2ecd5320e7f584fdb1bc2aaba111061d5c3 -R 3b3b7a8904349e1fc968ddd3854c9c21 +P fa5276725f246cef9d58b27c1e617ee3f873f7a9b88284a4e8fc453ebda338bc +R 3f3f316e7621b39e6212d4a123c3e0e2 U drh -Z 053f375f9db373c4b27ef764e92f78d7 +Z 65aae2da34a10e9f483e6d1ce0511661 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 70d47c032f..a72d788b29 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fa5276725f246cef9d58b27c1e617ee3f873f7a9b88284a4e8fc453ebda338bc \ No newline at end of file +c2965fea9df7076b235d3eadaf84f0a36242476d0329030b0e57557b66e2540c \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 9e6198f517..452e8b9cb1 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -2944,6 +2944,9 @@ static int str_in_array(const char *zStr, const char **azArray){ ** all opcodes that occur between the p2 jump destination and the opcode ** itself by 2 spaces. ** +** * Do the previous for "Return" instructions for when P2 is positive. +** See tag-20220407a in wherecode.c and vdbe.c. +** ** * For each "Goto", if the jump destination is earlier in the program ** and ends on one of: ** Yield SeekGt SeekLt RowSetRead Rewind @@ -2958,7 +2961,8 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ int iOp; /* Index of operation in p->aiIndent[] */ - const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 }; + const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", + "Return", 0 }; const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", "Rewind", 0 }; const char *azGoto[] = { "Goto", 0 }; @@ -3016,7 +3020,7 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ p->aiIndent[iOp] = 0; p->nIndent = iOp+1; - if( str_in_array(zOp, azNext) ){ + if( str_in_array(zOp, azNext) && p2op>0 ){ for(i=p2op; iaiIndent[i] += 2; } if( str_in_array(zOp, azGoto) && p2opnIndent diff --git a/src/vdbe.c b/src/vdbe.c index 02d0988f10..18286c297b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -991,11 +991,19 @@ jump_to_p2: break; } -/* Opcode: Return P1 * P3 * * +/* Opcode: Return P1 P2 P3 * * ** ** Jump to the next instruction after the address in register P1. After ** the jump, register P1 becomes undefined. ** +** P2 is not used by the byte-code engine. However, if P2 is positive +** and also less than the current address, then the "EXPLAIN" output +** formatter in the CLI will indent all opcodes from the P2 opcode up +** to be not including the current Return. P2 should be the first opcode +** in the subroutine from which this opcode is returnning. Thus the P2 +** value is a byte-code indentation hint. See tag-20220407a in +** wherecode.c and shell.c. +** ** P3 is not used by the byte-code engine. However, the code generator ** sets P3 to address of the associated OP_BeginSubrtn opcode, if there is ** one. diff --git a/src/wherecode.c b/src/wherecode.c index ce0279a8f6..bab514a693 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -2534,6 +2534,14 @@ Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeGoto(v, pLevel->addrBrk); sqlite3VdbeResolveLabel(v, iLoopBody); + /* Set the P2 operand of the OP_Return opcode that will end the current + ** loop to point to this spot, which is the top of the next containing + ** loop. The byte-code formatter will use that P2 value as a hint to + ** indent everything in between the this point and the final OP_Return. + ** See tag-20220407a in vdbe.c and shell.c */ + assert( pLevel->op==OP_Return ); + pLevel->p2 = sqlite3VdbeCurrentAddr(v); + if( pWInfo->nLevel>1 ){ sqlite3StackFree(db, pOrTab); } if( !untestedTerms ) disableTerm(pLevel, pTerm); }else