From: drh <> Date: Fri, 14 Nov 2025 21:40:20 +0000 (+0000) Subject: Enforce the --charlimit constraint in QRF. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c2b9896e5010326acda314d9e131f35b5794de91;p=thirdparty%2Fsqlite.git Enforce the --charlimit constraint in QRF. FossilOrigin-Name: c25f8fdedd8d68e3551a445e24e1c60e105e18f9cf8f1badcbb77a58974f3381 --- diff --git a/ext/qrf/README.md b/ext/qrf/README.md index 76abe1a8bc..b3acf5863c 100644 --- a/ext/qrf/README.md +++ b/ext/qrf/README.md @@ -298,15 +298,11 @@ If the sqlite3_qrf_spec.nCharLimit setting is non-zero, then the formatter will display only the first nCharLimit characters of each value. Only characters that take up space are counted when enforcing this limit. Zero-width characters and VT100 escape sequences do not count -toward this limit. The count is in characters, not bytes. - -Content length limits only apply to TEXT and BLOB values. Numeric -values and NULLs always display their full text regardless of the -nCharLimit setting. - -*This setting is a place-holder. -As for 2025-11-07, the nCharLimit constraint is not yet implemented. -The current behavior is always as if nCharLimit where zero.* +toward this limit. The count is in characters, not bytes. When +imposing this limit, the formatter adds the three characters "..." +to the end of the value. Those added characters are not counted +as part of the limit. Very small limits still result in truncation, +but might render a few more characters than the limit. If the sqlite3_qrf_spec.nLineLimit setting is non-zero, then the formatter will only display the first nLineLimit lines of each value. @@ -315,7 +311,7 @@ character, or if it split by wrapping. This setting merely limits the number of displayed lines. This setting only works for **Box**, **Column**, **Line**, **Markdown**, and **Table** styles. -The idea behind these settings is to prevent excessively large renderings +The idea behind both of these settings is to prevent large renderings when doing a query that (unexpectedly) contains very large text or blob values: perhaps megabyes of text. diff --git a/ext/qrf/qrf.c b/ext/qrf/qrf.c index c471fabf16..8eb1f2d1cf 100644 --- a/ext/qrf/qrf.c +++ b/ext/qrf/qrf.c @@ -859,6 +859,9 @@ static const char *qrfJsonbToJson(Qrf *p, int iCol){ ** Render value pVal into pOut */ static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){ +#if SQLITE_VERSION_NUMBER>=3052000 + int iStartLen = sqlite3_str_length(pOut); +#endif if( p->spec.xRender ){ sqlite3_value *pVal; char *z; @@ -969,6 +972,42 @@ static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){ break; } } +#if SQLITE_VERSION_NUMBER>=3052000 + if( p->spec.nCharLimit>0 + && (sqlite3_str_length(pOut) - iStartLen) > p->spec.nCharLimit + ){ + const unsigned char *z; + int ii = 0, w = 0, limit = p->spec.nCharLimit; + z = (const unsigned char*)sqlite3_str_value(pOut) + iStartLen; + if( limit<4 ) limit = 4; + while( 1 ){ + if( z[ii]<' ' ){ + int k; + if( z[ii]=='\033' && (k = qrfIsVt100(z+ii))>0 ){ + ii += k; + }else if( z[ii]==0 ){ + break; + }else{ + ii++; + } + }else if( (0x80&z[ii])==0 ){ + w++; + if( w>limit ) break; + ii++; + }else{ + int u = 0; + int len = sqlite3_qrf_decode_utf8(&z[ii], &u); + w += sqlite3_qrf_wcwidth(u); + if( w>limit ) break; + ii += len; + } + } + if( w>limit ){ + sqlite3_str_truncate(pOut, iStartLen+ii); + sqlite3_str_append(pOut, "...", 3); + } + } +#endif } /* diff --git a/manifest b/manifest index a51469a578..d9a60c985b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sqrf\sbranch. -D 2025-11-14T20:11:15.522 +C Enforce\sthe\s--charlimit\sconstraint\sin\sQRF. +D 2025-11-14T21:40:20.521 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -416,8 +416,8 @@ 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 db3710552dfdacfc600e4c9772f84dccdf84ceb9983837a86269d4f6cb67219a -F ext/qrf/qrf.c a8cb5b2ecc9fc57ed79668002fbb5c54c6af03de7e20fc15aca5c85978f6b070 +F ext/qrf/README.md 09dd538966d8ee32598fc010e7fe6755bd7190494953a02960a9c81197d20cf3 +F ext/qrf/qrf.c 0351a18ee34603f70a0a166c7ee2c17dd0306ca7b3ace1f797885f5464df8c8c F ext/qrf/qrf.h b4b3489b3b3683523fd248d15cf5945830643b036943efacdb772a3e00367aa2 F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8 F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255 @@ -1507,7 +1507,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 3e863267cf237516a5803d94e19046005cf148623ea24c8646acbd304a598c78 +F test/qrf01.test de83f4be443e17b4e3b9338ab6a574e259702ccdb6526f9375a977e21cfec307 F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92 F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 @@ -2175,8 +2175,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 229650a01dcd9cc4b39526d661106e9c3eb2f90ca7fbed8adc6e6fe85ef3fdaa fa85534ed927851dc37a4943e83259bff4509f141449226ffb506f9acc7b2cc5 -R 345c49aeb99e16774f28cf8e0c1a004d +P 9ee892b4f97c91208a658f09add00a567406e913edb022a2fd53333ea01c2b26 +R c9bf369ad8043e13ab5084e935fe2413 U drh -Z ce60499ced798382b41544ef3cdae0bc +Z c41407f8027f6af7e7c850d0c7018e85 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 53869e2565..093be235bf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9ee892b4f97c91208a658f09add00a567406e913edb022a2fd53333ea01c2b26 +c25f8fdedd8d68e3551a445e24e1c60e105e18f9cf8f1badcbb77a58974f3381 diff --git a/test/qrf01.test b/test/qrf01.test index f13c5d1e3c..99e3795d01 100644 --- a/test/qrf01.test +++ b/test/qrf01.test @@ -747,4 +747,34 @@ do_test 6.3 { set res } {bad -textnull "xyz": must be auto, yes, no, on, or off} +do_execsql_test 7.0 { + CREATE TABLE t7(a,b); + INSERT INTO t7 VALUES('abcdefghijklmnop', + 'abcぁdefかghiのjklはmnop'); +} +do_test 7.1 { + set result "\n[db format -style list -charlimit 13 \ + {SELECT * FROM t7}]" +} { +abcdefghijklm...|abcぁdefかghi... +} +do_test 7.2 { + set result "\n[db format -style list -charlimit 14 \ + {SELECT * FROM t7}]" +} { +abcdefghijklmn...|abcぁdefかghi... +} +do_test 7.3 { + set result "\n[db format -style list -charlimit 15 \ + {SELECT * FROM t7}]" +} { +abcdefghijklmno...|abcぁdefかghiの... +} +do_test 7.4 { + set result "\n[db format -style list -charlimit 16 \ + {SELECT * FROM t7}]" +} { +abcdefghijklmnop|abcぁdefかghiのj... +} + finish_test