From 099f7f052bae7215eb8566943f06a28ebad0ecb7 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 6 Nov 2025 19:22:34 +0000 Subject: [PATCH] Revamp so that Explain and Eqp styles force the statement into the the appropriate explain-mode for the rendering and restore it afterwards. Add the new scanstatus styles: Stats, StatsEst, and StatsVm. FossilOrigin-Name: 128f1149076ef00c567405ea2112be0ae665b12e81672ae5494d82af11633af5 --- ext/qrf/README.md | 20 ++--- ext/qrf/qrf.c | 190 +++++++++++++++++++++++++++++++++++++--------- ext/qrf/qrf.h | 18 +++-- manifest | 20 ++--- manifest.uuid | 2 +- src/tclsqlite.c | 10 +-- test/qrf01.test | 2 +- 7 files changed, 192 insertions(+), 70 deletions(-) diff --git a/ext/qrf/README.md b/ext/qrf/README.md index e725f75021..378feea190 100644 --- a/ext/qrf/README.md +++ b/ext/qrf/README.md @@ -374,14 +374,16 @@ The following output modes are currently defined: #define QRF_STYLE_Csv 6 /* Comma-separated-value */ #define QRF_STYLE_Quote 7 /* SQL-quoted, comma-separated */ #define QRF_STYLE_Explain 8 /* EXPLAIN output */ -#define QRF_STYLE_ScanExp 9 /* EXPLAIN output with vm stats */ -#define QRF_STYLE_EQP 10 /* Format EXPLAIN QUERY PLAN output */ -#define QRF_STYLE_Markdown 11 /* Markdown formatting */ -#define QRF_STYLE_Column 12 /* One record per line in neat columns */ -#define QRF_STYLE_Table 13 /* MySQL-style table formatting */ -#define QRF_STYLE_Box 14 /* Unicode box-drawing characters */ -#define QRF_STYLE_Count 15 /* Output only a count of the rows of output */ -#define QRF_STYLE_Off 16 /* No query output shown */ +#define QRF_STYLE_Eqp 10 /* Format EXPLAIN QUERY PLAN output */ +#define QRF_STYLE_Stats 11 /* EQP-like output but with performance stats */ +#define QRF_STYLE_StatsEst 12 /* EQP-like output with planner estimates */ +#define QRF_STYLE_StatsVm 13 /* EXPLAIN-like output with performance stats */ +#define QRF_STYLE_Markdown 14 /* Markdown formatting */ +#define QRF_STYLE_Column 15 /* One record per line in neat columns */ +#define QRF_STYLE_Table 16 /* MySQL-style table formatting */ +#define QRF_STYLE_Box 17 /* Unicode box-drawing characters */ +#define QRF_STYLE_Count 18 /* Output only a count of the rows of output */ +#define QRF_STYLE_Off 19 /* No query output shown */ ~~~ ### 5.0 Source Code Files @@ -390,7 +392,7 @@ The SQLite Query Result Formatter is implemented in three source code files: * `qrf.c` → The implementation, written in portable C99 * `qrf.h` → A header file defining interfaces - * `qrf.md` → This documentation, in Markdown + * `README.md` → This documentation, in Markdown To use the SQLite result formatter, include the "`qrf.h`" header file and link the application against the "`qrf.c`" source file. diff --git a/ext/qrf/qrf.c b/ext/qrf/qrf.c index d28a671d51..9923aa9769 100644 --- a/ext/qrf/qrf.c +++ b/ext/qrf/qrf.c @@ -51,12 +51,13 @@ struct Qrf { sqlite3_str *pOut; /* Accumulated output */ int iErr; /* Error code */ int nCol; /* Number of output columns */ + int expMode; /* Original sqlite3_stmt_isexplain() plus 1 */ union { struct { /* Content for QRF_STYLE_Line */ int mxColWth; /* Maximum display width of any column */ const char **azCol; /* Names of output columns (MODE_Line) */ } sLine; - EQPGraph *pGraph; /* EQP graph (MODE_EQP) */ + EQPGraph *pGraph; /* EQP graph (Eqp, Stats, and StatsEst) */ struct { /* Content for QRF_STYLE_Explain */ int nIndent; /* Slots allocated for aiIndent */ int iIndent; /* Current slot */ @@ -181,8 +182,8 @@ static void qrfEqpRenderLevel(Qrf *p, int iEqpId){ ** Display and reset the EXPLAIN QUERY PLAN data */ static void qrfEqpRender(Qrf *p, i64 nCycle){ - EQPGraphRow *pRow = p->u.pGraph->pRow; - if( pRow ){ + EQPGraphRow *pRow; + if( p->u.pGraph!=0 && (pRow = p->u.pGraph->pRow)!=0 ){ if( pRow->zText[0]=='-' ){ if( pRow->pNext==0 ){ qrfEqpReset(p); @@ -202,6 +203,129 @@ static void qrfEqpRender(Qrf *p, i64 nCycle){ } } +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +/* +** Helper function for qrfExpStats(). +** +*/ +static int qrfStatsHeight(sqlite3_stmt *p, int iEntry){ + int iPid = 0; + int ret = 1; + sqlite3_stmt_scanstatus_v2(p, iEntry, + SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid + ); + while( iPid!=0 ){ + int ii; + for(ii=0; 1; ii++){ + int iId; + int res; + res = sqlite3_stmt_scanstatus_v2(p, ii, + SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iId + ); + if( res ) break; + if( iId==iPid ){ + sqlite3_stmt_scanstatus_v2(p, ii, + SQLITE_SCANSTAT_PARENTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid + ); + } + } + ret++; + } + return ret; +} +#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ + + +/* +** Generate ".scanstatus est" style of EQP output. +*/ +static void qrfEqpStats(Qrf *p){ +#ifndef SQLITE_ENABLE_STMT_SCANSTATUS + qrfError(p, SQLITE_ERROR, "not available in this build"); +#else + static const int f = SQLITE_SCANSTAT_COMPLEX; + sqlite3_stmt *pS = p->pStmt; + int i = 0; + i64 nTotal = 0; + int nWidth = 0; + sqlite3_str *pLine = sqlite3_str_new(p->db); + sqlite3_str *pStats = sqlite3_str_new(p->db); + qrfEqpReset(p); + + for(i=0; 1; i++){ + const char *z = 0; + int n = 0; + if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){ + break; + } + n = (int)strlen(z) + qrfStatsHeight(pS,i)*3; + if( n>nWidth ) nWidth = n; + } + nWidth += 4; + + sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal); + for(i=0; 1; i++){ + i64 nLoop = 0; + i64 nRow = 0; + i64 nCycle = 0; + int iId = 0; + int iPid = 0; + const char *zo = 0; + const char *zName = 0; + double rEst = 0.0; + + if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){ + break; + } + sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst); + sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop); + sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow); + sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle); + sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId); + sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); + sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName); + + if( nCycle>=0 || nLoop>=0 || nRow>=0 ){ + const char *zSp = ""; + double rpl; + sqlite3_str_reset(pStats); + if( nCycle>=0 && nTotal>0 ){ + sqlite3_str_appendf(pStats, "cycles=%lld [%d%%]", + nCycle, ((nCycle*100)+nTotal/2) / nTotal + ); + zSp = " "; + } + if( nLoop>=0 ){ + sqlite3_str_appendf(pStats, "%sloops=%lld", zSp, nLoop); + zSp = " "; + } + if( nRow>=0 ){ + sqlite3_str_appendf(pStats, "%srows=%lld", zSp, nRow); + zSp = " "; + } + + if( p->spec.eStyle==QRF_STYLE_StatsEst ){ + rpl = (double)nRow / (double)nLoop; + sqlite3_str_appendf(pStats, "%srpl=%.1f est=%.1f", zSp, rpl, rEst); + } + + sqlite3_str_appendf(pLine, + "% *s (%s)", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo, + sqlite3_str_value(pStats) + ); + sqlite3_str_reset(pStats); + qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine)); + sqlite3_str_reset(pLine); + }else{ + qrfEqpAppend(p, iId, iPid, zo); + } + } + sqlite3_free(sqlite3_str_finish(pLine)); + sqlite3_free(sqlite3_str_finish(pStats)); +#endif +} + + /* ** Reset the prepared statement. */ @@ -1410,7 +1534,7 @@ static void qrfExplain(Qrf *p){ int nWidth = sizeof(aExplainWidth)/sizeof(int); int iIndent = 1; int nArg = p->nCol; - if( p->spec.eStyle==QRF_STYLE_ScanExp ){ + if( p->spec.eStyle==QRF_STYLE_StatsVm ){ aWidth = aScanExpWidth; aMap = aScanExpMap; nWidth = sizeof(aScanExpWidth)/sizeof(int); @@ -1541,7 +1665,7 @@ qrf_reinit: switch( sqlite3_stmt_isexplain(pStmt) ){ case 0: p->spec.eStyle = QRF_STYLE_Box; break; case 1: p->spec.eStyle = QRF_STYLE_Explain; break; - default: p->spec.eStyle = QRF_STYLE_EQP; break; + default: p->spec.eStyle = QRF_STYLE_Eqp; break; } goto qrf_reinit; } @@ -1592,37 +1716,19 @@ qrf_reinit: p->spec.zRowSep = "\n"; break; } - case QRF_STYLE_EQP: { - if( sqlite3_stmt_isexplain(p->pStmt)!=2 ){ - /* If EQP mode is requested, but the statement is not an EXPLAIN QUERY - ** PLAN statement, then convert the mode to a comma-separate list of - ** SQL-quoted values. Downstream expects an EQP statement if the - ** mode is EQP, so do not leave the mode in EQP if the statement is - ** not an EQP statement. - */ - p->spec.eStyle = QRF_STYLE_Column; - p->spec.bColumnNames = QRF_SW_On; - p->spec.eText = QRF_TEXT_Sql; - p->spec.eBlob = QRF_BLOB_Sql; - p->spec.zColumnSep = " "; - p->spec.zRowSep = "\n"; + case QRF_STYLE_Eqp: { + int expMode = sqlite3_stmt_isexplain(p->pStmt); + if( expMode!=2 ){ + sqlite3_stmt_explain(p->pStmt, 2); + p->expMode = expMode+1; } break; } case QRF_STYLE_Explain: { - if( sqlite3_stmt_isexplain(p->pStmt)!=1 ){ - /* If Explain mode is requested, but the statement is not an EXPLAIN - ** tatement, then convert the mode to a comma-separate list of - ** SQL-quoted values. Downstream expects an Explain statement if the - ** mode is Explain, so do not leave the mode in Explain if the - ** statement is not an EXPLAIN statement. - */ - p->spec.eStyle = QRF_STYLE_Column; - p->spec.bColumnNames = QRF_SW_On; - p->spec.eText = QRF_TEXT_Sql; - p->spec.eBlob = QRF_BLOB_Sql; - p->spec.zColumnSep = " "; - p->spec.zRowSep = "\n"; + int expMode = sqlite3_stmt_isexplain(p->pStmt); + if( expMode!=1 ){ + sqlite3_stmt_explain(p->pStmt, 1); + p->expMode = expMode+1; } break; } @@ -1790,7 +1896,7 @@ static void qrfOneSimpleRow(Qrf *p){ qrfWrite(p); break; } - case QRF_STYLE_EQP: { + case QRF_STYLE_Eqp: { const char *zEqpLine = (const char*)sqlite3_column_text(p->pStmt,3); int iEqpId = sqlite3_column_int(p->pStmt, 0); int iParentId = sqlite3_column_int(p->pStmt, 1); @@ -1843,7 +1949,9 @@ static void qrfFinalize(Qrf *p){ if( p->u.sLine.azCol ) sqlite3_free(p->u.sLine.azCol); break; } - case QRF_STYLE_EQP: { + case QRF_STYLE_Stats: + case QRF_STYLE_StatsEst: + case QRF_STYLE_Eqp: { qrfEqpRender(p, 0); qrfWrite(p); break; @@ -1871,7 +1979,12 @@ static void qrfFinalize(Qrf *p){ }else if( p->pOut ){ sqlite3_free(sqlite3_str_finish(p->pOut)); } - if( p->actualWidth ) sqlite3_free(p->actualWidth); + if( p->expMode>0 ){ + sqlite3_stmt_explain(p->pStmt, p->expMode-1); + } + if( p->actualWidth ){ + sqlite3_free(p->actualWidth); + } if( p->pJTrans ){ sqlite3 *db = sqlite3_db_handle(p->pJTrans); sqlite3_finalize(p->pJTrans); @@ -1909,10 +2022,15 @@ int sqlite3_format_query_result( qrfExplain(&qrf); break; } - case QRF_STYLE_ScanExp: { + case QRF_STYLE_StatsVm: { qrfScanStatusVm(&qrf); break; } + case QRF_STYLE_Stats: + case QRF_STYLE_StatsEst: { + qrfEqpStats(&qrf); + break; + } default: { /* Non-columnar modes where the output can occur after each row ** of result is received */ diff --git a/ext/qrf/qrf.h b/ext/qrf/qrf.h index 4b031b4b68..6f3455c172 100644 --- a/ext/qrf/qrf.h +++ b/ext/qrf/qrf.h @@ -73,14 +73,16 @@ int sqlite3_format_query_result( #define QRF_STYLE_Csv 6 /* Comma-separated-value */ #define QRF_STYLE_Quote 7 /* SQL-quoted, comma-separated */ #define QRF_STYLE_Explain 8 /* EXPLAIN output */ -#define QRF_STYLE_ScanExp 9 /* EXPLAIN output with vm stats */ -#define QRF_STYLE_EQP 10 /* Format EXPLAIN QUERY PLAN output */ -#define QRF_STYLE_Markdown 11 /* Markdown formatting */ -#define QRF_STYLE_Column 12 /* One record per line in neat columns */ -#define QRF_STYLE_Table 13 /* MySQL-style table formatting */ -#define QRF_STYLE_Box 14 /* Unicode box-drawing characters */ -#define QRF_STYLE_Count 15 /* Output only a count of the rows of output */ -#define QRF_STYLE_Off 16 /* No query output shown */ +#define QRF_STYLE_Eqp 10 /* Format EXPLAIN QUERY PLAN output */ +#define QRF_STYLE_Stats 11 /* EQP-like output but with performance stats */ +#define QRF_STYLE_StatsEst 12 /* EQP-like output with planner estimates */ +#define QRF_STYLE_StatsVm 13 /* EXPLAIN-like output with performance stats */ +#define QRF_STYLE_Markdown 14 /* Markdown formatting */ +#define QRF_STYLE_Column 15 /* One record per line in neat columns */ +#define QRF_STYLE_Table 16 /* MySQL-style table formatting */ +#define QRF_STYLE_Box 17 /* Unicode box-drawing characters */ +#define QRF_STYLE_Count 18 /* Output only a count of the rows of output */ +#define QRF_STYLE_Off 19 /* No query output shown */ /* ** Quoting styles for text. diff --git a/manifest b/manifest index 8e2cabe952..cf97f546aa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\stry\sto\simprove\sEXPLAIN\scapabilities.\s\sThis\sis\sa\ssnapshot\nprior\sto\san\sattempt\sto\smake\ssweeping\schanges\sin\sthat\sarea\sof\sthe\ninterface. -D 2025-11-06T17:28:34.534 +C Revamp\sso\sthat\sExplain\sand\sEqp\sstyles\sforce\sthe\sstatement\sinto\sthe\nthe\sappropriate\sexplain-mode\sfor\sthe\srendering\sand\srestore\sit\safterwards.\nAdd\sthe\snew\sscanstatus\sstyles:\sStats,\sStatsEst,\sand\sStatsVm. +D 2025-11-06T19:22:34.130 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -416,9 +416,9 @@ F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f6 F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c F ext/misc/zipfile.c 09e6e3a3ff40a99677de3c0bc6569bd5f4709b1844ac3d1c1452a456c5a62f1c F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee -F ext/qrf/README.md 5f12f91104d5df8ba8783e2240635698569ce54935e721b3a4e93abf4e00ddcb -F ext/qrf/qrf.c 598c793d08461d62ed4e74078f8542e2ff4a733ff4eeaa05de8dbd8c5829f311 -F ext/qrf/qrf.h 98e02eded10848c42053d37e56bd15ab69cb6fe9fc1f1ca05823d9047e9c8509 +F ext/qrf/README.md 9e0064b137239d19427a1ce1c148c5b45bba2741c466f03af19221dddf90c4c9 +F ext/qrf/qrf.c 82392dc3fb199d019dea4aa0bb381b7f4fa3b9cefb8e24f4806306f6fae17c02 +F ext/qrf/qrf.h c7ae981ab59b96d7ec2baeb391c0d7ce1e4f90ad673b7b1a8a7391fc6796de0e F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8 F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255 F ext/rbu/rbu10.test 7c22caa32c2ff26983ca8320779a31495a6555737684af7aba3daaf762ef3363 @@ -743,7 +743,7 @@ F src/sqliteInt.h 88f7fc9ce1630d9a5f7e0a8e1f3287cdc63882fba985c18e7eee1b9f457f59 F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 -F src/tclsqlite.c 6e87dda56e2add1581063c281f9fd2d4f65605bbabd6d36660905e579a20fc13 +F src/tclsqlite.c cf04173ac121e053b7cc30cd987c479af9eb027a5bcf1648b7a7dde8567c9ccb F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a F src/test1.c f880ab766eeedf2c063662bd9538b923fd42c4341b7bfc2150a6d93ab8b9341c F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff @@ -1506,7 +1506,7 @@ F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224c F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/pushdown.test 46a626ef1c0ca79b85296ff2e078b9da20a50e9b804b38f441590c3987580ddd -F test/qrf01.test 75acb2a17dfa8cbc5c0e70bcb6b90eb176ec39a08a8427e73210d537e0280f04 +F test/qrf01.test 1560df867282d37c4d43a4b2e66606ab129ade70fa1a1a3b9a720769ec8e36d0 F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92 F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 @@ -2173,8 +2173,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4e2ada6ad8a56d00aeb73570dc4ee22c484b65b8100a42a7085414d0a4c68afd -R ada052660ca6412932dab58de0554df7 +P e7367d8089d43a06933f919c33c6edb15ee9bedf52d9a2d9ea989654077d998f +R 93a1daf233952c02bd3cbe8cc59f80a0 U drh -Z e00ad94c88d3ff9e91d08c82898645f1 +Z d7063f3e75c72a15a6aaacd6e379ef65 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 85977569a5..c82c77b577 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e7367d8089d43a06933f919c33c6edb15ee9bedf52d9a2d9ea989654077d998f +128f1149076ef00c567405ea2112be0ae665b12e81672ae5494d82af11633af5 diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 6fe9edc6fd..b272594aba 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2122,16 +2122,16 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){ "count", "csv", "eqp", "explain", "html", "insert", "json", "line", "list", - "markdown", "quote", "scanexp", - "table", 0 + "markdown", "quote", "stats", + "stats-est", "stats-vm", "table", 0 }; static unsigned char aStyleMap[] = { QRF_STYLE_Auto, QRF_STYLE_Box, QRF_STYLE_Column, - QRF_STYLE_Count, QRF_STYLE_Csv, QRF_STYLE_EQP, + QRF_STYLE_Count, QRF_STYLE_Csv, QRF_STYLE_Eqp, QRF_STYLE_Explain, QRF_STYLE_Html, QRF_STYLE_Insert, QRF_STYLE_Json, QRF_STYLE_Line, QRF_STYLE_List, - QRF_STYLE_Markdown, QRF_STYLE_Quote, QRF_STYLE_ScanExp, - QRF_STYLE_Table + QRF_STYLE_Markdown, QRF_STYLE_Quote, QRF_STYLE_Stats, + QRF_STYLE_StatsEst, QRF_STYLE_StatsVm, QRF_STYLE_Table }; int style; rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azStyles, diff --git a/test/qrf01.test b/test/qrf01.test index 4c44a9cdde..77d8b9329d 100644 --- a/test/qrf01.test +++ b/test/qrf01.test @@ -80,7 +80,7 @@ do_test 1.15 { do_test 1.16 { catch {db format -text sql -style unk {SELECT * FROM t1}} res set res -} {bad format style (-style) "unk": must be auto, box, column, count, csv, eqp, explain, html, insert, json, line, list, markdown, quote, scanexp, or table} +} {bad format style (-style) "unk": must be auto, box, column, count, csv, eqp, explain, html, insert, json, line, list, markdown, quote, stats, stats-est, stats-vm, or table} do_test 1.20 { -- 2.47.3