git: 3d0030d26146 - stable/13 - sqlite3: Vendor import of sqlite3 3.38.5
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 12 Jun 2022 14:07:38 UTC
The branch stable/13 has been updated by cy: URL: https://cgit.FreeBSD.org/src/commit/?id=3d0030d261469b2399a0ad622bd8b3d159855468 commit 3d0030d261469b2399a0ad622bd8b3d159855468 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:07:03 +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 ***