Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Jun 2022 14:12:15 GMT
From:      Cy Schubert <cy@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: dc61e35a09f4 - stable/12 - sqlite3: Vendor import of sqlite3 3.38.5
Message-ID:  <202206121412.25CECFcf048459@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/12 has been updated by cy:

URL: https://cgit.FreeBSD.org/src/commit/?id=dc61e35a09f418dc1a55193acdc76992ab6a52d0

commit dc61e35a09f418dc1a55193acdc76992ab6a52d0
Author:     Cy Schubert <cy@FreeBSD.org>
AuthorDate: 2022-05-12 19:25:36 +0000
Commit:     Cy Schubert <cy@FreeBSD.org>
CommitDate: 2022-06-12 14:09:22 +0000

    sqlite3: Vendor import of sqlite3 3.38.5
    
    Changes at https://www.sqlite.org/releaselog/3_38_5.html.
    
    Obtained from https://www.sqlite.org/2022/sqlite-autoconf-3380500.tar.gz.
    
    Merge commit 'b562e59e27efbea397bdc8782dfceaa3c0e23542'
    
    (cherry picked from commit 4fe1295c964fa712dd763e3852187da8724ef79a)
---
 contrib/sqlite3/Makefile.msc             |    9 +-
 contrib/sqlite3/README.txt               |    2 +-
 contrib/sqlite3/configure                |   44 +-
 contrib/sqlite3/configure.ac             |   17 +-
 contrib/sqlite3/shell.c                  | 1178 +++-
 contrib/sqlite3/sqlite3.c                | 9796 ++++++++++++++++++------------
 contrib/sqlite3/sqlite3.h                |  380 +-
 contrib/sqlite3/sqlite3ext.h             |   14 +
 contrib/sqlite3/sqlite3rc.h              |    2 +-
 contrib/sqlite3/tea/configure            |   18 +-
 contrib/sqlite3/tea/configure.ac         |    2 +-
 contrib/sqlite3/tea/generic/tclsqlite3.c |   48 +-
 12 files changed, 7212 insertions(+), 4298 deletions(-)

diff --git a/contrib/sqlite3/Makefile.msc b/contrib/sqlite3/Makefile.msc
index 40d0e8113da0..e36eb21ea004 100644
--- a/contrib/sqlite3/Makefile.msc
+++ b/contrib/sqlite3/Makefile.msc
@@ -285,7 +285,6 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
@@ -502,12 +501,12 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
 #
 !IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
 !IF "$(PLATFORM)"=="x86"
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
 !ELSE
 !IFNDEF PLATFORM
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
 !ELSE
 CORE_CCONV_OPTS =
 SHELL_CCONV_OPTS =
diff --git a/contrib/sqlite3/README.txt b/contrib/sqlite3/README.txt
index 6e62a4e13854..ccf5e235ac93 100644
--- a/contrib/sqlite3/README.txt
+++ b/contrib/sqlite3/README.txt
@@ -105,7 +105,7 @@ may be specified in this manner as some require the amalgamation to be built
 with them enabled (see http://www.sqlite.org/compile.html). For example, the
 following will work:
 
-  "OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1"
+  "OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_OMIT_JSON=1"
 
 However, the following will not compile unless the amalgamation was built
 with it enabled:
diff --git a/contrib/sqlite3/configure b/contrib/sqlite3/configure
index 6747c0174ee3..5a5a81e27424 100755
--- a/contrib/sqlite3/configure
+++ b/contrib/sqlite3/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sqlite 3.37.2.
+# Generated by GNU Autoconf 2.69 for sqlite 3.38.5.
 #
 # Report bugs to <http://www.sqlite.org>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='sqlite'
 PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.37.2'
-PACKAGE_STRING='sqlite 3.37.2'
+PACKAGE_VERSION='3.38.5'
+PACKAGE_STRING='sqlite 3.38.5'
 PACKAGE_BUGREPORT='http://www.sqlite.org'
 PACKAGE_URL=''
 
@@ -776,7 +776,6 @@ enable_math
 enable_fts4
 enable_fts3
 enable_fts5
-enable_json1
 enable_rtree
 enable_session
 enable_debug
@@ -1342,7 +1341,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures sqlite 3.37.2 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.38.5 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1413,7 +1412,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of sqlite 3.37.2:";;
+     short | recursive ) echo "Configuration of sqlite 3.38.5:";;
    esac
   cat <<\_ACEOF
 
@@ -1442,7 +1441,6 @@ Optional Features:
   --enable-fts4           include fts4 support [default=yes]
   --enable-fts3           include fts3 support [default=no]
   --enable-fts5           include fts5 support [default=yes]
-  --enable-json1          include json1 support [default=yes]
   --enable-rtree          include rtree support [default=yes]
   --enable-session        enable the session extension [default=no]
   --enable-debug          build with debugging features enabled [default=no]
@@ -1539,7 +1537,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-sqlite configure 3.37.2
+sqlite configure 3.38.5
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1954,7 +1952,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by sqlite $as_me 3.37.2, which was
+It was created by sqlite $as_me 3.38.5, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2820,7 +2818,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='sqlite'
- VERSION='3.37.2'
+ VERSION='3.38.5'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -13730,28 +13728,6 @@ $as_echo "disabled" >&6; }
 fi
 #-----------------------------------------------------------------------
 
-#-----------------------------------------------------------------------
-#   --enable-json1
-#
-# Check whether --enable-json1 was given.
-if test "${enable_json1+set}" = set; then :
-  enableval=$enable_json1;
-else
-  enable_json1=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking JSON functions" >&5
-$as_echo_n "checking JSON functions... " >&6; }
-if test x"$enable_json1" = "xyes"; then
-  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
-$as_echo "enabled" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
-$as_echo "disabled" >&6; }
-fi
-#-----------------------------------------------------------------------
-
 #-----------------------------------------------------------------------
 #   --enable-rtree
 #
@@ -14569,7 +14545,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by sqlite $as_me 3.37.2, which was
+This file was extended by sqlite $as_me 3.38.5, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -14626,7 +14602,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-sqlite config.status 3.37.2
+sqlite config.status 3.38.5
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/contrib/sqlite3/configure.ac b/contrib/sqlite3/configure.ac
index 24097b2875f0..ee29e787b2fa 100644
--- a/contrib/sqlite3/configure.ac
+++ b/contrib/sqlite3/configure.ac
@@ -10,7 +10,7 @@
 #
 
 AC_PREREQ(2.61)
-AC_INIT(sqlite, 3.37.2, http://www.sqlite.org)
+AC_INIT(sqlite, 3.38.5, http://www.sqlite.org)
 AC_CONFIG_SRCDIR([sqlite3.c])
 AC_CONFIG_AUX_DIR([.])
 
@@ -173,21 +173,6 @@ else
 fi
 #-----------------------------------------------------------------------
 
-#-----------------------------------------------------------------------
-#   --enable-json1
-#
-AC_ARG_ENABLE(json1, [AS_HELP_STRING(
-  [--enable-json1], [include json1 support [default=yes]])], 
-  [],[enable_json1=yes])
-AC_MSG_CHECKING([JSON functions])
-if test x"$enable_json1" = "xyes"; then
-  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1"
-  AC_MSG_RESULT([enabled])
-else
-  AC_MSG_RESULT([disabled])
-fi
-#-----------------------------------------------------------------------
-
 #-----------------------------------------------------------------------
 #   --enable-rtree
 #
diff --git a/contrib/sqlite3/shell.c b/contrib/sqlite3/shell.c
index 26c0ae57174f..d10476832e97 100644
--- a/contrib/sqlite3/shell.c
+++ b/contrib/sqlite3/shell.c
@@ -41,10 +41,10 @@
 ** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
 ** file. Note that this macro has a like effect on sqlite3.c compilation.
 */
+# define SHELL_STRINGIFY_(f) #f
+# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
 #ifdef SQLITE_CUSTOM_INCLUDE
-# define INC_STRINGIFY_(f) #f
-# define INC_STRINGIFY(f) INC_STRINGIFY_(f)
-# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
+# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
 #endif
 
 /*
@@ -445,15 +445,6 @@ static sqlite3 *globalDb = 0;
 */
 static volatile int seenInterrupt = 0;
 
-#ifdef SQLITE_DEBUG
-/*
-** Out-of-memory simulator variables
-*/
-static unsigned int oomCounter = 0;    /* Simulate OOM when equals 1 */
-static unsigned int oomRepeat = 0;     /* Number of OOMs in a row */
-static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */
-#endif /* SQLITE_DEBUG */
-
 /*
 ** This is the name of our program. It is set in main(), used
 ** in a number of other places, mostly for error messages.
@@ -505,48 +496,12 @@ static void shell_out_of_memory(void){
   exit(1);
 }
 
-#ifdef SQLITE_DEBUG
-/* This routine is called when a simulated OOM occurs.  It is broken
-** out as a separate routine to make it easy to set a breakpoint on
-** the OOM
+/* Check a pointer to see if it is NULL.  If it is NULL, exit with an
+** out-of-memory error.
 */
-void shellOomFault(void){
-  if( oomRepeat>0 ){
-    oomRepeat--;
-  }else{
-    oomCounter--;
-  }
+static void shell_check_oom(void *p){
+  if( p==0 ) shell_out_of_memory();
 }
-#endif /* SQLITE_DEBUG */
-
-#ifdef SQLITE_DEBUG
-/* This routine is a replacement malloc() that is used to simulate
-** Out-Of-Memory (OOM) errors for testing purposes.
-*/
-static void *oomMalloc(int nByte){
-  if( oomCounter ){
-    if( oomCounter==1 ){
-      shellOomFault();
-      return 0;
-    }else{
-      oomCounter--;
-    }
-  }
-  return defaultMalloc(nByte);
-}
-#endif /* SQLITE_DEBUG */
-
-#ifdef SQLITE_DEBUG
-/* Register the OOM simulator.  This must occur before any memory
-** allocations */
-static void registerOomSimulator(void){
-  sqlite3_mem_methods mem;
-  sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
-  defaultMalloc = mem.xMalloc;
-  mem.xMalloc = oomMalloc;
-  sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
-}
-#endif
 
 /*
 ** Write I/O traces to the following stream.
@@ -703,7 +658,7 @@ static char *local_getline(char *zLine, FILE *in){
     if( n+100>nLine ){
       nLine = nLine*2 + 100;
       zLine = realloc(zLine, nLine);
-      if( zLine==0 ) shell_out_of_memory();
+      shell_check_oom(zLine);
     }
     if( fgets(&zLine[n], nLine - n, in)==0 ){
       if( n==0 ){
@@ -730,7 +685,7 @@ static char *local_getline(char *zLine, FILE *in){
       int nTrans = strlen30(zTrans)+1;
       if( nTrans>nLine ){
         zLine = realloc(zLine, nTrans);
-        if( zLine==0 ) shell_out_of_memory();
+        shell_check_oom(zLine);
       }
       memcpy(zLine, zTrans, nTrans);
       sqlite3_free(zTrans);
@@ -877,7 +832,7 @@ static void appendText(ShellText *p, char const *zAppend, char quote){
   if( p->z==0 || p->n+len>=p->nAlloc ){
     p->nAlloc = p->nAlloc*2 + len + 20;
     p->z = realloc(p->z, p->nAlloc);
-    if( p->z==0 ) shell_out_of_memory();
+    shell_check_oom(p->z);
   }
 
   if( quote ){
@@ -932,6 +887,7 @@ static char *shellFakeSchema(
 
   zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
                          zSchema ? zSchema : "main", zName);
+  shell_check_oom(zSql);
   sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
   sqlite3_free(zSql);
   initText(&s);
@@ -948,6 +904,7 @@ static char *shellFakeSchema(
     nRow++;
     appendText(&s, zDiv, 0);
     zDiv = ",";
+    if( zCol==0 ) zCol = "";
     cQuote = quoteChar(zCol);
     appendText(&s, zCol, cQuote);
   }
@@ -971,9 +928,11 @@ static void shellModuleSchema(
   int nVal,
   sqlite3_value **apVal
 ){
-  const char *zName = (const char*)sqlite3_value_text(apVal[0]);
-  char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
+  const char *zName;
+  char *zFake;
   UNUSED_PARAMETER(nVal);
+  zName = (const char*)sqlite3_value_text(apVal[0]);
+  zFake = zName ? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
   if( zFake ){
     sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
                         -1, sqlite3_free);
@@ -1861,6 +1820,7 @@ static void SHA3Update(
   unsigned int nData
 ){
   unsigned int i = 0;
+  if( aData==0 ) return;
 #if SHA3_BYTEORDER==1234
   if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
     for(; i+7<nData; i+=8){
@@ -2519,10 +2479,11 @@ static int writeFile(
   mode_t mode,                    /* MODE parameter passed to writefile() */
   sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
 ){
+  if( zFile==0 ) return 1;
 #if !defined(_WIN32) && !defined(WIN32)
   if( S_ISLNK(mode) ){
     const char *zTo = (const char*)sqlite3_value_text(pData);
-    if( symlink(zTo, zFile)<0 ) return 1;
+    if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
   }else
 #endif
   {
@@ -5490,7 +5451,7 @@ int sqlite3_ieee_init(
   SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg;  /* Unused parameter */
   for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
-    rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,	
+    rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
                                SQLITE_UTF8|SQLITE_INNOCUOUS,
                                (void*)&aFunc[i].iAux,
                                aFunc[i].xFunc, 0, 0);
@@ -5888,7 +5849,7 @@ static int seriesBestIndex(
     ** the preferred case */
     pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
     pIdxInfo->estimatedRows = 1000;
-    if( pIdxInfo->nOrderBy==1 ){
+    if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
       if( pIdxInfo->aOrderBy[0].desc ){
         idxNum |= 8;
       }else{
@@ -6723,13 +6684,15 @@ int sqlite3_regexp_init(
   int rc = SQLITE_OK;
   SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg;  /* Unused */
-  rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
-                               0, re_sql_func, 0, 0);
+  rc = sqlite3_create_function(db, "regexp", 2, 
+                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
+                            0, re_sql_func, 0, 0);
   if( rc==SQLITE_OK ){
     /* The regexpi(PATTERN,STRING) function is a case-insensitive version
     ** of regexp(PATTERN,STRING). */
-    rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
-                                 (void*)db, re_sql_func, 0, 0);
+    rc = sqlite3_create_function(db, "regexpi", 2,
+                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
+                            (void*)db, re_sql_func, 0, 0);
   }
   return rc;
 }
@@ -8001,9 +7964,14 @@ static int zipfileFilter(
     zipfileCursorErr(pCsr, "zipfile() function requires an argument");
     return SQLITE_ERROR;
   }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
+    static const u8 aEmptyBlob = 0;
     const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
     int nBlob = sqlite3_value_bytes(argv[0]);
     assert( pTab->pFirstEntry==0 );
+    if( aBlob==0 ){
+      aBlob = &aEmptyBlob;
+      nBlob = 0;
+    }
     rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
     pCsr->pFreeEntry = pTab->pFirstEntry;
     pTab->pFirstEntry = pTab->pLastEntry = 0;
@@ -8677,7 +8645,7 @@ static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
 **   SELECT zipfile(name,mode,mtime,data) ...
 **   SELECT zipfile(name,mode,mtime,data,method) ...
 */
-void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
+static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
   ZipfileCtx *p;                  /* Aggregate function context */
   ZipfileEntry e;                 /* New entry to add to zip archive */
 
@@ -8852,7 +8820,7 @@ void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
 /*
 ** xFinalize() callback for zipfile aggregate function.
 */
-void zipfileFinal(sqlite3_context *pCtx){
+static void zipfileFinal(sqlite3_context *pCtx){
   ZipfileCtx *p;
   ZipfileEOCD eocd;
   sqlite3_int64 nZip;
@@ -9941,17 +9909,25 @@ static int idxGetTableInfo(
 ){
   sqlite3_stmt *p1 = 0;
   int nCol = 0;
-  int nTab = STRLEN(zTab);
-  int nByte = sizeof(IdxTable) + nTab + 1;
+  int nTab;
+  int nByte;
   IdxTable *pNew = 0;
   int rc, rc2;
   char *pCsr = 0;
   int nPk = 0;
 
+  *ppOut = 0;
+  if( zTab==0 ) return SQLITE_ERROR;
+  nTab = STRLEN(zTab);
+  nByte = sizeof(IdxTable) + nTab + 1;
   rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
   while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
     const char *zCol = (const char*)sqlite3_column_text(p1, 1);
     const char *zColSeq = 0;
+    if( zCol==0 ){
+      rc = SQLITE_ERROR;
+      break;
+    }
     nByte += 1 + STRLEN(zCol);
     rc = sqlite3_table_column_metadata(
         db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
@@ -9978,7 +9954,9 @@ static int idxGetTableInfo(
   while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
     const char *zCol = (const char*)sqlite3_column_text(p1, 1);
     const char *zColSeq = 0;
-    int nCopy = STRLEN(zCol) + 1;
+    int nCopy;
+    if( zCol==0 ) continue;
+    nCopy = STRLEN(zCol) + 1;
     pNew->aCol[nCol].zName = pCsr;
     pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
     memcpy(pCsr, zCol, nCopy);
@@ -10130,6 +10108,7 @@ static int idxFindCompatible(
     IdxConstraint *pT = pTail;
     sqlite3_stmt *pInfo = 0;
     const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
+    if( zIdx==0 ) continue;
 
     /* Zero the IdxConstraint.bFlag values in the pEq list */
     for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
@@ -10412,7 +10391,7 @@ static void idxWriteFree(IdxWrite *pTab){
 ** runs all the queries to see which indexes they prefer, and populates
 ** IdxStatement.zIdx and IdxStatement.zEQP with the results.
 */
-int idxFindIndexes(
+static int idxFindIndexes(
   sqlite3expert *p,
   char **pzErr                         /* OUT: Error message (sqlite3_malloc) */
 ){
@@ -10541,6 +10520,7 @@ static int idxProcessOneTrigger(
   rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
   while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
     const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
+    if( zCreate==0 ) continue;
     rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
   }
   idxFinalize(&rc, pSelect);
@@ -10643,8 +10623,9 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
     const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
     const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
 
+    if( zType==0 || zName==0 ) continue;
     if( zType[0]=='v' || zType[1]=='r' ){
-      rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
+      if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
     }else{
       IdxTable *pTab;
       rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
@@ -10781,6 +10762,7 @@ static void idxRemFunc(
     case SQLITE_BLOB:
     case SQLITE_TEXT: {
       int nByte = sqlite3_value_bytes(argv[1]);
+      const void *pData = 0;
       if( nByte>pSlot->nByte ){
         char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
         if( zNew==0 ){
@@ -10792,9 +10774,11 @@ static void idxRemFunc(
       }
       pSlot->n = nByte;
       if( pSlot->eType==SQLITE_BLOB ){
-        memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
+        pData = sqlite3_value_blob(argv[1]);
+        if( pData ) memcpy(pSlot->z, pData, nByte);
       }else{
-        memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
+        pData = sqlite3_value_text(argv[1]);
+        memcpy(pSlot->z, pData, nByte);
       }
       break;
     }
@@ -11005,6 +10989,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
     i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
     const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
     const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
+    if( zTab==0 || zIdx==0 ) continue;
     if( p->iSample<100 && iPrev!=iRowid ){
       samplectx.target = (double)p->iSample / 100.0;
       samplectx.iTarget = p->iSample;
@@ -11071,14 +11056,14 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
 
   /* Copy the entire schema of database [db] into [dbm]. */
   if( rc==SQLITE_OK ){
-    sqlite3_stmt *pSql;
+    sqlite3_stmt *pSql = 0;
     rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, 
         "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
         " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
     );
     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
       const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
-      rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
+      if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
     }
     idxFinalize(&rc, pSql);
   }
@@ -12165,6 +12150,15 @@ struct EQPGraph {
   char zPrefix[100];    /* Graph prefix */
 };
 
+/* Parameters affecting columnar mode result display (defaulting together) */
+typedef struct ColModeOpts {
+  int iWrap;            /* In columnar modes, wrap lines reaching this limit */
+  u8 bQuote;            /* Quote results for .mode box and table */
+  u8 bWordWrap;         /* In columnar modes, wrap at word boundaries  */
+} ColModeOpts;
+#define ColModeOpts_default { 60, 0, 0 }
+#define ColModeOpts_default_qbox { 60, 1, 0 }
+
 /*
 ** State information about the database connection is contained in an
 ** instance of the following structure.
@@ -12183,8 +12177,10 @@ struct ShellState {
   u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
   u8 bSafeMode;          /* True to prohibit unsafe operations */
   u8 bSafeModePersist;   /* The long-term value of bSafeMode */
+  ColModeOpts cmOpts;    /* Option values affecting columnar mode output */
   unsigned statsOn;      /* True to display memory stats before each finalize */
   unsigned mEqpLines;    /* Mask of veritical lines in the EQP output graph */
+  int inputNesting;      /* Track nesting level of .read and other redirects */
   int outCount;          /* Revert to stdout when reaching zero */
   int cnt;               /* Number of records displayed so far */
   int lineno;            /* Line number of last line read from in */
@@ -12311,6 +12307,8 @@ struct ShellState {
 #define MODE_Markdown 14 /* Markdown formatting */
 #define MODE_Table   15  /* MySQL-style table formatting */
 #define MODE_Box     16  /* Unicode box-drawing characters */
+#define MODE_Count   17  /* Output only a count of the rows of output */
+#define MODE_Off     18  /* No query output shown */
 
 static const char *modeDescr[] = {
   "line",
@@ -12329,7 +12327,9 @@ static const char *modeDescr[] = {
   "json",
   "markdown",
   "table",
-  "box"
+  "box",
+  "count",
+  "off"
 };
 
 /*
@@ -12345,6 +12345,12 @@ static const char *modeDescr[] = {
 #define SEP_Unit      "\x1F"
 #define SEP_Record    "\x1E"
 
+/*
+** Limit input nesting via .read or any other input redirect.
+** It's not too expensive, so a generous allowance can be made.
+*/
+#define MAX_INPUT_NESTING 25
+
 /*
 ** A callback for the sqlite3_log() interface.
 */
@@ -12829,6 +12835,7 @@ static void output_csv(ShellState *p, const char *z, int bSep){
     }
     if( i==0 || strstr(z, p->colSeparator)!=0 ){
       char *zQuoted = sqlite3_mprintf("\"%w\"", z);
+      shell_check_oom(zQuoted);
       utf8_printf(out, "%s", zQuoted);
       sqlite3_free(zQuoted);
     }else{
@@ -13003,7 +13010,7 @@ static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
     utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
   }
   pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
-  if( pNew==0 ) shell_out_of_memory();
+  shell_check_oom(pNew);
   pNew->iEqpId = iEqpId;
   pNew->iParentId = p2;
   memcpy(pNew->zText, zText, nText+1);
@@ -13151,6 +13158,10 @@ static int shell_callback(
 
   if( azArg==0 ) return 0;
   switch( p->cMode ){
+    case MODE_Count:
+    case MODE_Off: {
+      break;
+    }
     case MODE_Line: {
       int w = 5;
       if( azArg==0 ) break;
@@ -13220,6 +13231,7 @@ static int shell_callback(
         break;
       }
       z = sqlite3_mprintf("%s", azArg[0]);
+      shell_check_oom(z);
       j = 0;
       for(i=0; IsSpace(z[i]); i++){}
       for(; (c = z[i])!=0; i++){
@@ -13351,6 +13363,7 @@ static int shell_callback(
           if( i>0 ) raw_printf(p->out, ",");
           if( quoteChar(azCol[i]) ){
             char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
+            shell_check_oom(z);
             utf8_printf(p->out, "%s", z);
             sqlite3_free(z);
           }else{
@@ -13382,7 +13395,12 @@ static int shell_callback(
           }else if( ur==0xfff0000000000000LL ){
             raw_printf(p->out, "-1e999");
           }else{
-            sqlite3_snprintf(50,z,"%!.20g", r);
+            sqlite3_int64 ir = (sqlite3_int64)r;
+            if( r==(double)ir ){
+              sqlite3_snprintf(50,z,"%lld.0", ir);
+            }else{
+              sqlite3_snprintf(50,z,"%!.20g", r);
+            }
             raw_printf(p->out, "%s", z);
           }
         }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
@@ -13596,7 +13614,7 @@ static void set_table_name(ShellState *p, const char *zName){
   n = strlen30(zName);
   if( cQuote ) n += n+2;
   z = p->zDestTable = malloc( n+1 );
-  if( z==0 ) shell_out_of_memory();
+  shell_check_oom(z);
   n = 0;
   if( cQuote ) z[n++] = cQuote;
   for(i=0; zName[i]; i++){
@@ -13607,6 +13625,47 @@ static void set_table_name(ShellState *p, const char *zName){
   z[n] = 0;
 }
 
+/*
+** Maybe construct two lines of text that point out the position of a
+** syntax error.  Return a pointer to the text, in memory obtained from
+** sqlite3_malloc().  Or, if the most recent error does not involve a
+** specific token that we can point to, return an empty string.
+**
+** In all cases, the memory returned is obtained from sqlite3_malloc64()
+** and should be released by the caller invoking sqlite3_free().
+*/
+static char *shell_error_context(const char *zSql, sqlite3 *db){
+  int iOffset;
+  size_t len;
+  char *zCode;
+  char *zMsg;
+  int i;
+  if( db==0
+   || zSql==0
+   || (iOffset = sqlite3_error_offset(db))<0
+  ){
+    return sqlite3_mprintf("");
+  }
+  while( iOffset>50 ){
+    iOffset--;
+    zSql++;
+    while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
+  }
+  len = strlen(zSql);
+  if( len>78 ){
+    len = 78;
+    while( (zSql[len]&0xc0)==0x80 ) len--;
+  }
+  zCode = sqlite3_mprintf("%.*s", len, zSql);
+  for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
+  if( iOffset<25 ){
+    zMsg = sqlite3_mprintf("\n  %z\n  %*s^--- error here", zCode, iOffset, "");
+  }else{
+    zMsg = sqlite3_mprintf("\n  %z\n  %*serror here ---^", zCode, iOffset-14, "");
+  }
+  return zMsg;
+}
+
 
 /*
 ** Execute a query statement that will generate SQL output.  Print
@@ -13629,8 +13688,10 @@ static int run_table_dump_query(
   const char *z;
   rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
   if( rc!=SQLITE_OK || !pSelect ){
-    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
-                sqlite3_errmsg(p->db));
+    char *zContext = shell_error_context(zSelect, p->db);
+    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
+                sqlite3_errmsg(p->db), zContext);
+    sqlite3_free(zContext);
     if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
     return rc;
   }
@@ -13665,12 +13726,25 @@ static int run_table_dump_query(
 */
 static char *save_err_msg(
   sqlite3 *db,           /* Database to query */
-  const char *zWhen,     /* Qualifier (format) wrapper */
-  int rc                 /* Error code returned from API */
+  const char *zPhase,    /* When the error occcurs */
+  int rc,                /* Error code returned from API */
+  const char *zSql       /* SQL string, or NULL */
 ){
-  if( zWhen==0 )
-    zWhen = "%s (%d)";
-  return sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc);
+  char *zErr;
+  char *zContext;
+  sqlite3_str *pStr = sqlite3_str_new(0);
+  sqlite3_str_appendf(pStr, "%s, %s", zPhase, sqlite3_errmsg(db));
+  if( rc>1 ){
+    sqlite3_str_appendf(pStr, " (%d)", rc);
+  }
+  zContext = shell_error_context(zSql, db);
+  if( zContext ){
+    sqlite3_str_appendall(pStr, zContext);
+    sqlite3_free(zContext);
+  }
+  zErr = sqlite3_str_finish(pStr);
+  shell_check_oom(zErr);
+  return zErr;
 }
 
 #ifdef __linux__
@@ -13848,6 +13922,7 @@ static int display_stats(
   }
 
   if( pArg->pStmt ){
+    int iHit, iMiss;
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
                                bReset);
     raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
@@ -13855,6 +13930,12 @@ static int display_stats(
     raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
     raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
+    iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
+    iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
+    if( iHit || iMiss ){
+      raw_printf(pArg->out, "Bloom filter bypass taken:           %d/%d\n",
+            iHit, iHit+iMiss);
+    }
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
     raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
@@ -14011,9 +14092,9 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
       }
       nAlloc += 100;
       p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
-      if( p->aiIndent==0 ) shell_out_of_memory();
+      shell_check_oom(p->aiIndent);
       abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
-      if( abYield==0 ) shell_out_of_memory();
+      shell_check_oom(abYield);
     }
     abYield[iOp] = str_in_array(zOp, azYield);
     p->aiIndent[iOp] = 0;
@@ -14189,7 +14270,134 @@ static void print_box_row_separator(
   fputs("\n", p->out);
 }
 
+/*
+** z[] is a line of text that is to be displayed the .mode box or table or
+** similar tabular formats.  z[] might contain control characters such
+** as \n, \t, \f, or \r.
+**
+** Compute characters to display on the first line of z[].  Stop at the
+** first \r, \n, or \f.  Expand \t into spaces.  Return a copy (obtained
+** from malloc()) of that first line, which caller should free sometime.
+** Write anything to display on the next line into *pzTail.  If this is
+** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
+*/
+static char *translateForDisplayAndDup(
+  const unsigned char *z,            /* Input text to be transformed */
+  const unsigned char **pzTail,      /* OUT: Tail of the input for next line */
+  int mxWidth,                       /* Max width.  0 means no limit */
+  u8 bWordWrap                       /* If true, avoid breaking mid-word */
+){
+  int i;                 /* Input bytes consumed */
+  int j;                 /* Output bytes generated */
+  int k;                 /* Input bytes to be displayed */
+  int n;                 /* Output column number */
+  unsigned char *zOut;   /* Output text */
+
+  if( z==0 ){
+    *pzTail = 0;
+    return 0;
+  }
+  if( mxWidth<0 ) mxWidth = -mxWidth;
+  if( mxWidth==0 ) mxWidth = 1000000;
+  i = j = n = 0;
+  while( n<mxWidth ){
+    if( z[i]>=' ' ){
+      n++;
+      do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
+      continue;
+    }
+    if( z[i]=='\t' ){
+      do{
+        n++;
+        j++;
+      }while( (n&7)!=0 && n<mxWidth );
+      i++;
+      continue;
+    }
+    break;
+  }
+  if( n>=mxWidth && bWordWrap  ){
+    /* Perhaps try to back up to a better place to break the line */
+    for(k=i; k>i/2; k--){
+      if( isspace(z[k-1]) ) break;
+    }
+    if( k<=i/2 ){
+      for(k=i; k>i/2; k--){
+        if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
+      }
+    }
+    if( k<=i/2 ){
+      k = i;
+    }else{
+      i = k;
+      while( z[i]==' ' ) i++;
+    }
+  }else{
+    k = i;
+  }
+  if( n>=mxWidth && z[i]>=' ' ){
+   *pzTail = &z[i];
+  }else if( z[i]=='\r' && z[i+1]=='\n' ){
+    *pzTail = z[i+2] ? &z[i+2] : 0;
+  }else if( z[i]==0 || z[i+1]==0 ){
+    *pzTail = 0;
+  }else{
+    *pzTail = &z[i+1];
+  }
+  zOut = malloc( j+1 );
+  shell_check_oom(zOut);
+  i = j = n = 0;
+  while( i<k ){
+    if( z[i]>=' ' ){
+      n++;
+      do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
+      continue;
+    }
+    if( z[i]=='\t' ){
+      do{
+        n++;
+        zOut[j++] = ' ';
+      }while( (n&7)!=0 && n<mxWidth );
+      i++;
+      continue;
+    }
+    break;
+  }
+  zOut[j] = 0;
+  return (char*)zOut;  
+}
 
+/* Extract the value of the i-th current column for pStmt as an SQL literal
+** value.  Memory is obtained from sqlite3_malloc64() and must be freed by
+** the caller.
+*/
+static char *quoted_column(sqlite3_stmt *pStmt, int i){
+  switch( sqlite3_column_type(pStmt, i) ){
+    case SQLITE_NULL: {
+      return sqlite3_mprintf("NULL");
+    }
+    case SQLITE_INTEGER:
+    case SQLITE_FLOAT: {
+      return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
+    }
+    case SQLITE_TEXT: {
+      return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
+    }
+    case SQLITE_BLOB: {
+      int j;
+      sqlite3_str *pStr = sqlite3_str_new(0);
+      const unsigned char *a = sqlite3_column_blob(pStmt,i);
+      int n = sqlite3_column_bytes(pStmt,i);
+      sqlite3_str_append(pStr, "x'", 2);
+      for(j=0; j<n; j++){
+        sqlite3_str_appendf(pStr, "%02x", a[j]);
+      }
+      sqlite3_str_append(pStr, "'", 1);
+      return sqlite3_str_finish(pStr);
+    }
+  }
+  return 0; /* Not reached */
+}
 
 /*
 ** Run a prepared statement and output the result in one of the
*** 17230 LINES SKIPPED ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202206121412.25CECFcf048459>