]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Notes on the result-formatter utility. None of the code works. These
authordrh <>
Mon, 20 Oct 2025 14:28:57 +0000 (14:28 +0000)
committerdrh <>
Mon, 20 Oct 2025 14:28:57 +0000 (14:28 +0000)
are just ideas I have jotted down as I try to figure out how to do this.

FossilOrigin-Name: c38f1c63247804486a6b368ead4c5122adaedd5c697487fadbed49e1acb155bc

ext/misc/resfmt.c [new file with mode: 0644]
ext/misc/resfmt.h [new file with mode: 0644]
ext/misc/resfmt.md
manifest
manifest.uuid

diff --git a/ext/misc/resfmt.c b/ext/misc/resfmt.c
new file mode 100644 (file)
index 0000000..a557e82
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+** 2025-10-20
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Implementation of the Result-Format or "resfmt" utility library for SQLite.
+** See the resfmt.md documentation for additional information.
+*/
+#include "resfmt.h"
+
+/*
+** Private state information.  Subject to change from one release to the
+** next.
+*/
+struct sqlite3_resfmt {
+  sqlite3_stmt *pStmt;        /* The statement whose output is to be rendered */
+  sqlite3 *db;                /* The corresponding database connection */
+  sqlite3_str *pErr;          /* Error message, or NULL */
+  sqlite3_str *pOut;          /* Accumulated output */
+  int iErr;                   /* Error code */
+  int nCol;                   /* Number of output columns */
+  sqlite3_int64 nRow;         /* Number of rows handled so far */
+  sqlite3_resfmt_spec spec;   /* Copy of the original spec */
+};
+
+
+/*
+** Free memory associated with pResfmt
+*/
+static void resfmtFree(sqlite3_resfmt *p){
+  if( p->pErr ) sqlite3_free(sqlite3_str_finish(p->pErr));
+  if( p->pOut ) sqlite3_free(sqlite3_str_finish(p->pOut));
+  sqlite3_free(p);
+}
+
+/*
+** Finish rendering the results
+*/
+int sqlite3_resfmt_finish(sqlite3_resfmt *p, int *piErr, char **pzErrMsg){
+  if( p==0 ){
+    return SQLITE_OK;
+  }
+  if( p->spec.pzOutput ){
+    *p->spec.pzOutput = sqlite3_str_finish(p->pOut);
+    p->pOut = 0;
+  }
+  if( piErr ){
+    *piErr = p->iErr;
+  }
+  if( pzErrMsg ){
+    *pzErrMsg = sqlite3_str_finish(p->pErr);
+    p->pErr = 0;
+  }
+  resfmtFree(p); 
+  return SQLITE_OK;
+}
+
+/*
+** Render value pVal into p->pOut
+*/
+static void resfmtRenderValue(sqlite3_resfmt *p, sqlite3_value *pVal){
+  if( p->xRender ){
+    char *z = p->xRender(p->pRenderArg, pVal);
+    if( z ){
+      sqlite3_str_appendall(p->pOut, z);
+      sqlite3_free(z);
+      return;
+    }
+  }
+  switch( sqlite3_value_type(pVal) {
+    case SQLITE_INTEGER: {
+      sqlite3_str_appendf(p->pOut, "%lld", sqlite3_value_int64(pVal));
+      break;
+    }
+    case SQLITE_FLOAT: {
+      sqlite3_str_appendf(p->pOut, p->zFloatFmt, sqlite3_value_double(pVal));
+      break;
+    }
+    case SQLITE_BLOB: {
+      int iStart = sqlite3_str_length(p->pOut);
+      int nBlob = sqlite3_value_bytes(pVal);
+      int i, j;
+      char *zVal;
+      unsigned char *a = sqlite3_value_blob(pVal);
+      sqlite3_str_append(p->pOut, "x'", 2);
+      sqlite3_str_appendchar(p->pOut, nBlob, ' ');
+      sqlite3_str_appendchar(p->pOut, nBlob, ' ');
+      sqlite3_str_appendchar(p->pOut, 1, '\'');
+      if( sqlite3_str_errcode(p->pOut ) return;
+      zVal = sqlite3_str_value(p->pOut);
+      for(i=0, j=iStart+2; i<nBlob; i++, j+=2){
+        unsigned char c = a[i];
+        zVal[j] = "0123456789abcdef"[(c>>4)&0xf]);
+        zVal[j+1] = "0123456789abcdef"[(c)&0xf]);
+      }
+      break;
+    }
+    case SQLITE_NULL: {
+      sqlite3_str_appendall(p->pOut, p->zNull);
+      break;
+    }
+    case SQLITE_TEXT: {
+      if( p->spec.bQuote ){
+        sqlite3_str_appendf(p->pOut, "%Q", sqlite3_value_text(pVal));
+      }else{
+        sqlite3_str_appendall(p->pOut, sqlite3_value_text(pVal));
+      }
+      break;
+    }
+  }
+}
+
+/*
+** If xWrite is defined, send all content of pOut to xWrite and
+** reset pOut.
+*/
+static void resfmtWrite(sqlite3_resfmt *p){
+  int n;
+  if( p->spec.xWrite && (n = sqlite3_str_length(p->pOut))>0 ){
+    p->spec.xWrite(p->spec.pWriteArg,
+               (const unsigned char*)sqlite3_str_value(p->pOut),
+               (size_t)n);
+    sqlite3_str_reset(p->pOut);
+  }
+}
+
+/*
+** Create a new rendering object
+*/
+sqlite3_resfmt *sqlite3_resfmt_begin(
+  sqlite3_stmt *pStmt,
+  sqlite3_resfmt_spec *pSpec
+){
+  sqlite3_resfmt *p;          /* The new sqlite3_resfmt being created */
+  size_t sz;                  /* Size of pSpec[], based on pSpec->iVersion */
+
+  if( pStmt==0 ) return 0;
+  if( pSpec==0 ) return 0;
+  if( pSpec->iVersion!=1 ) return 0;
+  p = sqlite3_malloc64( sizeof(*p) );
+  if( p==0 ) return 0;
+  p->pStmt = pStmt;
+  p->db = sqlite3_db_handle(pStmt);
+  p->pErr = 0;
+  p->pOut = 0;
+  p->pBuf = sqlite3_str_new(p->db);
+  if( p->pBuf==0 ){
+    reffmtFree(p);
+    return 0;
+  }
+  if( pSpec->pzOutput ){
+    p->pOut = sqlite3_str_new(p->db);
+    if( p->pOut==0 ){
+      reffmtFree(p);
+      return 0;
+    }
+  }
+  p->iErr = 0;
+  p->nCol = sqlite3_column_count(p->pStmt);
+  p->nRow = 0;
+  sz = sizeof(sqlite3_resfmt_spec); break;
+  memcpy(&p->spec, pSpec, sz);
+  return p;
+}
+
+/*
+** Output text in the manner requested by the spec (either by direct
+** write to 
+
+/*
+** Render a single row of output.
+*/
+int sqlite3_resfmt_row(sqlite3_resfmt *p){
+  int rc = SQLITE_OK;
+  int i;
+  if( p==0 ) return SQLITE_DONE;
+  switch( p->spec.eFormat ){
+    default: {  /* RESFMT_List */
+      sqlite3_str_reset(p->pOut);
+      for(i=0; i<p->nCol; i++){
+        if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
+        resfmtRenderValue(p, sqlite3_column_value(p->pStmt, i));
+      }
+      sqlite3_str_appendall(p->pOut, p->spec.zRowSep);
+      resfmtWrite(p);
+      break;
+    }
+  }
+  return rc;
+}
diff --git a/ext/misc/resfmt.h b/ext/misc/resfmt.h
new file mode 100644 (file)
index 0000000..5106c9f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+** 2025-10-20
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Header file for the Result-Format or "resfmt" utility library for SQLite.
+** See the resfmt.md documentation for additional information.
+*/
+#include "sqlite3.h"
+
+/*
+** Specification used by clients to define the output format they want
+*/
+typedef struct sqlite3_resfmt_spec sqlite3_resfmt_spec;
+struct sqlite3_resfmt_spec {
+  int iVersion;               /* Version number of this structure */
+  int eFormat;                /* Output format */
+  unsigned char bShowCNames;  /* True to show column names */
+  unsigned char eEscMode;     /* How to deal with control characters */
+  unsigned char bQuote;       /* Quote output values as SQL literals */
+  unsigned char bWordWrap;    /* Try to wrap on word boundaries */
+  int mxWidth;                /* Maximum column width in columnar modes */
+  const char *zColumnSep;     /* Alternative column separator */
+  const char *zRowSep;        /* Alternative row separator */
+  const char *zTableName;     /* Output table name */
+  const char *zNull;          /* Rendering of NULL */
+  const char *zFloatFmt;      /* printf-style string for rendering floats */
+  int nWidth;                 /* Number of column width parameters */
+  short int *aWidth;          /* Column widths */
+  char *(*xRender)(void*,sqlite3_value*);                 /* Render a value */
+  ssize_t (*xWrite)(void*,const unsigned char*,ssize_t);  /* Write callback */
+  void *pRenderArg;           /* First argument to the xRender callback */
+  void *pWriteArg;            /* First argument to the xWrite callback */
+  char **pzOutput;            /* Storage location for output string */
+  /* Additional fields may be added in the future */
+};
+
+/*
+** Opaque state structure used by this library.
+*/
+typedef struct sqlite3_resfmt sqlite3_resfmt;
+
+/*
+** Interfaces
+*/
+sqlite3_resfmt *sqlite3_resfmt_begin(sqlite3_stmt*, sqlite3_resfmt_spec*);
+int sqlite3_resfmt_row(sqlite3_resfmt*)
+int sqlite3_resfmt_finish(sqlite3_resfmt*,int*,char**);
+
+/*
+** Output styles:
+*/
+#define RESFMT_Line      0 /* One column per line. */
+#define RESFMT_Column    1 /* One record per line in neat columns */
+#define RESFMT_List      2 /* One record per line with a separator */
+#define RESFMT_Html      3 /* Generate an XHTML table */
+#define RESFMT_Insert    4 /* Generate SQL "insert" statements */
+#define RESFMT_Tcl       5 /* Generate ANSI-C or TCL quoted elements */
+#define RESFMT_Csv       6 /* Quote strings, numbers are plain */
+#define RESFMT_Explain   7 /* Like RESFMT_Column, but do not truncate data */
+#define RESFMT_Pretty    8 /* Pretty-print schemas */
+#define RESFMT_EQP       9 /* Converts EXPLAIN QUERY PLAN output into a graph */
+#define RESFMT_Json     10 /* Output JSON */
+#define RESFMT_Markdown 11 /* Markdown formatting */
+#define RESFMT_Table    12 /* MySQL-style table formatting */
+#define RESFMT_Box      13 /* Unicode box-drawing characters */
+#define RESFMT_Count    14 /* Output only a count of the rows of output */
+#define RESFMT_Off      15 /* No query output shown */
+#define RESFMT_ScanExp  16 /* Like RESFMT_Explain, but for ".scanstats vm" */
+#define RESFMT_Www      17 /* Full web-page output */
index 5c5af5a50bcd458802e75c7a9b50ea1835f3fd08..b0fd5a3842fcec3b4c03550de1aaf644e8c3367b 100644 (file)
@@ -13,10 +13,10 @@ bound and is ready to run.  Then to format the output from this
 prepared statement, use code similar to the following:
 
 > ~~~
-ResfmtSpec spec;     /* Formatter spec */
-Resfmt *pFmt;        /* Formatter object */
-int errCode;         /* Error code */
-char *zErrMsg;       /* Text error message (optional) */
+sqlite3_resfmt_spec spec;   /* Formatter spec */
+sqlite3_resfmt *pFmt;       /* Formatter object */
+int errCode;                /* Error code */
+char *zErrMsg;              /* Text error message (optional) */
 
 memset(&spec, 0, sizeof(spec));
 // Additional spec initialization here
@@ -29,8 +29,8 @@ sqlite3_resfmt_finish(pFmt, &errCode, &zErrMsg);
 sqlite3_free(zErrMsg);
 ~~~
 
-The `ResfmtSpec` structure (defined below) describes the desired
-output format.  The `pFmt` variable is a pointer to an opaque Resfmt
+The `sqlite3_resfmt_spec` structure (defined below) describes the desired
+output format.  The `pFmt` variable is a pointer to an opaque sqlite3_resfmt
 object that maintains the statement of the formatter.
 The pFmt object is used as the first parameter to two other
 routines, `sqlite3_resfmt_row()` and `sqlite3_resfmt_finish()`, and
@@ -38,15 +38,15 @@ is not usable for any other purpose by the caller.  The
 `sqlite3_resfmt_finish()` interface serves as a destructor for
 the pFmt object.
 
-## 2.0 The `ResfmtSpec` object
+## 2.0 The `sqlite3_resfmt_spec` object
 
 A pointer to an instance of the following structure is the second
 parameter to the `sqlite3_resfmt_begin()` interface.  This structure
 defines how the rules of the statement are to be formatted.
 
 > ~~~
-typedef struct ResfmtSpec ResfmtSpec;
-struct ResfmtSpec {
+typedef struct sqlite3_resfmt_spec sqlite3_resfmt_spec;
+struct sqlite3_resfmt_spec {
   int iVersion;               /* Version number of this structure */
   int eFormat;                /* Output format */
   unsigned char bShowCNames;  /* True to show column names */
@@ -57,45 +57,48 @@ struct ResfmtSpec {
   const char *zColumnSep;     /* Alternative column separator */
   const char *zRowSep;        /* Alternative row separator */
   const char *zTableName;     /* Output table name */
+  const char *zNull;          /* Rendering of NULL */
+  const char *zFloatFmt;      /* printf-style string for rendering floats */
   int nWidth;                 /* Number of column width parameters */
   short int *aWidth;          /* Column widths */
-  char *(*pRender)(void*,sqlite3_value*);                 /* Render a value */
-  ssize_t (*pWrite)(void*,const unsigned char*,ssize_t);  /* Write callback */
-  void *pWriteArg;            /* First argument to write callback */
+  char *(*xRender)(void*,sqlite3_value*);                 /* Render a value */
+  ssize_t (*xWrite)(void*,const unsigned char*,ssize_t);  /* Write callback */
+  void *pRenderArg;           /* First argument to the xRender callback */
+  void *pWriteArg;            /* First argument to the xWrite callback */
   char **pzOutput;            /* Storage location for output string */
   /* Additional fields may be added in the future */
 };
 ~~~
 
-The ResfmtSpec object must be fully initialized prior
+The sqlite3_resfmt_spec object must be fully initialized prior
 to calling `sqlite3_resfmt_begin()` and its value must not change
 by the application until after the corresponding call to
 `sqlite3_resfmt_finish()`.  Note that the result formatter itself
-might change values in the ResfmtSpec object as it runs.
+might change values in the sqlite3_resfmt_spec object as it runs.
 But the application should not try to change or use any fields of
-the ResfmtSpec object while the formatter is running.
+the sqlite3_resfmt_spec object while the formatter is running.
 
 ### 2.1 Structure Version Number
 
-The ResfmtSpec.iVersion field must be 1.  Future enhancements to this
-subsystem might add new fields onto the bottom of the ResfmtSpec object.
-Those new fields will only be accessible if the iVersion is greater than 1.
-Thus the iVersion field is used to support upgradability.
+The sqlite3_resfmt_spec.iVersion field must be 1.  Future enhancements to this
+subsystem might add new fields onto the bottom of the sqlite3_resfmt_spec
+object. Those new fields will only be accessible if the iVersion is greater
+than 1. Thus the iVersion field is used to support upgradability.
 
 ### 2.2 Output Deposition
 
 The formatted output can either be sent to a callback function
 or accumulated into an output buffer in memory obtained
-from system malloc().  If the ResfmtSpec.pWrite column is not NULL,
-then that function is invoked (using ResfmtSpec.pWriteArg as its
+from system malloc().  If the sqlite3_resfmt_spec.xWrite column is not NULL,
+then that function is invoked (using sqlite3_resfmt_spec.xWriteArg as its
 first argument) to transmit the formatted output.  Or, if
-ResfmtSpec.pzOutput points to a pointer to a character, then that
+sqlite3_resfmt_spec.pzOutput points to a pointer to a character, then that
 pointer is made to point to memory obtained from malloc() that
 contains the complete text of the formatted output.
 
 When `sqlite3_resfmt_begin()` is called,
-one of ResfmtSpec.pWrite and ResfmtSpec.pzOutput must be non-NULL
-and the other must be NULL.
+one of sqlite3_resfmt_spec.xWrite and sqlite3_resfmt_spec.pzOutput must be
+non-NULL and the other must be NULL.
 
 Output might be generated row by row, on each call to
 `sqlite3_resfmt_row()` or it might be written all at once
@@ -104,18 +107,18 @@ on the output format.
 
 ### 2.3 Output Format
 
-The ResfmtSpec.eFormat field is an integer code that defines the
+The sqlite3_resfmt_spec.eFormat field is an integer code that defines the
 specific output format that will be generated.  See the
 output format describes below for additional detail.
 
 ### 2.4 Show Column Names
 
-The ResfmtSpec.bShowCNames field is a boolean.  If true, then column
+The sqlite3_resfmt_spec.bShowCNames field is a boolean.  If true, then column
 names appear in the output.  If false, column names are omitted.
 
 ### 2.5 Control Character Escapes
 
-The ResfmtSpec.eEscMode determines how ASCII control characters are
+The sqlite3_resfmt_spec.eEscMode determines how ASCII control characters are
 formatted in the output.  If this value is zero, then the control character
 with value X is displayed as ^Y where Y is X+0x40.  Hence, a
 backspace character (U+0008) is shown as "^H".  This is the default.
@@ -128,27 +131,48 @@ The TAB (U+0009), LF (U+000a) and CR-LF (U+000d,U+000a) character
 sequence are always output literally and are not mapped to alternative
 display values, regardless of this setting.
 
-### 2.6 Word Wrapping In Columnar Modes
+### 2.6 Render output as SQL literals
+
+If the sqlite3_resfmt_spec.bQuote field is non-zero (true), then outputs
+are rendered as SQL literal values.  String are written within `'...'`
+with appropriate escapes.  BLOBs are of the form `x'...'`.  NULL values
+come out as "NULL".
+
+### 2.7 Word Wrapping In Columnar Modes
 
 For output modes that attempt to display equal-width columns, the
-ResfmtSpec.bWordWrap boolean determines whether long values are broken
-at word boundaries, or at arbitrary characters.  The ResfmtSpec.mxWidth
-determines the maximum width of an output column.
+sqlite3_resfmt_spec.bWordWrap boolean determines whether long values
+are broken at word boundaries, or at arbitrary characters.  The
+sqlite3_resfmt_spec.mxWidth determines the maximum width of an output column.
 
-### 2.7 Row and Column Separator Strings
+### 2.8 Row and Column Separator Strings
 
-The ResfmtSpec.zColumnSep and ResfmtSpec.zRowSep strings are alternative
-column and row separator character sequences.  If not specified (if these
-pointers are left as NULL) then appropriate defaults are used.
+The sqlite3_resfmt_spec.zColumnSep and sqlite3_resfmt_spec.zRowSep strings
+are alternative column and row separator character sequences.  If not
+specified (if these pointers are left as NULL) then appropriate defaults
+are used.
 
-### 2.8 The Output Table Name
+### 2.9 The Output Table Name
 
-The ResfmtSpec.zTableName value is the name of the output table
+The sqlite3_resfmt_spec.zTableName value is the name of the output table
 when the MODE_Insert output mode is used.
 
-### 2.9 Column Widths And Alignments
+### 2.10 The Rendering Of NULL
+
+If a value is NULL and sqlite3_resfmt_spec.xRender() does not exist
+or declines to provide a rendering, then show the NULL using the string
+found in sqlite3_resfmt_spec.zNull.  If zNull is itself a NULL pointer
+then NULL values are rendered as an empty string.
+
+### 2.11 Floating Point Value Format
 
-The ResfmtSpec.aWidth[] array, if specified, is an array of 
+If a value is a floating-point number other than Infinity or NaN, then
+the value is rendered using the printf-style format given by the
+sqlite3_resfmt_spec.zFloatFmt string.
+
+### 2.12 Column Widths And Alignments
+
+The sqlite3_resfmt_spec.aWidth[] array, if specified, is an array of 
 16-bit signed integers that specify the minimum column width and
 the alignment for all columns in columnar output modes.  Negative
 values mean right-justify.  The
@@ -156,17 +180,17 @@ absolute value is the minimum of the corresponding column.
 These widths are deliberately stored in a 16-bit signed integer
 as no good can come from having column widths greater than 32767.
 
-The ResfmtSpec.nWidth field is the number of values in the aWidth[]
+The sqlite3_resfmt_spec.nWidth field is the number of values in the aWidth[]
 array.  Any column beyond the nWidth-th column are assumed to have
 a minimum width of 0.
 
-### 2.10 Optional Value Rendering Callback
+### 2.13 Optional Value Rendering Callback
 
-If the ResfmtSpec.pRender field is not NULL, then each rendered
-sqlite3_value is first passed to the pRender function, giving it
-an opportunity to render the results.  If pRender chooses to render,
+If the sqlite3_resfmt_spec.xRender field is not NULL, then each rendered
+sqlite3_value is first passed to the xRender function, giving it
+an opportunity to render the results.  If xRender chooses to render,
 it should write the rendering into memory obtained from sqlite3_malloc()
-and return a pointer to that memory.  The pRender function can decline
+and return a pointer to that memory.  The xRender function can decline
 to render (for example, based on the sqlite3_value_type() or other
 characteristics of the value) in which case it can simply return a
 NULL pointer and the usual default rendering will be used instead.
@@ -175,28 +199,31 @@ The result rendering subsystem will take responsibility for the
 returned string and will pass the returned string to sqlite3_free()
 when it has finished with it.
 
+The bQuote and eEscMode settings above become no-ops if the xRender
+routine returns non-NULL.  In other words, the application-supplied
+xRender routine is expected to do its own bQuote and eEscMode processing
+if it chooses to render values.
+
 ## 3.0 The `sqlite3_resfmt_begin()` Interface
 
 Invoke the `sqlite3_resfmt_begin(P,S)` interface to begin formatting
 the output of prepared statement P using format specification S.
-This routine returns a pointer to an opaque Resfmt object that is
+This routine returns a pointer to an opaque sqlite3_resfmt object that is
 the current state of the formatter.  The `sqlite3_resfmt_finish()`
-routine is the destructor for the Resfmt object and must be called
+routine is the destructor for the sqlite3_resfmt object and must be called
 to prevent a memory leak.
 
 If an out-of-memory fault occurs while allocating space for the
-Resfmt object, then `sqlite3_resfmt_begin()` will return a NULL
+sqlite3_resfmt object, then `sqlite3_resfmt_begin()` will return a NULL
 pointer.  The application need not check for this case as the
-other routines that use a pointer to the Resfmt object all
-interpret a NULL parameter in place of the Resfmt pointer as
+other routines that use a pointer to the sqlite3_resfmt object all
+interpret a NULL parameter in place of the sqlite3_resfmt pointer as
 a harmless no-op.
 
 ## 4.0 The `sqlite3_resfmt_step()` Interface
 
-Invoke the `sqlite3_resfmt_step(F,P)` interface for each row
-in the prepared statement that is to be output.  The prepared
-statement pointer P must be the same as the P argument passed
-into `sqlite3_resfmt_begin()`, or unpredictable things can happen.
+Invoke the `sqlite3_resfmt_step(F)` interface for each row
+in the prepared statement that is to be output.
 
 The formatter might choose to output some content as each row
 is processed, or it might accumulate the output and send it all
@@ -221,6 +248,9 @@ is written into *E.  It is the responsibility of the calling
 application to invoke sqlite3_free() on this error message to
 reclaim the space.
 
+If the F argument to `sqlite3_resfmt_finish(F,C,E)` is a NULL pointer,
+then this interface is a harmless no-op.
+
 ### 6.0 Output Modes
 
 The result formatter supports a variety of output modes.  The
@@ -228,27 +258,24 @@ set of supported output modes might increase in future versions.
 The following output modes are currently defined:
 
 > ~~~
-#define MODE_Line      0 /* One column per line. */
-#define MODE_Column    1 /* One record per line in neat columns */
-#define MODE_List      2 /* One record per line with a separator */
-#define MODE_Semi      3 /* Same as MODE_List but append ";" to each line */
-#define MODE_Html      4 /* Generate an XHTML table */
-#define MODE_Insert    5 /* Generate SQL "insert" statements */
-#define MODE_Quote     6 /* Quote values as for SQL */
-#define MODE_Tcl       7 /* Generate ANSI-C or TCL quoted elements */
-#define MODE_Csv       8 /* Quote strings, numbers are plain */
-#define MODE_Explain   9 /* Like MODE_Column, but do not truncate data */
-#define MODE_Ascii    10 /* Use ASCII unit and record separators (0x1F/0x1E) */
-#define MODE_Pretty   11 /* Pretty-print schemas */
-#define MODE_EQP      12 /* Converts EXPLAIN QUERY PLAN output into a graph */
-#define MODE_Json     13 /* Output JSON */
-#define MODE_Markdown 14 /* Markdown formatting */
-#define MODE_Table    15 /* MySQL-style table formatting */
-#define MODE_Box      16 /* Unicode box-drawing characters */
-#define MODE_Count    17 /* Output only a count of the rows of output */
-#define MODE_Off      18 /* No query output shown */
-#define MODE_ScanExp  19 /* Like MODE_Explain, but for ".scanstats vm" */
-#define MODE_Www      20 /* Full web-page output */
+#define RESFMT_Line      0 /* One column per line. */
+#define RESFMT_Column    1 /* One record per line in neat columns */
+#define RESFMT_List      2 /* One record per line with a separator */
+#define RESFMT_Html      3 /* Generate an XHTML table */
+#define RESFMT_Insert    4 /* Generate SQL "insert" statements */
+#define RESFMT_Tcl       5 /* Generate ANSI-C or TCL quoted elements */
+#define RESFMT_Csv       6 /* Quote strings, numbers are plain */
+#define RESFMT_Explain   7 /* Like RESFMT_Column, but do not truncate data */
+#define RESFMT_Pretty    8 /* Pretty-print schemas */
+#define RESFMT_EQP       9 /* Converts EXPLAIN QUERY PLAN output into a graph */
+#define RESFMT_Json     10 /* Output JSON */
+#define RESFMT_Markdown 11 /* Markdown formatting */
+#define RESFMT_Table    12 /* MySQL-style table formatting */
+#define RESFMT_Box      13 /* Unicode box-drawing characters */
+#define RESFMT_Count    14 /* Output only a count of the rows of output */
+#define RESFMT_Off      15 /* No query output shown */
+#define RESFMT_ScanExp  16 /* Like RESFMT_Explain, but for ".scanstats vm" */
+#define RESFMT_Www      17 /* Full web-page output */
 ~~~
 
 Additional detail about the meaning of each of these output modes
index 7971ee783a816245bcb9770b56c7e3a5114c0655..93cd3e22b1693d2f348f96d9e2bc7bbcee03881a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\srecent\strunk\senhancements\sinto\sthe\sresfmt\sbranch.
-D 2025-10-20T10:55:01.253
+C Notes\son\sthe\sresult-formatter\sutility.\s\sNone\sof\sthe\scode\sworks.\s\sThese\nare\sjust\sideas\sI\shave\sjotted\sdown\sas\sI\stry\sto\sfigure\sout\show\sto\sdo\sthis.
+D 2025-10-20T14:28:57.161
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -389,7 +389,9 @@ F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47c
 F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
 F ext/misc/regexp.c 548151f3e57506fda678e6a65e85a763f4eece653287e1ad44e167f9485e0c6b
 F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
-F ext/misc/resfmt.md 676af474a6598dceb2e786f407917fd08f88891525929569c365c9b9dcb718e7
+F ext/misc/resfmt.c 63285008be21bd71ac036f37e91b9c099e8c221613a25c437d1cf07c0d0d93c8
+F ext/misc/resfmt.h bac5dbf40c174d99d300ed34f3e94bea6854af73ea703d18d0897088c73473a9
+F ext/misc/resfmt.md 6f6cefd95fa11ce30e4f34ea84052e7a8291dd48b7e666352bd7cf2e22c22ec4
 F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
 F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
 F ext/misc/series.c 22c6d8f00cc1b5089b1b37392e9097e9df9a5db53be86daf9a7669d95bb179f4
@@ -609,7 +611,7 @@ F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 9097074724172e31e56ce20ccd7482259cf72
 F ext/wasm/api/sqlite3-wasm.c dd7fc1d535281f0d5d2732bb1b662d1d403a762f07b63c2ea5663053377b2804
 F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bda1c75bd674a92a0e27cc2f3d46dbbf21e422413f8046814515a0bd7409328a
 F ext/wasm/api/sqlite3-worker1.c-pp.js 802d69ead8c38dc1be52c83afbfc77e757da8a91a2e159e7ed3ecda8b8dba2e7
-F ext/wasm/c-pp-lite.c b2098c8abb8d42f061a53c6857fbc1863298dc8a2d9eb5f114fca67c36f39a68 w ext/wasm/c-pp.c
+F ext/wasm/c-pp-lite.c b2098c8abb8d42f061a53c6857fbc1863298dc8a2d9eb5f114fca67c36f39a68
 F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
 F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
@@ -2172,8 +2174,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P d5dfbcf077db340690c482c8ebcc4def85fc9127fa6fcde2f71acfd928feaeff 53edea286b0a38f4f9c7017276f3a826037919144d517f8c89ef0f35b65af5f1
-R 594704bac1034825df5ef0f721316a40
+P 20c79a2cc1f9eedea12cbac0a657301614d042e3487ddf37cd4b0316e6f84f21
+R 894750e947c3f45bc6ad26f6f95da410
 U drh
-Z cb5661959eeb819bb8ecac2ffcfd5b2f
+Z 310d7ad8c0408f77d8a61f85297aa2df
 # Remove this line to create a well-formed Fossil manifest.
index 2ee3dd040b8cd64bf09dac6bccdd5c4f1552a9bc..f38a402e3ad91ade2147d692bcdec41607c126e8 100644 (file)
@@ -1 +1 @@
-20c79a2cc1f9eedea12cbac0a657301614d042e3487ddf37cd4b0316e6f84f21
+c38f1c63247804486a6b368ead4c5122adaedd5c697487fadbed49e1acb155bc