From: drh <> Date: Sat, 6 Dec 2025 10:07:15 +0000 (+0000) Subject: New text rendering style of QRF_TEXT_Relaxed. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cff66960fd0fc3db9a083e189bb490be3ba78ad2;p=thirdparty%2Fsqlite.git New text rendering style of QRF_TEXT_Relaxed. FossilOrigin-Name: d2049bffe6674b8840663b0e5f404a040b715640c87f022517cf11546548fda3 --- diff --git a/ext/qrf/README.md b/ext/qrf/README.md index 397c082076..067eeeed5a 100644 --- a/ext/qrf/README.md +++ b/ext/qrf/README.md @@ -254,6 +254,7 @@ Both fields can have one of the following values: #define QRF_TEXT_Html 4 /* HTML-style quoting */ #define QRF_TEXT_Tcl 5 /* C/Tcl quoting */ #define QRF_TEXT_Json 6 /* JSON quoting */ +#define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */ ~~~ A value of QRF_TEXT_Auto means that the query result formatter will choose @@ -267,6 +268,14 @@ look like SQL literals. That means the value will be surrounded by single-quotes (U+0027) and any single-quotes contained within the text will be doubled. +QRF_TEXT_Relaxed is similar to QRF_TEXT_Sql, except that automatically +reverts to QRF_TEXT_Plain if the value to be displayed does not contain +special characters and is not easily confused with a NULL or a numeric +value. QRF_TEXT_Relaxed strives to minimize the amount of quoting syntax +while keeping the result unambiguous and easy for humans to read. The +precise rules for when quoting is omitted in QRF_TEXT_Relaxed, and when +it is applied, might be adjusted in future releases. + A value of QRF_TEXT_Csv means that text values are escaped in accordance with RFC 4180, which defines Comma-Separated-Value or CSV files. Text strings that contain no special values appears as-is. Text strings diff --git a/ext/qrf/qrf.c b/ext/qrf/qrf.c index ddcc2dbf49..8c92e68676 100644 --- a/ext/qrf/qrf.c +++ b/ext/qrf/qrf.c @@ -17,6 +17,7 @@ #endif #include #include +#include typedef sqlite3_int64 i64; @@ -703,6 +704,45 @@ static void qrfEscape( } } +/* +** Determine if the string z[] can be shown as plain text. Return true +** if z[] is unambiguously text. Return false if z[] needs to be +** quoted. +** +** All of the following must be true in order for z[] to be relaxable: +** +** (1) z[] does not begin or end with ' or whitespace +** (2) z[] is not the same as the NULL rendering +** (3) z[] does not looks like a numeric literal +*/ +static int qrfRelaxable(Qrf *p, const char *z){ + size_t i, n; + if( z[0]=='\'' || isspace(z[0]) ) return 0; + if( z[0]==0 && (p->spec.zNull==0 || p->spec.zNull[0]==0) ) return 0; + n = strlen(z); + if( z[n-1]=='\'' || isspace(z[n-1]) ) return 0; + if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0; + i = (z[0]=='-' || z[0]=='+'); + if( strcmp(z+i,"Inf")==0 ) return 0; + if( !isdigit(z[i]) ) return 1; + i++; + while( isdigit(z[i]) ){ i++; } + if( z[i]==0 ) return 0; + if( z[i]=='.' ){ + i++; + while( isdigit(z[i]) ){ i++; } + if( z[i]==0 ) return 0; + } + if( z[i]=='e' || z[i]=='E' ){ + i++; + if( z[i]=='+' || z[i]=='-' ){ i++; } + if( !isdigit(z[i]) ) return 1; + i++; + while( isdigit(z[i]) ){ i++; } + } + return z[i]!=0; +} + /* ** If a field contains any character identified by a 1 in the following ** array, then the string must be quoted for CSV. @@ -732,6 +772,13 @@ static const char qrfCsvQuote[] = { static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){ int iStart = sqlite3_str_length(pOut); switch( p->spec.eText ){ + case QRF_TEXT_Relaxed: { + if( qrfRelaxable(p, zTxt) ){ + sqlite3_str_appendall(pOut, zTxt); + break; + } + /* Fall through into the SQL case */ + } case QRF_TEXT_Sql: { if( p->spec.eEsc==QRF_ESC_Off ){ sqlite3_str_appendf(pOut, "%Q", zTxt); @@ -2517,8 +2564,8 @@ static void qrfInitialize( if( p->mxHeight<=0 ) p->mxHeight = 2147483647; if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto; if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto; - if( p->spec.eText>QRF_TEXT_Json ) p->spec.eText = QRF_Auto; - if( p->spec.eTitle>QRF_TEXT_Json ) p->spec.eTitle = QRF_Auto; + if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto; + if( p->spec.eTitle>QRF_TEXT_Relaxed ) p->spec.eTitle = QRF_Auto; if( p->spec.eBlob>QRF_BLOB_Size ) p->spec.eBlob = QRF_Auto; qrf_reinit: switch( p->spec.eStyle ){ diff --git a/ext/qrf/qrf.h b/ext/qrf/qrf.h index 5e28d1e9cd..06ada9abee 100644 --- a/ext/qrf/qrf.h +++ b/ext/qrf/qrf.h @@ -109,6 +109,7 @@ int sqlite3_format_query_result( #define QRF_TEXT_Html 4 /* HTML-style quoting */ #define QRF_TEXT_Tcl 5 /* C/Tcl quoting */ #define QRF_TEXT_Json 6 /* JSON quoting */ +#define QRF_TEXT_Relaxed 7 /* Relaxed SQL quoting */ /* ** Quoting styles for BLOBs diff --git a/manifest b/manifest index 1e2ead5d26..db580e61d9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sdrawing\sboxes\susing\sQRF,\suse\srounded\scorners\sand\suse\sa\sdouble-line\sto\nseparate\scolumn\sheaders\sfrom\sthe\scontent. -D 2025-12-05T22:04:49.269 +C New\stext\srendering\sstyle\sof\sQRF_TEXT_Relaxed. +D 2025-12-06T10:07:15.670 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -416,10 +416,10 @@ F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f6 F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c F ext/misc/zipfile.c 9981cda2f5d08ff01f33c2e4cea82df75f83a4c0fdcbc5dce67e0f775b770fb1 F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee -F ext/qrf/README.md 86fc5c3c5e3eddbe54fc1235cbdc52b8c2c0732791d224345c3014cd45c4c0e7 +F ext/qrf/README.md fc76ed07e60060ae2832d732193dfe4e5218c685604a905a2dee950eb5269ca3 F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430 -F ext/qrf/qrf.c 639179fcbf6768fa61e5d931121c3f8bdc7cb62e92b9b239b3c6583c4d6ff49e -F ext/qrf/qrf.h 2cd7bd43579c522d3ae5c16034c7fdf41085684189811ae8e18ebc932a1cc79f +F ext/qrf/qrf.c 3bf0286cb6ac9afb022a93b7ab2266c2692fa35070573273e796975be5878425 +F ext/qrf/qrf.h 0f0387eb4c56eaa46405cd640132624933377e46df3d2baa940392f9a7d35768 F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8 F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255 F ext/rbu/rbu10.test 7c22caa32c2ff26983ca8320779a31495a6555737684af7aba3daaf762ef3363 @@ -737,7 +737,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c 8d53771eb51a4ab5f970150c3a70969d8db79cd04a8774c2d296bbcf471a0dd0 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c 344518c1bba9c4636bf651b7642304abd2e7075ba35feb4bae42a51e5efe991f -F src/shell.c.in a4a05fcc14c5e84867b3a2bb04cc1d53cb924b810ad72976157861a5d5f1a76b +F src/shell.c.in 09585992a8752390fab97ade0a6136468180ad991fe152b1c140e2aa7283e82f F src/sqlite.h.in 706cacea5308b0244fb6cec92e08310fb427a125375c64137cc1f878ae4cf5c0 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 5d5330f5f8461f5ce74960436ddcfa53ecd09c2b8b23901e22ae38aec3243998 @@ -745,7 +745,7 @@ F src/sqliteInt.h af67bc95fa6b66cd3c7f3d18d2d040ad386e4cbb02965ee318cc721ee9d5fa F src/sqliteLimit.h 7e705474d59912388832cc5465edbc0dbb552872e23452812846e90d280987f3 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 -F src/tclsqlite.c 4b6f6b142b951a8a127e0cbd2e37284fc71f8e6a391ec8c6188fb831b51ec0b8 +F src/tclsqlite.c cf5d43c1549e32804bf8ac1eb2478a695caaee688a7b29e8db1be33206b600b4 F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a F src/test1.c 0e71fbcb484a271564e98e0158192c28c24f5521594218c3ba48bcb4cf634f91 F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff @@ -2184,11 +2184,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 f82376f080ca5cb316b8eb2e48a128b1838eb376b9e903c7af611b398cfe9b1f -R 875f89180e49565d507ad67ac515a40e -T *branch * qrf-box-enhancements -T *sym-qrf-box-enhancements * -T -sym-trunk * +P 8c1ca30707c36f074dad29556df4176a74aa573491bb4aad973789aee5ad80da +R 81b5ef778830cc60943eae42e77827ea U drh -Z ede9962b23f4bc5bbbb7a1e52559a3c0 +Z 8f661d440d11fe3a4df6fb112e8f304a # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a184b46750..f9028c0eed 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8c1ca30707c36f074dad29556df4176a74aa573491bb4aad973789aee5ad80da +d2049bffe6674b8840663b0e5f404a040b715640c87f022517cf11546548fda3 diff --git a/src/shell.c.in b/src/shell.c.in index 27ed68bd9b..824e7bcb27 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1386,7 +1386,7 @@ static ShellState shellState; */ static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" }; static const char *qrfQuoteNames[] = - { "off","off","sql","hex","csv","tcl","json"}; + { "off","off","sql","hex","csv","tcl","json","relaxed"}; /* ** These are the allowed shellFlgs values @@ -7916,9 +7916,10 @@ static int dotCmdMode(ShellState *p){ if( (k = pickStr(azArg[i],0,"no","yes","0","1",""))>=0 ){ k &= 1; /* 0 for "off". 1 for "on". */ }else{ - char *zErr = 0; /* 0 1 2 3 4 5 6 */ - k = pickStr(azArg[i],&zErr,"off","on","sql","csv","html","tcl","json", - ""); + char *zErr = 0; + k = pickStr(azArg[i],&zErr, + "off","on","sql","csv","html","tcl","json","relaxed",""); + /* 0 1 2 3 4 5 6 7 */ if( k<0 ){ dotCmdError(p, i, "unknown", "%z", zErr); return 1; @@ -7947,6 +7948,9 @@ static int dotCmdMode(ShellState *p){ case 6: /* json */ p->mode.spec.eText = QRF_TEXT_Json; break; + case 7: /* relaxed */ + p->mode.spec.eText = QRF_TEXT_Relaxed; + break; default: /* off */ p->mode.spec.eText = QRF_TEXT_Plain; break; diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 147a64745b..3d20c3153a 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2194,12 +2194,12 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){ static const char *azText[] = { "off", "on", "auto", "csv", "html", "json", "plain", "sql", - "tcl", 0 + "tcl", "relaxed", 0 }; static unsigned char aTextMap[] = { QRF_TEXT_Auto, QRF_TEXT_Csv, QRF_TEXT_Html, QRF_TEXT_Json, QRF_TEXT_Plain, QRF_TEXT_Sql, - QRF_TEXT_Tcl + QRF_TEXT_Tcl, QRF_TEXT_Relaxed }; int txt; int k = zArg[2]=='e';