Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -705,13 +705,10 @@ $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS) fuzzcheck-asan$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) $(LTLINK) -o $@ -fsanitize=address $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS) -fuzzcheck-ubsan$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) - $(LTLINK) -o $@ -fsanitize=undefined $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS) - ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \ $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h @@ -1135,12 +1132,10 @@ # Source files that go into making shell.c SHELL_SRC = \ $(TOP)/src/shell.c.in \ $(TOP)/ext/misc/appendvfs.c \ $(TOP)/ext/misc/completion.c \ - $(TOP)/ext/consio/console_io.c \ - $(TOP)/ext/consio/console_io.h \ $(TOP)/ext/misc/decimal.c \ $(TOP)/ext/misc/basexx.c \ $(TOP)/ext/misc/base64.c \ $(TOP)/ext/misc/base85.c \ $(TOP)/ext/misc/fileio.c \ @@ -1489,11 +1484,11 @@ snapshot-tarball: sqlite3.c sqlite3rc.h TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot # Build a ZIP archive containing various command-line tools. # -tool-zip: testfixture sqlite3 sqldiff sqlite3_analyzer $(TOP)/tool/mktoolzip.tcl +tool-zip: testfixture sqlite3 sqldiff sqlite3_analyzer tool/mktoolzip.tcl ./testfixture $(TOP)/tool/mktoolzip.tcl # The next two rules are used to support the "threadtest" target. Building # threadtest runs a few thread-safety tests that are implemented in C. This # target is invoked by the releasetest.tcl script. Index: Makefile.msc ================================================================== --- Makefile.msc +++ Makefile.msc @@ -372,11 +372,10 @@ # the Windows platform. # !IFNDEF OPT_FEATURE_FLAGS !IF $(MINIMAL_AMALGAMATION)==0 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=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_STMTVTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1 @@ -1592,11 +1591,12 @@ $(TOP)\ext\misc\unionvtab.c \ $(TOP)\ext\misc\wholenumber.c \ $(TOP)\ext\rtree\test_rtreedoc.c \ $(TOP)\ext\recover\sqlite3recover.c \ $(TOP)\ext\recover\test_recover.c \ - $(TOP)\ext\recover\dbdata.c + $(TOP)\ext\recover\dbdata.c \ + fts5.c # If use of zlib is enabled, add the "zipfile.c" source file. # !IF $(USE_ZLIB)!=0 TESTEXT = $(TESTEXT) $(TOP)\ext\misc\zipfile.c @@ -1608,12 +1608,11 @@ TESTSRC2 = \ $(SRC00) \ $(SRC01) \ $(SRC07) \ $(SRC10) \ - $(TOP)\ext\async\sqlite3async.c \ - fts5.c + $(TOP)\ext\async\sqlite3async.c # Header files used by all library source files. # HDR = \ $(TOP)\src\btree.h \ @@ -1688,12 +1687,10 @@ !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_DQS=0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1 -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1 -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_STMT_SCANSTATUS=1 !ENDIF # <> # Extra compiler options for various test tools. # @@ -2259,12 +2256,10 @@ .\mkkeywordhash.exe > keywordhash.h # Source files that go into making shell.c SHELL_SRC = \ $(TOP)\src\shell.c.in \ - $(TOP)\ext\consio\console_io.c \ - $(TOP)\ext\consio\console_io.h \ $(TOP)\ext\misc\appendvfs.c \ $(TOP)\ext\misc\completion.c \ $(TOP)\ext\misc\base64.c \ $(TOP)\ext\misc\base85.c \ $(TOP)\ext\misc\decimal.c \ @@ -2470,11 +2465,11 @@ extensiontest: testfixture.exe testloadext.dll @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS) -tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe $(TOP)\tool\mktoolzip.tcl +tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe tool\mktoolzip.tcl .\testfixture.exe $(TOP)\tool\mktoolzip.tcl coretestprogs: $(TESTPROGS) testprogs: coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe Index: VERSION ================================================================== --- VERSION +++ VERSION @@ -1,1 +1,1 @@ -3.44.3 +3.44.0 Index: autoconf/Makefile.msc ================================================================== --- autoconf/Makefile.msc +++ autoconf/Makefile.msc @@ -294,11 +294,10 @@ # the Windows platform. # !IFNDEF OPT_FEATURE_FLAGS !IF $(MINIMAL_AMALGAMATION)==0 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=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_STMTVTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1 @@ -986,12 +985,10 @@ !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_DQS=0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1 -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1 -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_STMT_SCANSTATUS=1 !ENDIF # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. Index: autoconf/tea/configure.ac ================================================================== --- autoconf/tea/configure.ac +++ autoconf/tea/configure.ac @@ -17,11 +17,11 @@ # so you can encode the package version directly into the source files. # This will also define a special symbol for Windows (BUILD_ # so that we create the export library with the dll. #----------------------------------------------------------------------- -AC_INIT([sqlite],[3.44.3]) +AC_INIT([sqlite],[3.44.0]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. Index: configure ================================================================== --- configure +++ configure @@ -1,8 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sqlite 3.44.3. +# Generated by GNU Autoconf 2.69 for sqlite 3.44.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # @@ -724,12 +724,12 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.44.3' -PACKAGE_STRING='sqlite 3.44.3' +PACKAGE_VERSION='3.44.0' +PACKAGE_STRING='sqlite 3.44.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ @@ -1470,11 +1470,11 @@ # 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.44.3 to adapt to many kinds of systems. +\`configure' configures sqlite 3.44.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. @@ -1535,11 +1535,11 @@ _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.44.3:";; + short | recursive ) echo "Configuration of sqlite 3.44.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options @@ -1666,11 +1666,11 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.44.3 +sqlite configure 3.44.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. @@ -2085,11 +2085,11 @@ } # ac_fn_c_check_header_mongrel 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.44.3, which was +It was created by sqlite $as_me 3.44.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF @@ -12479,11 +12479,11 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # 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.44.3, which was +This file was extended by sqlite $as_me 3.44.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS @@ -12545,11 +12545,11 @@ _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.44.3 +sqlite config.status 3.44.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation DELETED ext/consio/console_io.c Index: ext/consio/console_io.c ================================================================== --- ext/consio/console_io.c +++ /dev/null @@ -1,679 +0,0 @@ -/* -** 2023 November 4 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -******************************************************************************** -** This file implements various interfaces used for console and stream I/O -** by the SQLite project command-line tools, as explained in console_io.h . -** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there. -*/ - -#ifndef SQLITE_CDECL -# define SQLITE_CDECL -#endif - -#ifndef SHELL_NO_SYSINC -# include -# include -# include -# include -# include -# include "console_io.h" -# include "sqlite3.h" -#endif - -#ifndef SQLITE_CIO_NO_TRANSLATE -# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT -# ifndef SHELL_NO_SYSINC -# include -# include -# undef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# include -# endif -# define CIO_WIN_WC_XLATE 1 /* Use WCHAR Windows APIs for console I/O */ -# else -# ifndef SHELL_NO_SYSINC -# include -# endif -# define CIO_WIN_WC_XLATE 0 /* Use plain C library stream I/O at console */ -# endif -#else -# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */ -#endif - -#if CIO_WIN_WC_XLATE -/* Character used to represent a known-incomplete UTF-8 char group (�) */ -static WCHAR cBadGroup = 0xfffd; -#endif - -#if CIO_WIN_WC_XLATE -static HANDLE handleOfFile(FILE *pf){ - int fileDesc = _fileno(pf); - union { intptr_t osfh; HANDLE fh; } fid = { - (fileDesc>=0)? _get_osfhandle(fileDesc) : (intptr_t)INVALID_HANDLE_VALUE - }; - return fid.fh; -} -#endif - -#ifndef SQLITE_CIO_NO_TRANSLATE -typedef struct PerStreamTags { -# if CIO_WIN_WC_XLATE - HANDLE hx; - DWORD consMode; - char acIncomplete[4]; -# else - short reachesConsole; -# endif - FILE *pf; -} PerStreamTags; - -/* Define NULL-like value for things which can validly be 0. */ -# define SHELL_INVALID_FILE_PTR ((FILE *)~0) -# if CIO_WIN_WC_XLATE -# define SHELL_INVALID_CONS_MODE 0xFFFF0000 -# endif - -# if CIO_WIN_WC_XLATE -# define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \ - {0,0,0,0}, SHELL_INVALID_FILE_PTR } -# else -# define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR } -# endif - -/* Quickly say whether a known output is going to the console. */ -# if CIO_WIN_WC_XLATE -static short pstReachesConsole(PerStreamTags *ppst){ - return (ppst->hx != INVALID_HANDLE_VALUE); -} -# else -# define pstReachesConsole(ppst) 0 -# endif - -# if CIO_WIN_WC_XLATE -static void restoreConsoleArb(PerStreamTags *ppst){ - if( pstReachesConsole(ppst) ) SetConsoleMode(ppst->hx, ppst->consMode); -} -# else -# define restoreConsoleArb(ppst) -# endif - -/* Say whether FILE* appears to be a console, collect associated info. */ -static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){ -# if CIO_WIN_WC_XLATE - short rv = 0; - DWORD dwCM = SHELL_INVALID_CONS_MODE; - HANDLE fh = handleOfFile(pf); - ppst->pf = pf; - if( INVALID_HANDLE_VALUE != fh ){ - rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwCM)); - } - ppst->hx = (rv)? fh : INVALID_HANDLE_VALUE; - ppst->consMode = dwCM; - return rv; -# else - ppst->pf = pf; - ppst->reachesConsole = ( (short)isatty(fileno(pf)) ); - return ppst->reachesConsole; -# endif -} - -# if CIO_WIN_WC_XLATE -/* Define console modes for use with the Windows Console API. */ -# define SHELL_CONI_MODE \ - (ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \ - | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT) -# define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \ - | ENABLE_VIRTUAL_TERMINAL_PROCESSING) -# endif - -typedef struct ConsoleInfo { - PerStreamTags pstSetup[3]; - PerStreamTags pstDesignated[3]; - StreamsAreConsole sacSetup; -} ConsoleInfo; - -static short isValidStreamInfo(PerStreamTags *ppst){ - return (ppst->pf != SHELL_INVALID_FILE_PTR); -} - -static ConsoleInfo consoleInfo = { - { /* pstSetup */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER }, - { /* pstDesignated[] */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER }, - SAC_NoConsole /* sacSetup */ -}; - -SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0; - -# if CIO_WIN_WC_XLATE -static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){ - if( pstReachesConsole(ppst) ){ - DWORD cm = odir? SHELL_CONO_MODE : SHELL_CONI_MODE; - SetConsoleMode(ppst->hx, cm); - } -} -# else -# define maybeSetupAsConsole(ppst,odir) -# endif - -SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void){ -# if CIO_WIN_WC_XLATE - int ix = 0; - while( ix < 6 ){ - PerStreamTags *ppst = (ix<3)? - &consoleInfo.pstSetup[ix] : &consoleInfo.pstDesignated[ix-3]; - maybeSetupAsConsole(ppst, (ix % 3)>0); - ++ix; - } -# endif -} - -SQLITE_INTERNAL_LINKAGE StreamsAreConsole -consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){ - StreamsAreConsole rv = SAC_NoConsole; - FILE* apf[3] = { pfIn, pfOut, pfErr }; - int ix; - for( ix = 2; ix >= 0; --ix ){ - PerStreamTags *ppst = &consoleInfo.pstSetup[ix]; - if( streamOfConsole(apf[ix], ppst) ){ - rv |= (SAC_InConsole< 0 ) fflush(apf[ix]); - } - consoleInfo.sacSetup = rv; - consoleRenewSetup(); - return rv; -} - -SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ){ -# if CIO_WIN_WC_XLATE - static ConsoleInfo *pci = &consoleInfo; - if( pci->sacSetup ){ - int ix; - for( ix=0; ix<3; ++ix ){ - if( pci->sacSetup & (SAC_InConsole<pstSetup[ix]; - SetConsoleMode(ppst->hx, ppst->consMode); - } - } - } -# endif -} -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ - -#ifdef SQLITE_CIO_INPUT_REDIR -/* Say whether given FILE* is among those known, via either -** consoleClassifySetup() or set{Output,Error}Stream, as -** readable, and return an associated PerStreamTags pointer -** if so. Otherwise, return 0. -*/ -static PerStreamTags * isKnownReadable(FILE *pf){ - static PerStreamTags *apst[] = { - &consoleInfo.pstDesignated[0], &consoleInfo.pstSetup[0], 0 - }; - int ix = 0; - do { - if( apst[ix]->pf == pf ) break; - } while( apst[++ix] != 0 ); - return apst[ix]; -} -#endif - -#ifndef SQLITE_CIO_NO_TRANSLATE -/* Say whether given FILE* is among those known, via either -** consoleClassifySetup() or set{Output,Error}Stream, as -** writable, and return an associated PerStreamTags pointer -** if so. Otherwise, return 0. -*/ -static PerStreamTags * isKnownWritable(FILE *pf){ - static PerStreamTags *apst[] = { - &consoleInfo.pstDesignated[1], &consoleInfo.pstDesignated[2], - &consoleInfo.pstSetup[1], &consoleInfo.pstSetup[2], 0 - }; - int ix = 0; - do { - if( apst[ix]->pf == pf ) break; - } while( apst[++ix] != 0 ); - return apst[ix]; -} - -static FILE *designateEmitStream(FILE *pf, unsigned chix){ - FILE *rv = consoleInfo.pstDesignated[chix].pf; - if( pf == invalidFileStream ) return rv; - else{ - /* Setting a possibly new output stream. */ - PerStreamTags *ppst = isKnownWritable(pf); - if( ppst != 0 ){ - PerStreamTags pst = *ppst; - consoleInfo.pstDesignated[chix] = pst; - }else streamOfConsole(pf, &consoleInfo.pstDesignated[chix]); - } - return rv; -} - -SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf){ - return designateEmitStream(pf, 1); -} -# ifdef CONSIO_SET_ERROR_STREAM -SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf){ - return designateEmitStream(pf, 2); -} -# endif -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ - -#ifndef SQLITE_CIO_NO_SETMODE -# if CIO_WIN_WC_XLATE -static void setModeFlushQ(FILE *pf, short bFlush, int mode){ - if( bFlush ) fflush(pf); - _setmode(_fileno(pf), mode); -} -# else -# define setModeFlushQ(f, b, m) if(b) fflush(f) -# endif - -SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *pf, short bFlush){ - setModeFlushQ(pf, bFlush, _O_BINARY); -} -SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *pf, short bFlush){ - setModeFlushQ(pf, bFlush, _O_TEXT); -} -# undef setModeFlushQ - -#else /* defined(SQLITE_CIO_NO_SETMODE) */ -# define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0) -# define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0) -#endif /* defined(SQLITE_CIO_NO_SETMODE) */ - -#ifndef SQLITE_CIO_NO_TRANSLATE -# if CIO_WIN_WC_XLATE -/* Write buffer cBuf as output to stream known to reach console, -** limited to ncTake char's. Return ncTake on success, else 0. */ -static int conZstrEmit(PerStreamTags *ppst, const char *z, int ncTake){ - int rv = 0; - if( z!=NULL ){ - int nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, 0,0); - if( nwc > 0 ){ - WCHAR *zw = sqlite3_malloc64(nwc*sizeof(WCHAR)); - if( zw!=NULL ){ - nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, zw,nwc); - if( nwc > 0 ){ - /* Translation from UTF-8 to UTF-16, then WCHARs out. */ - if( WriteConsoleW(ppst->hx, zw,nwc, 0, NULL) ){ - rv = ncTake; - } - } - sqlite3_free(zw); - } - } - } - return rv; -} - -/* For {f,o,e}PrintfUtf8() when stream is known to reach console. */ -static int conioVmPrintf(PerStreamTags *ppst, const char *zFormat, va_list ap){ - char *z = sqlite3_vmprintf(zFormat, ap); - if( z ){ - int rv = conZstrEmit(ppst, z, (int)strlen(z)); - sqlite3_free(z); - return rv; - }else return 0; -} -# endif /* CIO_WIN_WC_XLATE */ - -# ifdef CONSIO_GET_EMIT_STREAM -static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix, - PerStreamTags *ppst){ - PerStreamTags *rv = isKnownWritable(pf); - short isValid = (rv!=0)? isValidStreamInfo(rv) : 0; - if( rv != 0 && isValid ) return rv; - streamOfConsole(pf, ppst); - return ppst; -} -# endif - -/* Get stream info, either for designated output or error stream when -** chix equals 1 or 2, or for an arbitrary stream when chix == 0. -** In either case, ppst references a caller-owned PerStreamTags -** struct which may be filled in if none of the known writable -** streams is being held by consoleInfo. The ppf parameter is a -** byref output when chix!=0 and a byref input when chix==0. - */ -static PerStreamTags * -getEmitStreamInfo(unsigned chix, PerStreamTags *ppst, - /* in/out */ FILE **ppf){ - PerStreamTags *ppstTry; - FILE *pfEmit; - if( chix > 0 ){ - ppstTry = &consoleInfo.pstDesignated[chix]; - if( !isValidStreamInfo(ppstTry) ){ - ppstTry = &consoleInfo.pstSetup[chix]; - pfEmit = ppst->pf; - }else pfEmit = ppstTry->pf; - if( !isValidStreamInfo(ppstTry) ){ - pfEmit = (chix > 1)? stderr : stdout; - ppstTry = ppst; - streamOfConsole(pfEmit, ppstTry); - } - *ppf = pfEmit; - }else{ - ppstTry = isKnownWritable(*ppf); - if( ppstTry != 0 ) return ppstTry; - streamOfConsole(*ppf, ppst); - return ppst; - } - return ppstTry; -} - -SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...){ - va_list ap; - int rv; - FILE *pfOut; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut); -# else - getEmitStreamInfo(1, &pst, &pfOut); -# endif - assert(zFormat!=0); - va_start(ap, zFormat); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - rv = conioVmPrintf(ppst, zFormat, ap); - }else{ -# endif - rv = vfprintf(pfOut, zFormat, ap); -# if CIO_WIN_WC_XLATE - } -# endif - va_end(ap); - return rv; -} - -SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...){ - va_list ap; - int rv; - FILE *pfErr; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr); -# else - getEmitStreamInfo(2, &pst, &pfErr); -# endif - assert(zFormat!=0); - va_start(ap, zFormat); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - rv = conioVmPrintf(ppst, zFormat, ap); - }else{ -# endif - rv = vfprintf(pfErr, zFormat, ap); -# if CIO_WIN_WC_XLATE - } -# endif - va_end(ap); - return rv; -} - -SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...){ - va_list ap; - int rv; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO); -# else - getEmitStreamInfo(0, &pst, &pfO); -# endif - assert(zFormat!=0); - va_start(ap, zFormat); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - maybeSetupAsConsole(ppst, 1); - rv = conioVmPrintf(ppst, zFormat, ap); - if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst); - }else{ -# endif - rv = vfprintf(pfO, zFormat, ap); -# if CIO_WIN_WC_XLATE - } -# endif - va_end(ap); - return rv; -} - -SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO){ - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO); -# else - getEmitStreamInfo(0, &pst, &pfO); -# endif - assert(z!=0); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - int rv; - maybeSetupAsConsole(ppst, 1); - rv = conZstrEmit(ppst, z, (int)strlen(z)); - if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst); - return rv; - }else { -# endif - return (fputs(z, pfO)<0)? 0 : (int)strlen(z); -# if CIO_WIN_WC_XLATE - } -# endif -} - -SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z){ - FILE *pfErr; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr); -# else - getEmitStreamInfo(2, &pst, &pfErr); -# endif - assert(z!=0); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z)); - else { -# endif - return (fputs(z, pfErr)<0)? 0 : (int)strlen(z); -# if CIO_WIN_WC_XLATE - } -# endif -} - -SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z){ - FILE *pfOut; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut); -# else - getEmitStreamInfo(1, &pst, &pfOut); -# endif - assert(z!=0); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z)); - else { -# endif - return (fputs(z, pfOut)<0)? 0 : (int)strlen(z); -# if CIO_WIN_WC_XLATE - } -# endif -} - -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ - -#if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE)) -/* Skip over as much z[] input char sequence as is valid UTF-8, -** limited per nAccept char's or whole characters and containing -** no char cn such that ((1<=0 => char count, nAccept<0 => character - */ -SQLITE_INTERNAL_LINKAGE const char* -zSkipValidUtf8(const char *z, int nAccept, long ccm){ - int ng = (nAccept<0)? -nAccept : 0; - const char *pcLimit = (nAccept>=0)? z+nAccept : 0; - assert(z!=0); - while( (pcLimit)? (z= pcLimit ) return z; - else{ - char ct = *zt++; - if( ct==0 || (zt-z)>4 || (ct & 0xC0)!=0x80 ){ - /* Trailing bytes are too few, too many, or invalid. */ - return z; - } - } - } while( ((c <<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */ - z = zt; - } - } - return z; -} -#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/ - -#ifndef SQLITE_CIO_NO_TRANSLATE - -#ifdef CONSIO_SPUTB -SQLITE_INTERNAL_LINKAGE int -fPutbUtf8(FILE *pfO, const char *cBuf, int nAccept){ - assert(pfO!=0); -# if CIO_WIN_WC_XLATE - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ - PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO); - if( pstReachesConsole(ppst) ){ - int rv; - maybeSetupAsConsole(ppst, 1); - rv = conZstrEmit(ppst, cBuf, nAccept); - if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst); - return rv; - }else { -# endif - return (int)fwrite(cBuf, 1, nAccept, pfO); -# if CIO_WIN_WC_XLATE - } -# endif -} -#endif /* defined(CONSIO_SPUTB) */ - -SQLITE_INTERNAL_LINKAGE int -oPutbUtf8(const char *cBuf, int nAccept){ - FILE *pfOut; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut); -# else - getEmitStreamInfo(1, &pst, &pfOut); -# endif -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - return conZstrEmit(ppst, cBuf, nAccept); - }else { -# endif - return (int)fwrite(cBuf, 1, nAccept, pfOut); -# if CIO_WIN_WC_XLATE - } -# endif -} - -# ifdef CONSIO_EPUTB -SQLITE_INTERNAL_LINKAGE int -ePutbUtf8(const char *cBuf, int nAccept){ - FILE *pfErr; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ - PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - return conZstrEmit(ppst, cBuf, nAccept); - }else { -# endif - return (int)fwrite(cBuf, 1, nAccept, pfErr); -# if CIO_WIN_WC_XLATE - } -# endif -} -# endif /* defined(CONSIO_EPUTB) */ - -SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){ - if( pfIn==0 ) pfIn = stdin; -# if CIO_WIN_WC_XLATE - if( pfIn == consoleInfo.pstSetup[0].pf - && (consoleInfo.sacSetup & SAC_InConsole)!=0 ){ -# if CIO_WIN_WC_XLATE==1 -# define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */ - WCHAR wcBuf[SHELL_GULP+1]; - int lend = 0, noc = 0; - if( ncMax > 0 ) cBuf[0] = 0; - while( noc < ncMax-8-1 && !lend ){ - /* There is room for at least 2 more characters and a 0-terminator. */ - int na = (ncMax > SHELL_GULP*4+1 + noc)? SHELL_GULP : (ncMax-1 - noc)/4; -# undef SHELL_GULP - DWORD nbr = 0; - BOOL bRC = ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf, na, &nbr, 0); - if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){ - /* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */ - DWORD nbrx; - bRC &= ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf+nbr, 1, &nbrx, 0); - if( bRC ) nbr += nbrx; - } - if( !bRC || (noc==0 && nbr==0) ) return 0; - if( nbr > 0 ){ - int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0); - if( nmb != 0 && noc+nmb <= ncMax ){ - int iseg = noc; - nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0); - noc += nmb; - /* Fixup line-ends as coded by Windows for CR (or "Enter".) - ** This is done without regard for any setMode{Text,Binary}() - ** call that might have been done on the interactive input. - */ - if( noc > 0 ){ - if( cBuf[noc-1]=='\n' ){ - lend = 1; - if( noc > 1 && cBuf[noc-2]=='\r' ) cBuf[--noc-1] = '\n'; - } - } - /* Check for ^Z (anywhere in line) too, to act as EOF. */ - while( iseg < noc ){ - if( cBuf[iseg]=='\x1a' ){ - noc = iseg; /* Chop ^Z and anything following. */ - lend = 1; /* Counts as end of line too. */ - break; - } - ++iseg; - } - }else break; /* Drop apparent garbage in. (Could assert.) */ - }else break; - } - /* If got nothing, (after ^Z chop), must be at end-of-file. */ - if( noc > 0 ){ - cBuf[noc] = 0; - return cBuf; - }else return 0; -# endif - }else{ -# endif - return fgets(cBuf, ncMax, pfIn); -# if CIO_WIN_WC_XLATE - } -# endif -} -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ - -#undef SHELL_INVALID_FILE_PTR DELETED ext/consio/console_io.h Index: ext/consio/console_io.h ================================================================== --- ext/consio/console_io.h +++ /dev/null @@ -1,280 +0,0 @@ -/* -** 2023 November 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -******************************************************************************** -** This file exposes various interfaces used for console and other I/O -** by the SQLite project command-line tools. These interfaces are used -** at either source conglomeration time, compilation time, or run time. -** This source provides for either inclusion into conglomerated, -** "single-source" forms or separate compilation then linking. -** -** Platform dependencies are "hidden" here by various stratagems so -** that, provided certain conditions are met, the programs using this -** source or object code compiled from it need no explicit conditional -** compilation in their source for their console and stream I/O. -** -** The symbols and functionality exposed here are not a public API. -** This code may change in tandem with other project code as needed. -** -** When this .h file and its companion .c are directly incorporated into -** a source conglomeration (such as shell.c), the preprocessor symbol -** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O -** translation for Windows is effected for the build. -*/ - -#ifndef SQLITE_INTERNAL_LINKAGE -# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */ -# include -#else -# define SHELL_NO_SYSINC /* Better yet, modify mkshellc.tcl for this. */ -#endif - -#ifndef SQLITE3_H -# include "sqlite3.h" -#endif - -#ifndef SQLITE_CIO_NO_CLASSIFY - -/* Define enum for use with following function. */ -typedef enum StreamsAreConsole { - SAC_NoConsole = 0, - SAC_InConsole = 1, SAC_OutConsole = 2, SAC_ErrConsole = 4, - SAC_AnyConsole = 0x7 -} StreamsAreConsole; - -/* -** Classify the three standard I/O streams according to whether -** they are connected to a console attached to the process. -** -** Returns the bit-wise OR of SAC_{In,Out,Err}Console values, -** or SAC_NoConsole if none of the streams reaches a console. -** -** This function should be called before any I/O is done with -** the given streams. As a side-effect, the given inputs are -** recorded so that later I/O operations on them may be done -** differently than the C library FILE* I/O would be done, -** iff the stream is used for the I/O functions that follow, -** and to support the ones that use an implicit stream. -** -** On some platforms, stream or console mode alteration (aka -** "Setup") may be made which is undone by consoleRestore(). -*/ -SQLITE_INTERNAL_LINKAGE StreamsAreConsole -consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ); -/* A usual call for convenience: */ -#define SQLITE_STD_CONSOLE_INIT() consoleClassifySetup(stdin,stdout,stderr) - -/* -** After an initial call to consoleClassifySetup(...), renew -** the same setup it effected. (A call not after is an error.) -** This will restore state altered by consoleRestore(); -** -** Applications which run an inferior (child) process which -** inherits the same I/O streams may call this function after -** such a process exits to guard against console mode changes. -*/ -SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void); - -/* -** Undo any side-effects left by consoleClassifySetup(...). -** -** This should be called after consoleClassifySetup() and -** before the process terminates normally. It is suitable -** for use with the atexit() C library procedure. After -** this call, no console I/O should be done until one of -** console{Classify or Renew}Setup(...) is called again. -** -** Applications which run an inferior (child) process that -** inherits the same I/O streams might call this procedure -** before so that said process will have a console setup -** however users have configured it or come to expect. -*/ -SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ); - -#else /* defined(SQLITE_CIO_NO_CLASSIFY) */ -# define consoleClassifySetup(i,o,e) -# define consoleRenewSetup() -# define consoleRestore() -#endif /* defined(SQLITE_CIO_NO_CLASSIFY) */ - -#ifndef SQLITE_CIO_NO_REDIRECT -/* -** Set stream to be used for the functions below which write -** to "the designated X stream", where X is Output or Error. -** Returns the previous value. -** -** Alternatively, pass the special value, invalidFileStream, -** to get the designated stream value without setting it. -** -** Before the designated streams are set, they default to -** those passed to consoleClassifySetup(...), and before -** that is called they default to stdout and stderr. -** -** It is error to close a stream so designated, then, without -** designating another, use the corresponding {o,e}Emit(...). -*/ -SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream; -SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf); -# ifdef CONSIO_SET_ERROR_STREAM -SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf); -# endif -#else -# define setOutputStream(pf) -# define setErrorStream(pf) -#endif /* !defined(SQLITE_CIO_NO_REDIRECT) */ - -#ifndef SQLITE_CIO_NO_TRANSLATE -/* -** Emit output like fprintf(). If the output is going to the -** console and translation from UTF-8 is necessary, perform -** the needed translation. Otherwise, write formatted output -** to the provided stream almost as-is, possibly with newline -** translation as specified by set{Binary,Text}Mode(). -*/ -SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...); -/* Like fPrintfUtf8 except stream is always the designated output. */ -SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...); -/* Like fPrintfUtf8 except stream is always the designated error. */ -SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...); - -/* -** Emit output like fputs(). If the output is going to the -** console and translation from UTF-8 is necessary, perform -** the needed translation. Otherwise, write given text to the -** provided stream almost as-is, possibly with newline -** translation as specified by set{Binary,Text}Mode(). -*/ -SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO); -/* Like fPutsUtf8 except stream is always the designated output. */ -SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z); -/* Like fPutsUtf8 except stream is always the designated error. */ -SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z); - -/* -** Emit output like fPutsUtf8(), except that the length of the -** accepted char or character sequence is limited by nAccept. -** -** Returns the number of accepted char values. -*/ -#ifdef CONSIO_SPUTB -SQLITE_INTERNAL_LINKAGE int -fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept); -#endif -/* Like fPutbUtf8 except stream is always the designated output. */ -SQLITE_INTERNAL_LINKAGE int -oPutbUtf8(const char *cBuf, int nAccept); -/* Like fPutbUtf8 except stream is always the designated error. */ -#ifdef CONSIO_EPUTB -SQLITE_INTERNAL_LINKAGE int -ePutbUtf8(const char *cBuf, int nAccept); -#endif - -/* -** Collect input like fgets(...) with special provisions for input -** from the console on platforms that require same. Defers to the -** C library fgets() when input is not from the console. Newline -** translation may be done as set by set{Binary,Text}Mode(). As a -** convenience, pfIn==NULL is treated as stdin. -*/ -SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn); -/* Like fGetsUtf8 except stream is always the designated input. */ -/* SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax); */ - -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ - -#ifndef SQLITE_CIO_NO_SETMODE -/* -** Set given stream for binary mode, where newline translation is -** not done, or for text mode where, for some platforms, newlines -** are translated to the platform's conventional char sequence. -** If bFlush true, flush the stream. -** -** An additional side-effect is that if the stream is one passed -** to consoleClassifySetup() as an output, it is flushed first. -** -** Note that binary/text mode has no effect on console I/O -** translation. On all platforms, newline to the console starts -** a new line and CR,LF chars from the console become a newline. -*/ -SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *, short bFlush); -SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *, short bFlush); -#endif - -#ifdef SQLITE_CIO_PROMPTED_IN -typedef struct Prompts { - int numPrompts; - const char **azPrompts; -} Prompts; - -/* -** Macros for use of a line editor. -** -** The following macros define operations involving use of a -** line-editing library or simple console interaction. -** A "T" argument is a text (char *) buffer or filename. -** A "N" argument is an integer. -** -** SHELL_ADD_HISTORY(T) // Record text as line(s) of history. -** SHELL_READ_HISTORY(T) // Read history from file named by T. -** SHELL_WRITE_HISTORY(T) // Write history to file named by T. -** SHELL_STIFLE_HISTORY(N) // Limit history to N entries. -** -** A console program which does interactive console input is -** expected to call: -** SHELL_READ_HISTORY(T) before collecting such input; -** SHELL_ADD_HISTORY(T) as record-worthy input is taken; -** SHELL_STIFLE_HISTORY(N) after console input ceases; then -** SHELL_WRITE_HISTORY(T) before the program exits. -*/ - -/* -** Retrieve a single line of input text from an input stream. -** -** If pfIn is the input stream passed to consoleClassifySetup(), -** and azPrompt is not NULL, then a prompt is issued before the -** line is collected, as selected by the isContinuation flag. -** Array azPrompt[{0,1}] holds the {main,continuation} prompt. -** -** If zBufPrior is not NULL then it is a buffer from a prior -** call to this routine that can be reused, or will be freed. -** -** The result is stored in space obtained from malloc() and -** must either be freed by the caller or else passed back to -** this function as zBufPrior for reuse. -** -** This function may call upon services of a line-editing -** library to interactively collect line edited input. -*/ -SQLITE_INTERNAL_LINKAGE char * -shellGetLine(FILE *pfIn, char *zBufPrior, int nLen, - short isContinuation, Prompts azPrompt); -#endif /* defined(SQLITE_CIO_PROMPTED_IN) */ -/* -** TBD: Define an interface for application(s) to generate -** completion candidates for use by the line-editor. -** -** This may be premature; the CLI is the only application -** that does this. Yet, getting line-editing melded into -** console I/O is desirable because a line-editing library -** may have to establish console operating mode, possibly -** in a way that interferes with the above functionality. -*/ - -#if !(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE)) -/* Skip over as much z[] input char sequence as is valid UTF-8, -** limited per nAccept char's or whole characters and containing -** no char cn such that ((1<=0 => char count, nAccept<0 => character - */ -SQLITE_INTERNAL_LINKAGE const char* -zSkipValidUtf8(const char *z, int nAccept, long ccm); - -#endif Index: ext/expert/sqlite3expert.c ================================================================== --- ext/expert/sqlite3expert.c +++ ext/expert/sqlite3expert.c @@ -1868,13 +1868,12 @@ int nargs = sqlite3_column_int(pStmt,3); int flags = sqlite3_column_int(pStmt,4); const char *name = (char*)sqlite3_column_text(pStmt,0); const char *type = (char*)sqlite3_column_text(pStmt,1); const char *enc = (char*)sqlite3_column_text(pStmt,2); - if( name==0 || type==0 || enc==0 ){ - /* no-op. Only happens on OOM */ - }else{ + if( name==0 || type==0 || enc==0 ) rc = SQLITE_NOMEM; + else{ int ienc = SQLITE_UTF8; int rcf = SQLITE_ERROR; if( strcmp(enc,"utf16le")==0 ) ienc = SQLITE_UTF16LE; else if( strcmp(enc,"utf16be")==0 ) ienc = SQLITE_UTF16BE; ienc |= (flags & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY)); Index: ext/fts3/fts3.c ================================================================== --- ext/fts3/fts3.c +++ ext/fts3/fts3.c @@ -4004,40 +4004,31 @@ /* ** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual ** table. */ -static int fts3Integrity( - sqlite3_vtab *pVtab, /* The virtual table to be checked */ - const char *zSchema, /* Name of schema in which pVtab lives */ - const char *zTabname, /* Name of the pVTab table */ - int isQuick, /* True if this is a quick_check */ - char **pzErr /* Write error message here */ -){ +static int fts3Integrity(sqlite3_vtab *pVtab, char **pzErr){ Fts3Table *p = (Fts3Table*)pVtab; char *zSql; int rc; char *zErr = 0; - assert( pzErr!=0 ); - assert( *pzErr==0 ); - UNUSED_PARAMETER(isQuick); zSql = sqlite3_mprintf( "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');", - zSchema, zTabname, zTabname); + p->zDb, p->zName, p->zName); if( zSql==0 ){ return SQLITE_NOMEM; } rc = sqlite3_exec(p->db, zSql, 0, 0, &zErr); sqlite3_free(zSql); if( (rc&0xff)==SQLITE_CORRUPT ){ *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s", - p->bFts4 ? 4 : 3, zSchema, zTabname); + p->bFts4 ? 4 : 3, p->zDb, p->zName); }else if( rc!=SQLITE_OK ){ *pzErr = sqlite3_mprintf("unable to validate the inverted index for" " FTS%d table %s.%s: %s", - p->bFts4 ? 4 : 3, zSchema, zTabname, zErr); + p->bFts4 ? 4 : 3, p->zDb, p->zName, zErr); } sqlite3_free(zErr); return SQLITE_OK; } Index: ext/fts3/fts3_write.c ================================================================== --- ext/fts3/fts3_write.c +++ ext/fts3/fts3_write.c @@ -3979,12 +3979,10 @@ assert( pNode->n>0 ); assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) ); blobGrowBuffer(pPrev, nTerm, &rc); if( rc!=SQLITE_OK ) return rc; - assert( pPrev!=0 ); - assert( pPrev->a!=0 ); nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm); nSuffix = nTerm - nPrefix; if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; memcpy(pPrev->a, zTerm, nTerm); Index: ext/fts5/fts5_aux.c ================================================================== --- ext/fts5/fts5_aux.c +++ ext/fts5/fts5_aux.c @@ -108,23 +108,19 @@ /************************************************************************* ** Start of highlight() implementation. */ typedef struct HighlightContext HighlightContext; struct HighlightContext { - /* Constant parameters to fts5HighlightCb() */ + CInstIter iter; /* Coalesced Instance Iterator */ + int iPos; /* Current token offset in zIn[] */ int iRangeStart; /* First token to include */ int iRangeEnd; /* If non-zero, last token to include */ const char *zOpen; /* Opening highlight */ const char *zClose; /* Closing highlight */ const char *zIn; /* Input text */ int nIn; /* Size of input text in bytes */ - - /* Variables modified by fts5HighlightCb() */ - CInstIter iter; /* Coalesced Instance Iterator */ - int iPos; /* Current token offset in zIn[] */ - int iOff; /* Have copied up to this offset in zIn[] */ - int bOpen; /* True if highlight is open */ + int iOff; /* Current offset within zIn[] */ char *zOut; /* Output value */ }; /* ** Append text to the HighlightContext output string - p->zOut. Argument @@ -153,12 +149,12 @@ static int fts5HighlightCb( void *pContext, /* Pointer to HighlightContext object */ int tflags, /* Mask of FTS5_TOKEN_* flags */ const char *pToken, /* Buffer containing token */ int nToken, /* Size of token in bytes */ - int iStartOff, /* Start byte offset of token */ - int iEndOff /* End byte offset of token */ + int iStartOff, /* Start offset of token */ + int iEndOff /* End offset of token */ ){ HighlightContext *p = (HighlightContext*)pContext; int rc = SQLITE_OK; int iPos; @@ -170,51 +166,34 @@ if( p->iRangeEnd>=0 ){ if( iPosiRangeStart || iPos>p->iRangeEnd ) return SQLITE_OK; if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff; } - /* If the parenthesis is open, and this token is not part of the current - ** phrase, and the starting byte offset of this token is past the point - ** that has currently been copied into the output buffer, close the - ** parenthesis. */ - if( p->bOpen - && (iPos<=p->iter.iStart || p->iter.iStart<0) - && iStartOff>p->iOff - ){ - fts5HighlightAppend(&rc, p, p->zClose, -1); - p->bOpen = 0; - } - - /* If this is the start of a new phrase, and the highlight is not open: - ** - ** * copy text from the input up to the start of the phrase, and - ** * open the highlight. - */ - if( iPos==p->iter.iStart && p->bOpen==0 ){ + if( iPos==p->iter.iStart ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iStartOff - p->iOff); fts5HighlightAppend(&rc, p, p->zOpen, -1); p->iOff = iStartOff; - p->bOpen = 1; } if( iPos==p->iter.iEnd ){ - if( p->bOpen==0 ){ - assert( p->iRangeEnd>=0 ); + if( p->iRangeEnd>=0 && p->iter.iStartiRangeStart ){ fts5HighlightAppend(&rc, p, p->zOpen, -1); - p->bOpen = 1; } fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); + fts5HighlightAppend(&rc, p, p->zClose, -1); p->iOff = iEndOff; - if( rc==SQLITE_OK ){ rc = fts5CInstIterNext(&p->iter); } } - if( iPos==p->iRangeEnd ){ + if( p->iRangeEnd>=0 && iPos==p->iRangeEnd ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); p->iOff = iEndOff; + if( iPos>=p->iter.iStart && iPositer.iEnd ){ + fts5HighlightAppend(&rc, p, p->zClose, -1); + } } return rc; } @@ -251,13 +230,10 @@ } if( rc==SQLITE_OK ){ rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } - if( ctx.bOpen ){ - fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); - } fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); if( rc==SQLITE_OK ){ sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); } @@ -532,13 +508,10 @@ } if( rc==SQLITE_OK ){ rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } - if( ctx.bOpen ){ - fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); - } if( ctx.iRangeEnd>=(nColSize-1) ){ fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); }else{ fts5HighlightAppend(&rc, &ctx, zEllips, -1); } Index: ext/fts5/fts5_hash.c ================================================================== --- ext/fts5/fts5_hash.c +++ ext/fts5/fts5_hash.c @@ -430,12 +430,14 @@ return pRet; } /* -** Link all tokens from hash table iHash into a list in sorted order. The -** tokens are not removed from the hash table. +** Extract all tokens from hash table iHash and link them into a list +** in sorted order. The hash table is cleared before returning. It is +** the responsibility of the caller to free the elements of the returned +** list. */ static int fts5HashEntrySort( Fts5Hash *pHash, const char *pTerm, int nTerm, /* Query prefix, if any */ Fts5HashEntry **ppSorted Index: ext/fts5/fts5_index.c ================================================================== --- ext/fts5/fts5_index.c +++ ext/fts5/fts5_index.c @@ -355,11 +355,10 @@ int nContentlessDelete; /* Number of contentless delete ops */ int nPendingRow; /* Number of INSERT in hash table */ /* Error state. */ int rc; /* Current error code */ - int flushRc; /* State used by the fts5DataXXX() functions. */ sqlite3_blob *pReader; /* RO incr-blob open on %_data table */ sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ @@ -2718,18 +2717,10 @@ pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); if( pLeaf ){ pLeaf->p = (u8*)pList; } } - - /* The call to sqlite3Fts5HashScanInit() causes the hash table to - ** fill the size field of all existing position lists. This means they - ** can no longer be appended to. Since the only scenario in which they - ** can be appended to is if the previous operation on this table was - ** a DELETE, by clearing the Fts5Index.bDelete flag we can avoid this - ** possibility altogether. */ - p->bDelete = 0; }else{ p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data), (const char*)pTerm, nTerm, (void**)&pLeaf, &nList ); if( pLeaf ){ @@ -4001,11 +3992,10 @@ assert( p->pHash || p->nPendingData==0 ); if( p->pHash ){ sqlite3Fts5HashClear(p->pHash); p->nPendingData = 0; p->nPendingRow = 0; - p->flushRc = SQLITE_OK; } p->nContentlessDelete = 0; } /* @@ -4404,11 +4394,11 @@ ){ Fts5PageWriter *pPage = &pWriter->writer; const u8 *a = aData; int n = nData; - assert( p->pConfig->pgsz>0 || p->rc!=SQLITE_OK ); + assert( p->pConfig->pgsz>0 ); while( p->rc==SQLITE_OK && (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz ){ int nReq = p->pConfig->pgsz - pPage->buf.n - pPage->pgidx.n; int nCopy = 0; @@ -5137,28 +5127,22 @@ } } iOff = iStart; - /* If the position-list for the entry being removed flows over past - ** the end of this page, delete the portion of the position-list on the - ** next page and beyond. - ** - ** Set variable bLastInDoclist to true if this entry happens - ** to be the last rowid in the doclist for its term. */ - if( iNextOff>=iPgIdx ){ - int pgno = pSeg->iLeafPgno+1; - fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist); - iNextOff = iPgIdx; - } - + /* Set variable bLastInDoclist to true if this entry happens to be + ** the last rowid in the doclist for its term. */ if( pSeg->bDel==0 ){ - if( iNextOff!=iPgIdx ){ + if( iNextOff>=iPgIdx ){ + int pgno = pSeg->iLeafPgno+1; + fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist); + iNextOff = iPgIdx; + }else{ /* Loop through the page-footer. If iNextOff (offset of the ** entry following the one we are removing) is equal to the ** offset of a key on this page, then the entry is the last - ** in its doclist. */ + ** in its doclist. */ int iKeyOff = 0; for(iIdx=0; iIdxflushRc ){ - p->rc = p->flushRc; - return; - } if( p->nPendingData || p->nContentlessDelete ){ assert( p->pHash ); fts5FlushOneHash(p); if( p->rc==SQLITE_OK ){ sqlite3Fts5HashClear(p->pHash); p->nPendingData = 0; p->nPendingRow = 0; p->nContentlessDelete = 0; - }else if( p->nPendingData || p->nContentlessDelete ){ - p->flushRc = p->rc; } } } static Fts5Structure *fts5IndexOptimizeStruct( @@ -5676,13 +5654,12 @@ Fts5Structure *pStruct; Fts5Structure *pNew = 0; assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); - assert( p->rc!=SQLITE_OK || p->nContentlessDelete==0 ); + assert( p->nContentlessDelete==0 ); pStruct = fts5StructureRead(p); - assert( p->rc!=SQLITE_OK || pStruct!=0 ); fts5StructureInvalidate(p); if( pStruct ){ pNew = fts5IndexOptimizeStruct(p, pStruct); } @@ -6225,11 +6202,11 @@ } /* Flush the hash table to disk if required */ if( iRowidiWriteRowid || (iRowid==p->iWriteRowid && p->bDelete==0) - || (p->nPendingData > p->pConfig->nHashSize) + || (p->nPendingData > p->pConfig->nHashSize) ){ fts5IndexFlush(p); } p->iWriteRowid = iRowid; @@ -7257,20 +7234,20 @@ fts5DataRelease(pLeaf); } } static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){ - i64 iTermOff = 0; + int iTermOff = 0; int ii; Fts5Buffer buf1 = {0,0,0}; Fts5Buffer buf2 = {0,0,0}; ii = pLeaf->szLeaf; while( iinn && p->rc==SQLITE_OK ){ int res; - i64 iOff; + int iOff; int nIncr; ii += fts5GetVarint32(&pLeaf->p[ii], nIncr); iTermOff += nIncr; iOff = iTermOff; Index: ext/fts5/fts5_main.c ================================================================== --- ext/fts5/fts5_main.c +++ ext/fts5/fts5_main.c @@ -116,11 +116,11 @@ Fts5Table p; /* Public class members from fts5Int.h */ Fts5Storage *pStorage; /* Document store */ Fts5Global *pGlobal; /* Global (connection wide) data */ Fts5Cursor *pSortCsr; /* Sort data from this cursor */ int iSavepoint; /* Successful xSavepoint()+1 */ - + int bInSavepoint; #ifdef SQLITE_DEBUG struct Fts5TransactionState ts; #endif }; @@ -1571,14 +1571,11 @@ pConfig->bPrefixIndex = sqlite3_value_int(pVal); #endif }else if( 0==sqlite3_stricmp("flush", zCmd) ){ rc = sqlite3Fts5FlushToDisk(&pTab->p); }else{ - rc = sqlite3Fts5FlushToDisk(&pTab->p); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); - } + rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); if( rc==SQLITE_OK ){ rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError); } if( rc==SQLITE_OK ){ if( bError ){ @@ -2616,11 +2613,13 @@ sqlite3_vtab *pVtab, /* Virtual table handle */ const char *zName /* New name of table */ ){ int rc; Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + pTab->bInSavepoint = 1; rc = sqlite3Fts5StorageRename(pTab->pStorage, zName); + pTab->bInSavepoint = 0; return rc; } int sqlite3Fts5FlushToDisk(Fts5Table *pTab){ fts5TripCursors((Fts5FullTable*)pTab); @@ -2633,16 +2632,30 @@ ** Flush the contents of the pending-terms table to disk. */ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; int rc = SQLITE_OK; - + char *zSql = 0; fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); - rc = sqlite3Fts5FlushToDisk((Fts5Table*)pVtab); - if( rc==SQLITE_OK ){ - pTab->iSavepoint = iSavepoint+1; + + if( pTab->bInSavepoint==0 ){ + zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')", + pTab->p.pConfig->zDb, pTab->p.pConfig->zName, pTab->p.pConfig->zName + ); + if( zSql ){ + pTab->bInSavepoint = 1; + rc = sqlite3_exec(pTab->p.pConfig->db, zSql, 0, 0, 0); + pTab->bInSavepoint = 0; + sqlite3_free(zSql); + }else{ + rc = SQLITE_NOMEM; + } + if( rc==SQLITE_OK ){ + pTab->iSavepoint = iSavepoint+1; + } } + return rc; } /* ** The xRelease() method. @@ -2670,12 +2683,12 @@ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; int rc = SQLITE_OK; fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); fts5TripCursors(pTab); + pTab->p.pConfig->pgsz = 0; if( (iSavepoint+1)<=pTab->iSavepoint ){ - pTab->p.pConfig->pgsz = 0; rc = sqlite3Fts5StorageRollback(pTab->pStorage); } return rc; } @@ -2899,37 +2912,29 @@ /* ** Run an integrity check on the FTS5 data structures. Return a string ** if anything is found amiss. Return a NULL pointer if everything is ** OK. */ -static int fts5IntegrityMethod( - sqlite3_vtab *pVtab, /* the FTS5 virtual table to check */ - const char *zSchema, /* Name of schema in which this table lives */ - const char *zTabname, /* Name of the table itself */ - int isQuick, /* True if this is a quick-check */ - char **pzErr /* Write error message here */ -){ +static int fts5Integrity(sqlite3_vtab *pVtab, char **pzErr){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; Fts5Config *pConfig = pTab->p.pConfig; char *zSql; char *zErr = 0; int rc; - assert( pzErr!=0 && *pzErr==0 ); - UNUSED_PARAM(isQuick); zSql = sqlite3_mprintf( "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');", - zSchema, zTabname, pConfig->zName); + pConfig->zDb, pConfig->zName, pConfig->zName); if( zSql==0 ) return SQLITE_NOMEM; rc = sqlite3_exec(pConfig->db, zSql, 0, 0, &zErr); sqlite3_free(zSql); if( (rc&0xff)==SQLITE_CORRUPT ){ *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s", - zSchema, zTabname); + pConfig->zDb, pConfig->zName); }else if( rc!=SQLITE_OK ){ *pzErr = sqlite3_mprintf("unable to validate the inverted index for" " FTS5 table %s.%s: %s", - zSchema, zTabname, zErr); + pConfig->zDb, pConfig->zName, zErr); } sqlite3_free(zErr); return SQLITE_OK; } @@ -2957,11 +2962,11 @@ /* xRename */ fts5RenameMethod, /* xSavepoint */ fts5SavepointMethod, /* xRelease */ fts5ReleaseMethod, /* xRollbackTo */ fts5RollbackToMethod, /* xShadowName */ fts5ShadowName, - /* xIntegrity */ fts5IntegrityMethod + /* xIntegrity */ fts5Integrity }; int rc; Fts5Global *pGlobal = 0; Index: ext/fts5/test/fts5corrupt5.test ================================================================== --- ext/fts5/test/fts5corrupt5.test +++ ext/fts5/test/fts5corrupt5.test @@ -878,322 +878,9 @@ } do_catchsql_test 5.4 { UPDATE t1 SET content=randomblob(500); } {1 {database disk image is malformed}} -#------------------------------------------------------------------------- -reset_db -do_test 6.0 { - sqlite3 db {} - db deserialize [decode_hexdb { -.open --hexdb -| size 32768 pagesize 4096 filename crash-42fa37b694d45a.db -| page 1 offset 0 -| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3. -| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07 .....@ ........ -| 96: 00 00 00 00 0d 00 00 00 07 0d d2 00 0f c4 0f 6d ...............m -| 112: 0f 02 0e ab 0e 4e 0d f6 0d d2 00 00 00 00 00 00 .....N.......... -| 3536: 00 00 22 07 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet -| 3552: 32 74 32 07 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE -| 3568: 20 74 32 28 78 29 56 06 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta -| 3584: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c -| 3600: 6f 6e 66 69 67 06 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB -| 3616: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k -| 3632: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v) -| 3648: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 05 WITHOUT ROWID[. -| 3664: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d -| 3680: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize -| 3696: 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't -| 3712: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN -| 3728: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE -| 3744: 59 2c 20 73 7a 20 42 4c 4f 42 29 55 04 06 17 21 Y, sz BLOB)U...! -| 3760: 21 01 77 74 61 62 6c 65 74 31 5f 63 6f 6e 74 65 !.wtablet1_conte -| 3776: 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 04 43 52 45 ntt1_content.CRE -| 3792: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f ATE TABLE 't1_co -| 3808: 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 45 ntent'(id INTEGE -| 3824: 52 20 50 52 49 4d 41 52 49 20 4b 45 59 2c 20 63 R PRIMARI KEY, c -| 3840: 30 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 0)i.......-table -| 3856: 74 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 t1_idxt1_idx.CRE -| 3872: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 ATE TABLE 't1_id -| 3888: 78 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 x'(segid, term, -| 3904: 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 pgno, PRIMARY KE -| 3920: 59 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 Y(segid, term)) -| 3936: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 WITHOUT ROWIDU.. -| 3952: 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 ......tablet1_da -| 3968: 74 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 tat1_data.CREATE -| 3984: 20 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 TABLE 't1_data' -| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM -| 4016: 41 52 b9 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 AR. KEY, block B -| 4032: 4c 4f 42 29 3a 01 06 17 11 11 08 63 74 61 62 6c LOB):......ctabl -| 4048: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT -| 4064: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI -| 4080: 4e 47 20 66 74 73 35 28 63 6f 6e 74 65 6e 74 29 NG fts5(content) -| page 2 offset 4096 -| 0: 0d 00 00 00 03 0f bd 00 0f e8 0f ef 0f bd f0 00 ................ -| 16: 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ -| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 24 84 80 .............$.. -| 4032: 80 80 80 01 03 00 4e 00 10 00 1e 06 30 61 62 61 ......N.....0aba -| 4048: 63 6c 01 02 02 04 02 66 74 02 5f 02 04 04 6e 64 cl.....ft._...nd -| 4064: 6f 6e 02 02 02 04 0a 07 05 01 03 00 10 03 03 0f on.............. -| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 11 ...$............ -| page 3 offset 8192 -| 0: 0a 00 00 00 01 0f 00 01 00 00 00 00 00 00 00 00 ................ -| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ -| page 4 offset 12288 -| 0: 0d 00 00 00 03 0f e0 00 0f f6 0f ec 0f e0 00 00 ................ -| 4064: 0a 03 03 00 1b 61 62 61 6e 64 6f 6e 08 02 03 00 .....abandon.... -| 4080: 17 61 62 61 66 74 08 01 03 00 17 61 62 61 63 6b .abaft.....aback -| page 5 offset 16384 -| 0: 0d 00 00 00 03 0f ee 00 0f fa 0f 00 00 00 00 00 ................ -| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 03 ................ -| 4080: 03 00 0e 01 04 02 03 00 0e 01 04 01 03 00 0e 01 ................ -| page 6 offset 20480 -| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ -| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. -| page 7 offset 24576 -| 0: 0d 00 00 10 03 0f d6 00 0f 00 00 00 00 00 00 00 ................ -| 4048: 00 00 00 00 00 00 09 03 02 1b 72 65 62 75 69 6c ..........rebuil -| 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c -| 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 00 00 00 heck....optim... -| page 8 offset 28672 -| 0: 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ -| end crash-42fa37b694d45a.db -}]} {} - -do_execsql_test 6.1 { - INSERT INTO t1(t1,rank) VALUES('secure-delete',1); -} -do_catchsql_test 6.2 { - UPDATE t1 SET content=randomblob(500) WHERE t1; -} {1 {constraint failed}} - -#------------------------------------------------------------------------- -reset_db -do_test 9.0 { - sqlite3 db {} - db deserialize [decode_hexdb { -.open --hexdb -| size 32768 pagesize 4096 filename crash-c76a16c24c8ba6.db -| page 1 offset 0 -| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3. -| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........ -| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................ -| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6 -| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............ -| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet -| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE -| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta -| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c -| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB -| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k -| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v) -| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[. -| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d -| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize -| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't -| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN -| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE -| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...! -| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont -| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR -| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c -| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG -| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY, -| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i.... -| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt -| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB -| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi -| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P -| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid -| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT -| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t -| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da -| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE -| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT -| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY -| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8.. -| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR -| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB -| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5 -| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c)......... -| page 3 offset 8192 -| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................ -| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J.......... -| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00......... -| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160 -| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4. -| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5..... -| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000... -| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary.. -| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................ -| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................ -| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ -| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp -| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d -| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat........... -| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e -| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable........... -| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................ -| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................ -| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................ -| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension.. -| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4... -| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5....... -| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc......... -| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........ -| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........ -| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load......... -| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max........... -| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory........... -| 3648: 73 79 73 35 16 02 03 01 02 03 01 02 03 01 06 6e sys5...........n -| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase........... -| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................ -| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................ -| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................ -| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit......... -| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree......... -| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............ -| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................ -| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................ -| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ -| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 03 57 34 56 ..threadsafe.W4V -| 3840: 94 64 91 46 85 84 04 76 74 61 62 07 02 04 01 02 .d.F...vtab..... -| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x......... -| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 10 02 ................ -| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................ -| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................ -| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................ -| 3936: 01 02 01 06 01 01 10 01 06 01 01 02 01 06 01 01 ................ -| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................ -| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................ -| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................ -| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................ -| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................ -| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................ -| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G.......... -| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$. -| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............ -| page 4 offset 12288 -| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................ -| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ -| page 5 offset 16384 -| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t -| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./.......... -| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$...... -| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5.... -| 64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a .......x.W.>.$.. -| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%. -| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI -| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA -| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE.. -| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 31 46 45 3d ..%..THREADS1FE= -| 3152: 30 58 52 64 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRdRIM.!..3..OM -| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO -| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O -| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI -| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3.. -| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS -| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3.. -| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000 -| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3. -| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000 -| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3 -| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500 -| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....% -| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB -| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB -| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE. -| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR -| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E -| 3440: 4e 41 42 4b 45 20 4d 45 4d 53 59 53 35 58 42 49 NABKE MEMSYS5XBI -| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL -| 3472: 42 60 2d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 B`-EMSYS5XNOCASE -| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45 ....)..ENABLE ME -| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....% -| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB -| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB -| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE. -| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO -| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E -| 3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 NABLE GEOPOLYXBI -| 3616: 4e 41 52 59 1a 11 05 00 39 0f 19 45 4e 41 42 4c NARY....9..ENABL -| 3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45 E GEOPOLYXNOCASE -| 3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 45 ....)..ENABLE GE -| 3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23 OPOLYXRTRIM....# -| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI -| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL -| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE... -| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X -| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB -| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY.. -| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4 -| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN -| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM. -| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS -| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY. -| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS -| 3872: 54 41 54 20 56 54 24 15 48 4e 4f 43 41 53 45 1d TAT VT$.HNOCASE. -| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS -| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM.. -| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR -| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO -| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG -| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM -| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0 -| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY' -| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3c 67 ...C..COMPILERxFetch(pFd, pgsz*iPg, pgsz, (void**)&pMap); if( rc!=SQLITE_OK || pMap==0 ) break; - nTotal += (unsigned int)pMap[0]; - nTotal += (unsigned int)pMap[pgsz-1]; + nTotal += pMap[0]; + nTotal += pMap[pgsz-1]; rc = p->xUnfetch(pFd, pgsz*iPg, (void*)pMap); if( rc!=SQLITE_OK ) break; iPg++; } @@ -101,8 +101,7 @@ rc2 = sqlite3_exec(db, "END", 0, 0, 0); if( rc==SQLITE_OK ) rc = rc2; } - (void)nTotal; return rc; } Index: ext/misc/randomjson.c ================================================================== --- ext/misc/randomjson.c +++ ext/misc/randomjson.c @@ -50,11 +50,11 @@ p->y = p->y*1103515245 + 12345; return p->x ^ p->y; } static const char *azJsonAtoms[] = { -/* JSON JSON-5 */ + /* JSON /* JSON-5 */ "0", "0", "1", "1", "-1", "-1", "2", "+2", "3", "3", Index: ext/misc/zipfile.c ================================================================== --- ext/misc/zipfile.c +++ ext/misc/zipfile.c @@ -27,11 +27,10 @@ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include #include #include -#include #include #ifndef SQLITE_OMIT_VIRTUALTABLE Index: ext/rtree/rtree.c ================================================================== --- ext/rtree/rtree.c +++ ext/rtree/rtree.c @@ -168,11 +168,10 @@ char *zName; /* Name of r-tree table */ char *zNodeName; /* Name of the %_node table */ u32 nBusy; /* Current number of users of this structure */ i64 nRowEst; /* Estimated number of rows in this table */ u32 nCursor; /* Number of open cursors */ - u32 iGeneration; /* Cursors with smaller iGeneration are stale */ u32 nNodeRef; /* Number RtreeNodes with positive nRef */ char *zReadAuxSql; /* SQL for statement to read aux data */ /* List of nodes removed during a CondenseTree operation. List is ** linked together via the pointer normally used for hash chains - @@ -285,11 +284,10 @@ struct RtreeCursor { sqlite3_vtab_cursor base; /* Base class. Must be first */ u8 atEOF; /* True if at end of search */ u8 bPoint; /* True if sPoint is valid */ u8 bAuxValid; /* True if pReadAux is valid */ - u32 iGeneration; /* Stale if too small */ int iStrategy; /* Copy of idxNum search parameter */ int nConstraint; /* Number of entries in aConstraint */ RtreeConstraint *aConstraint; /* Search constraints. */ int nPointAlloc; /* Number of slots allocated for aPoint[] */ int nPoint; /* Number of slots used in aPoint[] */ @@ -694,13 +692,15 @@ /* ** Clear the Rtree.pNodeBlob object */ static void nodeBlobReset(Rtree *pRtree){ - sqlite3_blob *pBlob = pRtree->pNodeBlob; - pRtree->pNodeBlob = 0; - sqlite3_blob_close(pBlob); + if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){ + sqlite3_blob *pBlob = pRtree->pNodeBlob; + pRtree->pNodeBlob = 0; + sqlite3_blob_close(pBlob); + } } /* ** Obtain a reference to an r-tree node. */ @@ -740,10 +740,11 @@ rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, pRtree->zNodeName, "data", iNode, 0, &pRtree->pNodeBlob); } if( rc ){ + nodeBlobReset(pRtree); *ppNode = 0; /* If unable to open an sqlite3_blob on the desired row, that can only ** be because the shadow tables hold erroneous data. */ if( rc==SQLITE_ERROR ){ rc = SQLITE_CORRUPT_VTAB; @@ -799,11 +800,10 @@ rc = SQLITE_CORRUPT_VTAB; RTREE_IS_CORRUPT(pRtree); } *ppNode = pNode; }else{ - nodeBlobReset(pRtree); if( pNode ){ pRtree->nNodeRef--; sqlite3_free(pNode); } *ppNode = 0; @@ -1085,11 +1085,10 @@ pCsr = (RtreeCursor *)sqlite3_malloc64(sizeof(RtreeCursor)); if( pCsr ){ memset(pCsr, 0, sizeof(RtreeCursor)); pCsr->base.pVtab = pVTab; - pCsr->iGeneration = pRtree->iGeneration; rc = SQLITE_OK; pRtree->nCursor++; } *ppCursor = (sqlite3_vtab_cursor *)pCsr; @@ -1134,13 +1133,11 @@ assert( pRtree->nCursor>0 ); resetCursor(pCsr); sqlite3_finalize(pCsr->pReadAux); sqlite3_free(pCsr); pRtree->nCursor--; - if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){ - nodeBlobReset(pRtree); - } + nodeBlobReset(pRtree); return SQLITE_OK; } /* ** Rtree virtual table module xEof method. @@ -1628,13 +1625,10 @@ int nConstraint = pCur->nConstraint; int ii; int eInt; RtreeSearchPoint x; - if( pCur->iGenerationiGeneration ){ - return SQLITE_ABORT_ROLLBACK; - } eInt = pRtree->eCoordType==RTREE_COORD_INT32; while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){ u8 *pCellData; pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc); if( rc ) return rc; @@ -1858,11 +1852,10 @@ rtreeReference(pRtree); /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ resetCursor(pCsr); - pCsr->iGeneration = pRtree->iGeneration; pCsr->iStrategy = idxNum; if( idxNum==1 ){ /* Special case - lookup by rowid. */ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ @@ -3224,11 +3217,12 @@ /* ** Called when a transaction starts. */ static int rtreeBeginTransaction(sqlite3_vtab *pVtab){ Rtree *pRtree = (Rtree *)pVtab; - pRtree->inWrTrans = 1; + assert( pRtree->inWrTrans==0 ); + pRtree->inWrTrans++; return SQLITE_OK; } /* ** Called when a transaction completes (either by COMMIT or ROLLBACK). @@ -3238,20 +3232,10 @@ Rtree *pRtree = (Rtree *)pVtab; pRtree->inWrTrans = 0; nodeBlobReset(pRtree); return SQLITE_OK; } -static int rtreeRollback(sqlite3_vtab *pVtab){ - Rtree *pRtree = (Rtree *)pVtab; - pRtree->iGeneration++; - return rtreeEndTransaction(pVtab); -} -static int rtreeRollbackTo(sqlite3_vtab *pVtab, int notUsed){ - Rtree *pRtree = (Rtree *)pVtab; - pRtree->iGeneration++; - return SQLITE_OK; -} /* ** The xRename method for rtree module virtual tables. */ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){ @@ -3346,11 +3330,11 @@ } return 0; } /* Forward declaration */ -static int rtreeIntegrity(sqlite3_vtab*, const char*, const char*, int, char**); +static int rtreeIntegrity(sqlite3_vtab*, char**); static sqlite3_module rtreeModule = { 4, /* iVersion */ rtreeCreate, /* xCreate - create a table */ rtreeConnect, /* xConnect - connect to an existing table */ @@ -3366,16 +3350,16 @@ rtreeRowid, /* xRowid - read data */ rtreeUpdate, /* xUpdate - write data */ rtreeBeginTransaction, /* xBegin - begin transaction */ rtreeEndTransaction, /* xSync - sync transaction */ rtreeEndTransaction, /* xCommit - commit transaction */ - rtreeRollback, /* xRollback - rollback transaction */ + rtreeEndTransaction, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ rtreeRename, /* xRename - rename the table */ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ - rtreeRollbackTo, /* xRollbackTo */ + 0, /* xRollbackTo */ rtreeShadowName, /* xShadowName */ rtreeIntegrity /* xIntegrity */ }; static int rtreeSqlInit( @@ -4201,23 +4185,13 @@ } /* ** Implementation of the xIntegrity method for Rtree. */ -static int rtreeIntegrity( - sqlite3_vtab *pVtab, /* The virtual table to check */ - const char *zSchema, /* Schema in which the virtual table lives */ - const char *zName, /* Name of the virtual table */ - int isQuick, /* True for a quick_check */ - char **pzErr /* Write results here */ -){ +static int rtreeIntegrity(sqlite3_vtab *pVtab, char **pzErr){ Rtree *pRtree = (Rtree*)pVtab; int rc; - assert( pzErr!=0 && *pzErr==0 ); - UNUSED_PARAMETER(zSchema); - UNUSED_PARAMETER(zName); - UNUSED_PARAMETER(isQuick); rc = rtreeCheckTable(pRtree->db, pRtree->zDb, pRtree->zName, pzErr); if( rc==SQLITE_OK && *pzErr ){ *pzErr = sqlite3_mprintf("In RTree %s.%s:\n%z", pRtree->zDb, pRtree->zName, *pzErr); } Index: ext/rtree/rtree1.test ================================================================== --- ext/rtree/rtree1.test +++ ext/rtree/rtree1.test @@ -772,21 +772,19 @@ # 2023-05-22 https://sqlite.org/forum/forumpost/da70ee0d0d # Round-off error associated with using large integer constraints on # a rtree search. # -if {$tcl_platform(machine)!="i686" || $tcl_platform(os)!="Linux"} { - reset_db - do_execsql_test 22.0 { - CREATE VIRTUAL TABLE t1 USING rtree ( id, x0, x1 ); - INSERT INTO t1 VALUES (123, 9223372036854775799, 9223372036854775800); - SELECT id FROM t1 WHERE x0 > 9223372036854775807; - } {123} - do_execsql_test 22.1 { - SELECT id, x0 > 9223372036854775807 AS 'a0' FROM t1; - } {123 1} -} +reset_db +do_execsql_test 22.0 { + CREATE VIRTUAL TABLE t1 USING rtree ( id, x0, x1 ); + INSERT INTO t1 VALUES (123, 9223372036854775799, 9223372036854775800); + SELECT id FROM t1 WHERE x0 > 9223372036854775807; +} {123} +do_execsql_test 22.1 { + SELECT id, x0 > 9223372036854775807 AS 'a0' FROM t1; +} {123 1} # 2023-10-14 dbsqlfuzz --sql-fuzz find. rtreecheck() should not call # BEGIN/COMMIT because that causes problems with statement transactions, # and it is unnecessary. # DELETED ext/rtree/rtreeJ.test Index: ext/rtree/rtreeJ.test ================================================================== --- ext/rtree/rtreeJ.test +++ /dev/null @@ -1,163 +0,0 @@ -# 2024-02-03 -# -# The author disclaims copyright to this source code. In place of -# a legal notice, here is a blessing: -# -# May you do good and not evil. -# May you find forgiveness for yourself and forgive others. -# May you share freely, never taking more than you give. -# -#*********************************************************************** -# -# ROLLBACK in the middle of an RTREE query -# -if {![info exists testdir]} { - set testdir [file join [file dirname [info script]] .. .. test] -} -source $testdir/tester.tcl -set testprefix rtreeJ -ifcapable !rtree { - finish_test - return -} - -do_execsql_test 1.0 { - CREATE VIRTUAL TABLE t1 USING rtree(id, x1, x2); - INSERT INTO t1 VALUES(1, 1, 1), (2, 2, 2); -} {} - -do_execsql_test 1.1 { - SELECT * FROM t1 -} {1 1.0 1.0 2 2.0 2.0} - -# If a ROLLBACK occurs that backs out changes to the RTREE, then -# all pending queries to the RTREE are aborted. -# -do_test 1.2 { - db eval { - BEGIN; - INSERT INTO t1 VALUES(3, 3, 3); - INSERT INTO t1 VALUES(4, 4, 4); - } - set rc [catch { - db eval { SELECT * FROM t1 } { - if {$id==1} { - db eval { ROLLBACK } - } - lappend res $id $x1 $x2 - } - } msg] - list $rc $msg -} {1 {abort due to ROLLBACK}} - -do_execsql_test 1.3 { - SELECT * FROM t1; -} {1 1.0 1.0 2 2.0 2.0} - -# A COMMIT of changes to the RTREE does not affect pending queries -# -do_test 1.4 { - set res {} - db eval { - BEGIN; - INSERT INTO t1 VALUES(5, 5, 5); - INSERT INTO t1 VALUES(6, 6, 6); - } - db eval { SELECT * FROM t1 } { - if {$id==1} { - db eval { COMMIT } - } - lappend res $id $x1 $x2 - } - set res -} {1 1.0 1.0 2 2.0 2.0 5 5.0 5.0 6 6.0 6.0} - -do_execsql_test 1.5 { - SELECT * FROM t1; -} {1 1.0 1.0 2 2.0 2.0 5 5.0 5.0 6 6.0 6.0} - -do_execsql_test 1.6 { - DELETE FROM t1; - INSERT INTO t1 VALUES(1,1,1),(2,2,2),(3,3,3),(4,4,4); - CREATE TABLE t2(x); - SELECT * FROM t1; -} {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0 4 4.0 4.0} - -# A rollback that does not affect the rtree table because -# the rtree table has not been written to does not cause -# a query abort. -# -do_test 1.7 { - set res {} - db eval { - BEGIN; - INSERT INTO t2(x) VALUES(12345); - } - db eval { SELECT * FROM t1 } { - if {$id==1} { - db eval { ROLLBACK } - } - lappend res $id $x1 $x2 - } - set res -} {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0 4 4.0 4.0} - -# ROLLBACK TO that affects the RTREE does cause a query abort. -# -do_test 1.8 { - db eval { - DELETE FROM t1 WHERE rowid>1; - BEGIN; - DELETE FROM t2; - INSERT INTO t2(x) VALUES(23456); - SAVEPOINT 'one'; - INSERT INTO t1 VALUES(2,2,2),(3,3,3); - } - set rc [catch { - db eval { SELECT * FROM t1 } { - if {$id==1} { - db eval { ROLLBACK TO 'one'; } - } - lappend res $id $x1 $x2 - } - } msg] - list $rc $msg -} {1 {abort due to ROLLBACK}} - -do_execsql_test 1.9 { - COMMIT; - SELECT * FROM t1; -} {1 1.0 1.0} - -# ROLLBACK TO that does not affect the RTREE does not cause a query abort. -# -do_execsql_test 1.10 { - DELETE FROM t1; - INSERT INTO t1 VALUES(1,1,1),(2,2,2),(3,3,3); - BEGIN; - DELETE FROM t2; - INSERT INTO t2(x) VALUES(34567); - SAVEPOINT 'one'; - INSERT INTO t2(x) VALUES('a string'); - SELECT * FROM t1; -} {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0} -do_test 1.11 { - set rc [catch { - set res {} - db eval { SELECT * FROM t1 } { - if {$id==2} { - # db eval { ROLLBACK TO 'one'; } - } - lappend res $id $x1 $x2 - } - set res - } msg] - list $rc $msg -} {0 {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0}} - -do_execsql_test 1.12 { - COMMIT; - SELECT * FROM t1; -} {1 1.0 1.0 2 2.0 2.0 3 3.0 3.0} - -finish_test Index: ext/session/sqlite3session.c ================================================================== --- ext/session/sqlite3session.c +++ ext/session/sqlite3session.c @@ -601,14 +601,12 @@ ** The buffer that the argument points to contains a serialized SQL value. ** Return the number of bytes of space occupied by the value (including ** the type byte). */ static int sessionSerialLen(const u8 *a){ - int e; + int e = *a; int n; - assert( a!=0 ); - e = *a; if( e==0 || e==0xFF ) return 1; if( e==SQLITE_NULL ) return 1; if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; return sessionVarintGet(&a[1], &n) + 1 + n; } @@ -1266,11 +1264,11 @@ pSession->nMaxChangesetSize -= sessionVarintLen(nOldCol); } } } - sqlite3_free((char*)azCol); + sqlite3_free(azCol); return pSession->rc; } /* ** Session-change object (*pp) contains an old.* record with fewer than @@ -5450,11 +5448,10 @@ int nRec, /* Number of bytes in aRec */ SessionChange **ppNew /* OUT: Merged change */ ){ SessionChange *pNew = 0; int rc = SQLITE_OK; - assert( aRec!=0 ); if( !pExist ){ pNew = (SessionChange *)sqlite3_malloc64(sizeof(SessionChange) + nRec); if( !pNew ){ return SQLITE_NOMEM; Index: ext/session/test_session.c ================================================================== --- ext/session/test_session.c +++ ext/session/test_session.c @@ -390,10 +390,11 @@ { "rowid", SQLITE_SESSION_OBJCONFIG_ROWID }, { 0, 0 } }; size_t sz = sizeof(aOpt[0]); + int rc; int iArg; int iOpt; if( Tcl_GetIndexFromObjStruct(interp,objv[2],aOpt,sz,"option",0,&iOpt) ){ return TCL_ERROR; } Index: ext/wasm/api/sqlite3-wasm.c ================================================================== --- ext/wasm/api/sqlite3-wasm.c +++ ext/wasm/api/sqlite3-wasm.c @@ -126,10 +126,16 @@ # define SQLITE_ENABLE_STMTVTAB 1 #endif #ifndef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION # define SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION #endif + +/**********************************************************************/ +/* SQLITE_M... */ +#ifndef SQLITE_MAX_ALLOCATION_SIZE +# define SQLITE_MAX_ALLOCATION_SIZE 0x1fffffff +#endif /**********************************************************************/ /* SQLITE_O... */ #ifndef SQLITE_OMIT_DEPRECATED # define SQLITE_OMIT_DEPRECATED 1 @@ -875,11 +881,11 @@ DefInt(SQLITE_STMTSTATUS_RUN); DefInt(SQLITE_STMTSTATUS_FILTER_MISS); DefInt(SQLITE_STMTSTATUS_FILTER_HIT); DefInt(SQLITE_STMTSTATUS_MEMUSED); } _DefGroup; - + DefGroup(syncFlags) { DefInt(SQLITE_SYNC_NORMAL); DefInt(SQLITE_SYNC_FULL); DefInt(SQLITE_SYNC_DATAONLY); } _DefGroup; @@ -899,12 +905,10 @@ DefGroup(udfFlags) { DefInt(SQLITE_DETERMINISTIC); DefInt(SQLITE_DIRECTONLY); DefInt(SQLITE_INNOCUOUS); - DefInt(SQLITE_SUBTYPE); - DefInt(SQLITE_RESULT_SUBTYPE); } _DefGroup; DefGroup(version) { DefInt(SQLITE_VERSION_NUMBER); DefStr(SQLITE_VERSION); Index: ext/wasm/api/sqlite3-worker1-promiser.c-pp.js ================================================================== --- ext/wasm/api/sqlite3-worker1-promiser.c-pp.js +++ ext/wasm/api/sqlite3-worker1-promiser.c-pp.js @@ -197,15 +197,14 @@ msg = arguments[0]; }else if(2===arguments.length){ msg = Object.create(null); msg.type = arguments[0]; msg.args = arguments[1]; - msg.dbId = msg.args.dbId; }else{ toss("Invalid arugments for sqlite3Worker1Promiser()-created factory."); } - if(!msg.dbId && msg.type!=='open') msg.dbId = dbId; + if(!msg.dbId) msg.dbId = dbId; msg.messageId = genMsgId(msg); msg.departureTime = performance.now(); const proxy = Object.create(null); proxy.message = msg; let rowCallbackId /* message handler ID for exec on-row callback proxy */; @@ -246,12 +245,13 @@ }; }/*sqlite3Worker1Promiser()*/; globalThis.sqlite3Worker1Promiser.defaultConfig = { worker: function(){ //#if target=es6-bundler-friendly - return new Worker(new URL("sqlite3-worker1-bundler-friendly.mjs", import.meta.url),{ - type: 'module' + return new Worker("sqlite3-worker1-bundler-friendly.mjs",{ + type: 'module' /* Noting that neither Firefox nor Safari suppor this, + as of this writing. */ }); //#else let theJs = "sqlite3-worker1.js"; if(this.currentScript){ const src = this.currentScript.src.split('/'); @@ -265,14 +265,10 @@ theJs = urlParams.get('sqlite3.dir') + '/' + theJs; } } return new Worker(theJs + globalThis.location.search); //#endif - } -//#ifnot target=es6-bundler-friendly - .bind({ + }.bind({ currentScript: globalThis?.document?.currentScript - }) -//#endif - , + }), onerror: (...args)=>console.error('worker1 promiser error',...args) }; Index: main.mk ================================================================== --- main.mk +++ main.mk @@ -595,21 +595,11 @@ dbfuzz2$(EXE): $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h $(TCCX) -I. -g -O0 -DSTANDALONE -o dbfuzz2$(EXE) \ $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS) $(THREADLIB) fuzzcheck$(EXE): $(FUZZSRC) sqlite3.c sqlite3.h $(FUZZDEP) - $(TCCX) -o $@ -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ - -DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \ - $(FUZZSRC) sqlite3.c $(TLIBS) $(THREADLIB) - -fuzzcheck-asan$(EXE): $(FUZZSRC) sqlite3.c sqlite3.h $(FUZZDEP) - $(TCCX) -fsanitize=address -o $W -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ - -DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \ - $(FUZZSRC) sqlite3.c $(TLIBS) $(THREADLIB) - -fuzzcheck-ubsan$(EXE): $(FUZZSRC) sqlite3.c sqlite3.h $(FUZZDEP) - $(TCCX) -fsanitize=undefined -o $@ -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ + $(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \ $(FUZZSRC) sqlite3.c $(TLIBS) $(THREADLIB) ossshell$(EXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(TCCX) -o ossshell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -6279,14 +6279,11 @@ if( pCur->skipNext<0 ) return SQLITE_OK; } } pPage = pCur->pPage; - if( sqlite3FaultSim(412) ) pPage->isInit = 0; - if( !pPage->isInit ){ - return SQLITE_CORRUPT_BKPT; - } + assert( pPage->isInit ); if( !pPage->leaf ){ int idx = pCur->ix; rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); if( rc ) return rc; rc = moveToRightmost(pCur); @@ -10460,20 +10457,18 @@ /* ** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that ** corresponds to page iPg is already set. */ static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( pCheck->aPgRef!=0 ); assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); } /* ** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. */ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( pCheck->aPgRef!=0 ); assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); } @@ -10485,10 +10480,11 @@ ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ if( iPage>pCheck->nCkPage || iPage==0 ){ + if( pCheck->nCkPage==0 ) return 0; /* omit reference counting */ checkAppendMsg(pCheck, "invalid page number %u", iPage); return 1; } if( getPageReferenced(pCheck, iPage) ){ checkAppendMsg(pCheck, "2nd reference to page %u", iPage); @@ -10990,14 +10986,19 @@ sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; if( sCheck.nCkPage==0 ){ goto integrity_ck_cleanup; } - sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); - if( !sCheck.aPgRef ){ - checkOom(&sCheck); - goto integrity_ck_cleanup; + if( bPartial ){ + sCheck.nCkPage = 0; + sCheck.aPgRef = 0; + }else{ + sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); + if( !sCheck.aPgRef ){ + checkOom(&sCheck); + goto integrity_ck_cleanup; + } } sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); if( sCheck.heap==0 ){ checkOom(&sCheck); goto integrity_ck_cleanup; Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -1405,17 +1405,24 @@ pTab->tabFlags |= TF_OOOHidden; } } #endif +/* +** Name of the special TEMP trigger used to implement RETURNING. The +** name begins with "sqlite_" so that it is guaranteed not to collide +** with any application-generated triggers. +*/ +#define RETURNING_TRIGGER_NAME "sqlite_returning" + /* ** Clean up the data structures associated with the RETURNING clause. */ static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){ Hash *pHash; pHash = &(db->aDb[1].pSchema->trigHash); - sqlite3HashInsert(pHash, pRet->zName, 0); + sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0); sqlite3ExprListDelete(db, pRet->pReturnEL); sqlite3DbFree(db, pRet); } /* @@ -1454,13 +1461,11 @@ pRet->pReturnEL = pList; sqlite3ParserAddCleanup(pParse, (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet); testcase( pParse->earlyCleanup ); if( db->mallocFailed ) return; - sqlite3_snprintf(sizeof(pRet->zName), pRet->zName, - "sqlite_returning_%p", pParse); - pRet->retTrig.zName = pRet->zName; + pRet->retTrig.zName = RETURNING_TRIGGER_NAME; pRet->retTrig.op = TK_RETURNING; pRet->retTrig.tr_tm = TRIGGER_AFTER; pRet->retTrig.bReturning = 1; pRet->retTrig.pSchema = db->aDb[1].pSchema; pRet->retTrig.pTabSchema = db->aDb[1].pSchema; @@ -1467,13 +1472,13 @@ pRet->retTrig.step_list = &pRet->retTStep; pRet->retTStep.op = TK_RETURNING; pRet->retTStep.pTrig = &pRet->retTrig; pRet->retTStep.pExprList = pList; pHash = &(db->aDb[1].pSchema->trigHash); - assert( sqlite3HashFind(pHash, pRet->zName)==0 + assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr || pParse->ifNotExists ); - if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig) + if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig) ==&pRet->retTrig ){ sqlite3OomFault(db); } } @@ -3000,16 +3005,13 @@ /* Legacy versions of SQLite allowed the use of the magic "rowid" column ** on a view, even though views do not have rowids. The following flag ** setting fixes this problem. But the fix can be disabled by compiling ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that - ** depend upon the old buggy behavior. The ability can also be toggled - ** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */ -#else - p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */ + ** depend upon the old buggy behavior. */ +#ifndef SQLITE_ALLOW_ROWID_IN_VIEW + p->tabFlags |= TF_NoVisibleRowid; #endif sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -216,14 +216,13 @@ if( ExprHasProperty(pExpr, EP_Unlikely) ){ assert( ExprUseXList(pExpr) ); assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; - }else if( pExpr->op==TK_COLLATE ){ - pExpr = pExpr->pLeft; }else{ - break; + assert( pExpr->op==TK_COLLATE ); + pExpr = pExpr->pLeft; } } return pExpr; } @@ -1637,12 +1636,11 @@ assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= nNewSize+nToken ); assert( ExprHasProperty(p, EP_Reduced)==0 ); memcpy(sEdupBuf.zAlloc, p, nNewSize); }else{ u32 nSize = (u32)exprStructSize(p); - assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= - (int)EXPR_FULLSIZE+nToken ); + assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= EXPR_FULLSIZE+nToken ); memcpy(sEdupBuf.zAlloc, p, nSize); if( nSizey.pTab==0 /* Reference to column of index on expression */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - || (p->iColumn==XN_ROWID && IsView(p->y.pTab)) -#endif - || (p->iColumn>=0 + return ExprHasProperty(p, EP_CanBeNull) || + p->y.pTab==0 || /* Reference to column of index on expression */ + (p->iColumn>=0 && p->y.pTab->aCol!=0 /* Possible due to prior error */ && p->y.pTab->aCol[p->iColumn].notNull==0); default: return 1; } @@ -5324,14 +5319,12 @@ assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); if( pParse->pVdbe==0 ) return; inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); if( inReg!=target ){ u8 op; - Expr *pX = sqlite3ExprSkipCollateAndLikely(pExpr); - testcase( pX!=pExpr ); - if( ALWAYS(pX) - && (ExprHasProperty(pX,EP_Subquery) || pX->op==TK_REGISTER) + if( ALWAYS(pExpr) + && (ExprHasProperty(pExpr,EP_Subquery) || pExpr->op==TK_REGISTER) ){ op = OP_Copy; }else{ op = OP_SCopy; } @@ -6047,12 +6040,12 @@ ** Like sqlite3ExprCompare() except COLLATE operators at the top-level ** are ignored. */ int sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){ return sqlite3ExprCompare(0, - sqlite3ExprSkipCollate(pA), - sqlite3ExprSkipCollate(pB), + sqlite3ExprSkipCollateAndLikely(pA), + sqlite3ExprSkipCollateAndLikely(pB), iTab); } /* ** Return non-zero if Expr p can only be true if pNN is not NULL. @@ -6811,21 +6804,20 @@ assert( pExpr->pLeft->op==TK_ORDER ); assert( ExprUseXList(pExpr->pLeft) ); pItem->iOBTab = pParse->nTab++; pOBList = pExpr->pLeft->x.pList; assert( pOBList->nExpr>0 ); - assert( pItem->bOBUnique==0 ); if( pOBList->nExpr==1 && nArg==1 && sqlite3ExprCompare(0,pOBList->a[0].pExpr, pExpr->x.pList->a[0].pExpr,0)==0 ){ pItem->bOBPayload = 0; - pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct); }else{ pItem->bOBPayload = 1; } + pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct); }else{ pItem->iOBTab = -1; } if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){ pItem->iDistinct = pParse->nTab++; Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1890,11 +1890,11 @@ p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ if( p->approx ){ if( p->ovrfl ){ sqlite3_result_error(context,"integer overflow",-1); - }else if( !sqlite3IsOverflow(p->rErr) ){ + }else if( !sqlite3IsNaN(p->rErr) ){ sqlite3_result_double(context, p->rSum+p->rErr); }else{ sqlite3_result_double(context, p->rSum); } }else{ @@ -1907,11 +1907,11 @@ p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ double r; if( p->approx ){ r = p->rSum; - if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr; + if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; }else{ r = (double)(p->iSum); } sqlite3_result_double(context, r/(double)p->cnt); } @@ -1921,11 +1921,11 @@ double r = 0.0; p = sqlite3_aggregate_context(context, 0); if( p ){ if( p->approx ){ r = p->rSum; - if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr; + if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; }else{ r = (double)(p->iSum); } } sqlite3_result_double(context, r); Index: src/global.c ================================================================== --- src/global.c +++ src/global.c @@ -284,13 +284,10 @@ SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */ #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - 0, /* mNoVisibleRowid. 0 == allow rowid-in-view */ -#endif 0, /* bLocaltimeFault */ 0, /* xAltLocaltime */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ 0, /* iPrngSeed */ Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -1084,11 +1084,11 @@ pNx->pUpsertSrc = pTabList; pNx->regData = regData; pNx->iDataCur = iDataCur; pNx->iIdxCur = iIdxCur; if( pNx->pUpsertTarget ){ - if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){ + if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){ goto insert_cleanup; } } pNx = pNx->pNextUpsert; }while( pNx!=0 ); @@ -2976,14 +2976,11 @@ ** further downstream. */ return 0; /* Corrupt schema - two indexes on the same btree */ } } #ifndef SQLITE_OMIT_CHECK - if( pDest->pCheck - && (db->mDbFlags & DBFLAG_Vacuum)==0 - && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) - ){ + if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){ return 0; /* Tables have different CHECK constraints. Ticket #2252 */ } #endif #ifndef SQLITE_OMIT_FOREIGN_KEY /* Disallow the transfer optimization if the destination table contains Index: src/json.c ================================================================== --- src/json.c +++ src/json.c @@ -430,23 +430,17 @@ u32 i; jsonAppendChar(p, '"'); zIn++; N -= 2; while( N>0 ){ - for(i=0; i0 ){ jsonAppendRawNZ(p, zIn, i); zIn += i; N -= i; if( N==0 ) break; } - if( zIn[0]=='"' ){ - jsonAppendRawNZ(p, "\\\"", 2); - zIn++; - N--; - continue; - } assert( zIn[0]=='\\' ); switch( (u8)zIn[1] ){ case '\'': jsonAppendChar(p, '\''); break; @@ -837,12 +831,11 @@ */ static void jsonReturnJson( JsonParse *pParse, /* The complete JSON */ JsonNode *pNode, /* Node to return */ sqlite3_context *pCtx, /* Return value for this function */ - int bGenerateAlt, /* Also store the rendered text in zAlt */ - int omitSubtype /* Do not call sqlite3_result_subtype() */ + int bGenerateAlt /* Also store the rendered text in zAlt */ ){ JsonString s; if( pParse->oom ){ sqlite3_result_error_nomem(pCtx); return; @@ -853,11 +846,11 @@ if( bGenerateAlt && pParse->zAlt==0 && jsonForceRCStr(&s) ){ pParse->zAlt = sqlite3RCStrRef(s.zBuf); pParse->nAlt = s.nUsed; } jsonResult(&s); - if( !omitSubtype ) sqlite3_result_subtype(pCtx, JSON_SUBTYPE); + sqlite3_result_subtype(pCtx, JSON_SUBTYPE); } } /* ** Translate a single byte of Hex into an integer. @@ -894,12 +887,11 @@ ** Make the JsonNode the return value of the function. */ static void jsonReturn( JsonParse *pParse, /* Complete JSON parse tree */ JsonNode *pNode, /* Node to return */ - sqlite3_context *pCtx, /* Return value for this function */ - int omitSubtype /* Do not call sqlite3_result_subtype() */ + sqlite3_context *pCtx /* Return value for this function */ ){ switch( pNode->eType ){ default: { assert( pNode->eType==JSON_NULL ); sqlite3_result_null(pCtx); @@ -1041,11 +1033,11 @@ } break; } case JSON_ARRAY: case JSON_OBJECT: { - jsonReturnJson(pParse, pNode, pCtx, 0, omitSubtype); + jsonReturnJson(pParse, pNode, pCtx, 0); break; } } } @@ -2393,11 +2385,11 @@ printf("hasMod = %u\n", p->hasMod); printf("nJPRef = %u\n", p->nJPRef); printf("iSubst = %u\n", p->iSubst); printf("iHold = %u\n", p->iHold); jsonDebugPrintNodeEntries(p->aNode, p->nNode); - jsonReturnJson(p, p->aNode, ctx, 1, 0); + jsonReturnJson(p, p->aNode, ctx, 1); } /* ** The json_test1(JSON) function return true (1) if the input is JSON ** text generated by another json function. It returns (0) if the input @@ -2579,18 +2571,19 @@ }else{ pNode = jsonLookup(p, zPath, 0, ctx); } if( pNode ){ if( flags & JSON_JSON ){ - jsonReturnJson(p, pNode, ctx, 0, 0); + jsonReturnJson(p, pNode, ctx, 0); }else{ - jsonReturn(p, pNode, ctx, 1); + jsonReturn(p, pNode, ctx); + sqlite3_result_subtype(ctx, 0); } } }else{ pNode = jsonLookup(p, zPath, 0, ctx); - if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx, 0); + if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx); } }else{ /* Two or more PATH arguments results in a JSON array with each ** element of the array being the value selected by one of the PATHs */ int i; @@ -2712,11 +2705,11 @@ pResult = jsonMergePatch(pX, 0, pY->aNode); assert( pResult!=0 || pX->oom ); if( pResult && pX->oom==0 ){ jsonDebugPrintParse(pX); jsonDebugPrintNode(pResult); - jsonReturnJson(pX, pResult, ctx, 0, 0); + jsonReturnJson(pX, pResult, ctx, 0); }else{ sqlite3_result_error_nomem(ctx); } } @@ -2791,11 +2784,11 @@ pParse->hasMod = 1; pParse->useMod = 1; } } if( (pParse->aNode[0].jnFlags & JNODE_REMOVE)==0 ){ - jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0); + jsonReturnJson(pParse, pParse->aNode, ctx, 1); } remove_done: jsonDebugPrintParse(p); } @@ -2920,11 +2913,11 @@ if( pParse->nErr ) goto replace_err; if( pNode ){ jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); } } - jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0); + jsonReturnJson(pParse, pParse->aNode, ctx, 1); replace_err: jsonDebugPrintParse(pParse); jsonParseFree(pParse); } @@ -2974,11 +2967,11 @@ }else if( pNode && (bApnd || bIsSet) ){ jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); } } jsonDebugPrintParse(pParse); - jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0); + jsonReturnJson(pParse, pParse->aNode, ctx, 1); jsonSetDone: jsonParseFree(pParse); } /* @@ -3489,11 +3482,11 @@ JsonNode *pThis = &p->sParse.aNode[p->i]; switch( i ){ case JEACH_KEY: { if( p->i==0 ) break; if( p->eType==JSON_OBJECT ){ - jsonReturn(&p->sParse, pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); }else if( p->eType==JSON_ARRAY ){ u32 iKey; if( p->bRecursive ){ if( p->iRowid==0 ) break; assert( p->sParse.aNode[p->sParse.aUp[p->i]].eU==3 ); @@ -3505,11 +3498,11 @@ } break; } case JEACH_VALUE: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; - jsonReturn(&p->sParse, pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); break; } case JEACH_TYPE: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC); @@ -3516,11 +3509,11 @@ break; } case JEACH_ATOM: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; if( pThis->eType>=JSON_ARRAY ) break; - jsonReturn(&p->sParse, pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); break; } case JEACH_ID: { sqlite3_result_int64(ctx, (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0)); @@ -3809,47 +3802,38 @@ ** Register JSON functions. */ void sqlite3RegisterJsonFunctions(void){ #ifndef SQLITE_OMIT_JSON static FuncDef aJsonFunc[] = { - /* calls sqlite3_result_subtype() */ - /* | */ - /* Uses cache ______ | __ calls sqlite3_value_subtype() */ - /* | | | */ - /* Num args _________ | | | ___ Flags */ - /* | | | | | */ - /* | | | | | */ - JFUNCTION(json, 1, 1, 1, 0, 0, jsonRemoveFunc), - JFUNCTION(json_array, -1, 0, 1, 1, 0, jsonArrayFunc), - JFUNCTION(json_array_length, 1, 1, 0, 0, 0, jsonArrayLengthFunc), - JFUNCTION(json_array_length, 2, 1, 0, 0, 0, jsonArrayLengthFunc), - JFUNCTION(json_error_position,1, 1, 0, 0, 0, jsonErrorFunc), - JFUNCTION(json_extract, -1, 1, 1, 0, 0, jsonExtractFunc), - JFUNCTION(->, 2, 1, 1, 0, JSON_JSON, jsonExtractFunc), - JFUNCTION(->>, 2, 1, 0, 0, JSON_SQL, jsonExtractFunc), - JFUNCTION(json_insert, -1, 1, 1, 1, 0, jsonSetFunc), - JFUNCTION(json_object, -1, 0, 1, 1, 0, jsonObjectFunc), - JFUNCTION(json_patch, 2, 1, 1, 0, 0, jsonPatchFunc), - JFUNCTION(json_quote, 1, 0, 1, 1, 0, jsonQuoteFunc), - JFUNCTION(json_remove, -1, 1, 1, 0, 0, jsonRemoveFunc), - JFUNCTION(json_replace, -1, 1, 1, 1, 0, jsonReplaceFunc), - JFUNCTION(json_set, -1, 1, 1, 1, JSON_ISSET, jsonSetFunc), - JFUNCTION(json_type, 1, 1, 0, 0, 0, jsonTypeFunc), - JFUNCTION(json_type, 2, 1, 0, 0, 0, jsonTypeFunc), - JFUNCTION(json_valid, 1, 1, 0, 0, 0, jsonValidFunc), -#ifdef SQLITE_DEBUG - JFUNCTION(json_parse, 1, 1, 1, 0, 0, jsonParseFunc), - JFUNCTION(json_test1, 1, 1, 0, 1, 0, jsonTest1Func), + JFUNCTION(json, 1, 0, jsonRemoveFunc), + JFUNCTION(json_array, -1, 0, jsonArrayFunc), + JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), + JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), + JFUNCTION(json_error_position,1, 0, jsonErrorFunc), + JFUNCTION(json_extract, -1, 0, jsonExtractFunc), + JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc), + JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc), + JFUNCTION(json_insert, -1, 0, jsonSetFunc), + JFUNCTION(json_object, -1, 0, jsonObjectFunc), + JFUNCTION(json_patch, 2, 0, jsonPatchFunc), + JFUNCTION(json_quote, 1, 0, jsonQuoteFunc), + JFUNCTION(json_remove, -1, 0, jsonRemoveFunc), + JFUNCTION(json_replace, -1, 0, jsonReplaceFunc), + JFUNCTION(json_set, -1, JSON_ISSET, jsonSetFunc), + JFUNCTION(json_type, 1, 0, jsonTypeFunc), + JFUNCTION(json_type, 2, 0, jsonTypeFunc), + JFUNCTION(json_valid, 1, 0, jsonValidFunc), +#if SQLITE_DEBUG + JFUNCTION(json_parse, 1, 0, jsonParseFunc), + JFUNCTION(json_test1, 1, 0, jsonTest1Func), #endif WAGGREGATE(json_group_array, 1, 0, 0, jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| - SQLITE_DETERMINISTIC), + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), WAGGREGATE(json_group_object, 2, 0, 0, jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| - SQLITE_DETERMINISTIC) + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC) }; sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); #endif } Index: src/loadext.c ================================================================== --- src/loadext.c +++ src/loadext.c @@ -512,14 +512,11 @@ /* Version 3.40.0 and later */ sqlite3_value_encoding, /* Version 3.41.0 and later */ sqlite3_is_interrupted, /* Version 3.43.0 and later */ - sqlite3_stmt_explain, - /* Version 3.44.0 and later */ - sqlite3_get_clientdata, - sqlite3_set_clientdata + sqlite3_stmt_explain }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -380,13 +380,11 @@ } #endif /* Experimentally determine if high-precision floating point is ** available. */ -#ifndef SQLITE_OMIT_WSD sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc); -#endif return rc; } /* @@ -763,22 +761,10 @@ sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64); break; } #endif /* SQLITE_OMIT_DESERIALIZE */ - case SQLITE_CONFIG_ROWID_IN_VIEW: { - int *pVal = va_arg(ap,int*); -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( 0==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = TF_NoVisibleRowid; - if( 1==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = 0; - *pVal = (sqlite3GlobalConfig.mNoVisibleRowid==0); -#else - *pVal = 0; -#endif - break; - } - default: { rc = SQLITE_ERROR; break; } } @@ -1924,11 +1910,11 @@ } assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY ); extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY| - SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE); + SQLITE_SUBTYPE|SQLITE_INNOCUOUS); enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But ** the meaning is inverted. So flip the bit. */ assert( SQLITE_FUNC_UNSAFE==SQLITE_INNOCUOUS ); Index: src/mutex_w32.c ================================================================== --- src/mutex_w32.c +++ src/mutex_w32.c @@ -85,11 +85,11 @@ void sqlite3MemoryBarrier(void){ #if defined(SQLITE_MEMORY_BARRIER) SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) __sync_synchronize(); -#elif MSVC_VERSION>=1400 +#elif MSVC_VERSION>=1300 _ReadWriteBarrier(); #elif defined(MemoryBarrier) MemoryBarrier(); #endif } Index: src/os_unix.c ================================================================== --- src/os_unix.c +++ src/os_unix.c @@ -3148,10 +3148,13 @@ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; unixInodeInfo *pInode; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; int skipShared = 0; +#ifdef SQLITE_TEST + int h = pFile->h; +#endif assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, osGetpid(0))); @@ -3163,10 +3166,13 @@ pInode = pFile->pInode; sqlite3_mutex_enter(pInode->pLockMutex); assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); + SimulateIOErrorBenign(1); + SimulateIOError( h=(-1) ) + SimulateIOErrorBenign(0); #ifdef SQLITE_DEBUG /* When reducing a lock such that other processes can start ** reading the database file again, make sure that the ** transaction counter was updated if any part of the database @@ -3211,10 +3217,13 @@ ** the lock. */ unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte; pInode->nShared--; if( pInode->nShared==0 ){ + SimulateIOErrorBenign(1); + SimulateIOError( h=(-1) ) + SimulateIOErrorBenign(0); if( !skipShared ){ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); } if( !rc ){ pInode->eFileLock = NO_LOCK; @@ -5309,20 +5318,15 @@ #endif *pp = 0; #if SQLITE_MAX_MMAP_SIZE>0 if( pFd->mmapSizeMax>0 ){ - /* Ensure that there is always at least a 256 byte buffer of addressable - ** memory following the returned page. If the database is corrupt, - ** SQLite may overread the page slightly (in practice only a few bytes, - ** but 256 is safe, round, number). */ - const int nEofBuffer = 256; if( pFd->pMapRegion==0 ){ int rc = unixMapfile(pFd, -1); if( rc!=SQLITE_OK ) return rc; } - if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ + if( pFd->mmapSize >= iOff+nAmt ){ *pp = &((u8 *)pFd->pMapRegion)[iOff]; pFd->nFetchOut++; } } #endif Index: src/os_win.c ================================================================== --- src/os_win.c +++ src/os_win.c @@ -4519,24 +4519,19 @@ OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n", osGetCurrentProcessId(), fd, iOff, nAmt, pp)); #if SQLITE_MAX_MMAP_SIZE>0 if( pFd->mmapSizeMax>0 ){ - /* Ensure that there is always at least a 256 byte buffer of addressable - ** memory following the returned page. If the database is corrupt, - ** SQLite may overread the page slightly (in practice only a few bytes, - ** but 256 is safe, round, number). */ - const int nEofBuffer = 256; if( pFd->pMapRegion==0 ){ int rc = winMapfile(pFd, -1); if( rc!=SQLITE_OK ){ OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n", osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); return rc; } } - if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ + if( pFd->mmapSize >= iOff+nAmt ){ assert( pFd->pMapRegion!=0 ); *pp = &((u8 *)pFd->pMapRegion)[iOff]; pFd->nFetchOut++; } } Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -5060,17 +5060,14 @@ ** of the corresponding WAL or Journal name as passed into ** xOpen. */ sqlite3_file *sqlite3_database_file_object(const char *zName){ Pager *pPager; - const char *p; while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){ zName--; } - p = zName - 4 - sizeof(Pager*); - assert( EIGHT_BYTE_ALIGNMENT(p) ); - pPager = *(Pager**)p; + pPager = *(Pager**)(zName - 4 - sizeof(Pager*)); return pPager->fd; } /* @@ -6589,17 +6586,10 @@ #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE if( bBatch ){ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); if( rc==SQLITE_OK ){ rc = pager_write_pagelist(pPager, pList); - if( rc==SQLITE_OK && pPager->dbSize>pPager->dbFileSize ){ - char *pTmp = pPager->pTmpSpace; - int szPage = (int)pPager->pageSize; - memset(pTmp, 0, szPage); - rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, - ((i64)pPager->dbSize*pPager->pageSize)-szPage); - } if( rc==SQLITE_OK ){ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); } if( rc!=SQLITE_OK ){ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); @@ -7790,12 +7780,12 @@ assert( pPager->eState>=PAGER_READER ); return sqlite3WalFramesize(pPager->pWal); } #endif -#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) +#ifdef SQLITE_USE_SEH int sqlite3PagerWalSystemErrno(Pager *pPager){ return sqlite3WalSystemErrno(pPager->pWal); } #endif #endif /* SQLITE_OMIT_DISKIO */ Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -1760,11 +1760,34 @@ int bStrict; /* True for a STRICT table */ int r2; /* Previous key for WITHOUT ROWID tables */ int mxCol; /* Maximum non-virtual column number */ if( pObjTab && pObjTab!=pTab ) continue; - if( !IsOrdinaryTable(pTab) ) continue; + if( !IsOrdinaryTable(pTab) ){ +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_vtab *pVTab; + int a1; + if( !IsVirtual(pTab) ) continue; + if( pTab->nCol<=0 ){ + const char *zMod = pTab->u.vtab.azArg[0]; + if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue; + } + sqlite3ViewGetColumnNames(pParse, pTab); + if( pTab->u.vtab.p==0 ) continue; + pVTab = pTab->u.vtab.p->pVtab; + if( NEVER(pVTab==0) ) continue; + if( NEVER(pVTab->pModule==0) ) continue; + if( pVTab->pModule->iVersion<4 ) continue; + if( pVTab->pModule->xIntegrity==0 ) continue; + sqlite3VdbeAddOp2(v, OP_VCheck, 0, 3); + sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v); + integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, a1); +#endif + continue; + } if( isQuick || HasRowid(pTab) ){ pPk = 0; r2 = 0; }else{ pPk = sqlite3PrimaryKeyIndex(pTab); @@ -2085,43 +2108,10 @@ if( pPk ){ sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol); } } } - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Second pass to invoke the xIntegrity method on all virtual - ** tables. - */ - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - sqlite3_vtab *pVTab; - int a1; - if( pObjTab && pObjTab!=pTab ) continue; - if( IsOrdinaryTable(pTab) ) continue; - if( !IsVirtual(pTab) ) continue; - if( pTab->nCol<=0 ){ - const char *zMod = pTab->u.vtab.azArg[0]; - if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue; - } - sqlite3ViewGetColumnNames(pParse, pTab); - if( pTab->u.vtab.p==0 ) continue; - pVTab = pTab->u.vtab.p->pVtab; - if( NEVER(pVTab==0) ) continue; - if( NEVER(pVTab->pModule==0) ) continue; - if( pVTab->pModule->iVersion<4 ) continue; - if( pVTab->pModule->xIntegrity==0 ) continue; - sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick); - pTab->nTabRef++; - sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF); - a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, a1); -#endif - continue; - } - } { static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList endCode[] = { { OP_AddImm, 1, 0, 0}, /* 0 */ @@ -2754,15 +2744,11 @@ return SQLITE_OK; } j = seen[0]-1; pIdxInfo->aConstraintUsage[j].argvIndex = 1; pIdxInfo->aConstraintUsage[j].omit = 1; - if( seen[1]==0 ){ - pIdxInfo->estimatedCost = (double)1000; - pIdxInfo->estimatedRows = 1000; - return SQLITE_OK; - } + if( seen[1]==0 ) return SQLITE_OK; pIdxInfo->estimatedCost = (double)20; pIdxInfo->estimatedRows = 20; j = seen[1]-1; pIdxInfo->aConstraintUsage[j].argvIndex = 2; pIdxInfo->aConstraintUsage[j].omit = 1; Index: src/resolve.c ================================================================== --- src/resolve.c +++ src/resolve.c @@ -77,12 +77,10 @@ sqlite3 *db; /* The database connection */ assert( iCol>=0 && iColnExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); - assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) ); - if( pExpr->pAggInfo ) return; db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); if( db->mallocFailed ){ sqlite3ExprDelete(db, pDup); pDup = 0; @@ -182,11 +180,10 @@ n = pExpr->iColumn; assert( ExprUseYTab(pExpr) ); pExTab = pExpr->y.pTab; assert( pExTab!=0 ); - assert( n < pExTab->nCol ); if( (pExTab->tabFlags & TF_HasGenerated)!=0 && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0 ){ testcase( pExTab->nCol==BMS-1 ); testcase( pExTab->nCol==BMS ); @@ -466,41 +463,12 @@ } break; } } if( 0==cnt && VisibleRowid(pTab) ){ - /* pTab is a potential ROWID match. Keep track of it and match - ** the ROWID later if that seems appropriate. (Search for "cntTab" - ** to find related code.) Only allow a ROWID match if there is - ** a single ROWID match candidate. - */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - /* In SQLITE_ALLOW_ROWID_IN_VIEW mode, allow a ROWID match - ** if there is a single VIEW candidate or if there is a single - ** non-VIEW candidate plus multiple VIEW candidates. In other - ** words non-VIEW candidate terms take precedence over VIEWs. - */ - if( cntTab==0 - || (cntTab==1 - && ALWAYS(pMatch!=0) - && ALWAYS(pMatch->pTab!=0) - && (pMatch->pTab->tabFlags & TF_Ephemeral)!=0 - && (pTab->tabFlags & TF_Ephemeral)==0) - ){ - cntTab = 1; - pMatch = pItem; - }else{ - cntTab++; - } -#else - /* The (much more common) non-SQLITE_ALLOW_ROWID_IN_VIEW case is - ** simpler since we require exactly one candidate, which will - ** always be a non-VIEW - */ - cntTab++; - pMatch = pItem; -#endif + cntTab++; + pMatch = pItem; } } if( pMatch ){ pExpr->iTable = pMatch->iCursor; assert( ExprUseYTab(pExpr) ); @@ -622,17 +590,17 @@ /* ** Perhaps the name is a reference to the ROWID */ if( cnt==0 - && cntTab>=1 + && cntTab==1 && pMatch && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 && sqlite3IsRowid(zCol) && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom) ){ - cnt = cntTab; + cnt = 1; if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1; pExpr->affExpr = SQLITE_AFF_INTEGER; } /* @@ -788,11 +756,10 @@ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); } sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); pParse->checkSchema = 1; pTopNC->nNcErr++; - eNewExprOp = TK_NULL; } assert( pFJMatch==0 ); /* Remove all substructure from pExpr */ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ @@ -815,11 +782,11 @@ ** (See ticket [b92e5e8ec2cdbaa1]). ** ** If a generated column is referenced, set bits for every column ** of the table. */ - if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){ + if( pExpr->iColumn>=0 && pMatch!=0 ){ pMatch->colUsed |= sqlite3ExprColUsed(pExpr); } pExpr->op = eNewExprOp; lookupname_end: Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -1948,11 +1948,15 @@ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ if( iColpEList->nExpr - && (!ViewCanHaveRowid || iCol>=0) +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + && iCol>=0 +#else + && ALWAYS(iCol>=0) +#endif ){ /* If iCol is less than zero, then the expression requests the ** rowid of the sub-select or view. This expression is legal (see ** test case misc2.2.2) - it always evaluates to NULL. */ @@ -2313,12 +2317,11 @@ Expr *p; struct ExprList_item *a; NameContext sNC; assert( pSelect!=0 ); - testcase( (pSelect->selFlags & SF_Resolved)==0 ); - assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT ); + assert( (pSelect->selFlags & SF_Resolved)!=0 ); assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 ); assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB ); if( db->mallocFailed || IN_RENAME_OBJECT ) return; while( pSelect->pPrior ) pSelect = pSelect->pPrior; a = pSelect->pEList->a; @@ -5128,14 +5131,10 @@ ** ** (10) The inner query is not the right-hand table of a RIGHT JOIN. ** ** (11) The subquery is not a VALUES clause ** -** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This -** case only comes up if SQLite is compiled using -** SQLITE_ALLOW_ROWID_IN_VIEW. -** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ @@ -5240,22 +5239,10 @@ if( ExprHasProperty(pWhere,EP_OuterON) && pWhere->w.iJoin!=iCursor ){ return 0; /* restriction (5) */ } -#endif - -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){ - Expr *pLeft = pWhere->pLeft; - if( ALWAYS(pLeft) - && pLeft->op==TK_COLUMN - && pLeft->iColumn < 0 - ){ - return 0; /* Restriction (12) */ - } - } #endif if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){ nChng++; pSubq->selFlags |= SF_PushDown; @@ -5882,18 +5869,16 @@ pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom); } while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); pTab->iPKey = -1; - pTab->eTabType = TABTYP_VIEW; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); #ifndef SQLITE_ALLOW_ROWID_IN_VIEW /* The usual case - do not allow ROWID on a subquery */ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; #else - /* Legacy compatibility mode */ - pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid; + pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */ #endif return pParse->nErr ? SQLITE_ERROR : SQLITE_OK; } @@ -6157,11 +6142,11 @@ if( pFrom->fg.isNestedFrom ){ assert( pFrom->pSelect!=0 ); pNestedFrom = pFrom->pSelect->pEList; assert( pNestedFrom!=0 ); assert( pNestedFrom->nExpr==pTab->nCol ); - assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid ); + assert( VisibleRowid(pTab)==0 ); }else{ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } pNestedFrom = 0; @@ -6189,12 +6174,11 @@ } }else{ pUsing = 0; } - nAdd = pTab->nCol; - if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++; + nAdd = pTab->nCol + (VisibleRowid(pTab) && (selFlags&SF_NestedFrom)); for(j=0; jnCol ){ @@ -6272,12 +6256,11 @@ break; /* OOM */ } pX = &pNew->a[pNew->nExpr-1]; assert( pX->zEName==0 ); if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){ - if( pNestedFrom && (!ViewCanHaveRowid || jnExpr) ){ - assert( jnExpr ); + if( pNestedFrom ){ pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName); testcase( pX->zEName==0 ); }else{ pX->zEName = sqlite3MPrintf(db, "%s.%s.%s", zSchemaName, zTabName, zName); @@ -6387,15 +6370,14 @@ Parse *pParse; int i; SrcList *pTabList; SrcItem *pFrom; + assert( p->selFlags & SF_Resolved ); if( p->selFlags & SF_HasTypeInfo ) return; p->selFlags |= SF_HasTypeInfo; pParse = pWalker->pParse; - testcase( (p->selFlags & SF_Resolved)==0 ); - assert( (p->selFlags & SF_Resolved) || IN_RENAME_OBJECT ); pTabList = p->pSrc; for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; assert( pTab!=0 ); if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ @@ -6731,11 +6713,11 @@ }else{ assert( pF->pFExpr->pLeft!=0 ); assert( ExprUseXList(pF->pFExpr->pLeft) ); assert( pF->pFExpr->pLeft->x.pList!=0 ); nKey = pF->pFExpr->pLeft->x.pList->nExpr; - if( ALWAYS(!pF->bOBUnique) ) nKey++; + if( !pF->bOBUnique ) nKey++; } iTop = sqlite3VdbeAddOp1(v, OP_Rewind, pF->iOBTab); VdbeCoverage(v); for(j=nArg-1; j>=0; j--){ sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, nKey+j, regAgg+j); } @@ -6759,14 +6741,14 @@ ** If regAcc is non-zero and there are no min() or max() aggregates ** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator ** registers if register regAcc contains 0. The caller will take care ** of setting and clearing regAcc. ** -** For an ORDER BY aggregate, the actual accumulator memory cell update +** For an ORDER BY aggregate, the actually accumulator memory cell update ** is deferred until after all input rows have been received, so that they ** can be run in the requested order. In that case, instead of invoking -** OP_AggStep to update the accumulator, just add the arguments that would +** OP_AggStep to update accumulator, just add the arguments that would ** have been passed into OP_AggStep into the sorting ephemeral table ** (along with the appropriate sort key). */ static void updateAccumulator( Parse *pParse, @@ -6787,11 +6769,10 @@ for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ int nArg; int addrNext = 0; int regAgg; int regAggSz = 0; - int regDistinct = 0; ExprList *pList; assert( ExprUseXList(pF->pFExpr) ); assert( !IsWindowFunc(pF->pFExpr) ); pList = pF->pFExpr->x.pList; if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){ @@ -6837,25 +6818,22 @@ if( pF->bOBPayload ){ regAggSz += nArg; } regAggSz++; /* One extra register to hold result of MakeRecord */ regAgg = sqlite3GetTempRange(pParse, regAggSz); - regDistinct = regAgg; sqlite3ExprCodeExprList(pParse, pOBList, regAgg, 0, SQLITE_ECEL_DUP); jj = pOBList->nExpr; if( !pF->bOBUnique ){ sqlite3VdbeAddOp2(v, OP_Sequence, pF->iOBTab, regAgg+jj); jj++; } if( pF->bOBPayload ){ - regDistinct = regAgg+jj; - sqlite3ExprCodeExprList(pParse, pList, regDistinct, 0, SQLITE_ECEL_DUP); + sqlite3ExprCodeExprList(pParse, pList, regAgg+jj, 0, SQLITE_ECEL_DUP); } }else if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); - regDistinct = regAgg; sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); }else{ nArg = 0; regAgg = 0; } @@ -6862,11 +6840,11 @@ if( pF->iDistinct>=0 && pList ){ if( addrNext==0 ){ addrNext = sqlite3VdbeMakeLabel(pParse); } pF->iDistinct = codeDistinct(pParse, eDistinctType, - pF->iDistinct, addrNext, pList, regDistinct); + pF->iDistinct, addrNext, pList, regAgg); } if( pF->iOBTab>=0 ){ /* Insert a new record into the ORDER BY table */ sqlite3VdbeAddOp3(v, OP_MakeRecord, regAgg, regAggSz-1, regAgg+regAggSz-1); @@ -7413,11 +7391,10 @@ pItem->fg.jointype &= ~JT_LEFT; }else{ TREETRACE(0x1000,pParse,p, ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); - unsetJoinExpr(p->pWhere, pItem->iCursor, 0); } } if( pItem->fg.jointype & JT_LTORJ ){ for(j=i+1; jnSrc; j++){ SrcItem *pI2 = &pTabList->a[j]; @@ -7428,19 +7405,21 @@ pI2->fg.jointype &= ~JT_RIGHT; }else{ TREETRACE(0x1000,pParse,p, ("RIGHT-JOIN simplifies to JOIN on term %d\n",j)); pI2->fg.jointype &= ~(JT_RIGHT|JT_OUTER); - unsetJoinExpr(p->pWhere, pI2->iCursor, 1); } } } - for(j=pTabList->nSrc-1; j>=0; j--){ + for(j=pTabList->nSrc-1; j>=i; j--){ pTabList->a[j].fg.jointype &= ~JT_LTORJ; if( pTabList->a[j].fg.jointype & JT_RIGHT ) break; } } + assert( pItem->iCursor>=0 ); + unsetJoinExpr(p->pWhere, pItem->iCursor, + pTabList->a[0].fg.jointype & JT_LTORJ); } /* No further action if this term of the FROM clause is not a subquery */ if( pSub==0 ) continue; Index: src/shell.c.in ================================================================== --- src/shell.c.in +++ src/shell.c.in @@ -232,60 +232,33 @@ #define WIN32_LEAN_AND_MEAN #include /* string conversion routines only needed on Win32 */ extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); +extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int); +extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int); extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); #endif -/* Use console I/O package as a direct INCLUDE. */ -#define SQLITE_INTERNAL_LINKAGE static - -#ifdef SQLITE_SHELL_FIDDLE -/* Deselect most features from the console I/O package for Fiddle. */ -# define SQLITE_CIO_NO_REDIRECT -# define SQLITE_CIO_NO_CLASSIFY -# define SQLITE_CIO_NO_TRANSLATE -# define SQLITE_CIO_NO_SETMODE -#endif -INCLUDE ../ext/consio/console_io.h -INCLUDE ../ext/consio/console_io.c - -#ifndef SQLITE_SHELL_FIDDLE -/* From here onward, fgets() is redirected to the console_io library. */ -# define fgets(b,n,f) fGetsUtf8(b,n,f) -/* - * Define macros for emitting output text in various ways: - * sputz(s, z) => emit 0-terminated string z to given stream s - * sputf(s, f, ...) => emit varargs per format f to given stream s - * oputz(z) => emit 0-terminated string z to default stream - * oputf(f, ...) => emit varargs per format f to default stream - * eputz(z) => emit 0-terminated string z to error stream - * eputf(f, ...) => emit varargs per format f to error stream - * oputb(b, n) => emit char buffer b[0..n-1] to default stream - * - * Note that the default stream is whatever has been last set via: - * setOutputStream(FILE *pf) - * This is normally the stream that CLI normal output goes to. - * For the stand-alone CLI, it is stdout with no .output redirect. - */ -# define sputz(s,z) fPutsUtf8(z,s) -# define sputf fPrintfUtf8 -# define oputz(z) oPutsUtf8(z) -# define oputf oPrintfUtf8 -# define eputz(z) ePutsUtf8(z) -# define eputf ePrintfUtf8 -# define oputb(buf,na) oPutbUtf8(buf,na) +/* On Windows, we normally run with output mode of TEXT so that \n characters +** are automatically translated into \r\n. However, this behavior needs +** to be disabled in some cases (ex: when generating CSV output and when +** rendering quoted strings that contain \n characters). The following +** routines take care of that. +*/ +#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT +static void setBinaryMode(FILE *file, int isOutput){ + if( isOutput ) fflush(file); + _setmode(_fileno(file), _O_BINARY); +} +static void setTextMode(FILE *file, int isOutput){ + if( isOutput ) fflush(file); + _setmode(_fileno(file), _O_TEXT); +} #else -/* For Fiddle, all console handling and emit redirection is omitted. */ -# define sputz(fp,z) fputs(z,fp) -# define sputf(fp,fmt, ...) fprintf(fp,fmt,__VA_ARGS__) -# define oputz(z) fputs(z,stdout) -# define oputf(fmt, ...) printf(fmt,__VA_ARGS__) -# define eputz(z) fputs(z,stderr) -# define eputf(fmt, ...) fprintf(stderr,fmt,__VA_ARGS__) -# define oputb(buf,na) fwrite(buf,1,na,stdout) +# define setBinaryMode(X,Y) +# define setTextMode(X,Y) #endif /* True if the timer is enabled */ static int enableTimer = 0; @@ -356,14 +329,14 @@ static void endTimer(void){ if( enableTimer ){ sqlite3_int64 iEnd = timeOfDay(); struct rusage sEnd; getrusage(RUSAGE_SELF, &sEnd); - oputf("Run Time: real %.3f user %f sys %f\n", - (iEnd - iBegin)*0.001, - timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), - timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); + printf("Run Time: real %.3f user %f sys %f\n", + (iEnd - iBegin)*0.001, + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); } } #define BEGIN_TIMER beginTimer() #define END_TIMER endTimer() @@ -435,14 +408,14 @@ static void endTimer(void){ if( enableTimer && getProcessTimesAddr){ FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; sqlite3_int64 ftWallEnd = timeOfDay(); getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); - oputf("Run Time: real %.3f user %f sys %f\n", - (ftWallEnd - ftWallBegin)*0.001, - timeDiff(&ftUserBegin, &ftUserEnd), - timeDiff(&ftKernelBegin, &ftKernelEnd)); + printf("Run Time: real %.3f user %f sys %f\n", + (ftWallEnd - ftWallBegin)*0.001, + timeDiff(&ftUserBegin, &ftUserEnd), + timeDiff(&ftKernelBegin, &ftKernelEnd)); } } #define BEGIN_TIMER beginTimer() #define END_TIMER endTimer() @@ -474,14 +447,22 @@ ** Treat stdin as an interactive input if the following variable ** is true. Otherwise, assume stdin is connected to a file or pipe. */ static int stdin_is_interactive = 1; +#if (defined(_WIN32) || defined(WIN32)) && SHELL_USE_LOCAL_GETLINE \ + && !defined(SHELL_OMIT_WIN_UTF8) +# define SHELL_WIN_UTF8_OPT 1 + static int console_utf8 = sizeof(char*)/4 - 1; +#else +# define SHELL_WIN_UTF8_OPT 0 +#endif + /* -** On Windows systems we need to know if standard output is a console -** in order to show that UTF-16 translation is done in the sign-on -** banner. The following variable is true if it is the console. +** On Windows systems we have to know if standard output is a console +** in order to translate UTF-8 into MBCS. The following variable is +** true if translation is required. */ static int stdout_is_console = 1; /* ** The following is the open SQLite database. We make a pointer @@ -599,21 +580,182 @@ shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4); }else{ shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4); dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel); } - shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, - PROMPT_LEN_MAX-4); + shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4); } } return dynPrompt.dynamicPrompt; } #endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */ + +#if SHELL_WIN_UTF8_OPT +/* Following struct is used for -utf8 operation. */ +static struct ConsoleState { + int stdinEof; /* EOF has been seen on console input */ + int infsMode; /* Input file stream mode upon shell start */ + UINT inCodePage; /* Input code page upon shell start */ + UINT outCodePage; /* Output code page upon shell start */ + HANDLE hConsoleIn; /* Console input handle */ + DWORD consoleMode; /* Console mode upon shell start */ +} conState = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 }; + +#ifndef _O_U16TEXT /* For build environments lacking this constant: */ +# define _O_U16TEXT 0x20000 +#endif + +/* +** Prepare console, (if known to be a WIN32 console), for UTF-8 +** input (from either typing or suitable paste operations) and for +** UTF-8 rendering. This may "fail" with a message to stderr, where +** the preparation is not done and common "code page" issues occur. +*/ +static void console_prepare(void){ + HANDLE hCI = GetStdHandle(STD_INPUT_HANDLE); + DWORD consoleMode = 0; + if( isatty(0) && GetFileType(hCI)==FILE_TYPE_CHAR + && GetConsoleMode( hCI, &consoleMode) ){ + if( !IsValidCodePage(CP_UTF8) ){ + fprintf(stderr, "Cannot use UTF-8 code page.\n"); + console_utf8 = 0; + return; + } + conState.hConsoleIn = hCI; + conState.consoleMode = consoleMode; + conState.inCodePage = GetConsoleCP(); + conState.outCodePage = GetConsoleOutputCP(); + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + consoleMode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; + SetConsoleMode(conState.hConsoleIn, consoleMode); + conState.infsMode = _setmode(_fileno(stdin), _O_U16TEXT); + console_utf8 = 1; + }else{ + console_utf8 = 0; + } +} + +/* +** Undo the effects of console_prepare(), if any. +*/ +static void SQLITE_CDECL console_restore(void){ + if( console_utf8 && conState.inCodePage!=0 + && conState.hConsoleIn!=INVALID_HANDLE_VALUE ){ + _setmode(_fileno(stdin), conState.infsMode); + SetConsoleCP(conState.inCodePage); + SetConsoleOutputCP(conState.outCodePage); + SetConsoleMode(conState.hConsoleIn, conState.consoleMode); + /* Avoid multiple calls. */ + conState.hConsoleIn = INVALID_HANDLE_VALUE; + conState.consoleMode = 0; + console_utf8 = 0; + } +} + +/* +** Collect input like fgets(...) with special provisions for input +** from the Windows console to get around its strange coding issues. +** Defers to plain fgets() when input is not interactive or when the +** startup option, -utf8, has not been provided or taken effect. +*/ +static char* utf8_fgets(char *buf, int ncmax, FILE *fin){ + if( fin==0 ) fin = stdin; + if( fin==stdin && stdin_is_interactive && console_utf8 ){ +# define SQLITE_IALIM 150 + wchar_t wbuf[SQLITE_IALIM]; + int lend = 0; + int noc = 0; + if( ncmax==0 || conState.stdinEof ) return 0; + buf[0] = 0; + while( noc SQLITE_IALIM*4+1 + noc) + ? SQLITE_IALIM : (ncmax-1 - noc)/4; +# undef SQLITE_IALIM + DWORD nbr = 0; + BOOL bRC = ReadConsoleW(conState.hConsoleIn, wbuf, na, &nbr, 0); + if( !bRC || (noc==0 && nbr==0) ) return 0; + if( nbr > 0 ){ + int nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR, + wbuf,nbr,0,0,0,0); + if( nmb !=0 && noc+nmb <= ncmax ){ + int iseg = noc; + nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR, + wbuf,nbr,buf+noc,nmb,0,0); + noc += nmb; + /* Fixup line-ends as coded by Windows for CR (or "Enter".)*/ + if( noc > 0 ){ + if( buf[noc-1]=='\n' ){ + lend = 1; + if( noc > 1 && buf[noc-2]=='\r' ){ + buf[noc-2] = '\n'; + --noc; + } + } + } + /* Check for ^Z (anywhere in line) too. */ + while( iseg < noc ){ + if( buf[iseg]==0x1a ){ + conState.stdinEof = 1; + noc = iseg; /* Chop ^Z and anything following. */ + break; + } + ++iseg; + } + }else break; /* Drop apparent garbage in. (Could assert.) */ + }else break; + } + /* If got nothing, (after ^Z chop), must be at end-of-file. */ + if( noc == 0 ) return 0; + buf[noc] = 0; + return buf; + }else{ + return fgets(buf, ncmax, fin); + } +} + +# define fgets(b,n,f) utf8_fgets(b,n,f) +#endif /* SHELL_WIN_UTF8_OPT */ + +/* +** Render output like fprintf(). Except, if the output is going to the +** console and if this is running on a Windows machine, and if the -utf8 +** option is unavailable or (available and inactive), translate the +** output from UTF-8 into MBCS for output through 8-bit stdout stream. +** (With -utf8 active, no translation is needed and must not be done.) +*/ +#if defined(_WIN32) || defined(WIN32) +void utf8_printf(FILE *out, const char *zFormat, ...){ + va_list ap; + va_start(ap, zFormat); + if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8 ){ + char *z1 = sqlite3_vmprintf(zFormat, ap); + char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0); + sqlite3_free(z1); + fputs(z2, out); + sqlite3_free(z2); + }else{ + vfprintf(out, zFormat, ap); + } + va_end(ap); +} +#elif !defined(utf8_printf) +# define utf8_printf fprintf +#endif + +/* +** Render output like fprintf(). This should not be used on anything that +** includes string formatting (e.g. "%s"). +*/ +#if !defined(raw_printf) +# define raw_printf fprintf +#endif /* Indicate out-of-memory and exit. */ static void shell_out_of_memory(void){ - eputz("Error: out of memory\n"); + raw_printf(stderr,"Error: out of memory\n"); exit(1); } /* Check a pointer to see if it is NULL. If it is NULL, exit with an ** out-of-memory error. @@ -641,22 +783,22 @@ char *z; if( iotrace==0 ) return; va_start(ap, zFormat); z = sqlite3_vmprintf(zFormat, ap); va_end(ap); - sputf(iotrace, "%s", z); + utf8_printf(iotrace, "%s", z); sqlite3_free(z); } #endif /* -** Output string zUtf to Out stream as w characters. If w is negative, +** Output string zUtf to stream pOut as w characters. If w is negative, ** then right-justify the text. W is the width in UTF-8 characters, not ** in bytes. This is different from the %*.*s specification in printf ** since with %*.*s the width is measured in bytes, not characters. */ -static void utf8_width_print(int w, const char *zUtf){ +static void utf8_width_print(FILE *pOut, int w, const char *zUtf){ int i; int n; int aw = w<0 ? -w : w; if( zUtf==0 ) zUtf = ""; for(i=n=0; zUtf[i]; i++){ @@ -667,15 +809,15 @@ break; } } } if( n>=aw ){ - oputf("%.*s", i, zUtf); + utf8_printf(pOut, "%.*s", i, zUtf); }else if( w<0 ){ - oputf("%*s%s", aw-n, "", zUtf); + utf8_printf(pOut, "%*s%s", aw-n, "", zUtf); }else{ - oputf("%s%*s", zUtf, aw-n, ""); + utf8_printf(pOut, "%s%*s", zUtf, aw-n, ""); } } /* @@ -731,11 +873,11 @@ ** Return open FILE * if zFile exists, can be opened for read ** and is an ordinary file or a character stream source. ** Otherwise return 0. */ static FILE * openChrSource(const char *zFile){ -#if defined(_WIN32) || defined(WIN32) +#ifdef _WIN32 struct _stat x = {0}; # define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0) /* On Windows, open first, then check the stream nature. This order ** is necessary because _stat() and sibs, when checking a named pipe, ** effectively break the pipe as its supplier sees it. */ @@ -794,10 +936,27 @@ if( n>0 && zLine[n-1]=='\r' ) n--; zLine[n] = 0; break; } } +#if defined(_WIN32) || defined(WIN32) + /* For interactive input on Windows systems, without -utf8, + ** translate the multi-byte characterset characters into UTF-8. + ** This is the translation that predates the -utf8 option. */ + if( stdin_is_interactive && in==stdin && !console_utf8 ){ + char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); + if( zTrans ){ + i64 nTrans = strlen(zTrans)+1; + if( nTrans>nLine ){ + zLine = realloc(zLine, nTrans); + shell_check_oom(zLine); + } + memcpy(zLine, zTrans, nTrans); + sqlite3_free(zTrans); + } + } +#endif /* defined(_WIN32) || defined(WIN32) */ return zLine; } /* ** Retrieve a single line of input text. @@ -820,11 +979,11 @@ if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt; #if SHELL_USE_LOCAL_GETLINE - sputz(stdout, zPrompt); + printf("%s", zPrompt); fflush(stdout); do{ zResult = local_getline(zPrior, stdin); zPrior = 0; /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */ @@ -1067,11 +1226,11 @@ double r = sqlite3_value_double(apVal[0]); int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26; char z[400]; if( n<1 ) n = 1; if( n>350 ) n = 350; - sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r); + snprintf(z, sizeof(z)-1, "%#+.*e", n, r); sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); } /* @@ -1481,11 +1640,11 @@ ** A callback for the sqlite3_log() interface. */ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ ShellState *p = (ShellState*)pArg; if( p->pLog==0 ) return; - sputf(p->pLog, "(%d) %s\n", iErrCode, zMsg); + utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg); fflush(p->pLog); } /* ** SQL function: shell_putsnl(X) @@ -1496,13 +1655,13 @@ static void shellPutsFunc( sqlite3_context *pCtx, int nVal, sqlite3_value **apVal ){ - /* Unused: (ShellState*)sqlite3_user_data(pCtx); */ + ShellState *p = (ShellState*)sqlite3_user_data(pCtx); (void)nVal; - oputf("%s\n", sqlite3_value_text(apVal[0])); + utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0])); sqlite3_result_value(pCtx, apVal[0]); } /* ** If in safe mode, print an error message described by the arguments @@ -1517,11 +1676,12 @@ va_list ap; char *zMsg; va_start(ap, zErrMsg); zMsg = sqlite3_vmprintf(zErrMsg, ap); va_end(ap); - eputf("line %d: %s\n", p->lineno, zMsg); + raw_printf(stderr, "line %d: ", p->lineno); + utf8_printf(stderr, "%s\n", zMsg); exit(1); } } /* @@ -1685,11 +1845,11 @@ } /* ** Output the given string as a hex-encoded blob (eg. X'1234' ) */ -static void output_hex_blob(const void *pBlob, int nBlob){ +static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ int i; unsigned char *aBlob = (unsigned char*)pBlob; char *zStr = sqlite3_malloc(nBlob*2 + 1); shell_check_oom(zStr); @@ -1702,11 +1862,11 @@ zStr[i*2] = aHex[ (aBlob[i] >> 4) ]; zStr[i*2+1] = aHex[ (aBlob[i] & 0x0F) ]; } zStr[i*2] = '\0'; - oputf("X'%s'", zStr); + raw_printf(out,"X'%s'", zStr); sqlite3_free(zStr); } /* ** Find a string that is not found anywhere in z[]. Return a pointer @@ -1732,46 +1892,39 @@ /* ** Output the given string as a quoted string using SQL quoting conventions. ** ** See also: output_quoted_escaped_string() */ -static void output_quoted_string(const char *z){ +static void output_quoted_string(FILE *out, const char *z){ int i; char c; -#ifndef SQLITE_SHELL_FIDDLE - FILE *pfO = setOutputStream(invalidFileStream); - setBinaryMode(pfO, 1); -#endif + setBinaryMode(out, 1); if( z==0 ) return; for(i=0; (c = z[i])!=0 && c!='\''; i++){} if( c==0 ){ - oputf("'%s'",z); + utf8_printf(out,"'%s'",z); }else{ - oputz("'"); + raw_printf(out, "'"); while( *z ){ for(i=0; (c = z[i])!=0 && c!='\''; i++){} if( c=='\'' ) i++; if( i ){ - oputf("%.*s", i, z); + utf8_printf(out, "%.*s", i, z); z += i; } if( c=='\'' ){ - oputz("'"); + raw_printf(out, "'"); continue; } if( c==0 ){ break; } z++; } - oputz("'"); + raw_printf(out, "'"); } -#ifndef SQLITE_SHELL_FIDDLE - setTextMode(pfO, 1); -#else - setTextMode(stdout, 1); -#endif + setTextMode(out, 1); } /* ** Output the given string as a quoted string using SQL quoting conventions. ** Additionallly , escape the "\n" and "\r" characters so that they do not @@ -1779,20 +1932,17 @@ ** systems. ** ** This is like output_quoted_string() but with the addition of the \r\n ** escape mechanism. */ -static void output_quoted_escaped_string(const char *z){ +static void output_quoted_escaped_string(FILE *out, const char *z){ int i; char c; -#ifndef SQLITE_SHELL_FIDDLE - FILE *pfO = setOutputStream(invalidFileStream); - setBinaryMode(pfO, 1); -#endif + setBinaryMode(out, 1); for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){} if( c==0 ){ - oputf("'%s'",z); + utf8_printf(out,"'%s'",z); }else{ const char *zNL = 0; const char *zCR = 0; int nNL = 0; int nCR = 0; @@ -1800,167 +1950,121 @@ for(i=0; z[i]; i++){ if( z[i]=='\n' ) nNL++; if( z[i]=='\r' ) nCR++; } if( nNL ){ - oputz("replace("); + raw_printf(out, "replace("); zNL = unused_string(z, "\\n", "\\012", zBuf1); } if( nCR ){ - oputz("replace("); + raw_printf(out, "replace("); zCR = unused_string(z, "\\r", "\\015", zBuf2); } - oputz("'"); + raw_printf(out, "'"); while( *z ){ for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){} if( c=='\'' ) i++; if( i ){ - oputf("%.*s", i, z); + utf8_printf(out, "%.*s", i, z); z += i; } if( c=='\'' ){ - oputz("'"); + raw_printf(out, "'"); continue; } if( c==0 ){ break; } z++; if( c=='\n' ){ - oputz(zNL); + raw_printf(out, "%s", zNL); continue; } - oputz(zCR); + raw_printf(out, "%s", zCR); } - oputz("'"); + raw_printf(out, "'"); if( nCR ){ - oputf(",'%s',char(13))", zCR); + raw_printf(out, ",'%s',char(13))", zCR); } if( nNL ){ - oputf(",'%s',char(10))", zNL); - } - } -#ifndef SQLITE_SHELL_FIDDLE - setTextMode(pfO, 1); -#else - setTextMode(stdout, 1); -#endif -} - -/* -** Find earliest of chars within s specified in zAny. -** With ns == ~0, is like strpbrk(s,zAny) and s must be 0-terminated. -*/ -static const char *anyOfInStr(const char *s, const char *zAny, size_t ns){ - const char *pcFirst = 0; - if( ns == ~(size_t)0 ) ns = strlen(s); - while(*zAny){ - const char *pc = (const char*)memchr(s, *zAny&0xff, ns); - if( pc ){ - pcFirst = pc; - ns = pcFirst - s; - } - ++zAny; - } - return pcFirst; -} + raw_printf(out, ",'%s',char(10))", zNL); + } + } + setTextMode(out, 1); +} + /* ** Output the given string as a quoted according to C or TCL quoting rules. */ -static void output_c_string(const char *z){ - char c; - static const char *zq = "\""; - static long ctrlMask = ~0L; - static const char *zDQBSRO = "\"\\\x7f"; /* double-quote, backslash, rubout */ - char ace[3] = "\\?"; - char cbsSay; - oputz(zq); - while( *z!=0 ){ - const char *pcDQBSRO = anyOfInStr(z, zDQBSRO, ~(size_t)0); - const char *pcPast = zSkipValidUtf8(z, INT_MAX, ctrlMask); - const char *pcEnd = (pcDQBSRO && pcDQBSRO < pcPast)? pcDQBSRO : pcPast; - if( pcEnd > z ) oputb(z, (int)(pcEnd-z)); - if( (c = *pcEnd)==0 ) break; - ++pcEnd; - switch( c ){ - case '\\': case '"': - cbsSay = (char)c; - break; - case '\t': cbsSay = 't'; break; - case '\n': cbsSay = 'n'; break; - case '\r': cbsSay = 'r'; break; - case '\f': cbsSay = 'f'; break; - default: cbsSay = 0; break; - } - if( cbsSay ){ - ace[1] = cbsSay; - oputz(ace); +static void output_c_string(FILE *out, const char *z){ + unsigned int c; + fputc('"', out); + while( (c = *(z++))!=0 ){ + if( c=='\\' ){ + fputc(c, out); + fputc(c, out); + }else if( c=='"' ){ + fputc('\\', out); + fputc('"', out); + }else if( c=='\t' ){ + fputc('\\', out); + fputc('t', out); + }else if( c=='\n' ){ + fputc('\\', out); + fputc('n', out); + }else if( c=='\r' ){ + fputc('\\', out); + fputc('r', out); }else if( !isprint(c&0xff) ){ - oputf("\\%03o", c&0xff); + raw_printf(out, "\\%03o", c&0xff); }else{ - ace[1] = (char)c; - oputz(ace+1); + fputc(c, out); } - z = pcEnd; } - oputz(zq); + fputc('"', out); } /* ** Output the given string as a quoted according to JSON quoting rules. */ -static void output_json_string(const char *z, i64 n){ - char c; - static const char *zq = "\""; - static long ctrlMask = ~0L; - static const char *zDQBS = "\"\\"; - const char *pcLimit; - char ace[3] = "\\?"; - char cbsSay; - +static void output_json_string(FILE *out, const char *z, i64 n){ + unsigned int c; if( z==0 ) z = ""; - pcLimit = z + ((n<0)? strlen(z) : (size_t)n); - oputz(zq); - while( z < pcLimit ){ - const char *pcDQBS = anyOfInStr(z, zDQBS, pcLimit-z); - const char *pcPast = zSkipValidUtf8(z, (int)(pcLimit-z), ctrlMask); - const char *pcEnd = (pcDQBS && pcDQBS < pcPast)? pcDQBS : pcPast; - if( pcEnd > z ){ - oputb(z, (int)(pcEnd-z)); - z = pcEnd; - } - if( z >= pcLimit ) break; + if( n<0 ) n = strlen(z); + fputc('"', out); + while( n-- ){ c = *(z++); - switch( c ){ - case '"': case '\\': - cbsSay = (char)c; - break; - case '\b': cbsSay = 'b'; break; - case '\f': cbsSay = 'f'; break; - case '\n': cbsSay = 'n'; break; - case '\r': cbsSay = 'r'; break; - case '\t': cbsSay = 't'; break; - default: cbsSay = 0; break; - } - if( cbsSay ){ - ace[1] = cbsSay; - oputz(ace); + if( c=='\\' || c=='"' ){ + fputc('\\', out); + fputc(c, out); }else if( c<=0x1f ){ - oputf("u%04x", c); + fputc('\\', out); + if( c=='\b' ){ + fputc('b', out); + }else if( c=='\f' ){ + fputc('f', out); + }else if( c=='\n' ){ + fputc('n', out); + }else if( c=='\r' ){ + fputc('r', out); + }else if( c=='\t' ){ + fputc('t', out); + }else{ + raw_printf(out, "u%04x",c); + } }else{ - ace[1] = (char)c; - oputz(ace+1); + fputc(c, out); } } - oputz(zq); + fputc('"', out); } /* ** Output the given string with characters that are special to ** HTML escaped. */ -static void output_html_string(const char *z){ +static void output_html_string(FILE *out, const char *z){ int i; if( z==0 ) z = ""; while( *z ){ for(i=0; z[i] && z[i]!='<' @@ -1968,22 +2072,22 @@ && z[i]!='>' && z[i]!='\"' && z[i]!='\''; i++){} if( i>0 ){ - oputf("%.*s",i,z); + utf8_printf(out,"%.*s",i,z); } if( z[i]=='<' ){ - oputz("<"); + raw_printf(out,"<"); }else if( z[i]=='&' ){ - oputz("&"); + raw_printf(out,"&"); }else if( z[i]=='>' ){ - oputz(">"); + raw_printf(out,">"); }else if( z[i]=='\"' ){ - oputz("""); + raw_printf(out,"""); }else if( z[i]=='\'' ){ - oputz("'"); + raw_printf(out,"'"); }else{ break; } z += i + 1; } @@ -2017,12 +2121,13 @@ ** the separator, which may or may not be a comma. p->nullValue is ** the null value. Strings are quoted if necessary. The separator ** is only issued if bSep is true. */ static void output_csv(ShellState *p, const char *z, int bSep){ + FILE *out = p->out; if( z==0 ){ - oputf("%s",p->nullValue); + utf8_printf(out,"%s",p->nullValue); }else{ unsigned i; for(i=0; z[i]; i++){ if( needCsvQuote[((unsigned char*)z)[i]] ){ i = 0; @@ -2030,18 +2135,18 @@ } } if( i==0 || strstr(z, p->colSeparator)!=0 ){ char *zQuoted = sqlite3_mprintf("\"%w\"", z); shell_check_oom(zQuoted); - oputz(zQuoted); + utf8_printf(out, "%s", zQuoted); sqlite3_free(zQuoted); }else{ - oputz(z); + utf8_printf(out, "%s", z); } } if( bSep ){ - oputz(p->colSeparator); + utf8_printf(p->out, "%s", p->colSeparator); } } /* ** This routine runs when the user presses Ctrl-C @@ -2145,20 +2250,20 @@ const char *az[4]; az[0] = zA1; az[1] = zA2; az[2] = zA3; az[3] = zA4; - oputf("authorizer: %s", azAction[op]); + utf8_printf(p->out, "authorizer: %s", azAction[op]); for(i=0; i<4; i++){ - oputz(" "); + raw_printf(p->out, " "); if( az[i] ){ - output_c_string(az[i]); + output_c_string(p->out, az[i]); }else{ - oputz("NULL"); + raw_printf(p->out, "NULL"); } } - oputz("\n"); + raw_printf(p->out, "\n"); if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4); return SQLITE_OK; } #endif @@ -2170,11 +2275,11 @@ ** ** If the schema statement in z[] contains a start-of-comment and if ** sqlite3_complete() returns false, try to terminate the comment before ** printing the result. https://sqlite.org/forum/forumpost/d7be961c5c */ -static void printSchemaLine(const char *z, const char *zTail){ +static void printSchemaLine(FILE *out, const char *z, const char *zTail){ char *zToFree = 0; if( z==0 ) return; if( zTail==0 ) return; if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){ const char *zOrig = z; @@ -2192,20 +2297,20 @@ } sqlite3_free(zNew); } } if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){ - oputf("CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); + utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); }else{ - oputf("%s%s", z, zTail); + utf8_printf(out, "%s%s", z, zTail); } sqlite3_free(zToFree); } -static void printSchemaLineN(char *z, int n, const char *zTail){ +static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){ char c = z[n]; z[n] = 0; - printSchemaLine(z, zTail); + printSchemaLine(out, z, zTail); z[n] = c; } /* ** Return true if string z[] has nothing but whitespace and comments to the @@ -2229,11 +2334,11 @@ EQPGraphRow *pNew; i64 nText; if( zText==0 ) return; nText = strlen(zText); if( p->autoEQPtest ){ - oputf("%d,%d,%s\n", iEqpId, p2, zText); + utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); } pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); shell_check_oom(pNew); pNew->iEqpId = iEqpId; pNew->iParentId = p2; @@ -2277,11 +2382,12 @@ i64 n = strlen(p->sGraph.zPrefix); char *z; for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ pNext = eqp_next_row(p, iEqpId, pRow); z = pRow->zText; - oputf("%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z); + utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, + pNext ? "|--" : "`--", z); if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){ memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); eqp_render_level(p, pRow->iEqpId); p->sGraph.zPrefix[n] = 0; } @@ -2297,17 +2403,17 @@ if( pRow->zText[0]=='-' ){ if( pRow->pNext==0 ){ eqp_reset(p); return; } - oputf("%s\n", pRow->zText+3); + utf8_printf(p->out, "%s\n", pRow->zText+3); p->sGraph.pRow = pRow->pNext; sqlite3_free(pRow); }else if( nCycle>0 ){ - oputf("QUERY PLAN (cycles=%lld [100%%])\n", nCycle); + utf8_printf(p->out, "QUERY PLAN (cycles=%lld [100%%])\n", nCycle); }else{ - oputz("QUERY PLAN\n"); + utf8_printf(p->out, "QUERY PLAN\n"); } p->sGraph.zPrefix[0] = 0; eqp_render_level(p, 0); eqp_reset(p); } @@ -2319,33 +2425,33 @@ */ static int progress_handler(void *pClientData) { ShellState *p = (ShellState*)pClientData; p->nProgress++; if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){ - oputf("Progress limit reached (%u)\n", p->nProgress); + raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress); if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0; return 1; } if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){ - oputf("Progress %u\n", p->nProgress); + raw_printf(p->out, "Progress %u\n", p->nProgress); } return 0; } #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ /* ** Print N dashes */ -static void print_dashes(int N){ +static void print_dashes(FILE *out, int N){ const char zDash[] = "--------------------------------------------------"; const int nDash = sizeof(zDash) - 1; while( N>nDash ){ - oputz(zDash); + fputs(zDash, out); N -= nDash; } - oputf("%.*s", N, zDash); + raw_printf(out, "%.*s", N, zDash); } /* ** Print a markdown or table-style row separator using ascii-art */ @@ -2354,19 +2460,19 @@ int nArg, const char *zSep ){ int i; if( nArg>0 ){ - oputz(zSep); - print_dashes(p->actualWidth[0]+2); + fputs(zSep, p->out); + print_dashes(p->out, p->actualWidth[0]+2); for(i=1; iactualWidth[i]+2); + fputs(zSep, p->out); + print_dashes(p->out, p->actualWidth[i]+2); } - oputz(zSep); + fputs(zSep, p->out); } - oputz("\n"); + fputs("\n", p->out); } /* ** This is the callback routine that the shell ** invokes for each row of a query result. @@ -2392,14 +2498,14 @@ if( azArg==0 ) break; for(i=0; iw ) w = len; } - if( p->cnt++>0 ) oputz(p->rowSeparator); + if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator); for(i=0; inullValue, p->rowSeparator); + utf8_printf(p->out,"%*s = %s%s", w, azCol[i], + azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); } break; } case MODE_ScanExp: case MODE_Explain: { @@ -2422,16 +2528,16 @@ if( nArg>nWidth ) nArg = nWidth; /* If this is the first row seen, print out the headers */ if( p->cnt++==0 ){ for(i=0; iout, aWidth[i], azCol[ aMap[i] ]); + fputs(i==nArg-1 ? "\n" : " ", p->out); } for(i=0; iout, aWidth[i]); + fputs(i==nArg-1 ? "\n" : " ", p->out); } } /* If there is no data, exit early. */ if( azArg==0 ) break; @@ -2445,21 +2551,21 @@ w = strlenChar(zVal); zSep = " "; } if( i==iIndent && p->aiIndent && p->pStmt ){ if( p->iIndentnIndent ){ - oputf("%*.s", p->aiIndent[p->iIndent], ""); + utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); } p->iIndent++; } - utf8_width_print(w, zVal ? zVal : p->nullValue); - oputz(i==nArg-1 ? "\n" : zSep); + utf8_width_print(p->out, w, zVal ? zVal : p->nullValue); + fputs(i==nArg-1 ? "\n" : zSep, p->out); } break; } case MODE_Semi: { /* .schema and .fullschema output */ - printSchemaLine(azArg[0], ";\n"); + printSchemaLine(p->out, azArg[0], ";\n"); break; } case MODE_Pretty: { /* .schema and .fullschema with --indent */ char *z; int j; @@ -2470,11 +2576,11 @@ assert( nArg==1 ); if( azArg[0]==0 ) break; if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 ){ - oputf("%s;\n", azArg[0]); + utf8_printf(p->out, "%s;\n", azArg[0]); break; } z = sqlite3_mprintf("%s", azArg[0]); shell_check_oom(z); j = 0; @@ -2503,161 +2609,166 @@ }else if( c=='(' ){ nParen++; }else if( c==')' ){ nParen--; if( nLine>0 && nParen==0 && j>0 ){ - printSchemaLineN(z, j, "\n"); + printSchemaLineN(p->out, z, j, "\n"); j = 0; } } z[j++] = c; if( nParen==1 && cEnd==0 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1))) ){ if( c=='\n' ) j--; - printSchemaLineN(z, j, "\n "); + printSchemaLineN(p->out, z, j, "\n "); j = 0; nLine++; while( IsSpace(z[i+1]) ){ i++; } } } z[j] = 0; } - printSchemaLine(z, ";\n"); + printSchemaLine(p->out, z, ";\n"); sqlite3_free(z); break; } case MODE_List: { if( p->cnt++==0 && p->showHeader ){ for(i=0; irowSeparator : p->colSeparator); + utf8_printf(p->out,"%s%s",azCol[i], + i==nArg-1 ? p->rowSeparator : p->colSeparator); } } if( azArg==0 ) break; for(i=0; inullValue; - oputz(z); - oputz((icolSeparator : p->rowSeparator); + utf8_printf(p->out, "%s", z); + if( iout, "%s", p->colSeparator); + }else{ + utf8_printf(p->out, "%s", p->rowSeparator); + } } break; } case MODE_Html: { if( p->cnt++==0 && p->showHeader ){ - oputz(""); + raw_printf(p->out,""); for(i=0; i"); - output_html_string(azCol[i]); - oputz("\n"); + raw_printf(p->out,""); + output_html_string(p->out, azCol[i]); + raw_printf(p->out,"\n"); } - oputz("\n"); + raw_printf(p->out,"\n"); } if( azArg==0 ) break; - oputz(""); + raw_printf(p->out,""); for(i=0; i"); - output_html_string(azArg[i] ? azArg[i] : p->nullValue); - oputz("\n"); + raw_printf(p->out,""); + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue); + raw_printf(p->out,"\n"); } - oputz("\n"); + raw_printf(p->out,"\n"); break; } case MODE_Tcl: { if( p->cnt++==0 && p->showHeader ){ for(i=0; icolSeparator); + output_c_string(p->out,azCol[i] ? azCol[i] : ""); + if(iout, "%s", p->colSeparator); } - oputz(p->rowSeparator); + utf8_printf(p->out, "%s", p->rowSeparator); } if( azArg==0 ) break; for(i=0; inullValue); - if(icolSeparator); + output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue); + if(iout, "%s", p->colSeparator); } - oputz(p->rowSeparator); + utf8_printf(p->out, "%s", p->rowSeparator); break; } case MODE_Csv: { setBinaryMode(p->out, 1); if( p->cnt++==0 && p->showHeader ){ for(i=0; irowSeparator); + utf8_printf(p->out, "%s", p->rowSeparator); } if( nArg>0 ){ for(i=0; irowSeparator); + utf8_printf(p->out, "%s", p->rowSeparator); } setTextMode(p->out, 1); break; } case MODE_Insert: { if( azArg==0 ) break; - oputf("INSERT INTO %s",p->zDestTable); + utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); if( p->showHeader ){ - oputz("("); + raw_printf(p->out,"("); for(i=0; i0 ) oputz(","); + if( i>0 ) raw_printf(p->out, ","); if( quoteChar(azCol[i]) ){ char *z = sqlite3_mprintf("\"%w\"", azCol[i]); shell_check_oom(z); - oputz(z); + utf8_printf(p->out, "%s", z); sqlite3_free(z); }else{ - oputf("%s", azCol[i]); + raw_printf(p->out, "%s", azCol[i]); } } - oputz(")"); + raw_printf(p->out,")"); } p->cnt++; for(i=0; i0 ? "," : " VALUES("); + raw_printf(p->out, i>0 ? "," : " VALUES("); if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ - oputz("NULL"); + utf8_printf(p->out,"NULL"); }else if( aiType && aiType[i]==SQLITE_TEXT ){ if( ShellHasFlag(p, SHFLG_Newlines) ){ - output_quoted_string(azArg[i]); + output_quoted_string(p->out, azArg[i]); }else{ - output_quoted_escaped_string(azArg[i]); + output_quoted_escaped_string(p->out, azArg[i]); } }else if( aiType && aiType[i]==SQLITE_INTEGER ){ - oputz(azArg[i]); + utf8_printf(p->out,"%s", azArg[i]); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ char z[50]; double r = sqlite3_column_double(p->pStmt, i); sqlite3_uint64 ur; memcpy(&ur,&r,sizeof(r)); if( ur==0x7ff0000000000000LL ){ - oputz("9.0e+999"); + raw_printf(p->out, "9.0e+999"); }else if( ur==0xfff0000000000000LL ){ - oputz("-9.0e+999"); + raw_printf(p->out, "-9.0e+999"); }else{ sqlite3_int64 ir = (sqlite3_int64)r; if( r==(double)ir ){ sqlite3_snprintf(50,z,"%lld.0", ir); }else{ sqlite3_snprintf(50,z,"%!.20g", r); } - oputz(z); + raw_printf(p->out, "%s", z); } }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ const void *pBlob = sqlite3_column_blob(p->pStmt, i); int nBlob = sqlite3_column_bytes(p->pStmt, i); - output_hex_blob(pBlob, nBlob); + output_hex_blob(p->out, pBlob, nBlob); }else if( isNumber(azArg[i], 0) ){ - oputz(azArg[i]); + utf8_printf(p->out,"%s", azArg[i]); }else if( ShellHasFlag(p, SHFLG_Newlines) ){ - output_quoted_string(azArg[i]); + output_quoted_string(p->out, azArg[i]); }else{ - output_quoted_escaped_string(azArg[i]); + output_quoted_escaped_string(p->out, azArg[i]); } } - oputz(");\n"); + raw_printf(p->out,");\n"); break; } case MODE_Json: { if( azArg==0 ) break; if( p->cnt==0 ){ @@ -2665,93 +2776,93 @@ }else{ fputs(",\n{", p->out); } p->cnt++; for(i=0; iout, azCol[i], -1); + putc(':', p->out); if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ - oputz("null"); + fputs("null",p->out); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ char z[50]; double r = sqlite3_column_double(p->pStmt, i); sqlite3_uint64 ur; memcpy(&ur,&r,sizeof(r)); if( ur==0x7ff0000000000000LL ){ - oputz("9.0e+999"); + raw_printf(p->out, "9.0e+999"); }else if( ur==0xfff0000000000000LL ){ - oputz("-9.0e+999"); + raw_printf(p->out, "-9.0e+999"); }else{ sqlite3_snprintf(50,z,"%!.20g", r); - oputz(z); + raw_printf(p->out, "%s", z); } }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ const void *pBlob = sqlite3_column_blob(p->pStmt, i); int nBlob = sqlite3_column_bytes(p->pStmt, i); - output_json_string(pBlob, nBlob); + output_json_string(p->out, pBlob, nBlob); }else if( aiType && aiType[i]==SQLITE_TEXT ){ - output_json_string(azArg[i], -1); + output_json_string(p->out, azArg[i], -1); }else{ - oputz(azArg[i]); + utf8_printf(p->out,"%s", azArg[i]); } if( iout); } } - oputz("}"); + putc('}', p->out); break; } case MODE_Quote: { if( azArg==0 ) break; if( p->cnt==0 && p->showHeader ){ for(i=0; i0 ) fputs(p->colSeparator, p->out); - output_quoted_string(azCol[i]); + output_quoted_string(p->out, azCol[i]); } fputs(p->rowSeparator, p->out); } p->cnt++; for(i=0; i0 ) fputs(p->colSeparator, p->out); if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ - oputz("NULL"); + utf8_printf(p->out,"NULL"); }else if( aiType && aiType[i]==SQLITE_TEXT ){ - output_quoted_string(azArg[i]); + output_quoted_string(p->out, azArg[i]); }else if( aiType && aiType[i]==SQLITE_INTEGER ){ - oputz(azArg[i]); + utf8_printf(p->out,"%s", azArg[i]); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ char z[50]; double r = sqlite3_column_double(p->pStmt, i); sqlite3_snprintf(50,z,"%!.20g", r); - oputz(z); + raw_printf(p->out, "%s", z); }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ const void *pBlob = sqlite3_column_blob(p->pStmt, i); int nBlob = sqlite3_column_bytes(p->pStmt, i); - output_hex_blob(pBlob, nBlob); + output_hex_blob(p->out, pBlob, nBlob); }else if( isNumber(azArg[i], 0) ){ - oputz(azArg[i]); + utf8_printf(p->out,"%s", azArg[i]); }else{ - output_quoted_string(azArg[i]); + output_quoted_string(p->out, azArg[i]); } } fputs(p->rowSeparator, p->out); break; } case MODE_Ascii: { if( p->cnt++==0 && p->showHeader ){ for(i=0; i0 ) oputz(p->colSeparator); - oputz(azCol[i] ? azCol[i] : ""); + if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); + utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : ""); } - oputz(p->rowSeparator); + utf8_printf(p->out, "%s", p->rowSeparator); } if( azArg==0 ) break; for(i=0; i0 ) oputz(p->colSeparator); - oputz(azArg[i] ? azArg[i] : p->nullValue); + if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); + utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue); } - oputz(p->rowSeparator); + utf8_printf(p->out, "%s", p->rowSeparator); break; } case MODE_EQP: { eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]); break; @@ -2826,11 +2937,11 @@ "INSERT INTO selftest(tno,op,cmd,ans)" " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n" "DROP TABLE [_shell$self];" ,0,0,&zErrMsg); if( zErrMsg ){ - eputf("SELFTEST initialization failure: %s\n", zErrMsg); + utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg); sqlite3_free(zErrMsg); } sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0); } @@ -2929,36 +3040,37 @@ int i; const char *z; rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); if( rc!=SQLITE_OK || !pSelect ){ char *zContext = shell_error_context(zSelect, p->db); - oputf("/**** ERROR: (%d) %s *****/\n%s", - rc, sqlite3_errmsg(p->db), zContext); + 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; } rc = sqlite3_step(pSelect); nResult = sqlite3_column_count(pSelect); while( rc==SQLITE_ROW ){ z = (const char*)sqlite3_column_text(pSelect, 0); - oputf("%s", z); + utf8_printf(p->out, "%s", z); for(i=1; iout, ",%s", sqlite3_column_text(pSelect, i)); } if( z==0 ) z = ""; while( z[0] && (z[0]!='-' || z[1]!='-') ) z++; if( z[0] ){ - oputz("\n;\n"); + raw_printf(p->out, "\n;\n"); }else{ - oputz(";\n"); + raw_printf(p->out, ";\n"); } rc = sqlite3_step(pSelect); } rc = sqlite3_finalize(pSelect); if( rc!=SQLITE_OK ){ - oputf("/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); + utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, + sqlite3_errmsg(p->db)); if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; } return rc; } @@ -2990,11 +3102,11 @@ #ifdef __linux__ /* ** Attempt to display I/O stats on Linux using /proc/PID/io */ -static void displayLinuxIoStats(void){ +static void displayLinuxIoStats(FILE *out){ FILE *in; char z[200]; sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid()); in = fopen(z, "rb"); if( in==0 ) return; @@ -3013,11 +3125,11 @@ }; int i; for(i=0; i1 ){ sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr); }else{ sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr); } - oputf("%-36s %s\n", zLabel, zLine); + raw_printf(p->out, "%-36s %s\n", zLabel, zLine); } /* ** Display memory stats. */ @@ -3057,130 +3170,141 @@ ShellState *pArg, /* Pointer to ShellState */ int bReset /* True to reset the stats */ ){ int iCur; int iHiwtr; + FILE *out; if( pArg==0 || pArg->out==0 ) return 0; + out = pArg->out; if( pArg->pStmt && pArg->statsOn==2 ){ int nCol, i, x; sqlite3_stmt *pStmt = pArg->pStmt; char z[100]; nCol = sqlite3_column_count(pStmt); - oputf("%-36s %d\n", "Number of output columns:", nCol); + raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol); for(i=0; istatsOn==3 ){ if( pArg->pStmt ){ iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP,bReset); - oputf("VM-steps: %d\n", iCur); + raw_printf(pArg->out, "VM-steps: %d\n", iCur); } return 0; } - displayStatLine("Memory Used:", + displayStatLine(pArg, "Memory Used:", "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset); - displayStatLine("Number of Outstanding Allocations:", + displayStatLine(pArg, "Number of Outstanding Allocations:", "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset); if( pArg->shellFlgs & SHFLG_Pagecache ){ - displayStatLine("Number of Pcache Pages Used:", + displayStatLine(pArg, "Number of Pcache Pages Used:", "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset); } - displayStatLine("Number of Pcache Overflow Bytes:", + displayStatLine(pArg, "Number of Pcache Overflow Bytes:", "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset); - displayStatLine("Largest Allocation:", + displayStatLine(pArg, "Largest Allocation:", "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset); - displayStatLine("Largest Pcache Allocation:", + displayStatLine(pArg, "Largest Pcache Allocation:", "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset); #ifdef YYTRACKMAXSTACKDEPTH - displayStatLine("Deepest Parser Stack:", + displayStatLine(pArg, "Deepest Parser Stack:", "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset); #endif if( db ){ if( pArg->shellFlgs & SHFLG_Lookaside ){ iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); - oputf("Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr); + raw_printf(pArg->out, + "Lookaside Slots Used: %d (max %d)\n", + iCur, iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset); - oputf("Successful lookaside attempts: %d\n", iHiwtr); + raw_printf(pArg->out, "Successful lookaside attempts: %d\n", + iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset); - oputf("Lookaside failures due to size: %d\n", iHiwtr); + raw_printf(pArg->out, "Lookaside failures due to size: %d\n", + iHiwtr); sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset); - oputf("Lookaside failures due to OOM: %d\n", iHiwtr); + raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n", + iHiwtr); } iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); - oputf("Pager Heap Usage: %d bytes\n", iCur); + raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n", + iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); - oputf("Page cache hits: %d\n", iCur); + raw_printf(pArg->out, "Page cache hits: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); - oputf("Page cache misses: %d\n", iCur); + raw_printf(pArg->out, "Page cache misses: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); - oputf("Page cache writes: %d\n", iCur); + raw_printf(pArg->out, "Page cache writes: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1); - oputf("Page cache spills: %d\n", iCur); + raw_printf(pArg->out, "Page cache spills: %d\n", iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); - oputf("Schema Heap Usage: %d bytes\n", iCur); + raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n", + iCur); iHiwtr = iCur = -1; sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); - oputf("Statement Heap/Lookaside Usage: %d bytes\n", iCur); + raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", + iCur); } if( pArg->pStmt ){ int iHit, iMiss; iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset); - oputf("Fullscan Steps: %d\n", iCur); + raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); - oputf("Sort Operations: %d\n", iCur); + raw_printf(pArg->out, "Sort Operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); - oputf("Autoindex Inserts: %d\n", iCur); + 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 ){ - oputf("Bloom filter bypass taken: %d/%d\n", iHit, 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); - oputf("Virtual Machine Steps: %d\n", iCur); + raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset); - oputf("Reprepare operations: %d\n", iCur); + raw_printf(pArg->out, "Reprepare operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset); - oputf("Number of times run: %d\n", iCur); + raw_printf(pArg->out, "Number of times run: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset); - oputf("Memory used by prepared stmt: %d\n", iCur); + raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur); } #ifdef __linux__ - displayLinuxIoStats(); + displayLinuxIoStats(pArg->out); #endif /* Do not remove this machine readable comment: extra-stats-output-here */ return 0; @@ -3231,11 +3355,11 @@ const char *z = 0; int n = 0; if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){ break; } - n = (int)strlen(z) + scanStatsHeight(p, ii)*3; + n = strlen(z) + scanStatsHeight(p, ii)*3; if( n>nWidth ) nWidth = n; } nWidth += 4; sqlite3_stmt_scanstatus_v2(p, -1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal); @@ -3243,16 +3367,16 @@ i64 nLoop = 0; i64 nRow = 0; i64 nCycle = 0; int iId = 0; int iPid = 0; - const char *zo = 0; + const char *z = 0; const char *zName = 0; char *zText = 0; double rEst = 0.0; - if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){ + if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){ break; } sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_EST,f,(void*)&rEst); sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop); sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow); @@ -3259,11 +3383,11 @@ sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle); sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId); sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid); sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NAME,f,(void*)&zName); - zText = sqlite3_mprintf("%s", zo); + zText = sqlite3_mprintf("%s", z); if( nCycle>=0 || nLoop>=0 || nRow>=0 ){ char *z = 0; if( nCycle>=0 && nTotal>0 ){ z = sqlite3_mprintf("%zcycles=%lld [%d%%]", z, nCycle, ((nCycle*100)+nTotal/2) / nTotal @@ -3411,11 +3535,11 @@ #ifndef SQLITE_ENABLE_STMT_SCANSTATUS UNUSED_PARAMETER(db); UNUSED_PARAMETER(pArg); #else if( pArg->scanstatsOn==3 ){ - const char *zSql = + const char *zSql = " SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec," " round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles" " FROM bytecode(?)"; int rc = SQLITE_OK; @@ -3557,21 +3681,21 @@ #define BOX_1234 "\342\224\274" /* U+253c -|- */ /* Draw horizontal line N characters long using unicode box ** characters */ -static void print_box_line(int N){ +static void print_box_line(FILE *out, int N){ const char zDash[] = BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24; const int nDash = sizeof(zDash) - 1; N *= 3; while( N>nDash ){ - oputz(zDash); + utf8_printf(out, zDash); N -= nDash; } - oputf("%.*s", N, zDash); + utf8_printf(out, "%.*s", N, zDash); } /* ** Draw a horizontal separator for a MODE_Box table. */ @@ -3582,19 +3706,19 @@ const char *zSep2, const char *zSep3 ){ int i; if( nArg>0 ){ - oputz(zSep1); - print_box_line(p->actualWidth[0]+2); + utf8_printf(p->out, "%s", zSep1); + print_box_line(p->out, p->actualWidth[0]+2); for(i=1; iactualWidth[i]+2); + utf8_printf(p->out, "%s", zSep2); + print_box_line(p->out, p->actualWidth[i]+2); } - oputz(zSep3); + utf8_printf(p->out, "%s", zSep3); } - oputz("\n"); + 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 @@ -3853,15 +3977,15 @@ rowSep = "\n"; if( p->showHeader ){ for(i=0; iactualWidth[i]; if( p->colWidth[i]<0 ) w = -w; - utf8_width_print(w, azData[i]); + utf8_width_print(p->out, w, azData[i]); fputs(i==nColumn-1?"\n":" ", p->out); } for(i=0; iactualWidth[i]); + print_dashes(p->out, p->actualWidth[i]); fputs(i==nColumn-1?"\n":" ", p->out); } } break; } @@ -3871,12 +3995,12 @@ print_row_separator(p, nColumn, "+"); fputs("| ", p->out); for(i=0; iactualWidth[i]; n = strlenChar(azData[i]); - oputf("%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); - oputz(i==nColumn-1?" |\n":" | "); + utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); + fputs(i==nColumn-1?" |\n":" | ", p->out); } print_row_separator(p, nColumn, "+"); break; } case MODE_Markdown: { @@ -3884,66 +4008,66 @@ rowSep = " |\n"; fputs("| ", p->out); for(i=0; iactualWidth[i]; n = strlenChar(azData[i]); - oputf("%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); - oputz(i==nColumn-1?" |\n":" | "); + utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); + fputs(i==nColumn-1?" |\n":" | ", p->out); } print_row_separator(p, nColumn, "|"); break; } case MODE_Box: { colSep = " " BOX_13 " "; rowSep = " " BOX_13 "\n"; print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34); - oputz(BOX_13 " "); + utf8_printf(p->out, BOX_13 " "); for(i=0; iactualWidth[i]; n = strlenChar(azData[i]); - oputf("%*s%s%*s%s", - (w-n)/2, "", azData[i], (w-n+1)/2, "", - i==nColumn-1?" "BOX_13"\n":" "BOX_13" "); + utf8_printf(p->out, "%*s%s%*s%s", + (w-n)/2, "", azData[i], (w-n+1)/2, "", + i==nColumn-1?" "BOX_13"\n":" "BOX_13" "); } print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134); break; } } for(i=nColumn, j=0; icMode!=MODE_Column ){ - oputz(p->cMode==MODE_Box?BOX_13" ":"| "); + utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| "); } z = azData[i]; if( z==0 ) z = p->nullValue; w = p->actualWidth[j]; if( p->colWidth[j]<0 ) w = -w; - utf8_width_print(w, z); + utf8_width_print(p->out, w, z); if( j==nColumn-1 ){ - oputz(rowSep); + utf8_printf(p->out, "%s", rowSep); if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1cMode==MODE_Table ){ print_row_separator(p, nColumn, "+"); }else if( p->cMode==MODE_Box ){ print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134); }else if( p->cMode==MODE_Column ){ - oputz("\n"); + raw_printf(p->out, "\n"); } } j = -1; if( seenInterrupt ) goto columnar_end; }else{ - oputz(colSep); + utf8_printf(p->out, "%s", colSep); } } if( p->cMode==MODE_Table ){ print_row_separator(p, nColumn, "+"); }else if( p->cMode==MODE_Box ){ print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14); } columnar_end: if( seenInterrupt ){ - oputz("Interrupt\n"); + utf8_printf(p->out, "Interrupt\n"); } nData = (nRow+1)*nColumn; for(i=0; iexpert.pExpert; assert( p ); assert( bCancel || pzErr==0 || *pzErr==0 ); if( bCancel==0 ){ + FILE *out = pState->out; int bVerbose = pState->expert.bVerbose; rc = sqlite3_expert_analyze(p, pzErr); if( rc==SQLITE_OK ){ int nQuery = sqlite3_expert_count(p); int i; if( bVerbose ){ const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES); - oputz("-- Candidates -----------------------------\n"); - oputf("%s\n", zCand); + raw_printf(out, "-- Candidates -----------------------------\n"); + raw_printf(out, "%s\n", zCand); } for(i=0; iexpert.pExpert = 0; @@ -4135,30 +4260,31 @@ if( n>=2 && 0==cli_strncmp(z, "-verbose", n) ){ pState->expert.bVerbose = 1; } else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){ if( i==(nArg-1) ){ - eputf("option requires an argument: %s\n", z); + raw_printf(stderr, "option requires an argument: %s\n", z); rc = SQLITE_ERROR; }else{ iSample = (int)integerValue(azArg[++i]); if( iSample<0 || iSample>100 ){ - eputf("value out of range: %s\n", azArg[i]); + raw_printf(stderr, "value out of range: %s\n", azArg[i]); rc = SQLITE_ERROR; } } } else{ - eputf("unknown option: %s\n", z); + raw_printf(stderr, "unknown option: %s\n", z); rc = SQLITE_ERROR; } } if( rc==SQLITE_OK ){ pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr); if( pState->expert.pExpert==0 ){ - eputf("sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory"); + raw_printf(stderr, "sqlite3_expert_new: %s\n", + zErr ? zErr : "out of memory"); rc = SQLITE_ERROR; }else{ sqlite3_expert_config( pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample ); @@ -4481,33 +4607,33 @@ if( zType==0 ) return 0; dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0; noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0; if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){ - if( !dataOnly ) oputz("DELETE FROM sqlite_sequence;\n"); + if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n"); }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){ - if( !dataOnly ) oputz("ANALYZE sqlite_schema;\n"); + if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n"); }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){ return 0; }else if( dataOnly ){ /* no-op */ }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ char *zIns; if( !p->writableSchema ){ - oputz("PRAGMA writable_schema=ON;\n"); + raw_printf(p->out, "PRAGMA writable_schema=ON;\n"); p->writableSchema = 1; } zIns = sqlite3_mprintf( "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)" "VALUES('table','%q','%q',0,'%q');", zTable, zTable, zSql); shell_check_oom(zIns); - oputf("%s\n", zIns); + utf8_printf(p->out, "%s\n", zIns); sqlite3_free(zIns); return 0; }else{ - printSchemaLine(zSql, ";\n"); + printSchemaLine(p->out, zSql, ";\n"); } if( cli_strcmp(zType, "table")==0 ){ ShellText sSelect; ShellText sTable; @@ -4561,11 +4687,11 @@ savedMode = p->mode; p->zDestTable = sTable.z; p->mode = p->cMode = MODE_Insert; rc = shell_exec(p, sSelect.z, 0); if( (rc&0xff)==SQLITE_CORRUPT ){ - oputz("/****** CORRUPTION ERROR *******/\n"); + raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); toggleSelectOrder(p->db); shell_exec(p, sSelect.z, 0); toggleSelectOrder(p->db); } p->zDestTable = savedDestTable; @@ -4592,22 +4718,22 @@ char *zErr = 0; rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); if( rc==SQLITE_CORRUPT ){ char *zQ2; int len = strlen30(zQuery); - oputz("/****** CORRUPTION ERROR *******/\n"); + raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); if( zErr ){ - oputf("/****** %s ******/\n", zErr); + utf8_printf(p->out, "/****** %s ******/\n", zErr); sqlite3_free(zErr); zErr = 0; } zQ2 = malloc( len+100 ); if( zQ2==0 ) return rc; sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery); rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); if( rc ){ - oputf("/****** ERROR: %s ******/\n", zErr); + utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr); }else{ rc = SQLITE_CORRUPT; } sqlite3_free(zErr); free(zQ2); @@ -4959,24 +5085,24 @@ hh &= ~HH_Summary; break; } if( ((hw^hh)&HH_Undoc)==0 ){ if( (hh&HH_Summary)!=0 ){ - sputf(out, ".%s\n", azHelp[i]+1); + utf8_printf(out, ".%s\n", azHelp[i]+1); ++n; }else if( (hw&HW_SummaryOnly)==0 ){ - sputf(out, "%s\n", azHelp[i]); + utf8_printf(out, "%s\n", azHelp[i]); } } } }else{ /* Seek documented commands for which zPattern is an exact prefix */ zPat = sqlite3_mprintf(".%s*", zPattern); shell_check_oom(zPat); for(i=0; iin; @@ -5199,11 +5325,11 @@ n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */ a = sqlite3_malloc( n ? n : 1 ); shell_check_oom(a); memset(a, 0, n); if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){ - eputz("invalid pagesize\n"); + utf8_printf(stderr, "invalid pagesize\n"); goto readHexDb_error; } for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){ rc = sscanf(zLine, "| page %d offset %d", &j, &k); if( rc==2 ){ @@ -5241,11 +5367,11 @@ if(cli_strncmp(zLine, "| end ", 6)==0 ) break; } p->lineno = nLine; } sqlite3_free(a); - eputf("Error on line %d of --hexdb input\n", nLine); + utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine); return 0; } #endif /* SQLITE_OMIT_DESERIALIZE */ /* @@ -5317,23 +5443,26 @@ break; } } globalDb = p->db; if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ - eputf("Error: unable to open database \"%s\": %s\n", - zDbFilename, sqlite3_errmsg(p->db)); + utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", + zDbFilename, sqlite3_errmsg(p->db)); if( (openFlags & OPEN_DB_KEEPALIVE)==0 ){ exit(1); } sqlite3_close(p->db); sqlite3_open(":memory:", &p->db); if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ - eputz("Also: unable to open substitute in-memory database.\n"); + utf8_printf(stderr, + "Also: unable to open substitute in-memory database.\n" + ); exit(1); }else{ - eputf("Notice: using substitute in-memory database instead of \"%s\"\n", - zDbFilename); + utf8_printf(stderr, + "Notice: using substitute in-memory database instead of \"%s\"\n", + zDbFilename); } } sqlite3_db_config(p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, (int)0, (int*)0); /* Reflect the use or absence of --unsafe-testing invocation. */ @@ -5436,11 +5565,11 @@ } rc = sqlite3_deserialize(p->db, "main", aData, nData, nData, SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE); if( rc ){ - eputf("Error: sqlite3_deserialize() returns %d\n", rc); + utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc); } if( p->szMax>0 ){ sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax); } } @@ -5460,11 +5589,12 @@ ** Attempt to close the database connection. Report errors. */ void close_db(sqlite3 *db){ int rc = sqlite3_close(db); if( rc ){ - eputf("Error: sqlite3_close() returns %d: %s\n", rc, sqlite3_errmsg(db)); + utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n", + rc, sqlite3_errmsg(db)); } } #if HAVE_READLINE || HAVE_EDITLINE /* @@ -5621,11 +5751,12 @@ return 1; } if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){ return 0; } - eputf("ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", zArg); + utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", + zArg); return 0; } /* ** Set or clear a shell flag according to a boolean value. @@ -5659,11 +5790,11 @@ }else if( cli_strcmp(zFile, "off")==0 ){ f = 0; }else{ f = fopen(zFile, bTextMode ? "w" : "wb"); if( f==0 ){ - eputf("Error: cannot open \"%s\"\n", zFile); + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); } } return f; } @@ -5681,11 +5812,11 @@ sqlite3_stmt *pStmt; const char *zSql; i64 nSql; if( p->traceOut==0 ) return 0; if( mType==SQLITE_TRACE_CLOSE ){ - sputz(p->traceOut, "-- closing database connection\n"); + utf8_printf(p->traceOut, "-- closing database connection\n"); return 0; } if( mType!=SQLITE_TRACE_ROW && pX!=0 && ((const char*)pX)[0]=='-' ){ zSql = (const char*)pX; }else{ @@ -5712,16 +5843,16 @@ if( nSql>1000000000 ) nSql = 1000000000; while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; } switch( mType ){ case SQLITE_TRACE_ROW: case SQLITE_TRACE_STMT: { - sputf(p->traceOut, "%.*s;\n", (int)nSql, zSql); + utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql); break; } case SQLITE_TRACE_PROFILE: { sqlite3_int64 nNanosec = pX ? *(sqlite3_int64*)pX : 0; - sputf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec); + utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec); break; } } return 0; } @@ -5824,15 +5955,16 @@ do{ p->n--; }while( p->z[p->n]!=cQuote ); p->cTerm = c; break; } if( pc==cQuote && c!='\r' ){ - eputf("%s:%d: unescaped %c character\n", p->zFile, p->nLine, cQuote); + utf8_printf(stderr, "%s:%d: unescaped %c character\n", + p->zFile, p->nLine, cQuote); } if( c==EOF ){ - eputf("%s:%d: unterminated %c-quoted field\n", - p->zFile, startLine, cQuote); + utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n", + p->zFile, startLine, cQuote); p->cTerm = c; break; } import_append_char(p, c); ppc = pc; @@ -5926,12 +6058,13 @@ zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); shell_check_oom(zQuery); rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); if( rc ){ - eputf("Error %d: %s on [%s]\n", - sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery); + utf8_printf(stderr, "Error %d: %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); goto end_data_xfer; } n = sqlite3_column_count(pQuery); zInsert = sqlite3_malloc64(200 + nTable + n*3); shell_check_oom(zInsert); @@ -5943,12 +6076,13 @@ i += 2; } memcpy(zInsert+i, ");", 3); rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0); if( rc ){ - eputf("Error %d: %s on [%s]\n", - sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb), zInsert); + utf8_printf(stderr, "Error %d: %s on [%s]\n", + sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb), + zInsert); goto end_data_xfer; } for(k=0; k<2; k++){ while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ for(i=0; idb, zQuery, -1, &pQuery, 0); if( rc ){ - eputf("Warning: cannot step \"%s\" backwards", zTable); + utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable); break; } } /* End for(k=0...) */ end_data_xfer: @@ -6034,60 +6168,62 @@ zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" " WHERE %s ORDER BY rowid ASC", zWhere); shell_check_oom(zQuery); rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); if( rc ){ - eputf("Error: (%d) %s on [%s]\n", sqlite3_extended_errcode(p->db), - sqlite3_errmsg(p->db), zQuery); + utf8_printf(stderr, "Error: (%d) %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); goto end_schema_xfer; } while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ zName = sqlite3_column_text(pQuery, 0); zSql = sqlite3_column_text(pQuery, 1); if( zName==0 || zSql==0 ) continue; if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){ - sputf(stdout, "%s... ", zName); fflush(stdout); + printf("%s... ", zName); fflush(stdout); sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); if( zErrMsg ){ - eputf("Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); sqlite3_free(zErrMsg); zErrMsg = 0; } } if( xForEach ){ xForEach(p, newDb, (const char*)zName); } - sputz(stdout, "done\n"); + printf("done\n"); } if( rc!=SQLITE_DONE ){ sqlite3_finalize(pQuery); sqlite3_free(zQuery); zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" " WHERE %s ORDER BY rowid DESC", zWhere); shell_check_oom(zQuery); rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); if( rc ){ - eputf("Error: (%d) %s on [%s]\n", - sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery); + utf8_printf(stderr, "Error: (%d) %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); goto end_schema_xfer; } while( sqlite3_step(pQuery)==SQLITE_ROW ){ zName = sqlite3_column_text(pQuery, 0); zSql = sqlite3_column_text(pQuery, 1); if( zName==0 || zSql==0 ) continue; if( sqlite3_stricmp((char*)zName, "sqlite_sequence")==0 ) continue; - sputf(stdout, "%s... ", zName); fflush(stdout); + printf("%s... ", zName); fflush(stdout); sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); if( zErrMsg ){ - eputf("Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); sqlite3_free(zErrMsg); zErrMsg = 0; } if( xForEach ){ xForEach(p, newDb, (const char*)zName); } - sputz(stdout, "done\n"); + printf("done\n"); } } end_schema_xfer: sqlite3_finalize(pQuery); sqlite3_free(zQuery); @@ -6100,16 +6236,17 @@ */ static void tryToClone(ShellState *p, const char *zNewDb){ int rc; sqlite3 *newDb = 0; if( access(zNewDb,0)==0 ){ - eputf("File \"%s\" already exists.\n", zNewDb); + utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb); return; } rc = sqlite3_open(zNewDb, &newDb); if( rc ){ - eputf("Cannot create output database: %s\n", sqlite3_errmsg(newDb)); + utf8_printf(stderr, "Cannot create output database: %s\n", + sqlite3_errmsg(newDb)); }else{ sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0); sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0); tryToCloneSchema(p, newDb, "type='table'", tryToCloneData); tryToCloneSchema(p, newDb, "type!='table'", 0); @@ -6117,22 +6254,10 @@ sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); } close_db(newDb); } -#ifndef SQLITE_SHELL_FIDDLE -/* -** Change the output stream (file or pipe or console) to something else. -*/ -static void output_redir(ShellState *p, FILE *pfNew){ - if( p->out != stdout ) eputz("Output already redirected.\n"); - else{ - p->out = pfNew; - setOutputStream(pfNew); - } -} - /* ** Change the output file back to stdout. ** ** If the p->doXdgOpen flag is set, that means the output was being ** redirected to a temporary file named by p->zTempFile. In that case, @@ -6156,11 +6281,11 @@ "xdg-open"; #endif char *zCmd; zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile); if( system(zCmd) ){ - eputf("Failed: [%s]\n", zCmd); + utf8_printf(stderr, "Failed: [%s]\n", zCmd); }else{ /* Give the start/open/xdg-open command some time to get ** going before we continue, and potential delete the ** p->zTempFile data file out from under it */ sqlite3_sleep(2000); @@ -6171,16 +6296,11 @@ } #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ } p->outfile[0] = 0; p->out = stdout; - setOutputStream(stdout); } -#else -# define output_redir(SS,pfO) -# define output_reset(SS) -#endif /* ** Run an SQL command and return the single integer result. */ static int db_int(sqlite3 *db, const char *zSql){ @@ -6247,11 +6367,11 @@ if( p->db==0 ) return 1; rc = sqlite3_prepare_v2(p->db, "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1", -1, &pStmt, 0); if( rc ){ - eputf("error: %s\n", sqlite3_errmsg(p->db)); + utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db)); sqlite3_finalize(pStmt); return 1; } sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC); if( sqlite3_step(pStmt)==SQLITE_ROW @@ -6260,32 +6380,32 @@ const u8 *pb = sqlite3_column_blob(pStmt,0); shell_check_oom(pb); memcpy(aHdr, pb, 100); sqlite3_finalize(pStmt); }else{ - eputz("unable to read database header\n"); + raw_printf(stderr, "unable to read database header\n"); sqlite3_finalize(pStmt); return 1; } i = get2byteInt(aHdr+16); if( i==1 ) i = 65536; - oputf("%-20s %d\n", "database page size:", i); - oputf("%-20s %d\n", "write format:", aHdr[18]); - oputf("%-20s %d\n", "read format:", aHdr[19]); - oputf("%-20s %d\n", "reserved bytes:", aHdr[20]); + utf8_printf(p->out, "%-20s %d\n", "database page size:", i); + utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]); + utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]); + utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); for(i=0; iout, "%-20s %u", aField[i].zName, val); switch( ofst ){ case 56: { - if( val==1 ) oputz(" (utf8)"); - if( val==2 ) oputz(" (utf16le)"); - if( val==3 ) oputz(" (utf16be)"); + if( val==1 ) raw_printf(p->out, " (utf8)"); + if( val==2 ) raw_printf(p->out, " (utf16le)"); + if( val==3 ) raw_printf(p->out, " (utf16be)"); } } - oputz("\n"); + raw_printf(p->out, "\n"); } if( zDb==0 ){ zSchemaTab = sqlite3_mprintf("main.sqlite_schema"); }else if( cli_strcmp(zDb,"temp")==0 ){ zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema"); @@ -6294,25 +6414,25 @@ } for(i=0; idb, zSql); sqlite3_free(zSql); - oputf("%-20s %d\n", aQuery[i].zName, val); + utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val); } sqlite3_free(zSchemaTab); sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion); - oputf("%-20s %u\n", "data version", iDataVersion); + utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion); return 0; } #endif /* SQLITE_SHELL_HAVE_RECOVER */ /* ** Print the current sqlite3_errmsg() value to stderr and return 1. */ static int shellDatabaseError(sqlite3 *db){ const char *zErr = sqlite3_errmsg(db); - eputf("Error: %s\n", zErr); + utf8_printf(stderr, "Error: %s\n", zErr); return 1; } /* ** Compare the pattern in zGlob[] against the text in z[]. Return TRUE @@ -6543,10 +6663,11 @@ ShellState *pState, /* Current shell tool state */ char **azArg, /* Array of arguments passed to dot command */ int nArg /* Number of entries in azArg[] */ ){ sqlite3 *db = pState->db; /* Database handle to query "main" db of */ + FILE *out = pState->out; /* Stream to write non-error output to */ int bVerbose = 0; /* If -verbose is present */ int bGroupByParent = 0; /* If -groupbyparent is present */ int i; /* To iterate through azArg[] */ const char *zIndent = ""; /* How much to indent CREATE INDEX by */ int rc; /* Return code */ @@ -6624,11 +6745,13 @@ else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){ bGroupByParent = 1; zIndent = " "; } else{ - eputf("Usage: %s %s ?-verbose? ?-groupbyparent?\n", azArg[0], azArg[1]); + raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n", + azArg[0], azArg[1] + ); return SQLITE_ERROR; } } /* Register the fkey_collate_clause() SQL function */ @@ -6668,44 +6791,44 @@ } rc = sqlite3_finalize(pExplain); if( rc!=SQLITE_OK ) break; if( res<0 ){ - eputz("Error: internal error"); + raw_printf(stderr, "Error: internal error"); break; }else{ if( bGroupByParent && (bVerbose || res==0) && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) ){ - oputf("-- Parent table %s\n", zParent); + raw_printf(out, "-- Parent table %s\n", zParent); sqlite3_free(zPrev); zPrev = sqlite3_mprintf("%s", zParent); } if( res==0 ){ - oputf("%s%s --> %s\n", zIndent, zCI, zTarget); + raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); }else if( bVerbose ){ - oputf("%s/* no extra indexes required for %s -> %s */\n", - zIndent, zFrom, zTarget + raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", + zIndent, zFrom, zTarget ); } } } sqlite3_free(zPrev); if( rc!=SQLITE_OK ){ - eputf("%s\n", sqlite3_errmsg(db)); + raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); } rc2 = sqlite3_finalize(pSql); if( rc==SQLITE_OK && rc2!=SQLITE_OK ){ rc = rc2; - eputf("%s\n", sqlite3_errmsg(db)); + raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); } }else{ - eputf("%s\n", sqlite3_errmsg(db)); + raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); } return rc; } @@ -6721,13 +6844,13 @@ n = (nArg>=2 ? strlen30(azArg[1]) : 0); if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage; return lintFkeyIndexes(pState, azArg, nArg); usage: - eputf("Usage %s sub-command ?switches...?\n", azArg[0]); - eputz("Where sub-commands are:\n"); - eputz(" fkey-indexes\n"); + raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]); + raw_printf(stderr, "Where sub-commands are:\n"); + raw_printf(stderr, " fkey-indexes\n"); return SQLITE_ERROR; } #if !defined SQLITE_OMIT_VIRTUALTABLE static void shellPrepare( @@ -6738,11 +6861,13 @@ ){ *ppStmt = 0; if( *pRc==SQLITE_OK ){ int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); if( rc!=SQLITE_OK ){ - eputf("sql error: %s (%d)\n", sqlite3_errmsg(db), sqlite3_errcode(db)); + raw_printf(stderr, "sql error: %s (%d)\n", + sqlite3_errmsg(db), sqlite3_errcode(db) + ); *pRc = rc; } } } @@ -6789,11 +6914,11 @@ if( pStmt ){ sqlite3 *db = sqlite3_db_handle(pStmt); int rc = sqlite3_finalize(pStmt); if( *pRc==SQLITE_OK ){ if( rc!=SQLITE_OK ){ - eputf("SQL error: %s\n", sqlite3_errmsg(db)); + raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); } *pRc = rc; } } } @@ -6810,11 +6935,11 @@ ){ int rc = sqlite3_reset(pStmt); if( *pRc==SQLITE_OK ){ if( rc!=SQLITE_OK ){ sqlite3 *db = sqlite3_db_handle(pStmt); - eputf("SQL error: %s\n", sqlite3_errmsg(db)); + raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); } *pRc = rc; } } #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */ @@ -6860,15 +6985,15 @@ va_list ap; char *z; va_start(ap, zFmt); z = sqlite3_vmprintf(zFmt, ap); va_end(ap); - eputf("Error: %s\n", z); + utf8_printf(stderr, "Error: %s\n", z); if( pAr->fromCmdLine ){ - eputz("Use \"-A\" for more help\n"); + utf8_printf(stderr, "Use \"-A\" for more help\n"); }else{ - eputz("Use \".archive --help\" for more help\n"); + utf8_printf(stderr, "Use \".archive --help\" for more help\n"); } sqlite3_free(z); return SQLITE_ERROR; } @@ -6964,11 +7089,11 @@ }; int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch); struct ArSwitch *pEnd = &aSwitch[nSwitch]; if( nArg<=1 ){ - eputz("Wrong number of arguments. Usage:\n"); + utf8_printf(stderr, "Wrong number of arguments. Usage:\n"); return arUsage(stderr); }else{ char *z = azArg[1]; if( z[0]!='-' ){ /* Traditional style [tar] invocation */ @@ -7070,11 +7195,11 @@ } } } } if( pAr->eCmd==0 ){ - eputz("Required argument missing. Usage:\n"); + utf8_printf(stderr, "Required argument missing. Usage:\n"); return arUsage(stderr); } return SQLITE_OK; } @@ -7113,11 +7238,11 @@ if( SQLITE_ROW==sqlite3_step(pTest) ){ bOk = 1; } shellReset(&rc, pTest); if( rc==SQLITE_OK && bOk==0 ){ - eputf("not found in archive: %s\n", z); + utf8_printf(stderr, "not found in archive: %s\n", z); rc = SQLITE_ERROR; } } shellFinalize(&rc, pTest); } @@ -7180,26 +7305,30 @@ arWhereClause(&rc, pAr, &zWhere); shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose], pAr->zSrcTable, zWhere); if( pAr->bDryRun ){ - oputf("%s\n", sqlite3_sql(pSql)); + utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); }else{ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ if( pAr->bVerbose ){ - oputf("%s % 10d %s %s\n", - sqlite3_column_text(pSql, 0), sqlite3_column_int(pSql, 1), - sqlite3_column_text(pSql, 2),sqlite3_column_text(pSql, 3)); + utf8_printf(pAr->p->out, "%s % 10d %s %s\n", + sqlite3_column_text(pSql, 0), + sqlite3_column_int(pSql, 1), + sqlite3_column_text(pSql, 2), + sqlite3_column_text(pSql, 3) + ); }else{ - oputf("%s\n", sqlite3_column_text(pSql, 0)); + utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); } } } shellFinalize(&rc, pSql); sqlite3_free(zWhere); return rc; } + /* ** Implementation of .ar "Remove" command. */ static int arRemoveCommand(ArCommand *pAr){ @@ -7215,11 +7344,11 @@ } if( rc==SQLITE_OK ){ zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;", pAr->zSrcTable, zWhere); if( pAr->bDryRun ){ - oputf("%s\n", zSql); + utf8_printf(pAr->p->out, "%s\n", zSql); }else{ char *zErr = 0; rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); @@ -7228,11 +7357,11 @@ }else{ rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0); } } if( zErr ){ - sputf(stdout, "ERROR: %s\n", zErr); /* stdout? */ + utf8_printf(stdout, "ERROR: %s\n", zErr); sqlite3_free(zErr); } } } sqlite3_free(zWhere); @@ -7292,15 +7421,15 @@ ** populating them changes the timestamp). */ for(i=0; i<2; i++){ j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); sqlite3_bind_int(pSql, j, i); if( pAr->bDryRun ){ - oputf("%s\n", sqlite3_sql(pSql)); + utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); }else{ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ if( i==0 && pAr->bVerbose ){ - oputf("%s\n", sqlite3_column_text(pSql, 0)); + utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); } } } shellReset(&rc, pSql); } @@ -7316,17 +7445,17 @@ ** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out. */ static int arExecSql(ArCommand *pAr, const char *zSql){ int rc; if( pAr->bDryRun ){ - oputf("%s\n", zSql); + utf8_printf(pAr->p->out, "%s\n", zSql); rc = SQLITE_OK; }else{ char *zErr = 0; rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); if( zErr ){ - sputf(stdout, "ERROR: %s\n", zErr); + utf8_printf(stdout, "ERROR: %s\n", zErr); sqlite3_free(zErr); } } return rc; } @@ -7497,17 +7626,19 @@ }else{ flags = SQLITE_OPEN_READONLY; } cmd.db = 0; if( cmd.bDryRun ){ - oputf("-- open database '%s'%s\n", cmd.zFile, - eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : ""); + utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile, + eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : ""); } rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0); if( rc!=SQLITE_OK ){ - eputf("cannot open file: %s (%s)\n", cmd.zFile, sqlite3_errmsg(cmd.db)); + utf8_printf(stderr, "cannot open file: %s (%s)\n", + cmd.zFile, sqlite3_errmsg(cmd.db) + ); goto end_ar_command; } sqlite3_fileio_init(cmd.db, 0, 0); sqlite3_sqlar_init(cmd.db, 0, 0); sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p, @@ -7516,11 +7647,11 @@ } if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){ if( cmd.eCmd!=AR_CMD_CREATE && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) ){ - eputz("database does not contain an 'sqlar' table\n"); + utf8_printf(stderr, "database does not contain an 'sqlar' table\n"); rc = SQLITE_ERROR; goto end_ar_command; } cmd.zSrcTable = sqlite3_mprintf("sqlar"); } @@ -7574,11 +7705,11 @@ ** This function is used as a callback by the recover extension. Simply ** print the supplied SQL statement to stdout. */ static int recoverSqlCb(void *pCtx, const char *zSql){ ShellState *pState = (ShellState*)pCtx; - sputf(pState->out, "%s;\n", zSql); + utf8_printf(pState->out, "%s;\n", zSql); return SQLITE_OK; } /* ** This function is called to recover data from the database. A script @@ -7617,11 +7748,11 @@ }else if( n<=10 && memcmp("-no-rowids", z, n)==0 ){ bRowids = 0; } else{ - eputf("unexpected option: %s\n", azArg[i]); + utf8_printf(stderr, "unexpected option: %s\n", azArg[i]); showHelp(pState->out, azArg[0]); return 1; } } @@ -7636,11 +7767,11 @@ sqlite3_recover_run(p); if( sqlite3_recover_errcode(p)!=SQLITE_OK ){ const char *zErr = sqlite3_recover_errmsg(p); int errCode = sqlite3_recover_errcode(p); - eputf("sql error: %s (%d)\n", zErr, errCode); + raw_printf(stderr, "sql error: %s (%d)\n", zErr, errCode); } rc = sqlite3_recover_finish(p); return rc; } #endif /* SQLITE_SHELL_HAVE_RECOVER */ @@ -7661,11 +7792,11 @@ */ #ifdef SHELL_DEBUG #define rc_err_oom_die(rc) \ if( rc==SQLITE_NOMEM ) shell_check_oom(0); \ else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \ - eputf("E:%d\n",rc), assert(0) + fprintf(stderr,"E:%d\n",rc), assert(0) #else static void rc_err_oom_die(int rc){ if( rc==SQLITE_NOMEM ) shell_check_oom(0); assert(rc==SQLITE_OK||rc==SQLITE_DONE); } @@ -7801,11 +7932,10 @@ #ifdef SHELL_COLFIX_DB if(*zCOL_DB!=':') sqlite3_exec(*pDb,"drop table if exists ColNames;" "drop view if exists RepeatedNames;",0,0,0); #endif -#undef SHELL_COLFIX_DB rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0); rc_err_oom_die(rc); } assert(*pDb!=0); rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0); @@ -7915,11 +8045,11 @@ clearTempFile(p); #ifndef SQLITE_OMIT_AUTHORIZATION if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){ if( nArg!=2 ){ - eputz("Usage: .auth ON|OFF\n"); + raw_printf(stderr, "Usage: .auth ON|OFF\n"); rc = 1; goto meta_command_exit; } open_db(p, 0); if( booleanValue(azArg[1]) ){ @@ -7962,32 +8092,32 @@ }else if( cli_strcmp(z, "-async")==0 ){ bAsync = 1; }else { - eputf("unknown option: %s\n", azArg[j]); + utf8_printf(stderr, "unknown option: %s\n", azArg[j]); return 1; } }else if( zDestFile==0 ){ zDestFile = azArg[j]; }else if( zDb==0 ){ zDb = zDestFile; zDestFile = azArg[j]; }else{ - eputz("Usage: .backup ?DB? ?OPTIONS? FILENAME\n"); + raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n"); return 1; } } if( zDestFile==0 ){ - eputz("missing FILENAME argument on .backup\n"); + raw_printf(stderr, "missing FILENAME argument on .backup\n"); return 1; } if( zDb==0 ) zDb = "main"; rc = sqlite3_open_v2(zDestFile, &pDest, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs); if( rc!=SQLITE_OK ){ - eputf("Error: cannot open \"%s\"\n", zDestFile); + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile); close_db(pDest); return 1; } if( bAsync ){ sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;", @@ -7994,20 +8124,20 @@ 0, 0, 0); } open_db(p, 0); pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); if( pBackup==0 ){ - eputf("Error: %s\n", sqlite3_errmsg(pDest)); + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); close_db(pDest); return 1; } while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} sqlite3_backup_finish(pBackup); if( rc==SQLITE_DONE ){ rc = 0; }else{ - eputf("Error: %s\n", sqlite3_errmsg(pDest)); + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); rc = 1; } close_db(pDest); }else #endif /* !defined(SQLITE_SHELL_FIDDLE) */ @@ -8014,11 +8144,11 @@ if( c=='b' && n>=3 && cli_strncmp(azArg[0], "bail", n)==0 ){ if( nArg==2 ){ bail_on_error = booleanValue(azArg[1]); }else{ - eputz("Usage: .bail on|off\n"); + raw_printf(stderr, "Usage: .bail on|off\n"); rc = 1; } }else /* Undocumented. Legacy only. See "crnl" below */ @@ -8028,12 +8158,13 @@ setBinaryMode(p->out, 1); }else{ setTextMode(p->out, 1); } }else{ - eputz("The \".binary\" command is deprecated. Use \".crnl\" instead.\n" - "Usage: .binary on|off\n"); + raw_printf(stderr, "The \".binary\" command is deprecated." + " Use \".crnl\" instead.\n"); + raw_printf(stderr, "Usage: .binary on|off\n"); rc = 1; } }else /* The undocumented ".breakpoint" command causes a call to the no-op @@ -8053,25 +8184,25 @@ sqlite3_free(z); #else rc = chdir(azArg[1]); #endif if( rc ){ - eputf("Cannot change to directory \"%s\"\n", azArg[1]); + utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]); rc = 1; } }else{ - eputz("Usage: .cd DIRECTORY\n"); + raw_printf(stderr, "Usage: .cd DIRECTORY\n"); rc = 1; } }else #endif /* !defined(SQLITE_SHELL_FIDDLE) */ if( c=='c' && n>=3 && cli_strncmp(azArg[0], "changes", n)==0 ){ if( nArg==2 ){ setOrClearFlag(p, SHFLG_CountChanges, azArg[1]); }else{ - eputz("Usage: .changes on|off\n"); + raw_printf(stderr, "Usage: .changes on|off\n"); rc = 1; } }else #ifndef SQLITE_SHELL_FIDDLE @@ -8081,20 +8212,21 @@ */ if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){ char *zRes = 0; output_reset(p); if( nArg!=2 ){ - eputz("Usage: .check GLOB-PATTERN\n"); + raw_printf(stderr, "Usage: .check GLOB-PATTERN\n"); rc = 2; }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ rc = 2; }else if( testcase_glob(azArg[1],zRes)==0 ){ - eputf("testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", - p->zTestcase, azArg[1], zRes); + utf8_printf(stderr, + "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", + p->zTestcase, azArg[1], zRes); rc = 1; }else{ - oputf("testcase-%s ok\n", p->zTestcase); + utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase); p->nCheck++; } sqlite3_free(zRes); }else #endif /* !defined(SQLITE_SHELL_FIDDLE) */ @@ -8103,11 +8235,11 @@ if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){ failIfSafeMode(p, "cannot run .clone in safe mode"); if( nArg==2 ){ tryToClone(p, azArg[1]); }else{ - eputz("Usage: .clone FILENAME\n"); + raw_printf(stderr, "Usage: .clone FILENAME\n"); rc = 1; } }else #endif /* !defined(SQLITE_SHELL_FIDDLE) */ @@ -8123,13 +8255,13 @@ zFile = "(memory)"; }else if( zFile[0]==0 ){ zFile = "(temporary-file)"; } if( p->pAuxDb == &p->aAuxDb[i] ){ - sputf(stdout, "ACTIVE %d: %s\n", i, zFile); + utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile); }else if( p->aAuxDb[i].db!=0 ){ - sputf(stdout, " %d: %s\n", i, zFile); + utf8_printf(stdout, " %d: %s\n", i, zFile); } } }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){ int i = azArg[1][0] - '0'; if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && iaAuxDb) ){ @@ -8142,19 +8274,19 @@ && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){ int i = azArg[2][0] - '0'; if( i<0 || i>=ArraySize(p->aAuxDb) ){ /* No-op */ }else if( p->pAuxDb == &p->aAuxDb[i] ){ - eputz("cannot close the active database connection\n"); + raw_printf(stderr, "cannot close the active database connection\n"); rc = 1; }else if( p->aAuxDb[i].db ){ session_close_all(p, i); close_db(p->aAuxDb[i].db); p->aAuxDb[i].db = 0; } }else{ - eputz("Usage: .connection [close] [CONNECTION-NUMBER]\n"); + raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n"); rc = 1; } }else if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){ @@ -8164,13 +8296,13 @@ }else{ setBinaryMode(p->out, 1); } }else{ #if !defined(_WIN32) && !defined(WIN32) - eputz("The \".crnl\" is a no-op on non-Windows machines.\n"); + raw_printf(stderr, "The \".crnl\" is a no-op on non-Windows machines.\n"); #endif - eputz("Usage: .crnl on|off\n"); + raw_printf(stderr, "Usage: .crnl on|off\n"); rc = 1; } }else if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){ @@ -8179,11 +8311,11 @@ sqlite3_stmt *pStmt; int i; open_db(p, 0); rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); if( rc ){ - eputf("Error: %s\n", sqlite3_errmsg(p->db)); + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); rc = 1; }else{ while( sqlite3_step(pStmt)==SQLITE_ROW ){ const char *zSchema = (const char *)sqlite3_column_text(pStmt,1); const char *zFile = (const char*)sqlite3_column_text(pStmt,2); @@ -8198,13 +8330,15 @@ sqlite3_finalize(pStmt); for(i=0; idb, azName[i*2]); int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]); const char *z = azName[i*2+1]; - oputf("%s: %s %s%s\n", - azName[i*2], z && z[0] ? z : "\"\"", bRdonly ? "r/o" : "r/w", - eTxn==SQLITE_TXN_NONE ? "" : + utf8_printf(p->out, "%s: %s %s%s\n", + azName[i*2], + z && z[0] ? z : "\"\"", + bRdonly ? "r/o" : "r/w", + eTxn==SQLITE_TXN_NONE ? "" : eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn"); free(azName[i*2]); free(azName[i*2+1]); } sqlite3_free(azName); @@ -8240,16 +8374,16 @@ if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; if( nArg>=3 ){ sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); } sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); - oputf("%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); + utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); if( nArg>1 ) break; } if( nArg>1 && ii==ArraySize(aDbConfig) ){ - eputf("Error: unknown dbconfig \"%s\"\n", azArg[1]); - eputz("Enter \".dbconfig\" with no arguments for a list\n"); + utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); + utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); } }else #if SQLITE_SHELL_HAVE_RECOVER if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){ @@ -8275,12 +8409,12 @@ if( azArg[i][0]=='-' ){ const char *z = azArg[i]+1; if( z[0]=='-' ) z++; if( cli_strcmp(z,"preserve-rowids")==0 ){ #ifdef SQLITE_OMIT_VIRTUALTABLE - eputz("The --preserve-rowids option is not compatible" - " with SQLITE_OMIT_VIRTUALTABLE\n"); + raw_printf(stderr, "The --preserve-rowids option is not compatible" + " with SQLITE_OMIT_VIRTUALTABLE\n"); rc = 1; sqlite3_free(zLike); goto meta_command_exit; #else ShellSetFlag(p, SHFLG_PreserveRowid); @@ -8294,11 +8428,11 @@ }else if( cli_strcmp(z,"nosys")==0 ){ ShellSetFlag(p, SHFLG_DumpNoSys); }else { - eputf("Unknown option \"%s\" on \".dump\"\n", azArg[i]); + raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]); rc = 1; sqlite3_free(zLike); goto meta_command_exit; } }else{ @@ -8328,12 +8462,12 @@ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){ /* When playing back a "dump", the content might appear in an order ** which causes immediate foreign key constraints to be violated. ** So disable foreign-key constraint enforcement to prevent problems. */ - oputz("PRAGMA foreign_keys=OFF;\n"); - oputz("BEGIN TRANSACTION;\n"); + raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); + raw_printf(p->out, "BEGIN TRANSACTION;\n"); } p->writableSchema = 0; p->showHeader = 0; /* Set writable_schema=ON since doing so forces SQLite to initialize ** as much of the schema as it can even if the sqlite_schema table is @@ -8360,27 +8494,27 @@ run_table_dump_query(p, zSql); sqlite3_free(zSql); } sqlite3_free(zLike); if( p->writableSchema ){ - oputz("PRAGMA writable_schema=OFF;\n"); + raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); p->writableSchema = 0; } sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){ - oputz(p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n"); + raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n"); } p->showHeader = savedShowHeader; p->shellFlgs = savedShellFlags; }else if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){ if( nArg==2 ){ setOrClearFlag(p, SHFLG_Echo, azArg[1]); }else{ - eputz("Usage: .echo on|off\n"); + raw_printf(stderr, "Usage: .echo on|off\n"); rc = 1; } }else if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){ @@ -8407,11 +8541,11 @@ #endif }else{ p->autoEQP = (u8)booleanValue(azArg[1]); } }else{ - eputz("Usage: .eqp off|on|trace|trigger|full\n"); + raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n"); rc = 1; } }else #ifndef SQLITE_SHELL_FIDDLE @@ -8446,12 +8580,13 @@ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){ if( p->bSafeMode ){ - eputf("Cannot run experimental commands such as \"%s\" in safe mode\n", - azArg[0]); + raw_printf(stderr, + "Cannot run experimental commands such as \"%s\" in safe mode\n", + azArg[0]); rc = 1; }else{ open_db(p, 0); expertDotCommand(p, azArg, nArg); } @@ -8503,13 +8638,14 @@ if( zCmd[0]=='-' && zCmd[1] ) zCmd++; } /* --help lists all file-controls */ if( cli_strcmp(zCmd,"help")==0 ){ - oputz("Available file-controls:\n"); + utf8_printf(p->out, "Available file-controls:\n"); for(i=0; iout, " .filectrl %s %s\n", + aCtrl[i].zCtrlName, aCtrl[i].zUsage); } rc = 1; goto meta_command_exit; } @@ -8520,20 +8656,20 @@ if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){ if( filectrl<0 ){ filectrl = aCtrl[i].ctrlCode; iCtrl = i; }else{ - eputf("Error: ambiguous file-control: \"%s\"\n" - "Use \".filectrl --help\" for help\n", zCmd); + utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n" + "Use \".filectrl --help\" for help\n", zCmd); rc = 1; goto meta_command_exit; } } } if( filectrl<0 ){ - eputf("Error: unknown file-control: %s\n" - "Use \".filectrl --help\" for help\n", zCmd); + utf8_printf(stderr,"Error: unknown file-control: %s\n" + "Use \".filectrl --help\" for help\n", zCmd); }else{ switch(filectrl){ case SQLITE_FCNTL_SIZE_LIMIT: { if( nArg!=2 && nArg!=3 ) break; iRes = nArg==3 ? integerValue(azArg[2]) : -1; @@ -8572,11 +8708,11 @@ case SQLITE_FCNTL_TEMPFILENAME: { char *z = 0; if( nArg!=2 ) break; sqlite3_file_control(p->db, zSchema, filectrl, &z); if( z ){ - oputf("%s\n", z); + utf8_printf(p->out, "%s\n", z); sqlite3_free(z); } isOk = 2; break; } @@ -8586,23 +8722,23 @@ x = atoi(azArg[2]); sqlite3_file_control(p->db, zSchema, filectrl, &x); } x = -1; sqlite3_file_control(p->db, zSchema, filectrl, &x); - oputf("%d\n", x); + utf8_printf(p->out,"%d\n", x); isOk = 2; break; } } } if( isOk==0 && iCtrl>=0 ){ - oputf("Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); + utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); rc = 1; }else if( isOk==1 ){ char zBuf[100]; sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes); - oputf("%s\n", zBuf); + raw_printf(p->out, "%s\n", zBuf); } }else if( c=='f' && cli_strncmp(azArg[0], "fullschema", n)==0 ){ ShellState data; @@ -8613,11 +8749,11 @@ if( nArg==2 && optionMatch(azArg[1], "indent") ){ data.cMode = data.mode = MODE_Pretty; nArg = 1; } if( nArg!=1 ){ - eputz("Usage: .fullschema ?--indent?\n"); + raw_printf(stderr, "Usage: .fullschema ?--indent?\n"); rc = 1; goto meta_command_exit; } open_db(p, 0); rc = sqlite3_exec(p->db, @@ -8639,37 +8775,37 @@ doStats = sqlite3_step(pStmt)==SQLITE_ROW; sqlite3_finalize(pStmt); } } if( doStats==0 ){ - oputz("/* No STAT tables available */\n"); + raw_printf(p->out, "/* No STAT tables available */\n"); }else{ - oputz("ANALYZE sqlite_schema;\n"); + raw_printf(p->out, "ANALYZE sqlite_schema;\n"); data.cMode = data.mode = MODE_Insert; data.zDestTable = "sqlite_stat1"; shell_exec(&data, "SELECT * FROM sqlite_stat1", 0); data.zDestTable = "sqlite_stat4"; shell_exec(&data, "SELECT * FROM sqlite_stat4", 0); - oputz("ANALYZE sqlite_schema;\n"); + raw_printf(p->out, "ANALYZE sqlite_schema;\n"); } }else if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){ if( nArg==2 ){ p->showHeader = booleanValue(azArg[1]); p->shellFlgs |= SHFLG_HeaderSet; }else{ - eputz("Usage: .headers on|off\n"); + raw_printf(stderr, "Usage: .headers on|off\n"); rc = 1; } }else if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){ if( nArg>=2 ){ n = showHelp(p->out, azArg[1]); if( n==0 ){ - oputf("Nothing matches '%s'\n", azArg[1]); + utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); } }else{ showHelp(p->out, 0); } }else @@ -8709,11 +8845,11 @@ if( zFile==0 ){ zFile = z; }else if( zTable==0 ){ zTable = z; }else{ - oputf("ERROR: extra argument: \"%s\". Usage:\n", z); + utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z); showHelp(p->out, "import"); goto meta_command_exit; } }else if( cli_strcmp(z,"-v")==0 ){ eVerbose++; @@ -8730,18 +8866,18 @@ sCtx.cColSep = ','; sCtx.cRowSep = '\n'; xRead = csv_read_one_field; useOutputMode = 0; }else{ - oputf("ERROR: unknown option: \"%s\". Usage:\n", z); + utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z); showHelp(p->out, "import"); goto meta_command_exit; } } if( zTable==0 ){ - oputf("ERROR: missing %s argument. Usage:\n", - zFile==0 ? "FILE" : "TABLE"); + utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n", + zFile==0 ? "FILE" : "TABLE"); showHelp(p->out, "import"); goto meta_command_exit; } seenInterrupt = 0; open_db(p, 0); @@ -8748,21 +8884,24 @@ if( useOutputMode ){ /* If neither the --csv or --ascii options are specified, then set ** the column and row separator characters from the output mode. */ nSep = strlen30(p->colSeparator); if( nSep==0 ){ - eputz("Error: non-null column separator required for import\n"); + raw_printf(stderr, + "Error: non-null column separator required for import\n"); goto meta_command_exit; } if( nSep>1 ){ - eputz("Error: multi-character column separators not allowed" + raw_printf(stderr, + "Error: multi-character column separators not allowed" " for import\n"); goto meta_command_exit; } nSep = strlen30(p->rowSeparator); if( nSep==0 ){ - eputz("Error: non-null row separator required for import\n"); + raw_printf(stderr, + "Error: non-null row separator required for import\n"); goto meta_command_exit; } if( nSep==2 && p->mode==MODE_Csv && cli_strcmp(p->rowSeparator,SEP_CrLf)==0 ){ @@ -8772,22 +8911,22 @@ ** and output row separators. */ sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); nSep = strlen30(p->rowSeparator); } if( nSep>1 ){ - eputz("Error: multi-character row separators not allowed" - " for import\n"); + raw_printf(stderr, "Error: multi-character row separators not allowed" + " for import\n"); goto meta_command_exit; } sCtx.cColSep = (u8)p->colSeparator[0]; sCtx.cRowSep = (u8)p->rowSeparator[0]; } sCtx.zFile = zFile; sCtx.nLine = 1; if( sCtx.zFile[0]=='|' ){ #ifdef SQLITE_OMIT_POPEN - eputz("Error: pipes are not supported in this OS\n"); + raw_printf(stderr, "Error: pipes are not supported in this OS\n"); goto meta_command_exit; #else sCtx.in = popen(sCtx.zFile+1, "r"); sCtx.zFile = ""; sCtx.xCloser = pclose; @@ -8795,23 +8934,23 @@ }else{ sCtx.in = fopen(sCtx.zFile, "rb"); sCtx.xCloser = fclose; } if( sCtx.in==0 ){ - eputf("Error: cannot open \"%s\"\n", zFile); + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); goto meta_command_exit; } if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){ char zSep[2]; zSep[1] = 0; zSep[0] = sCtx.cColSep; - oputz("Column separator "); - output_c_string(zSep); - oputz(", row separator "); + utf8_printf(p->out, "Column separator "); + output_c_string(p->out, zSep); + utf8_printf(p->out, ", row separator "); zSep[0] = sCtx.cRowSep; - output_c_string(zSep); - oputz("\n"); + output_c_string(p->out, zSep); + utf8_printf(p->out, "\n"); } sCtx.z = sqlite3_malloc64(120); if( sCtx.z==0 ){ import_cleanup(&sCtx); shell_out_of_memory(); @@ -8842,18 +8981,18 @@ zAutoColumn(sCtx.z, &dbCols, 0); if( sCtx.cTerm!=sCtx.cColSep ) break; } zColDefs = zAutoColumn(0, &dbCols, &zRenames); if( zRenames!=0 ){ - sputf((stdin_is_interactive && p->in==stdin)? p->out : stderr, - "Columns renamed during .import %s due to duplicates:\n" - "%s\n", sCtx.zFile, zRenames); + utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr, + "Columns renamed during .import %s due to duplicates:\n" + "%s\n", sCtx.zFile, zRenames); sqlite3_free(zRenames); } assert(dbCols==0); if( zColDefs==0 ){ - eputf("%s: empty file\n", sCtx.zFile); + utf8_printf(stderr,"%s: empty file\n", sCtx.zFile); import_fail: sqlite3_free(zCreate); sqlite3_free(zSql); sqlite3_free(zFullTabName); import_cleanup(&sCtx); @@ -8860,24 +8999,24 @@ rc = 1; goto meta_command_exit; } zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs); if( eVerbose>=1 ){ - oputf("%s\n", zCreate); + utf8_printf(p->out, "%s\n", zCreate); } rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); if( rc ){ - eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db)); + utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db)); goto import_fail; } sqlite3_free(zCreate); zCreate = 0; rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); } if( rc ){ if (pStmt) sqlite3_finalize(pStmt); - eputf("Error: %s\n", sqlite3_errmsg(p->db)); + utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db)); goto import_fail; } sqlite3_free(zSql); nCol = sqlite3_column_count(pStmt); sqlite3_finalize(pStmt); @@ -8895,15 +9034,15 @@ zSql[j++] = '?'; } zSql[j++] = ')'; zSql[j] = 0; if( eVerbose>=2 ){ - oputf("Insert using: %s\n", zSql); + utf8_printf(p->out, "Insert using: %s\n", zSql); } rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); if( rc ){ - eputf("Error: %s\n", sqlite3_errmsg(p->db)); + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); if (pStmt) sqlite3_finalize(pStmt); goto import_fail; } sqlite3_free(zSql); sqlite3_free(zFullTabName); @@ -8932,31 +9071,32 @@ if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){ z = ""; } sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); if( i=nCol ){ sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); if( rc!=SQLITE_OK ){ - eputf("%s:%d: INSERT failed: %s\n", - sCtx.zFile, startLine, sqlite3_errmsg(p->db)); + utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, + startLine, sqlite3_errmsg(p->db)); sCtx.nErr++; }else{ sCtx.nRow++; } } @@ -8964,12 +9104,13 @@ import_cleanup(&sCtx); sqlite3_finalize(pStmt); if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); if( eVerbose>0 ){ - oputf("Added %d rows with %d errors using %d lines of input\n", - sCtx.nRow, sCtx.nErr, sCtx.nLine-1); + utf8_printf(p->out, + "Added %d rows with %d errors using %d lines of input\n", + sCtx.nRow, sCtx.nErr, sCtx.nLine-1); } }else #endif /* !defined(SQLITE_SHELL_FIDDLE) */ #ifndef SQLITE_UNTESTABLE @@ -8980,18 +9121,18 @@ int tnum = 0; int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ int i; if( !ShellHasFlag(p,SHFLG_TestingMode) ){ - eputf(".%s unavailable without --unsafe-testing\n", - "imposter"); + utf8_printf(stderr, ".%s unavailable without --unsafe-testing\n", + "imposter"); rc = 1; goto meta_command_exit; } if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ - eputz("Usage: .imposter INDEX IMPOSTER\n" - " .imposter off\n"); + utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" + " .imposter off\n"); /* Also allowed, but not documented: ** ** .imposter TABLE IMPOSTER ** ** where TABLE is a WITHOUT ROWID table. In that case, the @@ -9046,11 +9187,11 @@ zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol); } } sqlite3_finalize(pStmt); if( i==0 || tnum==0 ){ - eputf("no such index: \"%s\"\n", azArg[1]); + utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); rc = 1; sqlite3_free(zCollist); goto meta_command_exit; } if( lenPK==0 ) lenPK = 100000; @@ -9061,18 +9202,20 @@ rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); if( rc==SQLITE_OK ){ rc = sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); if( rc ){ - eputf("Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); + utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); }else{ - sputf(stdout, "%s;\n", zSql); - sputf(stdout, "WARNING: writing to an imposter table will corrupt" - " the \"%s\" %s!\n", azArg[1], isWO ? "table" : "index"); + utf8_printf(stdout, "%s;\n", zSql); + raw_printf(stdout, + "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n", + azArg[1], isWO ? "table" : "index" + ); } }else{ - eputf("SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); + raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); rc = 1; } sqlite3_free(zSql); }else #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */ @@ -9088,11 +9231,11 @@ sqlite3IoTrace = iotracePrintf; iotrace = stdout; }else{ iotrace = fopen(azArg[1], "w"); if( iotrace==0 ){ - eputf("Error: cannot open \"%s\"\n", azArg[1]); + utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); sqlite3IoTrace = 0; rc = 1; }else{ sqlite3IoTrace = iotracePrintf; } @@ -9120,15 +9263,15 @@ }; int i, n2; open_db(p, 0); if( nArg==1 ){ for(i=0; idb, aLimit[i].limitCode, -1)); + printf("%20s %d\n", aLimit[i].zLimitName, + sqlite3_limit(p->db, aLimit[i].limitCode, -1)); } }else if( nArg>3 ){ - eputz("Usage: .limit NAME ?NEW-VALUE?\n"); + raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n"); rc = 1; goto meta_command_exit; }else{ int iLimit = -1; n2 = strlen30(azArg[1]); @@ -9135,29 +9278,29 @@ for(i=0; idb, aLimit[iLimit].limitCode, (int)integerValue(azArg[2])); } - sputf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName, - sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); + printf("%20s %d\n", aLimit[iLimit].zLimitName, + sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); } }else if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){ open_db(p, 0); @@ -9169,38 +9312,38 @@ const char *zFile, *zProc; char *zErrMsg = 0; failIfSafeMode(p, "cannot run .load in safe mode"); if( nArg<2 || azArg[1][0]==0 ){ /* Must have a non-empty FILE. (Will not load self.) */ - eputz("Usage: .load FILE ?ENTRYPOINT?\n"); + raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); rc = 1; goto meta_command_exit; } zFile = azArg[1]; zProc = nArg>=3 ? azArg[2] : 0; open_db(p, 0); rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); if( rc!=SQLITE_OK ){ - eputf("Error: %s\n", zErrMsg); + utf8_printf(stderr, "Error: %s\n", zErrMsg); sqlite3_free(zErrMsg); rc = 1; } }else #endif if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){ if( nArg!=2 ){ - eputz("Usage: .log FILENAME\n"); + raw_printf(stderr, "Usage: .log FILENAME\n"); rc = 1; }else{ const char *zFile = azArg[1]; if( p->bSafeMode && cli_strcmp(zFile,"on")!=0 && cli_strcmp(zFile,"off")!=0 ){ - sputz(stdout, "cannot set .log to anything other" - " than \"on\" or \"off\"\n"); + raw_printf(stdout, "cannot set .log to anything other " + "than \"on\" or \"off\"\n"); zFile = "off"; } output_file_close(p->pLog); if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout"; p->pLog = output_file_open(zFile, 0); @@ -9235,35 +9378,37 @@ cmOpts = cmo; } }else if( zTabname==0 ){ zTabname = z; }else if( z[0]=='-' ){ - eputf("unknown option: %s\n", z); - eputz("options:\n" - " --noquote\n" - " --quote\n" - " --wordwrap on/off\n" - " --wrap N\n" - " --ww\n"); + utf8_printf(stderr, "unknown option: %s\n", z); + utf8_printf(stderr, "options:\n" + " --noquote\n" + " --quote\n" + " --wordwrap on/off\n" + " --wrap N\n" + " --ww\n"); rc = 1; goto meta_command_exit; }else{ - eputf("extra argument: \"%s\"\n", z); + utf8_printf(stderr, "extra argument: \"%s\"\n", z); rc = 1; goto meta_command_exit; } } if( zMode==0 ){ if( p->mode==MODE_Column || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) ){ - oputf("current output mode: %s --wrap %d --wordwrap %s --%squote\n", - modeDescr[p->mode], p->cmOpts.iWrap, - p->cmOpts.bWordWrap ? "on" : "off", - p->cmOpts.bQuote ? "" : "no"); + raw_printf + (p->out, + "current output mode: %s --wrap %d --wordwrap %s --%squote\n", + modeDescr[p->mode], p->cmOpts.iWrap, + p->cmOpts.bWordWrap ? "on" : "off", + p->cmOpts.bQuote ? "" : "no"); }else{ - oputf("current output mode: %s\n", modeDescr[p->mode]); + raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]); } zMode = modeDescr[p->mode]; } n2 = strlen30(zMode); if( cli_strncmp(zMode,"lines",n2)==0 ){ @@ -9318,26 +9463,26 @@ }else if( cli_strncmp(zMode,"off",n2)==0 ){ p->mode = MODE_Off; }else if( cli_strncmp(zMode,"json",n2)==0 ){ p->mode = MODE_Json; }else{ - eputz("Error: mode should be one of: " - "ascii box column csv html insert json line list markdown " - "qbox quote table tabs tcl\n"); + raw_printf(stderr, "Error: mode should be one of: " + "ascii box column csv html insert json line list markdown " + "qbox quote table tabs tcl\n"); rc = 1; } p->cMode = p->mode; }else #ifndef SQLITE_SHELL_FIDDLE if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){ if( nArg!=2 ){ - eputz("Usage: .nonce NONCE\n"); + raw_printf(stderr, "Usage: .nonce NONCE\n"); rc = 1; }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){ - eputf("line %d: incorrect nonce: \"%s\"\n", - p->lineno, azArg[1]); + raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n", + p->lineno, azArg[1]); exit(1); }else{ p->bSafeMode = 0; return 0; /* Return immediately to bypass the safe mode reset ** at the end of this procedure */ @@ -9348,11 +9493,11 @@ if( c=='n' && cli_strncmp(azArg[0], "nullvalue", n)==0 ){ if( nArg==2 ){ sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); }else{ - eputz("Usage: .nullvalue STRING\n"); + raw_printf(stderr, "Usage: .nullvalue STRING\n"); rc = 1; } }else if( c=='o' && cli_strncmp(azArg[0], "open", n)==0 && n>=2 ){ @@ -9387,15 +9532,15 @@ p->szMax = integerValue(azArg[++iName]); #endif /* SQLITE_OMIT_DESERIALIZE */ }else #endif /* !SQLITE_SHELL_FIDDLE */ if( z[0]=='-' ){ - eputf("unknown option: %s\n", z); + utf8_printf(stderr, "unknown option: %s\n", z); rc = 1; goto meta_command_exit; }else if( zFN ){ - eputf("extra argument: \"%s\"\n", z); + utf8_printf(stderr, "extra argument: \"%s\"\n", z); rc = 1; goto meta_command_exit; }else{ zFN = z; } @@ -9433,11 +9578,11 @@ zNewFilename = 0; } p->pAuxDb->zDbFilename = zNewFilename; open_db(p, OPEN_DB_KEEPALIVE); if( p->db==0 ){ - eputf("Error: cannot open '%s'\n", zNewFilename); + utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename); sqlite3_free(zNewFilename); }else{ p->pAuxDb->zFreeOnClose = zNewFilename; } } @@ -9457,13 +9602,13 @@ char *zFile = 0; int bTxtMode = 0; int i; int eMode = 0; int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */ - static const char *zBomUtf8 = "\xef\xbb\xbf"; - const char *zBom = 0; + unsigned char zBOM[4]; /* Byte-order mark to using if --bom is present */ + zBOM[0] = 0; failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]); if( c=='e' ){ eMode = 'x'; bOnce = 2; }else if( cli_strncmp(azArg[0],"once",n)==0 ){ @@ -9472,17 +9617,21 @@ for(i=1; iout, "ERROR: unknown option: \"%s\". Usage:\n", + azArg[i]); showHelp(p->out, azArg[0]); rc = 1; goto meta_command_exit; } }else if( zFile==0 && eMode!='e' && eMode!='x' ){ @@ -9490,11 +9639,12 @@ if( zFile && zFile[0]=='|' ){ while( i+1out,"ERROR: extra parameter: \"%s\". Usage:\n", + azArg[i]); showHelp(p->out, azArg[0]); rc = 1; sqlite3_free(zFile); goto meta_command_exit; } @@ -9529,34 +9679,34 @@ } #endif /* SQLITE_NOHAVE_SYSTEM */ shell_check_oom(zFile); if( zFile[0]=='|' ){ #ifdef SQLITE_OMIT_POPEN - eputz("Error: pipes are not supported in this OS\n"); + raw_printf(stderr, "Error: pipes are not supported in this OS\n"); rc = 1; - output_redir(p, stdout); + p->out = stdout; #else - FILE *pfPipe = popen(zFile + 1, "w"); - if( pfPipe==0 ){ - eputf("Error: cannot open pipe \"%s\"\n", zFile + 1); + p->out = popen(zFile + 1, "w"); + if( p->out==0 ){ + utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); + p->out = stdout; rc = 1; }else{ - output_redir(p, pfPipe); - if( zBom ) oputz(zBom); + if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out); sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); } #endif }else{ - FILE *pfFile = output_file_open(zFile, bTxtMode); - if( pfFile==0 ){ + p->out = output_file_open(zFile, bTxtMode); + if( p->out==0 ){ if( cli_strcmp(zFile,"off")!=0 ){ - eputf("Error: cannot write to \"%s\"\n", zFile); + utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile); } + p->out = stdout; rc = 1; } else { - output_redir(p, pfFile); - if( zBom ) oputz(zBom); + if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out); sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); } } sqlite3_free(zFile); }else @@ -9593,12 +9743,12 @@ if( len ){ rx = sqlite3_prepare_v2(p->db, "SELECT key, quote(value) " "FROM temp.sqlite_parameters;", -1, &pStmt, 0); while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - oputf("%-*s %s\n", len, sqlite3_column_text(pStmt,0), - sqlite3_column_text(pStmt,1)); + utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0), + sqlite3_column_text(pStmt,1)); } sqlite3_finalize(pStmt); } }else @@ -9638,11 +9788,11 @@ "VALUES(%Q,%Q);", zKey, zValue); shell_check_oom(zSql); rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rx!=SQLITE_OK ){ - oputf("Error: %s\n", sqlite3_errmsg(p->db)); + utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db)); sqlite3_finalize(pStmt); pStmt = 0; rc = 1; } } @@ -9667,14 +9817,14 @@ }else if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){ int i; for(i=1; i1 ) oputz(" "); - oputz(azArg[i]); + if( i>1 ) raw_printf(p->out, " "); + utf8_printf(p->out, "%s", azArg[i]); } - oputz("\n"); + raw_printf(p->out, "\n"); }else #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( c=='p' && n>=3 && cli_strncmp(azArg[0], "progress", n)==0 ){ int i; @@ -9699,19 +9849,19 @@ p->flgProgress |= SHELL_PROGRESS_ONCE; continue; } if( cli_strcmp(z,"limit")==0 ){ if( i+1>=nArg ){ - eputz("Error: missing argument on --limit\n"); + utf8_printf(stderr, "Error: missing argument on --limit\n"); rc = 1; goto meta_command_exit; }else{ p->mxProgress = (int)integerValue(azArg[++i]); } continue; } - eputf("Error: unknown option: \"%s\"\n", azArg[i]); + utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]); rc = 1; goto meta_command_exit; }else{ nn = (int)integerValue(z); } @@ -9740,31 +9890,31 @@ if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){ FILE *inSaved = p->in; int savedLineno = p->lineno; failIfSafeMode(p, "cannot run .read in safe mode"); if( nArg!=2 ){ - eputz("Usage: .read FILE\n"); + raw_printf(stderr, "Usage: .read FILE\n"); rc = 1; goto meta_command_exit; } if( azArg[1][0]=='|' ){ #ifdef SQLITE_OMIT_POPEN - eputz("Error: pipes are not supported in this OS\n"); + raw_printf(stderr, "Error: pipes are not supported in this OS\n"); rc = 1; p->out = stdout; #else p->in = popen(azArg[1]+1, "r"); if( p->in==0 ){ - eputf("Error: cannot open \"%s\"\n", azArg[1]); + utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); rc = 1; }else{ rc = process_input(p); pclose(p->in); } #endif }else if( (p->in = openChrSource(azArg[1]))==0 ){ - eputf("Error: cannot open \"%s\"\n", azArg[1]); + utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); rc = 1; }else{ rc = process_input(p); fclose(p->in); } @@ -9787,24 +9937,24 @@ zDb = "main"; }else if( nArg==3 ){ zSrcFile = azArg[2]; zDb = azArg[1]; }else{ - eputz("Usage: .restore ?DB? FILE\n"); + raw_printf(stderr, "Usage: .restore ?DB? FILE\n"); rc = 1; goto meta_command_exit; } rc = sqlite3_open(zSrcFile, &pSrc); if( rc!=SQLITE_OK ){ - eputf("Error: cannot open \"%s\"\n", zSrcFile); + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); close_db(pSrc); return 1; } open_db(p, 0); pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); if( pBackup==0 ){ - eputf("Error: %s\n", sqlite3_errmsg(p->db)); + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); close_db(pSrc); return 1; } while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK || rc==SQLITE_BUSY ){ @@ -9815,14 +9965,14 @@ } sqlite3_backup_finish(pBackup); if( rc==SQLITE_DONE ){ rc = 0; }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ - eputz("Error: source database is busy\n"); + raw_printf(stderr, "Error: source database is busy\n"); rc = 1; }else{ - eputf("Error: %s\n", sqlite3_errmsg(p->db)); + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); rc = 1; } close_db(pSrc); }else #endif /* !defined(SQLITE_SHELL_FIDDLE) */ @@ -9839,19 +9989,15 @@ } open_db(p, 0); sqlite3_db_config( p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0 ); -#if !defined(SQLITE_ENABLE_STMT_SCANSTATUS) - eputz("Warning: .scanstats not available in this build.\n"); -#elif !defined(SQLITE_ENABLE_BYTECODE_VTAB) - if( p->scanstatsOn==3 ){ - eputz("Warning: \".scanstats vm\" not available in this build.\n"); - } +#ifndef SQLITE_ENABLE_STMT_SCANSTATUS + raw_printf(stderr, "Warning: .scanstats not available in this build.\n"); #endif }else{ - eputz("Usage: .scanstats on|off|est\n"); + raw_printf(stderr, "Usage: .scanstats on|off|est\n"); rc = 1; } }else if( c=='s' && cli_strncmp(azArg[0], "schema", n)==0 ){ @@ -9876,17 +10022,18 @@ }else if( optionMatch(azArg[ii],"debug") ){ bDebug = 1; }else if( optionMatch(azArg[ii],"nosys") ){ bNoSystemTabs = 1; }else if( azArg[ii][0]=='-' ){ - eputf("Unknown option: \"%s\"\n", azArg[ii]); + utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]); rc = 1; goto meta_command_exit; }else if( zName==0 ){ zName = azArg[ii]; }else{ - eputz("Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n"); + raw_printf(stderr, + "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; } } if( zName!=0 ){ @@ -9915,11 +10062,11 @@ if( zDiv ){ sqlite3_stmt *pStmt = 0; rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", -1, &pStmt, 0); if( rc ){ - eputf("Error: %s\n", sqlite3_errmsg(p->db)); + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); sqlite3_finalize(pStmt); rc = 1; goto meta_command_exit; } appendText(&sSelect, "SELECT sql FROM", 0); @@ -9977,22 +10124,22 @@ appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0); } appendText(&sSelect, "sql IS NOT NULL" " ORDER BY snum, rowid", 0); if( bDebug ){ - oputf("SQL: %s;\n", sSelect.z); + utf8_printf(p->out, "SQL: %s;\n", sSelect.z); }else{ rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); } freeText(&sSelect); } if( zErrMsg ){ - eputf("Error: %s\n", zErrMsg); + utf8_printf(stderr,"Error: %s\n", zErrMsg); sqlite3_free(zErrMsg); rc = 1; }else if( rc != SQLITE_OK ){ - eputz("Error: querying schema information\n"); + raw_printf(stderr,"Error: querying schema information\n"); rc = 1; }else{ rc = 0; } }else @@ -10034,15 +10181,15 @@ */ if( cli_strcmp(azCmd[0],"attach")==0 ){ if( nCmd!=2 ) goto session_syntax_error; if( pSession->p==0 ){ session_not_open: - eputz("ERROR: No sessions are open\n"); + raw_printf(stderr, "ERROR: No sessions are open\n"); }else{ rc = sqlite3session_attach(pSession->p, azCmd[1]); if( rc ){ - eputf("ERROR: sqlite3session_attach() returns %d\n",rc); + raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc); rc = 0; } } }else @@ -10057,27 +10204,28 @@ failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]); if( nCmd!=2 ) goto session_syntax_error; if( pSession->p==0 ) goto session_not_open; out = fopen(azCmd[1], "wb"); if( out==0 ){ - eputf("ERROR: cannot open \"%s\" for writing\n", - azCmd[1]); + utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", + azCmd[1]); }else{ int szChng; void *pChng; if( azCmd[0][0]=='c' ){ rc = sqlite3session_changeset(pSession->p, &szChng, &pChng); }else{ rc = sqlite3session_patchset(pSession->p, &szChng, &pChng); } if( rc ){ - sputf(stdout, "Error: error code %d\n", rc); + printf("Error: error code %d\n", rc); rc = 0; } if( pChng && fwrite(pChng, szChng, 1, out)!=1 ){ - eputf("ERROR: Failed to write entire %d-byte output\n", szChng); + raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n", + szChng); } sqlite3_free(pChng); fclose(out); } }else @@ -10100,11 +10248,12 @@ int ii; if( nCmd>2 ) goto session_syntax_error; ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); if( pAuxDb->nSession ){ ii = sqlite3session_enable(pSession->p, ii); - oputf("session %s enable flag = %d\n", pSession->zName, ii); + utf8_printf(p->out, "session %s enable flag = %d\n", + pSession->zName, ii); } }else /* .session filter GLOB .... ** Set a list of GLOB patterns of table names to be excluded. @@ -10117,11 +10266,14 @@ sqlite3_free(pSession->azFilter[ii]); } sqlite3_free(pSession->azFilter); nByte = sizeof(pSession->azFilter[0])*(nCmd-1); pSession->azFilter = sqlite3_malloc( nByte ); - shell_check_oom( pSession->azFilter ); + if( pSession->azFilter==0 ){ + raw_printf(stderr, "Error: out or memory\n"); + exit(1); + } for(ii=1; iiazFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); shell_check_oom(x); } pSession->nFilter = ii-1; @@ -10135,11 +10287,12 @@ int ii; if( nCmd>2 ) goto session_syntax_error; ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); if( pAuxDb->nSession ){ ii = sqlite3session_indirect(pSession->p, ii); - oputf("session %s indirect flag = %d\n", pSession->zName, ii); + utf8_printf(p->out, "session %s indirect flag = %d\n", + pSession->zName, ii); } }else /* .session isempty ** Determine if the session is empty @@ -10147,20 +10300,21 @@ if( cli_strcmp(azCmd[0], "isempty")==0 ){ int ii; if( nCmd!=1 ) goto session_syntax_error; if( pAuxDb->nSession ){ ii = sqlite3session_isempty(pSession->p); - oputf("session %s isempty flag = %d\n", pSession->zName, ii); + utf8_printf(p->out, "session %s isempty flag = %d\n", + pSession->zName, ii); } }else /* .session list ** List all currently open sessions */ if( cli_strcmp(azCmd[0],"list")==0 ){ for(i=0; inSession; i++){ - oputf("%d %s\n", i, pAuxDb->aSession[i].zName); + utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName); } }else /* .session open DB NAME ** Open a new session called NAME on the attached database DB. @@ -10171,22 +10325,23 @@ if( nCmd!=3 ) goto session_syntax_error; zName = azCmd[2]; if( zName[0]==0 ) goto session_syntax_error; for(i=0; inSession; i++){ if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){ - eputf("Session \"%s\" already exists\n", zName); + utf8_printf(stderr, "Session \"%s\" already exists\n", zName); goto meta_command_exit; } } if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){ - eputf("Maximum of %d sessions\n", ArraySize(pAuxDb->aSession)); + raw_printf(stderr, + "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession)); goto meta_command_exit; } pSession = &pAuxDb->aSession[pAuxDb->nSession]; rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); if( rc ){ - eputf("Cannot open session: error code=%d\n", rc); + raw_printf(stderr, "Cannot open session: error code=%d\n", rc); rc = 0; goto meta_command_exit; } pSession->nFilter = 0; sqlite3session_table_filter(pSession->p, session_filter, pSession); @@ -10206,20 +10361,20 @@ if( c=='s' && n>=10 && cli_strncmp(azArg[0], "selftest-", 9)==0 ){ if( cli_strncmp(azArg[0]+9, "boolean", n-9)==0 ){ int i, v; for(i=1; iout, "%s: %d 0x%x\n", azArg[i], v, v); } } if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){ int i; sqlite3_int64 v; for(i=1; iout, "%s", zBuf); } } }else #endif @@ -10242,12 +10397,13 @@ }else if( cli_strcmp(z,"-v")==0 ){ bVerbose++; }else { - eputf("Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]); - eputz("Should be one of: --init -v\n"); + utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", + azArg[i], azArg[0]); + raw_printf(stderr, "Should be one of: --init -v\n"); rc = 1; goto meta_command_exit; } } if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0) @@ -10272,11 +10428,11 @@ "VALUES(0,'memo','Missing SELFTEST table - default checks only','')," " (1,'run','PRAGMA integrity_check','ok')", -1, &pStmt, 0); } if( rc ){ - eputz("Error querying the selftest table\n"); + raw_printf(stderr, "Error querying the selftest table\n"); rc = 1; sqlite3_finalize(pStmt); goto meta_command_exit; } for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){ @@ -10288,51 +10444,52 @@ if( zOp==0 ) continue; if( zSql==0 ) continue; if( zAns==0 ) continue; k = 0; if( bVerbose>0 ){ - sputf(stdout, "%d: %s %s\n", tno, zOp, zSql); + printf("%d: %s %s\n", tno, zOp, zSql); } if( cli_strcmp(zOp,"memo")==0 ){ - oputf("%s\n", zSql); + utf8_printf(p->out, "%s\n", zSql); }else if( cli_strcmp(zOp,"run")==0 ){ char *zErrMsg = 0; str.n = 0; str.z[0] = 0; rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); nTest++; if( bVerbose ){ - oputf("Result: %s\n", str.z); + utf8_printf(p->out, "Result: %s\n", str.z); } if( rc || zErrMsg ){ nErr++; rc = 1; - oputf("%d: error-code-%d: %s\n", tno, rc, zErrMsg); + utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); sqlite3_free(zErrMsg); }else if( cli_strcmp(zAns,str.z)!=0 ){ nErr++; rc = 1; - oputf("%d: Expected: [%s]\n", tno, zAns); - oputf("%d: Got: [%s]\n", tno, str.z); + utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); + utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); } - } - else{ - eputf("Unknown operation \"%s\" on selftest line %d\n", zOp, tno); + }else + { + utf8_printf(stderr, + "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); rc = 1; break; } } /* End loop over rows of content from SELFTEST */ sqlite3_finalize(pStmt); } /* End loop over k */ freeText(&str); - oputf("%d errors out of %d tests\n", nErr, nTest); + utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); }else if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){ if( nArg<2 || nArg>3 ){ - eputz("Usage: .separator COL ?ROW?\n"); + raw_printf(stderr, "Usage: .separator COL ?ROW?\n"); rc = 1; } if( nArg>=2 ){ sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); @@ -10371,17 +10528,18 @@ }else if( cli_strcmp(z,"debug")==0 ){ bDebug = 1; }else { - eputf("Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]); + utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", + azArg[i], azArg[0]); showHelp(p->out, azArg[0]); rc = 1; goto meta_command_exit; } }else if( zLike ){ - eputz("Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); + raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; }else{ zLike = z; bSeparate = 1; @@ -10449,11 +10607,11 @@ } shell_check_oom(zSql); freeText(&sQuery); freeText(&sSql); if( bDebug ){ - oputf("%s\n", zSql); + utf8_printf(p->out, "%s\n", zSql); }else{ shell_exec(p, zSql, 0); } #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE) { @@ -10479,11 +10637,11 @@ "||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n" "|| ' AND typeof('||cname||')=''text'' ',\n" "' OR ') as query, tname from tabcols group by tname)" , zRevText); shell_check_oom(zRevText); - if( bDebug ) oputf("%s\n", zRevText); + if( bDebug ) utf8_printf(p->out, "%s\n", zRevText); lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0); if( lrc!=SQLITE_OK ){ /* assert(lrc==SQLITE_NOMEM); // might also be SQLITE_ERROR if the ** user does cruel and unnatural things like ".limit expr_depth 0". */ rc = 1; @@ -10492,28 +10650,29 @@ lrc = SQLITE_ROW==sqlite3_step(pStmt); if( lrc ){ const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0); sqlite3_stmt *pCheckStmt; lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0); - if( bDebug ) oputf("%s\n", zGenQuery); + if( bDebug ) utf8_printf(p->out, "%s\n", zGenQuery); if( lrc!=SQLITE_OK ){ rc = 1; }else{ if( SQLITE_ROW==sqlite3_step(pCheckStmt) ){ double countIrreversible = sqlite3_column_double(pCheckStmt, 0); if( countIrreversible>0 ){ int sz = (int)(countIrreversible + 0.5); - eputf("Digest includes %d invalidly encoded text field%s.\n", - sz, (sz>1)? "s": ""); + utf8_printf(stderr, + "Digest includes %d invalidly encoded text field%s.\n", + sz, (sz>1)? "s": ""); } } sqlite3_finalize(pCheckStmt); } sqlite3_finalize(pStmt); } } - if( rc ) eputz(".sha3sum failed.\n"); + if( rc ) utf8_printf(stderr, ".sha3sum failed.\n"); sqlite3_free(zRevText); } #endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */ sqlite3_free(zSql); }else @@ -10525,77 +10684,76 @@ ){ char *zCmd; int i, x; failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]); if( nArg<2 ){ - eputz("Usage: .system COMMAND\n"); + raw_printf(stderr, "Usage: .system COMMAND\n"); rc = 1; goto meta_command_exit; } zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]); for(i=2; iautoEQP&3]); - oputf("%12.12s: %s\n","explain", - p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); - oputf("%12.12s: %s\n","headers", azBool[p->showHeader!=0]); + utf8_printf(p->out, "%12.12s: %s\n","echo", + azBool[ShellHasFlag(p, SHFLG_Echo)]); + utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); + utf8_printf(p->out, "%12.12s: %s\n","explain", + p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); + utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); if( p->mode==MODE_Column || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) ){ - oputf("%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode", - modeDescr[p->mode], p->cmOpts.iWrap, - p->cmOpts.bWordWrap ? "on" : "off", - p->cmOpts.bQuote ? "" : "no"); + utf8_printf + (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode", + modeDescr[p->mode], p->cmOpts.iWrap, + p->cmOpts.bWordWrap ? "on" : "off", + p->cmOpts.bQuote ? "" : "no"); }else{ - oputf("%12.12s: %s\n","mode", modeDescr[p->mode]); - } - oputf("%12.12s: ", "nullvalue"); - output_c_string(p->nullValue); - oputz("\n"); - oputf("%12.12s: %s\n","output", - strlen30(p->outfile) ? p->outfile : "stdout"); - oputf("%12.12s: ", "colseparator"); - output_c_string(p->colSeparator); - oputz("\n"); - oputf("%12.12s: ", "rowseparator"); - output_c_string(p->rowSeparator); - oputz("\n"); + utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); + } + utf8_printf(p->out, "%12.12s: ", "nullvalue"); + output_c_string(p->out, p->nullValue); + raw_printf(p->out, "\n"); + utf8_printf(p->out,"%12.12s: %s\n","output", + strlen30(p->outfile) ? p->outfile : "stdout"); + utf8_printf(p->out,"%12.12s: ", "colseparator"); + output_c_string(p->out, p->colSeparator); + raw_printf(p->out, "\n"); + utf8_printf(p->out,"%12.12s: ", "rowseparator"); + output_c_string(p->out, p->rowSeparator); + raw_printf(p->out, "\n"); switch( p->statsOn ){ case 0: zOut = "off"; break; default: zOut = "on"; break; case 2: zOut = "stmt"; break; case 3: zOut = "vmstep"; break; } - oputf("%12.12s: %s\n","stats", zOut); - oputf("%12.12s: ", "width"); + utf8_printf(p->out, "%12.12s: %s\n","stats", zOut); + utf8_printf(p->out, "%12.12s: ", "width"); for (i=0;inWidth;i++) { - oputf("%d ", p->colWidth[i]); + raw_printf(p->out, "%d ", p->colWidth[i]); } - oputz("\n"); - oputf("%12.12s: %s\n", "filename", - p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : ""); + raw_printf(p->out, "\n"); + utf8_printf(p->out, "%12.12s: %s\n", "filename", + p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : ""); }else if( c=='s' && cli_strncmp(azArg[0], "stats", n)==0 ){ if( nArg==2 ){ if( cli_strcmp(azArg[1],"stmt")==0 ){ @@ -10606,11 +10764,11 @@ p->statsOn = (u8)booleanValue(azArg[1]); } }else if( nArg==1 ){ display_stats(p->db, p, 0); }else{ - eputz("Usage: .stats ?on|off|stmt|vmstep?\n"); + raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n"); rc = 1; } }else if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0) @@ -10632,11 +10790,11 @@ if( nArg>2 && c=='i' ){ /* It is an historical accident that the .indexes command shows an error ** when called with the wrong number of arguments whereas the .tables ** command does not. */ - eputz("Usage: .indexes ?LIKE-PATTERN?\n"); + raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); rc = 1; sqlite3_finalize(pStmt); goto meta_command_exit; } for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ @@ -10708,13 +10866,14 @@ if( nPrintCol<1 ) nPrintCol = 1; nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; for(i=0; iout, "%s%-*s", zSp, maxlen, + azResult[j] ? azResult[j]:""); } - oputz("\n"); + raw_printf(p->out, "\n"); } } for(ii=0; iiout = output_file_open("testcase-out.txt", 0); if( p->out==0 ){ - eputz("Error: cannot open 'testcase-out.txt'\n"); + raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n"); } if( nArg>=2 ){ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); }else{ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); @@ -10765,11 +10924,11 @@ {"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" }, {"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" }, {"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" }, {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, {"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, - {"uselongdouble", SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"}, + {"uselongdouble", SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"}, }; int testctrl = -1; int iCtrl = -1; int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ int isOk = 0; @@ -10785,15 +10944,15 @@ if( zCmd[0]=='-' && zCmd[1] ) zCmd++; } /* --help lists all test-controls */ if( cli_strcmp(zCmd,"help")==0 ){ - oputz("Available test-controls:\n"); + utf8_printf(p->out, "Available test-controls:\n"); for(i=0; iout, " .testctrl %s %s\n", + aCtrl[i].zCtrlName, aCtrl[i].zUsage); } rc = 1; goto meta_command_exit; } @@ -10805,20 +10964,20 @@ if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){ if( testctrl<0 ){ testctrl = aCtrl[i].ctrlCode; iCtrl = i; }else{ - eputf("Error: ambiguous test-control: \"%s\"\n" - "Use \".testctrl --help\" for help\n", zCmd); + utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n" + "Use \".testctrl --help\" for help\n", zCmd); rc = 1; goto meta_command_exit; } } } if( testctrl<0 ){ - eputf("Error: unknown test-control: %s\n" - "Use \".testctrl --help\" for help\n", zCmd); + utf8_printf(stderr,"Error: unknown test-control: %s\n" + "Use \".testctrl --help\" for help\n", zCmd); }else{ switch(testctrl){ /* sqlite3_test_control(int, db, int) */ case SQLITE_TESTCTRL_OPTIMIZATIONS: @@ -10854,11 +11013,11 @@ if( nArg==3 || nArg==4 ){ int ii = (int)integerValue(azArg[2]); sqlite3 *db; if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){ sqlite3_randomness(sizeof(ii),&ii); - sputf(stdout, "-- random seed: %d\n", ii); + printf("-- random seed: %d\n", ii); } if( nArg==3 ){ db = 0; }else{ db = p->db; @@ -10922,11 +11081,11 @@ break; case SQLITE_TESTCTRL_SEEK_COUNT: { u64 x = 0; rc2 = sqlite3_test_control(testctrl, p->db, &x); - oputf("%llu\n", x); + utf8_printf(p->out, "%llu\n", x); isOk = 3; break; } #ifdef YYCOVERAGE @@ -10953,15 +11112,15 @@ int id = 1; while(1){ int val = 0; rc2 = sqlite3_test_control(testctrl, -id, &val); if( rc2!=SQLITE_OK ) break; - if( id>1 ) oputz(" "); - oputf("%d: %d", id, val); + if( id>1 ) utf8_printf(p->out, " "); + utf8_printf(p->out, "%d: %d", id, val); id++; } - if( id>1 ) oputz("\n"); + if( id>1 ) utf8_printf(p->out, "\n"); isOk = 3; } break; } #endif @@ -10973,16 +11132,16 @@ } break; } } if( isOk==0 && iCtrl>=0 ){ - oputf("Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); + utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); rc = 1; }else if( isOk==1 ){ - oputf("%d\n", rc2); + raw_printf(p->out, "%d\n", rc2); }else if( isOk==2 ){ - oputf("0x%08x\n", rc2); + raw_printf(p->out, "0x%08x\n", rc2); } }else #endif /* !defined(SQLITE_UNTESTABLE) */ if( c=='t' && n>4 && cli_strncmp(azArg[0], "timeout", n)==0 ){ @@ -10992,15 +11151,15 @@ if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){ if( nArg==2 ){ enableTimer = booleanValue(azArg[1]); if( enableTimer && !HAS_TIMER ){ - eputz("Error: timer not available on this system.\n"); + raw_printf(stderr, "Error: timer not available on this system.\n"); enableTimer = 0; } }else{ - eputz("Usage: .timer on|off\n"); + raw_printf(stderr, "Usage: .timer on|off\n"); rc = 1; } }else #ifndef SQLITE_OMIT_TRACE @@ -11033,11 +11192,11 @@ } else if( optionMatch(z, "close") ){ mType |= SQLITE_TRACE_CLOSE; } else { - eputf("Unknown option \"%s\" on \".trace\"\n", z); + raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z); rc = 1; goto meta_command_exit; } }else{ output_file_close(p->traceOut); @@ -11057,11 +11216,11 @@ if( c=='u' && cli_strncmp(azArg[0], "unmodule", n)==0 ){ int ii; int lenOpt; char *zOpt; if( nArg<2 ){ - eputz("Usage: .unmodule [--allexcept] NAME ...\n"); + raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n"); rc = 1; goto meta_command_exit; } open_db(p, 0); zOpt = azArg[1]; @@ -11079,100 +11238,100 @@ #endif #if SQLITE_USER_AUTHENTICATION if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){ if( nArg<2 ){ - eputz("Usage: .user SUBCOMMAND ...\n"); + raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); rc = 1; goto meta_command_exit; } open_db(p, 0); if( cli_strcmp(azArg[1],"login")==0 ){ if( nArg!=4 ){ - eputz("Usage: .user login USER PASSWORD\n"); + raw_printf(stderr, "Usage: .user login USER PASSWORD\n"); rc = 1; goto meta_command_exit; } rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3])); if( rc ){ - eputf("Authentication failed for user %s\n", azArg[2]); + utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]); rc = 1; } }else if( cli_strcmp(azArg[1],"add")==0 ){ if( nArg!=5 ){ - eputz("Usage: .user add USER PASSWORD ISADMIN\n"); + raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n"); rc = 1; goto meta_command_exit; } rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]), booleanValue(azArg[4])); if( rc ){ - eputf("User-Add failed: %d\n", rc); + raw_printf(stderr, "User-Add failed: %d\n", rc); rc = 1; } }else if( cli_strcmp(azArg[1],"edit")==0 ){ if( nArg!=5 ){ - eputz("Usage: .user edit USER PASSWORD ISADMIN\n"); + raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n"); rc = 1; goto meta_command_exit; } rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]), booleanValue(azArg[4])); if( rc ){ - eputf("User-Edit failed: %d\n", rc); + raw_printf(stderr, "User-Edit failed: %d\n", rc); rc = 1; } }else if( cli_strcmp(azArg[1],"delete")==0 ){ if( nArg!=3 ){ - eputz("Usage: .user delete USER\n"); + raw_printf(stderr, "Usage: .user delete USER\n"); rc = 1; goto meta_command_exit; } rc = sqlite3_user_delete(p->db, azArg[2]); if( rc ){ - eputf("User-Delete failed: %d\n", rc); + raw_printf(stderr, "User-Delete failed: %d\n", rc); rc = 1; } }else{ - eputz("Usage: .user login|add|edit|delete ...\n"); + raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n"); rc = 1; goto meta_command_exit; } }else #endif /* SQLITE_USER_AUTHENTICATION */ if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){ char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit"; - oputf("SQLite %s %s\n" /*extra-version-info*/, - sqlite3_libversion(), sqlite3_sourceid()); + utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/, + sqlite3_libversion(), sqlite3_sourceid()); #if SQLITE_HAVE_ZLIB - oputf("zlib version %s\n", zlibVersion()); + utf8_printf(p->out, "zlib version %s\n", zlibVersion()); #endif #define CTIMEOPT_VAL_(opt) #opt #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) #if defined(__clang__) && defined(__clang_major__) - oputf("clang-" CTIMEOPT_VAL(__clang_major__) "." - CTIMEOPT_VAL(__clang_minor__) "." - CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz); + utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "." + CTIMEOPT_VAL(__clang_minor__) "." + CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz); #elif defined(_MSC_VER) - oputf("msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz); + utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz); #elif defined(__GNUC__) && defined(__VERSION__) - oputf("gcc-" __VERSION__ " (%s)\n", zPtrSz); + utf8_printf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz); #endif }else if( c=='v' && cli_strncmp(azArg[0], "vfsinfo", n)==0 ){ const char *zDbName = nArg==2 ? azArg[1] : "main"; sqlite3_vfs *pVfs = 0; if( p->db ){ sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs); if( pVfs ){ - oputf("vfs.zName = \"%s\"\n", pVfs->zName); - oputf("vfs.iVersion = %d\n", pVfs->iVersion); - oputf("vfs.szOsFile = %d\n", pVfs->szOsFile); - oputf("vfs.mxPathname = %d\n", pVfs->mxPathname); + utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName); + raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); + raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); + raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); } } }else if( c=='v' && cli_strncmp(azArg[0], "vfslist", n)==0 ){ @@ -11180,17 +11339,17 @@ sqlite3_vfs *pCurrent = 0; if( p->db ){ sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent); } for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ - oputf("vfs.zName = \"%s\"%s\n", pVfs->zName, - pVfs==pCurrent ? " <--- CURRENT" : ""); - oputf("vfs.iVersion = %d\n", pVfs->iVersion); - oputf("vfs.szOsFile = %d\n", pVfs->szOsFile); - oputf("vfs.mxPathname = %d\n", pVfs->mxPathname); + utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName, + pVfs==pCurrent ? " <--- CURRENT" : ""); + raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); + raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); + raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); if( pVfs->pNext ){ - oputz("-----------------------------------\n"); + raw_printf(p->out, "-----------------------------------\n"); } } }else if( c=='v' && cli_strncmp(azArg[0], "vfsname", n)==0 ){ @@ -11197,11 +11356,11 @@ const char *zDbName = nArg==2 ? azArg[1] : "main"; char *zVfsName = 0; if( p->db ){ sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); if( zVfsName ){ - oputf("%s\n", zVfsName); + utf8_printf(p->out, "%s\n", zVfsName); sqlite3_free(zVfsName); } } }else @@ -11221,12 +11380,12 @@ p->colWidth[j-1] = (int)integerValue(azArg[j]); } }else { - eputf("Error: unknown command or invalid arguments: " - " \"%s\". Enter \".help\" for help\n", azArg[0]); + utf8_printf(stderr, "Error: unknown command or invalid arguments: " + " \"%s\". Enter \".help\" for help\n", azArg[0]); rc = 1; } meta_command_exit: if( p->outCount ){ @@ -11412,26 +11571,26 @@ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s near line %d:", zErrorType, startline); }else{ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType); } - eputf("%s %s\n", zPrefix, zErrorTail); + utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail); sqlite3_free(zErrMsg); zErrMsg = 0; return 1; }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ char zLineBuf[2000]; sqlite3_snprintf(sizeof(zLineBuf), zLineBuf, "changes: %lld total_changes: %lld", sqlite3_changes64(p->db), sqlite3_total_changes64(p->db)); - oputf("%s\n", zLineBuf); + raw_printf(p->out, "%s\n", zLineBuf); } return 0; } static void echo_group_input(ShellState *p, const char *zDo){ - if( ShellHasFlag(p, SHFLG_Echo) ) oputf("%s\n", zDo); + if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo); } #ifdef SQLITE_SHELL_FIDDLE /* ** Alternate one_input_line() impl for wasm mode. This is not in the primary @@ -11485,12 +11644,12 @@ i64 startline = 0; /* Line number for start of current input */ QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ if( p->inputNesting==MAX_INPUT_NESTING ){ /* This will be more informative in a later version. */ - eputf("Input nesting limit (%d) reached at line %d." - " Check recursion.\n", MAX_INPUT_NESTING, p->lineno); + utf8_printf(stderr,"Input nesting limit (%d) reached at line %d." + " Check recursion.\n", MAX_INPUT_NESTING, p->lineno); return 1; } ++p->inputNesting; p->lineno = 0; CONTINUE_PROMPT_RESET; @@ -11497,11 +11656,11 @@ while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ fflush(p->out); zLine = one_input_line(p->in, zLine, nSql>0); if( zLine==0 ){ /* End of input */ - if( p->in==0 && stdin_is_interactive ) oputz("\n"); + if( p->in==0 && stdin_is_interactive ) printf("\n"); break; } if( seenInterrupt ){ if( p->in!=0 ) break; seenInterrupt = 0; @@ -11707,27 +11866,27 @@ sqliterc = find_xdg_config(); } if( sqliterc == NULL ){ home_dir = find_home_dir(0); if( home_dir==0 ){ - eputz("-- warning: cannot find home directory;" - " cannot read ~/.sqliterc\n"); + raw_printf(stderr, "-- warning: cannot find home directory;" + " cannot read ~/.sqliterc\n"); return; } zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); shell_check_oom(zBuf); sqliterc = zBuf; } p->in = fopen(sqliterc,"rb"); if( p->in ){ if( stdin_is_interactive ){ - eputf("-- Loading resources from %s\n", sqliterc); + utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc); } if( process_input(p) && bail_on_error ) exit(1); fclose(p->in); }else if( sqliterc_override!=0 ){ - eputf("cannot open: \"%s\"\n", sqliterc); + utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc); if( bail_on_error ) exit(1); } p->in = inSaved; p->lineno = savedLineno; sqlite3_free(zBuf); @@ -11773,13 +11932,15 @@ " -mmap N default mmap size set to N\n" #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif " -newline SEP set output row separator. Default: '\\n'\n" +#if SHELL_WIN_UTF8_OPT + " -no-utf8 do not try to set up UTF-8 output (for legacy)\n" +#endif " -nofollow refuse to open symbolic links to database files\n" " -nonce STRING set the safe-mode escape nonce\n" - " -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n" " -nullvalue TEXT set text string for NULL values. Default ''\n" " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" " -pcachetrace trace all page cache operations\n" " -quote set output mode to 'quote'\n" " -readonly open the database read-only\n" @@ -11790,10 +11951,13 @@ #endif " -stats print memory stats before each finalize\n" " -table set output mode to 'table'\n" " -tabs set output mode to 'tabs'\n" " -unsafe-testing allow unsafe commands and modes for testing\n" +#if SHELL_WIN_UTF8_OPT + " -utf8 setup interactive console code page for UTF-8\n" +#endif " -version show SQLite version\n" " -vfs NAME use NAME as the default VFS\n" #ifdef SQLITE_ENABLE_VFSTRACE " -vfstrace enable tracing of all VFS calls\n" #endif @@ -11800,17 +11964,18 @@ #ifdef SQLITE_HAVE_ZLIB " -zip open the file as a ZIP Archive\n" #endif ; static void usage(int showDetail){ - eputf("Usage: %s [OPTIONS] [FILENAME [SQL]]\n" - "FILENAME is the name of an SQLite database. A new database is created\n" - "if the file does not previously exist. Defaults to :memory:.\n", Argv0); + utf8_printf(stderr, + "Usage: %s [OPTIONS] [FILENAME [SQL]]\n" + "FILENAME is the name of an SQLite database. A new database is created\n" + "if the file does not previously exist. Defaults to :memory:.\n", Argv0); if( showDetail ){ - eputf("OPTIONS include:\n%s", zOptions); + utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); }else{ - eputz("Use the -help option for additional information\n"); + raw_printf(stderr, "Use the -help option for additional information\n"); } exit(1); } /* @@ -11817,12 +11982,12 @@ ** Internal check: Verify that the SQLite is uninitialized. Print a ** error message if it is initialized. */ static void verify_uninitialized(void){ if( sqlite3_config(-1)==SQLITE_MISUSE ){ - sputz(stdout, "WARNING: attempt to configure SQLite after" - " initialization.\n"); + utf8_printf(stdout, "WARNING: attempt to configure SQLite after" + " initialization.\n"); } } /* ** Initialize the state information in data @@ -11847,45 +12012,46 @@ } /* ** Output text to the console in a font that attracts extra attention. */ -#if defined(_WIN32) || defined(WIN32) +#ifdef _WIN32 static void printBold(const char *zText){ #if !SQLITE_OS_WINRT HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo; GetConsoleScreenBufferInfo(out, &defaultScreenInfo); SetConsoleTextAttribute(out, FOREGROUND_RED|FOREGROUND_INTENSITY ); #endif - oputz(zText); + printf("%s", zText); #if !SQLITE_OS_WINRT SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes); #endif } #else static void printBold(const char *zText){ - oputf("\033[1m%s\033[0m", zText); + printf("\033[1m%s\033[0m", zText); } #endif /* ** Get the argument to an --option. Throw an error and die if no argument ** is available. */ static char *cmdline_option_value(int argc, char **argv, int i){ if( i==argc ){ - eputf("%s: Error: missing argument to %s\n", argv[0], argv[argc-1]); + utf8_printf(stderr, "%s: Error: missing argument to %s\n", + argv[0], argv[argc-1]); exit(1); } return argv[i]; } static void sayAbnormalExit(void){ - if( seenInterrupt ) eputz("Program interrupted.\n"); + if( seenInterrupt ) fprintf(stderr, "Program interrupted.\n"); } #ifndef SQLITE_SHELL_IS_UTF8 # if (defined(_WIN32) || defined(WIN32)) \ && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__))) @@ -11911,11 +12077,10 @@ char *zErrMsg = 0; #ifdef SQLITE_SHELL_FIDDLE # define data shellState #else ShellState data; - StreamsAreConsole consStreams = SAC_NoConsole; #endif const char *zInitFile = 0; int i; int rc = 0; int warnInmemoryDb = 0; @@ -11933,24 +12098,26 @@ #ifdef SQLITE_SHELL_FIDDLE stdin_is_interactive = 0; stdout_is_console = 1; data.wasm.zDefaultDbName = "/fiddle.sqlite3"; #else - consStreams = consoleClassifySetup(stdin, stdout, stderr); - stdin_is_interactive = (consStreams & SAC_InConsole)!=0; - stdout_is_console = (consStreams & SAC_OutConsole)!=0; - atexit(consoleRestore); + stdin_is_interactive = isatty(0); + stdout_is_console = isatty(1); +#endif +#if SHELL_WIN_UTF8_OPT + atexit(console_restore); /* Needs revision for CLI as library call */ #endif atexit(sayAbnormalExit); #ifdef SQLITE_DEBUG mem_main_enter = sqlite3_memory_used(); #endif #if !defined(_WIN32_WCE) if( getenv("SQLITE_DEBUG_BREAK") ){ if( isatty(0) && isatty(2) ){ - eputf("attach debugger to process %d and press any key to continue.\n", - GETPID()); + fprintf(stderr, + "attach debugger to process %d and press any key to continue.\n", + GETPID()); fgetc(stdin); }else{ #if defined(_WIN32) || defined(WIN32) #if SQLITE_OS_WINRT __debugbreak(); @@ -11966,18 +12133,18 @@ /* Register a valid signal handler early, before much else is done. */ #ifdef SIGINT signal(SIGINT, interrupt_handler); #elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) if( !SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE) ){ - eputz("No ^C handler.\n"); + fprintf(stderr, "No ^C handler.\n"); } #endif #if USE_SYSTEM_SQLITE+0!=1 if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){ - eputf("SQLite header and source version mismatch\n%s\n%s\n", - sqlite3_sourceid(), SQLITE_SOURCE_ID); + utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", + sqlite3_sourceid(), SQLITE_SOURCE_ID); exit(1); } #endif main_init(&data); @@ -12022,12 +12189,12 @@ } #endif /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, - ** the size of the alternative malloc heap, options affecting commands - ** or SQL run from the command line, and the first command to execute. + ** the size of the alternative malloc heap, + ** and the first command to execute. */ #ifndef SQLITE_SHELL_FIDDLE verify_uninitialized(); #endif for(i=1; izDbFilename==0 ){ #ifndef SQLITE_OMIT_MEMORYDB data.pAuxDb->zDbFilename = ":memory:"; warnInmemoryDb = argc==1; #else - eputf("%s: Error: no database filename specified\n", Argv0); + utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0); return 1; #endif } data.out = stdout; #ifndef SQLITE_SHELL_FIDDLE @@ -12335,23 +12491,25 @@ */ ShellSetFlag(&data, SHFLG_Backslash); }else if( cli_strcmp(z,"-bail")==0 ){ /* No-op. The bail_on_error flag should already be set. */ }else if( cli_strcmp(z,"-version")==0 ){ - oputf("%s %s (%d-bit)\n", sqlite3_libversion(), sqlite3_sourceid(), - 8*(int)sizeof(char*)); + printf("%s %s (%d-bit)\n", sqlite3_libversion(), sqlite3_sourceid(), + 8*(int)sizeof(char*)); return 0; }else if( cli_strcmp(z,"-interactive")==0 ){ - /* already handled */ + stdin_is_interactive = 1; }else if( cli_strcmp(z,"-batch")==0 ){ - /* already handled */ + stdin_is_interactive = 0; }else if( cli_strcmp(z,"-utf8")==0 ){ - /* already handled */ +#if SHELL_WIN_UTF8_OPT + console_utf8 = 1; +#endif /* SHELL_WIN_UTF8_OPT */ }else if( cli_strcmp(z,"-no-utf8")==0 ){ - /* already handled */ - }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){ - /* already handled */ +#if SHELL_WIN_UTF8_OPT + console_utf8 = 0; +#endif /* SHELL_WIN_UTF8_OPT */ }else if( cli_strcmp(z,"-heap")==0 ){ i++; }else if( cli_strcmp(z,"-pagecache")==0 ){ i+=2; }else if( cli_strcmp(z,"-lookaside")==0 ){ @@ -12394,22 +12552,22 @@ if( rc && bail_on_error ) return rc==2 ? 0 : rc; }else{ open_db(&data, 0); rc = shell_exec(&data, z, &zErrMsg); if( zErrMsg!=0 ){ - eputf("Error: %s\n", zErrMsg); + utf8_printf(stderr,"Error: %s\n", zErrMsg); if( bail_on_error ) return rc!=0 ? rc : 1; }else if( rc!=0 ){ - eputf("Error: unable to process SQL \"%s\"\n", z); + utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z); if( bail_on_error ) return rc; } } #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) }else if( cli_strncmp(z, "-A", 2)==0 ){ if( nCmd>0 ){ - eputf("Error: cannot mix regular SQL or dot-commands" - " with \"%s\"\n", z); + utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands" + " with \"%s\"\n", z); return 1; } open_db(&data, OPEN_DB_ZIPFILE); if( z[2] ){ argv[i] = &z[2]; @@ -12423,16 +12581,24 @@ }else if( cli_strcmp(z,"-safe")==0 ){ data.bSafeMode = data.bSafeModePersist = 1; }else if( cli_strcmp(z,"-unsafe-testing")==0 ){ /* Acted upon in first pass. */ }else{ - eputf("%s: Error: unknown option: %s\n", Argv0, z); - eputz("Use -help for a list of options.\n"); + utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); + raw_printf(stderr,"Use -help for a list of options.\n"); return 1; } data.cMode = data.mode; } +#if SHELL_WIN_UTF8_OPT + if( console_utf8 && stdin_is_interactive ){ + console_prepare(); + }else{ + setBinaryMode(stdin, 0); + console_utf8 = 0; + } +#endif if( !readStdin ){ /* Run all arguments that do not begin with '-' as if they were separate ** command-line inputs, except for the argToSkip argument which contains ** the database filename. @@ -12448,13 +12614,13 @@ open_db(&data, 0); echo_group_input(&data, azCmd[i]); rc = shell_exec(&data, azCmd[i], &zErrMsg); if( zErrMsg || rc ){ if( zErrMsg!=0 ){ - eputf("Error: %s\n", zErrMsg); + utf8_printf(stderr,"Error: %s\n", zErrMsg); }else{ - eputf("Error: unable to process SQL: %s\n", azCmd[i]); + utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]); } sqlite3_free(zErrMsg); free(azCmd); return rc!=0 ? rc : 1; } @@ -12464,24 +12630,25 @@ /* Run commands received from standard input */ if( stdin_is_interactive ){ char *zHome; char *zHistory; + const char *zCharset = ""; int nHistory; -#if CIO_WIN_WC_XLATE -# define SHELL_CIO_CHAR_SET (stdout_is_console? " (UTF-16 console I/O)" : "") -#else -# define SHELL_CIO_CHAR_SET "" +#if SHELL_WIN_UTF8_OPT + if( console_utf8 ) zCharset = " (utf8)"; #endif - oputf("SQLite version %s %.19s%s\n" /*extra-version-info*/ - "Enter \".help\" for usage hints.\n", - sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET); + printf( + "SQLite version %s %.19s%s\n" /*extra-version-info*/ + "Enter \".help\" for usage hints.\n", + sqlite3_libversion(), sqlite3_sourceid(), zCharset + ); if( warnInmemoryDb ){ - oputz("Connected to a "); + printf("Connected to a "); printBold("transient in-memory database"); - oputz(".\nUse \".open FILENAME\" to reopen on a" - " persistent database.\n"); + printf(".\nUse \".open FILENAME\" to reopen on a " + "persistent database.\n"); } zHistory = getenv("SQLITE_HISTORY"); if( zHistory ){ zHistory = strdup(zHistory); }else if( (zHome = find_home_dir(0))!=0 ){ @@ -12537,12 +12704,12 @@ /* Clear the global data structure so that valgrind will detect memory ** leaks */ memset(&data, 0, sizeof(data)); #ifdef SQLITE_DEBUG if( sqlite3_memory_used()>mem_main_enter ){ - eputf("Memory leaked: %u bytes\n", - (unsigned int)(sqlite3_memory_used()-mem_main_enter)); + utf8_printf(stderr, "Memory leaked: %u bytes\n", + (unsigned int)(sqlite3_memory_used()-mem_main_enter)); } #endif #endif /* !SQLITE_SHELL_FIDDLE */ return rc; } Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -2125,11 +2125,11 @@ ** of a table column that its values are likely to be very large - larger ** than the configured sorter-reference size threshold - then a reference ** is stored in each sorted record and the required column values loaded ** from the database as records are returned in sorted order. The default ** value for this option is to never use this optimization. Specifying a -** negative value for this option restores the default behavior. +** negative value for this option restores the default behaviour. ** This option is only available if SQLite is compiled with the ** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. ** ** [[SQLITE_CONFIG_MEMDB_MAXSIZE]] **
SQLITE_CONFIG_MEMDB_MAXSIZE @@ -2139,26 +2139,10 @@ ** size can be adjusted up or down for individual databases using the ** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. -** -** [[SQLITE_CONFIG_ROWID_IN_VIEW]] -**
SQLITE_CONFIG_ROWID_IN_VIEW -**
The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability -** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is -** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability -** defaults to on. This configuration option queries the current setting or -** changes the setting to off or on. The argument is a pointer to an integer. -** If that integer initially holds a value of 1, then the ability for VIEWs to -** have ROWIDs is activated. If the integer initially holds zero, then the -** ability is deactivated. Any other initial value for the integer leaves the -** setting unchanged. After changes, if any, the integer is written with -** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite -** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and -** recommended case) then the integer is always filled with zero, regardless -** if its initial value. ** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ @@ -2186,11 +2170,10 @@ #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ #define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ -#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that @@ -2317,11 +2300,11 @@ **
SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
**
Usually, when a database in wal mode is closed or detached from a ** database handle, SQLite checks if this will mean that there are now no ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to -** override this behavior. The first parameter passed to this operation +** override this behaviour. The first parameter passed to this operation ** is an integer - positive to disable checkpoints-on-close, or zero (the ** default) to enable them, and negative to leave the setting unchanged. ** The second parameter is a pointer to an integer ** into which is written 0 or 1 to indicate whether checkpoints-on-close ** have been disabled - 0 if they are not disabled, 1 if they are. @@ -3970,11 +3953,10 @@ **
  • sqlite3_error_offset() ** ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively. -** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** @@ -5588,39 +5570,24 @@ ** function has been carefully audited and found to be free of potentially ** security-adverse side-effects and information-leaks. **
  • ** ** [[SQLITE_SUBTYPE]]
    SQLITE_SUBTYPE
    -** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call +** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** This flag instructs SQLite to omit some corner-case optimizations that -** might disrupt the operation of the [sqlite3_value_subtype()] function, -** causing it to return zero rather than the correct subtype(). -** SQL functions that invokes [sqlite3_value_subtype()] should have this -** property. If the SQLITE_SUBTYPE property is omitted, then the return -** value from [sqlite3_value_subtype()] might sometimes be zero even though -** a non-zero subtype was specified by the function argument expression. -** -** [[SQLITE_RESULT_SUBTYPE]]
    SQLITE_RESULT_SUBTYPE
    -** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call -** [sqlite3_result_subtype()] to cause a sub-type to be associated with its -** result. -** Every function that invokes [sqlite3_result_subtype()] should have this -** property. If it does not, then the call to [sqlite3_result_subtype()] -** might become a no-op if the function is used as term in an -** [expression index]. On the other hand, SQL functions that never invoke -** [sqlite3_result_subtype()] should avoid setting this property, as the -** purpose of this property is to disable certain optimizations that are -** incompatible with subtypes. +** Specifying this flag makes no difference for scalar or aggregate user +** functions. However, if it is not specified for a user-defined window +** function, then any sub-types belonging to arguments passed to the window +** function may be discarded before the window function is called (i.e. +** sqlite3_value_subtype() will always return 0). **
    ** */ #define SQLITE_DETERMINISTIC 0x000000800 #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000 -#define SQLITE_RESULT_SUBTYPE 0x001000000 /* ** CAPI3REF: Deprecated Functions ** DEPRECATED ** @@ -5813,16 +5780,10 @@ ** The sqlite3_value_subtype(V) function returns the subtype for ** an [application-defined SQL function] argument V. The subtype ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. -** -** Every [application-defined SQL function] that invoke this interface -** should include the [SQLITE_SUBTYPE] property in the text -** encoding argument when the function is [sqlite3_create_function|registered]. -** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() -** might return zero instead of the upstream subtype in some corner cases. */ unsigned int sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values @@ -5949,26 +5910,18 @@ **
  • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement)^, or **
  • ^(when sqlite3_set_auxdata() is invoked again on the same ** parameter)^, or **
  • ^(during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.)^ -**
  • ^(during the original sqlite3_set_auxdata() call if the function -** is evaluated during query planning instead of during query execution, -** as sometimes happens with [SQLITE_ENABLE_STAT4].)^ +** allocation error occurs.)^ ** -** Note the last two bullets in particular. The destructor X in +** Note the last bullet in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. Furthermore, a call to -** sqlite3_get_auxdata() that occurs immediately after a corresponding call -** to sqlite3_set_auxdata() might still return NULL if an out-of-memory -** condition occurred during the sqlite3_set_auxdata() call or if the -** function is being evaluated during query planning rather than during -** query execution. +** sqlite3_set_auxdata() has been called. ** ** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** @@ -6005,11 +5958,11 @@ **
  • A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made ** with the same D and N parameters. **
  • The database connection closes. SQLite does not make any guarantees ** about the order in which destructors are called, only that all ** destructors will be called exactly once at some point during the -** database connection closing process. +** database connection closingi process. ** ** ** SQLite does not do anything with client data other than invoke ** destructors on the client data at the appropriate time. The intended ** use for client data is to provide a mechanism for wrapper libraries @@ -6238,24 +6191,10 @@ ** [sqlite3_context] C to be the value T. Only the lower 8 bits ** of the subtype T are preserved in current versions of SQLite; ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. -** -** Every [application-defined SQL function] that invokes this interface -** should include the [SQLITE_RESULT_SUBTYPE] property in its -** text encoding argument when the SQL function is -** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] -** property is omitted from the function that invokes sqlite3_result_subtype(), -** then in some cases the sqlite3_result_subtype() might fail to set -** the result subtype. -** -** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any -** SQL function that invokes the sqlite3_result_subtype() interface -** and that does not have the SQLITE_RESULT_SUBTYPE property will raise -** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 -** by default. */ void sqlite3_result_subtype(sqlite3_context*,unsigned int); /* ** CAPI3REF: Define New Collating Sequences @@ -6683,11 +6622,11 @@ ** a valid schema, then -1 is returned. */ int sqlite3_txn_state(sqlite3*,const char *zSchema); /* -** CAPI3REF: Allowed return values from sqlite3_txn_state() +** CAPI3REF: Allowed return values from [sqlite3_txn_state()] ** KEYWORDS: {transaction state} ** ** These constants define the current transaction state of a database file. ** ^The [sqlite3_txn_state(D,S)] interface returns one of these ** constants in order to describe the transaction state of schema S @@ -6815,11 +6754,11 @@ ** **

    ^There is only one autovacuum pages callback per database connection. ** ^Each call to the sqlite3_autovacuum_pages() interface overrides all ** previous invocations for that database connection. ^If the callback ** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer, -** then the autovacuum steps callback is canceled. The return value +** then the autovacuum steps callback is cancelled. The return value ** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might ** be some other error code if something goes wrong. The current ** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other ** return codes might be added in future releases. ** @@ -7336,12 +7275,11 @@ /* The methods above are in versions 1 and 2 of the sqlite_module object. ** Those below are for version 3 and greater. */ int (*xShadowName)(const char*); /* The methods above are in versions 1 through 3 of the sqlite_module object. ** Those below are for version 4 and greater. */ - int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema, - const char *zTabName, int mFlags, char **pzErr); + int (*xIntegrity)(sqlite3_vtab *pVTab, char**); }; /* ** CAPI3REF: Virtual Table Indexing Information ** KEYWORDS: sqlite3_index_info @@ -7825,11 +7763,11 @@ ** blob handles or active write statements, the current transaction is ** committed. ^If an error occurs while committing the transaction, an error ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behavior. ^Calling this routine +** open blob handle results in undefined behaviour. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ @@ -9367,12 +9305,12 @@ ** ^(There may be at most one unlock-notify callback registered by a ** blocked connection. If sqlite3_unlock_notify() is called when the ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is canceled. ^The blocked connections -** unlock-notify callback may also be canceled by closing the blocked +** unlock-notify callback is cancelled. ^The blocked connections +** unlock-notify callback may also be cancelled by closing the blocked ** connection using [sqlite3_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes ** any sqlite3_xxx API functions from within an unlock-notify callback, a ** crash or deadlock may be the result. Index: src/sqlite3ext.h ================================================================== --- src/sqlite3ext.h +++ src/sqlite3ext.h @@ -361,13 +361,10 @@ int (*value_encoding)(sqlite3_value*); /* Version 3.41.0 and later */ int (*is_interrupted)(sqlite3*); /* Version 3.43.0 and later */ int (*stmt_explain)(sqlite3_stmt*,int); - /* Version 3.44.0 and later */ - void *(*get_clientdata)(sqlite3*,const char*); - int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". @@ -694,13 +691,10 @@ #define sqlite3_value_encoding sqlite3_api->value_encoding /* Version 3.41.0 and later */ #define sqlite3_is_interrupted sqlite3_api->is_interrupted /* Version 3.43.0 and later */ #define sqlite3_stmt_explain sqlite3_api->stmt_explain -/* Version 3.44.0 and later */ -#define sqlite3_get_clientdata sqlite3_api->get_clientdata -#define sqlite3_set_clientdata sqlite3_api->set_clientdata #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2012,19 +2012,18 @@ #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */ #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */ -#define SQLITE_FUNC_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */ +/* 0x8000 -- available for reuse */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ -/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */ +#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */ #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */ #define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */ -/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */ #define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */ /* Identifier numbers for each in-line function */ #define INLINEFUNC_coalesce 0 #define INLINEFUNC_implies_nonnull_row 1 @@ -2112,14 +2111,13 @@ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } #define MFUNCTION(zName, nArg, xPtr, xFunc) \ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} } -#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, iArg, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\ - SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\ - ((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \ +#define JFUNCTION(zName, nArg, iArg, xFunc) \ + {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|\ + SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } #define INLINE_FUNC(zName, nArg, iArg, mFlags) \ {nArg, SQLITE_FUNC_BUILTIN|\ SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \ SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} } @@ -2514,19 +2512,10 @@ /* Does the table have a rowid */ #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) #define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) -/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is -** available. By default, this macro is false -*/ -#ifndef SQLITE_ALLOW_ROWID_IN_VIEW -# define ViewCanHaveRowid 0 -#else -# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0) -#endif - /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign @@ -3462,11 +3451,10 @@ Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */ ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */ Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */ Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */ u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */ - u8 isDup; /* True if 2nd or later with same pUpsertIdx */ /* Above this point is the parse tree for the ON CONFLICT clauses. ** The next group of fields stores intermediate data. */ void *pToFree; /* Free memory when deleting the Upsert object */ /* All fields above are owned by the Upsert object and must be freed ** when the Upsert is destroyed. The fields below are used to transfer @@ -4087,11 +4075,10 @@ Trigger retTrig; /* The transient trigger that implements RETURNING */ TriggerStep retTStep; /* The trigger step */ int iRetCur; /* Transient table holding RETURNING results */ int nRetCol; /* Number of in pReturnEL after expansion */ int iRetReg; /* Register array for holding a row of RETURNING */ - char zName[40]; /* Name of trigger: "sqlite_returning_%p" */ }; /* ** An objected used to accumulate the text of a string where we ** do not necessarily know how big the string will be in the end. @@ -4228,15 +4215,10 @@ sqlite3_int64 mxMemdbSize; /* Default max memdb size */ #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW - ** feature is disabled. 0 if rowids can - ** occur in views. */ -#endif int bLocaltimeFault; /* True to fail localtime() calls */ int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ @@ -4688,17 +4670,14 @@ #ifndef SQLITE_OMIT_FLOATING_POINT # define EXP754 (((u64)0x7ff)<<52) # define MAN754 ((((u64)1)<<52)-1) # define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0) -# define IsOvfl(X) (((X)&EXP754)==EXP754) int sqlite3IsNaN(double); - int sqlite3IsOverflow(double); #else -# define IsNaN(X) 0 -# define sqlite3IsNaN(X) 0 -# define sqlite3IsOVerflow(X) 0 +# define IsNaN(X) 0 +# define sqlite3IsNaN(X) 0 #endif /* ** An instance of the following structure holds information about SQL ** functions arguments that are the parameters to the printf() function. @@ -5534,11 +5513,11 @@ #endif #ifndef SQLITE_OMIT_UPSERT Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*); void sqlite3UpsertDelete(sqlite3*,Upsert*); Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); - int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*); + int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); Upsert *sqlite3UpsertOfIndex(Upsert*,Index*); int sqlite3UpsertNextIsIPK(Upsert*); #else #define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0) Index: src/test_config.c ================================================================== --- src/test_config.c +++ src/test_config.c @@ -57,18 +57,10 @@ Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY); #endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - Tcl_SetVar2( - interp, "sqlite_options", "allow_rowid_in_view", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2( - interp, "sqlite_options", "allow_rowid_in_view", "0", TCL_GLOBAL_ONLY); -#endif - #ifdef SQLITE_CASE_SENSITIVE_LIKE Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY); #endif Index: src/trigger.c ================================================================== --- src/trigger.c +++ src/trigger.c @@ -968,21 +968,14 @@ Returning *pReturning; Select sSelect; SrcList sFrom; assert( v!=0 ); - if( !pParse->bReturning ){ - /* This RETURNING trigger must be for a different statement as - ** this statement lacks a RETURNING clause. */ - return; - } + assert( pParse->bReturning ); assert( db->pParse==pParse ); pReturning = pParse->u1.pReturning; - if( pTrigger != &(pReturning->retTrig) ){ - /* This RETURNING trigger is for a different statement */ - return; - } + assert( pTrigger == &(pReturning->retTrig) ); memset(&sSelect, 0, sizeof(sSelect)); memset(&sFrom, 0, sizeof(sFrom)); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = &sFrom; sFrom.nSrc = 1; Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -919,13 +919,10 @@ }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, k); } } if( chngRowid==0 && pPk==0 ){ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid); -#endif sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid); } } /* Populate the array of registers beginning at regNew with the new Index: src/upsert.c ================================================================== --- src/upsert.c +++ src/upsert.c @@ -88,12 +88,11 @@ ** is wrong. */ int sqlite3UpsertAnalyzeTarget( Parse *pParse, /* The parsing context */ SrcList *pTabList, /* Table into which we are inserting */ - Upsert *pUpsert, /* The ON CONFLICT clauses */ - Upsert *pAll /* Complete list of all ON CONFLICT clauses */ + Upsert *pUpsert /* The ON CONFLICT clauses */ ){ Table *pTab; /* That table into which we are inserting */ int rc; /* Result code */ int iCursor; /* Cursor used by pTab */ Index *pIdx; /* One of the indexes of pTab */ @@ -192,18 +191,10 @@ /* Column ii of the index did not match any term of the conflict target. ** Continue the search with the next index. */ continue; } pUpsert->pUpsertIdx = pIdx; - if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){ - /* Really this should be an error. The isDup ON CONFLICT clause will - ** never fire. But this problem was not discovered until three years - ** after multi-CONFLICT upsert was added, and so we silently ignore - ** the problem to prevent breaking applications that might actually - ** have redundant ON CONFLICT clauses. */ - pUpsert->isDup = 1; - } break; } if( pUpsert->pUpsertIdx==0 ){ char zWhich[16]; if( nClause==0 && pUpsert->pNextUpsert==0 ){ @@ -226,17 +217,13 @@ */ int sqlite3UpsertNextIsIPK(Upsert *pUpsert){ Upsert *pNext; if( NEVER(pUpsert==0) ) return 0; pNext = pUpsert->pNextUpsert; - while( 1 /*exit-by-return*/ ){ - if( pNext==0 ) return 1; - if( pNext->pUpsertTarget==0 ) return 1; - if( pNext->pUpsertIdx==0 ) return 1; - if( !pNext->isDup ) return 0; - pNext = pNext->pNextUpsert; - } + if( pNext==0 ) return 1; + if( pNext->pUpsertTarget==0 ) return 1; + if( pNext->pUpsertIdx==0 ) return 1; return 0; } /* ** Given the list of ON CONFLICT clauses described by pUpsert, and Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -66,23 +66,10 @@ testcase( rc ); return rc; } #endif /* SQLITE_OMIT_FLOATING_POINT */ -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** Return true if the floating point value is NaN or +Inf or -Inf. -*/ -int sqlite3IsOverflow(double x){ - int rc; /* The value return */ - u64 y; - memcpy(&y,&x,sizeof(y)); - rc = IsOvfl(y); - return rc; -} -#endif /* SQLITE_OMIT_FLOATING_POINT */ - /* ** Compute a string length that is limited to what can be stored in ** lower 30 bits of a 32-bit signed integer. ** ** The value returned will never be negative. Nor will it ever be greater @@ -152,11 +139,11 @@ ** Load the sqlite3.iSysErrno field if that is an appropriate thing ** to do based on the SQLite error code in rc. */ void sqlite3SystemError(sqlite3 *db, int rc){ if( rc==SQLITE_IOERR_NOMEM ) return; -#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) +#ifdef SQLITE_USE_SEH if( rc==SQLITE_IOERR_IN_PAGE ){ int ii; int iErr; sqlite3BtreeEnterAll(db); for(ii=0; iinDb; ii++){ Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -130,16 +130,15 @@ ** sqlite3CorruptError(lineno) ** sqlite3MisuseError(lineno) ** sqlite3CantopenError(lineno) */ static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){ - static u64 n = 0; + static int n = 0; (void)pc; (void)pOp; (void)v; n++; - if( n==LARGEST_UINT64 ) abort(); /* So that n is used, preventing a warning */ } #endif /* ** Invoke the VDBE coverage callback, if that callback is defined. This @@ -6910,33 +6909,25 @@ ** Disable Auth and Trace callbacks while those statements are running if ** P1 is true. */ case OP_SqlExec: { char *zErr; -#ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth; -#endif u8 mTrace; sqlite3VdbeIncrWriteCounter(p, 0); db->nSqlExec++; zErr = 0; -#ifndef SQLITE_OMIT_AUTHORIZATION xAuth = db->xAuth; -#endif mTrace = db->mTrace; if( pOp->p1 ){ -#ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = 0; -#endif db->mTrace = 0; } rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr); db->nSqlExec--; -#ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = xAuth; -#endif db->mTrace = mTrace; if( zErr || rc ){ sqlite3VdbeError(p, "%s", zErr); sqlite3_free(zErr); if( rc==SQLITE_NOMEM ) goto no_mem; @@ -8161,44 +8152,42 @@ break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VCheck P1 P2 P3 P4 * +/* Opcode: VCheck * P2 * P4 * ** -** P4 is a pointer to a Table object that is a virtual table in schema P1 -** that supports the xIntegrity() method. This opcode runs the xIntegrity() -** method for that virtual table, using P3 as the integer argument. If -** an error is reported back, the table name is prepended to the error -** message and that message is stored in P2. If no errors are seen, -** register P2 is set to NULL. +** P4 is a pointer to a Table object that is a virtual table that +** supports the xIntegrity() method. This opcode runs the xIntegrity() +** method for that virtual table. If an error is reported back, the error +** message is stored in register P2. If no errors are seen, register P2 +** is set to NULL. */ case OP_VCheck: { /* out2 */ Table *pTab; sqlite3_vtab *pVtab; const sqlite3_module *pModule; char *zErr = 0; pOut = &aMem[pOp->p2]; sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */ - assert( pOp->p4type==P4_TABLEREF ); + assert( pOp->p4type==P4_TABLE ); pTab = pOp->p4.pTab; assert( pTab!=0 ); - assert( pTab->nTabRef>0 ); assert( IsVirtual(pTab) ); - if( pTab->u.vtab.p==0 ) break; + assert( pTab->u.vtab.p!=0 ); pVtab = pTab->u.vtab.p->pVtab; assert( pVtab!=0 ); pModule = pVtab->pModule; assert( pModule!=0 ); assert( pModule->iVersion>=4 ); assert( pModule->xIntegrity!=0 ); + pTab->nTabRef++; sqlite3VtabLock(pTab->u.vtab.p); - assert( pOp->p1>=0 && pOp->p1nDb ); - rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName, - pOp->p3, &zErr); + rc = pModule->xIntegrity(pVtab, &zErr); sqlite3VtabUnlock(pTab->u.vtab.p); + sqlite3DeleteTable(db, pTab); if( rc ){ sqlite3_free(zErr); goto abort_due_to_error; } if( zErr ){ Index: src/vdbe.h ================================================================== --- src/vdbe.h +++ src/vdbe.h @@ -124,11 +124,10 @@ #define P4_VTAB (-11) /* P4 is a pointer to an sqlite3_vtab structure */ #define P4_REAL (-12) /* P4 is a 64-bit floating point value */ #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */ #define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */ -#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 #define P5_ConstraintUnique 2 #define P5_ConstraintCheck 3 Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -529,22 +529,10 @@ void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ Mem *pOut; #ifdef SQLITE_ENABLE_API_ARMOR if( pCtx==0 ) return; #endif -#if defined(SQLITE_STRICT_SUBTYPE) && SQLITE_STRICT_SUBTYPE+0!=0 - if( pCtx->pFunc!=0 - && (pCtx->pFunc->funcFlags & SQLITE_RESULT_SUBTYPE)==0 - ){ - char zErr[200]; - sqlite3_snprintf(sizeof(zErr), zErr, - "misuse of sqlite3_result_subtype() by %s()", - pCtx->pFunc->zName); - sqlite3_result_error(pCtx, zErr, -1); - return; - } -#endif /* SQLITE_STRICT_SUBTYPE */ pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); pOut->eSubtype = eSubtype & 0xff; pOut->flags |= MEM_Subtype; } Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -209,15 +209,14 @@ ** sqlite3CorruptError(lineno) ** sqlite3MisuseError(lineno) ** sqlite3CantopenError(lineno) */ static void test_addop_breakpoint(int pc, Op *pOp){ - static u64 n = 0; + static int n = 0; (void)pc; (void)pOp; n++; - if( n==LARGEST_UINT64 ) abort(); /* so that n is used, preventing a warning */ } #endif /* ** Slow paths for sqlite3VdbeAddOp3() and sqlite3VdbeAddOp4Int() for the @@ -1398,14 +1397,10 @@ } case P4_VTAB : { if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); break; } - case P4_TABLEREF: { - if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4); - break; - } } } /* ** Free the space allocated for aOp and any p4 values allocated for the @@ -4058,27 +4053,10 @@ swapMixedEndianFloat(x); memcpy(&pMem->u.r, &x, sizeof(x)); pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real; } } -static int serialGet7( - const unsigned char *buf, /* Buffer to deserialize from */ - Mem *pMem /* Memory cell to write value into */ -){ - u64 x = FOUR_BYTE_UINT(buf); - u32 y = FOUR_BYTE_UINT(buf+4); - x = (x<<32) + y; - assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->u.r, &x, sizeof(x)); - if( IsNaN(x) ){ - pMem->flags = MEM_Null; - return 1; - } - pMem->flags = MEM_Real; - return 0; -} void sqlite3VdbeSerialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ @@ -4501,15 +4479,10 @@ ** Do a comparison between a 64-bit signed integer and a 64-bit floating-point ** number. Return negative, zero, or positive if the first (i64) is less than, ** equal to, or greater than the second (double). */ int sqlite3IntFloatCompare(i64 i, double r){ - if( sqlite3IsNaN(r) ){ - /* SQLite considers NaN to be a NULL. And all integer values are greater - ** than NULL */ - return 1; - } if( sqlite3Config.bUseLongDouble ){ LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; testcase( xr ); testcase( x==r ); @@ -4754,11 +4727,11 @@ if( serial_type>=10 ){ rc = serial_type==10 ? -1 : +1; }else if( serial_type==0 ){ rc = -1; }else if( serial_type==7 ){ - serialGet7(&aKey1[d1], &mem1); + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r); }else{ i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); i64 rhs = pRhs->u.i; if( lhsu.r ){ + if( mem1.u.ru.r ){ rc = -1; }else if( mem1.u.r>pRhs->u.r ){ rc = +1; - }else{ - assert( rc==0 ); } }else{ - sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r); } } } @@ -4860,18 +4829,11 @@ } /* RHS is null */ else{ serial_type = aKey1[idx1]; - if( serial_type==0 - || serial_type==10 - || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0) - ){ - assert( rc==0 ); - }else{ - rc = 1; - } + rc = (serial_type!=0 && serial_type!=10); } if( rc!=0 ){ int sortFlags = pPKey2->pKeyInfo->aSortFlags[i]; if( sortFlags ){ Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -1513,11 +1513,11 @@ #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION if( pFunc==0 ) return SQLITE_OK; #endif assert( pFunc ); if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || (pFunc->funcFlags & (SQLITE_FUNC_NEEDCOLL|SQLITE_FUNC_RUNONLY))!=0 + || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) ){ return SQLITE_OK; } if( pList ){ Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -5794,32 +5794,24 @@ assert( pIdx->bHasExpr ); pTab = pIdx->pTable; for(i=0; inColumn; i++){ Expr *pExpr; int j = pIdx->aiColumn[i]; + int bMaybeNullRow; if( j==XN_EXPR ){ pExpr = pIdx->aColExpr->a[i].pExpr; + testcase( pTabItem->fg.jointype & JT_LEFT ); + testcase( pTabItem->fg.jointype & JT_RIGHT ); + testcase( pTabItem->fg.jointype & JT_LTORJ ); + bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0; }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){ pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]); + bMaybeNullRow = 0; }else{ continue; } if( sqlite3ExprIsConstant(pExpr) ) continue; - if( pExpr->op==TK_FUNCTION ){ - /* Functions that might set a subtype should not be replaced by the - ** value taken from an expression index since the index omits the - ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */ - int n; - FuncDef *pDef; - sqlite3 *db = pParse->db; - assert( ExprUseXList(pExpr) ); - n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; - pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); - if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ - continue; - } - } p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr)); if( p==0 ) break; p->pIENext = pParse->pIdxEpr; #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace & 0x200 ){ @@ -5829,11 +5821,11 @@ #endif p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); p->iDataCur = pTabItem->iCursor; p->iIdxCur = iIdxCur; p->iIdxCol = i; - p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0; + p->bMaybeNullRow = bMaybeNullRow; if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){ p->aff = pIdx->zColAff[i]; } #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS p->zIdxName = pIdx->zName; @@ -5994,14 +5986,11 @@ db = pParse->db; memset(&sWLB, 0, sizeof(sWLB)); /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); - if( pOrderBy && pOrderBy->nExpr>=BMS ){ - pOrderBy = 0; - wctrlFlags &= ~WHERE_WANT_DISTINCT; - } + if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask */ testcase( pTabList->nSrc==BMS ); Index: src/window.c ================================================================== --- src/window.c +++ src/window.c @@ -1036,11 +1036,11 @@ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ExprList *pArgs; assert( ExprUseXList(pWin->pOwner) ); assert( pWin->pWFunc!=0 ); pArgs = pWin->pOwner->x.pList; - if( pWin->pWFunc->funcFlags & SQLITE_SUBTYPE ){ + if( pWin->pWFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){ selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); pWin->bExprArgs = 1; }else{ pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); Index: test/aggorderby.test ================================================================== --- test/aggorderby.test +++ test/aggorderby.test @@ -73,50 +73,7 @@ SELECT (SELECT string_agg(a,d ORDER BY d DESC) FROM t3) FROM t1; } {aaa-aaa bbb-bbb} do_execsql_test aggorderby-5.3 { SELECT (SELECT string_agg(a,'#' ORDER BY d) FROM t3) FROM t1; } {aaa#aaa bbb#bbb} - -# COLLATE works on the ORDER BY. -# -do_execsql_test aggorderby-6.0 { - WITH c(x) AS (VALUES('abc'),('DEF'),('xyz'),('ABC'),('XYZ')) - SELECT string_agg(x,',' ORDER BY x COLLATE nocase), - string_agg(x,',' ORDER BY x) FROM c; -} {abc,ABC,DEF,xyz,XYZ ABC,DEF,XYZ,abc,xyz} -do_execsql_test aggorderby-6.1 { - WITH c(x,y) AS (VALUES(1,'a'),(2,'B'),(3,'c'),(4,'D')) - SELECT group_concat(x ORDER BY y COLLATE nocase), - group_concat(x ORDER BY y COLLATE binary) FROM c; -} {1,2,3,4 2,4,1,3} - -# NULLS FIRST and NULLS LAST work on the ORDER BY -# -do_execsql_test aggorderby-7.0 { - WITH c(x) AS (VALUES(1),(NULL),(2.5),(NULL),('three')) - SELECT json_group_array(x ORDER BY x NULLS FIRST), - json_group_array(x ORDER BY x NULLS LAST) FROM c; -} {[null,null,1,2.5,"three"] [1,2.5,"three",null,null]} -do_execsql_test aggorderby-7.1 { - WITH c(x,y) AS (VALUES(1,9),(2,null),(3,5),(4,null),(5,1)) - SELECT json_group_array(x ORDER BY y NULLS FIRST, x), - json_group_array(x ORDER BY y NULLS LAST, x) FROM c; -} {[2,4,5,3,1] [5,3,1,2,4]} - -# The DISTINCT only applies to the function arguments, not to the -# ORDER BY arguments. -# -do_execsql_test aggorderby-8.0 { - WITH c(x,y,z) AS (VALUES('a',4,5),('b',3,6),('c',2,7),('c',1,8)) - SELECT group_concat(DISTINCT x ORDER BY y, z) FROM c; -} {c,b,a} -do_execsql_test aggorderby-8.1 { - WITH c(x,y,z) AS (VALUES('a',4,5),('b',3,6),('b',2,7),('c',1,8)) - SELECT group_concat(DISTINCT x ORDER BY y, z) FROM c; -} {c,b,a} -do_execsql_test aggorderby-8.2 { - WITH c(x,y) AS (VALUES(1,1),(2,2),(3,3),(3,4),(3,5),(3,6)) - SELECT sum(DISTINCT x ORDER BY y) FROM c; -} 6 - finish_test Index: test/alter.test ================================================================== --- test/alter.test +++ test/alter.test @@ -951,36 +951,7 @@ ALTER TABLE t1 ADD COLUMN b TEXT DEFAULT x'313233'; } {} do_catchsql_test alter-20.3 { INSERT INTO t1(a) VALUES(45); } {1 {cannot store BLOB value in TEXT column t1.b}} - -# 2023-11-17 dbsqlfuzz e0900262dadd5c78c2226ad6a435c7f0255be2cd -# Assertion fault associated with ALTER TABLE and an -# aggregate ORDER BY within an unknown aggregate function. -# -reset_db -do_execsql_test alter-21.1 { - CREATE TABLE t1(a,b,c,d); - CREATE TABLE t2(a,b,c,d,x); - CREATE TRIGGER r1 AFTER INSERT ON t2 BEGIN - SELECT unknown_function(a ORDER BY (SELECT group_concat(DISTINCT a ORDER BY a) FROM t1)) FROM t1; - END; - ALTER TABLE t2 RENAME TO e; -} {} -do_execsql_test alter-21.2 { - SELECT name, type FROM sqlite_schema ORDER BY name; -} {e table r1 trigger t1 table} -do_execsql_test alter-21.3 { - DROP TRIGGER r1; - CREATE TRIGGER r2 AFTER INSERT ON e BEGIN - SELECT unknown_function(a ORDER BY (SELECT group_concat(a ORDER BY a) FROM (SELECT b FROM t1))) FROM t1; - END; - ALTER TABLE e RENAME TO t99; -} -do_execsql_test alter-21.4 { - SELECT name, type FROM sqlite_schema ORDER BY name; -} {r2 trigger t1 table t99 table} - - finish_test Index: test/altermalloc3.test ================================================================== --- test/altermalloc3.test +++ test/altermalloc3.test @@ -24,11 +24,10 @@ set ::TMPDBERROR [list 1 \ {unable to open a temporary database file for storing temporary tables} ] -sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1 do_execsql_test 1.0 { CREATE TABLE x1( one, two, three, PRIMARY KEY(one), CHECK (three!="xyz"), CHECK (two!="one") ) WITHOUT ROWID; DELETED test/bestindexB.test Index: test/bestindexB.test ================================================================== --- test/bestindexB.test +++ /dev/null @@ -1,87 +0,0 @@ -# 2023-10-26 -# -# The author disclaims copyright to this source code. In place of -# a legal notice, here is a blessing: -# -# May you do good and not evil. -# May you find forgiveness for yourself and forgive others. -# May you share freely, never taking more than you give. -# -#*********************************************************************** -# -# - -set testdir [file dirname $argv0] -source $testdir/tester.tcl -set testprefix bestindexB - -ifcapable !vtab { - finish_test - return -} - -register_tcl_module db - -proc vtab_command {method args} { - switch -- $method { - xConnect { - return "CREATE TABLE t1(a, b, c)" - } - - xBestIndex { - set hdl [lindex $args 0] - set clist [$hdl constraints] - set orderby [$hdl orderby] - - if {[info exists ::xbestindex_sql]} { - explain_i $::xbestindex_sql - set ::xbestindex_res [ execsql $::xbestindex_sql ] - } - - return "cost 1000000 rows 1000000 idxnum 0 idxstr hello" - } - - xFilter { - return "sql {SELECT 0, 1, 2, 3}" - } - } - - return {} -} - -do_execsql_test 1.0 { - CREATE VIRTUAL TABLE x1 USING tcl(vtab_command); - CREATE TABLE y1(a, b); - CREATE TABLE y2(a, b); -} {} - -do_execsql_test 1.1 { - SELECT * FROM x1 -} {1 2 3} - -do_execsql_test 1.2 { - INSERT INTO y1 VALUES(1, 2) RETURNING rowid; -} {1} - -do_execsql_test 1.3 { - CREATE TRIGGER y1tr BEFORE INSERT ON y1 BEGIN - SELECT * FROM x1; - END; - INSERT INTO y1 VALUES(3, 4) RETURNING rowid; -} {2} - - -# This time, rig the xBestIndex() method of the vtab to invoke an SQL -# statement that uses RETURNING. -set ::xbestindex_sql { - INSERT INTO y2 VALUES(NULL, NULL) RETURNING rowid; -} -do_execsql_test 1.4 { - INSERT INTO y1 VALUES(5, 6) RETURNING rowid; -} {3} - -do_test 1.5 { - set ::xbestindex_res -} {1} - -finish_test Index: test/date4.test ================================================================== --- test/date4.test +++ test/date4.test @@ -26,11 +26,11 @@ if {$tcl_platform(os)=="Linux"} { set FMT {%d,%e,%F,%H,%k,%I,%l,%j,%m,%M,%u,%w,%W,%Y,%%,%P,%p} } else { set FMT {%d,%e,%F,%H,%I,%j,%p,%R,%u,%w,%W,%%} } -for {set i 0} {$i<=24854} {incr i} { +for {set i 0} {$i<=86400} {incr i} { set TS [expr {$i*86401}] do_execsql_test date4-$i { SELECT strftime($::FMT,$::TS,'unixepoch'); } [list [strftime $FMT $TS]] } Index: test/default.test ================================================================== --- test/default.test +++ test/default.test @@ -133,12 +133,8 @@ # reset_db do_catchsql_test default-5.1 { CREATE TABLE t1 (a,b DEFAULT(random() NOTNULL IN (RAISE(IGNORE),2,3))); INSERT INTO t1(a) VALUES(1); -} {1 {RAISE() may only be used within a trigger-program}} -do_catchsql_test default-5.2 { - CREATE TABLE Table0 (Col0 DEFAULT (RAISE(IGNORE) ) ) ; - INSERT INTO Table0 DEFAULT VALUES ; } {1 {RAISE() may only be used within a trigger-program}} finish_test Index: test/func.test ================================================================== --- test/func.test +++ test/func.test @@ -1551,27 +1551,6 @@ do_execsql_test func-38.100 { WITH t1(x) AS (VALUES(9e+999)) SELECT sum(x), avg(x), total(x) FROM t1; WITH t1(x) AS (VALUES(-9e+999)) SELECT sum(x), avg(x), total(x) FROM t1; } {Inf Inf Inf -Inf -Inf -Inf} -# 2024-03-21 https://sqlite.org/forum/forumpost/23b8688ef4 -# Another problem with Kahan-Babushka-Neumaier summation and -# infinities. -# -do_execsql_test func-39.101 { - WITH RECURSIVE c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<1) - SELECT sum(1.7976931348623157e308), - avg(1.7976931348623157e308), - total(1.7976931348623157e308) - FROM c; -} {1.79769313486232e+308 1.79769313486232e+308 1.79769313486232e+308} -for {set i 2} {$i<10} {incr i} { - do_execsql_test func-39.[expr {10*$i+100}] { - WITH RECURSIVE c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<$i) - SELECT sum(1.7976931348623157e308), - avg(1.7976931348623157e308), - total(1.7976931348623157e308) - FROM c; - } {Inf Inf Inf} -} - finish_test Index: test/fuzzinvariants.c ================================================================== --- test/fuzzinvariants.c +++ test/fuzzinvariants.c @@ -294,18 +294,10 @@ ){ /* This is a randomized column name and so cannot be used in the ** WHERE clause. */ continue; } -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( sqlite3_strlike("%rowid%",zColName,0)==0 - || sqlite3_strlike("%oid%",zColName,0)==0 - ){ - /* ROWID values are unreliable if SQLITE_ALLOW_ROWID_IN_VIEW is used */ - continue; - } -#endif for(j=0; j>'a'; } xyz -# 2023-11-08 forum/forumpost/ddcad3e884 -# -do_execsql_test 13.1 { - SELECT json('{x:''a "b" c''}'); -} {{{"x":"a \"b\" c"}}} finish_test Index: test/misc2.test ================================================================== --- test/misc2.test +++ test/misc2.test @@ -52,38 +52,23 @@ CREATE TABLE t2(a,b,c); INSERT INTO t2 VALUES(7,8,9); } } {} ifcapable subquery { - ifcapable allow_rowid_in_view { - do_catchsql_test misc2-2.2 { - SELECT rowid, * FROM (SELECT * FROM t1, t2); - } {0 {{} 1 2 3 7 8 9}} - } else { - do_catchsql_test misc2-2.2 { - SELECT rowid, * FROM (SELECT * FROM t1, t2); - } {1 {no such column: rowid}} - } + do_catchsql_test misc2-2.2 { + SELECT rowid, * FROM (SELECT * FROM t1, t2); + } {1 {no such column: rowid}} do_catchsql_test misc2-2.2b { SELECT 'rowid', * FROM (SELECT * FROM t1, t2); } {0 {rowid 1 2 3 7 8 9}} } ifcapable view { - ifcapable allow_rowid_in_view { - do_catchsql_test misc2-2.3 { - CREATE VIEW v1 AS SELECT * FROM t1, t2; - SELECT rowid, * FROM v1; - } {0 {{} 1 2 3 7 8 9}} - } else { - do_catchsql_test misc2-2.3 { - CREATE VIEW v1 AS SELECT * FROM t1, t2; - SELECT rowid, * FROM v1; - } {1 {no such column: rowid}} - } - - + do_catchsql_test misc2-2.3 { + CREATE VIEW v1 AS SELECT * FROM t1, t2; + SELECT rowid, * FROM v1; + } {1 {no such column: rowid}} do_catchsql_test misc2-2.3b { SELECT 'rowid', * FROM v1; } {0 {rowid 1 2 3 7 8 9}} } ;# ifcapable view Index: test/mmap1.test ================================================================== --- test/mmap1.test +++ test/mmap1.test @@ -43,21 +43,21 @@ $dbname func rblob rblob }] } -# For cases 1.1 and 1.4, the number of pages read using xRead() is 8 on -# unix and 12 on windows. The difference is that windows only ever maps +# For cases 1.1 and 1.4, the number of pages read using xRead() is 4 on +# unix and 9 on windows. The difference is that windows only ever maps # an integer number of OS pages (i.e. creates mappings that are a multiple # of 4KB in size). Whereas on unix any sized mapping may be created. # foreach {t mmap_size nRead c2init} { - 1.1 { PRAGMA mmap_size = 67108864 } /8|12/ {PRAGMA mmap_size = 0} - 1.2 { PRAGMA mmap_size = 53248 } 154 {PRAGMA mmap_size = 0} + 1.1 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 0} + 1.2 { PRAGMA mmap_size = 53248 } 150 {PRAGMA mmap_size = 0} 1.3 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 0} - 1.4 { PRAGMA mmap_size = 67108864 } /12|8/ {PRAGMA mmap_size = 67108864 } - 1.5 { PRAGMA mmap_size = 53248 } 154 {PRAGMA mmap_size = 67108864 } + 1.4 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 67108864 } + 1.5 { PRAGMA mmap_size = 53248 } 150 {PRAGMA mmap_size = 67108864 } 1.6 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 67108864 } } { do_multiclient_test tn { sql1 {PRAGMA cache_size=2000} DELETED test/mmapcorrupt.test Index: test/mmapcorrupt.test ================================================================== --- test/mmapcorrupt.test +++ /dev/null @@ -1,51 +0,0 @@ -# 2024 January 23 -# -# The author disclaims copyright to this source code. In place of -# a legal notice, here is a blessing: -# -# May you do good and not evil. -# May you find forgiveness for yourself and forgive others. -# May you share freely, never taking more than you give. -# -#*********************************************************************** -# -# Test special cases of corrupt database handling in mmap-mode. -# - -set testdir [file dirname $argv0] -source $testdir/tester.tcl -set testprefix mmapcorrupt - -database_may_be_corrupt - -db close -sqlite3_shutdown -sqlite3_config_lookaside 0 0 -sqlite3_initialize - -reset_db -do_execsql_test 1.0 { - PRAGMA page_size = 16384; - CREATE TABLE tn1(a PRIMARY KEY) WITHOUT ROWID; - CREATE TABLE t0(a PRIMARY KEY) WITHOUT ROWID; - CREATE TABLE t1(a PRIMARY KEY) WITHOUT ROWID; - INSERT INTO t1 VALUES('B'); -} -db close - -set sz [file size test.db] -hexio_write test.db [expr $sz-3] 800380 - -sqlite3 db test.db -do_execsql_test 2.1 { - PRAGMA mmap_size = 1000000; - SELECT sql FROM sqlite_schema LIMIT 1; - SELECT * FROM t0; -} {1000000 {CREATE TABLE tn1(a PRIMARY KEY) WITHOUT ROWID}} - -do_execsql_test 2.2 { - INSERT INTO t0 SELECT * FROM t1; -} - -finish_test - Index: test/pragma4.test ================================================================== --- test/pragma4.test +++ test/pragma4.test @@ -262,19 +262,7 @@ PRAGMA table_info = t4; } { 0 a {} 0 'abc' 0 1 b {} 0 -1 0 2 c {} 0 +4.0 0 } -# 2024-03-24 https://sqlite.org/forum/forumpost/85b6a8b6705fb77a -# -reset_db -do_execsql_test 6.0 { - CREATE TABLE t1(a INT PRIMARY KEY, b INT); - CREATE TABLE t2(c INT PRIMARY KEY, d INT REFERENCES t1); - SELECT t.name, f."table", f."from", i.name, i.pk - FROM pragma_table_list() AS t - JOIN pragma_foreign_key_list(t.name, t.schema) AS f - JOIN pragma_table_info(f."table", t.schema) AS i - WHERE i.pk; -} {t2 t1 d a 1} finish_test Index: test/returning1.test ================================================================== --- test/returning1.test +++ test/returning1.test @@ -210,42 +210,21 @@ CREATE TRIGGER tr2 INSTEAD OF UPDATE ON t1 BEGIN INSERT INTO log VALUES('update', new.rowid, new.a, new.b); END; } -ifcapable !allow_rowid_in_view { - do_catchsql_test 10.3a { - INSERT INTO t1(a, b) VALUES(1234, 5678) RETURNING rowid; - } {1 {no such column: new.rowid}} - - do_catchsql_test 10.3b { - UPDATE t1 SET a='z' WHERE b='y' RETURNING rowid; - } {1 {no such column: new.rowid}} - - do_execsql_test 10.4 { - SELECT * FROM log; - } {} -} else { - # Note: The values returned by the RETURNING clauses of the following - # two statements are the rowid columns of views. These values are not - # well defined, so the INSERT returns -1, and the UPDATE returns 1, 2 - # and 3. These match the values used for new.rowid expressions, but - # not much else. - do_catchsql_test 10.3a { - INSERT INTO t1(a, b) VALUES(1234, 5678) RETURNING rowid; - } {0 -1} - - do_catchsql_test 10.3b { - UPDATE t1 SET a='z' WHERE b='y' RETURNING rowid; - } {0 {1 2 3}} - - do_execsql_test 10.4 { - SELECT * FROM log; - } { - insert -1 1234 5678 update 1 z y update 2 z y update 3 z y - } -} +do_catchsql_test 10.3a { + INSERT INTO t1(a, b) VALUES(1234, 5678) RETURNING rowid; +} {1 {no such column: new.rowid}} + +do_catchsql_test 10.3b { + UPDATE t1 SET a='z' WHERE b='y' RETURNING rowid; +} {1 {no such column: new.rowid}} + +do_execsql_test 10.4 { + SELECT * FROM log; +} {} # 2021-04-27 dbsqlfuzz 78b9400770ef8cc7d9427dfba26f4fcf46ea7dc2 # Returning clauses on TEMP tables with triggers. # reset_db Index: test/rowid.test ================================================================== --- test/rowid.test +++ test/rowid.test @@ -801,33 +801,20 @@ INSERT INTO t1(rowid, x) VALUES(1, 1); INSERT INTO t2(y) VALUES(2); INSERT INTO t3(rowid, z) VALUES(3, 3); } -ifcapable allow_rowid_in_view { - set nosuch "1 {no such column: rowid}" - do_execsql_test 16.1 { SELECT rowid FROM t1, t2; } {1} - do_catchsql_test 16.2 { SELECT rowid FROM t1, v1; } $nosuch - do_catchsql_test 16.3 { SELECT rowid FROM t3, v1; } $nosuch - do_catchsql_test 16.4 { SELECT rowid FROM t3, (SELECT 123); } $nosuch - - do_execsql_test 16.5 { SELECT rowid FROM t2, t1; } {1} - do_catchsql_test 16.6 { SELECT rowid FROM v1, t1; } $nosuch - do_catchsql_test 16.7 { SELECT rowid FROM v1, t3; } $nosuch - do_execsql_test 16.8 { SELECT rowid FROM (SELECT 123), t3; } {3} -} else { - do_execsql_test 16.1 { SELECT rowid FROM t1, t2; } {1} - do_execsql_test 16.2 { SELECT rowid FROM t1, v1; } {1} - do_execsql_test 16.3 { SELECT rowid FROM t3, v1; } {3} - do_execsql_test 16.4 { SELECT rowid FROM t3, (SELECT 123); } {3} - - do_execsql_test 16.5 { SELECT rowid FROM t2, t1; } {1} - do_execsql_test 16.6 { SELECT rowid FROM v1, t1; } {1} - do_execsql_test 16.7 { SELECT rowid FROM v1, t3; } {3} - do_execsql_test 16.8 { SELECT rowid FROM (SELECT 123), t3; } {3} -} - -do_catchsql_test 16.9 { - SELECT rowid FROM t1, t3; -} {1 {ambiguous column name: rowid}} +do_execsql_test 16.1 { SELECT rowid FROM t1, t2; } {1} +do_execsql_test 16.2 { SELECT rowid FROM t1, v1; } {1} +do_execsql_test 16.3 { SELECT rowid FROM t3, v1; } {3} +do_execsql_test 16.4 { SELECT rowid FROM t3, (SELECT 123); } {3} + +do_execsql_test 16.5 { SELECT rowid FROM t2, t1; } {1} +do_execsql_test 16.6 { SELECT rowid FROM v1, t1; } {1} +do_execsql_test 16.7 { SELECT rowid FROM v1, t3; } {3} +do_execsql_test 16.8 { SELECT rowid FROM (SELECT 123), t3; } {3} + +do_catchsql_test 16.5 { SELECT rowid FROM t1, t3; } {1 {no such column: rowid}} + + finish_test Index: test/shell1.test ================================================================== --- test/shell1.test +++ test/shell1.test @@ -494,20 +494,15 @@ catchcmd "test.db" ".nullvalue FOO BAD" } {1 {Usage: .nullvalue STRING}} # .output FILENAME Send output to FILENAME do_test shell1-3.15.1 { - catchcmd "test.db" ".output -.print x" -} {0 x} + catchcmd "test.db" ".output" +} {0 {}} do_test shell1-3.15.2 { - catchcmd "test.db" ".output FOO -.print x -.output -SELECT readfile('FOO');" -} {0 {x -}} + catchcmd "test.db" ".output FOO" +} {0 {}} do_test shell1-3.15.3 { # too many arguments catchcmd "test.db" ".output FOO BAD" } {1 {ERROR: extra parameter: "BAD". Usage: .output ?FILE? Send output to FILE or stdout if FILE is omitted @@ -1070,11 +1065,11 @@ # the alarm (\a) character, and those with special meaning to # the SQLite shell itself. # set escapes [list \ \a \\a \b \\b \t \\t \n \\n \v \\v \f \\f \r \\r \ - " " "\" \"" \" \\\" \\ \\\\] + " " "\" \"" \" \\\" ' \"'\" \\ \\\\] } else { # # NOTE: On Unix, we need to escape most of the whitespace characters # and those with special meaning to the SQLite shell itself. # The alarm (\a), backspace (\b), and carriage-return (\r) Index: test/trigger9.test ================================================================== --- test/trigger9.test +++ test/trigger9.test @@ -240,29 +240,14 @@ CREATE TRIGGER tr3 INSTEAD OF INSERT ON v1 BEGIN INSERT INTO log VALUES('insert'); END; } -ifcapable !allow_rowid_in_view { - do_catchsql_test 4.2 { - DELETE FROM v1 WHERE rowid=1; - } {1 {no such column: rowid}} - - do_catchsql_test 4.3 { - UPDATE v1 SET a=b WHERE rowid=2; - } {1 {no such column: rowid}} -} else { - do_execsql_test 4.2a { - DELETE FROM log; - } - do_catchsql_test 4.2 { - DELETE FROM v1 WHERE rowid=1; - } {0 {}} - do_catchsql_test 4.3 { - UPDATE v1 SET a=b WHERE rowid=2; - } {0 {}} - do_execsql_test 4.3b { - SELECT * FROM log; - } -} +do_catchsql_test 4.2 { + DELETE FROM v1 WHERE rowid=1; +} {1 {no such column: rowid}} + +do_catchsql_test 4.3 { + UPDATE v1 SET a=b WHERE rowid=2; +} {1 {no such column: rowid}} finish_test Index: test/unionall.test ================================================================== --- test/unionall.test +++ test/unionall.test @@ -344,17 +344,10 @@ SELECT *, '+' FROM t1 LEFT JOIN t2 ON (a NOT IN(SELECT v FROM t1, t3 WHERE a=k)=NOT EXISTS(SELECT 1 FROM t1 LEFT JOIN t3 ON (a=k))); } {0 {} {} {} + 1 one {} {} + 2 two {} {} + 5 five {} {} + 3 three {} {} + 6 six {} {} +} do_execsql_test 5.20 { SELECT *, '+' FROM t1 LEFT JOIN t3 ON (a NOT IN(SELECT v FROM t1 LEFT JOIN t2 ON (a=k))=k); } {0 {} {} {} + 1 one {} {} + 2 two {} {} + 5 five {} {} + 3 three {} {} + 6 six {} {} +} -ifcapable vtab { -do_catchsql_test 5.30 { - SELECT * FROM (t1 NATURAL JOIN pragma_table_xinfo('t1_a') NATURAL JOIN t3) t1 - NATURAL JOIN t2 NATURAL JOIN t3 - WHERE rowid ISNULL>0 AND 0%y; -} {1 {ambiguous column name: rowid}} -} reset_db do_execsql_test 6.0 { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); Index: test/upsert5.test ================================================================== --- test/upsert5.test +++ test/upsert5.test @@ -406,48 +406,6 @@ ON CONFLICT(c) DO UPDATE SET b='' ON CONFLICT((SELECT t2 FROM nosuchtable)) DO NOTHING; } {1 {no such table: nosuchtable}} -# 2024-03-08 https://sqlite.org/forum/forumpost/919c6579c8 -# A redundant ON CONFLICT clause in an upsert can lead to -# index corruption. -# -reset_db -do_execsql_test 3.0 { - CREATE TABLE t1(aa INTEGER PRIMARY KEY, bb INT); - INSERT INTO t1 VALUES(11,22); - CREATE UNIQUE INDEX t1bb ON t1(bb); - REPLACE INTO t1 VALUES(11,33) - ON CONFLICT(bb) DO UPDATE SET aa = 44 - ON CONFLICT(bb) DO UPDATE SET aa = 44; - PRAGMA integrity_check; -} {ok} -do_execsql_test 3.1 { - SELECT * FROM t1 NOT INDEXED; -} {11 33} -do_execsql_test 3.2 { - SELECT * FROM t1 INDEXED BY t1bb; -} {11 33} -do_execsql_test 3.3 { - DROP TABLE t1; - CREATE TABLE t1(aa INTEGER PRIMARY KEY, bb INT, cc INT); - INSERT INTO t1 VALUES(10,21,32),(11,22,33),(12,23,34); - CREATE UNIQUE INDEX t1bb ON t1(bb); - CREATE UNIQUE INDEX t1cc ON t1(cc); - REPLACE INTO t1 VALUES(11,44,55) - ON CONFLICT(bb) DO UPDATE SET aa = 99 - ON CONFLICT(cc) DO UPDATE SET aa = 99 - ON CONFLICT(bb) DO UPDATE SET aa = 99; - PRAGMA integrity_check; -} {ok} -do_execsql_test 3.4 { - SELECT * FROM t1 NOT INDEXED ORDER BY +aa; -} {10 21 32 11 44 55 12 23 34} -do_execsql_test 3.5 { - SELECT * FROM t1 INDEXED BY t1bb ORDER BY +aa; -} {10 21 32 11 44 55 12 23 34} -do_execsql_test 3.6 { - SELECT * FROM t1 INDEXED BY t1cc ORDER BY +aa; -} {10 21 32 11 44 55 12 23 34} - finish_test Index: test/vacuum-into.test ================================================================== --- test/vacuum-into.test +++ test/vacuum-into.test @@ -24,40 +24,17 @@ return } forcedelete out.db do_execsql_test vacuum-into-100 { - CREATE TABLE t1( - a INTEGER PRIMARY KEY, - b ANY, - c INT AS (b+1), --- See "2024-04-09" block - CHECK( typeof(b)!='integer' OR b>a-5 ) --- comment below - ); + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) INSERT INTO t1(a,b) SELECT x, randomblob(600) FROM c; CREATE INDEX t1b ON t1(b); DELETE FROM t1 WHERE a%2; SELECT count(*), sum(a), sum(length(b)) FROM t1; } {50 2550 30000} - -# Update 2024-04-09 for forum post eec177d68fe7fa2c. -# -# VACUUM INTO is sensitive to tables holding both generated columns -# and CHECK constraints. -# -# CHECK constraints are ignored for read-only databases in order to save -# memory (see check-in 34ddf02d3d21151b on 2014-05-21). But the xfer -# optimization normally only works if CHECK constraints match between the -# source and destination tables. So the xfer optimization was not -# working for VACUUM INTO when the source was a read-only database and the -# table held CHECK constraints. But if the table has generated columns, -# then the xfer optimization is required or else VACUUM will raise an -# error. -# -# Fix this by ignoring CHECK constraints when determining whether or not -# the xfer optimization can run while doing VACUUM. - do_execsql_test vacuum-into-110 { VACUUM main INTO 'out.db'; } {} sqlite3 db2 out.db do_test vacuum-into-120 { @@ -109,25 +86,15 @@ VACUUM INTO target2() } {1 {no such function: target2}} # The ability to VACUUM INTO a read-only database db close -if {$tcl_platform(platform)=="windows"} { - file attributes test.db -readonly 1 -} else { - file attributes test.db -permissions 292 ;# 292 == 0444 -} sqlite3 db test.db -readonly 1 forcedelete test.db2 do_execsql_test vacuum-into-500 { VACUUM INTO 'test.db2'; } -if {$tcl_platform(platform)=="windows"} { - file attributes test.db -readonly 0 -} else { - file attributes test.db -permissions 420 ;# 420 = 0644 -} sqlite3 db2 test.db2 do_test vacuum-into-510 { db2 eval {SELECT name FROM sqlite_master ORDER BY 1} } {t1 t1b t2} db2 close Index: test/vt02.c ================================================================== --- test/vt02.c +++ test/vt02.c @@ -578,15 +578,12 @@ iBI = 1; } sqlite3_finalize(pStmt); } sqlite3RunSql(db,pVTab, - "INSERT INTO temp.\"%w\"(bi,vn,ix) VALUES(%d,'nConstraint',%d)" - "RETURNING iif(bi=%d,'ok',RAISE(ABORT,'wrong trigger'))", - /* The RETURNING clause checks to see that the returning trigger fired - ** for the correct INSERT in the case of nested INSERT RETURNINGs. */ - zLogTab, iBI, pInfo->nConstraint, iBI + "INSERT INTO temp.\"%w\"(bi,vn,ix) VALUES(%d,'nConstraint',%d)", + zLogTab, iBI, pInfo->nConstraint ); for(i=0; inConstraint; i++){ sqlite3_value *pVal; char *zSql; int iCol = pInfo->aConstraint[i].iColumn; Index: test/whereG.test ================================================================== --- test/whereG.test +++ test/whereG.test @@ -309,24 +309,10 @@ SELECT * FROM t0 WHERE unlikely(t0.rowid <= '0'); } {} do_execsql_test 8.10 { SELECT * FROM t0 WHERE likelihood(t0.rowid <= '0', 0.5); } {} -# Forum https://sqlite.org/forum/forumpost/45ec3d9788 -reset_db -do_execsql_test 8.11 { - CREATE TABLE t1(c0 INT); - INSERT INTO t1(c0) VALUES (NULL); - CREATE INDEX i46 ON t1(CAST( (c0 IS TRUE) AS TEXT)); - CREATE VIEW v0(c2) AS SELECT CAST( (c0 IS TRUE) AS TEXT ) FROM t1; -} -do_execsql_test 8.12 { - SELECT quote(c0), quote(c2) FROM t1, v0 WHERE (0 < LIKELY(v0.c2)); -} {NULL '0'} -do_execsql_test 8.13 { - SELECT quote(c0), quote(c2) FROM t1, v0 WHERE (0 < LIKELY(v0.c2)) IS TRUE; -} {NULL '0'} # 2019-12-31: assertion fault discovered by Yongheng's fuzzer. # Harmless memIsValid() due to the code generators failure to # release the registers used by OP_ResultRow. # Index: tool/mkctimec.tcl ================================================================== --- tool/mkctimec.tcl +++ tool/mkctimec.tcl @@ -5,17 +5,10 @@ # const char **azCompileOpt[] # # definition used in src/ctime.c, run this script from # the checkout root. It generates src/ctime.c . # -# Results are normally written into src/ctime.c. But if an argument is -# provided, results are written there instead. Examples: -# -# tclsh tool/mkctimec.tcl ;# <-- results to src/ctime.c -# -# tclsh tool/mkctimec.tcl /dev/tty ;# <-- results to the terminal -# set ::headWarning {/* DO NOT EDIT! ** This file is automatically generated by the script in the canonical ** SQLite source tree at tool/mkctimec.tcl. @@ -434,19 +427,14 @@ "$name=" CTIMEOPT_VAL2($v), #endif }] } -if {$argc>0} { - set destfile [lindex $argv 0] -} else { - set destfile "[file dir [file dir [file normal $argv0]]]/src/ctime.c" - puts "Overwriting $destfile..." -} - -if {[catch {set cfd [open $destfile w]}]!=0} { - puts stderr "File '$destfile' unwritable." +set ctime_c "src/ctime.c" + +if {[catch {set cfd [open $ctime_c w]}]!=0} { + puts stderr "File '$ctime_c' unwritable." exit 1; } puts $cfd $::headWarning; puts $cfd $::headCode; Index: tool/mkpragmatab.tcl ================================================================== --- tool/mkpragmatab.tcl +++ tool/mkpragmatab.tcl @@ -7,18 +7,10 @@ # to generate the ../src/pragma.h header file that contains macros and # the lookup table needed for pragma name lookup in the pragma.c module. # Then add the extra "case PragTyp_XXXXX:" and subsequent code for the # new pragma in ../src/pragma.c. # -# The results are normally written into the ../src/pragma.h file. However, -# if an alternative output file name is provided as an argument, then -# results are written into the alternative. For example: -# -# tclsh tool/mkpragmatab.tcl ;# <--- Results to src/pragma.h -# -# tclsh tool/mkpragmatab.tcl /dev/tty ;# <-- results to terminal -# # Flag meanings: set flagMeaning(NeedSchema) {Force schema load before running} set flagMeaning(ReadOnly) {Read-only HEADER_VALUE} set flagMeaning(Result0) {Acts as query when no argument} @@ -408,16 +400,12 @@ IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) } # Open the output file # -if {$argc>0} { - set destfile [lindex $argv 0] -} else { - set destfile "[file dir [file dir [file normal $argv0]]]/src/pragma.h" - puts "Overwriting $destfile with new pragma table..." -} +set destfile "[file dir [file dir [file normal $argv0]]]/src/pragma.h" +puts "Overwriting $destfile with new pragma table..." set fd [open $destfile wb] puts $fd {/* DO NOT EDIT! ** This file is automatically generated by the script at ** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit ** that script and rerun it. Index: tool/mksqlite3c.tcl ================================================================== --- tool/mksqlite3c.tcl +++ tool/mksqlite3c.tcl @@ -114,11 +114,11 @@ set vsrcprog ./src-verify } if {[file executable $vsrcprog] && [file readable $srcroot/manifest]} { set res [string trim [split [exec $vsrcprog -x $srcroot]] \n] puts $out "** The content in this amalgamation comes from Fossil check-in" - puts -nonewline $out "** [string range [lindex $res 0] 0 35]" + puts -nonewline $out "** [string range [lindex $res 0] 1 35]" if {[llength $res]==1} { puts $out "." } else { puts $out " with changes in files:\n**" foreach f [lrange $res 1 end] { Index: tool/mktoolzip.tcl ================================================================== --- tool/mktoolzip.tcl +++ tool/mktoolzip.tcl @@ -46,24 +46,14 @@ } default { set ARCH unk } } -set in [open [file join [file dirname [file dirname [info script]]] VERSION]] +set in [open VERSION] set vers [read $in] close $in scan $vers %d.%d.%d v1 v2 v3 set v2 [format 3%02d%02d00 $v2 $v3] set name sqlite-tools-$OS-$ARCH-$v2.zip - -if {$OS=="win32"} { - # The win32 tar.exe supports the -a ("auto-compress") option. This causes - # tar to create an archive type based on the extension of the output file. - # In this case, a zip file. - puts "tar -a -cf $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE" - puts [exec tar -a -cf $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE] - puts "$name: [file size $name] bytes" -} else { - puts "zip $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE" - puts [exec zip $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE] - puts [exec ls -l $name] -} +puts "zip $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE" +puts [exec zip $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE] +puts [exec ls -l $name] Index: tool/showwal.c ================================================================== --- tool/showwal.c +++ tool/showwal.c @@ -541,30 +541,19 @@ fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]); exit(1); } zPgSz[0] = 0; zPgSz[1] = 0; - fstat(fd, &sbuf); - if( sbuf.st_size<32 ){ - printf("%s: file too small to be a WAL - only %d bytes\n", - argv[1], (int)sbuf.st_size); - return 0; - } - if( lseek(fd, 8, SEEK_SET)!=8 ){ - printf("\"%s\" seems to not be a valid WAL file\n", argv[1]); - return 1; - } - if( read(fd, zPgSz, 4)!=4 ){ - printf("\"%s\": cannot read the page size\n", argv[1]); - return 1; - } + lseek(fd, 8, SEEK_SET); + read(fd, zPgSz, 4); pagesize = zPgSz[1]*65536 + zPgSz[2]*256 + zPgSz[3]; if( pagesize==0 ) pagesize = 1024; printf("Pagesize: %d\n", pagesize); - if( (pagesize & (pagesize-1))!=0 || pagesize<512 || pagesize>65536 ){ - printf("\"%s\": invalid page size.\n", argv[1]); - return 1; + fstat(fd, &sbuf); + if( sbuf.st_size<32 ){ + printf("file too small to be a WAL\n"); + return 0; } mxFrame = (sbuf.st_size - 32)/(pagesize + 24); printf("Available pages: 1..%d\n", mxFrame); if( argc==2 ){ int i; Index: tool/srctree-check.tcl ================================================================== --- tool/srctree-check.tcl +++ tool/srctree-check.tcl @@ -25,66 +25,55 @@ } # Find the root of the tree. # set ROOT [file dir [file dir [file normalize $argv0]]] +cd $ROOT # Name of the TCL interpreter # set TCLSH [info nameofexe] -# Number of errors seen. -# -set NERR 0 - ######################### autoconf/tea/configure.ac ########################### set confac [readfile $ROOT/autoconf/tea/configure.ac] set vers [readfile $ROOT/VERSION] set pattern {AC_INIT([sqlite],[} append pattern [string trim $vers] append pattern {])} if {[string first $pattern $confac]<=0} { puts "ERROR: ./autoconf/tea/configure.ac does not agree with ./VERSION" - puts "...... Fix: manually edit ./autoconf/tea/configure.ac to" - incr NERR + exit 1 } ######################### autoconf/Makefile.msc ############################### set f1 [readfile $ROOT/autoconf/Makefile.msc] -exec $TCLSH $ROOT/tool/mkmsvcmin.tcl $ROOT/Makefile.msc tmp1.txt -set f2 [readfile tmp1.txt] -file delete tmp1.txt +exec mv $ROOT/autoconf/Makefile.msc $ROOT/autoconf/Makefile.msc.tmp +exec $TCLSH $ROOT/tool/mkmsvcmin.tcl +set f2 [readfile $ROOT/autoconf/Makefile.msc] +exec mv $ROOT/autoconf/Makefile.msc.tmp $ROOT/autoconf/Makefile.msc if {$f1 != $f2} { puts "ERROR: ./autoconf/Makefile.msc does not agree with ./Makefile.msc" - puts "...... Fix: tclsh tool/mkmsvcmin.tcl" - incr NERR } ######################### src/pragma.h ######################################## set f1 [readfile $ROOT/src/pragma.h] -exec $TCLSH $ROOT/tool/mkpragmatab.tcl tmp2.txt -set f2 [readfile tmp2.txt] -file delete tmp2.txt +exec mv $ROOT/src/pragma.h $ROOT/src/pragma.h.tmp +exec $TCLSH $ROOT/tool/mkpragmatab.tcl +set f2 [readfile $ROOT/src/pragma.h] +exec mv $ROOT/src/pragma.h.tmp $ROOT/src/pragma.h if {$f1 != $f2} { puts "ERROR: ./src/pragma.h does not agree with ./tool/mkpragmatab.tcl" - puts "...... Fix: tclsh tool/mkpragmatab.tcl" - incr NERR } ######################### src/ctime.c ######################################## set f1 [readfile $ROOT/src/ctime.c] -exec $TCLSH $ROOT/tool/mkctimec.tcl tmp3.txt -set f2 [readfile tmp3.txt] -file delete tmp3.txt +exec mv $ROOT/src/ctime.c $ROOT/src/ctime.c.tmp +exec $TCLSH $ROOT/tool/mkctimec.tcl +set f2 [readfile $ROOT/src/ctime.c] +exec mv $ROOT/src/ctime.c.tmp $ROOT/src/ctime.c if {$f1 != $f2} { puts "ERROR: ./src/ctime.c does not agree with ./tool/mkctimec.tcl" - puts "..... Fix: tclsh tool/mkctimec.tcl" - incr NERR } - -# If any errors are seen, exit 1 so that the build will fail. -# -if {$NERR>0} {exit 1}