From: larrybr Date: Thu, 24 Feb 2022 04:29:09 +0000 (+0000) Subject: Regularize CLI .mode processing X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a6f9a8d97ff12360cff4c711293d5f5db6f3c543;p=thirdparty%2Fsqlite.git Regularize CLI .mode processing FossilOrigin-Name: 6d0557244f69e78474f9222aae95c4c47925a466aa15e5666d0ada237538e262 --- diff --git a/manifest b/manifest index f70c7f90be..da4d88a4cb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Sync\swith\s3.38 -D 2022-02-23T10:10:59.145 +C Regularize\sCLI\s.mode\sprocessing +D 2022-02-24T04:29:09.586 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -555,7 +555,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35 -F src/shell.c.in 1986c71edd5023c320d5c68a14a464cc375cf7b3d7b7fc730bd6368a89576882 +F src/shell.c.in 0b1269056aca0e71680a65dac98bd731597f97334ab7a06509eba49f4d6e5093 F src/shext_linkage.h 5897e8140a06cb733d07a927994b30d41225eb93b5b8cf2ad0e3460cb4e95fd6 F src/sqlite.h.in e30cedf008d9c51511f4027a3739b727a588da553424748b48d2393f85dbde41 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1391,7 +1391,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 8ff9d7684346a39fdd73e201d30788b5d2207fd527d83ba793f8b1a85d6f34d1 +F test/shell1.test e05b84687a531419165dd79aefcfd149e4da24532480ec93439ddfa13efdf65b F test/shell2.test aed8773dd236517149a6abaeccf94f066e5a0c871108e8d21889122132dd51ba F test/shell3.test a50628ab1d78d90889d9d3f32fb2c084ee15674771e96afe954aaa0accd1de3c F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759 @@ -1947,8 +1947,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 ec363f81ce775bb3313d08a959e1573f694f18eb4699a33a9b98ce241056292e 710de6a2137c872812effa43ea888aa77d339362ca0b6c8990d4426c8fb20689 -R 3e137f57c07bfa1d2f3bcf91d0b0c096 +P b9b27d74b93ada32ece46c9e53652f766de97f5a77fe4c34251996697374e659 +R 3b1535aa20e62ad155a398c2745a0c17 U larrybr -Z adaf44bd0c510479196b838bd6c2a755 +Z 1bf768e26b209b9a9f7fc853e590446e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e889478348..d3eefb1647 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b9b27d74b93ada32ece46c9e53652f766de97f5a77fe4c34251996697374e659 \ No newline at end of file +6d0557244f69e78474f9222aae95c4c47925a466aa15e5666d0ada237538e262 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 0f6b684706..92a773bd53 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1285,48 +1285,55 @@ static void updateSafeMode(ShellState *pSS){ #define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X))) /* -** These are the allowed modes. +** These are the allowed modes, in search order (for abbreviation matches.) */ #define MODE_Line 0 /* One column per line. Blank line between records */ #define MODE_Column 1 /* One record per line in neat columns */ #define MODE_List 2 /* One record per line with a separator */ -#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ -#define MODE_Html 4 /* Generate an XHTML table */ -#define MODE_Insert 5 /* Generate SQL "insert" statements */ -#define MODE_Quote 6 /* Quote values as for SQL */ -#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ -#define MODE_Csv 8 /* Quote strings, numbers are plain */ -#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ -#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ -#define MODE_Pretty 11 /* Pretty-print schemas */ -#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */ -#define MODE_Json 13 /* Output JSON */ -#define MODE_Markdown 14 /* Markdown formatting */ -#define MODE_Table 15 /* MySQL-style table formatting */ -#define MODE_Box 16 /* Unicode box-drawing characters */ -#define MODE_Count 17 /* Output only a count of the rows of output */ -#define MODE_Off 18 /* No query output shown */ - -static const char *modeDescr[] = { - "line", - "column", - "list", - "semi", - "html", - "insert", - "quote", - "tcl", - "csv", - "explain", - "ascii", - "prettyprint", - "eqp", - "json", - "markdown", - "table", - "box", - "count", - "off" +#define MODE_Html 3 /* Generate an XHTML table */ +#define MODE_Tcl 4 /* Generate ANSI-C or TCL quoted elements */ +#define MODE_Csv 5 /* Quote strings, numbers are plain */ +#define MODE_Tab 6 /* Transitory */ +#define MODE_Insert 7 /* Generate SQL "insert" statements */ +#define MODE_Quote 8 /* Quote values as for SQL */ +#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ +#define MODE_Markdown 10 /* Markdown formatting */ +#define MODE_Table 11 /* MySQL-style table formatting */ +#define MODE_Box 12 /* Unicode box-drawing characters */ +#define MODE_Count 13 /* Output only a count of the rows of output */ +#define MODE_Off 14 /* No query output shown */ +#define MODE_Json 15 /* Output JSON */ +#define MODE_EQP 16 /* Converts EXPLAIN QUERY PLAN output into a graph */ +#define MODE_Explain 17 /* Like MODE_Column, but do not truncate data */ +#define MODE_Pretty 18 /* Pretty-print schemas */ +#define MODE_Semi 19 /* Same as MODE_List but append ";" to each line */ +#define MODE_COUNT_OF 20 +static struct { + const char *zModeName; + u8 bDepluralize; + u8 bUserBlocked; + u8 iAliasFor; +} modeDescr[] = { + { "lines", 1, 0, MODE_Line }, + { "columns", 1, 0, MODE_Column }, + { "list", 0, 0, MODE_List }, + { "html", 0, 0, MODE_Html }, + { "tcl", 0, 0, MODE_Tcl }, + { "csv", 0, 0, MODE_Csv }, + { "tabs", 1, 0, MODE_List }, + { "insert", 0, 0, MODE_Insert }, + { "quote", 0, 0, MODE_Quote }, + { "ascii", 0, 0, MODE_Ascii }, + { "markdown", 0, 0, MODE_Markdown }, + { "table", 0, 0, MODE_Table }, + { "box", 0, 0, MODE_Box }, + { "count", 0, 0, MODE_Count }, + { "off", 0, 0, MODE_Off }, + { "json", 0, 0, MODE_Json }, + { "eqp", 0, 1, MODE_EQP }, + { "explain", 0, 1, MODE_Explain }, + { "prettyprint", 0, 1, MODE_Pretty }, + { "semi", 0, 1, MODE_Semi } }; /* @@ -9177,126 +9184,153 @@ COLLECT_HELP_TEXT[ " --noquote Do not quote output text", " TABLE The name of SQL table used for \"insert\" mode", ]; -DISPATCHABLE_COMMAND( mode ? 1 3 ){ - const char *zMode = 0; +DISPATCHABLE_COMMAND( mode ? 1 0 ){ const char *zTabname = 0; - int i, n2; + const char *zArg; + int i; + u8 foundMode = MODE_COUNT_OF, setMode = MODE_COUNT_OF; ColModeOpts cmOpts = ColModeOpts_default; for(i=1; imode==MODE_Column - || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) - ){ + /* Not a known option. Check for known mode, or possibly a table name. */ + if( foundMode==MODE_Insert && zTabname==0 ){ + zTabname = zArg; + }else if( *zArg=='-' ){ + goto flag_unknown; + }else{ + int im, nza = strlen30(zArg); + if( foundMode!=MODE_COUNT_OF ) goto mode_badarg; + for( im=0; immode; + assert(i>=0 && imode==MODE_Column || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) ){ raw_printf - (p->out, - "current output mode: %s --wrap %d --wordwrap %s --%squote\n", - modeDescr[p->mode], p->cmOpts.iWrap, + (p->out, "current output mode: %.*s --wrap %d --wordwrap %s --%squote\n", + nms, zMode, p->cmOpts.iWrap, p->cmOpts.bWordWrap ? "on" : "off", p->cmOpts.bQuote ? "" : "no"); }else{ - raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]); - } - zMode = modeDescr[p->mode]; - } - n2 = strlen30(zMode); - if( strncmp(zMode,"lines",n2)==0 ){ - p->mode = MODE_Line; - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( strncmp(zMode,"columns",n2)==0 ){ - p->mode = MODE_Column; - if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){ - p->showHeader = 1; - } - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - p->cmOpts = cmOpts; - }else if( strncmp(zMode,"list",n2)==0 ){ - p->mode = MODE_List; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( strncmp(zMode,"html",n2)==0 ){ - p->mode = MODE_Html; - }else if( strncmp(zMode,"tcl",n2)==0 ){ - p->mode = MODE_Tcl; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( strncmp(zMode,"csv",n2)==0 ){ - p->mode = MODE_Csv; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); - }else if( strncmp(zMode,"tabs",n2)==0 ){ - p->mode = MODE_List; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); - }else if( strncmp(zMode,"insert",n2)==0 ){ - p->mode = MODE_Insert; - set_table_name(p, zTabname ? zTabname : "table"); - }else if( strncmp(zMode,"quote",n2)==0 ){ - p->mode = MODE_Quote; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( strncmp(zMode,"ascii",n2)==0 ){ - p->mode = MODE_Ascii; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); - }else if( strncmp(zMode,"markdown",n2)==0 ){ - p->mode = MODE_Markdown; - p->cmOpts = cmOpts; - }else if( strncmp(zMode,"table",n2)==0 ){ - p->mode = MODE_Table; - p->cmOpts = cmOpts; - }else if( strncmp(zMode,"box",n2)==0 ){ - p->mode = MODE_Box; - p->cmOpts = cmOpts; - }else if( strncmp(zMode,"count",n2)==0 ){ - p->mode = MODE_Count; - }else if( strncmp(zMode,"off",n2)==0 ){ - p->mode = MODE_Off; - }else if( strncmp(zMode,"json",n2)==0 ){ - p->mode = MODE_Json; + raw_printf(p->out, "current output mode: %.*s\n", nms, zMode); + } }else{ - raw_printf(stderr, "Error: mode should be one of: " - "ascii box column csv html insert json line list markdown " - "qbox quote table tabs tcl\n"); - return 1; + /* Effect the specified mode change. */ + const char *zColSep = 0, *zRowSep = 0; + assert(setMode!=MODE_COUNT_OF); + switch( foundMode ){ + case MODE_Line: + zRowSep = SEP_Row; + break; + case MODE_Column: + if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){ + p->showHeader = 1; + } + zRowSep = SEP_Row; + p->cmOpts = cmOpts; + break; + case MODE_List: + zColSep = SEP_Column; + zRowSep = SEP_Row; + break; + case MODE_Html: + break; + case MODE_Tcl: + zColSep = SEP_Space; + zRowSep = SEP_Row; + break; + case MODE_Csv: + zColSep = SEP_Comma; + zRowSep = SEP_CrLf; + break; + case MODE_Tab: + zColSep = SEP_Tab; + break; + case MODE_Insert: + set_table_name(p, zTabname ? zTabname : "table"); + break; + case MODE_Quote: + zColSep = SEP_Comma; + zRowSep = SEP_Row; + break; + case MODE_Ascii: + zColSep = SEP_Unit; + zRowSep = SEP_Record; + break; + case MODE_Markdown: + /* fall-thru */ + case MODE_Table: + /* fall-thru */ + case MODE_Box: + p->cmOpts = cmOpts; + break; + case MODE_Count: + /* fall-thru */ + case MODE_Off: + /* fall-thru */ + case MODE_Json: + break; + case MODE_Explain: case MODE_Semi: case MODE_EQP: case MODE_Pretty: default: + /* Modes used internally, not settable by .mode command. */ + return 0; + } + if( zRowSep!=0 ){ + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, zRowSep); + } + if( zColSep!=0 ){ + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, zColSep); + } + p->mode = setMode; } p->cMode = p->mode; return 0; + flag_unknown: + utf8_printf(stderr, "Error: Unknown .mode option: %s\nValid options:\n%s", + zArg, + " --noquote\n" + " --quote\n" + " --wordwrap on/off\n" + " --wrap N\n" + " --ww\n"); + return 1; + mode_unknown: + raw_printf(stderr, "Error: Mode should be one of: " + "ascii box column csv html insert json line list markdown " + "qbox quote table tabs tcl\n"); + return 1; + mode_badarg: + utf8_printf(stderr, "Error: Invalid .mode argument: %s\n", zArg); + return 1; } /***************** @@ -10715,16 +10749,18 @@ DISPATCHABLE_COMMAND( show ? 1 1 ){ utf8_printf(p->out, "%12.12s: %s\n","explain", p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); + zOut = modeDescr[p->mode].zModeName; + i = strlen30(zOut) - modeDescr[p->mode].bDepluralize; if( p->mode==MODE_Column || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) ){ utf8_printf - (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode", - modeDescr[p->mode], p->cmOpts.iWrap, + (p->out, "%12.12s: %.*s --wrap %d --wordwrap %s --%squote\n", "mode", + i, zOut, p->cmOpts.iWrap, p->cmOpts.bWordWrap ? "on" : "off", p->cmOpts.bQuote ? "" : "no"); }else{ - utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); + utf8_printf(p->out, "%12.12s: %.*s\n","mode", i, zOut); } utf8_printf(p->out, "%12.12s: ", "nullvalue"); output_c_string(p->out, p->nullValue); diff --git a/test/shell1.test b/test/shell1.test index fee302b5dd..2aca271e37 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -190,7 +190,7 @@ do_test shell1-2.1.3 { catchcmd "test.db" ".\'foo OFF\'" } {1 {Error: unknown command: "foo OFF"}} -set modeShouldBe "Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl" +set modeShouldBe "Error: Mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl" # unbalanced quotes do_test shell1-2.2.1 { @@ -466,17 +466,11 @@ do_test shell1-3.13.10 { do_test shell1-3.13.11 { # extra arguments rejected catchcmd "test.db" ".mode tcl BAD" -} {1 {Error: invalid arguments for ".mode"}} +} {1 {Error: Invalid .mode argument: BAD}} -# don't allow too-partial mode type matches +# allow partial mode type matches do_test shell1-3.13.12 { catchcmd "test.db" ".mode l" -} [list 1 $modeShouldBe] -do_test shell1-3.13.13 { - catchcmd "test.db" ".mode li" -} [list 1 $modeShouldBe] -do_test shell1-3.13.14 { - catchcmd "test.db" ".mode lin" } {0 {}} # .nullvalue STRING Print STRING in place of NULL values