]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
More capabilities being added. Incremental check-in.
authordrh <>
Mon, 20 Oct 2025 19:55:26 +0000 (19:55 +0000)
committerdrh <>
Mon, 20 Oct 2025 19:55:26 +0000 (19:55 +0000)
FossilOrigin-Name: 9adaf791f88875c5afeba7e7aa72efb59df42c6052898f8d7e2f83aede00a044

ext/misc/resfmt-tester.c
ext/misc/resfmt.c
manifest
manifest.uuid

index 79a37372781099392a3d5f4ff1036fbc909ff1bb..28e7e69391725a36bc06fb443dcfe46a74f196c7 100644 (file)
@@ -14,6 +14,7 @@
 */
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 #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]); 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);
     }
   }
index c151c78338c45c1e78b1a54adf432c7a6b4627d8..b7caa1f7e13b9e359585affd5ee634dec0f0ce5a 100644 (file)
@@ -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<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;
     }
@@ -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; 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);
@@ -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;
+}
index e699450caaa032d4a08e7e8d55a8b3224c48326f..bfa718287a393e5f59e083eabd97ba9f91e6778e 100644 (file)
--- 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.
index 640a6fe046cdcea39158ed1f9222ba2f6c62d25e..ac7439330f58cc6ff55c6d62fa5487abc73713fc 100644 (file)
@@ -1 +1 @@
-7aaaeea319c7165284028ff8cf1b3448a818c5029de02e7199614bb45aa304c5
+9adaf791f88875c5afeba7e7aa72efb59df42c6052898f8d7e2f83aede00a044