*/
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include "sqlite3.h"
#include "resfmt.h"
}
/* Allocate memory that will be freed all at once by freeall() */
-static void *tempMalloc(unsigned n){
+static void *tempMalloc(size_t n){
memblock *p;
if( n>0x10000000 ) checkOOM(0);
p = sqlite3_malloc64( n+sizeof(memblock) );
return (void*)&pToFree[1];
}
+/* Make a copy of a string using tempMalloc() */
+static char *tempStrdup(char *zIn){
+ size_t n;
+ char *z;
+ if( zIn==0 ) zIn = "";
+ n = strlen(zIn);
+ if( n>0x10000000 ) checkOOM(0);
+ z = tempMalloc( n+1 );
+ checkOOM(z);
+ memcpy(z, zIn, n+1);
+ return z;
+}
+
/* Function used for writing to the console */
ssize_t testWriter(void *pContext, const unsigned char *p, size_t n){
return fwrite(p,1,n,stdout);
sqlite3_stmt *pStmt;
int rc;
int lineNum = 0;
+ int bUseWriter = 1;
sqlite3_resfmt_spec spec;
char zLine[1000];
}
memset(&spec, 0, sizeof(spec));
spec.iVersion = 1;
- spec.eFormat = RESFMT_Line;
+ spec.eFormat = RESFMT_List;
spec.xWrite = testWriter;
pBuf = sqlite3_str_new(0);
+ rc = sqlite3_open(":memory:", &db);
+ if( rc ){
+ fprintf(stderr, "unable to open an in-memory database: %s\n",
+ sqlite3_errmsg(db));
+ exit(1);
+ }
while( fgets(zLine, sizeof(zLine), pSrc) ){
size_t n = strlen(zLine);
lineNum++;
}
}else
if( strcmp(zLine, "--go")==0 ){
- char *zSql;
+ const char *zSql, *zTail;
sqlite3_resfmt *pFmt;
int iErr = 0;
char *zErr = 0;
+ int n;
if( db==0 ){
fprintf(stderr, "%s:%d: database not open\n", zSrc, lineNum);
exit(1);
}
zSql = sqlite3_str_value(pBuf);
pStmt = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc || pStmt==0 ){
- fprintf(stderr, "%s:%d: sqlite3_prepare() fails: %s\n",
- zSrc, lineNum, sqlite3_errmsg(db));
- }
- pFmt = sqlite3_resfmt_begin(pStmt, &spec);
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- sqlite3_resfmt_row(pFmt);
+ while( zSql[0] ){
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zTail);
+ if( rc || pStmt==0 ){
+ fprintf(stderr, "%s:%d: sqlite3_prepare() fails: %s\n",
+ zSrc, lineNum, sqlite3_errmsg(db));
+ sqlite3_finalize(pStmt);
+ break;
+ }
+ zSql = sqlite3_sql(pStmt);
+ while( isspace(zSql[0]) ) zSql++;
+ n = (int)strlen(zSql);
+ while( n>0 && isspace(zSql[n-1]) ) n--;
+ if( n>0 ){
+ char *zOut = 0;
+ printf("/* %.*s */\n", n, zSql);
+ if( bUseWriter ){
+ spec.pzOutput = 0;
+ spec.xWrite = testWriter;
+ }else{
+ 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);
+ }
+ printf("/* rc=%d. error-code=%d. error-message=%s */\n",
+ rc, iErr, zErr ? zErr : "NULL");
+ sqlite3_free(zErr);
+ }
+ sqlite3_finalize(pStmt);
+ pStmt = 0;
+ zSql = zTail;
}
- rc = sqlite3_resfmt_finish(pFmt, &iErr, &zErr);
- printf("rc=%d. error-code=%d. error-message=%s\n",
- rc, iErr, zErr ? zErr : "NULL");
- sqlite3_free(zErr);
- sqlite3_finalize(pStmt);
- pStmt = 0;
sqlite3_str_reset(pBuf);
}else
+ if( strncmp(zLine, "--eFormat=", 10)==0 ){
+ const struct { const char *zFmt; int eMode; } aFmt[] = {
+ { "line", RESFMT_Line, },
+ { "column", RESFMT_Column, },
+ { "list", RESFMT_List, },
+ { "html", RESFMT_Html, },
+ { "insert", RESFMT_Insert, },
+ { "tcl", RESFMT_Tcl, },
+ { "csv", RESFMT_Csv, },
+ { "explain", RESFMT_Explain, },
+ { "pretty", RESFMT_Pretty, },
+ { "eqp", RESFMT_EQP, },
+ { "json", RESFMT_Json, },
+ { "markdown", RESFMT_Markdown, },
+ { "table", RESFMT_Table, },
+ { "box", RESFMT_Box, },
+ { "count", RESFMT_Count, },
+ { "off", RESFMT_Off, },
+ { "scanexp", RESFMT_ScanExp, },
+ { "www", RESFMT_Www, },
+ };
+ int i;
+ for(i=0; i<sizeof(aFmt)/sizeof(aFmt[0]); i++){
+ if( strcmp(aFmt[i].zFmt,&zLine[10])==0 ){
+ spec.eFormat = aFmt[i].eMode;
+ break;
+ }
+ }
+ if( i>=sizeof(aFmt)/sizeof(aFmt[0]) ){
+ fprintf(stderr, "%s:%d: no such format: \"%s\"\n",
+ zSrc, lineNum, &zLine[10]);
+ }
+ }else
+ if( strncmp(zLine, "--bQuote=", 9)==0 ){
+ spec.bQuote = atoi(&zLine[9])!=0;
+ }else
+ if( strncmp(zLine, "--bShowCNames=", 14)==0 ){
+ spec.bShowCNames = atoi(&zLine[14])!=0;
+ }else
+ if( strncmp(zLine, "--zNull=", 8)==0 ){
+ spec.zNull = tempStrdup(&zLine[8]);
+ }else
+ if( strncmp(zLine, "--zColumnSep=", 13)==0 ){
+ spec.zColumnSep = tempStrdup(&zLine[13]);
+ }else
+ if( strncmp(zLine, "--zRowSep=", 10)==0 ){
+ spec.zRowSep = tempStrdup(&zLine[10]);
+ }else
if( strcmp(zLine, "--exit")==0 ){
break;
}else
+ if( strncmp(zLine, "--use-writer=",13)==0 ){
+ bUseWriter = atoi(&zLine[13])!=0;
+ }else
{
- if( sqlite3_str_length(pBuf) ) sqlite3_str_appendchar(pBuf, ' ', 1);
+ if( sqlite3_str_length(pBuf) ) sqlite3_str_append(pBuf, "\n", 1);
sqlite3_str_appendall(pBuf, zLine);
}
}
}
/*
-** Finish rendering the results
+** If xWrite is defined, send all content of pOut to xWrite and
+** reset pOut.
*/
-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;
+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);
}
- if( pzErrMsg ){
- *pzErrMsg = sqlite3_str_finish(p->pErr);
- p->pErr = 0;
+}
+
+/*
+** Encode text appropriately and append it to p->pOut.
+*/
+static void resfmtEncodeText(sqlite3_resfmt *p, const char *zTxt){
+ if( p->spec.bQuote ){
+ sqlite3_str_appendf(p->pOut, "%Q", zTxt);
+ }else{
+ sqlite3_str_appendall(p->pOut, zTxt);
}
- resfmtFree(p);
- return SQLITE_OK;
}
/*
break;
}
case SQLITE_BLOB: {
- int iStart = sqlite3_str_length(p->pOut);
- int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
- int i, j;
- char *zVal;
- const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol);
- 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];
+ if( p->spec.bQuote ){
+ int iStart = sqlite3_str_length(p->pOut);
+ int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
+ int i, j;
+ char *zVal;
+ const unsigned char *a = sqlite3_column_blob(p->pStmt,iCol);
+ 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];
+ }
+ }else{
+ const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
+ sqlite3_str_appendall(p->pOut, zTxt);
}
break;
}
}
case SQLITE_TEXT: {
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
- if( p->spec.bQuote ){
- sqlite3_str_appendf(p->pOut, "%Q", zTxt);
- }else{
- sqlite3_str_appendall(p->pOut, zTxt);
- }
+ resfmtEncodeText(p, zTxt);
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
*/
memcpy(&p->spec, pSpec, sz);
if( p->spec.zNull==0 ) p->spec.zNull = "";
switch( p->spec.eFormat ){
- case RESFMT_Line: {
- if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = ",";
+ case RESFMT_List: {
+ if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = "|";
if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n";
break;
}
int i;
if( p==0 ) return SQLITE_DONE;
switch( p->spec.eFormat ){
+ case RESFMT_Off:
+ case RESFMT_Count: {
+ /* No-op */
+ break;
+ }
default: { /* RESFMT_List */
- sqlite3_str_reset(p->pOut);
+ if( p->nRow==0 && p->spec.bShowCNames ){
+ for(i=0; i<p->nCol; i++){
+ const char *zCName = sqlite3_column_name(p->pStmt, i);
+ if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
+ resfmtEncodeText(p, zCName);
+ }
+ sqlite3_str_appendall(p->pOut, p->spec.zRowSep);
+ resfmtWrite(p);
+ }
for(i=0; i<p->nCol; i++){
if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
resfmtRenderValue(p, i);
break;
}
}
+ 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;
+ }
+ switch( p->spec.eFormat ){
+ case RESFMT_Count: {
+ sqlite3_str_appendf(p->pOut, "%lld\n", p->nRow);
+ resfmtWrite(p);
+ break;
+ }
+ }
+ 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;
+}
-C Add\stest\sprogram\sfor\sresfmt.c.\s\sNow\scompiles\sand\sruns.
-D 2025-10-20T17:19:30.111
+C More\scapabilities\sbeing\sadded.\s\sIncremental\scheck-in.
+D 2025-10-20T19:55:26.972
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 51149ed2da237e5b927c1379cb6d5b9189191f60f4237d2bd5183a33a2b30776
-F ext/misc/resfmt.c 3c82b41fa33a3b05a60fb43e96c3b3926edda1eb45a3432e94b30d769d094cc1
+F ext/misc/resfmt-tester.c a657a79ce49ea6b39294d8684a9972c8b5824a7d9d51a08e5166c29e08a2dd70
+F ext/misc/resfmt.c a634719bdc83cbe8f732d6dbbdafd3a73060a8aa45a4fdfe55ecc93530bc2e5a
F ext/misc/resfmt.h 2cb13016806263897e4aad0689f26f07eb8b5b26619d09f07af5c64be3041f4b
F ext/misc/resfmt.md 6f6cefd95fa11ce30e4f34ea84052e7a8291dd48b7e666352bd7cf2e22c22ec4
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P c38f1c63247804486a6b368ead4c5122adaedd5c697487fadbed49e1acb155bc
-R c7be1ef7fe6eb1c112e628cf30c74761
+P 7aaaeea319c7165284028ff8cf1b3448a818c5029de02e7199614bb45aa304c5
+R 93f18f5de015815076ba558bceea8787
U drh
-Z 01552c3fb5b64b22ab51e3ac81071bb9
+Z db7581bf692ee1510ff2608fd9941892
# Remove this line to create a well-formed Fossil manifest.