]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the nTitleLimit option to QRF. Also change "line" style so that it
authordrh <>
Wed, 10 Dec 2025 15:24:46 +0000 (15:24 +0000)
committerdrh <>
Wed, 10 Dec 2025 15:24:46 +0000 (15:24 +0000)
uses zColumnSep as the divider between the title and the value.

FossilOrigin-Name: d67a299c86ff80ed67857d2546b0edaf852cb23dbfbc15e24793d1c4860a2e50

12 files changed:
ext/qrf/README.md
ext/qrf/qrf.c
ext/qrf/qrf.h
manifest
manifest.tags
manifest.uuid
src/shell.c.in
src/tclsqlite.c
test/modeA.clitest
test/qrf01.test
test/shell5.test
test/shellA.test

index 111d2b2d9672d07a82068b4d3afbca672eacfe5d..02672d67dc1c76f351a539e6aee099dacad4703d 100644 (file)
@@ -114,6 +114,7 @@ struct sqlite3_qrf_spec {
   short int nWrap;            /* Wrap columns wider than this */
   short int nScreenWidth;     /* Maximum overall table width */
   short int nLineLimit;       /* Maximum number of lines for any row */
+  short int nTitleLimit;      /* Maximum number of characters in a title */
   int nCharLimit;             /* Maximum number of characters in a cell */
   int nWidth;                 /* Number of entries in aWidth[] */
   int nAlign;                 /* Number of entries in aAlignment[] */
@@ -343,7 +344,7 @@ A value of QRF_BLOB_Size does not show any BLOB content at all.
 Instead, it substitutes a text string that says how many bytes
 the BLOB contains.
 
-### 2.8 Maximum size of displayed content (nLineLimit, nCharLimit)
+### 2.8 Maximum size of displayed content (nLineLimit, nCharLimit, nTitleLimit)
 
 If the sqlite3_qrf_spec.nCharLimit setting is non-zero, then the formatter
 will display only the first nCharLimit characters of each value.
@@ -366,6 +367,17 @@ 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.
 
+If the sqlite3_qrf_spec.nTitleLimit is non-zero, then the formatter
+attempts to limits the size of column titles to at most nTitleLimit
+display characters in width and a single line of text.  The nTitleLimit
+is useful for queries that have result columns that are scalar
+subqueries or complex expressions.  If those columns lack an AS
+clause, then the name of the column will be a copy of the expression
+that defines the column, which in some queries can be hundreds of
+characters and multiple lines in length, which can reduce the readability
+of tabular displays.  An nTitleLimit somewhere in the range of 10 to
+20 can improve readability.
+
 ### 2.9 Word Wrapping In Columnar Styles (nWrap, bWordWrap)
 
 When using columnar formatting modes (QRF_STYLE_Box, QRF_STYLE_Column,
index 4c542f8333ef422a92f3581219c708772b600b33..465054ad1e9c660fb7a96b9a04c56892f46d5c22 100644 (file)
@@ -56,7 +56,7 @@ struct Qrf {
   union {
     struct {                  /* Content for QRF_STYLE_Line */
       int mxColWth;             /* Maximum display width of any column */
-      const char **azCol;       /* Names of output columns (MODE_Line) */
+      char **azCol;             /* Names of output columns (MODE_Line) */
     } sLine;
     qrfEQPGraph *pGraph;      /* EQP graph (Eqp, Stats, and StatsEst) */
     struct {                  /* Content for QRF_STYLE_Explain */
@@ -945,6 +945,50 @@ static const char *qrfJsonbToJson(Qrf *p, int iCol){
   }
 }
 
+/*
+** Adjust the input string zIn[] such that it is no more than N display
+** characters wide.  If it is wider than that, then truncate and add
+** ellipsis.  Or if zIn[] contains a \r or \n, truncate at that point,
+** adding ellipsis.  Embedded tabs in zIn[] are converted into ordinary
+** spaces.
+**
+** Return this display width of the modified title string.
+*/
+static int qrfTitleLimit(char *zIn, int N){
+  unsigned char *z = (unsigned char*)zIn;
+  int n = 0;
+  unsigned char *zEllipse = 0;
+  while( z[0] ){
+    if( z[0]<' ' ){
+      int k;
+      if( z[0]=='\033' && (k = qrfIsVt100(z))>0 ){
+        z += k;
+      }else if( z[0]=='\t' ){
+        z[0] = ' ';
+      }else if( z[0]=='\n' || z[0]=='\r' ){
+        z[0] = ' ';
+      }else{
+        z++;
+      }
+    }else if( (0x80&z[0])==0 ){
+      if( n>=(N-3) && zEllipse==0 ) zEllipse = z;
+      if( n==N ){ z[0] = 0; break; }
+      n++;
+      z++;
+    }else{
+      int u = 0;
+      int len = sqlite3_qrf_decode_utf8(z, &u);
+      if( n+len>(N-3) && zEllipse==0 ) zEllipse = z;
+      if( n+len>N ){ z[0] = 0; break; }
+      z += len;
+      n += sqlite3_qrf_wcwidth(u);
+    }
+  }
+  if( zEllipse ) memcpy(zEllipse,"...",4);
+  return n;
+}
+
+
 /*
 ** Render value pVal into pOut
 */
@@ -1828,7 +1872,13 @@ static void qrfColumnar(Qrf *p){
       qrfEncodeText(p, pStr, z ? z : "");
       n = sqlite3_str_length(pStr);
       z = data.az[data.n] = sqlite3_str_finish(pStr);
-      data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
+      if( p->spec.nTitleLimit ){
+        nNL = 0;
+        data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n],
+                                               p->spec.nTitleLimit );
+      }else{
+        data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
+      }
       data.n++;
       if( w>data.a[i].mxW ) data.a[i].mxW = w;
       if( nNL ) data.bMultiRow = 1;
@@ -2454,6 +2504,7 @@ static void qrfOneSimpleRow(Qrf *p){
       sqlite3_str *pVal;
       int mxW;
       int bWW;
+      int nSep;
       if( p->u.sLine.azCol==0 ){
         p->u.sLine.azCol = sqlite3_malloc64( p->nCol*sizeof(char*) );
         if( p->u.sLine.azCol==0 ){
@@ -2463,21 +2514,26 @@ static void qrfOneSimpleRow(Qrf *p){
         p->u.sLine.mxColWth = 0;
         for(i=0; i<p->nCol; i++){
           int sz;
-          p->u.sLine.azCol[i] = sqlite3_column_name(p->pStmt, i);
-          if( p->u.sLine.azCol[i]==0 ) p->u.sLine.azCol[i] = "unknown";
+          const char *zCName = sqlite3_column_name(p->pStmt, i);
+          if( zCName==0 ) zCName = "unknown";
+          p->u.sLine.azCol[i] = sqlite3_mprintf("%s", zCName);
+          if( p->spec.nTitleLimit>0 ){
+            (void)qrfTitleLimit(p->u.sLine.azCol[i], p->spec.nTitleLimit);
+          }
           sz = (int)sqlite3_qrf_wcswidth(p->u.sLine.azCol[i]);
           if( sz > p->u.sLine.mxColWth ) p->u.sLine.mxColWth = sz;
         }
       }
       if( p->nRow ) sqlite3_str_append(p->pOut, "\n", 1);
       pVal = sqlite3_str_new(p->db);
-      mxW = p->mxWidth - (3 + p->u.sLine.mxColWth);
+      nSep = (int)strlen(p->spec.zColumnSep);
+      mxW = p->mxWidth - (nSep + p->u.sLine.mxColWth);
       bWW = p->spec.bWordWrap==QRF_Yes;
       for(i=0; i<p->nCol; i++){
         const char *zVal;
         int cnt = 0;
         qrfWidthPrint(p, p->pOut, -p->u.sLine.mxColWth, p->u.sLine.azCol[i]);
-        sqlite3_str_append(p->pOut, " = ", 3);
+        sqlite3_str_append(p->pOut, p->spec.zColumnSep, nSep);
         qrfRenderValue(p, pVal, i);
         zVal = sqlite3_str_value(pVal);
         if( zVal==0 ) zVal = "";
@@ -2608,6 +2664,12 @@ qrf_reinit:
       }
       break;
     }
+    case QRF_STYLE_Line: {
+      if( p->spec.zColumnSep==0 ){
+        p->spec.zColumnSep = ": ";
+      }
+      break;
+    }
     case QRF_STYLE_Csv: {
       p->spec.eStyle = QRF_STYLE_List;
       p->spec.eText = QRF_TEXT_Csv;
@@ -2716,7 +2778,11 @@ static void qrfFinalize(Qrf *p){
       break;
     }
     case QRF_STYLE_Line: {
-      if( p->u.sLine.azCol ) sqlite3_free(p->u.sLine.azCol);
+      if( p->u.sLine.azCol ){
+        int i;
+        for(i=0; i<p->nCol; i++) sqlite3_free(p->u.sLine.azCol[i]);
+        sqlite3_free(p->u.sLine.azCol);
+      }
       break;
     }
     case QRF_STYLE_Stats:
index 06ada9abee11902f8dc38655afc70b2c5419e9ab..c23ec772f05a7d021c9c709507c4dd1bddf2aabe 100644 (file)
@@ -41,6 +41,7 @@ struct sqlite3_qrf_spec {
   short int nWrap;            /* Wrap columns wider than this */
   short int nScreenWidth;     /* Maximum overall table width */
   short int nLineLimit;       /* Maximum number of lines for any row */
+  short int nTitleLimit;      /* Maximum number of characters in a title */
   int nCharLimit;             /* Maximum number of characters in a cell */
   int nWidth;                 /* Number of entries in aWidth[] */
   int nAlign;                 /* Number of entries in aAlignment[] */
index 9ffb108ad0dc50c6da5d56f1cc148a584137278b..d7936a1c352e75b43870c144371dbc2f1f5df644 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C In\sfts5,\savoid\sholding\san\sopen\sblob\shandle\safter\san\sINSERT/UPDATE/DELETE\sstatement,\sas\sthis\scan\sinterfere\swith\ssqlite3_interrupt().\sForum\spost\s[forum:/forumpost/95413eb410\s|\s95413eb410].
-D 2025-12-09T13:41:01.298
+C Add\sthe\snTitleLimit\soption\sto\sQRF.\s\sAlso\schange\s"line"\sstyle\sso\sthat\sit\nuses\szColumnSep\sas\sthe\sdivider\sbetween\sthe\stitle\sand\sthe\svalue.
+D 2025-12-10T15:24:46.290
 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 d792ed9b936ddfe9a210ecc893352afaee306c63b084187f6e44951f6f669e21
 F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
-F ext/qrf/README.md e726cff56c5c8a3aa493d15b6c052834cb6b5f1ca612867bc1cc6a11be8f019b
+F ext/qrf/README.md af1c7faf239625cf27a3a0e8c9d78af4e0da8e4d887223141182bc87bfbd22c8
 F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
-F ext/qrf/qrf.c 7fb2c4b600fcba4439a3ce8f7aed95f726f15548ce375b78cd983388a0ecebf7
-F ext/qrf/qrf.h 0f0387eb4c56eaa46405cd640132624933377e46df3d2baa940392f9a7d35768
+F ext/qrf/qrf.c 03191b452a83aa970f43f0e3bac25082e1f5b71da5cab2f547789fa5fb0fbf28
+F ext/qrf/qrf.h 2ac14b0aaacf44636d8c81051bfeab4afae50a98fbb2e10ff5aed0c28a87b2b2
 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 5eb15c585bd49b8cce88e762353a92b470b99a95e459bb434da41576a4f1b6eb
+F src/shell.c.in fe95f5121a2a05ce3b5f9582a3d96d77f6d148cb784c5c4f2f78f26a4ed9ab19
 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 1411438584e8e08c0959e6341acb0487039de662dab223ae0fef26d361211b6e
+F src/tclsqlite.c 85b5a20df96016e5d1d8fdc68c8a4c279c5b93e2049b77cd806c2cc50b9d8c56
 F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
 F src/test1.c 0e71fbcb484a271564e98e0158192c28c24f5521594218c3ba48bcb4cf634f91
 F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
@@ -1441,7 +1441,7 @@ F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
 F test/mmapcorrupt.test 470fb44fe92e99c1d23701d156f8c17865f5b027063c9119dcfdb842791f4465
 F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
 F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
-F test/modeA.clitest 96939c5fac8595213d84de82f3e09e4d126bafed19ec30167953627f4afa1723
+F test/modeA.clitest c06845925e37a4aeaadcc9f4878127cc8b5500e848c5bebdcd167a84ad8d55c9
 F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
 F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
 F test/multiplex3.test fac575e0b1b852025575a6a8357701d80933e98b5d2fe6d35ddaa68f92f6a1f7
@@ -1511,7 +1511,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 7ad8bb08eaaf9dee2a76a807741dfe4d6752614baa3c03afc734580bccc59afa
+F test/qrf01.test c464a5c72bcb11377d25ba955bfde47eae6332e1c00fcc97a6a1ca996d8fe11b
 F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92
 F test/qrf03.test e7efe46d204671726b4707585126cd78d107368de4a7d0c7b8d5157cdd8624ed
 F test/qrf04.test 0894692c998d2401dcc33449c02051b503ecce0c94217be54fb007c82d2d1379
@@ -1614,12 +1614,12 @@ F test/shell1.test 4e1b57c43b6246fb3e617903992b704ce3798c437b01cbf1e7a5e75060fdb
 F test/shell2.test 9d55aa53ca36c6889dedf5a23d849793afbd2dbe62d512ce066cb293a8a66a88
 F test/shell3.test 840192774cc4edf7653520c0434a311c7477b9bc324abbc7bd2887915792fa8c
 F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
-F test/shell5.test 7a249400bb2af59ac8524f357f8cf2844a62b6ac5ff8ecd69b045ceb688700ae
+F test/shell5.test 145a9474bab6d80b6ee452b83135507b25275d53b0936aab76520f007ac4d9dc
 F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
 F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
 F test/shell8.test 641cf21a99c59404c24e3062923734951c4099a6b6b6520de00cf7a1249ee871
 F test/shell9.test 8742a5b390cdcef6369f5aa223e415aa4255a4129ef249b177887dc635a87209
-F test/shellA.test 5fa0bdb7a19b0c1ba32649eab3eca0f7164bd9d33d391fff17586abcbc6c6e18
+F test/shellA.test 6319e4ede6658aa71b8d5265bf96071bcccdafe93853b56e670f64345a590029
 F test/shellB.test de879b1ea7c25daf1a06b2c882b45a5d002e6580c81c57169ce47084cc6afb6b
 F test/shmlock.test 9f1f729a7fe2c46c88b156af819ac9b72c0714ac6f7246638a73c5752b5fd13c
 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
@@ -2184,8 +2184,11 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 939275c6c574a3354e0626164aab1a005998f811c53a66b078249d6b2fcbd68e
-R 286d8b5aad9d68a56a5f96ea87c4c7dc
-U dan
-Z 7641cdfba34b6b7502af4bf575815d5f
+P f88e1d03573f394fc7caf60704c96152717b3fe8be4eef0caeb64737054f0fd2
+R ffbc5a3c90afd01d69ca06bdb0522a1b
+T *branch * title-limit
+T *sym-title-limit *
+T -sym-trunk *
+U drh
+Z 42a92002f07a36f7c65671dbf43f2ad5
 # Remove this line to create a well-formed Fossil manifest.
index bec971799ff1b8ee641c166c7aeb22d12c785393..2992329bb11dcfc48c83c09a6f2843610182abba 100644 (file)
@@ -1,2 +1,2 @@
-branch trunk
-tag trunk
+branch title-limit
+tag title-limit
index 939fec28a9512123430e687c9c3db461a552936b..84481c3f43a7995fae6541d36c934869d10cfe77 100644 (file)
@@ -1 +1 @@
-f88e1d03573f394fc7caf60704c96152717b3fe8be4eef0caeb64737054f0fd2
+d67a299c86ff80ed67857d2546b0edaf852cb23dbfbc15e24793d1c4860a2e50
index 1af8a3b9c640209acfa004c655cab418ccedfeb9..825c33e128812506ec7aa1c62130513594994410 100644 (file)
@@ -1448,8 +1448,8 @@ struct ModeInfo {
 static const char *aModeStr[] = 
   /* 0    1       2       3       4     5        6        7        8    */
    { 0,   "\n",   "|",    " ",    ",",  "\r\n",  "\036",  "\037",  "\t",
-     "",  "NULL", "null", "\"\""                                         };
-  /* 9    10      11      12                                            */
+     "",  "NULL", "null", "\"\"", ": ",                                   };
+  /* 9    10      11      12      13                                    */
 
 static const ModeInfo aModeInfo[] = {
 /*   zName      eCSep  eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */
@@ -1464,7 +1464,7 @@ static const ModeInfo aModeInfo[] = {
   { "jatom",    4,     1,    11,   6,    6,    0,   1,   12,    0,  0 },
   { "jobject",  0,     1,    11,   6,    6,    0,   0,   10,    0,  0 },
   { "json",     0,     0,    11,   6,    6,    0,   0,   9,     0,  0 },
-  { "line",     0,     1,    9,    1,    1,    0,   0,   11,    1,  0 },
+  { "line",     13,    1,    9,    1,    1,    0,   0,   11,    1,  0 },
   { "list",     2,     1,    9,    1,    1,    0,   1,   12,    0,  0 },
   { "markdown", 0,     0,    9,    1,    1,    0,   2,   13,    2,  0 },
   { "off",      0,     0,    0,    0,    0,    0,   0,   14,    0,  0 },
@@ -1629,6 +1629,7 @@ static void modeChange(ShellState *p, unsigned char eMode){
     p->mode.spec.nCharLimit = 300;
     p->mode.spec.nLineLimit = 5;
     p->mode.spec.bTextJsonb = QRF_Yes;
+    p->mode.spec.nTitleLimit = 20;
     p->mode.mFlags = mFlags;
   }
 }
@@ -7707,6 +7708,7 @@ static int modeTitleDsply(ShellState *p, int bAll){
 **   --title ARG              Whether or not to show column headers, and if so
 **                            how to encode them.  ARG can be "off", "on",
 **                            "sql", "csv", "html", "tcl", or "json".
+**   --titlelimit N           Limit the length of column titles to N characters.
 **   -v|--verbose             Verbose output
 **   --widths LIST            Set the columns widths for columnar modes. The
 **                            argument is a list of integers, one for each
@@ -7801,17 +7803,17 @@ static int dotCmdMode(ShellState *p){
         p->mode.spec.bBorder = k & 0x3;
       }
       chng = 1;
-    }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","")) ){
+    }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","-titlelimit","")) ){
       int w;                /*   0            1  */
       if( i+1>=nArg ){
         dotCmdError(p, i, "missing argument", 0);
         return 1;
       }
       w = integerValue(azArg[++i]);
-      if( k==0 ){
-        p->mode.spec.nCharLimit = w;
-      }else{
-        p->mode.spec.nLineLimit = w;
+      switch( k ){
+        case 0:   p->mode.spec.nCharLimit = w;   break;
+        case 1:   p->mode.spec.nLineLimit = w;   break;
+        default:  p->mode.spec.nTitleLimit = w;  break;
       }
       chng = 1;
     }else if( 0<=(k=pickStr(z,0,"-tablename","-rowsep","-colsep","-null","")) ){
@@ -8176,6 +8178,9 @@ static int dotCmdMode(ShellState *p){
       sqlite3_str_appendf(pDesc," --textjsonb %s",
              p->mode.spec.bTextJsonb==QRF_Yes ? "on" : "off");
     }
+    if( bAll || p->mode.spec.nTitleLimit>0 ){
+      sqlite3_str_appendf(pDesc, " --titlelimit %d", p->mode.spec.nTitleLimit);
+    }
     k = modeTitleDsply(p, bAll);
     if( k==1 ){
       sqlite3_str_appendall(pDesc, " --titles off");
index d6bc3926fa78cd0cfd453c063193f62b70193943..2c7918926643a817bdb2a757d2e4a539c9ff4091 100644 (file)
@@ -2070,6 +2070,7 @@ static void DbHookCmd(
 **     -screenwidth NUMBER                     Width of the display TTY
 **     -linelimit NUMBER                       Max lines for any cell
 **     -charlimit NUMBER                       Content truncated to this size
+**     -titlelimit NUMBER                      Max width of column titles
 **     -align LIST-OF-ALIGNMENT                Alignment of columns
 **     -widths LIST-OF-NUMBERS                 Widths for individual columns
 **     -columnsep TEXT                         Column separator text
@@ -2097,6 +2098,7 @@ static void DbHookCmd(
 **     -screenwidth      nScreenWidth
 **     -linelimit        nLineLimit
 **     -charlimit        nCharLimit
+**     -titlelimit       nTitleLimit
 **     -align            nAlign, aAlign
 **     -widths           nWidth, aWidth
 **     -columnsep        zColumnSep
@@ -2272,6 +2274,7 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
     }else if( strcmp(zArg,"-wrap")==0
            || strcmp(zArg,"-screenwidth")==0 
            || strcmp(zArg,"-linelimit")==0 
+           || strcmp(zArg,"-titlelimit")==0 
     ){
       int v = 0;
       rc = Tcl_GetIntFromObj(pDb->interp, objv[i+1], &v);
@@ -2285,6 +2288,8 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
         qrf.nWrap = v;
       }else if( zArg[1]=='s' ){
         qrf.nScreenWidth = v;
+      }else if( zArg[1]=='t' ){
+        qrf.nTitleLimit = v;
       }else{
         qrf.nLineLimit = v;
       }
index ec5fab6774cd36618b658de6239fb8c307920542..e4dbbe953c859bd09acece226f74138986655ac3 100644 (file)
@@ -79,12 +79,12 @@ END
 .output memory
 .mode
 .output --verify END
-current output mode: qbox --limits 5,300 --quote relaxed --screenwidth auto --textjsonb on
+current output mode: qbox --limits 5,300 --quote relaxed --screenwidth auto --textjsonb on --titlelimit 20
 END
 .output memory
 .mode -v
 .output --verify END
-current output mode: qbox --align "" --border on --blob-quote auto --colsep "" --escape auto --limits 5,300 --null "NULL" --quote relaxed --rowsep "" --screenwidth auto --tablename "" --textjsonb on --titles on --widths "" --wordwrap off --wrap 10
+current output mode: qbox --align "" --border on --blob-quote auto --colsep "" --escape auto --limits 5,300 --null "NULL" --quote relaxed --rowsep "" --screenwidth auto --tablename "" --textjsonb on --titlelimit 20 --titles on --widths "" --wordwrap off --wrap 10
 END
 
 .output memory --error-prefix "Error:"
index 89624002afb028c1e93e457dd3d62215437a4177..8cf080b645b9b5ad7b40ca13f7a2f8f8646d2c52 100644 (file)
@@ -289,27 +289,27 @@ do_test 1.92 {
 do_test 1.100 {
   set result "\n[db format -style line {SELECT * FROM t1}]"
 } {
-a = 1
-b = 2.5
-c = three
+a: 1
+b: 2.5
+c: three
 
-a = BLOB
-b = 
-c = Ἀμήν
+a: BLOB
+b: 
+c: Ἀμήν
 }
 do_test 1.101 {
   set result "\n[db format -style line -null (NULL) {SELECT * FROM t1}]"
 } {
-a = 1
-b = 2.5
-c = three
+a: 1
+b: 2.5
+c: three
 
-a = BLOB
-b = (NULL)
-c = Ἀμήν
+a: BLOB
+b: (NULL)
+c: Ἀμήν
 }
 do_test 1.102 {
-  set result "\n[db format -style line -null (NULL) \
+  set result "\n[db format -style line -null (NULL) -columnsep { = } \
                  -text sql {SELECT * FROM t1}]"
 } {
 a = 1
@@ -624,7 +624,8 @@ do_test 5.1 {
   set sql {SELECT name, mtime, datetime(mtime,'unixepoch') AS time,
                         value FROM t1 ORDER BY mtime}
   set result "\n[db format -style line -screenwidth 60 -blob sql \
-                   -text sql -wordwrap off -linelimit 77 $sql]"
+                   -text sql -wordwrap off -linelimit 77 \
+                   -columnsep { = } $sql]"
 } {
  name = 'sample-jsonb'
 mtime = 1333101221
@@ -660,7 +661,7 @@ do_test 5.2 {
   set sql {SELECT name, mtime, datetime(mtime,'unixepoch') AS time,
                         value FROM t1 ORDER BY mtime}
   set result "\n[db format -style line -screenwidth 60 -blob sql \
-                   -text plain -esc off -textjsonb yes \
+                   -text plain -esc off -textjsonb yes -columnsep { = }\
                    -wordwrap yes -linelimit 3 $sql]"
 } {
  name = sample-jsonb
index 2c8181579b73573bf8640df87c2cbd6387773457..bb8d36732c952f9a772ffcccd8b3e214a37cef0a 100644 (file)
@@ -521,7 +521,7 @@ do_test shell5-5.1 {
   close $out
   forcedelete test.db
   catchcmd test.db {.import -csv shell5.csv t1
-.mode line
+.mode line --colsep ' = '
 SELECT * FROM t1;}
 } {1 {    ? = 0
  x_02 = x2
@@ -537,7 +537,7 @@ Columns renamed during .import shell5.csv due to duplicates:
 "z" to "z_05",
 "z" to "z_08"}}
 
-do_test shell5-5.1 {
+do_test shell5-5.1b {
   set out [open shell5.csv w]
   fconfigure $out -translation lf
   puts $out {"COW","cow","CoW","cOw"}
@@ -547,10 +547,10 @@ do_test shell5-5.1 {
   catchcmd test.db {.import -csv shell5.csv t1
 .mode line
 SELECT * FROM t1;}
-} {1 {COW_1 = uuu
-cow_2 = lll
-CoW_3 = ulu
-cOw_4 = lul
+} {1 {COW_1: uuu
+cow_2: lll
+CoW_3: ulu
+cOw_4: lul
 Columns renamed during .import shell5.csv due to duplicates:
 "COW" to "COW_1",
 "cow" to "cow_2",
@@ -569,7 +569,7 @@ do_test_with_ansi_output shell5-6.1 {
   close $out
   forcedelete test.db
   catchcmd test.db {.import -csv shell5.csv t1
-.mode line
+.mode line --colsep " = "
 SELECT * FROM t1;}
 } {0 {   あい = 1
 うえお = 2}}
@@ -584,8 +584,8 @@ do_test_with_ansi_output shell5-6.2 {
   catchcmd test.db {.import -csv shell5.csv t1
 .mode line
 SELECT * FROM t1;}
-} {0 {1 = あい
-2 = うえお}}
+} {0 {1: あい
+2: うえお}}
 
 # 2024-03-11 https://sqlite.org/forum/forumpost/ca014d7358
 # Import into a table that contains computed columns.
index 6a0ea26fe26932018733fc0adddc6248a69c6115..e6b7bcd33f53d19887cac2830bb4637800880a8f 100644 (file)
@@ -139,41 +139,41 @@ do_test_with_ansi_output shellA-3.1 {
  exec {*}$CLI -noinit test.db --line --escape symbol \
     {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
 } {
-    a = 1
-    x = line with ' single quote
+    a: 1
+    x: line with ' single quote
 
-    a = 2
-    x = ␛[31mVT-100 codes␛[0m
+    a: 2
+    x: ␛[31mVT-100 codes␛[0m
 
-    a = 6
-    x = new
-line
+    a: 6
+    x: new
+       line
 
-    a = 7
-    x = carriage␍return
+    a: 7
+    x: carriage␍return
 
-    a = 8
-    x = last line
+    a: 8
+    x: last line
 }
 do_test shellA-3.2 {
  exec {*}$CLI -noinit test.db --line --escape ascii \
     {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
 } {
-    a = 1
-    x = line with ' single quote
+    a: 1
+    x: line with ' single quote
 
-    a = 2
-    x = ^[[31mVT-100 codes^[[0m
+    a: 2
+    x: ^[[31mVT-100 codes^[[0m
 
-    a = 6
-    x = new
-line
+    a: 6
+    x: new
+       line
 
-    a = 7
-    x = carriage^Mreturn
+    a: 7
+    x: carriage^Mreturn
 
-    a = 8
-    x = last line
+    a: 8
+    x: last line
 }
 
 # ".mode box"