From: drh <> Date: Wed, 22 Oct 2025 12:09:50 +0000 (+0000) Subject: Simplify the interface to use just a single API. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=22f8a84fda8e9d099ac6332fc59de03cfe7030a7;p=thirdparty%2Fsqlite.git Simplify the interface to use just a single API. FossilOrigin-Name: 82dc13ec4887f90995bd984ede9c2670fb7512962ccceb1848a7e9aab7891c00 --- diff --git a/ext/misc/resfmt-tester.c b/ext/misc/resfmt-tester.c index cd7ccd7525..e0d159117f 100644 --- a/ext/misc/resfmt-tester.c +++ b/ext/misc/resfmt-tester.c @@ -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_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); @@ -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; diff --git a/ext/misc/resfmt.c b/ext/misc/resfmt.c index 1bbbce2dcd..0ac046271d 100644 --- a/ext/misc/resfmt.c +++ b/ext/misc/resfmt.c @@ -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; +} + +/* +** 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; } diff --git a/ext/misc/resfmt.h b/ext/misc/resfmt.h index c13c077e84..ab8f0accf2 100644 --- a/ext/misc/resfmt.h +++ b/ext/misc/resfmt.h @@ -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. diff --git a/manifest b/manifest index aabdd8d3c9..a1e3b26423 100644 --- a/manifest +++ b/manifest @@ -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. diff --git a/manifest.uuid b/manifest.uuid index f8322532f6..c8b8c4c146 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f364ea3c08badd555a9ce70bb96cb8f862d6cc6425e9ff41da228fdd2f29361 +82dc13ec4887f90995bd984ede9c2670fb7512962ccceb1848a7e9aab7891c00