From 3a5f3aa85800fd63047f0eca02946c2f7f88dbc5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 11 Nov 2025 00:44:25 +0000 Subject: [PATCH] Factor the code for ".mode" out of do_meta_command() and into its own subroutine, to show how the new infrastructure makes this easy. We need to do the same for all the dot-commands. At the same time, add the -textjsonb option to .mode. FossilOrigin-Name: b48aa054df488747a7db56faf1cd0da42e322edff60650b9187448e58eb12def --- manifest | 12 +- manifest.uuid | 2 +- src/shell.c.in | 348 ++++++++++++++++++++++++++----------------------- 3 files changed, 193 insertions(+), 169 deletions(-) diff --git a/manifest b/manifest index 2925737c6e..7382392ac0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Bug\sfixes.\s\sAll\stests\sare\snow\spassing. -D 2025-11-11T00:21:26.959 +C Factor\sthe\scode\sfor\s".mode"\sout\sof\sdo_meta_command()\sand\sinto\sits\sown\nsubroutine,\sto\sshow\show\sthe\snew\sinfrastructure\smakes\sthis\seasy.\s\sWe\sneed\nto\sdo\sthe\ssame\sfor\sall\sthe\sdot-commands.\s\sAt\sthe\ssame\stime,\sadd\sthe\n-textjsonb\soption\sto\s.mode. +D 2025-11-11T00:44:25.681 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -735,7 +735,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c 5616fbcf3b833c7c705b24371828215ad0925d0c0073216c4f153348d5753f0a F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c ba9cd07ffa3277883c1986085f6ddc4320f4d35d5f212ab58df79a7ecc1a576a -F src/shell.c.in 41eafc6ecd66a9cb99b6efb522c3d25eb074078e689fe8ffcd722f38c23dd1d9 +F src/shell.c.in e3f804207b35a78be6a72c794291b771de7fafdc319fce3f9f2979bbf14d7488 F src/sqlite.h.in 7403a952a8f1239de7525b73c4e3a0f9540ec0607ed24fec887f5832642d44b8 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 7f236ca1b175ffe03316d974ef57df79b3938466c28d2f95caef5e08c57f3a52 @@ -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 8cc581e53c2ab15bd311e082048b7c57b03a754d25c0b4beead08a3362ac1c7a -R 5ec50f9665eadf1d8e44e1c03a2dcff7 +P a0fc99a3bdd12f9ac69511c1aea2bd9a3d5de593d44b4a732cfc8f48e0931c76 +R 89d6866f71ef4d7cd775ab4a25b5defa U drh -Z 2e2be373085f7686f8e083362b123b95 +Z d05d0d77f90346dd26288eb7ce7ea406 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 23f7f7ed40..8b673851dc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a0fc99a3bdd12f9ac69511c1aea2bd9a3d5de593d44b4a732cfc8f48e0931c76 +b48aa054df488747a7db56faf1cd0da42e322edff60650b9187448e58eb12def diff --git a/src/shell.c.in b/src/shell.c.in index 68d6678c1a..93d2ae414d 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -6981,6 +6981,191 @@ static int faultsim_callback(int iArg){ return faultsim_state.iErr; } +/* +** COMMAND: .mode +*/ +static int dotCmdMode(ShellState *p){ + int nArg = p->dot.nArg; + char **azArg = p->dot.azArg; + const char *zMode = 0; + const char *zTabname = 0; + int i, n2; + int chng = 0; /* 0x01: change to cmopts. 0x02: Any other change */ + + for(i=1; iQRF_MAX_WIDTH ) w = QRF_MAX_WIDTH; + p->mode.spec.mxColWidth = w; + chng |= 1; + }else if( optionMatch(z,"ww") ){ + p->mode.spec.bWordWrap = QRF_Yes; + chng |= 1; + }else if( optionMatch(z,"wordwrap") ){ + if( i+1>=nArg ){ + dotCmdError(p, i, "missing argument", 0); + return 1; + } + p->mode.spec.bWordWrap = (u8)booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; + chng |= 1; + }else if( optionMatch(z,"quote") ){ + p->mode.spec.eText = QRF_TEXT_Sql; + p->mode.spec.eBlob = QRF_BLOB_Sql; + chng |= 1; + }else if( optionMatch(z,"textjsonb") ){ + if( i+1>=nArg ){ + dotCmdError(p, i, "missing argument", 0); + return 1; + } + p->mode.spec.bTextJsonb = (u8)booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; + chng |= 1; + }else if( optionMatch(z,"noquote") ){ + p->mode.spec.eText = QRF_Auto; + p->mode.spec.eBlob = QRF_Auto; + chng |= 1; + }else if( optionMatch(z,"escape") ){ + /* See similar code at tag-20250224-1 */ + if( i+1>=nArg ){ + dotCmdError(p, i, "missing argument", 0); + return 1; + } + const char *zEsc = azArg[++i]; + int k; + for(k=0; kmode.spec.eEsc = k; + chng |= 2; + break; + } + } + if( k>=ArraySize(qrfEscNames) ){ + sqlite3_fprintf(stderr, "unknown control character escape mode \"%s\"" + " - choices:", zEsc); + for(k=0; kmode.spec.eText = QRF_TEXT_Sql; + p->mode.spec.eBlob = QRF_BLOB_Sql; + } + }else if( zTabname==0 ){ + zTabname = z; + }else if( z[0]=='-' ){ + sqlite3_fprintf(stderr,"unknown option: %s\n", z); + eputz("options:\n" + " --escape MODE\n" + " --noquote\n" + " --quote\n" + " --wordwrap on/off\n" + " --wrap N\n" + " --ww\n"); + return 1; + }else{ + sqlite3_fprintf(stderr,"extra argument: \"%s\"\n", z); + return 1; + } + } + if( !chng ){ + if( p->mode.eMode==MODE_Column + || p->mode.eMode==MODE_Box + || p->mode.eMode==MODE_Table + || p->mode.eMode==MODE_Markdown + ){ + sqlite3_fprintf(p->out, "current output mode: %s", + modeDescr[p->mode.eMode]); + if( p->mode.spec.mxColWidth ){ + sqlite3_fprintf(p->out, " --wrap %d", + p->mode.spec.mxColWidth); + }else{ + sqlite3_fprintf(p->out, " --wrap off"); + } + sqlite3_fprintf(p->out, " --wordwrap %s --%squote --escape %s\n", + p->mode.spec.bWordWrap==QRF_Yes ? "on" : "off", + p->mode.spec.eText==QRF_TEXT_Sql ? "" : "no", + qrfEscNames[p->mode.spec.eEsc==QRF_ESC_Auto? + QRF_ESC_Ascii:p->mode.spec.eEsc] + ); + }else{ + sqlite3_fprintf(p->out, + "current output mode: %s --escape %s\n", + modeDescr[p->mode.eMode], + qrfEscNames[p->mode.spec.eEsc==QRF_ESC_Auto? + QRF_ESC_Ascii:p->mode.spec.eEsc] + ); + } + } + if( zMode==0 ){ + zMode = modeDescr[p->mode.eMode]; + } + n2 = strlen30(zMode); + if( cli_strncmp(zMode,"lines",n2)==0 ){ + p->mode.eMode = MODE_Line; + modeSetStr(&p->mode.spec.zRowSep, SEP_Row); + }else if( cli_strncmp(zMode,"columns",n2)==0 ){ + p->mode.eMode = MODE_Column; + modeSetStr(&p->mode.spec.zRowSep, SEP_Row); + }else if( cli_strncmp(zMode,"list",n2)==0 ){ + p->mode.eMode = MODE_List; + modeSetStr(&p->mode.spec.zColumnSep, SEP_Column); + modeSetStr(&p->mode.spec.zRowSep, SEP_Row); + }else if( cli_strncmp(zMode,"html",n2)==0 ){ + p->mode.eMode = MODE_Html; + }else if( cli_strncmp(zMode,"tcl",n2)==0 ){ + p->mode.eMode = MODE_Tcl; + modeSetStr(&p->mode.spec.zColumnSep, SEP_Space); + modeSetStr(&p->mode.spec.zRowSep, SEP_Row); + }else if( cli_strncmp(zMode,"csv",n2)==0 ){ + p->mode.eMode = MODE_Csv; + modeSetStr(&p->mode.spec.zColumnSep, SEP_Comma); + modeSetStr(&p->mode.spec.zRowSep, SEP_CrLf); + }else if( cli_strncmp(zMode,"tabs",n2)==0 ){ + p->mode.eMode = MODE_List; + modeSetStr(&p->mode.spec.zColumnSep, SEP_Tab); + }else if( cli_strncmp(zMode,"insert",n2)==0 ){ + p->mode.eMode = MODE_Insert; + modeSetStr(&p->mode.spec.zTableName, zTabname); + }else if( cli_strncmp(zMode,"quote",n2)==0 ){ + p->mode.eMode = MODE_Quote; + modeSetStr(&p->mode.spec.zColumnSep, SEP_Comma); + modeSetStr(&p->mode.spec.zRowSep, SEP_Row); + }else if( cli_strncmp(zMode,"ascii",n2)==0 ){ + p->mode.eMode = MODE_Ascii; + modeSetStr(&p->mode.spec.zColumnSep, SEP_Unit); + modeSetStr(&p->mode.spec.zRowSep, SEP_Record); + }else if( cli_strncmp(zMode,"markdown",n2)==0 ){ + p->mode.eMode = MODE_Markdown; + }else if( cli_strncmp(zMode,"table",n2)==0 ){ + p->mode.eMode = MODE_Table; + }else if( cli_strncmp(zMode,"box",n2)==0 ){ + p->mode.eMode = MODE_Box; + }else if( cli_strncmp(zMode,"count",n2)==0 ){ + p->mode.eMode = MODE_Count; + }else if( cli_strncmp(zMode,"off",n2)==0 ){ + p->mode.eMode = MODE_Off; + }else if( cli_strncmp(zMode,"json",n2)==0 ){ + p->mode.eMode = MODE_Json; + }else{ + eputz("Error: mode should be one of: " + "ascii box column csv html insert json line list markdown " + "qbox quote table tabs tcl\n"); + return 1; + } + return 0; +} + + /* ** If an input line begins with "." then invoke this routine to ** process that line. @@ -8394,168 +8579,7 @@ static int do_meta_command(const char *zLine, ShellState *p){ }else if( c=='m' && cli_strncmp(azArg[0], "mode", n)==0 ){ - const char *zMode = 0; - const char *zTabname = 0; - int i, n2; - int chng = 0; /* 0x01: change to cmopts. 0x02: Any other change */ - for(i=1; iQRF_MAX_WIDTH ) w = QRF_MAX_WIDTH; - p->mode.spec.mxColWidth = w; - chng |= 1; - }else if( optionMatch(z,"ww") ){ - p->mode.spec.bWordWrap = QRF_Yes; - chng |= 1; - }else if( optionMatch(z,"wordwrap") && i+1mode.spec.bWordWrap = (u8)booleanValue(azArg[++i]) ? QRF_Yes : QRF_No; - chng |= 1; - }else if( optionMatch(z,"quote") ){ - p->mode.spec.eText = QRF_TEXT_Sql; - p->mode.spec.eBlob = QRF_BLOB_Sql; - chng |= 1; - }else if( optionMatch(z,"noquote") ){ - p->mode.spec.eText = QRF_Auto; - p->mode.spec.eBlob = QRF_Auto; - chng |= 1; - }else if( optionMatch(z,"escape") && i+1mode.spec.eEsc = k; - chng |= 2; - break; - } - } - if( k>=ArraySize(qrfEscNames) ){ - sqlite3_fprintf(stderr, "unknown control character escape mode \"%s\"" - " - choices:", zEsc); - for(k=0; kmode.spec.eText = QRF_TEXT_Sql; - p->mode.spec.eBlob = QRF_BLOB_Sql; - } - }else if( zTabname==0 ){ - zTabname = z; - }else if( z[0]=='-' ){ - sqlite3_fprintf(stderr,"unknown option: %s\n", z); - eputz("options:\n" - " --escape MODE\n" - " --noquote\n" - " --quote\n" - " --wordwrap on/off\n" - " --wrap N\n" - " --ww\n"); - rc = 1; - goto meta_command_exit; - }else{ - sqlite3_fprintf(stderr,"extra argument: \"%s\"\n", z); - rc = 1; - goto meta_command_exit; - } - } - if( !chng ){ - if( p->mode.eMode==MODE_Column - || p->mode.eMode==MODE_Box - || p->mode.eMode==MODE_Table - || p->mode.eMode==MODE_Markdown - ){ - sqlite3_fprintf(p->out, "current output mode: %s", - modeDescr[p->mode.eMode]); - if( p->mode.spec.mxColWidth ){ - sqlite3_fprintf(p->out, " --wrap %d", - p->mode.spec.mxColWidth); - }else{ - sqlite3_fprintf(p->out, " --wrap off"); - } - sqlite3_fprintf(p->out, " --wordwrap %s --%squote --escape %s\n", - p->mode.spec.bWordWrap==QRF_Yes ? "on" : "off", - p->mode.spec.eText==QRF_TEXT_Sql ? "" : "no", - qrfEscNames[p->mode.spec.eEsc==QRF_ESC_Auto? - QRF_ESC_Ascii:p->mode.spec.eEsc] - ); - }else{ - sqlite3_fprintf(p->out, - "current output mode: %s --escape %s\n", - modeDescr[p->mode.eMode], - qrfEscNames[p->mode.spec.eEsc==QRF_ESC_Auto? - QRF_ESC_Ascii:p->mode.spec.eEsc] - ); - } - } - if( zMode==0 ){ - zMode = modeDescr[p->mode.eMode]; - } - n2 = strlen30(zMode); - if( cli_strncmp(zMode,"lines",n2)==0 ){ - p->mode.eMode = MODE_Line; - modeSetStr(&p->mode.spec.zRowSep, SEP_Row); - }else if( cli_strncmp(zMode,"columns",n2)==0 ){ - p->mode.eMode = MODE_Column; - modeSetStr(&p->mode.spec.zRowSep, SEP_Row); - }else if( cli_strncmp(zMode,"list",n2)==0 ){ - p->mode.eMode = MODE_List; - modeSetStr(&p->mode.spec.zColumnSep, SEP_Column); - modeSetStr(&p->mode.spec.zRowSep, SEP_Row); - }else if( cli_strncmp(zMode,"html",n2)==0 ){ - p->mode.eMode = MODE_Html; - }else if( cli_strncmp(zMode,"tcl",n2)==0 ){ - p->mode.eMode = MODE_Tcl; - modeSetStr(&p->mode.spec.zColumnSep, SEP_Space); - modeSetStr(&p->mode.spec.zRowSep, SEP_Row); - }else if( cli_strncmp(zMode,"csv",n2)==0 ){ - p->mode.eMode = MODE_Csv; - modeSetStr(&p->mode.spec.zColumnSep, SEP_Comma); - modeSetStr(&p->mode.spec.zRowSep, SEP_CrLf); - }else if( cli_strncmp(zMode,"tabs",n2)==0 ){ - p->mode.eMode = MODE_List; - modeSetStr(&p->mode.spec.zColumnSep, SEP_Tab); - }else if( cli_strncmp(zMode,"insert",n2)==0 ){ - p->mode.eMode = MODE_Insert; - modeSetStr(&p->mode.spec.zTableName, zTabname); - }else if( cli_strncmp(zMode,"quote",n2)==0 ){ - p->mode.eMode = MODE_Quote; - modeSetStr(&p->mode.spec.zColumnSep, SEP_Comma); - modeSetStr(&p->mode.spec.zRowSep, SEP_Row); - }else if( cli_strncmp(zMode,"ascii",n2)==0 ){ - p->mode.eMode = MODE_Ascii; - modeSetStr(&p->mode.spec.zColumnSep, SEP_Unit); - modeSetStr(&p->mode.spec.zRowSep, SEP_Record); - }else if( cli_strncmp(zMode,"markdown",n2)==0 ){ - p->mode.eMode = MODE_Markdown; - }else if( cli_strncmp(zMode,"table",n2)==0 ){ - p->mode.eMode = MODE_Table; - }else if( cli_strncmp(zMode,"box",n2)==0 ){ - p->mode.eMode = MODE_Box; - }else if( cli_strncmp(zMode,"count",n2)==0 ){ - p->mode.eMode = MODE_Count; - }else if( cli_strncmp(zMode,"off",n2)==0 ){ - p->mode.eMode = MODE_Off; - }else if( cli_strncmp(zMode,"json",n2)==0 ){ - p->mode.eMode = MODE_Json; - }else{ - eputz("Error: mode should be one of: " - "ascii box column csv html insert json line list markdown " - "qbox quote table tabs tcl\n"); - rc = 1; - } + rc = dotCmdMode(p); }else #ifndef SQLITE_SHELL_FIDDLE -- 2.47.3