From: drh <> Date: Mon, 20 Oct 2025 19:55:26 +0000 (+0000) Subject: More capabilities being added. Incremental check-in. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e334ef6169ee1c66c633bb32f8d00df837bfd36;p=thirdparty%2Fsqlite.git More capabilities being added. Incremental check-in. FossilOrigin-Name: 9adaf791f88875c5afeba7e7aa72efb59df42c6052898f8d7e2f83aede00a044 --- diff --git a/ext/misc/resfmt-tester.c b/ext/misc/resfmt-tester.c index 79a3737278..28e7e69391 100644 --- a/ext/misc/resfmt-tester.c +++ b/ext/misc/resfmt-tester.c @@ -14,6 +14,7 @@ */ #include #include +#include #include "sqlite3.h" #include "resfmt.h" @@ -44,7 +45,7 @@ static void tempFreeAll(void){ } /* 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) ); @@ -54,6 +55,19 @@ static void *tempMalloc(unsigned n){ 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); @@ -67,6 +81,7 @@ int main(int argc, char **argv){ sqlite3_stmt *pStmt; int rc; int lineNum = 0; + int bUseWriter = 1; sqlite3_resfmt_spec spec; char zLine[1000]; @@ -83,9 +98,15 @@ int main(int argc, char **argv){ } 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++; @@ -104,38 +125,114 @@ int main(int argc, char **argv){ } }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]) ){ + 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); } } diff --git a/ext/misc/resfmt.c b/ext/misc/resfmt.c index c151c78338..b7caa1f7e1 100644 --- a/ext/misc/resfmt.c +++ b/ext/misc/resfmt.c @@ -41,25 +41,28 @@ static void resfmtFree(sqlite3_resfmt *p){ } /* -** 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; } /* @@ -94,21 +97,26 @@ static void resfmtRenderValue(sqlite3_resfmt *p, int iCol){ 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>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>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; } @@ -118,30 +126,12 @@ static void resfmtRenderValue(sqlite3_resfmt *p, int iCol){ } 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 */ @@ -172,8 +162,8 @@ sqlite3_resfmt *sqlite3_resfmt_begin( 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; } @@ -189,8 +179,21 @@ int sqlite3_resfmt_row(sqlite3_resfmt *p){ 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; inCol; 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; inCol; i++){ if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep); resfmtRenderValue(p, i); @@ -200,5 +203,35 @@ int sqlite3_resfmt_row(sqlite3_resfmt *p){ 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; +} diff --git a/manifest b/manifest index e699450caa..bfa718287a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -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 @@ -389,8 +389,8 @@ 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 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 @@ -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 c38f1c63247804486a6b368ead4c5122adaedd5c697487fadbed49e1acb155bc -R c7be1ef7fe6eb1c112e628cf30c74761 +P 7aaaeea319c7165284028ff8cf1b3448a818c5029de02e7199614bb45aa304c5 +R 93f18f5de015815076ba558bceea8787 U drh -Z 01552c3fb5b64b22ab51e3ac81071bb9 +Z db7581bf692ee1510ff2608fd9941892 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 640a6fe046..ac7439330f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7aaaeea319c7165284028ff8cf1b3448a818c5029de02e7199614bb45aa304c5 +9adaf791f88875c5afeba7e7aa72efb59df42c6052898f8d7e2f83aede00a044