1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-25 20:58:26 +03:00

Simplify the interface to use just a single API.

FossilOrigin-Name: 82dc13ec4887f90995bd984ede9c2670fb7512962ccceb1848a7e9aab7891c00
This commit is contained in:
drh
2025-10-22 12:09:50 +00:00
parent ce3d809d62
commit 22f8a84fda
5 changed files with 111 additions and 83 deletions

View File

@@ -134,8 +134,6 @@ int main(int argc, char **argv){
}else
if( strcmp(zLine, "--go")==0 ){
const char *zSql, *zTail;
sqlite3_resfmt *pFmt;
int iErr = 0;
char *zErr = 0;
int n;
if( db==0 ){
@@ -166,17 +164,16 @@ int main(int argc, char **argv){
spec.pzOutput = &zOut;
spec.xWrite = 0;
}
pFmt = sqlite3_resfmt_begin(pStmt, &spec);
while( sqlite3_step(pStmt)==SQLITE_ROW ){
sqlite3_resfmt_row(pFmt);
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);
}
}
rc = sqlite3_resfmt_finish(pFmt, &iErr, &zErr);
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);
@@ -190,7 +187,6 @@ int main(int argc, char **argv){
{ "box", RESFMT_Box, },
{ "column", RESFMT_Column, },
{ "count", RESFMT_Count, },
{ "csv", RESFMT_Csv, },
{ "eqp", RESFMT_EQP, },
{ "explain", RESFMT_Explain, },
{ "html", RESFMT_Html, },
@@ -200,9 +196,7 @@ int main(int argc, char **argv){
{ "list", RESFMT_List, },
{ "markdown", RESFMT_Markdown, },
{ "off", RESFMT_Off, },
{ "pretty", RESFMT_Pretty, },
{ "table", RESFMT_Table, },
{ "tcl", RESFMT_Tcl, },
{ "scanexp", RESFMT_ScanExp, },
};
int i;

View File

@@ -19,10 +19,11 @@
** 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 */
@@ -30,14 +31,33 @@ struct sqlite3_resfmt {
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");
}
/*
@@ -361,27 +381,29 @@ static void resfmtRenderValue(sqlite3_resfmt *p, int iCol){
}
/*
** 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);
@@ -405,16 +427,13 @@ sqlite3_resfmt *sqlite3_resfmt_begin(
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: {
@@ -441,16 +460,12 @@ int sqlite3_resfmt_row(sqlite3_resfmt *p){
}
}
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);
@@ -460,15 +475,36 @@ int sqlite3_resfmt_finish(sqlite3_resfmt *p, int *piErr, char **pzErrMsg){
}
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;
}
if( pzErrMsg ){
*pzErrMsg = sqlite3_str_finish(p->pErr);
p->pErr = 0;
}
resfmtFree(p);
return SQLITE_OK;
}
/*
** 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( fmt.iErr==SQLITE_OK ){
int rc = sqlite3_reset(fmt.pStmt);
if( rc!=SQLITE_OK ){
resfmtError(&fmt, rc, "%s", sqlite3_errmsg(fmt.db));
}
}
resfmtFinalize(&fmt);
return fmt.iErr;
}

View File

@@ -20,14 +20,14 @@
*/
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 */
@@ -43,17 +43,14 @@ struct sqlite3_resfmt_spec {
/* 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:
@@ -61,16 +58,17 @@ int sqlite3_resfmt_finish(sqlite3_resfmt*,int*,char**);
#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.

View File

@@ -1,5 +1,5 @@
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
@@ -389,9 +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-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
@@ -2175,8 +2175,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 1a28eae74ed354d556f5ba45c716b03ff36d26b8a6729a5428d7895d8337af78
R 6892d861551a00de62fd7fcb651f12e2
P 1f364ea3c08badd555a9ce70bb96cb8f862d6cc6425e9ff41da228fdd2f29361
R e9ac91203f0abef1ee5b35000bb54fe9
U drh
Z 7c407302cce92000d1b62ee6c390d8da
Z 7963d538858020e5fc3e5fc1a9ddc9f8
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
1f364ea3c08badd555a9ce70bb96cb8f862d6cc6425e9ff41da228fdd2f29361
82dc13ec4887f90995bd984ede9c2670fb7512962ccceb1848a7e9aab7891c00