1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Further simplification and modularization of the EXPLAIN logic.

FossilOrigin-Name: aee1c12f4227cea9e8c6295cee3ec11797422c31b48c9468f176eb52f8261fe8
This commit is contained in:
drh
2020-03-23 19:14:11 +00:00
parent 356cd76aa8
commit cb49f5468e
4 changed files with 66 additions and 102 deletions

View File

@ -1,5 +1,5 @@
C Begin\sbreaking\sappear\sthe\ssqlite3VdbeList()\sroutine\sinto\ssubroutines\sthat\ncan\sbe\sreused\sby\sthe\sbytecode()\stable. C Further\ssimplification\sand\smodularization\sof\sthe\sEXPLAIN\slogic.
D 2020-03-23T17:24:46.014 D 2020-03-23T19:14:11.433
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -607,7 +607,7 @@ F src/vdbe.c c1c123c6248fa88940b932a00bcc75056921b6d046d45a82566cb97415d2299c
F src/vdbe.h 07b8c636a87df8b6e58f29d6badd7f10d5844353deff1d7c88ed1c2bfe3bbd35 F src/vdbe.h 07b8c636a87df8b6e58f29d6badd7f10d5844353deff1d7c88ed1c2bfe3bbd35
F src/vdbeInt.h 198e552a1a8945061c7576d3d7f8c8603300bbbb9ba0a337184bf13a7cdda65d F src/vdbeInt.h 198e552a1a8945061c7576d3d7f8c8603300bbbb9ba0a337184bf13a7cdda65d
F src/vdbeapi.c 1252d80c548711e47a6d84dae88ed4e95d3fbb4e7bd0eaa1347299af7efddf02 F src/vdbeapi.c 1252d80c548711e47a6d84dae88ed4e95d3fbb4e7bd0eaa1347299af7efddf02
F src/vdbeaux.c 46991da5699ff4986c15264c46d6300a56c008b758adade974dcebb5b9dba74e F src/vdbeaux.c a041e907fed078029e6d7608f62acf9d69ea262d515b00254f8736eff5f4d363
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1 F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
F src/vdbemem.c 39b942ecca179f4f30a32b54579a85d74ccaefa5af2a0ad2700abe5ef0768b22 F src/vdbemem.c 39b942ecca179f4f30a32b54579a85d74ccaefa5af2a0ad2700abe5ef0768b22
F src/vdbesort.c 2be76d26998ce2b3324cdcc9f6443728e54b6c7677c553ad909c7d7cfab587df F src/vdbesort.c 2be76d26998ce2b3324cdcc9f6443728e54b6c7677c553ad909c7d7cfab587df
@ -821,7 +821,7 @@ F test/descidx1.test edc8adee58d491b06c7157c50364eaf1c3605c9c19f8093cb1ea2b6184f
F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad78298 F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad78298
F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926 F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test 8b6c652f0b2d477f0830884736f2a1cd2e8f7fc10a04aa6d571a401fa13ed88b F test/distinct.test e7d0cf371944dd0cbedff86420744e2f1ea2b528156451c97eb6ff41a99b9236
F test/distinct2.test 11b0594c932098e969d084ba45ab81d5040f4d4e766db65d49146705a305ed98 F test/distinct2.test 11b0594c932098e969d084ba45ab81d5040f4d4e766db65d49146705a305ed98
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05 F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
@ -1861,7 +1861,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 2795f0d633577e0de66b389d9e8e44c55e85975bdc62f1a0b8f93959d19b22bf P 2c4dd79fbd4b9f72634a732abb9ed833cd8c9b05fe1e10af8f23e6d6ec023c7c
R d0c0c7fad919870cffac31ef6d1a6170 R 4748d2ea6081821a30c83e5089756745
U drh U drh
Z bedd18e23757a54ddb7ae33ec04cb1e6 Z 573498e339f1a839323caa9c87282f78

View File

@ -1 +1 @@
2c4dd79fbd4b9f72634a732abb9ed833cd8c9b05fe1e10af8f23e6d6ec023c7c aee1c12f4227cea9e8c6295cee3ec11797422c31b48c9468f176eb52f8261fe8

View File

@ -1464,11 +1464,10 @@ static int translateP(char c, const Op *pOp){
** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0 ** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x ** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
*/ */
static int displayComment( static char *displayComment(
sqlite3 *db, /* Optional - Oom error reporting only */
const Op *pOp, /* The opcode to be commented */ const Op *pOp, /* The opcode to be commented */
const char *zP4, /* Previously obtained value for P4 */ const char *zP4 /* Previously obtained value for P4 */
char *zTemp, /* Write result here */
int nTemp /* Space available in zTemp[] */
){ ){
const char *zOpName; const char *zOpName;
const char *zSynopsis; const char *zSynopsis;
@ -1476,8 +1475,8 @@ static int displayComment(
int ii; int ii;
char zAlt[50]; char zAlt[50];
StrAccum x; StrAccum x;
sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
zOpName = sqlite3OpcodeName(pOp->opcode); zOpName = sqlite3OpcodeName(pOp->opcode);
nOpName = sqlite3Strlen30(zOpName); nOpName = sqlite3Strlen30(zOpName);
if( zOpName[nOpName+1] ){ if( zOpName[nOpName+1] ){
@ -1544,8 +1543,10 @@ static int displayComment(
}else if( pOp->zComment ){ }else if( pOp->zComment ){
sqlite3_str_appendall(&x, pOp->zComment); sqlite3_str_appendall(&x, pOp->zComment);
} }
sqlite3StrAccumFinish(&x); if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){
return x.nChar; sqlite3OomFault(db);
}
return sqlite3StrAccumFinish(&x);
} }
#endif /* SQLITE_DEBUG */ #endif /* SQLITE_DEBUG */
@ -1628,11 +1629,11 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
** Compute a string that describes the P4 parameter for an opcode. ** Compute a string that describes the P4 parameter for an opcode.
** Use zTemp for any required temporary buffer space. ** Use zTemp for any required temporary buffer space.
*/ */
static char *displayP4(Op *pOp, char *zTemp, int nTemp){ static char *displayP4(sqlite3 *db, Op *pOp){
char *zP4 = zTemp; char *zP4 = 0;
StrAccum x; StrAccum x;
assert( nTemp>=20 );
sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0); sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
switch( pOp->p4type ){ switch( pOp->p4type ){
case P4_KEYINFO: { case P4_KEYINFO: {
int j; int j;
@ -1718,34 +1719,31 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
for(i=1; i<=n; i++){ for(i=1; i<=n; i++){
sqlite3_str_appendf(&x, ",%d", ai[i]); sqlite3_str_appendf(&x, ",%d", ai[i]);
} }
zTemp[0] = '['; if( !x.accError ) x.zText[0] = '[';
sqlite3_str_append(&x, "]", 1); sqlite3_str_append(&x, "]", 1);
break; break;
} }
case P4_SUBPROGRAM: { case P4_SUBPROGRAM: {
sqlite3_str_appendf(&x, "program"); zP4 = "program";
break; break;
} }
case P4_DYNBLOB: case P4_DYNBLOB:
case P4_ADVANCE: { case P4_ADVANCE: {
zTemp[0] = 0;
break; break;
} }
case P4_TABLE: { case P4_TABLE: {
sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName); zP4 = pOp->p4.pTab->zName;
break; break;
} }
default: { default: {
zP4 = pOp->p4.z; zP4 = pOp->p4.z;
if( zP4==0 ){
zP4 = zTemp;
zTemp[0] = 0;
}
} }
} }
sqlite3StrAccumFinish(&x); if( zP4 ) sqlite3_str_appendall(&x, zP4);
assert( zP4!=0 ); if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){
return zP4; sqlite3OomFault(db);
}
return sqlite3StrAccumFinish(&x);
} }
#endif /* VDBE_DISPLAY_P4 */ #endif /* VDBE_DISPLAY_P4 */
@ -1835,24 +1833,25 @@ void sqlite3VdbeLeave(Vdbe *p){
*/ */
void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){ void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
char *zP4; char *zP4;
char zPtr[50]; char *zCom;
char zCom[100];
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n"; static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
if( pOut==0 ) pOut = stdout; if( pOut==0 ) pOut = stdout;
zP4 = displayP4(pOp, zPtr, sizeof(zPtr)); zP4 = displayP4(0, pOp);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
displayComment(pOp, zP4, zCom, sizeof(zCom)); zCom = displayComment(0, pOp, zP4);
#else #else
zCom[0] = 0; zCom = 0;
#endif #endif
/* NB: The sqlite3OpcodeName() function is implemented by code created /* NB: The sqlite3OpcodeName() function is implemented by code created
** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
** information from the vdbe.c source text */ ** information from the vdbe.c source text */
fprintf(pOut, zFormat1, pc, fprintf(pOut, zFormat1, pc,
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5, sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
zCom zCom ? zCom : ""
); );
fflush(pOut); fflush(pOut);
sqlite3_free(zP4);
sqlite3_free(zCom);
} }
#endif #endif
@ -2133,76 +2132,41 @@ int sqlite3VdbeList(
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
}else{ }else{
char *zP4; char *zP4 = displayP4(db, pOp);
if( p->explain==1 ){ if( p->explain==2 ){
pMem->flags = MEM_Int; sqlite3VdbeMemSetInt64(pMem, pOp->p1);
pMem->u.i = i; /* Program counter */ sqlite3VdbeMemSetInt64(pMem+1, pOp->p2);
pMem++; sqlite3VdbeMemSetInt64(pMem+2, pOp->p3);
sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free);
pMem->flags = MEM_Static|MEM_Str|MEM_Term; p->nResColumn = 4;
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
pMem++;
}
pMem->flags = MEM_Int;
pMem->u.i = pOp->p1; /* P1 */
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p2; /* P2 */
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p3; /* P3 */
pMem++;
if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
pMem->flags = MEM_Str|MEM_Term;
zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
if( zP4!=pMem->z ){
pMem->n = 0;
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
}else{ }else{
assert( pMem->z!=0 ); sqlite3VdbeMemSetInt64(pMem+0, i);
pMem->n = sqlite3Strlen30(pMem->z); sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode),
pMem->enc = SQLITE_UTF8; -1, SQLITE_UTF8, SQLITE_STATIC);
} sqlite3VdbeMemSetInt64(pMem+2, pOp->p1);
pMem++; sqlite3VdbeMemSetInt64(pMem+3, pOp->p2);
sqlite3VdbeMemSetInt64(pMem+4, pOp->p3);
if( p->explain==1 ){ /* pMem+5 for p4 is done last */
if( sqlite3VdbeMemClearAndResize(pMem, 4) ){ sqlite3VdbeMemSetInt64(pMem+6, pOp->p5);
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
pMem->flags = MEM_Str|MEM_Term;
pMem->n = 2;
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
pMem->enc = SQLITE_UTF8;
pMem++;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
if( sqlite3VdbeMemClearAndResize(pMem, 500) ){ {
assert( p->db->mallocFailed ); char *zCom = displayComment(db, pOp, zP4);
return SQLITE_ERROR; sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free);
} }
pMem->flags = MEM_Str|MEM_Term;
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
pMem->enc = SQLITE_UTF8;
#else #else
pMem->flags = MEM_Null; /* Comment */ sqlite3VdbeMemSetNull(pMem+7);
#endif #endif
sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free);
p->nResColumn = 8;
}
p->pResultSet = pMem;
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM;
rc = SQLITE_ERROR;
}else{
p->rc = SQLITE_OK;
rc = SQLITE_ROW;
} }
p->nResColumn = 8 - 4*(p->explain-1);
p->pResultSet = &p->aMem[1];
p->rc = SQLITE_OK;
rc = SQLITE_ROW;
} }
} }
return rc; return rc;

View File

@ -51,8 +51,8 @@ proc do_temptables_test {tn sql temptables} {
set ret "" set ret ""
db eval "EXPLAIN [set sql]" { db eval "EXPLAIN [set sql]" {
if {$opcode == "OpenEphemeral" || $opcode == "SorterOpen"} { if {$opcode == "OpenEphemeral" || $opcode == "SorterOpen"} {
if {$p5 != "08" && $p5!="00"} { error "p5 = $p5" } if {$p5!=8 && $p5!=0} { error "p5 = $p5" }
if {$p5 == "08"} { if {$p5==8} {
lappend ret hash lappend ret hash
} else { } else {
lappend ret btree lappend ret btree