mirror of
https://github.com/sqlite/sqlite.git
synced 2025-10-21 11:13:54 +03:00
Initial prototype spec for the SQLite Query Result Formatter.
FossilOrigin-Name: 87b5e41b999877a1d0b4bb049642909c1698dc1b24e4e45631eb13d02818f0ec
This commit is contained in:
247
ext/misc/resfmt.md
Normal file
247
ext/misc/resfmt.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# SQLite Result Formatting Subsystem
|
||||
|
||||
The "resfmt" subsystem is a set of C-language subroutines that work
|
||||
together to format the output from an SQLite query. The output format
|
||||
is configurable. The application can request CSV, or a table, or
|
||||
any of several other formats, according to needs.
|
||||
|
||||
## 1.0 Overview Of Operation
|
||||
|
||||
Suppose `pStmt` is a pointer to an SQLite prepared statement
|
||||
(a pointer to an `sqlite3_stmt` object) that has been reset and
|
||||
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) */
|
||||
|
||||
memset(&spec, 0, sizeof(spec));
|
||||
// Additional spec initialization here
|
||||
pFmt = sqlite3_resfmt_begin(pStmt, &spec);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
sqlite3_resfmt_row(pFmt, pStmt);
|
||||
}
|
||||
sqlite3_resfmt_finish(pFmt, &errCode, &zErrMsg);
|
||||
// Do something with errcode and zErrMsg
|
||||
sqlite3_free(zErrMsg);
|
||||
~~~
|
||||
|
||||
The `ResfmtSpec` structure (defined below) describes the desired
|
||||
output format. The `pFmt` variable is a pointer to an opaque 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
|
||||
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
|
||||
|
||||
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 {
|
||||
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 */
|
||||
int nWidth; /* Number of column width parameters */
|
||||
int *aWidth; /* Column widths */
|
||||
ssize_t (*pWrite)(void*,const unsigned char*,ssize_t); /* Write callback */
|
||||
void *pWriteArg; /* First argument to write callback */
|
||||
char **pzOutput; /* Storage location for output string */
|
||||
/* Additional fields may be added in the future */
|
||||
};
|
||||
~~~
|
||||
|
||||
The ResfmtSpec 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.
|
||||
But the application should not try to change or use any fields of
|
||||
the ResfmtSpec 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.
|
||||
|
||||
### 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
|
||||
first argument) to transmit the formatted output. Or, if
|
||||
ResfmtSpec.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.
|
||||
|
||||
Output might be generated row by row, on each call to
|
||||
`sqlite3_resfmt_row()` or it might be written all at once
|
||||
on the final call to `sqlite3_resfmt_finish()`, depending
|
||||
on the output format.
|
||||
|
||||
### 2.3 Output Format
|
||||
|
||||
The ResfmtSpec.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
|
||||
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
|
||||
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.
|
||||
If eEscMode is one, then control characters in the range of U+0001
|
||||
through U+001f are mapped into U+2401 through U+241f, respectively.
|
||||
If eEscMode is 2, then control characters are output directly, with
|
||||
no translation.
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
### 2.7 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.
|
||||
|
||||
### 2.8 The Output Table Name
|
||||
|
||||
The ResfmtSpec.zTableName value is the name of the output table
|
||||
when the MODE_Insert output mode is used.
|
||||
|
||||
### 2.9 Column Widths And Alignments
|
||||
|
||||
The ResfmtSpec.aWidth[] array, if specified, is an array of integers
|
||||
that specify the minimum column width and the alignment for all columns
|
||||
in columnar output modes. Negative values mean right-justify. The
|
||||
absolute value is the minimum of the corresponding column.
|
||||
|
||||
The ResfmtSpec.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.
|
||||
|
||||
## 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
|
||||
the current state of the formatter. The `sqlite3_resfmt_finish()`
|
||||
routine is the destructor for the 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
|
||||
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
|
||||
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.
|
||||
|
||||
The formatter might choose to output some content as each row
|
||||
is processed, or it might accumulate the output and send it all
|
||||
at once when `sqlite3_resfmt_finish()` is called. This is at
|
||||
the discretion of the output formatter. Generally, rows are
|
||||
output one-by-one on each call to `sqlite3_resfmt_row()` when the
|
||||
output format is such that the row can be computed without knowing
|
||||
the value of subsequence, such as in CSV output mode, and
|
||||
the output is accumulated and sent all at once in columnar output
|
||||
modes where the complete output content is needed to compute column
|
||||
widths.
|
||||
|
||||
### 5.0 The `sqlite3_resfmt_finish()` Interface
|
||||
|
||||
Invoke the `sqlite3_resfmt_finish(F,C,E)` interface to finish
|
||||
the formatting. C is an optional pointer to an integer. If C
|
||||
is not a NULL pointer, then any error code associated with the
|
||||
formatting operation is written into *C. E is an optional pointer
|
||||
to a human-readable text error message. If E is not a NULL pointer,
|
||||
then an error message held in memory obtained from sqlite3_malloc()
|
||||
is written into *E. It is the responsibility of the calling
|
||||
application to invoke sqlite3_free() on this error message to
|
||||
reclaim the space.
|
||||
|
||||
### 6.0 Output Modes
|
||||
|
||||
The result formatter supports a variety of output modes. The
|
||||
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 */
|
||||
~~~
|
||||
|
||||
Additional detail about the meaning of each of these output modes
|
||||
is pending.
|
||||
|
||||
### 7.0 Source Code Files
|
||||
|
||||
The SQLite result formatter is implemented in three source code files:
|
||||
|
||||
* `resfmt.c` → The implementation, written in portable C99
|
||||
* `resfmt.h` → A header file defining interfaces
|
||||
* `resfmt.md` → This documentation, in Markdown
|
||||
|
||||
To use the SQLite result formatter, include the "`resfmt.h`" header file
|
||||
and link the application against the "`resfmt.c`" source file.
|
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
||||
C Improve\sthe\sinvariant\schecker\smodule\sso\sthat\sso\sthat\sit\sadded\s"+"\sbefore\n"column\sISNULL"\sin\squeries\swhere\sthe\sbase\squery\scontains\sa\sGROUP\sBY,\sto\nprevent\sthe\sISNULL\sterm\sfrom\sbeing\spushed\sdown\sinto\sthe\ssubquery,\ssince\nthat\scan\scause\sambiguities\sif\scolumn\sis\sUNIQUE.
|
||||
D 2025-10-07T18:06:05.110
|
||||
C Initial\sprototype\sspec\sfor\sthe\sSQLite\sQuery\sResult\sFormatter.
|
||||
D 2025-10-07T20:11:19.383
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -390,6 +390,7 @@ 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 33cf7edf5860e13e0fc17445e6b53e2f2a009f24d20a1d8d653066bfd1af8616
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
|
||||
F ext/misc/series.c cbbec483aa0246661e7656971ce4de8e62ecc3151be94218306206fe4f5b7a9e
|
||||
@@ -2168,8 +2169,11 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 06b4bd2aba22c57f5a5fed606c3bee225dee6fdc13bb16cc58194040ef0d7d85
|
||||
R 453915b0b72d47b5291d37cc0a19ae2f
|
||||
P b4ff920fbeef9a8590219596d73c09976da3da53c08a685be56f6b2cd2cdc70c
|
||||
R 51927445b0466af2ada0962ee88c55c2
|
||||
T *branch * resfmt
|
||||
T *sym-resfmt *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 1eb68a79b24ce28ad8c3cdcce7ce295e
|
||||
Z eb3a746c4a23932f9916a7ae201a8054
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@@ -1,2 +1,2 @@
|
||||
branch trunk
|
||||
tag trunk
|
||||
branch resfmt
|
||||
tag resfmt
|
||||
|
@@ -1 +1 @@
|
||||
b4ff920fbeef9a8590219596d73c09976da3da53c08a685be56f6b2cd2cdc70c
|
||||
87b5e41b999877a1d0b4bb049642909c1698dc1b24e4e45631eb13d02818f0ec
|
||||
|
Reference in New Issue
Block a user