}else
if( strcmp(zLine, "--go")==0 ){
const char *zSql, *zTail;
- sqlite3_resfmt *pFmt;
- int iErr = 0;
char *zErr = 0;
int n;
if( db==0 ){
spec.pzOutput = &zOut;
spec.xWrite = 0;
}
- pFmt = sqlite3_resfmt_begin(pStmt, &spec);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- sqlite3_resfmt_row(pFmt);
- }
- rc = sqlite3_resfmt_finish(pFmt, &iErr, &zErr);
- if( !bUseWriter && zOut ){
- fputs(zOut, stdout);
- sqlite3_free(zOut);
+ rc = sqlite3_format_query_result(pStmt, &spec, &zErr);
+ if( rc!=SQLITE_OK ){
+ fprintf(stderr, "%s:%d: Error %d: %s\n", zSrc, lineNum,
+ rc, zErr);
+ }else{
+ if( !bUseWriter && zOut ){
+ fputs(zOut, stdout);
+ sqlite3_free(zOut);
+ }
}
- printf("/* rc=%d. error-code=%d. error-message=%s */\n",
- rc, iErr, zErr ? zErr : "NULL");
sqlite3_free(zErr);
}
sqlite3_finalize(pStmt);
{ "box", RESFMT_Box, },
{ "column", RESFMT_Column, },
{ "count", RESFMT_Count, },
- { "csv", RESFMT_Csv, },
{ "eqp", RESFMT_EQP, },
{ "explain", RESFMT_Explain, },
{ "html", RESFMT_Html, },
{ "list", RESFMT_List, },
{ "markdown", RESFMT_Markdown, },
{ "off", RESFMT_Off, },
- { "pretty", RESFMT_Pretty, },
{ "table", RESFMT_Table, },
- { "tcl", RESFMT_Tcl, },
{ "scanexp", RESFMT_ScanExp, },
};
int i;
** Private state information. Subject to change from one release to the
** next.
*/
+typedef struct sqlite3_resfmt sqlite3_resfmt;
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 */
+ char **pzErr; /* Write error message here, if not NULL */
sqlite3_str *pOut; /* Accumulated output */
int iErr; /* Error code */
int nCol; /* Number of output columns */
sqlite3_resfmt_spec spec; /* Copy of the original spec */
};
+/*
+** Set an error code and error message.
+*/
+static void resfmtError(
+ sqlite3_resfmt *p, /* Query result state */
+ int iCode, /* Error code */
+ const char *zFormat, /* Message format (or NULL) */
+ ...
+){
+ p->iErr = iCode;
+ if( p->pzErr!=0 ){
+ sqlite3_free(*p->pzErr);
+ *p->pzErr = 0;
+ if( zFormat ){
+ va_list ap;
+ va_start(ap, zFormat);
+ *p->pzErr = sqlite3_mprintf(zFormat, ap);
+ va_end(ap);
+ }
+ }
+}
/*
-** Free memory associated with pResfmt
+** Out-of-memory error.
*/
-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);
+static void resfmtOom(sqlite3_resfmt *p){
+ resfmtError(p, SQLITE_NOMEM, "out of memory");
}
/*
}
/*
-** Create a new rendering object
+** Initialize the internal sqlite3_resfmt object.
*/
-sqlite3_resfmt *sqlite3_resfmt_begin(
- sqlite3_stmt *pStmt,
- sqlite3_resfmt_spec *pSpec
+static void resfmtInitialize(
+ sqlite3_resfmt *p, /* State object to be initialized */
+ sqlite3_stmt *pStmt, /* Query whose output to be formatted */
+ const sqlite3_resfmt_spec *pSpec, /* Format specification */
+ char **pzErr /* Write errors here */
){
- 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;
+ memset(p, 0, sizeof(*p));
+ p->pzErr = pzErr;
+ if( pSpec->iVersion!=1 ){
+ resfmtError(p, SQLITE_ERROR,
+ "unusable sqlite3_resfmt_spec.iVersion (%d)",
+ pSpec->iVersion);
+ return;
+ }
p->pStmt = pStmt;
p->db = sqlite3_db_handle(pStmt);
- p->pErr = 0;
p->pOut = sqlite3_str_new(p->db);
if( p->pOut==0 ){
- resfmtFree(p);
- return 0;
+ resfmtOom(p);
+ return;
}
p->iErr = 0;
p->nCol = sqlite3_column_count(p->pStmt);
break;
}
}
- return p;
}
/*
** Render a single row of output.
*/
-int sqlite3_resfmt_row(sqlite3_resfmt *p){
- int rc = SQLITE_OK;
+static void resfmtDoOneRow(sqlite3_resfmt *p){
int i;
- if( p==0 ) return SQLITE_DONE;
switch( p->spec.eFormat ){
case RESFMT_Off:
case RESFMT_Count: {
}
}
p->nRow++;
- return rc;
}
/*
** Finish rendering the results
*/
-int sqlite3_resfmt_finish(sqlite3_resfmt *p, int *piErr, char **pzErrMsg){
- if( p==0 ){
- return SQLITE_OK;
- }
+static void resfmtFinalize(sqlite3_resfmt *p){
switch( p->spec.eFormat ){
case RESFMT_Count: {
sqlite3_str_appendf(p->pOut, "%lld\n", p->nRow);
}
if( p->spec.pzOutput ){
*p->spec.pzOutput = sqlite3_str_finish(p->pOut);
- p->pOut = 0;
+ }else if( p->pOut ){
+ sqlite3_free(sqlite3_str_finish(p->pOut));
}
- if( piErr ){
- *piErr = p->iErr;
+}
+
+/*
+** Run the prepared statement pStmt and format the results according
+** to the specification provided in pSpec. Return an error code.
+** If pzErr is not NULL and if an error occurs, write an error message
+** into *pzErr.
+*/
+int sqlite3_format_query_result(
+ sqlite3_stmt *pStmt, /* Statement to evaluate */
+ const sqlite3_resfmt_spec *pSpec, /* Format specification */
+ char **pzErr /* Write error message here */
+){
+ sqlite3_resfmt fmt; /* The new sqlite3_resfmt being created */
+
+ if( pStmt==0 ) return SQLITE_OK; /* No-op */
+ if( pSpec==0 ) return SQLITE_MISUSE;
+ resfmtInitialize(&fmt, pStmt, pSpec, pzErr);
+ while( fmt.iErr==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
+ resfmtDoOneRow(&fmt);
}
- if( pzErrMsg ){
- *pzErrMsg = sqlite3_str_finish(p->pErr);
- p->pErr = 0;
+ if( fmt.iErr==SQLITE_OK ){
+ int rc = sqlite3_reset(fmt.pStmt);
+ if( rc!=SQLITE_OK ){
+ resfmtError(&fmt, rc, "%s", sqlite3_errmsg(fmt.db));
+ }
}
- resfmtFree(p);
- return SQLITE_OK;
+ resfmtFinalize(&fmt);
+ return fmt.iErr;
}
*/
typedef struct sqlite3_resfmt_spec sqlite3_resfmt_spec;
struct sqlite3_resfmt_spec {
- short int iVersion; /* Version number of this structure */
+ unsigned char iVersion; /* Version number of this structure */
unsigned char eFormat; /* Output format */
unsigned char bShowCNames; /* True to show column names */
unsigned char eEscape; /* How to deal with control characters */
unsigned char eQuote; /* Quoting style for text */
unsigned char eBlob; /* Quoting style for BLOBs */
unsigned char bWordWrap; /* Try to wrap on word boundaries */
- short int mxWidth; /* Maximum column width in columnar modes */
+ short int mxWidth; /* Maximum width of any column */
int nWidth; /* Number of column width parameters */
short int *aWidth; /* Column widths */
const char *zColumnSep; /* Alternative column separator */
/* 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**);
+int sqlite3_format_query_result(
+ sqlite3_stmt *pStmt, /* SQL statement to run */
+ const sqlite3_resfmt_spec *pSpec, /* Result format specification */
+ char **pzErr /* OUT: Write error message here */
+);
/*
** Output styles:
#define RESFMT_List 0 /* One record per line with a separator */
#define RESFMT_Line 1 /* One column per line. */
#define RESFMT_Html 2 /* Generate an XHTML table */
-#define RESFMT_Insert 3 /* Generate SQL "insert" statements */
-#define RESFMT_Explain 4 /* EXPLAIN output */
-#define RESFMT_ScanExp 5 /* EXPLAIN output with vm stats */
-#define RESFMT_EQP 6 /* Converts EXPLAIN QUERY PLAN output into a graph */
-#define RESFMT_Markdown 7 /* Markdown formatting */
-#define RESFMT_Column 8 /* One record per line in neat columns */
-#define RESFMT_Table 9 /* MySQL-style table formatting */
-#define RESFMT_Box 10 /* Unicode box-drawing characters */
-#define RESFMT_Count 11 /* Output only a count of the rows of output */
-#define RESFMT_Off 12 /* No query output shown */
+#define RESFMT_Json 3 /* Output is a list of JSON objects */
+#define RESFMT_Insert 4 /* Generate SQL "insert" statements */
+#define RESFMT_Explain 5 /* EXPLAIN output */
+#define RESFMT_ScanExp 6 /* EXPLAIN output with vm stats */
+#define RESFMT_EQP 7 /* Converts EXPLAIN QUERY PLAN output into a graph */
+#define RESFMT_Markdown 8 /* Markdown formatting */
+#define RESFMT_Column 9 /* One record per line in neat columns */
+#define RESFMT_Table 10 /* MySQL-style table formatting */
+#define RESFMT_Box 11 /* Unicode box-drawing characters */
+#define RESFMT_Count 12 /* Output only a count of the rows of output */
+#define RESFMT_Off 13 /* No query output shown */
/*
** Quoting styles for text.
-C Simplify\sthe\sset\sof\sformatting\schoices.
-D 2025-10-21T20:10:44.822
+C Simplify\sthe\sinterface\sto\suse\sjust\sa\ssingle\sAPI.
+D 2025-10-22T12:09:50.023
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
F ext/misc/regexp.c 548151f3e57506fda678e6a65e85a763f4eece653287e1ad44e167f9485e0c6b
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
-F ext/misc/resfmt-tester.c 64b799da88145f7bd1b70635ffc629b2058dfa31e33d04c266ebeae36d1381a0
-F ext/misc/resfmt.c aedb80cf3eae75d85457b116c840c7a834aef867ae4efa1b45926656f13d4c4d
-F ext/misc/resfmt.h 35b86324479f51ac0a5a2e39ffb7ca0ca4663667b2892583a393c8a8fc6c6264
+F ext/misc/resfmt-tester.c 3188324e10f945429fd684c1d1a468a1bde43e1379af60f0d34c5411a04b0edc
+F ext/misc/resfmt.c 86c6e1a4e77a64423de38942fcbc1c07ba052b405be3550f1e72980173e0d7f1
+F ext/misc/resfmt.h ebb635f87324499a1487cdad812f64ab9f98a1b09accf0ba45fea0e274e2bd3b
F ext/misc/resfmt.md 6f6cefd95fa11ce30e4f34ea84052e7a8291dd48b7e666352bd7cf2e22c22ec4
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 1a28eae74ed354d556f5ba45c716b03ff36d26b8a6729a5428d7895d8337af78
-R 6892d861551a00de62fd7fcb651f12e2
+P 1f364ea3c08badd555a9ce70bb96cb8f862d6cc6425e9ff41da228fdd2f29361
+R e9ac91203f0abef1ee5b35000bb54fe9
U drh
-Z 7c407302cce92000d1b62ee6c390d8da
+Z 7963d538858020e5fc3e5fc1a9ddc9f8
# Remove this line to create a well-formed Fossil manifest.
-1f364ea3c08badd555a9ce70bb96cb8f862d6cc6425e9ff41da228fdd2f29361
+82dc13ec4887f90995bd984ede9c2670fb7512962ccceb1848a7e9aab7891c00