]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the --blob-quote option to the ".mode" command in the CLI.
authordrh <>
Mon, 24 Nov 2025 18:31:13 +0000 (18:31 +0000)
committerdrh <>
Mon, 24 Nov 2025 18:31:13 +0000 (18:31 +0000)
FossilOrigin-Name: 76a986b10d284b25915a07b7150ef1b85f4ef7d48d4e5315b13e7d1532cb97f1

ext/qrf/qrf.c
manifest
manifest.uuid
src/shell.c.in
test/qrf01.test

index 7b314f1f2afcdd23394eefd9e2b1471850a19c67..278420829ab86482f908cda687b57e51e18c0d46 100644 (file)
@@ -2441,7 +2441,6 @@ qrf_reinit:
     case QRF_STYLE_JObject:
     case QRF_STYLE_Json: {
       p->spec.eText = QRF_TEXT_Json;
-      p->spec.eBlob = QRF_BLOB_Json;
       p->spec.zNull = "null";
       break;
     }
@@ -2452,7 +2451,6 @@ qrf_reinit:
     }
     case QRF_STYLE_Insert: {
       p->spec.eText = QRF_TEXT_Sql;
-      p->spec.eBlob = QRF_BLOB_Sql;
       p->spec.zNull = "NULL";
       if( p->spec.zTableName==0 || p->spec.zTableName[0]==0 ){
         p->spec.zTableName = "tab";
@@ -2462,7 +2460,6 @@ qrf_reinit:
     case QRF_STYLE_Csv: {
       p->spec.eStyle = QRF_STYLE_List;
       p->spec.eText = QRF_TEXT_Csv;
-      p->spec.eBlob = QRF_BLOB_Text;
       p->spec.zColumnSep = ",";
       p->spec.zRowSep = "\r\n";
       p->spec.zNull = "";
@@ -2470,7 +2467,6 @@ qrf_reinit:
     }
     case QRF_STYLE_Quote: {
       p->spec.eText = QRF_TEXT_Sql;
-      p->spec.eBlob = QRF_BLOB_Sql;
       p->spec.zNull = "NULL";
       p->spec.zColumnSep = ",";
       p->spec.zRowSep = "\n";
index 4970651664702d671b1e224b4a96a0d72dfb5121..3ab974ff38dcb776b088012b54fe3ab005afbb2c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Change\ssome\s32-bit\sintegers\sin\sfts3_write.c\sto\s64-bit\sto\sreduce\sthe\schances\sof\sinteger\soverflow.
-D 2025-11-24T17:44:17.066
+C Add\sthe\s--blob-quote\soption\sto\sthe\s".mode"\scommand\sin\sthe\sCLI.
+D 2025-11-24T18:31:13.324
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -417,7 +417,7 @@ F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6
 F ext/misc/zipfile.c 09e6e3a3ff40a99677de3c0bc6569bd5f4709b1844ac3d1c1452a456c5a62f1c
 F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
 F ext/qrf/README.md dd565fd1ca0c46ea37dbf4d496e368b9ecade768c92669640bc106e039629016
-F ext/qrf/qrf.c 9e3eaf868d4cfbabfb1b26b54537ee46f8345a5cef4bbc7b2920563bba5907df
+F ext/qrf/qrf.c af7c0f07ec880077f2cb8cbb32012523080be10c22a9a03fbd434b21bf46f650
 F ext/qrf/qrf.h a758fd35e488ef93c7fe145aa96c228c985d3c4691eb89da6328ef3ebe1fedce
 F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
 F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
@@ -735,7 +735,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 5616fbcf3b833c7c705b24371828215ad0925d0c0073216c4f153348d5753f0a
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c 6a509cddd815d64f6141e539fff633a518a393772a44dffb4490f7fc3f0d83a9
-F src/shell.c.in 6de2bcea19da8782879da7f763d94564f30424786628e094b903b0bb534e9e0a
+F src/shell.c.in 575c08b667378e442e8e63579bcaa1c9ae19e37c080b8096ee04e996e93cb9d6
 F src/sqlite.h.in f1363321ca55cc2feaa289e9fe6dfb08102a28c54edf005564711a2348b06eef
 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
 F src/sqlite3ext.h 5d5330f5f8461f5ce74960436ddcfa53ecd09c2b8b23901e22ae38aec3243998
@@ -1509,7 +1509,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 e92c24195b129606210f5ff3b21e6a1468999c885d3b7f4f62bdf284221969e4
+F test/qrf01.test 6aae6741fc307bae4dd647eaccf2186eb32704a2e5db36eb8e9042e9a1b2a7b8
 F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92
 F test/qrf03.test 9de53aea459f5a127283db03cbb6011500757685646d21aa3c29c44c6ef23e86
 F test/qrf04.test 0894692c998d2401dcc33449c02051b503ecce0c94217be54fb007c82d2d1379
@@ -2179,8 +2179,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 bafff695d34202377b937cb4ca9f8a7611ae286d9ab927e6c71faa3cd99496e5
-R cfc1251bc868a6200eefed64db533f1c
-U dan
-Z 6252b8ce71cf1f222eab37a79e8ca011
+P 8f8a7224c1e0173764757d5022de60abec3babdc3d4131632805e0b04d1a65bf
+R 41c492e567cc3e3b2bc92a56b0c8251a
+U drh
+Z 879f2fe1a0da2d52e74ae988e2731bed
 # Remove this line to create a well-formed Fossil manifest.
index 06358b804244da27d2af22c43cd1ad7d1f25e168..af348c50a6445d7887b758981d8e7b00259fac3b 100644 (file)
@@ -1 +1 @@
-8f8a7224c1e0173764757d5022de60abec3babdc3d4131632805e0b04d1a65bf
+76a986b10d284b25915a07b7150ef1b85f4ef7d48d4e5315b13e7d1532cb97f1
index 07357df95c6639277fbd7acd05e307a719282cfd..b657531c3542d617438eee1707c9b85437af00f1 100644 (file)
@@ -1468,28 +1468,28 @@ static const char *aModeStr[] =
 
 static const ModeInfo aModeInfo[] = {
 /*   zName      eCSep  eRSep eNull eText eHdr eBlob bHdr eStyle eCx */
-  { "ascii",    7,     6,    9,    1,    1,    1,   1,   12,    0 },
-  { "box",      0,     0,    9,    1,    1,    1,   2,   1,     2 },
+  { "ascii",    7,     6,    9,    1,    1,    0,   1,   12,    0 },
+  { "box",      0,     0,    9,    1,    1,    0,   2,   1,     2 },
   { "c",        4,     1,    10,   5,    5,    4,   1,   12,    0 },
-  { "column",   0,     0,    9,    1,    1,    1,   2,   2,     2 },
+  { "column",   0,     0,    9,    1,    1,    0,   2,   2,     2 },
   { "count",    0,     0,    0,    0,    0,    0,   0,   3,     0 },
-  { "csv",      4,     5,    9,    3,    3,    3,   1,   12,    0 },
-  { "html",     0,     0,    9,    4,    4,    1,   2,   7,     0 },
-  { "insert",   0,     0,    10,   2,    2,    2,   1,   8,     0 },
-  { "jatom",    4,     1,    11,   6,    6,    5,   1,   12,    0 },
-  { "jobject",  0,     1,    11,   6,    6,    5,   0,   10,    0 },
+  { "csv",      4,     5,    9,    3,    3,    0,   1,   12,    0 },
+  { "html",     0,     0,    9,    4,    4,    0,   2,   7,     0 },
+  { "insert",   0,     0,    10,   2,    2,    0,   1,   8,     0 },
+  { "jatom",    4,     1,    11,   6,    6,    0,   1,   12,    0 },
+  { "jobject",  0,     1,    11,   6,    6,    0,   0,   10,    0 },
   { "json",     0,     0,    11,   6,    6,    0,   0,   9,     0 },
   { "line",     0,     1,    9,    1,    1,    0,   0,   11,    1 },
-  { "list",     2,     1,    9,    1,    1,    1,   1,   12,    0 },
-  { "markdown", 0,     0,    9,    1,    1,    1,   2,   13,    2 },
+  { "list",     2,     1,    9,    1,    1,    0,   1,   12,    0 },
+  { "markdown", 0,     0,    9,    1,    1,    0,   2,   13,    2 },
   { "off",      0,     0,    0,    0,    0,    0,   0,   14,    0 },
-  { "qbox",     0,     0,    9,    2,    1,    2,   2,   1,     2 },
-  { "quote",    4,     1,    10,   2,    2,    2,   1,   12,    0 },
-  { "split",    0,     0,    9,    1,    1,    1,   1,   2,     2 },
-  { "table",    0,     0,    9,    1,    1,    1,   2,   19,    2 },
-  { "tabs",     8,     1,    9,    3,    3,    1,   1,   12,    0 },
+  { "qbox",     0,     0,    9,    2,    1,    0,   2,   1,     2 },
+  { "quote",    4,     1,    10,   2,    2,    0,   1,   12,    0 },
+  { "split",    0,     0,    9,    1,    1,    0,   1,   2,     2 },
+  { "table",    0,     0,    9,    1,    1,    0,   2,   19,    2 },
+  { "tabs",     8,     1,    9,    3,    3,    0,   1,   12,    0 },
   { "tcl",      3,     1,    12,   5,    5,    4,   1,   12,    0 },
-  { "www",      0,     0,    9,    4,    4,    1,   2,   7,     0 }
+  { "www",      0,     0,    9,    4,    4,    0,   2,   7,     0 }
 };     /*       |     /     /      |     /    /     |    |       \
        **       |    /     /       |    /    /      |    |        \_ 2: columnar
        ** Index into aModeStr[]    |   /    /       |    |           1: line
@@ -1499,12 +1499,13 @@ static const ModeInfo aModeInfo[] = {
        **      v-------------------'      |   hdrs? |       The QRF style
        **      0: n/a                blob |   v-----'
        **      1: plain        v_---------'   0: n/a
-       **      2: sql          0: n/a         1: no         
+       **      2: sql          0: auto        1: no         
        **      3: csv          1: as-text     2: yes
        **      4: html         2: sql
        **      5: c            3: hex
        **      6: json         4: c
        **                      5: json
+       **                      6: size
        ******************************************************************/
 /*
 ** These are the column/row/line separators used by the various
@@ -3194,6 +3195,13 @@ static int shell_exec(
   if( pArg->mode.bAutoScreenWidth ){
     spec.nScreenWidth = shellScreenWidth();
   }
+  if( spec.eBlob==QRF_BLOB_Auto ){
+    switch( spec.eText ){
+      case QRF_TEXT_Sql:  spec.eBlob = QRF_BLOB_Sql;   break;
+      case QRF_TEXT_Json: spec.eBlob = QRF_BLOB_Json;  break;
+      default:            spec.eBlob = QRF_BLOB_Text;  break;
+    }
+  }
 
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
   if( pArg->expert.pExpert ){
@@ -3561,6 +3569,8 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
     savedMode = p->mode;
     p->mode.spec.zTableName = (char*)zTable;
     p->mode.eMode = MODE_Insert;
+    p->mode.spec.eText = QRF_TEXT_Sql;
+    p->mode.spec.eBlob = QRF_BLOB_Sql;
     p->mode.spec.bTitles = QRF_No;
     rc = shell_exec(p, sSelect.zTxt, 0);
     if( (rc&0xff)==SQLITE_CORRUPT ){
@@ -7663,6 +7673,8 @@ static int modeTitleDsply(ShellState *p, int bAll){
 **                            meaning "left", "centered", and "right", with
 **                            one letter per column starting from the left.
 **                            Unspecified alignment defaults to 'L'.
+**   --blob-quote ARG         ARG can be "auto", "text", "sql", "hex", "tcl",
+**                            "tcl", "json", or "size".  Default is "auto".
 **   --charlimit N            Set the maximum number of output characters to
 **                            show for any single SQL value to N. Longer values
 **                            truncated. Zero means "no limit".
@@ -7768,6 +7780,19 @@ static int dotCmdMode(ShellState *p){
              "Should contain only characters L, C, and R.");
         return 1;
       }
+    }else if( pickStr(z,0,"-blob","-blob-quote","")>=0 ){
+      if( (++i)>=nArg ){
+        dotCmdError(p, i-1, "missing argument", 0);
+        return 1;
+      }
+      k = pickStr(azArg[i], 0,
+                    "auto", "text", "sql", "hex", "tcl", "json", "size", "");
+        /*           0       1       2      3      4      5       6
+        ** Must match QRF_BLOB_xxxx values.  See also tag-20251124a */
+      if( k>=0 ){
+        p->mode.spec.eBlob = k & 0xff;
+      }
+      chng = 1;
     }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","")) ){
       int w;                /*   0            1  */
       if( i+1>=nArg ){
@@ -7854,7 +7879,7 @@ static int dotCmdMode(ShellState *p){
     }else if( optionMatch(z,"noquote") ){
       /* (undocumented legacy) --noquote always turns quoting off */
       p->mode.spec.eText = QRF_TEXT_Plain;
-      p->mode.spec.eBlob = QRF_BLOB_Text;
+      p->mode.spec.eBlob = QRF_BLOB_Auto;
       chng = 1;
     }else if( optionMatch(z,"quote") ){
       if( i+1<nArg
@@ -7884,27 +7909,21 @@ static int dotCmdMode(ShellState *p){
         case 1:  /* on */
         case 2:  /* sql */
           p->mode.spec.eText = QRF_TEXT_Sql;
-          p->mode.spec.eBlob = QRF_BLOB_Sql;
           break;
         case 3:  /* csv */
           p->mode.spec.eText = QRF_TEXT_Csv;
-          p->mode.spec.eBlob = QRF_BLOB_Text;
           break;
         case 4:  /* html */
           p->mode.spec.eText = QRF_TEXT_Html;
-          p->mode.spec.eBlob = QRF_BLOB_Text;
           break;
         case 5:  /* tcl */
           p->mode.spec.eText = QRF_TEXT_Tcl;
-          p->mode.spec.eBlob = QRF_BLOB_Text;
           break;
         case 6:  /* json */
           p->mode.spec.eText = QRF_TEXT_Json;
-          p->mode.spec.eBlob = QRF_BLOB_Json;
           break;
         default: /* off */
           p->mode.spec.eText = QRF_TEXT_Plain;
-          p->mode.spec.eBlob = QRF_BLOB_Text;
           break;
       }
       chng = 1;
@@ -8074,6 +8093,14 @@ static int dotCmdMode(ShellState *p){
       }
       sqlite3_str_append(pDesc, "\"", 1);
     }
+    if( bAll || p->mode.spec.eBlob!=QRF_BLOB_Auto ){
+      const char *azBQuote[] =
+           { "auto", "text", "sql", "hex", "tcl", "json", "size" };
+      /*      0       1       2      3      4      5       6
+      ** Must match QRF_BLOB_xxxx values.  See all instances of tag-20251124a */
+      u8 e = p->mode.spec.eBlob;
+      sqlite3_str_appendf(pDesc, " --blob-quote %s", azBQuote[e]);
+    }
     if( bAll || p->mode.spec.nCharLimit>0 ){
       sqlite3_str_appendf(pDesc, " --charlimit %d",p->mode.spec.nCharLimit);
     }
index a3fe83cb22c8ffae5e964a5e16f9eac6edb99e0e..dd81f49612c068e495a51d01c6996a9d76cd1df2 100644 (file)
@@ -137,19 +137,19 @@ do_test 1.60a {
 } "1,2.5,three\r\n\"\\102\\114\\117\\102\",,\"Ἀμήν\"\r\n"
 do_test 1.60b {
   db format -style csv -columnsep xyz -rowsep pqr -text sql -blob sql {SELECT * FROM t1}
-} "1,2.5,three\r\nBLOB,,\"Ἀμήν\"\r\n"
+} "1,2.5,three\r\nx'424c4f42',,\"Ἀμήν\"\r\n"
 do_test 1.61a {
   db format -style list -columnsep , -rowsep \r\n -text csv -title auto -blob tcl {SELECT * FROM t1}
 } "a,b,c\r\n1,2.5,three\r\n\"\\102\\114\\117\\102\",,\"Ἀμήν\"\r\n"
 do_test 1.61b {
   db format -style csv -title auto -blob tcl {SELECT * FROM t1}
-} "a,b,c\r\n1,2.5,three\r\nBLOB,,\"Ἀμήν\"\r\n"
+} "a,b,c\r\n1,2.5,three\r\n\"\\102\\114\\117\\102\",,\"Ἀμήν\"\r\n"
 do_test 1.62a {
   db format -style list -columnsep , -rowsep \r\n -text csv -title csv -blob tcl {SELECT a AS 'a x y', b, c FROM t1}
 } "\"a x y\",b,c\r\n1,2.5,three\r\n\"\\102\\114\\117\\102\",,\"Ἀμήν\"\r\n"
 do_test 1.62b {
   db format -style csv -title csv -blob tcl {SELECT a AS 'a x y', b, c FROM t1}
-} "\"a x y\",b,c\r\n1,2.5,three\r\nBLOB,,\"Ἀμήν\"\r\n"
+} "\"a x y\",b,c\r\n1,2.5,three\r\n\"\\102\\114\\117\\102\",,\"Ἀμήν\"\r\n"
 
 do_test 1.70 {
   set result "\n[db format -style html {SELECT * FROM t1}]"