]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Continuing work on --rowcount and --title always.
authordrh <>
Tue, 7 Jul 2026 00:23:38 +0000 (00:23 +0000)
committerdrh <>
Tue, 7 Jul 2026 00:23:38 +0000 (00:23 +0000)
FossilOrigin-Name: adeb4fbb86a8a781d7efb0eecb9c84ce605d0bd45f63992bf2ecd60765a60d2c

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

index 8555cb0780d3748248e48dee4d08c8a33bd1380c..fed33a57603cfe10f2f41cf07b5c1bae489aacab 100644 (file)
@@ -187,10 +187,9 @@ ignored, depending on the value of eStyle.
 
 ### 2.4 Show Column Names (bTitles)
 
-The sqlite3_qrf_spec.bTitles field can be either QRF_SW_Auto,
-QRF_SW_On, or QRF_SW_Off.  Those three constants also have shorter
-alternative spellings: QRF_Auto, QRF_No, and
-QRF_Yes.
+The sqlite3_qrf_spec.bTitles field can be one of QRF_SW_Auto,
+QRF_SW_On, QRF_SW_Off, or QRF_Always.  The first three constants also
+have shorter alternative spellings: QRF_Auto, QRF_No, and QRF_Yes.
 
 > ~~~
 #define QRF_SW_Auto     0 /* Let QRF choose the best value */
@@ -199,11 +198,16 @@ QRF_Yes.
 #define QRF_Auto        0 /* Alternate spelling for QRF_SW_Auto and others */
 #define QRF_No          1 /* Alternate spelling for QRF_SW_Off */
 #define QRF_Yes         2 /* Alternate spelling for QRF_SW_On */
+#define QRF_Always      3 /* Always try to show column names */
 ~~~
 
-If the value is QRF_Yes, then column names appear in the output.
+If the value is QRF_Yes, then column names appear in the output when
+there are one or more rows of output.
 If the value is QRF_No, column names are omitted.  If the
 value is QRF_Auto, then an appropriate default is chosen.
+The value QRF_Always is like QRF_Yes except that the output might
+still show column headers even if the number of result rows is zero,
+depending on eStyle.
 
 ### 2.5 Control Character Escapes (eEsc)
 
@@ -594,6 +598,12 @@ not applicable to xRender because title values come from the
 sqlite3_column_name() interface not from sqlite3_column_value(),
 and so that names of columns are never processed by xRender.
 
+### 2.18 Show Row Counts On Query Output (bRowCount)
+
+If the value of bRowCount is QRF_Yes, then an extra line of text
+of the form "(N rows)" might be appended to the end of query output,
+depending on eStyle.
+
 ## 3.0 The `sqlite3_format_query_result()` Interface
 
 Invoke the `sqlite3_format_query_result(P,S,E)` interface to run
index af2145859258f1996fb0c78aa8ca581e15813da0..03a5a72d386d5604d1e25335744755b73e776210 100644 (file)
@@ -1955,7 +1955,18 @@ static void qrfColumnar(Qrf *p){
   if( nColumn==0 ){
     return;   /* Not a query.  No results every shown. */
   }
-  if( rc!=SQLITE_ROW && (rc!=SQLITE_DONE || p->spec.bTitles!=QRF_Always) ){
+  if( rc==SQLITE_DONE && nColumn>0 ){
+    /* Empty query */
+    if( p->spec.bTitles==QRF_Always ){
+      /* fall through into the columnar logic below */
+    }else{
+      if( p->spec.bRowCount==QRF_Yes ){
+        sqlite3_str_appendf(p->pOut, "(0 rows)\n");
+        qrfWrite(p);
+      }
+      return;   /* No output, other than the row count */
+    }
+  }else if( rc!=SQLITE_ROW ){
     return;   /* No output */
   }
 
@@ -2543,6 +2554,45 @@ static void qrfOneJsonRow(Qrf *p){
   qrfWrite(p);
 }
 
+/*
+** Render a title row (a row containing column names) if the spec
+** calls for one and if it makes sense for the eStyle.  Title rows
+** do not make sense for some eStyles, such as QRF_STYLE_Off,
+** QRF_STYLE_Count, QRF_STYLE_Json, and similar.
+*/
+static void qrfSimpleTitle(Qrf *p){
+  assert( p->nRow==0 );
+  assert( p->spec.bTitles>=QRF_Yes );
+  switch( p->spec.eStyle ){
+    case QRF_STYLE_Html: {
+      int i;
+      sqlite3_str_append(p->pOut, "<TR>", 4);
+      for(i=0; i<p->nCol; i++){
+        const char *zCName = sqlite3_column_name(p->pStmt, i);
+        sqlite3_str_append(p->pOut, "\n<TH>", 5);
+        qrfEncodeText(p, p->pOut, zCName);
+      }
+      sqlite3_str_append(p->pOut, "\n</TR>\n", 7);
+      break;
+    }
+    case QRF_STYLE_Quote:
+    case QRF_STYLE_List: {
+      int i;
+      int saved_eText = p->spec.eText;
+      p->spec.eText = p->spec.eTitle;
+      for(i=0; i<p->nCol; i++){
+        const char *zCName = sqlite3_column_name(p->pStmt, i);
+        if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
+        qrfEncodeText(p, p->pOut, zCName);
+      }
+      sqlite3_str_appendall(p->pOut, p->spec.zRowSep);
+      qrfWrite(p);
+      p->spec.eText = saved_eText;
+      break;
+    }
+  }
+}
+
 /*
 ** Render a single row of output for non-columnar styles - any
 ** style that lets us render row by row as the content is received
@@ -2576,13 +2626,7 @@ static void qrfOneSimpleRow(Qrf *p){
     }
     case QRF_STYLE_Html: {
       if( p->nRow==0 && p->spec.bTitles>=QRF_Yes ){
-        sqlite3_str_append(p->pOut, "<TR>", 4);
-        for(i=0; i<p->nCol; i++){
-          const char *zCName = sqlite3_column_name(p->pStmt, i);
-          sqlite3_str_append(p->pOut, "\n<TH>", 5);
-          qrfEncodeText(p, p->pOut, zCName);
-        }
-        sqlite3_str_append(p->pOut, "\n</TR>\n", 7);
+        qrfSimpleTitle(p);
       }
       sqlite3_str_append(p->pOut, "<TR>", 4);
       for(i=0; i<p->nCol; i++){
@@ -2707,16 +2751,7 @@ static void qrfOneSimpleRow(Qrf *p){
     }
     default: {  /* QRF_STYLE_List */
       if( p->nRow==0 && p->spec.bTitles>=QRF_Yes ){
-        int saved_eText = p->spec.eText;
-        p->spec.eText = p->spec.eTitle;
-        for(i=0; i<p->nCol; i++){
-          const char *zCName = sqlite3_column_name(p->pStmt, i);
-          if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
-          qrfEncodeText(p, p->pOut, zCName);
-        }
-        sqlite3_str_appendall(p->pOut, p->spec.zRowSep);
-        qrfWrite(p);
-        p->spec.eText = saved_eText;
+        qrfSimpleTitle(p);
       }
       for(i=0; i<p->nCol; i++){
         if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
@@ -3032,6 +3067,26 @@ int sqlite3_format_query_result(
       while( qrf.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
         qrfOneSimpleRow(&qrf);
       }
+      if( qrf.nCol>0 && qrf.nRow==0 && qrf.spec.bTitles==QRF_Always ){
+        qrfSimpleTitle(&qrf);
+      }
+      if( qrf.nCol>0 && qrf.spec.bRowCount==QRF_Yes ){
+        switch( qrf.spec.eStyle ){
+          case QRF_STYLE_Line:
+            if( qrf.nRow>0 ) sqlite3_str_append(qrf.pOut, "\n", 1);
+            /* Fall through */
+          case QRF_STYLE_Csv:
+          case QRF_STYLE_List:
+          case QRF_STYLE_Quote:
+            sqlite3_str_appendf(qrf.pOut,"(%d row%s)\n",
+                                qrf.nRow, qrf.nRow==1 ? "" : "s");
+            break;
+          case QRF_STYLE_Html:
+            sqlite3_str_appendf(qrf.pOut,"<!-- %d row%s -->\n",
+                                qrf.nRow, qrf.nRow==1 ? "" : "s");
+            break;
+        }
+      }
       break;
     }
   }
index b125638df77d3b55dd2bcc2a2f0d7c7dcce4edc6..f4efb1690903aa555e3902f0f1617463d56fee34 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\snew\soption\s"bRowCount"\sto\sQRF.\s\sAdd\sQRF_Always\sas\sa\spossibility\sfor\nbTitles.\s\sUse\sthese\sfeature\sto\senhance\s".mode\spsql"\sto\sbe\sa\sbetter\napproximation\sof\swhat\spsql\sactually\sdoes.
-D 2026-07-06T19:24:15.260
+C Continuing\swork\son\s--rowcount\sand\s--title\salways.
+D 2026-07-07T00:23:38.996
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -423,9 +423,9 @@ F ext/misc/wholenumber.c e41953e078894e66a0ff05dd6c76a61f904828c9a4620c7255fac26
 F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
 F ext/misc/zipfile.c 5cf901996c840b32a5c03d947c4ee86bda166f6e595a41871840df8520458054
 F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
-F ext/qrf/README.md 9e644615d7d7b77ef7e9db798765679e50c5ed12eda48bce21c9ef9eb4715e9d
+F ext/qrf/README.md 3dfd5de860cdc0c572d8926ba0c1b3cc8925487dfbda10e63af66a8811907687
 F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
-F ext/qrf/qrf.c 99c3ab46eedbc68211296e58797d601a80667f75a8db746a75cb92ec20ca923a
+F ext/qrf/qrf.c 151396f96eb0262443b2dda0313976ffb072b17341374d80cd9681d38345000d
 F ext/qrf/qrf.h fcbc33578176b2fd9dda8310d8f6ba4eaf4f75052f466dfe682802e6664df8bd
 F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
 F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
@@ -743,7 +743,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 54395ee97eb710e695202d4112cf2b1c1c7767a57afcea745df71abb1c917768
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c f553420eaf5c72a49cef786621eea79dd8c4411671839fb05250bb49ca74a0a0
-F src/shell.c.in c26f8aca2312ed8a8be1f63f887c23f45e37911d4ede17f9c6b9d7897d574b80
+F src/shell.c.in ad7b45289ca6867ca2d87230aefc5acc63b86511f9605f23765b0129105e5576
 F src/sqlite.h.in d9ec41feb4cd804e68b174328b43beb3f1f71bba13e1c7a439efb826d301cccc
 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
 F src/sqlite3ext.h 0efd4723bad9124ea1f581d9f1ea0254ac1c6f3e5fb29e4f3dcf36c72485a456
@@ -751,7 +751,7 @@ F src/sqliteInt.h 92563b8edc673513b82d87bf6a8d7aeb554b2c7b7d5e30992fbca04010db79
 F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
-F src/tclsqlite.c 7401c73c917a4d1b380c896a324c8d8eb533a999559d9e339d479596553bebfd
+F src/tclsqlite.c 9ac18aac16dd91fec546d1329c17a41b6b2fd095b2294ba063fa02aca0161f8e
 F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
 F src/test1.c df2df0a74c9aa81cbbad9d7d8277e49ac255334cba97da9ee22501beac274201
 F src/test2.c 2b9ab96bba63a1c369d5769390475259ad210f144a877805f2e32e563f9e93c1
@@ -1533,7 +1533,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 0b5095dfc841eaa12806fe20fc0ede72573885390b3152edc0edb66378fb55f7
+F test/qrf01.test cc17b3efe5d4de8b1f2c9ddd0bb8a6b6934d4f32252803d9d145fac3cecb369e
 F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92
 F test/qrf03.test e7efe46d204671726b4707585126cd78d107368de4a7d0c7b8d5157cdd8624ed
 F test/qrf04.test 0894692c998d2401dcc33449c02051b503ecce0c94217be54fb007c82d2d1379
@@ -2213,11 +2213,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 7f49a7a90eda01753c0dff65197bd7bc48a751e24a46919d30af6e2baf0788fc
-R d458787ae041129a9286190077b172aa
-T *branch * psql-mode
-T *sym-psql-mode *
-T -sym-trunk *
+P 600c6b464050078b38cc688668148f684243e7c5f08d0aae4d5f72aa6f985482
+R 6b8e1ec56e5918c44216302c94fac591
 U drh
-Z e2f6af93169d3a630e55ed3303140615
+Z 7a466c86906d29efc86be3f3db820048
 # Remove this line to create a well-formed Fossil manifest.
index 8fe0186d00ff760fad4500220dbf7955c91a0543..71f1f786095987387e55735dbdef895fa41c396e 100644 (file)
@@ -1 +1 @@
-600c6b464050078b38cc688668148f684243e7c5f08d0aae4d5f72aa6f985482
+adeb4fbb86a8a781d7efb0eecb9c84ce605d0bd45f63992bf2ecd60765a60d2c
index eaf0cc801d2ab54620fa369be35a4cc9d1bcf5c9..c9ebae848cac25064c0d10a0436671fb38a42c49 100644 (file)
@@ -2165,6 +2165,7 @@ static void modeChange(ShellState *p, unsigned char eMode){
       pM->spec.bRowCount = QRF_Yes;
     }else{
       pM->spec.bBorder = QRF_Auto;
+      pM->spec.bRowCount = QRF_No;
     }
     if( pI->mFlg & 0x02 ){
       pM->spec.bSplitColumn = QRF_Yes;
@@ -8660,7 +8661,7 @@ static int modeTitleDsply(ShellState *p, int bAll){
 **                            "tcl", or "json". "off" means show the text as-is.
 **                            "on" is an alias for "sql".
 **   --reset                  Changes all mode settings back to their default.
-**   --rowcount BOOLEAN       Show "(N rows)" at the end of output.
+**   --rowcount BOOLEAN       Show "(N rows)" at the end of query results.
 **   --rowsep STRING          Use STRING as the row separator
 **   --sw|--screenwidth N     Declare the screen width of the output device
 **                            to be N characters.  An attempt may be made to
@@ -8672,7 +8673,7 @@ static int modeTitleDsply(ShellState *p, int bAll){
 **   --textjsonb BOOLEAN      If enabled, JSONB text is displayed as text JSON.
 **   --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".
+**                            "sql", "csv", "html", "tcl", "json", or "always".
 **   --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
index 8f46f7e810cc1bc4af7f2d37c177f58f886a9a19..bee03fe3d9af74c2ec7d6dc816da57e0a67302f6 100644 (file)
@@ -2066,6 +2066,7 @@ static void DbHookCmd(
 **     -defaultalign ("auto"|"left"|...)       Default alignment
 **     -titalalign ("auto"|"left"|"right"|...) Default column name alignment
 **     -border ("auto"|"off"|"on")             Border for box and table styles
+**     -rowcount ("auto"|"off"|"on")           Show row counts
 **     -wrap NUMBER                            Max width of any single column
 **     -screenwidth NUMBER                     Width of the display TTY
 **     -linelimit NUMBER                       Max lines for any cell
@@ -2136,7 +2137,7 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
   };
 
   memset(&qrf, 0, sizeof(qrf));
-  qrf.iVersion = 1;
+  qrf.iVersion = 2;
   qrf.pzOutput = &zResult;
   for(i=2; i<objc; i++){
     const char *zArg = Tcl_GetString(objv[i]);
@@ -2150,7 +2151,7 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
       }
       zSql  = zArg;
     }else if( i==objc-1 ){
-      Tcl_AppendResult(pDb->interp, "option has no argument: ", zArg, (char*)0);
+      Tcl_AppendResult(pDb->interp, "option has no argument: ", zArg,(char*)0);
       rc = TCL_ERROR;
       goto format_failed;
     }else if( strcmp(zArg,"-style")==0 ){
@@ -2195,7 +2196,7 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
       /* NB: --title can be "off" or "on but --text may not be.  Thus we put
       ** the "off" and "on" choices first and start the search on the
       ** thrid element of the array when processing --text */
-      static const char *azText[] = {           "off",   "on",
+      static const char *azText[] = {           "off",   "on",  "always",
         "auto",             "csv",              "html",
         "json",             "plain",            "relaxed",
         "sql",              "tcl",              0
@@ -2207,17 +2208,20 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
       };
       int txt;
       int k = zArg[2]=='e';
-      rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], &azText[k*2], zArg,
+      rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], &azText[k*3], zArg,
                                0, &txt);
       if( rc ) goto format_failed;
       if( k ){
         qrf.eText = aTextMap[txt];
-      }else if( txt<=1 ){
-        qrf.bTitles = txt ? QRF_Yes : QRF_No;
+      }else if( txt<=2 ){
+        assert( QRF_No==1 );
+        assert( QRF_Yes==2 );
+        assert( QRF_Always==3 );
+        qrf.bTitles = txt+QRF_No;
         qrf.eTitle = QRF_TEXT_Auto;
       }else{
         qrf.bTitles = QRF_Yes;
-        qrf.eTitle = aTextMap[txt-2];
+        qrf.eTitle = aTextMap[txt-3];
       }
       i++;
     }else if( strcmp(zArg,"-blob")==0 ){
@@ -2247,6 +2251,7 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
     }else if( strcmp(zArg,"-textjsonb")==0
            || strcmp(zArg,"-splitcolumn")==0
            || strcmp(zArg,"-border")==0
+           || strcmp(zArg,"-rowcount")==0
     ){
       int v = 0;
       rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBool,
@@ -2256,11 +2261,14 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
         qrf.bTextJsonb = aBoolMap[v];
       }else if( zArg[1]=='b' ){
         qrf.bBorder = aBoolMap[v];
+      }else if( zArg[1]=='r' ){
+        qrf.bRowCount = aBoolMap[v];
       }else{
         qrf.bSplitColumn = aBoolMap[v];
       }
       i++;
-    }else if( strcmp(zArg,"-defaultalign")==0 || strcmp(zArg,"-titlealign")==0){
+    }else if( strcmp(zArg,"-defaultalign")==0
+           || strcmp(zArg,"-titlealign")==0){
       int ax = 0;
       rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azAlign,
                     zArg[1]=='d' ?  "default alignment (-defaultalign)" :
index 25b7a893beea1867c6ba6d68e7451725986657bd..c8a6527419326963400163544b5b3136a469cbf4 100644 (file)
@@ -66,6 +66,51 @@ do_test 1.11d {
  1           │ 2.5 │ three
  x'424c4f42' │     │ Ἀμήν
 }
+do_test 1.11e {
+  set result "\n[db format -rowcount on {SELECT * FROM t1}]"
+} {
+╭──────┬─────┬───────╮
+│  a   │  b  │   c   │
+╞══════╪═════╪═══════╡
+│    1 │ 2.5 │ three │
+│ BLOB │     │ Ἀμήν  │
+╰──────┴─────┴───────╯
+(2 rows)
+}
+do_test 1.11f {
+  set result "\n[db format -rowcount on {SELECT * FROM t1 WHERE a=1}]"
+} {
+╭───┬─────┬───────╮
+│ a │  b  │   c   │
+╞═══╪═════╪═══════╡
+│ 1 │ 2.5 │ three │
+╰───┴─────┴───────╯
+(1 row)
+}
+do_test 1.11g {
+  set result "\n[db format {SELECT * FROM t1 WHERE a=2}]"
+} {}
+do_test 1.11h {
+  set result "\n[db format -rowcount on {SELECT * FROM t1 WHERE a=2}]"
+} {
+(0 rows)
+}
+do_test 1.11i {
+  set result "\n[db format -title always -rowcount off {SELECT * FROM t1 WHERE a=2}]"
+} {
+╭───┬───┬───╮
+│ a │ b │ c │
+╰───┴───┴───╯
+}
+do_test 1.11j {
+  set result "\n[db format -title always -rowcount on {SELECT * FROM t1 WHERE a=2}]"
+} {
+╭───┬───┬───╮
+│ a │ b │ c │
+╰───┴───┴───╯
+(0 rows)
+}
+
 do_test 1.12 {
   set result "\n[db format -text csv {SELECT * FROM t1}]"
 } {
@@ -378,7 +423,7 @@ x'424c4f42'|NULL|'Ἀμήν'
 do_test 1.118 {
   set rc [catch {db format -style list -title unk {SELECT * FROM t1}} res]
   lappend rc $res
-} {1 {bad -title "unk": must be off, on, auto, csv, html, json, plain, relaxed, sql, or tcl}}
+} {1 {bad -title "unk": must be off, on, always, auto, csv, html, json, plain, relaxed, sql, or tcl}}
 
 
 do_test 1.120 {
@@ -410,7 +455,6 @@ do_test 1.131 {
 x'424c4f42',NULL,'Ἀμήν'
 }
 
-
 do_execsql_test 2.0 {
   DELETE FROM t1;
   INSERT INTO t1 VALUES(1,2,'The quick fox jumps over the lazy brown dog.');