Update this branch with latest trunk changes.
FossilOrigin-Name: 9797482ded7de985e3b20aedec5e4d81f55065c8
This commit is contained in:
commit
062c267dff
@ -536,6 +536,12 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h
|
||||
-o $@ $(TOP)/src/shell.c libsqlite3.la \
|
||||
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
|
||||
|
||||
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
|
||||
|
||||
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
|
||||
|
||||
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) -rpath "$(libdir)"
|
||||
@ -1059,7 +1065,7 @@ install: sqlite3$(BEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_instal
|
||||
$(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir)
|
||||
|
||||
pkgIndex.tcl:
|
||||
echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3.so sqlite3]' > $@
|
||||
echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@
|
||||
tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
|
||||
$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
|
||||
$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
|
||||
|
68
Makefile.msc
68
Makefile.msc
@ -42,8 +42,8 @@ DYNAMIC_SHELL = 0
|
||||
#
|
||||
!IFNDEF NO_WARN
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4152 -wd4189 -wd4206 -wd4210
|
||||
NO_WARN = $(NO_WARN) -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
|
||||
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@ -115,6 +115,14 @@ USE_RC = 1
|
||||
FOR_WINRT = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to compile binaries suitable for the UAP environment.
|
||||
# This setting does not apply to any binaries that require Tcl to operate
|
||||
# properly (i.e. the text fixture, etc).
|
||||
#
|
||||
!IFNDEF FOR_UAP
|
||||
FOR_UAP = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to skip attempting to look for and/or link with the Tcl
|
||||
# runtime library.
|
||||
#
|
||||
@ -288,6 +296,11 @@ BCC = $(BCC) -FAcs
|
||||
#
|
||||
!IF $(USE_NATIVE_LIBPATHS)!=0
|
||||
NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
|
||||
|
||||
!IFDEF NUCRTLIBPATH
|
||||
NUCRTLIBPATH = $(NUCRTLIBPATH:\\=\)
|
||||
NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)"
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# C compiler and options for use in building executables that
|
||||
@ -312,12 +325,12 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src
|
||||
#
|
||||
!IF $(USE_STDCALL)!=0
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
!ELSE
|
||||
!IFNDEF PLATFORM
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
SHELL_CCONV_OPTS =
|
||||
@ -331,7 +344,7 @@ SHELL_CCONV_OPTS =
|
||||
# These are additional compiler options used for the core library.
|
||||
#
|
||||
!IFNDEF CORE_COMPILE_OPTS
|
||||
!IF $(USE_STDCALL)!=0
|
||||
!IF $(DYNAMIC_SHELL)!=0
|
||||
CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport)
|
||||
!ELSE
|
||||
CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
|
||||
@ -342,7 +355,7 @@ CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
|
||||
# when linking.
|
||||
#
|
||||
!IFNDEF CORE_LINK_DEP
|
||||
!IF $(USE_STDCALL)!=0
|
||||
!IF $(DYNAMIC_SHELL)!=0
|
||||
CORE_LINK_DEP =
|
||||
!ELSE
|
||||
CORE_LINK_DEP = sqlite3.def
|
||||
@ -352,7 +365,7 @@ CORE_LINK_DEP = sqlite3.def
|
||||
# These are additional linker options used for the core library.
|
||||
#
|
||||
!IFNDEF CORE_LINK_OPTS
|
||||
!IF $(USE_STDCALL)!=0
|
||||
!IF $(DYNAMIC_SHELL)!=0
|
||||
CORE_LINK_OPTS =
|
||||
!ELSE
|
||||
CORE_LINK_OPTS = /DEF:sqlite3.def
|
||||
@ -453,11 +466,13 @@ RCC = $(RCC) -I$(TOP)\ext\rtree
|
||||
# options are necessary in order to allow debugging symbols to
|
||||
# work correctly with Visual Studio when using the amalgamation.
|
||||
#
|
||||
!IFNDEF MKSQLITE3C_ARGS
|
||||
!IF $(DEBUG)>1
|
||||
MKSQLITE3C_ARGS = --linemacros
|
||||
!ELSE
|
||||
MKSQLITE3C_ARGS =
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
|
||||
# Omitting the define will cause extra debugging code to be inserted and
|
||||
@ -706,7 +721,7 @@ LTLIBOPTS = /NOLOGO
|
||||
#
|
||||
!IF $(FOR_WINRT)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
|
||||
!IF "$(VISUALSTUDIOVERSION)"=="12.0"
|
||||
!IF "$(VISUALSTUDIOVERSION)"=="12.0" || "$(VISUALSTUDIOVERSION)"=="14.0"
|
||||
!IFNDEF STORELIBPATH
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
STORELIBPATH = $(CRTLIBPATH)\store
|
||||
@ -750,6 +765,16 @@ LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelH
|
||||
LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
|
||||
!ENDIF
|
||||
|
||||
# When compiling for UAP, some extra linker options are also required.
|
||||
#
|
||||
!IF $(FOR_UAP)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib
|
||||
LTLINKOPTS = $(LTLINKOPTS) mincore.lib
|
||||
!IFDEF PSDKLIBPATH
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)"
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# If either debugging or symbols are enabled, enable PDBs.
|
||||
#
|
||||
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
|
||||
@ -1154,10 +1179,30 @@ sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \
|
||||
/link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) $(TOP)\tool\sqldiff.c sqlite3.c
|
||||
|
||||
fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) $(TOP)\tool\fuzzershell.c sqlite3.c
|
||||
|
||||
mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20
|
||||
MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20
|
||||
|
||||
mptest: mptester.exe
|
||||
del /Q mptest.db 2>NUL
|
||||
$(MPTEST1) --journalmode DELETE
|
||||
$(MPTEST2) --journalmode WAL
|
||||
$(MPTEST1) --journalmode WAL
|
||||
$(MPTEST2) --journalmode PERSIST
|
||||
$(MPTEST1) --journalmode PERSIST
|
||||
$(MPTEST2) --journalmode TRUNCATE
|
||||
$(MPTEST1) --journalmode TRUNCATE
|
||||
$(MPTEST2) --journalmode DELETE
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
# build on the target system. Some of the C source code and header
|
||||
@ -1594,6 +1639,9 @@ queryplantest: testfixture.exe sqlite3.exe
|
||||
test: testfixture.exe sqlite3.exe
|
||||
.\testfixture.exe $(TOP)\test\veryquick.test
|
||||
|
||||
smoketest: testfixture.exe
|
||||
.\testfixture.exe $(TOP)\test\main.test
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
|
||||
copy $(SQLITE3C) + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@
|
||||
echo static const char *tclsh_main_loop(void){ >> $@
|
||||
|
48
configure
vendored
48
configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.9.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.10.
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.8.9'
|
||||
PACKAGE_STRING='sqlite 3.8.9'
|
||||
PACKAGE_VERSION='3.8.10'
|
||||
PACKAGE_STRING='sqlite 3.8.10'
|
||||
PACKAGE_BUGREPORT=''
|
||||
|
||||
# Factoring default headers for most tests.
|
||||
@ -884,6 +884,7 @@ TCL_LIB_SPEC
|
||||
TCL_STUB_LIB_FILE
|
||||
TCL_STUB_LIB_FLAG
|
||||
TCL_STUB_LIB_SPEC
|
||||
TCL_SHLIB_SUFFIX
|
||||
HAVE_TCL
|
||||
TARGET_READLINE_LIBS
|
||||
TARGET_READLINE_INC
|
||||
@ -1480,7 +1481,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.8.9 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.8.10 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1545,7 +1546,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.9:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.10:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1659,7 +1660,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.8.9
|
||||
sqlite configure 3.8.10
|
||||
generated by GNU Autoconf 2.62
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@ -1673,7 +1674,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.8.9, which was
|
||||
It was created by sqlite $as_me 3.8.10, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -3724,13 +3725,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3727: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3728: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3730: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3731: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3733: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3734: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@ -4952,7 +4953,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 4955 "configure"' > conftest.$ac_ext
|
||||
echo '#line 4956 "configure"' > conftest.$ac_ext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@ -6821,11 +6822,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6824: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6825: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6828: \$? = $ac_status" >&5
|
||||
echo "$as_me:6829: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -7160,11 +7161,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7163: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7164: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7167: \$? = $ac_status" >&5
|
||||
echo "$as_me:7168: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -7265,11 +7266,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7268: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7269: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7272: \$? = $ac_status" >&5
|
||||
echo "$as_me:7273: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@ -7320,11 +7321,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7323: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7324: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7327: \$? = $ac_status" >&5
|
||||
echo "$as_me:7328: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@ -10133,7 +10134,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 10136 "configure"
|
||||
#line 10137 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -10229,7 +10230,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 10232 "configure"
|
||||
#line 10233 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -12827,6 +12828,7 @@ $as_echo "file not found" >&6; }
|
||||
|
||||
|
||||
|
||||
|
||||
fi
|
||||
fi
|
||||
if test "${use_tcl}" = "no" ; then
|
||||
@ -13951,7 +13953,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.8.9, which was
|
||||
This file was extended by sqlite $as_me 3.8.10, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -14004,7 +14006,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.8.9
|
||||
sqlite config.status 3.8.10
|
||||
configured by $0, generated by GNU Autoconf 2.62,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
@ -430,6 +430,7 @@ if test "${use_tcl}" = "yes" ; then
|
||||
AC_SUBST(TCL_STUB_LIB_FILE)
|
||||
AC_SUBST(TCL_STUB_LIB_FLAG)
|
||||
AC_SUBST(TCL_STUB_LIB_SPEC)
|
||||
AC_SUBST(TCL_SHLIB_SUFFIX)
|
||||
fi
|
||||
fi
|
||||
if test "${use_tcl}" = "no" ; then
|
||||
|
115
ext/fts3/fts3.c
115
ext/fts3/fts3.c
@ -313,6 +313,13 @@ static int fts3EvalStart(Fts3Cursor *pCsr);
|
||||
static int fts3TermSegReaderCursor(
|
||||
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# if defined(SQLITE_DEBUG)
|
||||
int sqlite3Fts3Always(int b) { assert( b ); return b; }
|
||||
int sqlite3Fts3Never(int b) { assert( !b ); return b; }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Write a 64-bit variable-length integer to memory starting at p[0].
|
||||
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
|
||||
@ -422,7 +429,7 @@ void sqlite3Fts3Dequote(char *z){
|
||||
/* If the first byte was a '[', then the close-quote character is a ']' */
|
||||
if( quote=='[' ) quote = ']';
|
||||
|
||||
while( ALWAYS(z[iIn]) ){
|
||||
while( z[iIn] ){
|
||||
if( z[iIn]==quote ){
|
||||
if( z[iIn+1]!=quote ) break;
|
||||
z[iOut++] = quote;
|
||||
@ -910,7 +917,7 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
|
||||
** This function is used when parsing the "prefix=" FTS4 parameter.
|
||||
*/
|
||||
static int fts3GobbleInt(const char **pp, int *pnOut){
|
||||
const MAX_NPREFIX = 10000000;
|
||||
const int MAX_NPREFIX = 10000000;
|
||||
const char *p; /* Iterator pointer */
|
||||
int nInt = 0; /* Output value */
|
||||
|
||||
@ -1019,7 +1026,8 @@ static int fts3ContentColumns(
|
||||
const char *zTbl, /* Name of content table */
|
||||
const char ***pazCol, /* OUT: Malloc'd array of column names */
|
||||
int *pnCol, /* OUT: Size of array *pazCol */
|
||||
int *pnStr /* OUT: Bytes of string content */
|
||||
int *pnStr, /* OUT: Bytes of string content */
|
||||
char **pzErr /* OUT: error message */
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
char *zSql; /* "SELECT *" statement on zTbl */
|
||||
@ -1030,6 +1038,9 @@ static int fts3ContentColumns(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
|
||||
@ -1108,7 +1119,7 @@ static int fts3InitVtab(
|
||||
const char **aCol; /* Array of column names */
|
||||
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
|
||||
|
||||
int nIndex; /* Size of aIndex[] array */
|
||||
int nIndex = 0; /* Size of aIndex[] array */
|
||||
struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
|
||||
|
||||
/* The results of parsing supported FTS4 key=value options: */
|
||||
@ -1281,7 +1292,7 @@ static int fts3InitVtab(
|
||||
if( nCol==0 ){
|
||||
sqlite3_free((void*)aCol);
|
||||
aCol = 0;
|
||||
rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
|
||||
rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr);
|
||||
|
||||
/* If a languageid= option was specified, remove the language id
|
||||
** column from the aCol[] array. */
|
||||
@ -2502,26 +2513,33 @@ static int fts3DoclistOrMerge(
|
||||
**
|
||||
** The right-hand input doclist is overwritten by this function.
|
||||
*/
|
||||
static void fts3DoclistPhraseMerge(
|
||||
static int fts3DoclistPhraseMerge(
|
||||
int bDescDoclist, /* True if arguments are desc */
|
||||
int nDist, /* Distance from left to right (1=adjacent) */
|
||||
char *aLeft, int nLeft, /* Left doclist */
|
||||
char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
|
||||
char **paRight, int *pnRight /* IN/OUT: Right/output doclist */
|
||||
){
|
||||
sqlite3_int64 i1 = 0;
|
||||
sqlite3_int64 i2 = 0;
|
||||
sqlite3_int64 iPrev = 0;
|
||||
char *aRight = *paRight;
|
||||
char *pEnd1 = &aLeft[nLeft];
|
||||
char *pEnd2 = &aRight[*pnRight];
|
||||
char *p1 = aLeft;
|
||||
char *p2 = aRight;
|
||||
char *p;
|
||||
int bFirstOut = 0;
|
||||
char *aOut = aRight;
|
||||
char *aOut;
|
||||
|
||||
assert( nDist>0 );
|
||||
|
||||
if( bDescDoclist ){
|
||||
aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
|
||||
if( aOut==0 ) return SQLITE_NOMEM;
|
||||
}else{
|
||||
aOut = aRight;
|
||||
}
|
||||
p = aOut;
|
||||
|
||||
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
|
||||
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
|
||||
|
||||
@ -2550,6 +2568,12 @@ static void fts3DoclistPhraseMerge(
|
||||
}
|
||||
|
||||
*pnRight = (int)(p - aOut);
|
||||
if( bDescDoclist ){
|
||||
sqlite3_free(aRight);
|
||||
*paRight = aOut;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2674,8 +2698,22 @@ static int fts3TermSelectMerge(
|
||||
){
|
||||
if( pTS->aaOutput[0]==0 ){
|
||||
/* If this is the first term selected, copy the doclist to the output
|
||||
** buffer using memcpy(). */
|
||||
pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
|
||||
** buffer using memcpy().
|
||||
**
|
||||
** Add FTS3_VARINT_MAX bytes of unused space to the end of the
|
||||
** allocation. This is so as to ensure that the buffer is big enough
|
||||
** to hold the current doclist AND'd with any other doclist. If the
|
||||
** doclists are stored in order=ASC order, this padding would not be
|
||||
** required (since the size of [doclistA AND doclistB] is always less
|
||||
** than or equal to the size of [doclistA] in that case). But this is
|
||||
** not true for order=DESC. For example, a doclist containing (1, -1)
|
||||
** may be smaller than (-1), as in the first example the -1 may be stored
|
||||
** as a single-byte delta, whereas in the second it must be stored as a
|
||||
** FTS3_VARINT_MAX byte varint.
|
||||
**
|
||||
** Similar padding is added in the fts3DoclistOrMerge() function.
|
||||
*/
|
||||
pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1);
|
||||
pTS->anOutput[0] = nDoclist;
|
||||
if( pTS->aaOutput[0] ){
|
||||
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
|
||||
@ -3421,11 +3459,31 @@ static void fts3ReversePoslist(char *pStart, char **ppPoslist){
|
||||
char *p = &(*ppPoslist)[-2];
|
||||
char c = 0;
|
||||
|
||||
/* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */
|
||||
while( p>pStart && (c=*p--)==0 );
|
||||
|
||||
/* Search backwards for a varint with value zero (the end of the previous
|
||||
** poslist). This is an 0x00 byte preceded by some byte that does not
|
||||
** have the 0x80 bit set. */
|
||||
while( p>pStart && (*p & 0x80) | c ){
|
||||
c = *p--;
|
||||
}
|
||||
if( p>pStart ){ p = &p[2]; }
|
||||
assert( p==pStart || c==0 );
|
||||
|
||||
/* At this point p points to that preceding byte without the 0x80 bit
|
||||
** set. So to find the start of the poslist, skip forward 2 bytes then
|
||||
** over a varint.
|
||||
**
|
||||
** Normally. The other case is that p==pStart and the poslist to return
|
||||
** is the first in the doclist. In this case do not skip forward 2 bytes.
|
||||
** The second part of the if condition (c==0 && *ppPoslist>&p[2])
|
||||
** is required for cases where the first byte of a doclist and the
|
||||
** doclist is empty. For example, if the first docid is 10, a doclist
|
||||
** that begins with:
|
||||
**
|
||||
** 0x0A 0x00 <next docid delta varint>
|
||||
*/
|
||||
if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; }
|
||||
while( *p++&0x80 );
|
||||
*ppPoslist = p;
|
||||
}
|
||||
@ -3496,6 +3554,8 @@ static void fts3SnippetFunc(
|
||||
}
|
||||
if( !zEllipsis || !zEnd || !zStart ){
|
||||
sqlite3_result_error_nomem(pContext);
|
||||
}else if( nToken==0 ){
|
||||
sqlite3_result_text(pContext, "", -1, SQLITE_STATIC);
|
||||
}else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
|
||||
sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
|
||||
}
|
||||
@ -3931,14 +3991,17 @@ static void fts3EvalAllocateReaders(
|
||||
** This function assumes that pList points to a buffer allocated using
|
||||
** sqlite3_malloc(). This function takes responsibility for eventually
|
||||
** freeing the buffer.
|
||||
**
|
||||
** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs.
|
||||
*/
|
||||
static void fts3EvalPhraseMergeToken(
|
||||
static int fts3EvalPhraseMergeToken(
|
||||
Fts3Table *pTab, /* FTS Table pointer */
|
||||
Fts3Phrase *p, /* Phrase to merge pList/nList into */
|
||||
int iToken, /* Token pList/nList corresponds to */
|
||||
char *pList, /* Pointer to doclist */
|
||||
int nList /* Number of bytes in pList */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
assert( iToken!=p->iDoclistToken );
|
||||
|
||||
if( pList==0 ){
|
||||
@ -3977,13 +4040,16 @@ static void fts3EvalPhraseMergeToken(
|
||||
nDiff = p->iDoclistToken - iToken;
|
||||
}
|
||||
|
||||
fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight);
|
||||
rc = fts3DoclistPhraseMerge(
|
||||
pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight
|
||||
);
|
||||
sqlite3_free(pLeft);
|
||||
p->doclist.aAll = pRight;
|
||||
p->doclist.nAll = nRight;
|
||||
}
|
||||
|
||||
if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4009,7 +4075,7 @@ static int fts3EvalPhraseLoad(
|
||||
char *pThis = 0;
|
||||
rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
|
||||
if( rc==SQLITE_OK ){
|
||||
fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
|
||||
rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
|
||||
}
|
||||
}
|
||||
assert( pToken->pSegcsr==0 );
|
||||
@ -4551,12 +4617,14 @@ static void fts3EvalStartReaders(
|
||||
){
|
||||
if( pExpr && SQLITE_OK==*pRc ){
|
||||
if( pExpr->eType==FTSQUERY_PHRASE ){
|
||||
int i;
|
||||
int nToken = pExpr->pPhrase->nToken;
|
||||
for(i=0; i<nToken; i++){
|
||||
if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
|
||||
if( nToken ){
|
||||
int i;
|
||||
for(i=0; i<nToken; i++){
|
||||
if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
|
||||
}
|
||||
pExpr->bDeferred = (i==nToken);
|
||||
}
|
||||
pExpr->bDeferred = (i==nToken);
|
||||
*pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
|
||||
}else{
|
||||
fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
|
||||
@ -4811,9 +4879,13 @@ static int fts3EvalSelectDeferred(
|
||||
char *pList = 0;
|
||||
rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
|
||||
assert( rc==SQLITE_OK || pList==0 );
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3EvalPhraseMergeToken(
|
||||
pTab, pTC->pPhrase, pTC->iToken,pList,nList
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int nCount;
|
||||
fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
|
||||
nCount = fts3DoclistCountDocids(
|
||||
pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
|
||||
);
|
||||
@ -5715,7 +5787,8 @@ int sqlite3Fts3EvalPhrasePoslist(
|
||||
pIter = pPhrase->pOrPoslist;
|
||||
iDocid = pPhrase->iOrDocid;
|
||||
if( pCsr->bDesc==bDescDoclist ){
|
||||
bEof = (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll));
|
||||
bEof = !pPhrase->doclist.nAll ||
|
||||
(pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll));
|
||||
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
|
||||
sqlite3Fts3DoclistNext(
|
||||
bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
|
||||
|
@ -134,6 +134,11 @@ SQLITE_EXTENSION_INIT3
|
||||
#ifdef SQLITE_COVERAGE_TEST
|
||||
# define ALWAYS(x) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif defined(SQLITE_DEBUG)
|
||||
# define ALWAYS(x) sqlite3Fts3Always((x)!=0)
|
||||
# define NEVER(x) sqlite3Fts3Never((x)!=0)
|
||||
int sqlite3Fts3Always(int b);
|
||||
int sqlite3Fts3Never(int b);
|
||||
#else
|
||||
# define ALWAYS(x) (x)
|
||||
# define NEVER(x) (x)
|
||||
|
@ -69,7 +69,7 @@ static void scalarFunc(
|
||||
if( argc==2 ){
|
||||
void *pOld;
|
||||
int n = sqlite3_value_bytes(argv[1]);
|
||||
if( n!=sizeof(pPtr) ){
|
||||
if( zName==0 || n!=sizeof(pPtr) ){
|
||||
sqlite3_result_error(context, "argument type mismatch", -1);
|
||||
return;
|
||||
}
|
||||
@ -80,7 +80,9 @@ static void scalarFunc(
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
pPtr = sqlite3Fts3HashFind(pHash, zName, nName);
|
||||
if( zName ){
|
||||
pPtr = sqlite3Fts3HashFind(pHash, zName, nName);
|
||||
}
|
||||
if( !pPtr ){
|
||||
char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
@ -277,9 +279,9 @@ static void testFunc(
|
||||
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
|
||||
|
||||
if( !p ){
|
||||
char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName);
|
||||
sqlite3_result_error(context, zErr2, -1);
|
||||
sqlite3_free(zErr2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -876,7 +876,7 @@ static fuzzer_stem *fuzzerNewStem(
|
||||
if( pNew==0 ) return 0;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
pNew->zBasis = (char*)&pNew[1];
|
||||
pNew->nBasis = (int)strlen(zWord);
|
||||
pNew->nBasis = (fuzzer_len)strlen(zWord);
|
||||
memcpy(pNew->zBasis, zWord, pNew->nBasis+1);
|
||||
pRule = pCur->pVtab->pRule;
|
||||
while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){
|
||||
|
21
main.mk
21
main.mk
@ -437,10 +437,31 @@ sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h
|
||||
$(TOP)/src/shell.c \
|
||||
libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
|
||||
|
||||
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
|
||||
$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\
|
||||
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) $(THREADLIB)
|
||||
|
||||
MPTEST1=./mptester$(EXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
|
||||
MPTEST2=./mptester$(EXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
|
||||
mptest: mptester$(EXE)
|
||||
rm -f mptest.db
|
||||
$(MPTEST1) --journalmode DELETE
|
||||
$(MPTEST2) --journalmode WAL
|
||||
$(MPTEST1) --journalmode WAL
|
||||
$(MPTEST2) --journalmode PERSIST
|
||||
$(MPTEST1) --journalmode PERSIST
|
||||
$(MPTEST2) --journalmode TRUNCATE
|
||||
$(MPTEST1) --journalmode TRUNCATE
|
||||
$(MPTEST2) --journalmode DELETE
|
||||
|
||||
sqlite3.o: sqlite3.c
|
||||
$(TCCX) -I. -c sqlite3.c
|
||||
|
||||
|
246
manifest
246
manifest
@ -1,12 +1,12 @@
|
||||
C Fix\sa\sproblem\sin\sfts5fault1.test.
|
||||
D 2015-04-21T20:13:38.631
|
||||
C Update\sthis\sbranch\swith\slatest\strunk\schanges.
|
||||
D 2015-04-22T09:40:35.867
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb
|
||||
F Makefile.in faaf75b89840659d74501bea269c7e33414761c1
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc cd626b52ebeec0e2c0dd929243bdd25b0df19a71
|
||||
F Makefile.msc 32d8fe89ac5c130f9f14293fb4a59b120895c943
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
|
||||
F VERSION 319eb1ced4b4d17a67730f2b7b85f15c1346cb60
|
||||
F VERSION 2e244662b71e6e68a5c29b014ebc5b7564f4cc5a
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@ -38,8 +38,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 613b220c2f2c7adcd50eb5ee4144ab581a150b47 x
|
||||
F configure.ac 6a8d145aea6d81f0b90013340780e43ed74fd5f4
|
||||
F configure 2ea5f5b58dd106da449ab598ab6e515339d7fa2a x
|
||||
F configure.ac 0b775d383c536bbaafc1e46dd3cbb81a7ea11aeb
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
@ -78,9 +78,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c e2c7e61d676ce7b9383d1078c9774a2f22947d57
|
||||
F ext/fts3/fts3.c 1b198ddb76cd706722dacbbaeb17a2fde6fca2cc
|
||||
F ext/fts3/fts3.h 62a77d880cf06a2865052726f8325c8fabcecad7
|
||||
F ext/fts3/fts3Int.h 394858c12a17740f7a1f6bd372c4606d4425a8d1
|
||||
F ext/fts3/fts3Int.h 3626655d6ba903a3919bb44e1c38e5f0f9d6be82
|
||||
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
|
||||
F ext/fts3/fts3_expr.c 40123785eaa3ebd4c45c9b23407cc44ac0c49905
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
@ -91,7 +91,7 @@ F ext/fts3/fts3_snippet.c 52c2dcf410b1f9af5a44d81a2cf8c68ed1cb5283
|
||||
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
|
||||
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
|
||||
F ext/fts3/fts3_tokenize_vtab.c becc661223db7898b213f9e8a23d75bac02408c9
|
||||
F ext/fts3/fts3_tokenizer.c 0f9e6e01de1e1fe2e79074e3cf70ed1b1ea848b7
|
||||
F ext/fts3/fts3_tokenizer.c 9afd223b07740b14dd589edd3116acacf951fd78
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
|
||||
@ -158,7 +158,7 @@ F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012
|
||||
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
|
||||
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c e3e18f47252c151b5553d7e806f38e757d37c4cc
|
||||
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
|
||||
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
@ -199,58 +199,58 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk e481861d67f0030e2c86ca947f4a7abaedaf696c
|
||||
F main.mk 0bdbbda2133675d0624b333f55e5d38a46ece577
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
|
||||
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
|
||||
F mptest/mptest.c 1e464f41f1bbc6578d6925043da56170f83aea96
|
||||
F mptest/mptest.c fca59f0a922e03f95ed17c44b1515ed37a841c81
|
||||
F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c d23d6b6991f66b383934f137fd4384d93fb98c81
|
||||
F src/analyze.c 91540f835163d5369ccbae78e2e6c74d0dd53c1d
|
||||
F src/attach.c 880f9b8641a829c563e52dd13c452ce457ae4dd8
|
||||
F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b
|
||||
F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae
|
||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c d4d52fb14e863cff9dbc7c746e9048ec0967a555
|
||||
F src/btree.c 127aceb71ba93f59bc9c6ba810e992a04299e98a
|
||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||
F src/btreeInt.h 2bfefc01875d8da066504c233ec259fcb3b2ef72
|
||||
F src/build.c 0419bba592c22f6d00e6d57a2ca7136720d02c1a
|
||||
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
||||
F src/build.c e246c2cea69c8f6fc825a156ea2de9dd4a17f18b
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463
|
||||
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
|
||||
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
|
||||
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
|
||||
F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
|
||||
F src/expr.c eb4d795abca1e876726aecc7aeb95ceb29e73fe7
|
||||
F src/expr.c 5555f768c05d7d4a7840c6c2e72ad7aecbe0fe54
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12
|
||||
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
|
||||
F src/func.c 1414c24c873c48796ad45942257a179a423ba42f
|
||||
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 5b9243a33726008cc4132897d2be371db12a13be
|
||||
F src/insert.c 8176ba5bad8fcef643558ca5708f33ed05a4035a
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
|
||||
F src/main.c 350c13b7a12bab4a502b361455ec3a0bba7b161c
|
||||
F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
|
||||
F src/main.c 43cb916046dc9dfde761380a764190a4a4223bc6
|
||||
F src/malloc.c 6a370b83d54e4bbf6f94021221c2a311cff26a18
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
|
||||
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
|
||||
F src/msvc.h e78002098966e39b2fd9915bd70b7bc3ec8398b7
|
||||
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
|
||||
F src/mutex.c 19bf9acba69ca2f367c3761080f8a9f0cf4670a8
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c 529bab0743c3321c940f32c3464de494fd38cfa9
|
||||
@ -261,32 +261,32 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
|
||||
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c cc903ecc6ebda90ef703d043ddaa7f33de0cab0f
|
||||
F src/os_win.c 8223e7db5b7c4a81d8b161098ac3959400434cdb
|
||||
F src/os_unix.c 5ed7e2e453c2980909a6b2c80dc55764b50819a8
|
||||
F src/os_win.c 03d27be3a20048ef52a648d5f0a15f5edda9f2a3
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c
|
||||
F src/pager.c 5283581c8ce8950ff483a0b3a3cab9cb4d25a21e
|
||||
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
|
||||
F src/parse.y 1299c66e7b1707322ccd8af43a359b8fb0d46d72
|
||||
F src/parse.y c4e0387bc88c8e21e5ba653e2578959a1f3cdbc7
|
||||
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
|
||||
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
|
||||
F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf
|
||||
F src/pragma.c ac4f3f856b4234e85f55b0f069698a4766011100
|
||||
F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9
|
||||
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
|
||||
F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f
|
||||
F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9
|
||||
F src/printf.c 8da9a2687a396daa19860f4dc90975d319304744
|
||||
F src/prepare.c 1fffbdcd6f8a0173a8f70d71f22528f4c0e1e3d3
|
||||
F src/printf.c 08fa675c200aac29e561c6153f91f909ed17612f
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c f4d79e31ffa5820c2e3d1740baa5e9b190425f2b
|
||||
F src/resolve.c 53486a98c17b7ae09b8c2b398013e973ce4c1aae
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 72ffb62e2879956302140e9f6e6ae88aee36b0e5
|
||||
F src/shell.c 9c1589c8271c04c02d23cdbc2c07bb40752fa9eb
|
||||
F src/sqlite.h.in c7c9111477b76c82c46bf851b619df4dd35cc095
|
||||
F src/select.c 35433ea8894ac42594ddc31eb0165a6d6401cfe5
|
||||
F src/shell.c 78eabce4c16c45e36fea2368f95118116399ba8a
|
||||
F src/sqlite.h.in ca27603a36fcacdaac5a19d8ee35aaff8ce8516f
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
F src/sqliteInt.h f2300529f3592323a98fd7acccec63d0e9082dc5
|
||||
F src/sqliteInt.h 8abcea1295138f10ef8f7ed38db5f1b573b93ece
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 81712116e826b0089bb221b018929536b2b5406f
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
|
||||
F src/tclsqlite.c a1c728bf8abe39b24ed16951c8e5ba004fe8803c
|
||||
F src/tclsqlite.c 3d89752d9a58039c2e82412a85387fe49eec6f72
|
||||
F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
|
||||
@ -312,12 +312,12 @@ F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
|
||||
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c b9495384e74923aefde8311de974bf9b0f5ba570
|
||||
F src/test_multiplex.c 97813565daa7ee480abcc5dd1e9984ed1f71eb8c
|
||||
F src/test_malloc.c 208f09a4e21defa496bc1094fcfadea19385a112
|
||||
F src/test_multiplex.c 4dfb159e5c280c0ebdbf8b5ab9d95bf2765061f9
|
||||
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
|
||||
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
|
||||
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
|
||||
F src/test_osinst.c 3d0340bc31a9f3d8a3547e0272373e80f78dde25
|
||||
F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10
|
||||
F src/test_osinst.c 5423dc1d355f594371f27dd292ca54bd320b8196
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c 180813f43683be5725458fc1ff13ac455d8e722d
|
||||
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
|
||||
@ -330,31 +330,31 @@ F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
|
||||
F src/test_vfs.c b7e6831e6fcf04c5090accff30640ec5c9630739
|
||||
F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
|
||||
F src/tokenize.c 05e52378c46efbc1fd63cbbbf7f3c555f840f4bf
|
||||
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
|
||||
F src/tokenize.c b7fb584c2be5ec39b6fdf04b185e7c6f33f8dc15
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
|
||||
F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec
|
||||
F src/vdbe.c bd793ed436edccaf264ec969ac92c9b5f4b41d64
|
||||
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
|
||||
F src/vdbeInt.h bb56fd199d8af1a2c1b9639ee2f70724b4338e3a
|
||||
F src/util.c a6431c92803b975b7322724a7b433e538d243539
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c f0cf3cf527d5a40b8d5d2324fdbb31da6c90cd8b
|
||||
F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d
|
||||
F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0
|
||||
F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75
|
||||
F src/vdbeaux.c 23390670e64f011f3fed8f38a2f25aaccacb74d2
|
||||
F src/vdbeaux.c 03591cca98ec50e1493043f0ff7abbece0b9c83d
|
||||
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
|
||||
F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9
|
||||
F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6
|
||||
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
|
||||
F src/vtab.c 6206db6ca9eff2e7f0076816a8ff8a3c0bfd7a7b
|
||||
F src/vdbemem.c b5256445b318b0f2b3bc429028469cfbb08f19a5
|
||||
F src/vdbesort.c 2e7f683464fd5db3be4beaa1ff2d39e24fcb64b8
|
||||
F src/vdbetrace.c f95c2dff9041fcf07f871789c22ebb0648ea0b7c
|
||||
F src/vtab.c fcbf338e0e8a91906aaf24bda8120e9f00cb4576
|
||||
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a
|
||||
F src/wal.c 753995db83247f20361a8e8a874990b21a75abd9
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c 85d832efa5ef57de542db7f430b72fecd3af8b38
|
||||
F src/where.c 32fe265e3dc74ef3b27deb9e6eb5fc3c71409612
|
||||
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@ -367,8 +367,8 @@ F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
|
||||
F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
F test/analyze3.test 75b9e42ea1e4edc919250450dc5762186965d4e6
|
||||
F test/analyze.test 3eb35a4af972f98422e5dc0586501b17d103d321
|
||||
F test/analyze3.test 0f0ee6135b293a0e5af471a8423b80b688469d71
|
||||
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
@ -387,7 +387,7 @@ F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
|
||||
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
|
||||
F test/atof1.test 08a61df9365c341f334a65f4348897312d8f3db7
|
||||
F test/attach.test 0d112b7713611fdf0340260192749737135fda5f
|
||||
F test/attach.test 437107943f14d131cf5efc2ae5305a94d7cb1d58
|
||||
F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
|
||||
F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27
|
||||
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
|
||||
@ -396,7 +396,7 @@ F test/auth.test 855233ef26eb3601b6886567ea4e326c72959360
|
||||
F test/auth2.test 264c6af53cad9aba5218c68bbe18036e39007bfa
|
||||
F test/auth3.test 5cfa94ed90c6617c42b7ba4b133fd79678b251c7
|
||||
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
|
||||
F test/autoindex1.test 7008c9f604141fdabe31b7bb95b5ff31b518251f
|
||||
F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
|
||||
F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8
|
||||
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
@ -431,6 +431,7 @@ F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45
|
||||
F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
|
||||
F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
|
||||
F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
|
||||
F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99
|
||||
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
|
||||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
@ -445,9 +446,9 @@ F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
|
||||
F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
|
||||
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
|
||||
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
|
||||
F test/collate1.test 7fcfe78f9613dc4a7e247d6bd27749955f108741
|
||||
F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846
|
||||
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
|
||||
F test/collate3.test 79558a286362cb9ed603c6fa543f1cda7f563f0f
|
||||
F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5
|
||||
F test/collate4.test f04d5168685f2eef637ecfa2d4ddf8ec0d600177
|
||||
F test/collate5.test 65d928034d30d2d263a80f6359f7549ee1598ec6
|
||||
F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907
|
||||
@ -472,15 +473,16 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
|
||||
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
|
||||
F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
|
||||
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
|
||||
F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb
|
||||
F test/corruptC.test 3fcc0f73d2cf2d69befe2d96332b942426a6aae2
|
||||
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
|
||||
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
|
||||
F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
|
||||
F test/corruptI.test 221ad8b7f0a9ac6b80fc577e73b5ad8cdea31243
|
||||
F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91
|
||||
F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318
|
||||
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
|
||||
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
|
||||
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
|
||||
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
|
||||
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
|
||||
@ -521,7 +523,7 @@ F test/e_expr.test 8f5fdd7261e2d746813b0c6a1c0e34824ad3c5ad
|
||||
F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707
|
||||
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||
F test/e_insert.test 0e63edc037afe738bb81a626a676811ed7862c90
|
||||
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
|
||||
F test/e_reindex.test 57d439f6c644befc8274ac93cf2f5449cf2736c1
|
||||
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
||||
F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
|
||||
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
@ -530,7 +532,7 @@ F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
|
||||
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
|
||||
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
|
||||
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
|
||||
F test/e_walauto.test ca70cf75c07a6cb1874ced101dd426da76625649
|
||||
F test/e_walauto.test 6544af03423abc61b53cfb976839385ddc2a0a70
|
||||
F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608
|
||||
F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
@ -544,13 +546,13 @@ F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
|
||||
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
|
||||
F test/expr.test c4b9bf0cc60b26862475e19999fbd2609ca8259c
|
||||
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
|
||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
|
||||
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
|
||||
F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b
|
||||
F test/fkey2.test 1db212cda86b0d3ce72714001f7b6381c321341c
|
||||
F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2
|
||||
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
F test/fkey5.test 56bcb5a6e8b725b17febc267fb041a6695e86853
|
||||
@ -596,7 +598,7 @@ F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
|
||||
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
|
||||
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
||||
F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
|
||||
F test/fts3aa.test edd20ddbbc5b6015ab340abf2ca278ae11ec387d
|
||||
F test/fts3aa.test 6c263a6f8845205ee02550981a94c2e8dc1e7058
|
||||
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
|
||||
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
|
||||
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
|
||||
@ -611,7 +613,7 @@ F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
|
||||
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
|
||||
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
|
||||
F test/fts3ao.test 3e4e3d5e75c076520341d0bdf4eb17c00e8cbde2
|
||||
F test/fts3atoken.test 95c721d71acb141eb754701b15a8e60bb6eb4263
|
||||
F test/fts3atoken.test e3a126365131a6db52efc20a9a6053cd44e5f289
|
||||
F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
|
||||
F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221
|
||||
F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
|
||||
@ -632,26 +634,27 @@ F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
|
||||
F test/fts3expr4.test e1be1248566f43c252d4404d52914f1fc4bfa065
|
||||
F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
|
||||
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
|
||||
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
|
||||
F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
|
||||
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
||||
F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e
|
||||
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
||||
F test/fts3prefix.test 9f68e3598a139c23ec47d09299420e0fc4c72a83
|
||||
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
|
||||
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
|
||||
F test/fts3query.test c838b18f2b859e15fd31c64be3d79ef1556803ca
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
|
||||
F test/fts3snippet.test 03c2f3be7d3b7c8bb105ed237f204833392bd57f
|
||||
F test/fts3snippet.test 63dbd687d5bf5191f1b8e6a0977aa9c1e28a7004
|
||||
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
|
||||
F test/fts3tok1.test c551043de056b0b1582a54e878991f57bad074bc
|
||||
F test/fts3tok1.test 178c050199af8c05299b1ad572514ce1c54b7827
|
||||
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
|
||||
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
|
||||
F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a
|
||||
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
|
||||
F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d
|
||||
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
||||
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
|
||||
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
|
||||
@ -678,11 +681,11 @@ F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/hexlit.test f9ecde8145bfc2341573473256c74ae37a200497
|
||||
F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67
|
||||
F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
|
||||
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
|
||||
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
|
||||
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
|
||||
F test/in.test b52fa96bcf6cebc5c8829c822315d0f87af9c6c2
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
|
||||
@ -700,18 +703,18 @@ F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
|
||||
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
|
||||
F test/index.test 4d990005a67a36984e4f1a5f1bdccea8d08da4ee
|
||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||
F test/index3.test 55a90cff99834305e8141df7afaef39674b57062
|
||||
F test/index3.test b6ec456cf3b81d9a32123fe7e449bde434db338b
|
||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||
F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e
|
||||
F test/index6.test 3ae54e53c53f2adcacda269237d8e52bdb05a481
|
||||
F test/index7.test 3d54dce09344c4530ea39a458aa304da044c887a
|
||||
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
|
||||
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
|
||||
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
|
||||
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
|
||||
F test/insert4.test 4791662c50518bdd37d394cae9a7a8014e845bb3
|
||||
F test/insert4.test a20432f1c0fbbcff8f11d0e6ab4acb8c9db58023
|
||||
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
|
||||
F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
|
||||
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
|
||||
@ -788,11 +791,11 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
|
||||
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
|
||||
F test/misc1.test 4864f2834b203cad7f688df8a5f725e4bab08029
|
||||
F test/misc1.test 783ba75743b2cf71e0f646bf540a6cef57264811
|
||||
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
|
||||
F test/misc5.test f96428ea95b3820aafc6f1c50cf48a09e4597ee1
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
|
||||
F test/misc8.test fc2754d38892f7dac30c22db3616c2764f117d66
|
||||
@ -813,10 +816,10 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
|
||||
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
|
||||
F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/orderby1.test eb246e377612b21a418fbea57047ba8ea88aaa6b
|
||||
F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
||||
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
||||
@ -839,11 +842,11 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 62ff8c49738c72a70b034ecc31957bee437f76ff
|
||||
F test/pragma.test ad99d05e411c7687302124be56f3b362204be041
|
||||
F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2
|
||||
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
|
||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/printf2.test b4acd4bf8734243257f01ddefa17c4fb090acc8a
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
|
||||
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
@ -857,7 +860,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl 13f401c10dd4fe1a2fb811ae6ed27fd7d1300d3c
|
||||
F test/releasetest.tcl a37cd82092c8be438255d65804b5951d6e3ecdae
|
||||
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
|
||||
@ -881,20 +884,20 @@ F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
|
||||
F test/schema5.test 29699b4421f183c8f0e88bd28ce7d75d13ea653e
|
||||
F test/securedel.test 21749c32ccc30f1ea9e4b9f33295a6521ec20fa0
|
||||
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test fc2a61f226a649393664ad54bc5376631801517c
|
||||
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test e20e8ce47b558de80616102ef273704cf0d48a3b
|
||||
F test/select4.test 48e14766d98b744b2202cca6d4679bf7ef3784c8
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
||||
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
|
||||
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
|
||||
F test/selectA.test 64b88a80271c1710966e50e633380696b60a12a4
|
||||
F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7
|
||||
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
|
||||
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
|
||||
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
|
||||
F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7
|
||||
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
|
||||
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
|
||||
F test/selectG.test e8600e379589e85e9fefd2fe4d44a4cdd63f6982
|
||||
F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
|
||||
@ -945,7 +948,7 @@ F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
|
||||
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
|
||||
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9
|
||||
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
|
||||
F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f
|
||||
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
@ -953,7 +956,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/table.test 06271d61eb13871490d38168433c1ef3dd82bb2a
|
||||
F test/table.test bd841e8df69b99172ce9c7d53587463913d711ca
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
|
||||
@ -1127,12 +1130,12 @@ F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
||||
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
|
||||
F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
|
||||
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
|
||||
F test/trigger7.test b39e6dee1debe0ff9c2ef66326668f149f07c9c4
|
||||
F test/trigger7.test 200dd51e728c9cdc20c72d99d9e9d45c667248f8
|
||||
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
||||
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
|
||||
F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
|
||||
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
|
||||
F test/triggerC.test a68980c5955d62ee24be6f97129d824f199f9a4c
|
||||
F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
|
||||
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
|
||||
F test/triggerE.test 355e9c5cbaed5cd039a60baad1fb2197caeb8e52
|
||||
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
|
||||
@ -1152,13 +1155,13 @@ F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
|
||||
F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
|
||||
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
|
||||
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
|
||||
F test/vtab1.test 1cef14310144718812351a61c5cfb4ba8494a171
|
||||
F test/vtab1.test d1e5ec7a818f1d3f0402382b6a1d0c06071b770f
|
||||
F test/vtab2.test 3644649aa8d1daac57fd541f6a5f914cac59203e
|
||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
||||
@ -1167,7 +1170,7 @@ F test/vtab6.test 5f5380c425e52993560ab4763db4f826d2ba7b09
|
||||
F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5
|
||||
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
|
||||
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
|
||||
F test/vtabA.test c86e1990b7e1e2bb34602a06fffa4c69f2b516dc
|
||||
F test/vtabA.test 1317f06a03597eee29f40a49b6c21e1aaba4285f
|
||||
F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796
|
||||
F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
|
||||
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
|
||||
@ -1189,7 +1192,7 @@ F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
|
||||
F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
|
||||
F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877
|
||||
F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434
|
||||
F test/walblock.test f1290524714232c109fb0b14db28f14d81c3ddd0
|
||||
F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d
|
||||
F test/walcksum.test 9afeb96240296c08c72fc524d199c912cfe34daa
|
||||
F test/walcrash.test 451d79e528add5c42764cea74aa2750754171b25
|
||||
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
|
||||
@ -1216,7 +1219,7 @@ F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
|
||||
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
|
||||
F test/whereD.test fd9120e262f9da3c45940f52aefeef4d15b904e5
|
||||
F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
||||
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
||||
@ -1227,9 +1230,9 @@ F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
F test/win32lock.test 71642fa56e9b06e5cfffe6bad67cb8c1eb2c555a
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/with1.test 9df5cd8a62148b3d9ef8597aea563e3863018bcd
|
||||
F test/with1.test a86bf7f9288ba759a25ee57221d3bffaca36032a
|
||||
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
|
||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||
F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151
|
||||
@ -1239,19 +1242,20 @@ F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
||||
F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862
|
||||
F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f
|
||||
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
|
||||
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
|
||||
F test/zeroblob.test fb3c0e4ab172d386954deda24c03f500e121d80d
|
||||
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
F tool/build-all-msvc.bat 62785b25bf7ea82dc016b3233a896151c786cfbb x
|
||||
F tool/build-all-msvc.bat 9058bd90a3c078a3d8c17d40e853aaa0f47885f4 x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
|
||||
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
|
||||
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
|
||||
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
|
||||
F tool/fuzzershell.c 00c12b1e95095f43980ae3cafb51938eda577fe2
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c 1864c4fe4a72b1bb28f1792b60504804fe82c5d2
|
||||
F tool/lemon.c b9109f59b57e7b6f101c4fe644c8361ba6dee969
|
||||
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/loadfts.c 76b6589ab5efcdc9cfe16d43ab5a6c2618e44bd4
|
||||
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
|
||||
@ -1260,19 +1264,20 @@ F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 94f196c9961e0ca3513e29f57125a3197808be2d
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 9ef48e1748dce7b844f67e2450ff9dfeb0fb4ab5
|
||||
F tool/mksqlite3c.tcl d7e4b042022fae78a70a8e64f534c1b22afd7c94
|
||||
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
|
||||
F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e
|
||||
F tool/mksqlite3c.tcl e3136f007fcdaac00c207306ef4b352ca87bf9af
|
||||
F tool/mksqlite3h.tcl 44730d586c9031638cdd2eb443b801c0d2dbd9f8
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
|
||||
F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/showdb.c 63cdef19e7fbca0c164b096ef8aef3bb9e9dd222
|
||||
F tool/showdb.c 3b5d335d537e4dc44d0c86967023819453c87dc6
|
||||
F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5
|
||||
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
|
||||
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
@ -1284,6 +1289,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/sqldiff.c 393b0f5b17ef29341664563a90d40ee63a0a18f7
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
|
||||
@ -1294,7 +1300,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P e50e8031d6f804ebe50e0eec9a8b6e7f0152ecc3
|
||||
R 60eea8ec1517faa88921988ca09638c5
|
||||
P a21d60cb2ac6463c012d82d1970d90da5da2a14a 2cb945116e7a5b78741b19839899826b539d5868
|
||||
R ce8dc868a2df13b90cea4f2e6b631af2
|
||||
U dan
|
||||
Z b632ef0339d92005d6b22a3d7746ce59
|
||||
Z da83630e09cb54023a2663ea2cafcf24
|
||||
|
@ -1 +1 @@
|
||||
a21d60cb2ac6463c012d82d1970d90da5da2a14a
|
||||
9797482ded7de985e3b20aedec5e4d81f55065c8
|
@ -72,7 +72,6 @@
|
||||
sub("\r","",name)
|
||||
op[name] = -1 # op[x] holds the numeric value for OP symbol x
|
||||
jump[name] = 0
|
||||
out2_prerelease[name] = 0
|
||||
in1[name] = 0
|
||||
in2[name] = 0
|
||||
in3[name] = 0
|
||||
@ -92,8 +91,6 @@
|
||||
sub(",","",x)
|
||||
if(x=="jump"){
|
||||
jump[name] = 1
|
||||
}else if(x=="out2-prerelease"){
|
||||
out2_prerelease[name] = 1
|
||||
}else if(x=="in1"){
|
||||
in1[name] = 1
|
||||
}else if(x=="in2"){
|
||||
@ -194,13 +191,12 @@ END {
|
||||
name = def[i]
|
||||
a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
|
||||
if( jump[name] ) a0 = 1;
|
||||
if( out2_prerelease[name] ) a1 = 2;
|
||||
if( in1[name] ) a2 = 4;
|
||||
if( in2[name] ) a3 = 8;
|
||||
if( in3[name] ) a4 = 16;
|
||||
if( out2[name] ) a5 = 32;
|
||||
if( out3[name] ) a6 = 64;
|
||||
bv[i] = a0+a1+a2+a3+a4+a5+a6+a7;
|
||||
if( in1[name] ) a2 = 2;
|
||||
if( in2[name] ) a3 = 4;
|
||||
if( in3[name] ) a4 = 8;
|
||||
if( out2[name] ) a5 = 16;
|
||||
if( out3[name] ) a6 = 32;
|
||||
bv[i] = a0+a1+a2+a3+a4+a5+a6;
|
||||
}
|
||||
print "\n"
|
||||
print "/* Properties such as \"out2\" or \"jump\" that are specified in"
|
||||
@ -208,12 +204,11 @@ END {
|
||||
print "** are encoded into bitvectors as follows:"
|
||||
print "*/"
|
||||
print "#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */"
|
||||
print "#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */"
|
||||
print "#define OPFLG_IN1 0x0004 /* in1: P1 is an input */"
|
||||
print "#define OPFLG_IN2 0x0008 /* in2: P2 is an input */"
|
||||
print "#define OPFLG_IN3 0x0010 /* in3: P3 is an input */"
|
||||
print "#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */"
|
||||
print "#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */"
|
||||
print "#define OPFLG_IN1 0x0002 /* in1: P1 is an input */"
|
||||
print "#define OPFLG_IN2 0x0004 /* in2: P2 is an input */"
|
||||
print "#define OPFLG_IN3 0x0008 /* in3: P3 is an input */"
|
||||
print "#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */"
|
||||
print "#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */"
|
||||
print "#define OPFLG_INITIALIZER {\\"
|
||||
for(i=0; i<=max; i++){
|
||||
if( i%8==0 ) printf("/* %3d */",i)
|
||||
|
@ -53,6 +53,13 @@
|
||||
# define GETPID getpid
|
||||
#endif
|
||||
|
||||
/* The directory separator character(s) */
|
||||
#if defined(_WIN32)
|
||||
# define isDirSep(c) (((c) == '/') || ((c) == '\\'))
|
||||
#else
|
||||
# define isDirSep(c) ((c) == '/')
|
||||
#endif
|
||||
|
||||
/* Mark a parameter as unused to suppress compiler warnings */
|
||||
#define UNUSED_PARAMETER(x) (void)x
|
||||
|
||||
@ -824,7 +831,7 @@ static void waitForClient(int iClient, int iTimeout, char *zErrPrefix){
|
||||
*/
|
||||
static char *filenameTail(char *z){
|
||||
int i, j;
|
||||
for(i=j=0; z[i]; i++) if( z[i]=='/' ) j = i+1;
|
||||
for(i=j=0; z[i]; i++) if( isDirSep(z[i]) ) j = i+1;
|
||||
return z+j;
|
||||
}
|
||||
|
||||
@ -1021,9 +1028,9 @@ static void runScript(
|
||||
char *zNewFile, *zNewScript;
|
||||
char *zToDel = 0;
|
||||
zNewFile = azArg[0];
|
||||
if( zNewFile[0]!='/' ){
|
||||
if( !isDirSep(zNewFile[0]) ){
|
||||
int k;
|
||||
for(k=(int)strlen(zFilename)-1; k>=0 && zFilename[k]!='/'; k--){}
|
||||
for(k=(int)strlen(zFilename)-1; k>=0 && !isDirSep(zFilename[k]); k--){}
|
||||
if( k>0 ){
|
||||
zNewFile = zToDel = sqlite3_mprintf("%.*s/%s", k,zFilename,zNewFile);
|
||||
}
|
||||
@ -1231,7 +1238,7 @@ static void usage(const char *argv0){
|
||||
int i;
|
||||
const char *zTail = argv0;
|
||||
for(i=0; argv0[i]; i++){
|
||||
if( argv0[i]=='/' ) zTail = argv0+i+1;
|
||||
if( isDirSep(argv0[i]) ) zTail = argv0+i+1;
|
||||
}
|
||||
fprintf(stderr,"Usage: %s DATABASE ?OPTIONS? ?SCRIPT?\n", zTail);
|
||||
exit(1);
|
||||
@ -1312,6 +1319,9 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
GETPID(), iClient);
|
||||
}else{
|
||||
if( g.iTrace>0 ){
|
||||
printf("BEGIN: %s", argv[0]);
|
||||
for(i=1; i<argc; i++) printf(" %s", argv[i]);
|
||||
printf("\n");
|
||||
printf("With SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\n" );
|
||||
for(i=0; (zCOption = sqlite3_compileoption_get(i))!=0; i++){
|
||||
printf("-DSQLITE_%s\n", zCOption);
|
||||
@ -1324,6 +1334,18 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
}
|
||||
rc = sqlite3_open_v2(g.zDbFile, &g.db, openFlags, g.zVfs);
|
||||
if( rc ) fatalError("cannot open [%s]", g.zDbFile);
|
||||
if( zJMode ){
|
||||
#if defined(_WIN32)
|
||||
if( sqlite3_stricmp(zJMode,"persist")==0
|
||||
|| sqlite3_stricmp(zJMode,"truncate")==0
|
||||
){
|
||||
printf("Changing journal mode to DELETE from %s", zJMode);
|
||||
zJMode = "DELETE";
|
||||
}
|
||||
#endif
|
||||
runSql("PRAGMA journal_mode=%Q;", zJMode);
|
||||
}
|
||||
if( !g.bSync ) trySql("PRAGMA synchronous=OFF");
|
||||
sqlite3_enable_load_extension(g.db, 1);
|
||||
sqlite3_busy_handler(g.db, busyHandler, 0);
|
||||
sqlite3_create_function(g.db, "vfsname", 0, SQLITE_UTF8, 0,
|
||||
@ -1332,7 +1354,6 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
evalFunc, 0, 0);
|
||||
g.iTimeout = DEFAULT_TIMEOUT;
|
||||
if( g.bSqlTrace ) sqlite3_trace(g.db, sqlTraceCallback, 0);
|
||||
if( !g.bSync ) trySql("PRAGMA synchronous=OFF");
|
||||
if( iClient>0 ){
|
||||
if( n>0 ) unrecognizedArguments(argv[0], n, argv+2);
|
||||
if( g.iTrace ) logMessage("start-client");
|
||||
@ -1355,7 +1376,6 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
fatalError("missing script filename");
|
||||
}
|
||||
if( n>1 ) unrecognizedArguments(argv[0], n, argv+2);
|
||||
if( zJMode ) runSql("PRAGMA journal_mode=%Q;", zJMode);
|
||||
runSql(
|
||||
"DROP TABLE IF EXISTS task;\n"
|
||||
"DROP TABLE IF EXISTS counters;\n"
|
||||
@ -1409,6 +1429,9 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
maybeClose(g.pErrLog);
|
||||
if( iClient==0 ){
|
||||
printf("Summary: %d errors out of %d tests\n", g.nError, g.nTest);
|
||||
printf("END: %s", argv[0]);
|
||||
for(i=1; i<argc; i++) printf(" %s", argv[i]);
|
||||
printf("\n");
|
||||
}
|
||||
return g.nError>0;
|
||||
}
|
||||
|
@ -1519,14 +1519,17 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
||||
z = argv[2];
|
||||
|
||||
if( pIndex ){
|
||||
tRowcnt *aiRowEst = 0;
|
||||
int nCol = pIndex->nKeyCol+1;
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(
|
||||
sizeof(tRowcnt) * nCol
|
||||
);
|
||||
if( aiRowEst==0 ) pInfo->db->mallocFailed = 1;
|
||||
#else
|
||||
tRowcnt * const aiRowEst = 0;
|
||||
/* Index.aiRowEst may already be set here if there are duplicate
|
||||
** sqlite_stat1 entries for this index. In that case just clobber
|
||||
** the old data with the new instead of allocating a new array. */
|
||||
if( pIndex->aiRowEst==0 ){
|
||||
pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol);
|
||||
if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1;
|
||||
}
|
||||
aiRowEst = pIndex->aiRowEst;
|
||||
#endif
|
||||
pIndex->bUnordered = 0;
|
||||
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
|
||||
|
@ -298,7 +298,7 @@ static void detachFunc(
|
||||
sqlite3BtreeClose(pDb->pBt);
|
||||
pDb->pBt = 0;
|
||||
pDb->pSchema = 0;
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
sqlite3CollapseDatabaseArray(db);
|
||||
return;
|
||||
|
||||
detach_error:
|
||||
@ -332,7 +332,6 @@ static void codeAttach(
|
||||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
|
||||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
|
||||
){
|
||||
pParse->nErr++;
|
||||
goto attach_end;
|
||||
}
|
||||
|
||||
|
145
src/btree.c
145
src/btree.c
@ -600,10 +600,15 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){
|
||||
static int saveCursorPosition(BtCursor *pCur){
|
||||
int rc;
|
||||
|
||||
assert( CURSOR_VALID==pCur->eState );
|
||||
assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState );
|
||||
assert( 0==pCur->pKey );
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
|
||||
if( pCur->eState==CURSOR_SKIPNEXT ){
|
||||
pCur->eState = CURSOR_VALID;
|
||||
}else{
|
||||
pCur->skipNext = 0;
|
||||
}
|
||||
rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
|
||||
assert( rc==SQLITE_OK ); /* KeySize() cannot fail */
|
||||
|
||||
@ -674,7 +679,7 @@ static int SQLITE_NOINLINE saveCursorsOnList(
|
||||
){
|
||||
do{
|
||||
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
|
||||
if( p->eState==CURSOR_VALID ){
|
||||
if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
|
||||
int rc = saveCursorPosition(p);
|
||||
if( SQLITE_OK!=rc ){
|
||||
return rc;
|
||||
@ -746,17 +751,19 @@ static int btreeMoveto(
|
||||
*/
|
||||
static int btreeRestoreCursorPosition(BtCursor *pCur){
|
||||
int rc;
|
||||
int skipNext;
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->eState>=CURSOR_REQUIRESEEK );
|
||||
if( pCur->eState==CURSOR_FAULT ){
|
||||
return pCur->skipNext;
|
||||
}
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext);
|
||||
rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_free(pCur->pKey);
|
||||
pCur->pKey = 0;
|
||||
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
|
||||
pCur->skipNext |= skipNext;
|
||||
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
|
||||
pCur->eState = CURSOR_SKIPNEXT;
|
||||
}
|
||||
@ -808,9 +815,10 @@ int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
|
||||
*pDifferentRow = 1;
|
||||
return rc;
|
||||
}
|
||||
if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
|
||||
if( pCur->eState!=CURSOR_VALID ){
|
||||
*pDifferentRow = 1;
|
||||
}else{
|
||||
assert( pCur->skipNext==0 );
|
||||
*pDifferentRow = 0;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
@ -1951,16 +1959,18 @@ int sqlite3BtreeOpen(
|
||||
*/
|
||||
if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
|
||||
if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
|
||||
int nFilename = sqlite3Strlen30(zFilename)+1;
|
||||
int nFullPathname = pVfs->mxPathname+1;
|
||||
char *zFullPathname = sqlite3Malloc(nFullPathname);
|
||||
char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename));
|
||||
MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
|
||||
|
||||
p->sharable = 1;
|
||||
if( !zFullPathname ){
|
||||
sqlite3_free(p);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( isMemdb ){
|
||||
memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
|
||||
memcpy(zFullPathname, zFilename, nFilename);
|
||||
}else{
|
||||
rc = sqlite3OsFullPathname(pVfs, zFilename,
|
||||
nFullPathname, zFullPathname);
|
||||
@ -2017,8 +2027,8 @@ int sqlite3BtreeOpen(
|
||||
** the right size. This is to guard against size changes that result
|
||||
** when compiling on a different architecture.
|
||||
*/
|
||||
assert( sizeof(i64)==8 || sizeof(i64)==4 );
|
||||
assert( sizeof(u64)==8 || sizeof(u64)==4 );
|
||||
assert( sizeof(i64)==8 );
|
||||
assert( sizeof(u64)==8 );
|
||||
assert( sizeof(u32)==4 );
|
||||
assert( sizeof(u16)==2 );
|
||||
assert( sizeof(Pgno)==4 );
|
||||
@ -3625,7 +3635,7 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
|
||||
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
|
||||
int i;
|
||||
if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
|
||||
if( p->eState==CURSOR_VALID ){
|
||||
if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
|
||||
rc = saveCursorPosition(p);
|
||||
if( rc!=SQLITE_OK ){
|
||||
(void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
|
||||
@ -4031,6 +4041,8 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
|
||||
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( pCur->iPage>=0 );
|
||||
assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
|
||||
assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
|
||||
getCellInfo(pCur);
|
||||
*pSize = pCur->info.nPayload;
|
||||
@ -4439,13 +4451,18 @@ static const void *fetchPayload(
|
||||
BtCursor *pCur, /* Cursor pointing to entry to read from */
|
||||
u32 *pAmt /* Write the number of available bytes here */
|
||||
){
|
||||
u32 amt;
|
||||
assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
|
||||
assert( pCur->info.nSize>0 );
|
||||
*pAmt = pCur->info.nLocal;
|
||||
assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
|
||||
assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
|
||||
amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload);
|
||||
if( pCur->info.nLocal<amt ) amt = pCur->info.nLocal;
|
||||
*pAmt = amt;
|
||||
return (void*)pCur->info.pPayload;
|
||||
}
|
||||
|
||||
@ -4509,7 +4526,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if SQLITE_DEBUG
|
||||
/*
|
||||
** Page pParent is an internal (non-leaf) tree page. This function
|
||||
** asserts that page number iChild is the left-child if the iIdx'th
|
||||
@ -4518,6 +4535,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
|
||||
** the page.
|
||||
*/
|
||||
static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
|
||||
if( CORRUPT_DB ) return; /* The conditions tested below might not be true
|
||||
** in a corrupt database */
|
||||
assert( iIdx<=pParent->nCell );
|
||||
if( iIdx==pParent->nCell ){
|
||||
assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild );
|
||||
@ -4542,19 +4561,11 @@ static void moveToParent(BtCursor *pCur){
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( pCur->iPage>0 );
|
||||
assert( pCur->apPage[pCur->iPage] );
|
||||
|
||||
/* UPDATE: It is actually possible for the condition tested by the assert
|
||||
** below to be untrue if the database file is corrupt. This can occur if
|
||||
** one cursor has modified page pParent while a reference to it is held
|
||||
** by a second cursor. Which can only happen if a single page is linked
|
||||
** into more than one b-tree structure in a corrupt database. */
|
||||
#if 0
|
||||
assertParentIndex(
|
||||
pCur->apPage[pCur->iPage-1],
|
||||
pCur->aiIdx[pCur->iPage-1],
|
||||
pCur->apPage[pCur->iPage]->pgno
|
||||
);
|
||||
#endif
|
||||
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
|
||||
|
||||
releasePage(pCur->apPage[pCur->iPage]);
|
||||
@ -6729,7 +6740,6 @@ static int balance_nonroot(
|
||||
}else if( iParentIdx==i ){
|
||||
nxDiv = i-2+bBulk;
|
||||
}else{
|
||||
assert( bBulk==0 );
|
||||
nxDiv = iParentIdx-1;
|
||||
}
|
||||
i = 2-bBulk;
|
||||
@ -7502,6 +7512,7 @@ static int balance(BtCursor *pCur){
|
||||
/* The next iteration of the do-loop balances the parent page. */
|
||||
releasePage(pPage);
|
||||
pCur->iPage--;
|
||||
assert( pCur->iPage>=0 );
|
||||
}
|
||||
}while( rc==SQLITE_OK );
|
||||
|
||||
@ -7978,9 +7989,13 @@ static int clearDatabasePage(
|
||||
if( pgno>btreePagecount(pBt) ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
|
||||
rc = getAndInitPage(pBt, pgno, &pPage, 0);
|
||||
if( rc ) return rc;
|
||||
if( pPage->bBusy ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto cleardatabasepage_out;
|
||||
}
|
||||
pPage->bBusy = 1;
|
||||
hdr = pPage->hdrOffset;
|
||||
for(i=0; i<pPage->nCell; i++){
|
||||
pCell = findCell(pPage, i);
|
||||
@ -8005,6 +8020,7 @@ static int clearDatabasePage(
|
||||
}
|
||||
|
||||
cleardatabasepage_out:
|
||||
pPage->bBusy = 0;
|
||||
releasePage(pPage);
|
||||
return rc;
|
||||
}
|
||||
@ -8512,6 +8528,57 @@ static void checkList(
|
||||
}
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
||||
/*
|
||||
** An implementation of a min-heap.
|
||||
**
|
||||
** aHeap[0] is the number of elements on the heap. aHeap[1] is the
|
||||
** root element. The daughter nodes of aHeap[N] are aHeap[N*2]
|
||||
** and aHeap[N*2+1].
|
||||
**
|
||||
** The heap property is this: Every node is less than or equal to both
|
||||
** of its daughter nodes. A consequence of the heap property is that the
|
||||
** root node aHeap[1] is always the minimum value current in the heap.
|
||||
**
|
||||
** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto
|
||||
** the heap, preserving the heap property. The btreeHeapPull() routine
|
||||
** removes the root element from the heap (the minimum value in the heap)
|
||||
** and then move other nodes around as necessary to preserve the heap
|
||||
** property.
|
||||
**
|
||||
** This heap is used for cell overlap and coverage testing. Each u32
|
||||
** entry represents the span of a cell or freeblock on a btree page.
|
||||
** The upper 16 bits are the index of the first byte of a range and the
|
||||
** lower 16 bits are the index of the last byte of that range.
|
||||
*/
|
||||
static void btreeHeapInsert(u32 *aHeap, u32 x){
|
||||
u32 j, i = ++aHeap[0];
|
||||
aHeap[i] = x;
|
||||
while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
|
||||
x = aHeap[j];
|
||||
aHeap[j] = aHeap[i];
|
||||
aHeap[i] = x;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
static int btreeHeapPull(u32 *aHeap, u32 *pOut){
|
||||
u32 j, i, x;
|
||||
if( (x = aHeap[0])==0 ) return 0;
|
||||
*pOut = aHeap[1];
|
||||
aHeap[1] = aHeap[x];
|
||||
aHeap[x] = 0xffffffff;
|
||||
aHeap[0]--;
|
||||
i = 1;
|
||||
while( (j = i*2)<=aHeap[0] ){
|
||||
if( aHeap[j]>aHeap[j+1] ) j++;
|
||||
if( aHeap[i]<aHeap[j] ) break;
|
||||
x = aHeap[i];
|
||||
aHeap[i] = aHeap[j];
|
||||
aHeap[j] = x;
|
||||
i = j;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
/*
|
||||
** Do various sanity checks on a single page of a tree. Return
|
||||
@ -8544,7 +8611,8 @@ static int checkTreePage(
|
||||
u8 *data;
|
||||
BtShared *pBt;
|
||||
int usableSize;
|
||||
char *hit = 0;
|
||||
u32 *heap = 0;
|
||||
u32 x, prev = 0;
|
||||
i64 nMinKey = 0;
|
||||
i64 nMaxKey = 0;
|
||||
const char *saved_zPfx = pCheck->zPfx;
|
||||
@ -8689,15 +8757,15 @@ static int checkTreePage(
|
||||
*/
|
||||
data = pPage->aData;
|
||||
hdr = pPage->hdrOffset;
|
||||
hit = sqlite3PageMalloc( pBt->pageSize );
|
||||
heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
|
||||
pCheck->zPfx = 0;
|
||||
if( hit==0 ){
|
||||
if( heap==0 ){
|
||||
pCheck->mallocFailed = 1;
|
||||
}else{
|
||||
int contentOffset = get2byteNotZero(&data[hdr+5]);
|
||||
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
memset(hit+contentOffset, 0, usableSize-contentOffset);
|
||||
memset(hit, 1, contentOffset);
|
||||
heap[0] = 0;
|
||||
btreeHeapInsert(heap, contentOffset-1);
|
||||
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
||||
** number of cells on the page. */
|
||||
nCell = get2byte(&data[hdr+3]);
|
||||
@ -8709,7 +8777,6 @@ static int checkTreePage(
|
||||
for(i=0; i<nCell; i++){
|
||||
int pc = get2byte(&data[cellStart+i*2]);
|
||||
u32 size = 65536;
|
||||
int j;
|
||||
if( pc<=usableSize-4 ){
|
||||
size = cellSizePtr(pPage, &data[pc]);
|
||||
}
|
||||
@ -8718,7 +8785,7 @@ static int checkTreePage(
|
||||
checkAppendMsg(pCheck,
|
||||
"Corruption detected in cell %d on page %d",i,iPage);
|
||||
}else{
|
||||
for(j=pc+size-1; j>=pc; j--) hit[j]++;
|
||||
btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
|
||||
}
|
||||
}
|
||||
/* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
|
||||
@ -8730,7 +8797,7 @@ static int checkTreePage(
|
||||
assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
size = get2byte(&data[i+2]);
|
||||
assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
for(j=i+size-1; j>=i; j--) hit[j]++;
|
||||
btreeHeapInsert(heap, (i<<16)|(i+size-1));
|
||||
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
|
||||
** big-endian integer which is the offset in the b-tree page of the next
|
||||
** freeblock in the chain, or zero if the freeblock is the last on the
|
||||
@ -8742,27 +8809,33 @@ static int checkTreePage(
|
||||
assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
i = j;
|
||||
}
|
||||
for(i=cnt=0; i<usableSize; i++){
|
||||
if( hit[i]==0 ){
|
||||
cnt++;
|
||||
}else if( hit[i]>1 ){
|
||||
cnt = 0;
|
||||
assert( heap[0]>0 );
|
||||
assert( (heap[1]>>16)==0 );
|
||||
btreeHeapPull(heap,&prev);
|
||||
while( btreeHeapPull(heap,&x) ){
|
||||
if( (prev&0xffff)+1>(x>>16) ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Multiple uses for byte %d of page %d", i, iPage);
|
||||
"Multiple uses for byte %u of page %d", x>>16, iPage);
|
||||
break;
|
||||
}else{
|
||||
cnt += (x>>16) - (prev&0xffff) - 1;
|
||||
prev = x;
|
||||
}
|
||||
}
|
||||
cnt += usableSize - (prev&0xffff) - 1;
|
||||
/* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
|
||||
** is stored in the fifth field of the b-tree page header.
|
||||
** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
|
||||
** number of fragmented free bytes within the cell content area.
|
||||
*/
|
||||
if( cnt!=data[hdr+7] ){
|
||||
if( heap[0]==0 && cnt!=data[hdr+7] ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Fragmentation of %d bytes reported as %d on page %d",
|
||||
cnt, data[hdr+7], iPage);
|
||||
}
|
||||
}
|
||||
sqlite3PageFree(hit);
|
||||
sqlite3PageFree(heap);
|
||||
releasePage(pPage);
|
||||
|
||||
end_of_check:
|
||||
|
@ -280,6 +280,7 @@ struct MemPage {
|
||||
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
|
||||
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
|
||||
u8 max1bytePayload; /* min(maxLocal,127) */
|
||||
u8 bBusy; /* Prevent endless loops on corrupt database files */
|
||||
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
|
||||
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
|
||||
u16 cellOffset; /* Index in aData of first cell pointer */
|
||||
|
23
src/build.c
23
src/build.c
@ -142,9 +142,11 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
|
||||
assert( pParse->pToplevel==0 );
|
||||
db = pParse->db;
|
||||
if( db->mallocFailed ) return;
|
||||
if( pParse->nested ) return;
|
||||
if( pParse->nErr ) return;
|
||||
if( db->mallocFailed || pParse->nErr ){
|
||||
if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Begin by generating some termination code at the end of the
|
||||
** vdbe program
|
||||
@ -226,7 +228,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
|
||||
/* Get the VDBE program ready for execution
|
||||
*/
|
||||
if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
|
||||
if( v && pParse->nErr==0 && !db->mallocFailed ){
|
||||
assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
|
||||
/* A minimum of one cursor is required if autoincrement is used
|
||||
* See ticket [a696379c1f08866] */
|
||||
@ -761,14 +763,12 @@ int sqlite3TwoPartName(
|
||||
if( ALWAYS(pName2!=0) && pName2->n>0 ){
|
||||
if( db->init.busy ) {
|
||||
sqlite3ErrorMsg(pParse, "corrupt database");
|
||||
pParse->nErr++;
|
||||
return -1;
|
||||
}
|
||||
*pUnqual = pName2;
|
||||
iDb = sqlite3FindDb(db, pName1);
|
||||
if( iDb<0 ){
|
||||
sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
|
||||
pParse->nErr++;
|
||||
return -1;
|
||||
}
|
||||
}else{
|
||||
@ -927,7 +927,7 @@ void sqlite3StartTable(
|
||||
if( !noErr ){
|
||||
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
|
||||
}else{
|
||||
assert( !db->init.busy );
|
||||
assert( !db->init.busy || CORRUPT_DB );
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
}
|
||||
goto begin_table_error;
|
||||
@ -1216,7 +1216,8 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){
|
||||
p = pParse->pNewTable;
|
||||
if( p==0 || NEVER(p->nCol<1) ) return;
|
||||
pCol = &p->aCol[p->nCol-1];
|
||||
assert( pCol->zType==0 );
|
||||
assert( pCol->zType==0 || CORRUPT_DB );
|
||||
sqlite3DbFree(pParse->db, pCol->zType);
|
||||
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
|
||||
pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
|
||||
}
|
||||
@ -2450,6 +2451,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
||||
}
|
||||
assert( pParse->nErr==0 );
|
||||
assert( pName->nSrc==1 );
|
||||
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
|
||||
if( noErr ) db->suppressErr++;
|
||||
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
|
||||
if( noErr ) db->suppressErr--;
|
||||
@ -2763,7 +2765,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
sqlite3ReleaseTempReg(pParse, regRecord);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
|
||||
@ -2856,8 +2859,7 @@ Index *sqlite3CreateIndex(
|
||||
char *zExtra = 0; /* Extra space after the Index object */
|
||||
Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
|
||||
|
||||
assert( pParse->nErr==0 ); /* Never called with prior errors */
|
||||
if( db->mallocFailed || IN_DECLARE_VTAB ){
|
||||
if( db->mallocFailed || IN_DECLARE_VTAB || pParse->nErr>0 ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
@ -3776,7 +3778,6 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
|
||||
void sqlite3SrcListShiftJoinType(SrcList *p){
|
||||
if( p ){
|
||||
int i;
|
||||
assert( p->a || p->nSrc==0 );
|
||||
for(i=p->nSrc-1; i>0; i--){
|
||||
p->a[i].jointype = p->a[i-1].jointype;
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ int sqlite3_complete(const char *zSql){
|
||||
int sqlite3_complete16(const void *zSql){
|
||||
sqlite3_value *pVal;
|
||||
char const *zSql8;
|
||||
int rc = SQLITE_NOMEM;
|
||||
int rc;
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
rc = sqlite3_initialize();
|
||||
|
@ -397,6 +397,7 @@ static void exprSetHeight(Expr *p){
|
||||
** Expr.flags.
|
||||
*/
|
||||
void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
|
||||
if( pParse->nErr ) return;
|
||||
exprSetHeight(p);
|
||||
sqlite3ExprCheckHeight(pParse, p->nHeight);
|
||||
}
|
||||
@ -1250,7 +1251,8 @@ u32 sqlite3ExprListFlags(const ExprList *pList){
|
||||
u32 m = 0;
|
||||
if( pList ){
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
m |= pList->a[i].pExpr->flags;
|
||||
Expr *pExpr = pList->a[i].pExpr;
|
||||
if( ALWAYS(pExpr) ) m |= pList->a[i].pExpr->flags;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
@ -1690,7 +1692,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
|
||||
** ephemeral table.
|
||||
*/
|
||||
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
|
||||
if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
|
||||
if( pParse->nErr==0 && isCandidateForInOpt(p) ){
|
||||
sqlite3 *db = pParse->db; /* Database connection */
|
||||
Table *pTab; /* Table <table>. */
|
||||
Expr *pExpr; /* Expression <column> */
|
||||
@ -2015,6 +2017,7 @@ int sqlite3CodeSubselect(
|
||||
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
|
||||
&sqlite3IntTokens[1]);
|
||||
pSel->iLimit = 0;
|
||||
pSel->selFlags &= ~SF_MultiValue;
|
||||
if( sqlite3Select(pParse, pSel, &dest) ){
|
||||
return 0;
|
||||
}
|
||||
@ -4015,7 +4018,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
|
||||
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
|
||||
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
|
||||
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
||||
if( ALWAYS((combinedFlags & EP_Reduced)==0) ){
|
||||
if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){
|
||||
if( pA->iColumn!=pB->iColumn ) return 2;
|
||||
if( pA->iTable!=pB->iTable
|
||||
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
|
||||
|
28
src/fkey.c
28
src/fkey.c
@ -1184,7 +1184,8 @@ static Trigger *fkActionTrigger(
|
||||
|
||||
iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
|
||||
assert( iFromCol>=0 );
|
||||
tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid";
|
||||
assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
|
||||
tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName;
|
||||
tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName;
|
||||
|
||||
tToCol.n = sqlite3Strlen30(tToCol.z);
|
||||
@ -1196,10 +1197,10 @@ static Trigger *fkActionTrigger(
|
||||
** parent table are used for the comparison. */
|
||||
pEq = sqlite3PExpr(pParse, TK_EQ,
|
||||
sqlite3PExpr(pParse, TK_DOT,
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
|
||||
sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
|
||||
, 0),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol)
|
||||
sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0)
|
||||
, 0);
|
||||
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
|
||||
|
||||
@ -1211,12 +1212,12 @@ static Trigger *fkActionTrigger(
|
||||
if( pChanges ){
|
||||
pEq = sqlite3PExpr(pParse, TK_IS,
|
||||
sqlite3PExpr(pParse, TK_DOT,
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
|
||||
0),
|
||||
sqlite3PExpr(pParse, TK_DOT,
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
|
||||
0),
|
||||
0);
|
||||
pWhen = sqlite3ExprAnd(db, pWhen, pEq);
|
||||
@ -1226,8 +1227,8 @@ static Trigger *fkActionTrigger(
|
||||
Expr *pNew;
|
||||
if( action==OE_Cascade ){
|
||||
pNew = sqlite3PExpr(pParse, TK_DOT,
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
|
||||
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
|
||||
, 0);
|
||||
}else if( action==OE_SetDflt ){
|
||||
Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
|
||||
@ -1274,13 +1275,12 @@ static Trigger *fkActionTrigger(
|
||||
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
|
||||
sizeof(Trigger) + /* struct Trigger */
|
||||
sizeof(TriggerStep) + /* Single step in trigger program */
|
||||
nFrom + 1 /* Space for pStep->target.z */
|
||||
nFrom + 1 /* Space for pStep->zTarget */
|
||||
);
|
||||
if( pTrigger ){
|
||||
pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
|
||||
pStep->target.z = (char *)&pStep[1];
|
||||
pStep->target.n = nFrom;
|
||||
memcpy((char *)pStep->target.z, zFrom, nFrom);
|
||||
pStep->zTarget = (char *)&pStep[1];
|
||||
memcpy((char *)pStep->zTarget, zFrom, nFrom);
|
||||
|
||||
pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
|
||||
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
|
||||
|
84
src/insert.c
84
src/insert.c
@ -342,20 +342,23 @@ static int xferOptimization(
|
||||
/*
|
||||
** This routine is called to handle SQL of the following forms:
|
||||
**
|
||||
** insert into TABLE (IDLIST) values(EXPRLIST)
|
||||
** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),...
|
||||
** insert into TABLE (IDLIST) select
|
||||
** insert into TABLE (IDLIST) default values
|
||||
**
|
||||
** The IDLIST following the table name is always optional. If omitted,
|
||||
** then a list of all columns for the table is substituted. The IDLIST
|
||||
** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted.
|
||||
** then a list of all (non-hidden) columns for the table is substituted.
|
||||
** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST
|
||||
** is omitted.
|
||||
**
|
||||
** The pList parameter holds EXPRLIST in the first form of the INSERT
|
||||
** statement above, and pSelect is NULL. For the second form, pList is
|
||||
** NULL and pSelect is a pointer to the select statement used to generate
|
||||
** data for the insert.
|
||||
** For the pSelect parameter holds the values to be inserted for the
|
||||
** first two forms shown above. A VALUES clause is really just short-hand
|
||||
** for a SELECT statement that omits the FROM clause and everything else
|
||||
** that follows. If the pSelect parameter is NULL, that means that the
|
||||
** DEFAULT VALUES form of the INSERT statement is intended.
|
||||
**
|
||||
** The code generated follows one of four templates. For a simple
|
||||
** insert with data coming from a VALUES clause, the code executes
|
||||
** insert with data coming from a single-row VALUES clause, the code executes
|
||||
** once straight down through. Pseudo-code follows (we call this
|
||||
** the "1st template"):
|
||||
**
|
||||
@ -462,7 +465,7 @@ void sqlite3Insert(
|
||||
u8 useTempTable = 0; /* Store SELECT results in intermediate table */
|
||||
u8 appendFlag = 0; /* True if the insert is likely to be an append */
|
||||
u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
|
||||
u8 bIdListInOrder = 1; /* True if IDLIST is in table order */
|
||||
u8 bIdListInOrder; /* True if IDLIST is in table order */
|
||||
ExprList *pList = 0; /* List of VALUES() to be inserted */
|
||||
|
||||
/* Register allocations */
|
||||
@ -487,8 +490,8 @@ void sqlite3Insert(
|
||||
}
|
||||
|
||||
/* If the Select object is really just a simple VALUES() list with a
|
||||
** single row values (the common case) then keep that one row of values
|
||||
** and go ahead and discard the Select object
|
||||
** single row (the common case) then keep that one row of values
|
||||
** and discard the other (unused) parts of the pSelect object
|
||||
*/
|
||||
if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
|
||||
pList = pSelect->pEList;
|
||||
@ -596,6 +599,7 @@ void sqlite3Insert(
|
||||
** is appears in the original table. (The index of the INTEGER
|
||||
** PRIMARY KEY in the original table is pTab->iPKey.)
|
||||
*/
|
||||
bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0;
|
||||
if( pColumn ){
|
||||
for(i=0; i<pColumn->nId; i++){
|
||||
pColumn->a[i].idx = -1;
|
||||
@ -631,7 +635,8 @@ void sqlite3Insert(
|
||||
** co-routine is the common header to the 3rd and 4th templates.
|
||||
*/
|
||||
if( pSelect ){
|
||||
/* Data is coming from a SELECT. Generate a co-routine to run the SELECT */
|
||||
/* Data is coming from a SELECT or from a multi-row VALUES clause.
|
||||
** Generate a co-routine to run the SELECT. */
|
||||
int regYield; /* Register holding co-routine entry-point */
|
||||
int addrTop; /* Top of the co-routine */
|
||||
int rc; /* Result code */
|
||||
@ -644,8 +649,7 @@ void sqlite3Insert(
|
||||
dest.nSdst = pTab->nCol;
|
||||
rc = sqlite3Select(pParse, pSelect, &dest);
|
||||
regFromSelect = dest.iSdst;
|
||||
assert( pParse->nErr==0 || rc );
|
||||
if( rc || db->mallocFailed ) goto insert_cleanup;
|
||||
if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
|
||||
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield);
|
||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||
assert( pSelect->pEList );
|
||||
@ -693,8 +697,8 @@ void sqlite3Insert(
|
||||
sqlite3ReleaseTempReg(pParse, regTempRowid);
|
||||
}
|
||||
}else{
|
||||
/* This is the case if the data for the INSERT is coming from a VALUES
|
||||
** clause
|
||||
/* This is the case if the data for the INSERT is coming from a
|
||||
** single-row VALUES clause
|
||||
*/
|
||||
NameContext sNC;
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
@ -1765,6 +1769,7 @@ static int xferOptimization(
|
||||
int onError, /* How to handle constraint errors */
|
||||
int iDbDest /* The database of pDest */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
ExprList *pEList; /* The result set of the SELECT */
|
||||
Table *pSrc; /* The table in the FROM clause of SELECT */
|
||||
Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
|
||||
@ -1912,11 +1917,11 @@ static int xferOptimization(
|
||||
** the extra complication to make this rule less restrictive is probably
|
||||
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
|
||||
*/
|
||||
if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
|
||||
if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if( (pParse->db->flags & SQLITE_CountRows)!=0 ){
|
||||
if( (db->flags & SQLITE_CountRows)!=0 ){
|
||||
return 0; /* xfer opt does not play well with PRAGMA count_changes */
|
||||
}
|
||||
|
||||
@ -1927,7 +1932,7 @@ static int xferOptimization(
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_xferopt_count++;
|
||||
#endif
|
||||
iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema);
|
||||
iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema);
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
sqlite3CodeVerifySchema(pParse, iDbSrc);
|
||||
iSrc = pParse->nTab++;
|
||||
@ -1937,14 +1942,18 @@ static int xferOptimization(
|
||||
regRowid = sqlite3GetTempReg(pParse);
|
||||
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
|
||||
assert( HasRowid(pDest) || destHasUniqueIdx );
|
||||
if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
|
||||
if( (db->flags & SQLITE_Vacuum)==0 && (
|
||||
(pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
|
||||
|| destHasUniqueIdx /* (2) */
|
||||
|| (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */
|
||||
){
|
||||
)){
|
||||
/* In some circumstances, we are able to run the xfer optimization
|
||||
** only if the destination table is initially empty. This code makes
|
||||
** that determination. Conditions under which the destination must
|
||||
** be empty:
|
||||
** only if the destination table is initially empty. Unless the
|
||||
** SQLITE_Vacuum flag is set, this block generates code to make
|
||||
** that determination. If SQLITE_Vacuum is set, then the destination
|
||||
** table is always empty.
|
||||
**
|
||||
** Conditions under which the destination must be empty:
|
||||
**
|
||||
** (1) There is no INTEGER PRIMARY KEY but there are indices.
|
||||
** (If the destination is not initially empty, the rowid fields
|
||||
@ -1987,6 +1996,7 @@ static int xferOptimization(
|
||||
sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName);
|
||||
}
|
||||
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
|
||||
u8 useSeekResult = 0;
|
||||
for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
|
||||
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
|
||||
}
|
||||
@ -2000,7 +2010,33 @@ static int xferOptimization(
|
||||
VdbeComment((v, "%s", pDestIdx->zName));
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
|
||||
if( db->flags & SQLITE_Vacuum ){
|
||||
/* This INSERT command is part of a VACUUM operation, which guarantees
|
||||
** that the destination table is empty. If all indexed columns use
|
||||
** collation sequence BINARY, then it can also be assumed that the
|
||||
** index will be populated by inserting keys in strictly sorted
|
||||
** order. In this case, instead of seeking within the b-tree as part
|
||||
** of every OP_IdxInsert opcode, an OP_Last is added before the
|
||||
** OP_IdxInsert to seek to the point within the b-tree where each key
|
||||
** should be inserted. This is faster.
|
||||
**
|
||||
** If any of the indexed columns use a collation sequence other than
|
||||
** BINARY, this optimization is disabled. This is because the user
|
||||
** might change the definition of a collation sequence and then run
|
||||
** a VACUUM command. In that case keys may not be written in strictly
|
||||
** sorted order. */
|
||||
for(i=0; i<pSrcIdx->nColumn; i++){
|
||||
char *zColl = pSrcIdx->azColl[i];
|
||||
assert( zColl!=0 );
|
||||
if( sqlite3_stricmp("BINARY", zColl) ) break;
|
||||
}
|
||||
if( i==pSrcIdx->nColumn ){
|
||||
useSeekResult = OPFLAG_USESEEKRESULT;
|
||||
sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
|
||||
sqlite3VdbeChangeP5(v, useSeekResult);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
|
||||
|
@ -65,7 +65,7 @@ int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
|
||||
** I/O active are written using this function. These messages
|
||||
** are intended for debugging activity only.
|
||||
*/
|
||||
/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0;
|
||||
SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -131,6 +131,11 @@ int sqlite3_initialize(void){
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the following assert() fails on some obscure processor/compiler
|
||||
** combination, the work-around is to set the correct pointer
|
||||
** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */
|
||||
assert( SQLITE_PTRSIZE==sizeof(char*) );
|
||||
|
||||
/* If SQLite is already completely initialized, then this call
|
||||
** to sqlite3_initialize() should be a no-op. But the initialization
|
||||
** must be complete. So isInit must not be set until the very end
|
||||
|
54
src/malloc.c
54
src/malloc.c
@ -75,6 +75,13 @@ static SQLITE_WSD struct Mem0Global {
|
||||
|
||||
#define mem0 GLOBAL(struct Mem0Global, mem0)
|
||||
|
||||
/*
|
||||
** Return the memory allocator mutex. sqlite3_status() needs it.
|
||||
*/
|
||||
sqlite3_mutex *sqlite3MallocMutex(void){
|
||||
return mem0.mutex;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine runs when the memory allocator sees that the
|
||||
** total memory allocation is about to exceed the soft heap
|
||||
@ -97,7 +104,7 @@ static int sqlite3MemoryAlarm(
|
||||
void *pArg,
|
||||
sqlite3_int64 iThreshold
|
||||
){
|
||||
int nUsed;
|
||||
sqlite3_int64 nUsed;
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
mem0.alarmCallback = xCallback;
|
||||
mem0.alarmArg = pArg;
|
||||
@ -155,6 +162,7 @@ void sqlite3_soft_heap_limit(int n){
|
||||
** Initialize the memory allocation subsystem.
|
||||
*/
|
||||
int sqlite3MallocInit(void){
|
||||
int rc;
|
||||
if( sqlite3GlobalConfig.m.xMalloc==0 ){
|
||||
sqlite3MemSetDefault();
|
||||
}
|
||||
@ -190,7 +198,9 @@ int sqlite3MallocInit(void){
|
||||
sqlite3GlobalConfig.szPage = 0;
|
||||
sqlite3GlobalConfig.nPage = 0;
|
||||
}
|
||||
return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
|
||||
rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
|
||||
if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -266,7 +276,7 @@ static int mallocWithAlarm(int n, void **pp){
|
||||
nFull = sqlite3GlobalConfig.m.xRoundup(n);
|
||||
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
|
||||
if( mem0.alarmCallback!=0 ){
|
||||
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
if( nUsed >= mem0.alarmThreshold - nFull ){
|
||||
mem0.nearlyFull = 1;
|
||||
sqlite3MallocAlarm(nFull);
|
||||
@ -283,8 +293,8 @@ static int mallocWithAlarm(int n, void **pp){
|
||||
#endif
|
||||
if( p ){
|
||||
nFull = sqlite3MallocSize(p);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
}
|
||||
*pp = p;
|
||||
return nFull;
|
||||
@ -361,14 +371,14 @@ void *sqlite3ScratchMalloc(int n){
|
||||
p = mem0.pScratchFree;
|
||||
mem0.pScratchFree = mem0.pScratchFree->pNext;
|
||||
mem0.nScratchFree--;
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
p = sqlite3Malloc(n);
|
||||
if( sqlite3GlobalConfig.bMemstat && p ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
|
||||
sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
|
||||
@ -409,19 +419,19 @@ void sqlite3ScratchFree(void *p){
|
||||
mem0.pScratchFree = pSlot;
|
||||
mem0.nScratchFree++;
|
||||
assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
/* Release memory back to the heap */
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
int iSize = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3GlobalConfig.m.xFree(p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
@ -452,7 +462,7 @@ int sqlite3MallocSize(void *p){
|
||||
}
|
||||
int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
if( db==0 ){
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
return sqlite3MallocSize(p);
|
||||
}else{
|
||||
@ -461,13 +471,13 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
return db->lookaside.sz;
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_uint64 sqlite3_msize(void *p){
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
@ -478,11 +488,11 @@ sqlite3_uint64 sqlite3_msize(void *p){
|
||||
void sqlite3_free(void *p){
|
||||
if( p==0 ) return; /* IMP: R-49053-54554 */
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p));
|
||||
sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3GlobalConfig.m.xFree(p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
@ -523,7 +533,7 @@ void sqlite3DbFree(sqlite3 *db, void *p){
|
||||
}
|
||||
}
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
sqlite3_free(p);
|
||||
@ -536,7 +546,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
int nOld, nNew, nDiff;
|
||||
void *pNew;
|
||||
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) );
|
||||
if( pOld==0 ){
|
||||
return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */
|
||||
}
|
||||
@ -570,7 +580,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
}
|
||||
if( pNew ){
|
||||
nNew = sqlite3MallocSize(pNew);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
||||
}
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
@ -703,7 +713,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
|
||||
}
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
pNew = sqlite3_realloc64(p, n);
|
||||
if( !pNew ){
|
||||
|
@ -20,6 +20,7 @@
|
||||
#pragma warning(disable : 4055)
|
||||
#pragma warning(disable : 4100)
|
||||
#pragma warning(disable : 4127)
|
||||
#pragma warning(disable : 4130)
|
||||
#pragma warning(disable : 4152)
|
||||
#pragma warning(disable : 4189)
|
||||
#pragma warning(disable : 4206)
|
||||
|
@ -91,6 +91,17 @@
|
||||
# include <sys/param.h>
|
||||
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
|
||||
|
||||
#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
|
||||
(__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
|
||||
# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
|
||||
&& (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
|
||||
# define HAVE_GETHOSTUUID 1
|
||||
# else
|
||||
# warning "gethostuuid() is disabled."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_VXWORKS
|
||||
# include <sys/ioctl.h>
|
||||
# include <semaphore.h>
|
||||
@ -1536,7 +1547,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
||||
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
|
||||
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
|
||||
azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared,
|
||||
osGetpid()));
|
||||
osGetpid(0)));
|
||||
|
||||
/* If there is already a lock of this type or more restrictive on the
|
||||
** unixFile, do nothing. Don't use the end_lock: exit path, as
|
||||
@ -1744,7 +1755,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||
assert( pFile );
|
||||
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
|
||||
osGetpid()));
|
||||
osGetpid(0)));
|
||||
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
if( pFile->eFileLock<=eFileLock ){
|
||||
@ -2171,7 +2182,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, osGetpid()));
|
||||
pFile->eFileLock, osGetpid(0)));
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
|
||||
/* no-op if possible */
|
||||
@ -2389,7 +2400,7 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, osGetpid()));
|
||||
pFile->eFileLock, osGetpid(0)));
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
|
||||
/* no-op if possible */
|
||||
@ -2557,7 +2568,7 @@ static int semXUnlock(sqlite3_file *id, int eFileLock) {
|
||||
assert( pFile );
|
||||
assert( pSem );
|
||||
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, osGetpid()));
|
||||
pFile->eFileLock, osGetpid(0)));
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
|
||||
/* no-op if possible */
|
||||
@ -2771,7 +2782,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
|
||||
assert( pFile );
|
||||
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
|
||||
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
|
||||
azFileLock(pInode->eFileLock), pInode->nShared , osGetpid()));
|
||||
azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0)));
|
||||
|
||||
/* If there is already a lock of this type or more restrictive on the
|
||||
** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
|
||||
@ -2957,7 +2968,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
||||
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()));
|
||||
osGetpid(0)));
|
||||
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
if( pFile->eFileLock<=eFileLock ){
|
||||
@ -3782,6 +3793,10 @@ static int unixGetTempname(int nBuf, char *zBuf);
|
||||
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_WAL_BLOCK: {
|
||||
/* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_LOCKSTATE: {
|
||||
*(int*)pArg = pFile->eFileLock;
|
||||
return SQLITE_OK;
|
||||
@ -4632,7 +4647,7 @@ static int unixShmLock(
|
||||
}
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
|
||||
p->id, osGetpid(), p->sharedMask, p->exclMask));
|
||||
p->id, osGetpid(0), p->sharedMask, p->exclMask));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -5727,8 +5742,8 @@ static int unixOpen(
|
||||
** the same instant might all reset the PRNG. But multiple resets
|
||||
** are harmless.
|
||||
*/
|
||||
if( randomnessPid!=osGetpid() ){
|
||||
randomnessPid = osGetpid();
|
||||
if( randomnessPid!=osGetpid(0) ){
|
||||
randomnessPid = osGetpid(0);
|
||||
sqlite3_randomness(0,0);
|
||||
}
|
||||
|
||||
@ -6119,7 +6134,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
|
||||
** tests repeatable.
|
||||
*/
|
||||
memset(zBuf, 0, nBuf);
|
||||
randomnessPid = osGetpid();
|
||||
randomnessPid = osGetpid(0);
|
||||
#if !defined(SQLITE_TEST)
|
||||
{
|
||||
int fd, got;
|
||||
@ -6440,7 +6455,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
|
||||
{
|
||||
if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
|
||||
OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
|
||||
lPath, errno, osGetpid()));
|
||||
lPath, errno, osGetpid(0)));
|
||||
return SQLITE_IOERR_LOCK;
|
||||
}
|
||||
len = strlcat(lPath, "sqliteplocks", maxLen);
|
||||
@ -6462,7 +6477,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
|
||||
}
|
||||
lPath[i+len]='\0';
|
||||
strlcat(lPath, ":auto:", maxLen);
|
||||
OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid()));
|
||||
OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid(0)));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@ -6489,7 +6504,7 @@ static int proxyCreateLockPath(const char *lockPath){
|
||||
if( err!=EEXIST ) {
|
||||
OSTRACE(("CREATELOCKPATH FAILED creating %s, "
|
||||
"'%s' proxy lock path=%s pid=%d\n",
|
||||
buf, strerror(err), lockPath, osGetpid()));
|
||||
buf, strerror(err), lockPath, osGetpid(0)));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -6498,7 +6513,7 @@ static int proxyCreateLockPath(const char *lockPath){
|
||||
}
|
||||
buf[i] = lockPath[i];
|
||||
}
|
||||
OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid()));
|
||||
OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid(0)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -6598,8 +6613,10 @@ int sqlite3_hostid_num = 0;
|
||||
|
||||
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
|
||||
|
||||
#ifdef HAVE_GETHOSTUUID
|
||||
/* Not always defined in the headers as it ought to be */
|
||||
extern int gethostuuid(uuid_t id, const struct timespec *wait);
|
||||
#endif
|
||||
|
||||
/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
|
||||
** bytes of writable memory.
|
||||
@ -6607,8 +6624,7 @@ extern int gethostuuid(uuid_t id, const struct timespec *wait);
|
||||
static int proxyGetHostID(unsigned char *pHostID, int *pError){
|
||||
assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
|
||||
memset(pHostID, 0, PROXY_HOSTIDLEN);
|
||||
# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
|
||||
(__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
|
||||
#ifdef HAVE_GETHOSTUUID
|
||||
{
|
||||
struct timespec timeout = {1, 0}; /* 1 sec timeout */
|
||||
if( gethostuuid(pHostID, &timeout) ){
|
||||
@ -6804,7 +6820,7 @@ static int proxyTakeConch(unixFile *pFile){
|
||||
|
||||
OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
|
||||
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
|
||||
osGetpid()));
|
||||
osGetpid(0)));
|
||||
|
||||
rc = proxyGetHostID(myHostID, &pError);
|
||||
if( (rc&0xff)==SQLITE_IOERR ){
|
||||
@ -7014,7 +7030,7 @@ static int proxyReleaseConch(unixFile *pFile){
|
||||
conchFile = pCtx->conchFile;
|
||||
OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
|
||||
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
|
||||
osGetpid()));
|
||||
osGetpid(0)));
|
||||
if( pCtx->conchHeld>0 ){
|
||||
rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
|
||||
}
|
||||
@ -7156,7 +7172,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
|
||||
}
|
||||
|
||||
OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
|
||||
(lockPath ? lockPath : ":auto:"), osGetpid()));
|
||||
(lockPath ? lockPath : ":auto:"), osGetpid(0)));
|
||||
|
||||
pCtx = sqlite3_malloc( sizeof(*pCtx) );
|
||||
if( pCtx==0 ){
|
||||
@ -7228,10 +7244,6 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
|
||||
*/
|
||||
static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_WAL_BLOCK: {
|
||||
id->ctrlFlags |= UNIXFILE_BLOCK;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
if( pFile->pMethod == &proxyIoMethods ){
|
||||
|
111
src/os_win.c
111
src/os_win.c
@ -197,8 +197,10 @@ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
|
||||
#endif /* SQLITE_OS_WINRT */
|
||||
|
||||
/*
|
||||
** This file mapping API is common to both Win32 and WinRT.
|
||||
** These file mapping APIs are common to both Win32 and WinRT.
|
||||
*/
|
||||
|
||||
WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T);
|
||||
WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
|
||||
#endif /* SQLITE_WIN32_FILEMAPPING_API */
|
||||
|
||||
@ -1083,6 +1085,15 @@ static struct win_syscall {
|
||||
#define osUuidCreateSequential \
|
||||
((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
|
||||
|
||||
#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
|
||||
{ "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
|
||||
#else
|
||||
{ "FlushViewOfFile", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osFlushViewOfFile \
|
||||
((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
|
||||
/*
|
||||
@ -1966,11 +1977,11 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
|
||||
/*
|
||||
** Log a I/O error retry episode.
|
||||
*/
|
||||
static void winLogIoerr(int nRetry){
|
||||
static void winLogIoerr(int nRetry, int lineno){
|
||||
if( nRetry ){
|
||||
sqlite3_log(SQLITE_IOERR,
|
||||
"delayed %dms for lock/sharing conflict",
|
||||
winIoerrRetryDelay*nRetry*(nRetry+1)/2
|
||||
sqlite3_log(SQLITE_NOTICE,
|
||||
"delayed %dms for lock/sharing conflict at line %d",
|
||||
winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2450,7 +2461,8 @@ static int winClose(sqlite3_file *id){
|
||||
assert( pFile->pShm==0 );
|
||||
#endif
|
||||
assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
|
||||
OSTRACE(("CLOSE file=%p\n", pFile->h));
|
||||
OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
winUnmapfile(pFile);
|
||||
@ -2479,7 +2491,8 @@ static int winClose(sqlite3_file *id){
|
||||
pFile->h = NULL;
|
||||
}
|
||||
OpenCounter(-1);
|
||||
OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
|
||||
OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed"));
|
||||
return rc ? SQLITE_OK
|
||||
: winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
|
||||
"winClose", pFile->zPath);
|
||||
@ -2507,7 +2520,8 @@ static int winRead(
|
||||
assert( amt>0 );
|
||||
assert( offset>=0 );
|
||||
SimulateIOError(return SQLITE_IOERR_READ);
|
||||
OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
|
||||
"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
|
||||
pFile->h, pBuf, amt, offset, pFile->locktype));
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
@ -2516,7 +2530,8 @@ static int winRead(
|
||||
if( offset<pFile->mmapSize ){
|
||||
if( offset+amt <= pFile->mmapSize ){
|
||||
memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
|
||||
OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
int nCopy = (int)(pFile->mmapSize - offset);
|
||||
@ -2530,7 +2545,8 @@ static int winRead(
|
||||
|
||||
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
if( winSeekFile(pFile, offset) ){
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_FULL;
|
||||
}
|
||||
while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
|
||||
@ -2544,19 +2560,22 @@ static int winRead(
|
||||
DWORD lastErrno;
|
||||
if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
|
||||
pFile->lastErrno = lastErrno;
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
|
||||
"winRead", pFile->zPath);
|
||||
}
|
||||
winLogIoerr(nRetry);
|
||||
winLogIoerr(nRetry, __LINE__);
|
||||
if( nRead<(DWORD)amt ){
|
||||
/* Unread parts of the buffer must be zero-filled */
|
||||
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@ -2579,7 +2598,8 @@ static int winWrite(
|
||||
SimulateIOError(return SQLITE_IOERR_WRITE);
|
||||
SimulateDiskfullError(return SQLITE_FULL);
|
||||
|
||||
OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
|
||||
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
|
||||
"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
|
||||
pFile->h, pBuf, amt, offset, pFile->locktype));
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
@ -2588,7 +2608,8 @@ static int winWrite(
|
||||
if( offset<pFile->mmapSize ){
|
||||
if( offset+amt <= pFile->mmapSize ){
|
||||
memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
|
||||
OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
int nCopy = (int)(pFile->mmapSize - offset);
|
||||
@ -2651,17 +2672,20 @@ static int winWrite(
|
||||
if( rc ){
|
||||
if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
|
||||
|| ( pFile->lastErrno==ERROR_DISK_FULL )){
|
||||
OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
|
||||
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return winLogError(SQLITE_FULL, pFile->lastErrno,
|
||||
"winWrite1", pFile->zPath);
|
||||
}
|
||||
OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
|
||||
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
|
||||
"winWrite2", pFile->zPath);
|
||||
}else{
|
||||
winLogIoerr(nRetry);
|
||||
winLogIoerr(nRetry, __LINE__);
|
||||
}
|
||||
OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@ -2675,8 +2699,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
|
||||
|
||||
assert( pFile );
|
||||
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
|
||||
OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
|
||||
pFile->h, nByte, pFile->locktype));
|
||||
OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));
|
||||
|
||||
/* If the user has configured a chunk-size for this file, truncate the
|
||||
** file so that it consists of an integer number of chunks (i.e. the
|
||||
@ -2708,7 +2732,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
|
||||
}
|
||||
#endif
|
||||
|
||||
OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
|
||||
OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc)));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2753,8 +2778,9 @@ static int winSync(sqlite3_file *id, int flags){
|
||||
*/
|
||||
SimulateDiskfullError( return SQLITE_FULL );
|
||||
|
||||
OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
|
||||
pFile->h, flags, pFile->locktype));
|
||||
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h, flags,
|
||||
pFile->locktype));
|
||||
|
||||
#ifndef SQLITE_TEST
|
||||
UNUSED_PARAMETER(flags);
|
||||
@ -2769,19 +2795,38 @@ static int winSync(sqlite3_file *id, int flags){
|
||||
** no-op
|
||||
*/
|
||||
#ifdef SQLITE_NO_SYNC
|
||||
OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
#else
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
if( pFile->pMapRegion ){
|
||||
if( osFlushViewOfFile(pFile->pMapRegion, 0) ){
|
||||
OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
|
||||
"rc=SQLITE_OK\n", osGetCurrentProcessId(),
|
||||
pFile, pFile->pMapRegion));
|
||||
}else{
|
||||
pFile->lastErrno = osGetLastError();
|
||||
OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
|
||||
"rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(),
|
||||
pFile, pFile->pMapRegion));
|
||||
return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
|
||||
"winSync1", pFile->zPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rc = osFlushFileBuffers(pFile->h);
|
||||
SimulateIOError( rc=FALSE );
|
||||
if( rc ){
|
||||
OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
pFile->lastErrno = osGetLastError();
|
||||
OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
|
||||
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
|
||||
"winSync", pFile->zPath);
|
||||
"winSync2", pFile->zPath);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -4752,7 +4797,7 @@ static int winOpen(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
winLogIoerr(cnt);
|
||||
winLogIoerr(cnt, __LINE__);
|
||||
|
||||
OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
|
||||
dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
|
||||
@ -4936,7 +4981,7 @@ static int winDelete(
|
||||
if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
|
||||
rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
|
||||
}else{
|
||||
winLogIoerr(cnt);
|
||||
winLogIoerr(cnt, __LINE__);
|
||||
}
|
||||
sqlite3_free(zConverted);
|
||||
OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
|
||||
@ -4986,7 +5031,7 @@ static int winAccess(
|
||||
attr = sAttrData.dwFileAttributes;
|
||||
}
|
||||
}else{
|
||||
winLogIoerr(cnt);
|
||||
winLogIoerr(cnt, __LINE__);
|
||||
if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
|
||||
sqlite3_free(zConverted);
|
||||
return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
|
||||
@ -5555,7 +5600,7 @@ int sqlite3_os_init(void){
|
||||
|
||||
/* Double-check that the aSyscall[] array has been constructed
|
||||
** correctly. See ticket [bb3a86e890c8e96ab] */
|
||||
assert( ArraySize(aSyscall)==79 );
|
||||
assert( ArraySize(aSyscall)==80 );
|
||||
|
||||
/* get memory map allocation granularity */
|
||||
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
|
||||
|
@ -3044,9 +3044,7 @@ static int pagerWalFrames(
|
||||
){
|
||||
int rc; /* Return code */
|
||||
int nList; /* Number of pages in pList */
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
|
||||
PgHdr *p; /* For looping over pages */
|
||||
#endif
|
||||
|
||||
assert( pPager->pWal );
|
||||
assert( pList );
|
||||
@ -3063,7 +3061,6 @@ static int pagerWalFrames(
|
||||
** any pages with page numbers greater than nTruncate into the WAL file.
|
||||
** They will never be read by any client. So remove them from the pDirty
|
||||
** list here. */
|
||||
PgHdr *p;
|
||||
PgHdr **ppNext = &pList;
|
||||
nList = 0;
|
||||
for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
|
||||
@ -3083,7 +3080,6 @@ static int pagerWalFrames(
|
||||
pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
|
||||
);
|
||||
if( rc==SQLITE_OK && pPager->pBackup ){
|
||||
PgHdr *p;
|
||||
for(p=pList; p; p=p->pDirty){
|
||||
sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
|
||||
}
|
||||
|
44
src/parse.y
44
src/parse.y
@ -409,28 +409,35 @@ cmd ::= select(X). {
|
||||
%type oneselect {Select*}
|
||||
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
|
||||
|
||||
select(A) ::= with(W) selectnowith(X). {
|
||||
Select *p = X, *pNext, *pLoop;
|
||||
if( p ){
|
||||
int cnt = 0, mxSelect;
|
||||
p->pWith = W;
|
||||
%include {
|
||||
/*
|
||||
** For a compound SELECT statement, make sure p->pPrior->pNext==p for
|
||||
** all elements in the list. And make sure list length does not exceed
|
||||
** SQLITE_LIMIT_COMPOUND_SELECT.
|
||||
*/
|
||||
static void parserDoubleLinkSelect(Parse *pParse, Select *p){
|
||||
if( p->pPrior ){
|
||||
u16 allValues = SF_Values;
|
||||
pNext = 0;
|
||||
Select *pNext = 0, *pLoop;
|
||||
int mxSelect, cnt = 0;
|
||||
for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
|
||||
pLoop->pNext = pNext;
|
||||
pLoop->selFlags |= SF_Compound;
|
||||
allValues &= pLoop->selFlags;
|
||||
}
|
||||
if( allValues ){
|
||||
p->selFlags |= SF_AllValues;
|
||||
}else if(
|
||||
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0
|
||||
&& cnt>mxSelect
|
||||
if( (p->selFlags & SF_MultiValue)==0 &&
|
||||
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
|
||||
cnt>mxSelect
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select(A) ::= with(W) selectnowith(X). {
|
||||
Select *p = X;
|
||||
if( p ){
|
||||
p->pWith = W;
|
||||
parserDoubleLinkSelect(pParse, p);
|
||||
}else{
|
||||
sqlite3WithDelete(pParse->db, W);
|
||||
}
|
||||
@ -445,12 +452,14 @@ selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). {
|
||||
SrcList *pFrom;
|
||||
Token x;
|
||||
x.n = 0;
|
||||
parserDoubleLinkSelect(pParse, pRhs);
|
||||
pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
|
||||
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0);
|
||||
}
|
||||
if( pRhs ){
|
||||
pRhs->op = (u8)Y;
|
||||
pRhs->pPrior = X;
|
||||
pRhs->selFlags &= ~SF_MultiValue;
|
||||
if( Y!=TK_ALL ) pParse->hasCompound = 1;
|
||||
}else{
|
||||
sqlite3SelectDelete(pParse->db, X);
|
||||
@ -498,13 +507,16 @@ values(A) ::= VALUES LP nexprlist(X) RP. {
|
||||
A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0);
|
||||
}
|
||||
values(A) ::= values(X) COMMA LP exprlist(Y) RP. {
|
||||
Select *pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values,0,0);
|
||||
Select *pRight, *pLeft = X;
|
||||
pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
|
||||
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
|
||||
if( pRight ){
|
||||
pRight->op = TK_ALL;
|
||||
pRight->pPrior = X;
|
||||
pLeft = X;
|
||||
pRight->pPrior = pLeft;
|
||||
A = pRight;
|
||||
}else{
|
||||
A = X;
|
||||
A = pLeft;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,6 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
|
||||
static void *pcache1Alloc(int nByte){
|
||||
void *p = 0;
|
||||
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
|
||||
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
if( nByte<=pcache1.szSlot ){
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
p = (PgHdr1 *)pcache1.pFree;
|
||||
@ -204,7 +203,8 @@ static void *pcache1Alloc(int nByte){
|
||||
pcache1.nFreeSlot--;
|
||||
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
|
||||
assert( pcache1.nFreeSlot>=0 );
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
}
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
}
|
||||
@ -217,7 +217,8 @@ static void *pcache1Alloc(int nByte){
|
||||
if( p ){
|
||||
int sz = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
|
||||
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
}
|
||||
#endif
|
||||
@ -235,7 +236,7 @@ static int pcache1Free(void *p){
|
||||
if( p>=pcache1.pStart && p<pcache1.pEnd ){
|
||||
PgFreeslot *pSlot;
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
pSlot = (PgFreeslot*)p;
|
||||
pSlot->pNext = pcache1.pFree;
|
||||
pcache1.pFree = pSlot;
|
||||
@ -249,7 +250,7 @@ static int pcache1Free(void *p){
|
||||
nFreed = sqlite3MallocSize(p);
|
||||
#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
|
||||
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed);
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
#endif
|
||||
sqlite3_free(p);
|
||||
@ -986,6 +987,14 @@ void sqlite3PCacheSetDefault(void){
|
||||
*/
|
||||
int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
|
||||
|
||||
/*
|
||||
** Return the global mutex used by this PCACHE implementation. The
|
||||
** sqlite3_status() routine needs access to this mutex.
|
||||
*/
|
||||
sqlite3_mutex *sqlite3Pcache1Mutex(void){
|
||||
return pcache1.mutex;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
/*
|
||||
** This function is called to free superfluous dynamically allocated memory
|
||||
|
18
src/pragma.c
18
src/pragma.c
@ -164,15 +164,15 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
|
||||
*/
|
||||
static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
int mem = ++pParse->nMem;
|
||||
int nMem = ++pParse->nMem;
|
||||
i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value));
|
||||
if( pI64 ){
|
||||
memcpy(pI64, &value, sizeof(value));
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64);
|
||||
sqlite3VdbeAddOp4(v, OP_Int64, 0, nMem, 0, (char*)pI64, P4_INT64);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -337,11 +337,11 @@ void sqlite3Pragma(
|
||||
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( aFcntl[0] ){
|
||||
int mem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0);
|
||||
int nMem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, nMem, 0, aFcntl[0], 0);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1);
|
||||
sqlite3_free(aFcntl[0]);
|
||||
}
|
||||
goto pragma_out;
|
||||
@ -946,7 +946,9 @@ void sqlite3Pragma(
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"Safety level may not be changed inside a transaction");
|
||||
}else{
|
||||
pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
|
||||
int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
|
||||
if( iLevel==0 ) iLevel = 1;
|
||||
pDb->safety_level = iLevel;
|
||||
setAllPagerFlags(db);
|
||||
}
|
||||
}
|
||||
@ -1041,7 +1043,7 @@ void sqlite3Pragma(
|
||||
}else if( pPk==0 ){
|
||||
k = 1;
|
||||
}else{
|
||||
for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
|
||||
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
|
||||
|
@ -67,7 +67,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
||||
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
|
||||
if( argv[1]==0 ){
|
||||
corruptSchema(pData, argv[0], 0);
|
||||
}else if( argv[2] && argv[2][0] ){
|
||||
}else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
|
||||
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
|
||||
** But because db->init.busy is set to 1, no VDBE code is generated
|
||||
** or executed. All the parser does is build the internal data
|
||||
@ -98,8 +98,8 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}else if( argv[0]==0 ){
|
||||
corruptSchema(pData, 0, 0);
|
||||
}else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
|
||||
corruptSchema(pData, argv[0], 0);
|
||||
}else{
|
||||
/* If the SQL column is blank it means this is an index that
|
||||
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
|
||||
|
34
src/printf.c
34
src/printf.c
@ -261,15 +261,19 @@ void sqlite3VXPrintf(
|
||||
}
|
||||
if( width<0 ){
|
||||
flag_leftjustify = 1;
|
||||
width = -width;
|
||||
width = width >= -2147483647 ? -width : 0;
|
||||
}
|
||||
c = *++fmt;
|
||||
}else{
|
||||
unsigned wx = 0;
|
||||
while( c>='0' && c<='9' ){
|
||||
width = width*10 + c - '0';
|
||||
wx = wx*10 + c - '0';
|
||||
c = *++fmt;
|
||||
}
|
||||
testcase( wx>0x7fffffff );
|
||||
width = wx & 0x7fffffff;
|
||||
}
|
||||
|
||||
/* Get the precision */
|
||||
if( c=='.' ){
|
||||
precision = 0;
|
||||
@ -280,13 +284,18 @@ void sqlite3VXPrintf(
|
||||
}else{
|
||||
precision = va_arg(ap,int);
|
||||
}
|
||||
if( precision<0 ) precision = -precision;
|
||||
c = *++fmt;
|
||||
if( precision<0 ){
|
||||
precision = precision >= -2147483647 ? -precision : -1;
|
||||
}
|
||||
}else{
|
||||
unsigned px = 0;
|
||||
while( c>='0' && c<='9' ){
|
||||
precision = precision*10 + c - '0';
|
||||
px = px*10 + c - '0';
|
||||
c = *++fmt;
|
||||
}
|
||||
testcase( px>0x7fffffff );
|
||||
precision = px & 0x7fffffff;
|
||||
}
|
||||
}else{
|
||||
precision = -1;
|
||||
@ -450,7 +459,8 @@ void sqlite3VXPrintf(
|
||||
else prefix = 0;
|
||||
}
|
||||
if( xtype==etGENERIC && precision>0 ) precision--;
|
||||
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
|
||||
testcase( precision>0xfff );
|
||||
for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
|
||||
if( xtype==etFLOAT ) realvalue += rounder;
|
||||
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
|
||||
exp = 0;
|
||||
@ -505,8 +515,9 @@ void sqlite3VXPrintf(
|
||||
}else{
|
||||
e2 = exp;
|
||||
}
|
||||
if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
|
||||
bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
|
||||
if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){
|
||||
bufpt = zExtra
|
||||
= sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
|
||||
if( bufpt==0 ){
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
return;
|
||||
@ -738,7 +749,7 @@ void sqlite3VXPrintf(
|
||||
*/
|
||||
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
char *zNew;
|
||||
assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
|
||||
assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
|
||||
if( p->accError ){
|
||||
testcase(p->accError==STRACCUM_TOOBIG);
|
||||
testcase(p->accError==STRACCUM_NOMEM);
|
||||
@ -787,7 +798,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
** Append N copies of character c to the given string buffer.
|
||||
*/
|
||||
void sqlite3AppendChar(StrAccum *p, int N, char c){
|
||||
if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
|
||||
testcase( p->nChar + (i64)N > 0x7fffffff );
|
||||
if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
|
||||
return;
|
||||
}
|
||||
while( (N--)>0 ) p->zText[p->nChar++] = c;
|
||||
}
|
||||
|
||||
@ -812,7 +826,7 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
|
||||
** size of the memory allocation for StrAccum if necessary.
|
||||
*/
|
||||
void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
assert( z!=0 );
|
||||
assert( z!=0 || N==0 );
|
||||
assert( p->zText!=0 || p->nChar==0 || p->accError );
|
||||
assert( N>=0 );
|
||||
assert( p->accError==0 || p->nAlloc==0 );
|
||||
|
@ -993,9 +993,11 @@ static int resolveCompoundOrderBy(
|
||||
if( pItem->pExpr==pE ){
|
||||
pItem->pExpr = pNew;
|
||||
}else{
|
||||
assert( pItem->pExpr->op==TK_COLLATE );
|
||||
assert( pItem->pExpr->pLeft==pE );
|
||||
pItem->pExpr->pLeft = pNew;
|
||||
Expr *pParent = pItem->pExpr;
|
||||
assert( pParent->op==TK_COLLATE );
|
||||
while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
|
||||
assert( pParent->pLeft==pE );
|
||||
pParent->pLeft = pNew;
|
||||
}
|
||||
sqlite3ExprDelete(db, pE);
|
||||
pItem->u.x.iOrderByCol = (u16)iCol;
|
||||
@ -1186,6 +1188,20 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
sqlite3ResolveExprNames(&sNC, p->pOffset) ){
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
/* If the SF_Converted flags is set, then this Select object was
|
||||
** was created by the convertCompoundSelectToSubquery() function.
|
||||
** In this case the ORDER BY clause (p->pOrderBy) should be resolved
|
||||
** as if it were part of the sub-query, not the parent. This block
|
||||
** moves the pOrderBy down to the sub-query. It will be moved back
|
||||
** after the names have been resolved. */
|
||||
if( p->selFlags & SF_Converted ){
|
||||
Select *pSub = p->pSrc->a[0].pSelect;
|
||||
assert( p->pSrc->nSrc==1 && p->pOrderBy );
|
||||
assert( pSub->pPrior && pSub->pOrderBy==0 );
|
||||
pSub->pOrderBy = p->pOrderBy;
|
||||
p->pOrderBy = 0;
|
||||
}
|
||||
|
||||
/* Recursively resolve names in all subqueries
|
||||
*/
|
||||
@ -1268,12 +1284,30 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
sNC.pNext = 0;
|
||||
sNC.ncFlags |= NC_AllowAgg;
|
||||
|
||||
/* If this is a converted compound query, move the ORDER BY clause from
|
||||
** the sub-query back to the parent query. At this point each term
|
||||
** within the ORDER BY clause has been transformed to an integer value.
|
||||
** These integers will be replaced by copies of the corresponding result
|
||||
** set expressions by the call to resolveOrderGroupBy() below. */
|
||||
if( p->selFlags & SF_Converted ){
|
||||
Select *pSub = p->pSrc->a[0].pSelect;
|
||||
p->pOrderBy = pSub->pOrderBy;
|
||||
pSub->pOrderBy = 0;
|
||||
}
|
||||
|
||||
/* Process the ORDER BY clause for singleton SELECT statements.
|
||||
** The ORDER BY clause for compounds SELECT statements is handled
|
||||
** below, after all of the result-sets for all of the elements of
|
||||
** the compound have been resolved.
|
||||
**
|
||||
** If there is an ORDER BY clause on a term of a compound-select other
|
||||
** than the right-most term, then that is a syntax error. But the error
|
||||
** is not detected until much later, and so we need to go ahead and
|
||||
** resolve those symbols on the incorrect ORDER BY for consistency.
|
||||
*/
|
||||
if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
|
||||
if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
|
||||
&& resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
|
||||
){
|
||||
return WRC_Abort;
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
|
44
src/select.c
44
src/select.c
@ -111,7 +111,6 @@ Select *sqlite3SelectNew(
|
||||
Select standin;
|
||||
sqlite3 *db = pParse->db;
|
||||
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
|
||||
assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */
|
||||
if( pNew==0 ){
|
||||
assert( db->mallocFailed );
|
||||
pNew = &standin;
|
||||
@ -131,7 +130,7 @@ Select *sqlite3SelectNew(
|
||||
pNew->op = TK_SELECT;
|
||||
pNew->pLimit = pLimit;
|
||||
pNew->pOffset = pOffset;
|
||||
assert( pOffset==0 || pLimit!=0 );
|
||||
assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
|
||||
pNew->addrOpenEphm[0] = -1;
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
if( db->mallocFailed ) {
|
||||
@ -1381,7 +1380,7 @@ static const char *columnTypeImpl(
|
||||
** of the SELECT statement. Return the declaration type and origin
|
||||
** data for the result-set column of the sub-select.
|
||||
*/
|
||||
if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
|
||||
if( iCol>=0 && iCol<pS->pEList->nExpr ){
|
||||
/* 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.
|
||||
@ -1701,12 +1700,14 @@ static void selectAddColumnTypeAndCollation(
|
||||
a = pSelect->pEList->a;
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
p = a[i].pExpr;
|
||||
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
|
||||
if( pCol->zType==0 ){
|
||||
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
|
||||
}
|
||||
szAll += pCol->szEst;
|
||||
pCol->affinity = sqlite3ExprAffinity(p);
|
||||
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
|
||||
pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
if( pColl ){
|
||||
if( pColl && pCol->zColl==0 ){
|
||||
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
|
||||
}
|
||||
}
|
||||
@ -2108,8 +2109,7 @@ static int multiSelectValues(
|
||||
int nExpr = p->pEList->nExpr;
|
||||
int nRow = 1;
|
||||
int rc = 0;
|
||||
assert( p->pNext==0 );
|
||||
assert( p->selFlags & SF_AllValues );
|
||||
assert( p->selFlags & SF_MultiValue );
|
||||
do{
|
||||
assert( p->selFlags & SF_Values );
|
||||
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
|
||||
@ -2218,7 +2218,7 @@ static int multiSelect(
|
||||
|
||||
/* Special handling for a compound-select that originates as a VALUES clause.
|
||||
*/
|
||||
if( p->selFlags & SF_AllValues ){
|
||||
if( p->selFlags & SF_MultiValue ){
|
||||
rc = multiSelectValues(pParse, p, &dest);
|
||||
goto multi_select_end;
|
||||
}
|
||||
@ -2629,7 +2629,7 @@ static int generateOutputSubroutine(
|
||||
** of the scan loop.
|
||||
*/
|
||||
case SRT_Mem: {
|
||||
assert( pIn->nSdst==1 );
|
||||
assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 );
|
||||
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
|
||||
/* The LIMIT clause will jump out of the loop for us */
|
||||
break;
|
||||
@ -2644,7 +2644,7 @@ static int generateOutputSubroutine(
|
||||
pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst);
|
||||
pDest->nSdst = pIn->nSdst;
|
||||
}
|
||||
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst);
|
||||
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst);
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
|
||||
break;
|
||||
}
|
||||
@ -2860,8 +2860,10 @@ static int multiSelectOrderBy(
|
||||
if( aPermute ){
|
||||
struct ExprList_item *pItem;
|
||||
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
|
||||
assert( pItem->u.x.iOrderByCol>0
|
||||
&& pItem->u.x.iOrderByCol<=p->pEList->nExpr );
|
||||
assert( pItem->u.x.iOrderByCol>0 );
|
||||
/* assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ) is also true
|
||||
** but only for well-formed SELECT statements. */
|
||||
testcase( pItem->u.x.iOrderByCol > p->pEList->nExpr );
|
||||
aPermute[i] = pItem->u.x.iOrderByCol - 1;
|
||||
}
|
||||
pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
|
||||
@ -3071,7 +3073,7 @@ static int multiSelectOrderBy(
|
||||
/*** TBD: Insert subroutine calls to close cursors on incomplete
|
||||
**** subqueries ****/
|
||||
explainComposite(pParse, p->op, iSub1, iSub2, 0);
|
||||
return SQLITE_OK;
|
||||
return pParse->nErr!=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3883,7 +3885,10 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
|
||||
pNew->pOrderBy = 0;
|
||||
p->pPrior = 0;
|
||||
p->pNext = 0;
|
||||
p->pWith = 0;
|
||||
p->selFlags &= ~SF_Compound;
|
||||
assert( (p->selFlags & SF_Converted)==0 );
|
||||
p->selFlags |= SF_Converted;
|
||||
assert( pNew->pPrior!=0 );
|
||||
pNew->pPrior->pNext = pNew;
|
||||
pNew->pLimit = 0;
|
||||
@ -4419,7 +4424,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
}
|
||||
w.xSelectCallback = selectExpander;
|
||||
if( (pSelect->selFlags & SF_AllValues)==0 ){
|
||||
if( (pSelect->selFlags & SF_MultiValue)==0 ){
|
||||
w.xSelectCallback2 = selectPopWith;
|
||||
}
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
@ -4605,7 +4610,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
}
|
||||
if( pF->iDistinct>=0 ){
|
||||
addrNext = sqlite3VdbeMakeLabel(v);
|
||||
assert( nArg==1 );
|
||||
testcase( nArg==0 ); /* Error condition */
|
||||
testcase( nArg>1 ); /* Also an error */
|
||||
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
|
||||
}
|
||||
if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
|
||||
@ -5480,10 +5486,9 @@ int sqlite3Select(
|
||||
*/
|
||||
sqlite3VdbeResolveLabel(v, iEnd);
|
||||
|
||||
/* The SELECT was successfully coded. Set the return code to 0
|
||||
** to indicate no errors.
|
||||
*/
|
||||
rc = 0;
|
||||
/* The SELECT has been coded. If there is an error in the Parse structure,
|
||||
** set the return code to 1. Otherwise 0. */
|
||||
rc = (pParse->nErr>0);
|
||||
|
||||
/* Control jumps to here if an error is encountered above, or upon
|
||||
** successful coding of the SELECT.
|
||||
@ -5535,6 +5540,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
StrAccum x;
|
||||
char zLine[100];
|
||||
sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0);
|
||||
x.useMalloc = 0;
|
||||
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
|
||||
if( pItem->zDatabase ){
|
||||
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
|
||||
|
121
src/shell.c
121
src/shell.c
@ -27,7 +27,7 @@
|
||||
/*
|
||||
** No support for loadable extensions in VxWorks.
|
||||
*/
|
||||
#if defined(_WRS_KERNEL) && !SQLITE_OMIT_LOAD_EXTENSION
|
||||
#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
|
||||
# define SQLITE_OMIT_LOAD_EXTENSION 1
|
||||
#endif
|
||||
|
||||
@ -336,7 +336,7 @@ static int stdin_is_interactive = 1;
|
||||
** to this database a static variable so that it can be accessed
|
||||
** by the SIGINT handler to interrupt database processing.
|
||||
*/
|
||||
static sqlite3 *db = 0;
|
||||
static sqlite3 *globalDb = 0;
|
||||
|
||||
/*
|
||||
** True if an interrupt (Control-C) has been received.
|
||||
@ -370,7 +370,7 @@ static FILE *iotrace = 0;
|
||||
** is written to iotrace.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
static void iotracePrintf(const char *zFormat, ...){
|
||||
static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
char *z;
|
||||
if( iotrace==0 ) return;
|
||||
@ -527,6 +527,7 @@ struct ShellState {
|
||||
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
|
||||
int statsOn; /* True to display memory stats before each finalize */
|
||||
int scanstatsOn; /* True to display scan stats before each finalize */
|
||||
int backslashOn; /* Resolve C-style \x escapes in SQL input text */
|
||||
int outCount; /* Revert to stdout when reaching zero */
|
||||
int cnt; /* Number of records displayed so far */
|
||||
FILE *out; /* Write results here */
|
||||
@ -804,7 +805,7 @@ static void interrupt_handler(int NotUsed){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
seenInterrupt++;
|
||||
if( seenInterrupt>2 ) exit(1);
|
||||
if( db ) sqlite3_interrupt(db);
|
||||
if( globalDb ) sqlite3_interrupt(globalDb);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1908,23 +1909,23 @@ static void open_db(ShellState *p, int keepAlive){
|
||||
if( p->db==0 ){
|
||||
sqlite3_initialize();
|
||||
sqlite3_open(p->zDbFilename, &p->db);
|
||||
db = p->db;
|
||||
if( db && sqlite3_errcode(db)==SQLITE_OK ){
|
||||
sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
|
||||
globalDb = p->db;
|
||||
if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
|
||||
sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
|
||||
shellstaticFunc, 0, 0);
|
||||
}
|
||||
if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
|
||||
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
|
||||
fprintf(stderr,"Error: unable to open database \"%s\": %s\n",
|
||||
p->zDbFilename, sqlite3_errmsg(db));
|
||||
p->zDbFilename, sqlite3_errmsg(p->db));
|
||||
if( keepAlive ) return;
|
||||
exit(1);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
sqlite3_enable_load_extension(p->db, 1);
|
||||
#endif
|
||||
sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
|
||||
sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0,
|
||||
readfileFunc, 0, 0);
|
||||
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
|
||||
sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0,
|
||||
writefileFunc, 0, 0);
|
||||
}
|
||||
}
|
||||
@ -1944,7 +1945,7 @@ static void resolve_backslashes(char *z){
|
||||
char c;
|
||||
while( *z && *z!='\\' ) z++;
|
||||
for(i=j=0; (c = z[i])!=0; i++, j++){
|
||||
if( c=='\\' ){
|
||||
if( c=='\\' && z[i+1]!=0 ){
|
||||
c = z[++i];
|
||||
if( c=='n' ){
|
||||
c = '\n';
|
||||
@ -2585,7 +2586,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
** Return 1 on error, 2 to exit, and 0 otherwise.
|
||||
*/
|
||||
static int do_meta_command(char *zLine, ShellState *p){
|
||||
int i = 1;
|
||||
int h = 1;
|
||||
int nArg = 0;
|
||||
int n, c;
|
||||
int rc = 0;
|
||||
@ -2593,24 +2594,24 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
/* Parse the input line into tokens.
|
||||
*/
|
||||
while( zLine[i] && nArg<ArraySize(azArg) ){
|
||||
while( IsSpace(zLine[i]) ){ i++; }
|
||||
if( zLine[i]==0 ) break;
|
||||
if( zLine[i]=='\'' || zLine[i]=='"' ){
|
||||
int delim = zLine[i++];
|
||||
azArg[nArg++] = &zLine[i];
|
||||
while( zLine[i] && zLine[i]!=delim ){
|
||||
if( zLine[i]=='\\' && delim=='"' && zLine[i+1]!=0 ) i++;
|
||||
i++;
|
||||
while( zLine[h] && nArg<ArraySize(azArg) ){
|
||||
while( IsSpace(zLine[h]) ){ h++; }
|
||||
if( zLine[h]==0 ) break;
|
||||
if( zLine[h]=='\'' || zLine[h]=='"' ){
|
||||
int delim = zLine[h++];
|
||||
azArg[nArg++] = &zLine[h];
|
||||
while( zLine[h] && zLine[h]!=delim ){
|
||||
if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
|
||||
h++;
|
||||
}
|
||||
if( zLine[i]==delim ){
|
||||
zLine[i++] = 0;
|
||||
if( zLine[h]==delim ){
|
||||
zLine[h++] = 0;
|
||||
}
|
||||
if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
|
||||
}else{
|
||||
azArg[nArg++] = &zLine[i];
|
||||
while( zLine[i] && !IsSpace(zLine[i]) ){ i++; }
|
||||
if( zLine[i] ) zLine[i++] = 0;
|
||||
azArg[nArg++] = &zLine[h];
|
||||
while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
|
||||
if( zLine[h] ) zLine[h++] = 0;
|
||||
resolve_backslashes(azArg[nArg-1]);
|
||||
}
|
||||
}
|
||||
@ -2986,7 +2987,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
nByte = strlen30(zSql);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
|
||||
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
|
||||
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
|
||||
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
|
||||
char cSep = '(';
|
||||
while( xRead(&sCtx) ){
|
||||
@ -3006,7 +3007,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_free(zCreate);
|
||||
if( rc ){
|
||||
fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
|
||||
sqlite3_errmsg(db));
|
||||
sqlite3_errmsg(p->db));
|
||||
sqlite3_free(sCtx.z);
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
@ -3016,7 +3017,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
|
||||
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
}
|
||||
@ -3041,13 +3042,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
|
||||
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
}
|
||||
needCommit = sqlite3_get_autocommit(db);
|
||||
if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
|
||||
needCommit = sqlite3_get_autocommit(p->db);
|
||||
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
|
||||
do{
|
||||
int startLine = sCtx.nLine;
|
||||
for(i=0; i<nCol; i++){
|
||||
@ -3086,7 +3087,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
rc = sqlite3_reset(pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine,
|
||||
sqlite3_errmsg(db));
|
||||
sqlite3_errmsg(p->db));
|
||||
}
|
||||
}
|
||||
}while( sCtx.cTerm!=EOF );
|
||||
@ -3094,7 +3095,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
xCloser(sCtx.in);
|
||||
sqlite3_free(sCtx.z);
|
||||
sqlite3_finalize(pStmt);
|
||||
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
|
||||
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
|
||||
}else
|
||||
|
||||
if( c=='i' && (strncmp(azArg[0], "indices", n)==0
|
||||
@ -3144,7 +3145,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
|
||||
extern void (*sqlite3IoTrace)(const char*, ...);
|
||||
SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
|
||||
if( iotrace && iotrace!=stdout ) fclose(iotrace);
|
||||
iotrace = 0;
|
||||
if( nArg<2 ){
|
||||
@ -3648,13 +3649,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
if( nRow>=nAlloc ){
|
||||
char **azNew;
|
||||
int n = nAlloc*2 + 10;
|
||||
azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n);
|
||||
int n2 = nAlloc*2 + 10;
|
||||
azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n2);
|
||||
if( azNew==0 ){
|
||||
fprintf(stderr, "Error: out of memory\n");
|
||||
break;
|
||||
}
|
||||
nAlloc = n;
|
||||
nAlloc = n2;
|
||||
azResult = azNew;
|
||||
}
|
||||
azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
|
||||
@ -3707,15 +3708,15 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "imposter", SQLITE_TESTCTRL_IMPOSTER },
|
||||
};
|
||||
int testctrl = -1;
|
||||
int rc = 0;
|
||||
int i, n;
|
||||
int rc2 = 0;
|
||||
int i, n2;
|
||||
open_db(p, 0);
|
||||
|
||||
/* convert testctrl text option to value. allow any unique prefix
|
||||
** of the option name, or a numerical value. */
|
||||
n = strlen30(azArg[1]);
|
||||
n2 = strlen30(azArg[1]);
|
||||
for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
|
||||
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
|
||||
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
|
||||
if( testctrl<0 ){
|
||||
testctrl = aCtrl[i].ctrlCode;
|
||||
}else{
|
||||
@ -3736,8 +3737,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_TESTCTRL_RESERVE:
|
||||
if( nArg==3 ){
|
||||
int opt = (int)strtol(azArg[2], 0, 0);
|
||||
rc = sqlite3_test_control(testctrl, p->db, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl, p->db, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
|
||||
azArg[1]);
|
||||
@ -3750,8 +3751,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_TESTCTRL_PRNG_RESET:
|
||||
case SQLITE_TESTCTRL_BYTEORDER:
|
||||
if( nArg==2 ){
|
||||
rc = sqlite3_test_control(testctrl);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
|
||||
}
|
||||
@ -3761,8 +3762,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_TESTCTRL_PENDING_BYTE:
|
||||
if( nArg==3 ){
|
||||
unsigned int opt = (unsigned int)integerValue(azArg[2]);
|
||||
rc = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes a single unsigned"
|
||||
" int option\n", azArg[1]);
|
||||
@ -3775,8 +3776,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_TESTCTRL_NEVER_CORRUPT:
|
||||
if( nArg==3 ){
|
||||
int opt = booleanValue(azArg[2]);
|
||||
rc = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
|
||||
azArg[1]);
|
||||
@ -3788,8 +3789,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_TESTCTRL_ISKEYWORD:
|
||||
if( nArg==3 ){
|
||||
const char *opt = azArg[2];
|
||||
rc = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
|
||||
azArg[1]);
|
||||
@ -3799,13 +3800,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
case SQLITE_TESTCTRL_IMPOSTER:
|
||||
if( nArg==5 ){
|
||||
rc = sqlite3_test_control(testctrl, p->db,
|
||||
rc2 = sqlite3_test_control(testctrl, p->db,
|
||||
azArg[2],
|
||||
integerValue(azArg[3]),
|
||||
integerValue(azArg[4]));
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
}else{
|
||||
fprintf(stderr,"Usage: .testctrl initmode dbName onoff tnum\n");
|
||||
rc = 1;
|
||||
fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4111,6 +4112,7 @@ static int process_input(ShellState *p, FILE *in){
|
||||
&& sqlite3_complete(zSql) ){
|
||||
p->cnt = 0;
|
||||
open_db(p, 0);
|
||||
if( p->backslashOn ) resolve_backslashes(zSql);
|
||||
BEGIN_TIMER;
|
||||
rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
|
||||
END_TIMER;
|
||||
@ -4577,6 +4579,13 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
data.statsOn = 1;
|
||||
}else if( strcmp(z,"-scanstats")==0 ){
|
||||
data.scanstatsOn = 1;
|
||||
}else if( strcmp(z,"-backslash")==0 ){
|
||||
/* Undocumented command-line option: -backslash
|
||||
** Causes C-style backslash escapes to be evaluated in SQL statements
|
||||
** prior to sending the SQL into SQLite. Useful for injecting
|
||||
** crazy bytes in the middle of SQL statements for testing and debugging.
|
||||
*/
|
||||
data.backslashOn = 1;
|
||||
}else if( strcmp(z,"-bail")==0 ){
|
||||
bail_on_error = 1;
|
||||
}else if( strcmp(z,"-version")==0 ){
|
||||
|
137
src/sqlite.h.in
137
src/sqlite.h.in
@ -43,18 +43,20 @@ extern "C" {
|
||||
|
||||
|
||||
/*
|
||||
** Add the ability to override 'extern'
|
||||
** Provide the ability to override linkage features of the interface.
|
||||
*/
|
||||
#ifndef SQLITE_EXTERN
|
||||
# define SQLITE_EXTERN extern
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Add the ability to override 'cdecl'
|
||||
*/
|
||||
#ifndef SQLITE_API
|
||||
# define SQLITE_API
|
||||
#endif
|
||||
#ifndef SQLITE_CDECL
|
||||
# define SQLITE_CDECL
|
||||
#endif
|
||||
#ifndef SQLITE_STDCALL
|
||||
# define SQLITE_STDCALL
|
||||
#endif
|
||||
|
||||
/*
|
||||
** These no-op macros are used in front of interfaces to mark those
|
||||
@ -268,6 +270,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Closing A Database Connection
|
||||
** DESTRUCTOR: sqlite3
|
||||
**
|
||||
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
|
||||
** for the [sqlite3] object.
|
||||
@ -319,6 +322,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
|
||||
|
||||
/*
|
||||
** CAPI3REF: One-Step Query Execution Interface
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** The sqlite3_exec() interface is a convenience wrapper around
|
||||
** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
|
||||
@ -1376,6 +1380,7 @@ int sqlite3_config(int, ...);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configure database connections
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** The sqlite3_db_config() interface is used to make configuration
|
||||
** changes to a [database connection]. The interface is similar to
|
||||
@ -1550,7 +1555,7 @@ struct sqlite3_mem_methods {
|
||||
** <li> [sqlite3_memory_used()]
|
||||
** <li> [sqlite3_memory_highwater()]
|
||||
** <li> [sqlite3_soft_heap_limit64()]
|
||||
** <li> [sqlite3_status()]
|
||||
** <li> [sqlite3_status64()]
|
||||
** </ul>)^
|
||||
** ^Memory allocation statistics are enabled by default unless SQLite is
|
||||
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
|
||||
@ -1873,6 +1878,7 @@ struct sqlite3_mem_methods {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Extended Result Codes
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_extended_result_codes() routine enables or disables the
|
||||
** [extended result codes] feature of SQLite. ^The extended result
|
||||
@ -1882,6 +1888,7 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Last Insert Rowid
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
|
||||
** has a unique 64-bit signed
|
||||
@ -1933,6 +1940,7 @@ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Count The Number Of Rows Modified
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This function returns the number of rows modified, inserted or
|
||||
** deleted by the most recently completed INSERT, UPDATE or DELETE
|
||||
@ -1985,6 +1993,7 @@ int sqlite3_changes(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Total Number Of Rows Modified
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This function returns the total number of rows inserted, modified or
|
||||
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
|
||||
@ -2008,6 +2017,7 @@ int sqlite3_total_changes(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Interrupt A Long-Running Query
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This function causes any pending database operation to abort and
|
||||
** return at its earliest opportunity. This routine is typically
|
||||
@ -2084,6 +2094,7 @@ int sqlite3_complete16(const void *sql);
|
||||
/*
|
||||
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
|
||||
** KEYWORDS: {busy-handler callback} {busy handler}
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
|
||||
** that might be invoked with argument P whenever
|
||||
@ -2143,6 +2154,7 @@ int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Set A Busy Timeout
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
|
||||
** for a specified amount of time when a table is locked. ^The handler
|
||||
@ -2165,6 +2177,7 @@ int sqlite3_busy_timeout(sqlite3*, int ms);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Convenience Routines For Running Queries
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** This is a legacy interface that is preserved for backwards compatibility.
|
||||
** Use of this interface is not recommended.
|
||||
@ -2500,6 +2513,7 @@ void sqlite3_randomness(int N, void *P);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Compile-Time Authorization Callbacks
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This routine registers an authorizer callback with a particular
|
||||
** [database connection], supplied in the first argument.
|
||||
@ -2656,6 +2670,7 @@ int sqlite3_set_authorizer(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Tracing And Profiling Functions
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** These routines register callback functions that can be used for
|
||||
** tracing and profiling the execution of SQL statements.
|
||||
@ -2688,6 +2703,7 @@ SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
|
||||
|
||||
/*
|
||||
** CAPI3REF: Query Progress Callbacks
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
|
||||
** function X to be invoked periodically during long running calls to
|
||||
@ -2721,6 +2737,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Opening A New Database Connection
|
||||
** CONSTRUCTOR: sqlite3
|
||||
**
|
||||
** ^These routines open an SQLite database file as specified by the
|
||||
** filename argument. ^The filename argument is interpreted as UTF-8 for
|
||||
@ -3006,6 +3023,7 @@ sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Error Codes And Messages
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^If the most recent sqlite3_* API call associated with
|
||||
** [database connection] D failed, then the sqlite3_errcode(D) interface
|
||||
@ -3051,33 +3069,34 @@ const void *sqlite3_errmsg16(sqlite3*);
|
||||
const char *sqlite3_errstr(int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Statement Object
|
||||
** CAPI3REF: Prepared Statement Object
|
||||
** KEYWORDS: {prepared statement} {prepared statements}
|
||||
**
|
||||
** An instance of this object represents a single SQL statement.
|
||||
** This object is variously known as a "prepared statement" or a
|
||||
** "compiled SQL statement" or simply as a "statement".
|
||||
** An instance of this object represents a single SQL statement that
|
||||
** has been compiled into binary form and is ready to be evaluated.
|
||||
**
|
||||
** The life of a statement object goes something like this:
|
||||
** Think of each SQL statement as a separate computer program. The
|
||||
** original SQL text is source code. A prepared statement object
|
||||
** is the compiled object code. All SQL must be converted into a
|
||||
** prepared statement before it can be run.
|
||||
**
|
||||
** The life-cycle of a prepared statement object usually goes like this:
|
||||
**
|
||||
** <ol>
|
||||
** <li> Create the object using [sqlite3_prepare_v2()] or a related
|
||||
** function.
|
||||
** <li> Bind values to [host parameters] using the sqlite3_bind_*()
|
||||
** <li> Create the prepared statement object using [sqlite3_prepare_v2()].
|
||||
** <li> Bind values to [parameters] using the sqlite3_bind_*()
|
||||
** interfaces.
|
||||
** <li> Run the SQL by calling [sqlite3_step()] one or more times.
|
||||
** <li> Reset the statement using [sqlite3_reset()] then go back
|
||||
** <li> Reset the prepared statement using [sqlite3_reset()] then go back
|
||||
** to step 2. Do this zero or more times.
|
||||
** <li> Destroy the object using [sqlite3_finalize()].
|
||||
** </ol>
|
||||
**
|
||||
** Refer to documentation on individual methods above for additional
|
||||
** information.
|
||||
*/
|
||||
typedef struct sqlite3_stmt sqlite3_stmt;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-time Limits
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^(This interface allows the size of various constructs to be limited
|
||||
** on a connection by connection basis. The first parameter is the
|
||||
@ -3189,6 +3208,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
/*
|
||||
** CAPI3REF: Compiling An SQL Statement
|
||||
** KEYWORDS: {SQL statement compiler}
|
||||
** METHOD: sqlite3
|
||||
** CONSTRUCTOR: sqlite3_stmt
|
||||
**
|
||||
** To execute an SQL query, it must first be compiled into a byte-code
|
||||
** program using one of these routines.
|
||||
@ -3296,6 +3317,7 @@ int sqlite3_prepare16_v2(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Retrieving Statement SQL
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^This interface can be used to retrieve a saved copy of the original
|
||||
** SQL text used to create a [prepared statement] if that statement was
|
||||
@ -3305,6 +3327,7 @@ const char *sqlite3_sql(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If An SQL Statement Writes The Database
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
|
||||
** and only if the [prepared statement] X makes no direct changes to
|
||||
@ -3336,6 +3359,7 @@ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
|
||||
** [prepared statement] S has been stepped at least once using
|
||||
@ -3410,6 +3434,7 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** CAPI3REF: Binding Values To Prepared Statements
|
||||
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
|
||||
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
|
||||
** literals may be replaced by a [parameter] that matches one of following
|
||||
@ -3528,6 +3553,7 @@ int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Number Of SQL Parameters
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^This routine can be used to find the number of [SQL parameters]
|
||||
** in a [prepared statement]. SQL parameters are tokens of the
|
||||
@ -3548,6 +3574,7 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Name Of A Host Parameter
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_bind_parameter_name(P,N) interface returns
|
||||
** the name of the N-th [SQL parameter] in the [prepared statement] P.
|
||||
@ -3575,6 +3602,7 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Index Of A Parameter With A Given Name
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^Return the index of an SQL parameter given its name. ^The
|
||||
** index value returned is suitable for use as the second
|
||||
@ -3591,6 +3619,7 @@ int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Reset All Bindings On A Prepared Statement
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset
|
||||
** the [sqlite3_bind_blob | bindings] on a [prepared statement].
|
||||
@ -3600,6 +3629,7 @@ int sqlite3_clear_bindings(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Number Of Columns In A Result Set
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^Return the number of columns in the result set returned by the
|
||||
** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
|
||||
@ -3611,6 +3641,7 @@ int sqlite3_column_count(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Column Names In A Result Set
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^These routines return the name assigned to a particular column
|
||||
** in the result set of a [SELECT] statement. ^The sqlite3_column_name()
|
||||
@ -3640,6 +3671,7 @@ const void *sqlite3_column_name16(sqlite3_stmt*, int N);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Source Of Data In A Query Result
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^These routines provide a means to determine the database, table, and
|
||||
** table column that is the origin of a particular result column in
|
||||
@ -3692,6 +3724,7 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Declared Datatype Of A Query Result
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^(The first parameter is a [prepared statement].
|
||||
** If this statement is a [SELECT] statement and the Nth column of the
|
||||
@ -3724,6 +3757,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Evaluate An SQL Statement
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** After a [prepared statement] has been prepared using either
|
||||
** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
|
||||
@ -3803,6 +3837,7 @@ int sqlite3_step(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Number of columns in a result set
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_data_count(P) interface returns the number of columns in the
|
||||
** current row of the result set of [prepared statement] P.
|
||||
@ -3856,6 +3891,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
/*
|
||||
** CAPI3REF: Result Values From A Query
|
||||
** KEYWORDS: {column access functions}
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** These routines form the "result set" interface.
|
||||
**
|
||||
@ -4028,6 +4064,7 @@ sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Destroy A Prepared Statement Object
|
||||
** DESTRUCTOR: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
|
||||
** ^If the most recent evaluation of the statement encountered no errors
|
||||
@ -4055,6 +4092,7 @@ int sqlite3_finalize(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Reset A Prepared Statement Object
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** The sqlite3_reset() function is called to reset a [prepared statement]
|
||||
** object back to its initial state, ready to be re-executed.
|
||||
@ -4084,6 +4122,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
|
||||
** KEYWORDS: {function creation routines}
|
||||
** KEYWORDS: {application-defined SQL function}
|
||||
** KEYWORDS: {application-defined SQL functions}
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^These functions (collectively known as "function creation routines")
|
||||
** are used to add SQL functions or aggregates or to redefine the behavior
|
||||
@ -4253,6 +4292,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtaining SQL Function Parameter Values
|
||||
** METHOD: sqlite3_value
|
||||
**
|
||||
** The C-language implementation of SQL functions and aggregates uses
|
||||
** this set of interface routines to access the parameter values on
|
||||
@ -4311,6 +4351,7 @@ int sqlite3_value_numeric_type(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain Aggregate Function Context
|
||||
** METHOD: sqlite3_context
|
||||
**
|
||||
** Implementations of aggregate SQL functions use this
|
||||
** routine to allocate memory for storing their state.
|
||||
@ -4355,6 +4396,7 @@ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
|
||||
|
||||
/*
|
||||
** CAPI3REF: User Data For Functions
|
||||
** METHOD: sqlite3_context
|
||||
**
|
||||
** ^The sqlite3_user_data() interface returns a copy of
|
||||
** the pointer that was the pUserData parameter (the 5th parameter)
|
||||
@ -4369,6 +4411,7 @@ void *sqlite3_user_data(sqlite3_context*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection For Functions
|
||||
** METHOD: sqlite3_context
|
||||
**
|
||||
** ^The sqlite3_context_db_handle() interface returns a copy of
|
||||
** the pointer to the [database connection] (the 1st parameter)
|
||||
@ -4380,6 +4423,7 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Function Auxiliary Data
|
||||
** METHOD: sqlite3_context
|
||||
**
|
||||
** These functions may be used by (non-aggregate) SQL functions to
|
||||
** associate metadata with argument values. If the same value is passed to
|
||||
@ -4452,6 +4496,7 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Setting The Result Of An SQL Function
|
||||
** METHOD: sqlite3_context
|
||||
**
|
||||
** These routines are used by the xFunc or xFinal callbacks that
|
||||
** implement SQL functions and aggregates. See
|
||||
@ -4587,6 +4632,7 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Define New Collating Sequences
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^These functions add, remove, or modify a [collation] associated
|
||||
** with the [database connection] specified as the first argument.
|
||||
@ -4689,6 +4735,7 @@ int sqlite3_create_collation16(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Collation Needed Callbacks
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^To avoid having to register all collation sequences before a database
|
||||
** can be used, a single callback function may be registered with the
|
||||
@ -4896,6 +4943,7 @@ SQLITE_EXTERN char *sqlite3_data_directory;
|
||||
/*
|
||||
** CAPI3REF: Test For Auto-Commit Mode
|
||||
** KEYWORDS: {autocommit mode}
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_get_autocommit() interface returns non-zero or
|
||||
** zero if the given database connection is or is not in autocommit mode,
|
||||
@ -4918,6 +4966,7 @@ int sqlite3_get_autocommit(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Find The Database Handle Of A Prepared Statement
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_db_handle interface returns the [database connection] handle
|
||||
** to which a [prepared statement] belongs. ^The [database connection]
|
||||
@ -4930,6 +4979,7 @@ sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Return The Filename For A Database Connection
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
|
||||
** associated with database N of connection D. ^The main database file
|
||||
@ -4946,6 +4996,7 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine if a database is read-only
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
|
||||
** of connection D is read-only, 0 if it is read/write, or -1 if N is not
|
||||
@ -4955,6 +5006,7 @@ int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Find the next prepared statement
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This interface returns a pointer to the next [prepared statement] after
|
||||
** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
|
||||
@ -4970,6 +5022,7 @@ sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Commit And Rollback Notification Callbacks
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_commit_hook() interface registers a callback
|
||||
** function to be invoked whenever a transaction is [COMMIT | committed].
|
||||
@ -5019,6 +5072,7 @@ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Data Change Notification Callbacks
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_update_hook() interface registers a callback function
|
||||
** with the [database connection] identified by the first argument
|
||||
@ -5125,6 +5179,7 @@ int sqlite3_release_memory(int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Free Memory Used By A Database Connection
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
|
||||
** memory as possible from database connection D. Unlike the
|
||||
@ -5202,6 +5257,7 @@ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Extract Metadata About A Column Of A Table
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
|
||||
** information about column C of table T in database D
|
||||
@ -5280,6 +5336,7 @@ int sqlite3_table_column_metadata(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Load An Extension
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This interface loads an SQLite extension library from the named file.
|
||||
**
|
||||
@ -5321,6 +5378,7 @@ int sqlite3_load_extension(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Extension Loading
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^So as not to open security holes in older applications that are
|
||||
** unprepared to deal with [extension loading], and as a means of disabling
|
||||
@ -5570,6 +5628,7 @@ struct sqlite3_index_info {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^These routines are used to register a new [virtual table module] name.
|
||||
** ^Module names must be registered before
|
||||
@ -5627,7 +5686,7 @@ int sqlite3_create_module_v2(
|
||||
*/
|
||||
struct sqlite3_vtab {
|
||||
const sqlite3_module *pModule; /* The module for this virtual table */
|
||||
int nRef; /* NO LONGER USED */
|
||||
int nRef; /* Number of open cursors */
|
||||
char *zErrMsg; /* Error message from sqlite3_mprintf() */
|
||||
/* Virtual table implementations will typically add additional fields */
|
||||
};
|
||||
@ -5666,6 +5725,7 @@ int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Overload A Function For A Virtual Table
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^(Virtual tables can provide alternative implementations of functions
|
||||
** using the [xFindFunction] method of the [virtual table module].
|
||||
@ -5708,6 +5768,8 @@ typedef struct sqlite3_blob sqlite3_blob;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Open A BLOB For Incremental I/O
|
||||
** METHOD: sqlite3
|
||||
** CONSTRUCTOR: sqlite3_blob
|
||||
**
|
||||
** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
|
||||
** in row iRow, column zColumn, table zTable in database zDb;
|
||||
@ -5789,6 +5851,7 @@ int sqlite3_blob_open(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Move a BLOB Handle to a New Row
|
||||
** METHOD: sqlite3_blob
|
||||
**
|
||||
** ^This function is used to move an existing blob handle so that it points
|
||||
** to a different row of the same database table. ^The new row is identified
|
||||
@ -5813,6 +5876,7 @@ SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Close A BLOB Handle
|
||||
** DESTRUCTOR: sqlite3_blob
|
||||
**
|
||||
** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed
|
||||
** unconditionally. Even if this routine returns an error code, the
|
||||
@ -5835,6 +5899,7 @@ int sqlite3_blob_close(sqlite3_blob *);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Return The Size Of An Open BLOB
|
||||
** METHOD: sqlite3_blob
|
||||
**
|
||||
** ^Returns the size in bytes of the BLOB accessible via the
|
||||
** successfully opened [BLOB handle] in its only argument. ^The
|
||||
@ -5850,6 +5915,7 @@ int sqlite3_blob_bytes(sqlite3_blob *);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Read Data From A BLOB Incrementally
|
||||
** METHOD: sqlite3_blob
|
||||
**
|
||||
** ^(This function is used to read data from an open [BLOB handle] into a
|
||||
** caller-supplied buffer. N bytes of data are copied into buffer Z
|
||||
@ -5878,6 +5944,7 @@ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Write Data Into A BLOB Incrementally
|
||||
** METHOD: sqlite3_blob
|
||||
**
|
||||
** ^(This function is used to write data into an open [BLOB handle] from a
|
||||
** caller-supplied buffer. N bytes of data are copied from the buffer Z
|
||||
@ -6205,6 +6272,7 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Retrieve the mutex for a database connection
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This interface returns a pointer the [sqlite3_mutex] object that
|
||||
** serializes access to the [database connection] given in the argument
|
||||
@ -6216,6 +6284,7 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Low-Level Control Of Database Files
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The [sqlite3_file_control()] interface makes a direct call to the
|
||||
** xFileControl method for the [sqlite3_io_methods] object associated
|
||||
@ -6305,7 +6374,7 @@ int sqlite3_test_control(int op, ...);
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
**
|
||||
** ^This interface is used to retrieve runtime status information
|
||||
** ^These interfaces are used to retrieve runtime status information
|
||||
** about the performance of SQLite, and optionally to reset various
|
||||
** highwater marks. ^The first argument is an integer code for
|
||||
** the specific parameter to measure. ^(Recognized integer codes
|
||||
@ -6319,19 +6388,22 @@ int sqlite3_test_control(int op, ...);
|
||||
** ^(Other parameters record only the highwater mark and not the current
|
||||
** value. For these latter parameters nothing is written into *pCurrent.)^
|
||||
**
|
||||
** ^The sqlite3_status() routine returns SQLITE_OK on success and a
|
||||
** non-zero [error code] on failure.
|
||||
** ^The sqlite3_status() and sqlite3_status64() routines return
|
||||
** SQLITE_OK on success and a non-zero [error code] on failure.
|
||||
**
|
||||
** This routine is threadsafe but is not atomic. This routine can be
|
||||
** called while other threads are running the same or different SQLite
|
||||
** interfaces. However the values returned in *pCurrent and
|
||||
** *pHighwater reflect the status of SQLite at different points in time
|
||||
** and it is possible that another thread might change the parameter
|
||||
** in between the times when *pCurrent and *pHighwater are written.
|
||||
** If either the current value or the highwater mark is too large to
|
||||
** be represented by a 32-bit integer, then the values returned by
|
||||
** sqlite3_status() are undefined.
|
||||
**
|
||||
** See also: [sqlite3_db_status()]
|
||||
*/
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
int sqlite3_status64(
|
||||
int op,
|
||||
sqlite3_int64 *pCurrent,
|
||||
sqlite3_int64 *pHighwater,
|
||||
int resetFlag
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
@ -6429,6 +6501,7 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Status
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This interface is used to retrieve runtime status information
|
||||
** about a single [database connection]. ^The first argument is the
|
||||
@ -6557,6 +6630,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepared Statement Status
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^(Each prepared statement maintains various
|
||||
** [SQLITE_STMTSTATUS counters] that measure the number
|
||||
@ -7060,6 +7134,7 @@ int sqlite3_backup_pagecount(sqlite3_backup *p);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Unlock Notification
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^When running in shared-cache mode, a database operation may fail with
|
||||
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
|
||||
@ -7230,6 +7305,7 @@ void sqlite3_log(int iErrCode, const char *zFormat, ...);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Write-Ahead Log Commit Hook
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The [sqlite3_wal_hook()] function is used to register a callback that
|
||||
** is invoked each time data is committed to a database in wal mode.
|
||||
@ -7269,6 +7345,7 @@ void *sqlite3_wal_hook(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configure an auto-checkpoint
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
|
||||
** [sqlite3_wal_hook()] that causes any database on [database connection] D
|
||||
@ -7299,6 +7376,7 @@ int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Checkpoint a database
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
|
||||
** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
|
||||
@ -7320,6 +7398,7 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Checkpoint a database
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint
|
||||
** operation on database X of [database connection] D in mode M. Status
|
||||
@ -7574,6 +7653,7 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepared Statement Scan Status
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** This interface returns information about the predicted and measured
|
||||
** performance for pStmt. Advanced applications can use this
|
||||
@ -7611,6 +7691,7 @@ SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Zero Scan-Status Counters
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
|
||||
**
|
||||
|
@ -594,6 +594,20 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
|
||||
*/
|
||||
typedef INT16_TYPE LogEst;
|
||||
|
||||
/*
|
||||
** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
|
||||
*/
|
||||
#ifndef SQLITE_PTRSIZE
|
||||
# if defined(__SIZEOF_POINTER__)
|
||||
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
|
||||
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
|
||||
defined(_M_ARM) || defined(__arm__) || defined(__x86)
|
||||
# define SQLITE_PTRSIZE 4
|
||||
# else
|
||||
# define SQLITE_PTRSIZE 8
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Macros to determine whether the machine is big or little endian,
|
||||
** and whether or not that determination is run-time or compile-time.
|
||||
@ -1098,6 +1112,7 @@ struct sqlite3 {
|
||||
int nVdbeRead; /* Number of active VDBEs that read or write */
|
||||
int nVdbeWrite; /* Number of active VDBEs that read and write */
|
||||
int nVdbeExec; /* Number of nested calls to VdbeExec() */
|
||||
int nVDestroy; /* Number of active OP_VDestroy operations */
|
||||
int nExtension; /* Number of loaded extensions */
|
||||
void **aExtension; /* Array of shared library handles */
|
||||
void (*xTrace)(void*,const char*); /* Trace function */
|
||||
@ -1211,6 +1226,7 @@ struct sqlite3 {
|
||||
#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
|
||||
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
|
||||
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
|
||||
#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */
|
||||
|
||||
|
||||
/*
|
||||
@ -1606,6 +1622,12 @@ struct Table {
|
||||
|
||||
/*
|
||||
** Allowed values for Table.tabFlags.
|
||||
**
|
||||
** TF_OOOHidden applies to virtual tables that have hidden columns that are
|
||||
** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
|
||||
** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
|
||||
** the TF_OOOHidden attribute would apply in this case. Such tables require
|
||||
** special handling during INSERT processing.
|
||||
*/
|
||||
#define TF_Readonly 0x01 /* Read-only system table */
|
||||
#define TF_Ephemeral 0x02 /* An ephemeral table */
|
||||
@ -1613,6 +1635,7 @@ struct Table {
|
||||
#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
|
||||
#define TF_Virtual 0x10 /* Is a virtual table */
|
||||
#define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */
|
||||
#define TF_OOOHidden 0x40 /* Out-of-Order hidden columns */
|
||||
|
||||
|
||||
/*
|
||||
@ -2369,11 +2392,12 @@ struct Select {
|
||||
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
|
||||
#define SF_Compound 0x0040 /* Part of a compound query */
|
||||
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
|
||||
#define SF_AllValues 0x0100 /* All terms of compound are VALUES */
|
||||
#define SF_MultiValue 0x0100 /* Single VALUES term with multiple rows */
|
||||
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
|
||||
#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */
|
||||
#define SF_Converted 0x2000 /* By convertCompoundSelectToSubquery() */
|
||||
|
||||
|
||||
/*
|
||||
@ -2752,7 +2776,7 @@ struct Trigger {
|
||||
* orconf -> stores the ON CONFLICT algorithm
|
||||
* pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
|
||||
* this stores a pointer to the SELECT statement. Otherwise NULL.
|
||||
* target -> A token holding the quoted name of the table to insert into.
|
||||
* zTarget -> Dequoted name of the table to insert into.
|
||||
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
|
||||
* this stores values to be inserted. Otherwise NULL.
|
||||
* pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
|
||||
@ -2760,12 +2784,12 @@ struct Trigger {
|
||||
* inserted into.
|
||||
*
|
||||
* (op == TK_DELETE)
|
||||
* target -> A token holding the quoted name of the table to delete from.
|
||||
* zTarget -> Dequoted name of the table to delete from.
|
||||
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
|
||||
* Otherwise NULL.
|
||||
*
|
||||
* (op == TK_UPDATE)
|
||||
* target -> A token holding the quoted name of the table to update rows of.
|
||||
* zTarget -> Dequoted name of the table to update.
|
||||
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
|
||||
* Otherwise NULL.
|
||||
* pExprList -> A list of the columns to update and the expressions to update
|
||||
@ -2777,8 +2801,8 @@ struct TriggerStep {
|
||||
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
|
||||
u8 orconf; /* OE_Rollback etc. */
|
||||
Trigger *pTrig; /* The trigger that this step is a part of */
|
||||
Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
|
||||
Token target; /* Target table for DELETE, UPDATE, INSERT */
|
||||
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
|
||||
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
|
||||
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
|
||||
ExprList *pExprList; /* SET clause for UPDATE. */
|
||||
IdList *pIdList; /* Column names for INSERT */
|
||||
@ -3097,10 +3121,15 @@ const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
|
||||
int sqlite3MutexEnd(void);
|
||||
#endif
|
||||
|
||||
int sqlite3StatusValue(int);
|
||||
void sqlite3StatusAdd(int, int);
|
||||
sqlite3_int64 sqlite3StatusValue(int);
|
||||
void sqlite3StatusUp(int, int);
|
||||
void sqlite3StatusDown(int, int);
|
||||
void sqlite3StatusSet(int, int);
|
||||
|
||||
/* Access to mutexes used by sqlite3_status() */
|
||||
sqlite3_mutex *sqlite3Pcache1Mutex(void);
|
||||
sqlite3_mutex *sqlite3MallocMutex(void);
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int sqlite3IsNaN(double);
|
||||
#else
|
||||
@ -3783,7 +3812,7 @@ void sqlite3Put4byte(u8*, u32);
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
|
||||
void sqlite3VdbeIOTraceSql(Vdbe*);
|
||||
SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
|
||||
SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
|
||||
#else
|
||||
# define IOTRACE(A)
|
||||
# define sqlite3VdbeIOTraceSql(X)
|
||||
|
94
src/status.c
94
src/status.c
@ -21,10 +21,32 @@
|
||||
*/
|
||||
typedef struct sqlite3StatType sqlite3StatType;
|
||||
static SQLITE_WSD struct sqlite3StatType {
|
||||
int nowValue[10]; /* Current value */
|
||||
int mxValue[10]; /* Maximum value */
|
||||
#if SQLITE_PTRSIZE>4
|
||||
sqlite3_int64 nowValue[10]; /* Current value */
|
||||
sqlite3_int64 mxValue[10]; /* Maximum value */
|
||||
#else
|
||||
u32 nowValue[10]; /* Current value */
|
||||
u32 mxValue[10]; /* Maximum value */
|
||||
#endif
|
||||
} sqlite3Stat = { {0,}, {0,} };
|
||||
|
||||
/*
|
||||
** Elements of sqlite3Stat[] are protected by either the memory allocator
|
||||
** mutex, or by the pcache1 mutex. The following array determines which.
|
||||
*/
|
||||
static const char statMutex[] = {
|
||||
0, /* SQLITE_STATUS_MEMORY_USED */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_USED */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */
|
||||
0, /* SQLITE_STATUS_SCRATCH_USED */
|
||||
0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */
|
||||
0, /* SQLITE_STATUS_MALLOC_SIZE */
|
||||
0, /* SQLITE_STATUS_PARSER_STACK */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_SIZE */
|
||||
0, /* SQLITE_STATUS_SCRATCH_SIZE */
|
||||
0, /* SQLITE_STATUS_MALLOC_COUNT */
|
||||
};
|
||||
|
||||
|
||||
/* The "wsdStat" macro will resolve to the status information
|
||||
** state vector. If writable static data is unsupported on the target,
|
||||
@ -41,33 +63,60 @@ static SQLITE_WSD struct sqlite3StatType {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the current value of a status parameter.
|
||||
** Return the current value of a status parameter. The caller must
|
||||
** be holding the appropriate mutex.
|
||||
*/
|
||||
int sqlite3StatusValue(int op){
|
||||
sqlite3_int64 sqlite3StatusValue(int op){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
return wsdStat.nowValue[op];
|
||||
}
|
||||
|
||||
/*
|
||||
** Add N to the value of a status record. It is assumed that the
|
||||
** caller holds appropriate locks.
|
||||
** Add N to the value of a status record. The caller must hold the
|
||||
** appropriate mutex. (Locking is checked by assert()).
|
||||
**
|
||||
** The StatusUp() routine can accept positive or negative values for N.
|
||||
** The value of N is added to the current status value and the high-water
|
||||
** mark is adjusted if necessary.
|
||||
**
|
||||
** The StatusDown() routine lowers the current value by N. The highwater
|
||||
** mark is unchanged. N must be non-negative for StatusDown().
|
||||
*/
|
||||
void sqlite3StatusAdd(int op, int N){
|
||||
void sqlite3StatusUp(int op, int N){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
wsdStat.nowValue[op] += N;
|
||||
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
}
|
||||
}
|
||||
void sqlite3StatusDown(int op, int N){
|
||||
wsdStatInit;
|
||||
assert( N>=0 );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
wsdStat.nowValue[op] -= N;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the value of a status to X.
|
||||
** Set the value of a status to X. The highwater mark is adjusted if
|
||||
** necessary. The caller must hold the appropriate mutex.
|
||||
*/
|
||||
void sqlite3StatusSet(int op, int X){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
wsdStat.nowValue[op] = X;
|
||||
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
@ -76,12 +125,14 @@ void sqlite3StatusSet(int op, int X){
|
||||
|
||||
/*
|
||||
** Query status information.
|
||||
**
|
||||
** This implementation assumes that reading or writing an aligned
|
||||
** 32-bit integer is an atomic operation. If that assumption is not true,
|
||||
** then this routine is not threadsafe.
|
||||
*/
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
int sqlite3_status64(
|
||||
int op,
|
||||
sqlite3_int64 *pCurrent,
|
||||
sqlite3_int64 *pHighwater,
|
||||
int resetFlag
|
||||
){
|
||||
sqlite3_mutex *pMutex;
|
||||
wsdStatInit;
|
||||
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
@ -89,13 +140,30 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex();
|
||||
sqlite3_mutex_enter(pMutex);
|
||||
*pCurrent = wsdStat.nowValue[op];
|
||||
*pHighwater = wsdStat.mxValue[op];
|
||||
if( resetFlag ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
}
|
||||
sqlite3_mutex_leave(pMutex);
|
||||
(void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
sqlite3_int64 iCur, iHwtr;
|
||||
int rc;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
|
||||
if( rc==0 ){
|
||||
*pCurrent = (int)iCur;
|
||||
*pHighwater = (int)iHwtr;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Query status information for a single database connection
|
||||
|
@ -1191,7 +1191,7 @@ static int dbPrepareAndBind(
|
||||
int n;
|
||||
u8 *data;
|
||||
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
|
||||
char c = zType[0];
|
||||
c = zType[0];
|
||||
if( zVar[0]=='@' ||
|
||||
(c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){
|
||||
/* Load a BLOB type if the Tcl variable is a bytearray and
|
||||
@ -2298,7 +2298,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
}
|
||||
Tcl_DecrRefCount(pRet);
|
||||
}else{
|
||||
ClientData cd[2];
|
||||
ClientData cd2[2];
|
||||
DbEvalContext *p;
|
||||
Tcl_Obj *pArray = 0;
|
||||
Tcl_Obj *pScript;
|
||||
@ -2312,9 +2312,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
|
||||
dbEvalInit(p, pDb, objv[2], pArray);
|
||||
|
||||
cd[0] = (void *)p;
|
||||
cd[1] = (void *)pScript;
|
||||
rc = DbEvalNextCmd(cd, interp, TCL_OK);
|
||||
cd2[0] = (void *)p;
|
||||
cd2[1] = (void *)pScript;
|
||||
rc = DbEvalNextCmd(cd2, interp, TCL_OK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -211,15 +211,15 @@ static int faultsimInstall(int install){
|
||||
faultsimBeginBenign, faultsimEndBenign
|
||||
);
|
||||
}else{
|
||||
sqlite3_mem_methods m;
|
||||
sqlite3_mem_methods m2;
|
||||
assert(memfault.m.xMalloc);
|
||||
|
||||
/* One should be able to reset the default memory allocator by storing
|
||||
** a zeroed allocator then calling GETMALLOC. */
|
||||
memset(&m, 0, sizeof(m));
|
||||
sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
|
||||
sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m);
|
||||
assert( memcmp(&m, &memfault.m, sizeof(m))==0 );
|
||||
memset(&m2, 0, sizeof(m2));
|
||||
sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
|
||||
sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
|
||||
assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
|
||||
|
||||
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
|
||||
|
@ -568,15 +568,15 @@ static int multiplexOpen(
|
||||
if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_int64 sz;
|
||||
sqlite3_int64 sz64;
|
||||
|
||||
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
|
||||
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz64);
|
||||
if( rc==SQLITE_OK && zName ){
|
||||
int bExists;
|
||||
if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
|
||||
pGroup->bEnabled = 0;
|
||||
}else
|
||||
if( sz==0 ){
|
||||
if( sz64==0 ){
|
||||
if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
|
||||
/* If opening a main journal file and the first chunk is zero
|
||||
** bytes in size, delete any subsequent chunks from the
|
||||
@ -607,10 +607,10 @@ static int multiplexOpen(
|
||||
rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
|
||||
SQLITE_ACCESS_EXISTS, &bExists);
|
||||
bExists = multiplexSubSize(pGroup, 1, &rc)>0;
|
||||
if( rc==SQLITE_OK && bExists && sz==(sz&0xffff0000) && sz>0
|
||||
&& sz!=pGroup->szChunk ){
|
||||
pGroup->szChunk = (int)sz;
|
||||
}else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){
|
||||
if( rc==SQLITE_OK && bExists && sz64==(sz64&0xffff0000) && sz64>0
|
||||
&& sz64!=pGroup->szChunk ){
|
||||
pGroup->szChunk = (int)sz64;
|
||||
}else if( rc==SQLITE_OK && !bExists && sz64>pGroup->szChunk ){
|
||||
pGroup->bEnabled = 0;
|
||||
}
|
||||
}
|
||||
|
@ -595,9 +595,9 @@ static int fsOpen(
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){
|
||||
tmp_file *p = (tmp_file *)pFile;
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->base.pMethods = &tmp_io_methods;
|
||||
tmp_file *p2 = (tmp_file *)pFile;
|
||||
memset(p2, 0, sizeof(*p2));
|
||||
p2->base.pMethods = &tmp_io_methods;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -1131,7 +1131,6 @@ static int test_vfslog(
|
||||
|
||||
switch( (enum VL_enum)iSub ){
|
||||
case VL_ANNOTATE: {
|
||||
int rc;
|
||||
char *zVfs;
|
||||
char *zMsg;
|
||||
if( objc!=4 ){
|
||||
@ -1148,7 +1147,6 @@ static int test_vfslog(
|
||||
break;
|
||||
}
|
||||
case VL_FINALIZE: {
|
||||
int rc;
|
||||
char *zVfs;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "VFS");
|
||||
@ -1164,7 +1162,6 @@ static int test_vfslog(
|
||||
};
|
||||
|
||||
case VL_NEW: {
|
||||
int rc;
|
||||
char *zVfs;
|
||||
char *zParent;
|
||||
char *zLog;
|
||||
|
@ -1080,7 +1080,7 @@ static int testvfs_obj_cmd(
|
||||
switch( aSubcmd[i].eCmd ){
|
||||
case CMD_SHM: {
|
||||
Tcl_Obj *pObj;
|
||||
int i, rc;
|
||||
int rc;
|
||||
TestvfsBuffer *pBuffer;
|
||||
char *zName;
|
||||
if( objc!=3 && objc!=4 ){
|
||||
@ -1160,7 +1160,6 @@ static int testvfs_obj_cmd(
|
||||
};
|
||||
Tcl_Obj **apElem = 0;
|
||||
int nElem = 0;
|
||||
int i;
|
||||
int mask = 0;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "LIST");
|
||||
|
@ -430,10 +430,8 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
break;
|
||||
}
|
||||
case TK_ILLEGAL: {
|
||||
sqlite3DbFree(db, *pzErrMsg);
|
||||
*pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"",
|
||||
sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"",
|
||||
&pParse->sLastToken);
|
||||
nErr++;
|
||||
goto abort_parse;
|
||||
}
|
||||
case TK_SEMI: {
|
||||
@ -451,7 +449,8 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
}
|
||||
}
|
||||
abort_parse:
|
||||
if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
|
||||
assert( nErr==0 );
|
||||
if( zSql[i]==0 && pParse->rc==SQLITE_OK ){
|
||||
if( lastTokenParsed!=TK_SEMI ){
|
||||
sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
|
||||
pParse->zTail = &zSql[i];
|
||||
@ -459,9 +458,11 @@ abort_parse:
|
||||
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
|
||||
}
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
sqlite3_mutex_enter(sqlite3MallocMutex());
|
||||
sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK,
|
||||
sqlite3ParserStackPeak(pEngine)
|
||||
);
|
||||
sqlite3_mutex_leave(sqlite3MallocMutex());
|
||||
#endif /* YYDEBUG */
|
||||
sqlite3ParserFree(pEngine, sqlite3_free);
|
||||
db->lookaside.bEnabled = enableLookaside;
|
||||
@ -515,8 +516,6 @@ abort_parse:
|
||||
pParse->pZombieTab = p->pNextZombie;
|
||||
sqlite3DeleteTable(db, p);
|
||||
}
|
||||
if( nErr>0 && pParse->rc==SQLITE_OK ){
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
assert( nErr==0 || pParse->rc!=SQLITE_OK );
|
||||
return nErr;
|
||||
}
|
||||
|
@ -193,7 +193,6 @@ void sqlite3BeginTrigger(
|
||||
/* Do not create a trigger on a system table */
|
||||
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
|
||||
pParse->nErr++;
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
|
||||
@ -373,12 +372,12 @@ static TriggerStep *triggerStepAllocate(
|
||||
){
|
||||
TriggerStep *pTriggerStep;
|
||||
|
||||
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n);
|
||||
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
|
||||
if( pTriggerStep ){
|
||||
char *z = (char*)&pTriggerStep[1];
|
||||
memcpy(z, pName->z, pName->n);
|
||||
pTriggerStep->target.z = z;
|
||||
pTriggerStep->target.n = pName->n;
|
||||
sqlite3Dequote(z);
|
||||
pTriggerStep->zTarget = z;
|
||||
pTriggerStep->op = op;
|
||||
}
|
||||
return pTriggerStep;
|
||||
@ -661,7 +660,7 @@ Trigger *sqlite3TriggersExist(
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert the pStep->target token into a SrcList and return a pointer
|
||||
** Convert the pStep->zTarget string into a SrcList and return a pointer
|
||||
** to that SrcList.
|
||||
**
|
||||
** This routine adds a specific database name, if needed, to the target when
|
||||
@ -674,17 +673,17 @@ static SrcList *targetSrcList(
|
||||
Parse *pParse, /* The parsing context */
|
||||
TriggerStep *pStep /* The trigger containing the target token */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb; /* Index of the database to use */
|
||||
SrcList *pSrc; /* SrcList to be returned */
|
||||
|
||||
pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
|
||||
pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
|
||||
if( pSrc ){
|
||||
assert( pSrc->nSrc>0 );
|
||||
assert( pSrc->a!=0 );
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
|
||||
pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
|
||||
iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
|
||||
if( iDb==0 || iDb>=2 ){
|
||||
sqlite3 *db = pParse->db;
|
||||
assert( iDb<pParse->db->nDb );
|
||||
assert( iDb<db->nDb );
|
||||
pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
|
||||
}
|
||||
}
|
||||
@ -796,6 +795,7 @@ static void transferParseError(Parse *pTo, Parse *pFrom){
|
||||
if( pTo->nErr==0 ){
|
||||
pTo->zErrMsg = pFrom->zErrMsg;
|
||||
pTo->nErr = pFrom->nErr;
|
||||
pTo->rc = pFrom->rc;
|
||||
}else{
|
||||
sqlite3DbFree(pFrom->db, pFrom->zErrMsg);
|
||||
}
|
||||
|
@ -655,6 +655,7 @@ int sqlite3GetInt32(const char *zNum, int *pValue){
|
||||
}
|
||||
}
|
||||
#endif
|
||||
while( zNum[0]=='0' ) zNum++;
|
||||
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
|
||||
v = v*10 + c;
|
||||
}
|
||||
|
@ -250,6 +250,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
|
||||
** the contents to the temporary database.
|
||||
*/
|
||||
assert( (db->flags & SQLITE_Vacuum)==0 );
|
||||
db->flags |= SQLITE_Vacuum;
|
||||
rc = execExecSql(db, pzErrMsg,
|
||||
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
|
||||
"|| ' SELECT * FROM main.' || quote(name) || ';'"
|
||||
@ -257,6 +259,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
"WHERE type = 'table' AND name!='sqlite_sequence' "
|
||||
" AND coalesce(rootpage,1)>0"
|
||||
);
|
||||
assert( (db->flags & SQLITE_Vacuum)!=0 );
|
||||
db->flags &= ~SQLITE_Vacuum;
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
|
||||
/* Copy over the sequence table
|
||||
|
382
src/vdbe.c
382
src/vdbe.c
File diff suppressed because it is too large
Load Diff
@ -213,6 +213,7 @@ int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
|
||||
|
||||
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
|
||||
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
|
||||
|
||||
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
|
||||
|
@ -313,14 +313,6 @@ struct ScanStatus {
|
||||
**
|
||||
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
|
||||
** is really a pointer to an instance of this structure.
|
||||
**
|
||||
** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
|
||||
** any virtual table method invocations made by the vdbe program. It is
|
||||
** set to 2 for xDestroy method calls and 1 for all other methods. This
|
||||
** variable is used for two purposes: to allow xDestroy methods to execute
|
||||
** "DROP TABLE" statements and to prevent some nasty side effects of
|
||||
** malloc failure when SQLite is invoked recursively by a virtual table
|
||||
** method function.
|
||||
*/
|
||||
struct Vdbe {
|
||||
sqlite3 *db; /* The database connection that owns this statement */
|
||||
@ -351,7 +343,6 @@ struct Vdbe {
|
||||
u8 errorAction; /* Recovery action to do in case of an error */
|
||||
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
||||
bft explain:2; /* True if EXPLAIN present on SQL command */
|
||||
bft inVtabMethod:2; /* See comments above */
|
||||
bft changeCntOn:1; /* True to update the change-counter */
|
||||
bft expired:1; /* True if the VM needs to be recompiled */
|
||||
bft runOnlyOnce:1; /* Automatically expire on reset */
|
||||
|
@ -1118,7 +1118,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
case P4_VTAB: {
|
||||
sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab;
|
||||
sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
|
||||
sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -1782,13 +1782,29 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
||||
else if( pCx->pVtabCursor ){
|
||||
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
|
||||
const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
|
||||
p->inVtabMethod = 1;
|
||||
assert( pVtabCursor->pVtab->nRef>0 );
|
||||
pVtabCursor->pVtab->nRef--;
|
||||
pModule->xClose(pVtabCursor);
|
||||
p->inVtabMethod = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Close all cursors in the current frame.
|
||||
*/
|
||||
static void closeCursorsInFrame(Vdbe *p){
|
||||
if( p->apCsr ){
|
||||
int i;
|
||||
for(i=0; i<p->nCursor; i++){
|
||||
VdbeCursor *pC = p->apCsr[i];
|
||||
if( pC ){
|
||||
sqlite3VdbeFreeCursor(p, pC);
|
||||
p->apCsr[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
|
||||
** is used, for example, when a trigger sub-program is halted to restore
|
||||
@ -1796,6 +1812,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
||||
*/
|
||||
int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
|
||||
Vdbe *v = pFrame->v;
|
||||
closeCursorsInFrame(v);
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
v->anExec = pFrame->anExec;
|
||||
#endif
|
||||
@ -1830,17 +1847,7 @@ static void closeAllCursors(Vdbe *p){
|
||||
p->nFrame = 0;
|
||||
}
|
||||
assert( p->nFrame==0 );
|
||||
|
||||
if( p->apCsr ){
|
||||
int i;
|
||||
for(i=0; i<p->nCursor; i++){
|
||||
VdbeCursor *pC = p->apCsr[i];
|
||||
if( pC ){
|
||||
sqlite3VdbeFreeCursor(p, pC);
|
||||
p->apCsr[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
closeCursorsInFrame(p);
|
||||
if( p->aMem ){
|
||||
releaseMemArray(&p->aMem[1], p->nMem);
|
||||
}
|
||||
@ -3585,7 +3592,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
|
||||
** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
|
||||
** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
|
||||
*/
|
||||
static int vdbeRecordCompareWithSkip(
|
||||
int sqlite3VdbeRecordCompareWithSkip(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
UnpackedRecord *pPKey2, /* Right key */
|
||||
int bSkip /* If true, skip the first field */
|
||||
@ -3771,7 +3778,7 @@ int sqlite3VdbeRecordCompare(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
UnpackedRecord *pPKey2 /* Right key */
|
||||
){
|
||||
return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
|
||||
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -3859,7 +3866,7 @@ static int vdbeRecordCompareInt(
|
||||
}else if( pPKey2->nField>1 ){
|
||||
/* The first fields of the two keys are equal. Compare the trailing
|
||||
** fields. */
|
||||
res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
||||
res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
||||
}else{
|
||||
/* The first fields of the two keys are equal and there are no trailing
|
||||
** fields. Return pPKey2->default_rc in this case. */
|
||||
@ -3907,7 +3914,7 @@ static int vdbeRecordCompareString(
|
||||
res = nStr - pPKey2->aMem[0].n;
|
||||
if( res==0 ){
|
||||
if( pPKey2->nField>1 ){
|
||||
res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
||||
res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
||||
}else{
|
||||
res = pPKey2->default_rc;
|
||||
}
|
||||
|
@ -1647,7 +1647,7 @@ void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
|
||||
Mem *aMem = pRec->aMem;
|
||||
sqlite3 *db = aMem[0].db;
|
||||
for(i=0; i<nCol; i++){
|
||||
if( aMem[i].szMalloc ) sqlite3DbFree(db, aMem[i].zMalloc);
|
||||
sqlite3VdbeMemRelease(&aMem[i]);
|
||||
}
|
||||
sqlite3KeyInfoUnref(pRec->pKeyInfo);
|
||||
sqlite3DbFree(db, pRec);
|
||||
|
232
src/vdbesort.c
232
src/vdbesort.c
@ -291,6 +291,7 @@ struct MergeEngine {
|
||||
** after the thread has finished are not dire. So we don't worry about
|
||||
** memory barriers and such here.
|
||||
*/
|
||||
typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int);
|
||||
struct SortSubtask {
|
||||
SQLiteThread *pThread; /* Background thread, if any */
|
||||
int bDone; /* Set if thread is finished but not joined */
|
||||
@ -298,10 +299,12 @@ struct SortSubtask {
|
||||
UnpackedRecord *pUnpacked; /* Space to unpack a record */
|
||||
SorterList list; /* List for thread to write to a PMA */
|
||||
int nPMA; /* Number of PMAs currently in file */
|
||||
SorterCompare xCompare; /* Compare function to use */
|
||||
SorterFile file; /* Temp file for level-0 PMAs */
|
||||
SorterFile file2; /* Space for other PMAs */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Main sorter structure. A single instance of this is allocated for each
|
||||
** sorter cursor created by the VDBE.
|
||||
@ -328,9 +331,13 @@ struct VdbeSorter {
|
||||
u8 bUseThreads; /* True to use background threads */
|
||||
u8 iPrev; /* Previous thread used to flush PMA */
|
||||
u8 nTask; /* Size of aTask[] array */
|
||||
u8 typeMask;
|
||||
SortSubtask aTask[1]; /* One or more subtasks */
|
||||
};
|
||||
|
||||
#define SORTER_TYPE_INTEGER 0x01
|
||||
#define SORTER_TYPE_TEXT 0x02
|
||||
|
||||
/*
|
||||
** An instance of the following object is used to read records out of a
|
||||
** PMA, in sorted order. The next key to be read is cached in nKey/aKey.
|
||||
@ -742,32 +749,162 @@ static int vdbePmaReaderInit(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** A version of vdbeSorterCompare() that assumes that it has already been
|
||||
** determined that the first field of key1 is equal to the first field of
|
||||
** key2.
|
||||
*/
|
||||
static int vdbeSorterCompareTail(
|
||||
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
||||
int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2 /* Right side of comparison */
|
||||
){
|
||||
UnpackedRecord *r2 = pTask->pUnpacked;
|
||||
if( *pbKey2Cached==0 ){
|
||||
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
|
||||
*pbKey2Cached = 1;
|
||||
}
|
||||
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
|
||||
** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences
|
||||
** used by the comparison. Return the result of the comparison.
|
||||
**
|
||||
** Before returning, object (pTask->pUnpacked) is populated with the
|
||||
** unpacked version of key2. Or, if pKey2 is passed a NULL pointer, then it
|
||||
** is assumed that the (pTask->pUnpacked) structure already contains the
|
||||
** unpacked key to use as key2.
|
||||
** If IN/OUT parameter *pbKey2Cached is true when this function is called,
|
||||
** it is assumed that (pTask->pUnpacked) contains the unpacked version
|
||||
** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked
|
||||
** version of key2 and *pbKey2Cached set to true before returning.
|
||||
**
|
||||
** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set
|
||||
** to SQLITE_NOMEM.
|
||||
*/
|
||||
static int vdbeSorterCompare(
|
||||
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
||||
int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2 /* Right side of comparison */
|
||||
){
|
||||
UnpackedRecord *r2 = pTask->pUnpacked;
|
||||
if( pKey2 ){
|
||||
if( !*pbKey2Cached ){
|
||||
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
|
||||
*pbKey2Cached = 1;
|
||||
}
|
||||
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
|
||||
}
|
||||
|
||||
/*
|
||||
** A specially optimized version of vdbeSorterCompare() that assumes that
|
||||
** the first field of each key is a TEXT value and that the collation
|
||||
** sequence to compare them with is BINARY.
|
||||
*/
|
||||
static int vdbeSorterCompareText(
|
||||
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
||||
int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2 /* Right side of comparison */
|
||||
){
|
||||
const u8 * const p1 = (const u8 * const)pKey1;
|
||||
const u8 * const p2 = (const u8 * const)pKey2;
|
||||
const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
|
||||
const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
|
||||
|
||||
int n1;
|
||||
int n2;
|
||||
int res;
|
||||
|
||||
getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2;
|
||||
getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2;
|
||||
res = memcmp(v1, v2, MIN(n1, n2));
|
||||
if( res==0 ){
|
||||
res = n1 - n2;
|
||||
}
|
||||
|
||||
if( res==0 ){
|
||||
if( pTask->pSorter->pKeyInfo->nField>1 ){
|
||||
res = vdbeSorterCompareTail(
|
||||
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
|
||||
);
|
||||
}
|
||||
}else{
|
||||
if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
|
||||
res = res * -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** A specially optimized version of vdbeSorterCompare() that assumes that
|
||||
** the first field of each key is an INTEGER value.
|
||||
*/
|
||||
static int vdbeSorterCompareInt(
|
||||
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
||||
int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2 /* Right side of comparison */
|
||||
){
|
||||
const u8 * const p1 = (const u8 * const)pKey1;
|
||||
const u8 * const p2 = (const u8 * const)pKey2;
|
||||
const int s1 = p1[1]; /* Left hand serial type */
|
||||
const int s2 = p2[1]; /* Right hand serial type */
|
||||
const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
|
||||
const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
|
||||
int res; /* Return value */
|
||||
|
||||
assert( (s1>0 && s1<7) || s1==8 || s1==9 );
|
||||
assert( (s2>0 && s2<7) || s2==8 || s2==9 );
|
||||
|
||||
if( s1>7 && s2>7 ){
|
||||
res = s1 - s2;
|
||||
}else{
|
||||
if( s1==s2 ){
|
||||
if( (*v1 ^ *v2) & 0x80 ){
|
||||
/* The two values have different signs */
|
||||
res = (*v1 & 0x80) ? -1 : +1;
|
||||
}else{
|
||||
/* The two values have the same sign. Compare using memcmp(). */
|
||||
static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 };
|
||||
int i;
|
||||
res = 0;
|
||||
for(i=0; i<aLen[s1]; i++){
|
||||
if( (res = v1[i] - v2[i]) ) break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( s2>7 ){
|
||||
res = +1;
|
||||
}else if( s1>7 ){
|
||||
res = -1;
|
||||
}else{
|
||||
res = s1 - s2;
|
||||
}
|
||||
assert( res!=0 );
|
||||
|
||||
if( res>0 ){
|
||||
if( *v1 & 0x80 ) res = -1;
|
||||
}else{
|
||||
if( *v2 & 0x80 ) res = +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( res==0 ){
|
||||
if( pTask->pSorter->pKeyInfo->nField>1 ){
|
||||
res = vdbeSorterCompareTail(
|
||||
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
|
||||
);
|
||||
}
|
||||
}else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
|
||||
res = res * -1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize the temporary index cursor just opened as a sorter cursor.
|
||||
**
|
||||
@ -835,9 +972,13 @@ int sqlite3VdbeSorterInit(
|
||||
pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
|
||||
memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
|
||||
pKeyInfo->db = 0;
|
||||
if( nField && nWorker==0 ) pKeyInfo->nField = nField;
|
||||
if( nField && nWorker==0 ){
|
||||
pKeyInfo->nXField += (pKeyInfo->nField - nField);
|
||||
pKeyInfo->nField = nField;
|
||||
}
|
||||
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
|
||||
pSorter->nTask = nWorker + 1;
|
||||
pSorter->iPrev = nWorker-1;
|
||||
pSorter->bUseThreads = (pSorter->nTask>1);
|
||||
pSorter->db = db;
|
||||
for(i=0; i<pSorter->nTask; i++){
|
||||
@ -863,6 +1004,12 @@ int sqlite3VdbeSorterInit(
|
||||
if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if( (pKeyInfo->nField+pKeyInfo->nXField)<13
|
||||
&& (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
|
||||
){
|
||||
pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -887,30 +1034,24 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
|
||||
*/
|
||||
static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){
|
||||
sqlite3DbFree(db, pTask->pUnpacked);
|
||||
pTask->pUnpacked = 0;
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
/* pTask->list.aMemory can only be non-zero if it was handed memory
|
||||
** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */
|
||||
if( pTask->list.aMemory ){
|
||||
sqlite3_free(pTask->list.aMemory);
|
||||
pTask->list.aMemory = 0;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
assert( pTask->list.aMemory==0 );
|
||||
vdbeSorterRecordFree(0, pTask->list.pList);
|
||||
}
|
||||
pTask->list.pList = 0;
|
||||
if( pTask->file.pFd ){
|
||||
sqlite3OsCloseFree(pTask->file.pFd);
|
||||
pTask->file.pFd = 0;
|
||||
pTask->file.iEof = 0;
|
||||
}
|
||||
if( pTask->file2.pFd ){
|
||||
sqlite3OsCloseFree(pTask->file2.pFd);
|
||||
pTask->file2.pFd = 0;
|
||||
pTask->file2.iEof = 0;
|
||||
}
|
||||
memset(pTask, 0, sizeof(SortSubtask));
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG_SORTER_THREADS
|
||||
@ -1090,6 +1231,7 @@ void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
|
||||
for(i=0; i<pSorter->nTask; i++){
|
||||
SortSubtask *pTask = &pSorter->aTask[i];
|
||||
vdbeSortSubtaskCleanup(db, pTask);
|
||||
pTask->pSorter = pSorter;
|
||||
}
|
||||
if( pSorter->list.aMemory==0 ){
|
||||
vdbeSorterRecordFree(0, pSorter->list.pList);
|
||||
@ -1199,28 +1341,42 @@ static void vdbeSorterMerge(
|
||||
){
|
||||
SorterRecord *pFinal = 0;
|
||||
SorterRecord **pp = &pFinal;
|
||||
void *pVal2 = p2 ? SRVAL(p2) : 0;
|
||||
int bCached = 0;
|
||||
|
||||
while( p1 && p2 ){
|
||||
int res;
|
||||
res = vdbeSorterCompare(pTask, SRVAL(p1), p1->nVal, pVal2, p2->nVal);
|
||||
res = pTask->xCompare(
|
||||
pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal
|
||||
);
|
||||
|
||||
if( res<=0 ){
|
||||
*pp = p1;
|
||||
pp = &p1->u.pNext;
|
||||
p1 = p1->u.pNext;
|
||||
pVal2 = 0;
|
||||
}else{
|
||||
*pp = p2;
|
||||
pp = &p2->u.pNext;
|
||||
pp = &p2->u.pNext;
|
||||
p2 = p2->u.pNext;
|
||||
if( p2==0 ) break;
|
||||
pVal2 = SRVAL(p2);
|
||||
bCached = 0;
|
||||
}
|
||||
}
|
||||
*pp = p1 ? p1 : p2;
|
||||
*ppOut = pFinal;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the SorterCompare function to compare values collected by the
|
||||
** sorter object passed as the only argument.
|
||||
*/
|
||||
static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){
|
||||
if( p->typeMask==SORTER_TYPE_INTEGER ){
|
||||
return vdbeSorterCompareInt;
|
||||
}else if( p->typeMask==SORTER_TYPE_TEXT ){
|
||||
return vdbeSorterCompareText;
|
||||
}
|
||||
return vdbeSorterCompare;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sort the linked list of records headed at pTask->pList. Return
|
||||
** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if
|
||||
@ -1235,12 +1391,14 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
|
||||
rc = vdbeSortAllocUnpacked(pTask);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
p = pList->pList;
|
||||
pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);
|
||||
|
||||
aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
|
||||
if( !aSlot ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
p = pList->pList;
|
||||
while( p ){
|
||||
SorterRecord *pNext;
|
||||
if( pList->aMemory ){
|
||||
@ -1454,13 +1612,12 @@ static int vdbeMergeEngineStep(
|
||||
int i; /* Index of aTree[] to recalculate */
|
||||
PmaReader *pReadr1; /* First PmaReader to compare */
|
||||
PmaReader *pReadr2; /* Second PmaReader to compare */
|
||||
u8 *pKey2; /* To pReadr2->aKey, or 0 if record cached */
|
||||
int bCached = 0;
|
||||
|
||||
/* Find the first two PmaReaders to compare. The one that was just
|
||||
** advanced (iPrev) and the one next to it in the array. */
|
||||
pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)];
|
||||
pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)];
|
||||
pKey2 = pReadr2->aKey;
|
||||
|
||||
for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){
|
||||
/* Compare pReadr1 and pReadr2. Store the result in variable iRes. */
|
||||
@ -1470,8 +1627,8 @@ static int vdbeMergeEngineStep(
|
||||
}else if( pReadr2->pFd==0 ){
|
||||
iRes = -1;
|
||||
}else{
|
||||
iRes = vdbeSorterCompare(pTask,
|
||||
pReadr1->aKey, pReadr1->nKey, pKey2, pReadr2->nKey
|
||||
iRes = pTask->xCompare(pTask, &bCached,
|
||||
pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey
|
||||
);
|
||||
}
|
||||
|
||||
@ -1493,9 +1650,9 @@ static int vdbeMergeEngineStep(
|
||||
if( iRes<0 || (iRes==0 && pReadr1<pReadr2) ){
|
||||
pMerger->aTree[i] = (int)(pReadr1 - pMerger->aReadr);
|
||||
pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
|
||||
pKey2 = pReadr2->aKey;
|
||||
bCached = 0;
|
||||
}else{
|
||||
if( pReadr1->pFd ) pKey2 = 0;
|
||||
if( pReadr1->pFd ) bCached = 0;
|
||||
pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr);
|
||||
pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
|
||||
}
|
||||
@ -1602,6 +1759,16 @@ int sqlite3VdbeSorterWrite(
|
||||
int bFlush; /* True to flush contents of memory to PMA */
|
||||
int nReq; /* Bytes of memory required */
|
||||
int nPMA; /* Bytes of PMA space required */
|
||||
int t; /* serial type of first record field */
|
||||
|
||||
getVarint32((const u8*)&pVal->z[1], t);
|
||||
if( t>0 && t<10 && t!=7 ){
|
||||
pSorter->typeMask &= SORTER_TYPE_INTEGER;
|
||||
}else if( t>10 && (t & 0x01) ){
|
||||
pSorter->typeMask &= SORTER_TYPE_TEXT;
|
||||
}else{
|
||||
pSorter->typeMask = 0;
|
||||
}
|
||||
|
||||
assert( pSorter );
|
||||
|
||||
@ -1867,10 +2034,12 @@ static void vdbeMergeEngineCompare(
|
||||
}else if( p2->pFd==0 ){
|
||||
iRes = i1;
|
||||
}else{
|
||||
SortSubtask *pTask = pMerger->pTask;
|
||||
int bCached = 0;
|
||||
int res;
|
||||
assert( pMerger->pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */
|
||||
res = vdbeSorterCompare(
|
||||
pMerger->pTask, p1->aKey, p1->nKey, p2->aKey, p2->nKey
|
||||
assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */
|
||||
res = pTask->xCompare(
|
||||
pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey
|
||||
);
|
||||
if( res<=0 ){
|
||||
iRes = i1;
|
||||
@ -2288,6 +2457,11 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){
|
||||
MergeEngine *pMain = 0;
|
||||
#if SQLITE_MAX_WORKER_THREADS
|
||||
sqlite3 *db = pTask0->pSorter->db;
|
||||
int i;
|
||||
SorterCompare xCompare = vdbeSorterGetCompare(pSorter);
|
||||
for(i=0; i<pSorter->nTask; i++){
|
||||
pSorter->aTask[i].xCompare = xCompare;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);
|
||||
|
@ -95,6 +95,8 @@ char *sqlite3VdbeExpandSql(
|
||||
assert( (zRawSql - zStart) > 0 );
|
||||
sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
|
||||
}
|
||||
}else if( p->nVar==0 ){
|
||||
sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql));
|
||||
}else{
|
||||
while( zRawSql[0] ){
|
||||
n = findNextHostParameter(zRawSql, &nToken);
|
||||
@ -111,10 +113,12 @@ char *sqlite3VdbeExpandSql(
|
||||
idx = nextIndex;
|
||||
}
|
||||
}else{
|
||||
assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
|
||||
assert( zRawSql[0]==':' || zRawSql[0]=='$' ||
|
||||
zRawSql[0]=='@' || zRawSql[0]=='#' );
|
||||
testcase( zRawSql[0]==':' );
|
||||
testcase( zRawSql[0]=='$' );
|
||||
testcase( zRawSql[0]=='@' );
|
||||
testcase( zRawSql[0]=='#' );
|
||||
idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
|
||||
assert( idx>0 );
|
||||
}
|
||||
|
59
src/vtab.c
59
src/vtab.c
@ -24,6 +24,8 @@
|
||||
struct VtabCtx {
|
||||
VTable *pVTable; /* The virtual table being constructed */
|
||||
Table *pTab; /* The Table object to which the virtual table belongs */
|
||||
VtabCtx *pPrior; /* Parent context (if any) */
|
||||
int bDeclared; /* True after sqlite3_declare_vtab() is called */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -470,7 +472,7 @@ void sqlite3VtabArgExtend(Parse *pParse, Token *p){
|
||||
pArg->z = p->z;
|
||||
pArg->n = p->n;
|
||||
}else{
|
||||
assert(pArg->z < p->z);
|
||||
assert(pArg->z <= p->z);
|
||||
pArg->n = (int)(&p->z[p->n] - pArg->z);
|
||||
}
|
||||
}
|
||||
@ -487,15 +489,27 @@ static int vtabCallConstructor(
|
||||
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
|
||||
char **pzErr
|
||||
){
|
||||
VtabCtx sCtx, *pPriorCtx;
|
||||
VtabCtx sCtx;
|
||||
VTable *pVTable;
|
||||
int rc;
|
||||
const char *const*azArg = (const char *const*)pTab->azModuleArg;
|
||||
int nArg = pTab->nModuleArg;
|
||||
char *zErr = 0;
|
||||
char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
|
||||
char *zModuleName;
|
||||
int iDb;
|
||||
VtabCtx *pCtx;
|
||||
|
||||
/* Check that the virtual-table is not already being initialized */
|
||||
for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
|
||||
if( pCtx->pTab==pTab ){
|
||||
*pzErr = sqlite3MPrintf(db,
|
||||
"vtable constructor called recursively: %s", pTab->zName
|
||||
);
|
||||
return SQLITE_LOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
|
||||
if( !zModuleName ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@ -516,11 +530,13 @@ static int vtabCallConstructor(
|
||||
assert( xConstruct );
|
||||
sCtx.pTab = pTab;
|
||||
sCtx.pVTable = pVTable;
|
||||
pPriorCtx = db->pVtabCtx;
|
||||
sCtx.pPrior = db->pVtabCtx;
|
||||
sCtx.bDeclared = 0;
|
||||
db->pVtabCtx = &sCtx;
|
||||
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
|
||||
db->pVtabCtx = pPriorCtx;
|
||||
db->pVtabCtx = sCtx.pPrior;
|
||||
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
|
||||
assert( sCtx.pTab==pTab );
|
||||
|
||||
if( SQLITE_OK!=rc ){
|
||||
if( zErr==0 ){
|
||||
@ -536,13 +552,14 @@ static int vtabCallConstructor(
|
||||
memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
|
||||
pVTable->pVtab->pModule = pMod->pModule;
|
||||
pVTable->nRef = 1;
|
||||
if( sCtx.pTab ){
|
||||
if( sCtx.bDeclared==0 ){
|
||||
const char *zFormat = "vtable constructor did not declare schema: %s";
|
||||
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
|
||||
sqlite3VtabUnlock(pVTable);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
int iCol;
|
||||
u8 oooHidden = 0;
|
||||
/* If everything went according to plan, link the new VTable structure
|
||||
** into the linked list headed by pTab->pVTable. Then loop through the
|
||||
** columns of the table to see if any of them contain the token "hidden".
|
||||
@ -555,7 +572,10 @@ static int vtabCallConstructor(
|
||||
char *zType = pTab->aCol[iCol].zType;
|
||||
int nType;
|
||||
int i = 0;
|
||||
if( !zType ) continue;
|
||||
if( !zType ){
|
||||
pTab->tabFlags |= oooHidden;
|
||||
continue;
|
||||
}
|
||||
nType = sqlite3Strlen30(zType);
|
||||
if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){
|
||||
for(i=0; i<nType; i++){
|
||||
@ -578,6 +598,9 @@ static int vtabCallConstructor(
|
||||
zType[i-1] = '\0';
|
||||
}
|
||||
pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
|
||||
oooHidden = TF_OOOHidden;
|
||||
}else{
|
||||
pTab->tabFlags |= oooHidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -706,8 +729,8 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
|
||||
** virtual table module.
|
||||
*/
|
||||
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
VtabCtx *pCtx;
|
||||
Parse *pParse;
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
Table *pTab;
|
||||
char *zErr = 0;
|
||||
@ -718,11 +741,13 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
|
||||
pCtx = db->pVtabCtx;
|
||||
if( !pCtx || pCtx->bDeclared ){
|
||||
sqlite3Error(db, SQLITE_MISUSE);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
pTab = pCtx->pTab;
|
||||
assert( (pTab->tabFlags & TF_Virtual)!=0 );
|
||||
|
||||
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
|
||||
@ -745,7 +770,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
pParse->pNewTable->nCol = 0;
|
||||
pParse->pNewTable->aCol = 0;
|
||||
}
|
||||
db->pVtabCtx->pTab = 0;
|
||||
pCtx->bDeclared = 1;
|
||||
}else{
|
||||
sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
@ -780,11 +805,15 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
|
||||
|
||||
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
|
||||
if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){
|
||||
VTable *p = vtabDisconnectAll(db, pTab);
|
||||
|
||||
assert( rc==SQLITE_OK );
|
||||
VTable *p;
|
||||
for(p=pTab->pVTable; p; p=p->pNext){
|
||||
assert( p->pVtab );
|
||||
if( p->pVtab->nRef>0 ){
|
||||
return SQLITE_LOCKED;
|
||||
}
|
||||
}
|
||||
p = vtabDisconnectAll(db, pTab);
|
||||
rc = p->pMod->pModule->xDestroy(p->pVtab);
|
||||
|
||||
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pTab->pVTable==p && p->pNext==0 );
|
||||
@ -936,7 +965,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
|
||||
assert( iSavepoint>=0 );
|
||||
assert( iSavepoint>=-1 );
|
||||
if( db->aVTrans ){
|
||||
int i;
|
||||
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
|
||||
|
@ -1730,6 +1730,14 @@ static int walCheckpoint(
|
||||
mxSafeFrame = pWal->hdr.mxFrame;
|
||||
mxPage = pWal->hdr.nPage;
|
||||
for(i=1; i<WAL_NREADER; i++){
|
||||
/* Thread-sanitizer reports that the following is an unsafe read,
|
||||
** as some other thread may be in the process of updating the value
|
||||
** of the aReadMark[] slot. The assumption here is that if that is
|
||||
** happening, the other client may only be increasing the value,
|
||||
** not decreasing it. So assuming either that either the "old" or
|
||||
** "new" version of the value is read, and not some arbitrary value
|
||||
** that would never be written by a real client, things are still
|
||||
** safe. */
|
||||
u32 y = pInfo->aReadMark[i];
|
||||
if( mxSafeFrame>y ){
|
||||
assert( y<=pWal->hdr.mxFrame );
|
||||
|
18
src/where.c
18
src/where.c
@ -255,13 +255,14 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
|
||||
** all terms of the WHERE clause.
|
||||
*/
|
||||
static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
|
||||
Expr *pE2 = sqlite3ExprSkipCollate(pExpr);
|
||||
pWC->op = op;
|
||||
if( pExpr==0 ) return;
|
||||
if( pExpr->op!=op ){
|
||||
if( pE2==0 ) return;
|
||||
if( pE2->op!=op ){
|
||||
whereClauseInsert(pWC, pExpr, 0);
|
||||
}else{
|
||||
whereSplit(pWC, pExpr->pLeft, op);
|
||||
whereSplit(pWC, pExpr->pRight, op);
|
||||
whereSplit(pWC, pE2->pLeft, op);
|
||||
whereSplit(pWC, pE2->pRight, op);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1532,7 +1533,7 @@ static int findIndexCol(
|
||||
&& p->iTable==iBase
|
||||
){
|
||||
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
|
||||
if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
|
||||
if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -1806,7 +1807,7 @@ static void constructAutomaticIndex(
|
||||
idxCols |= cMask;
|
||||
pIdx->aiColumn[n] = pTerm->u.leftColumn;
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
|
||||
pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY";
|
||||
pIdx->azColl[n] = pColl ? pColl->zName : "BINARY";
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@ -4781,7 +4782,7 @@ static int whereLoopAddBtreeIndex(
|
||||
}else if( eOp & (WO_EQ) ){
|
||||
pNew->wsFlags |= WHERE_COLUMN_EQ;
|
||||
if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){
|
||||
if( iCol>=0 && !IsUniqueIndex(pProbe) ){
|
||||
if( iCol>=0 && pProbe->uniqNotNull==0 ){
|
||||
pNew->wsFlags |= WHERE_UNQ_WANTED;
|
||||
}else{
|
||||
pNew->wsFlags |= WHERE_ONEROW;
|
||||
@ -6241,7 +6242,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
pWInfo->revMask = pFrom->revLoop;
|
||||
}
|
||||
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
|
||||
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
|
||||
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0
|
||||
){
|
||||
Bitmask revMask = 0;
|
||||
int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy,
|
||||
@ -6646,7 +6647,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
#ifdef WHERETRACE_ENABLED /* !=0 */
|
||||
if( sqlite3WhereTrace ){
|
||||
int ii;
|
||||
sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
|
||||
if( pWInfo->nOBSat>0 ){
|
||||
sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask);
|
||||
|
@ -359,6 +359,6 @@ do_test analyze-99.1 {
|
||||
catchsql {
|
||||
ANALYZE
|
||||
}
|
||||
} {1 {malformed database schema (sqlite_stat1) - near "nonsense": syntax error}}
|
||||
} {1 {malformed database schema (sqlite_stat1)}}
|
||||
|
||||
finish_test
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix analyze3
|
||||
|
||||
ifcapable !stat4&&!stat3 {
|
||||
finish_test
|
||||
@ -46,6 +47,9 @@ ifcapable !stat4&&!stat3 {
|
||||
#
|
||||
# analyze3-6.*: Test that the problem fixed by commit [127a5b776d] is fixed.
|
||||
#
|
||||
# analyze3-7.*: Test that some memory leaks discovered by fuzz testing
|
||||
# have been fixed.
|
||||
#
|
||||
|
||||
proc getvar {varname} { uplevel #0 set $varname }
|
||||
db function var getvar
|
||||
@ -662,4 +666,30 @@ do_eqp_test analyze3-6-2 {
|
||||
SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# 2015-04-20.
|
||||
# Memory leak in sqlite3Stat4ProbeFree(). (Discovered while fuzzing.)
|
||||
#
|
||||
do_execsql_test analyze-7.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(1,1,'0000');
|
||||
CREATE INDEX t0b ON t1(b);
|
||||
ANALYZE;
|
||||
SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND hex(1);
|
||||
} {}
|
||||
|
||||
# At one point duplicate stat1 entries were causing a memory leak.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.2 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
ANALYZE;
|
||||
SELECT * FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
|
||||
ANALYZE sqlite_master;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
@ -859,4 +859,16 @@ do_test attach-10.2 {
|
||||
}] 9 end
|
||||
} {4 noname {} 5 inmem {}}
|
||||
|
||||
# Attach with a very long URI filename.
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db -uri 1
|
||||
do_execsql_test attach-11.1 {
|
||||
ATTACH printf('file:%09000x/x.db?mode=memory&cache=shared',1) AS aux1;
|
||||
CREATE TABLE aux1.t1(x,y);
|
||||
INSERT INTO aux1.t1(x,y) VALUES(1,2),(3,4);
|
||||
SELECT * FROM aux1.t1;
|
||||
} {1 2 3 4}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -512,5 +512,12 @@ do_execsql_test autoindex1-901 {
|
||||
WHERE t1.x IN (1,2,3);
|
||||
} {/USING AUTOMATIC COVERING INDEX/}
|
||||
|
||||
# 2015-04-15: A NULL CollSeq pointer in automatic index creation.
|
||||
#
|
||||
do_execsql_test autoindex1-920 {
|
||||
CREATE TABLE t920(x);
|
||||
INSERT INTO t920 VALUES(3),(4),(5);
|
||||
SELECT * FROM t920,(SELECT 0 FROM t920),(VALUES(9)) WHERE 5 IN (x);
|
||||
} {5 0 9 5 0 9 5 0 9}
|
||||
|
||||
finish_test
|
||||
|
52
test/btree02.test
Normal file
52
test/btree02.test
Normal file
@ -0,0 +1,52 @@
|
||||
# 2015-03-25
|
||||
#
|
||||
# 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 regression tests for SQLite library.
|
||||
#
|
||||
# The focus of this script is making multiple calls to saveCursorPosition()
|
||||
# and restoreCursorPosition() when cursors have eState==CURSOR_SKIPNEXT
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
load_static_extension db eval
|
||||
do_execsql_test btree02-100 {
|
||||
CREATE TABLE t1(a TEXT, ax INTEGER, b INT, PRIMARY KEY(a,ax)) WITHOUT ROWID;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,ax,b) SELECT printf('%02x',i), random(), i FROM c;
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE TABLE t2(x,y);
|
||||
CREATE TABLE t3(cnt);
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<4)
|
||||
INSERT INTO t3(cnt) SELECT i FROM c;
|
||||
SELECT count(*) FROM t1;
|
||||
} {10}
|
||||
do_test btree02-110 {
|
||||
db eval BEGIN
|
||||
set i 0
|
||||
db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} {
|
||||
db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)}
|
||||
# puts "a,b,cnt = ($a,$b,$cnt)"
|
||||
incr i
|
||||
if {$i%2==1} {
|
||||
set bx [expr {$b+1000}]
|
||||
# puts "INSERT ($a),$bx"
|
||||
db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)}
|
||||
} else {
|
||||
# puts "DELETE a=$a"
|
||||
db eval {DELETE FROM t1 WHERE a=$a}
|
||||
}
|
||||
db eval {COMMIT; BEGIN}
|
||||
}
|
||||
db one {COMMIT; SELECT count(*) FROM t1;}
|
||||
} {20}
|
||||
|
||||
finish_test
|
@ -385,6 +385,20 @@ do_execsql_test 6.8 {
|
||||
SELECT x, y FROM c1 ORDER BY y COLLATE """""""";
|
||||
} {2 abb 1 ABC 4 WXY 3 wxz}
|
||||
|
||||
# 2015-04-15: Nested COLLATE operators
|
||||
#
|
||||
do_execsql_test 7.0 {
|
||||
SELECT 'abc' UNION ALL SELECT 'DEF'
|
||||
ORDER BY 1 COLLATE nocase COLLATE nocase COLLATE nocase COLLATE nocase;
|
||||
} {abc DEF}
|
||||
do_execsql_test 7.1 {
|
||||
SELECT 'abc' UNION ALL SELECT 'DEF'
|
||||
ORDER BY 1 COLLATE nocase COLLATE nocase COLLATE nocase COLLATE binary;
|
||||
} {DEF abc}
|
||||
do_execsql_test 7.2 {
|
||||
SELECT 'abc' UNION ALL SELECT 'DEF'
|
||||
ORDER BY 1 COLLATE binary COLLATE binary COLLATE binary COLLATE nocase;
|
||||
} {abc DEF}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
@ -32,7 +32,7 @@ source $testdir/tester.tcl
|
||||
#
|
||||
do_test collate3-1.0 {
|
||||
execsql {
|
||||
CREATE TABLE collate3t1(c1);
|
||||
CREATE TABLE collate3t1(c1 UNIQUE);
|
||||
}
|
||||
} {}
|
||||
do_test collate3-1.1 {
|
||||
@ -40,6 +40,11 @@ do_test collate3-1.1 {
|
||||
SELECT * FROM collate3t1 ORDER BY 1 collate garbage;
|
||||
}
|
||||
} {1 {no such collation sequence: garbage}}
|
||||
do_test collate3-1.1.2 {
|
||||
catchsql {
|
||||
SELECT DISTINCT c1 COLLATE garbage FROM collate3t1;
|
||||
}
|
||||
} {1 {no such collation sequence: garbage}}
|
||||
do_test collate3-1.2 {
|
||||
catchsql {
|
||||
CREATE TABLE collate3t2(c1 collate garbage);
|
||||
|
@ -292,7 +292,7 @@ do_test corruptC-2.15 {
|
||||
hexio_write test.db 986 b9
|
||||
sqlite3 db test.db
|
||||
catchsql {SELECT count(*) FROM sqlite_master;}
|
||||
} {1 {malformed database schema (t1i1) - no such table: main.t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#
|
||||
# Now test for a series of quasi-random seeds.
|
||||
|
80
test/corruptJ.test
Normal file
80
test/corruptJ.test
Normal file
@ -0,0 +1,80 @@
|
||||
# 2015-03-30
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Corruption consisting of a database page that thinks it is a child
|
||||
# of itself.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix corruptJ
|
||||
|
||||
if {[permutation]=="mmap"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Do not use a codec for tests in this file, as the database file is
|
||||
# manipulated directly using tcl scripts (using the [hexio_write] command).
|
||||
#
|
||||
do_not_use_codec
|
||||
database_may_be_corrupt
|
||||
|
||||
# Initialize the database.
|
||||
#
|
||||
do_execsql_test 1.1 {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=0;
|
||||
CREATE TABLE t1(a,b);
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,b) SELECT i, zeroblob(700) FROM c;
|
||||
} {}
|
||||
db close
|
||||
|
||||
# Corrupt the root page of the t1 table such that the left-child pointer
|
||||
# for the very first cell points back to the root. Then try to DROP the
|
||||
# table. The clearDatabasePage() routine should not loop.
|
||||
#
|
||||
do_test 1.2 {
|
||||
hexio_write test.db [expr {2*1024-2}] 02
|
||||
sqlite3 db test.db
|
||||
catchsql { DROP TABLE t1 }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
# Similar test using a WITHOUT ROWID table
|
||||
#
|
||||
do_test 2.1 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=0;
|
||||
CREATE TABLE t1(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<100)
|
||||
INSERT INTO t1(a,b) SELECT i, zeroblob(200) FROM c;
|
||||
}
|
||||
} {}
|
||||
|
||||
# The table is three levels deep. Corrupt the left child of an intermediate
|
||||
# page so that it points back to the root page.
|
||||
#
|
||||
do_test 2.2 {
|
||||
db close
|
||||
hexio_read test.db [expr {9*1024+391}] 8
|
||||
} {00000008814D0401}
|
||||
do_test 2.2b {
|
||||
hexio_write test.db [expr {9*1024+391}] 00000002
|
||||
sqlite3 db test.db
|
||||
catchsql { PRAGMA secure_delete=ON; DROP TABLE t1; }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
@ -191,4 +191,9 @@ do_execsql_test count-5.1 {
|
||||
SELECT count(*) FROM t5;
|
||||
} {1}
|
||||
|
||||
do_catchsql_test count-6.1 {
|
||||
CREATE TABLE t6(x);
|
||||
SELECT count(DISTINCT) FROM t6 GROUP BY x;
|
||||
} {1 {DISTINCT aggregates must have exactly one argument}}
|
||||
|
||||
finish_test
|
||||
|
@ -48,8 +48,11 @@ do_execsql_test e_reindex-1.1 {
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
|
||||
CREATE TABLE saved(a,b,c,d,e);
|
||||
INSERT INTO saved SELECT * FROM sqlite_master WHERE type = 'index';
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql = '-- ' || sql WHERE type = 'index';
|
||||
DELETE FROM sqlite_master WHERE type = 'index';
|
||||
} {}
|
||||
|
||||
db close
|
||||
@ -59,7 +62,8 @@ do_execsql_test e_reindex-1.2 {
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql = substr(sql, 4) WHERE type = 'index';
|
||||
INSERT INTO sqlite_master SELECT * FROM saved;
|
||||
DROP TABLE saved;
|
||||
} {}
|
||||
|
||||
db close
|
||||
|
@ -15,6 +15,14 @@ source $testdir/tester.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
set testprefix e_walauto
|
||||
|
||||
# Do not run this test on OpenBSD, as it depends on read() and mmap both
|
||||
# accessing the same coherent view of the "test.db-shm" file. This doesn't
|
||||
# work on OpenBSD.
|
||||
#
|
||||
if {$tcl_platform(os) == "OpenBSD"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc read_nbackfill {} {
|
||||
seek $::shmfd 96
|
||||
|
@ -943,5 +943,13 @@ do_realnum_test expr-13.7 {
|
||||
}
|
||||
} {9.22337203685478e+18}
|
||||
|
||||
do_execsql_test expr-13.8 {
|
||||
SELECT "" <= '';
|
||||
} {1}
|
||||
do_execsql_test expr-13.9 {
|
||||
SELECT '' <= "";
|
||||
} {1}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -121,4 +121,34 @@ do_test fkey1-3.5 {
|
||||
sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
|
||||
} {0 0 0}
|
||||
|
||||
# Stress the dequoting logic. The first test is not so bad.
|
||||
do_execsql_test fkey1-4.0 {
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE "xx1"("xx2" TEXT PRIMARY KEY, "xx3" TEXT);
|
||||
INSERT INTO "xx1"("xx2","xx3") VALUES('abc','def');
|
||||
CREATE TABLE "xx4"("xx5" TEXT REFERENCES "xx1" ON DELETE CASCADE);
|
||||
INSERT INTO "xx4"("xx5") VALUES('abc');
|
||||
INSERT INTO "xx1"("xx2","xx3") VALUES('uvw','xyz');
|
||||
SELECT 1, "xx5" FROM "xx4";
|
||||
DELETE FROM "xx1";
|
||||
SELECT 2, "xx5" FROM "xx4";
|
||||
} {1 abc}
|
||||
|
||||
# This case is identical to the previous except the "xx" in each name
|
||||
# is changed to a single escaped double-quote character.
|
||||
do_execsql_test fkey1-4.1 {
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE """1"("""2" TEXT PRIMARY KEY, """3" TEXT);
|
||||
INSERT INTO """1"("""2","""3") VALUES('abc','def');
|
||||
CREATE TABLE """4"("""5" TEXT REFERENCES """1" ON DELETE CASCADE);
|
||||
INSERT INTO """4"("""5") VALUES('abc');
|
||||
INSERT INTO """1"("""2","""3") VALUES('uvw','xyz');
|
||||
SELECT 1, """5" FROM """4";
|
||||
DELETE FROM """1";
|
||||
SELECT 2, """5" FROM """4";
|
||||
} {1 abc}
|
||||
do_execsql_test fkey1-4.2 {
|
||||
PRAGMA table_info="""1";
|
||||
} {0 {"2} TEXT 0 {} 1 1 {"3} TEXT 0 {} 0}
|
||||
|
||||
finish_test
|
||||
|
@ -676,6 +676,11 @@ do_test fkey2-9.2.3 {
|
||||
SELECT * FROM cc;
|
||||
}
|
||||
} {{} A {} {} B {} 3 A 2 3 B 2}
|
||||
do_execsql_test fkey2-9.3.0 {
|
||||
CREATE TABLE t3(x PRIMARY KEY REFERENCES t3 ON DELETE SET NULL);
|
||||
INSERT INTO t3(x) VALUES(12345);
|
||||
DROP TABLE t3;
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests, fkey2-10.*, test "foreign key mismatch" and
|
||||
@ -746,10 +751,10 @@ do_test fkey2-10.2.2 {
|
||||
drop_all_tables
|
||||
do_test fkey2-11.1.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, rowid, _rowid_, oid);
|
||||
CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE);
|
||||
|
||||
INSERT INTO t1 VALUES(10, 100);
|
||||
INSERT INTO t1 VALUES(10, 100, 'abc', 'def', 'ghi');
|
||||
INSERT INTO t2 VALUES(10, 100);
|
||||
UPDATE t1 SET a = 15;
|
||||
SELECT * FROM t2;
|
||||
@ -2014,4 +2019,18 @@ do_test fkey2-ce7c13.1.6 {
|
||||
}
|
||||
} {1 {FOREIGN KEY constraint failed}}
|
||||
|
||||
# 2015-04-16: Foreign key errors propagate back up to the parser.
|
||||
#
|
||||
do_test fkey2-20150416-100 {
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
catchsql {
|
||||
PRAGMA foreign_keys=1;
|
||||
CREATE TABLE t1(x PRIMARY KEY);
|
||||
CREATE TABLE t(y REFERENCES t0(x)ON DELETE SET DEFAULT);
|
||||
CREATE TABLE t0(y REFERENCES t1 ON DELETE SET NULL);
|
||||
REPLACE INTO t1 SELECT(0);CREATE TABLE t2(x);CREATE TABLE t3;
|
||||
}
|
||||
} {1 {foreign key mismatch - "t" referencing "t0"}}
|
||||
|
||||
finish_test
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts3aa
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
@ -221,5 +222,26 @@ do_catchsql_test fts3aa-7.5 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts4(tokenize=simple, tokenize=simple);
|
||||
} {1 {unrecognized parameter: tokenize=simple}}
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts4(order=desc);
|
||||
BEGIN;
|
||||
INSERT INTO t0(rowid, content) VALUES(1, 'abc');
|
||||
UPDATE t0 SET docid=5 WHERE docid=1;
|
||||
INSERT INTO t0(rowid, content) VALUES(6, 'abc');
|
||||
}
|
||||
do_execsql_test 8.1 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH 'abc';
|
||||
} {6 5}
|
||||
do_execsql_test 8.2 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"';
|
||||
} {}
|
||||
do_execsql_test 8.3 { COMMIT }
|
||||
do_execsql_test 8.4 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH 'abc';
|
||||
} {6 5}
|
||||
do_execsql_test 8.5 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"';
|
||||
} {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -203,5 +203,15 @@ do_catchsql_test 6.1.3 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts4(tokenize=" ");
|
||||
} {1 {unknown tokenizer: }}
|
||||
|
||||
do_catchsql_test 6.2.1 {
|
||||
SELECT fts3_tokenizer(NULL);
|
||||
} {1 {unknown tokenizer: }}
|
||||
do_catchsql_test 6.2.2 {
|
||||
SELECT fts3_tokenizer(NULL, X'1234567812345678');
|
||||
} {1 {argument type mismatch}}
|
||||
do_catchsql_test 6.2.3 {
|
||||
SELECT fts3_tokenizer(NULL, X'12345678');
|
||||
} {1 {argument type mismatch}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
48
test/fts3expr5.test
Normal file
48
test/fts3expr5.test
Normal file
@ -0,0 +1,48 @@
|
||||
# 2006 September 9
|
||||
#
|
||||
# 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 regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS3 module.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts3expr5
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Various forms of empty phrase expressions.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts3(x);
|
||||
SELECT rowid FROM t0 WHERE x MATCH '';
|
||||
} {}
|
||||
do_execsql_test 1.1 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '""';
|
||||
} {}
|
||||
do_execsql_test 1.2 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" ""';
|
||||
} {}
|
||||
do_execsql_test 1.3 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" OR ""';
|
||||
} {}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" NOT ""';
|
||||
} {}
|
||||
do_execsql_test 1.5 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '""""';
|
||||
} {}
|
||||
|
||||
finish_test
|
@ -155,4 +155,23 @@ ifcapable fts3_unicode {
|
||||
}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_test 6.0 {
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(x,order=DESC);
|
||||
INSERT INTO t6(docid, x) VALUES(-1,'a b');
|
||||
INSERT INTO t6(docid, x) VALUES(1, 'b');
|
||||
}
|
||||
faultsim_save_and_close
|
||||
} {}
|
||||
|
||||
do_faultsim_test 6.1 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {SELECT * FROM sqlite_master}
|
||||
} -body {
|
||||
execsql { SELECT docid FROM t6 WHERE t6 MATCH '"a* b"' }
|
||||
} -test {
|
||||
faultsim_test_result {0 -1}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
@ -274,4 +274,22 @@ do_execsql_test 6.5.2 {
|
||||
SELECT md5sum(quote(root)) FROM t1_segdir;
|
||||
} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
|
||||
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(x,order=DESC);
|
||||
INSERT INTO t6(docid, x) VALUES(-1,'a b');
|
||||
INSERT INTO t6(docid, x) VALUES(1, 'b');
|
||||
}
|
||||
do_execsql_test 7.1 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH '"a* b"';
|
||||
} {-1}
|
||||
do_execsql_test 7.2 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH 'a*';
|
||||
} {-1}
|
||||
do_execsql_test 7.3 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH 'a* b';
|
||||
} {-1}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -538,6 +538,25 @@ do_execsql_test 3.4 {
|
||||
SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one OR two OR three';
|
||||
} {{[<b>one</b> <b>two</b> <b>three</b>]}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Request a snippet 0 tokens in size. This is always an empty string.
|
||||
do_execsql_test 4.1 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts4;
|
||||
INSERT INTO t4 VALUES('a b c d');
|
||||
SELECT snippet(t4, '[', ']', '...', 0, 0) FROM t4 WHERE t4 MATCH 'b';
|
||||
} {{}}
|
||||
|
||||
do_test 4.2 {
|
||||
set x35 [string trim [string repeat "x " 35]]
|
||||
execsql "INSERT INTO t4 VALUES('$x35 E $x35 F $x35 G $x35');"
|
||||
llength [db one {
|
||||
SELECT snippet(t4, '', '', '', 0, 64) FROM t4 WHERE t4 MATCH 'E'
|
||||
}]
|
||||
} {64}
|
||||
|
||||
|
||||
|
||||
|
||||
set sqlite_fts3_enable_parentheses 0
|
||||
finish_test
|
||||
|
||||
|
@ -110,5 +110,15 @@ do_catchsql_test 2.1 {
|
||||
SELECT * FROM t4;
|
||||
} {1 {SQL logic error or missing database}}
|
||||
|
||||
do_catchsql_test 2.2 {
|
||||
CREATE VIRTUAL TABLE t USING fts4(tokenize=simple"");
|
||||
} {0 {}}
|
||||
|
||||
ifcapable fts3_unicode {
|
||||
do_catchsql_test 2.3 {
|
||||
CREATE VIRTUAL TABLE u USING fts4(tokenize=unicode61"");
|
||||
} {1 {unknown tokenizer}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -48,6 +48,9 @@ ifcapable !fts3 {
|
||||
#
|
||||
# 9.* - Test using content=xxx where xxx is a virtual table.
|
||||
#
|
||||
# 11.* - Test that circular references (e.g. "t1(content=t1)") are
|
||||
# detected.
|
||||
#
|
||||
|
||||
do_execsql_test 1.1.1 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
@ -406,7 +409,7 @@ do_execsql_test 5.1.7 {
|
||||
#
|
||||
do_catchsql_test 6.1.1 {
|
||||
CREATE VIRTUAL TABLE ft7 USING fts4(content=t7);
|
||||
} {1 {vtable constructor failed: ft7}}
|
||||
} {1 {no such table: main.t7}}
|
||||
|
||||
do_execsql_test 6.2.1 {
|
||||
CREATE TABLE t7(one, two);
|
||||
@ -433,7 +436,7 @@ do_execsql_test 6.2.3 {
|
||||
}
|
||||
do_catchsql_test 6.2.4 {
|
||||
SELECT * FROM ft7;
|
||||
} {1 {vtable constructor failed: ft7}}
|
||||
} {1 {no such table: main.t7}}
|
||||
do_execsql_test 6.2.5 {
|
||||
CREATE TABLE t7(x, y);
|
||||
INSERT INTO t7 VALUES('A B', 'B A');
|
||||
@ -622,4 +625,15 @@ do_execsql_test 10.7 {
|
||||
{...c d [e] f g...}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test cases 11.*
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_catchsql_test 11.1 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts4(content=x1);
|
||||
} {1 {vtable constructor called recursively: x1}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -109,6 +109,11 @@ do_execsql_test hexlit-301 {
|
||||
do_catchsql_test hexlist-400 {
|
||||
SELECT 0x10000000000000000;
|
||||
} {1 {hex literal too big: 0x10000000000000000}}
|
||||
do_catchsql_test hexlist-410 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1+0x10000000000000000);
|
||||
} {1 {hex literal too big: 0x10000000000000000}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -615,6 +615,12 @@ do_test in-13.14 {
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test in-13.15 {
|
||||
catchsql {
|
||||
SELECT 0 WHERE (SELECT 0,0) OR (0 IN (1,2));
|
||||
}
|
||||
} {1 {only a single result allowed for a SELECT that is part of an expression}}
|
||||
|
||||
|
||||
do_test in-13.X {
|
||||
db nullvalue ""
|
||||
|
@ -51,6 +51,6 @@ do_test index3-99.1 {
|
||||
db close
|
||||
catch { sqlite3 db test.db }
|
||||
catchsql { DROP INDEX i1 }
|
||||
} {1 {malformed database schema (t1) - near "nonsense": syntax error}}
|
||||
} {1 {malformed database schema (t1)}}
|
||||
|
||||
finish_test
|
||||
|
@ -311,5 +311,9 @@ do_eqp_test index7-6.4 {
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
|
||||
}
|
||||
do_catchsql_test index7-6.5 {
|
||||
CREATE INDEX t5a ON t5(a) WHERE a=#1;
|
||||
} {1 {near "#1": syntax error}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix insert2
|
||||
|
||||
# Create some tables with data that we can select against
|
||||
#
|
||||
@ -275,4 +276,23 @@ ifcapable subquery {
|
||||
} {1 2 1 3 1 4}
|
||||
}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t5(a, b, c DEFAULT 'c', d);
|
||||
}
|
||||
do_execsql_test 6.1 {
|
||||
INSERT INTO t5(a) SELECT 456 UNION ALL SELECT 123 ORDER BY 1;
|
||||
SELECT * FROM t5 ORDER BY rowid;
|
||||
} {123 {} c {} 456 {} c {}}
|
||||
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 6.2 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts4(a);
|
||||
}
|
||||
do_execsql_test 6.3 {
|
||||
INSERT INTO t0 SELECT 0 UNION SELECT 0 AS 'x' ORDER BY x;
|
||||
SELECT * FROM t0;
|
||||
} {0}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -560,5 +560,10 @@ do_test insert4-8.25 {
|
||||
}
|
||||
} {1 3}
|
||||
|
||||
do_catchsql_test insert4-9.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1(x) VALUES(5 COLLATE xyzzy) UNION SELECT 0;
|
||||
} {1 {no such collation sequence: xyzzy}}
|
||||
|
||||
finish_test
|
||||
|
@ -13,7 +13,6 @@
|
||||
# This file implements tests for miscellanous features that were
|
||||
# left out of other test files.
|
||||
#
|
||||
# $Id: misc1.test,v 1.42 2007/11/05 14:58:23 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -631,4 +630,58 @@ do_execsql_test misc1-20.1 {
|
||||
SELECT rowid, quote(x) FROM t0;
|
||||
} {1 ''}
|
||||
|
||||
# 2015-03-22: NULL pointer dereference after a syntax error
|
||||
#
|
||||
do_catchsql_test misc1-21.1 {
|
||||
select''like''like''like#0;
|
||||
} {1 {near "#0": syntax error}}
|
||||
do_catchsql_test misc1-21.2 {
|
||||
VALUES(0,0x0MATCH#0;
|
||||
} {1 {near ";": syntax error}}
|
||||
|
||||
# 2015-04-15
|
||||
do_execsql_test misc1-22.1 {
|
||||
SELECT ""+3 FROM (SELECT ""+5);
|
||||
} {3}
|
||||
|
||||
# 2015-04-19: NULL pointer dereference on a corrupt schema
|
||||
#
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test misc1-23.1 {
|
||||
CREATE TABLE t1(x);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS t3;
|
||||
} {}
|
||||
|
||||
# 2015-04-19: Faulty assert() statement
|
||||
#
|
||||
db close
|
||||
database_may_be_corrupt
|
||||
sqlite3 db :memory:
|
||||
do_catchsql_test misc1-23.2 {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE TABLE IF not EXISTS t(c)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(x);
|
||||
ROLLBACK;
|
||||
DROP TABLE F;
|
||||
} {1 {no such table: F}}
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_catchsql_test misc1-23.3 {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table y(a TEXT, a TEXT)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS t;
|
||||
} {0 {}}
|
||||
|
||||
finish_test
|
||||
|
@ -583,6 +583,24 @@ do_test misc5-7.1 {
|
||||
catchsql $sql
|
||||
} {1 {parser stack overflow}}
|
||||
|
||||
# Parser stack overflow is silently ignored when it occurs while parsing the
|
||||
# schema and PRAGMA writable_schema is turned on.
|
||||
#
|
||||
do_test misc5-7.2 {
|
||||
sqlite3 db2 :memory:
|
||||
catchsql {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table t(o CHECK(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((;VALUES(o)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS D;
|
||||
} db2
|
||||
} {0 {}}
|
||||
db2 close
|
||||
|
||||
|
||||
# Ticket #1911
|
||||
#
|
||||
ifcapable compound {
|
||||
|
@ -278,6 +278,23 @@ do_test null-8.15 {
|
||||
}
|
||||
} {1}
|
||||
|
||||
do_execsql_test null-9.1 {
|
||||
CREATE TABLE t5(a, b, c);
|
||||
CREATE UNIQUE INDEX t5ab ON t5(a, b);
|
||||
|
||||
INSERT INTO t5 VALUES(1, NULL, 'one');
|
||||
INSERT INTO t5 VALUES(1, NULL, 'i');
|
||||
INSERT INTO t5 VALUES(NULL, 'x', 'two');
|
||||
INSERT INTO t5 VALUES(NULL, 'x', 'ii');
|
||||
}
|
||||
|
||||
do_execsql_test null-9.2 {
|
||||
SELECT * FROM t5 WHERE a = 1 AND b IS NULL;
|
||||
} {1 {} one 1 {} i}
|
||||
|
||||
do_execsql_test null-9.3 {
|
||||
SELECT * FROM t5 WHERE a IS NULL AND b = 'x';
|
||||
} {{} x two {} x ii}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -463,6 +463,9 @@ do_execsql_test 5.1 {
|
||||
do_execsql_test 5.2 {
|
||||
SELECT 5 UNION ALL SELECT 3 ORDER BY 1
|
||||
} {3 5}
|
||||
do_execsql_test 5.3 {
|
||||
SELECT 986 AS x GROUP BY X ORDER BY X
|
||||
} {986}
|
||||
|
||||
# The following test (originally derived from a single test within fuzz.test)
|
||||
# verifies that a PseudoTable cursor is not closed prematurely in a deeply
|
||||
@ -495,5 +498,34 @@ do_execsql_test 7.0 {
|
||||
SELECT * FROM t7 WHERE a=?1 ORDER BY rowid;
|
||||
} {~/ORDER BY/}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test a partial sort large enough to cause the sorter to spill data
|
||||
# to disk.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.0 {
|
||||
PRAGMA cache_size = 5;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
}
|
||||
|
||||
do_eqp_test 8.1 {
|
||||
SELECT * FROM t1 ORDER BY a, b;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING INDEX i1}
|
||||
0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
}
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
WITH cnt(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000
|
||||
)
|
||||
INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt;
|
||||
}
|
||||
|
||||
do_test 8.3 {
|
||||
db eval { SELECT * FROM t1 ORDER BY a, b } { incr res $a }
|
||||
set res
|
||||
} 5000
|
||||
|
||||
finish_test
|
||||
|
@ -219,6 +219,24 @@ do_test pragma-1.14 {
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {2}
|
||||
do_test pragma-1.14.1 {
|
||||
execsql {
|
||||
PRAGMA synchronous=4;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {0}
|
||||
do_test pragma-1.14.2 {
|
||||
execsql {
|
||||
PRAGMA synchronous=3;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {0}
|
||||
do_test pragma-1.14.3 {
|
||||
execsql {
|
||||
PRAGMA synchronous=10;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {2}
|
||||
} ;# ifcapable pager_pragmas
|
||||
|
||||
# Test turning "flag" pragmas on and off.
|
||||
@ -752,6 +770,16 @@ do_test pragma-6.7 {
|
||||
{3 four REAL 0 X'abcdef' 0} \
|
||||
{4 five {} 0 CURRENT_TIME 0} \
|
||||
]
|
||||
do_test pragma-6.8 {
|
||||
execsql {
|
||||
CREATE TABLE t68(a,b,c,PRIMARY KEY(a,b,a,c));
|
||||
PRAGMA table_info(t68);
|
||||
}
|
||||
} [concat \
|
||||
{0 a {} 0 {} 1} \
|
||||
{1 b {} 0 {} 2} \
|
||||
{2 c {} 0 {} 4} \
|
||||
]
|
||||
} ;# ifcapable schema_pragmas
|
||||
# Miscellaneous tests
|
||||
#
|
||||
|
@ -472,6 +472,18 @@ do_test printf-1.16.7 {
|
||||
sqlite3_mprintf_int {abc: (%#6d) (%#6x) (%#6o) :xyz}\
|
||||
0xff676981 0xff676981 0xff676981
|
||||
} {abc: (-9999999) (0xff676981) (037731664601) :xyz}
|
||||
do_test printf-1.17.1 {
|
||||
sqlite3_mprintf_int {abd: %2147483647d %2147483647x %2147483647o} 1 1 1
|
||||
} {}
|
||||
do_test printf-1.17.2 {
|
||||
sqlite3_mprintf_int {abd: %*d %x} 2147483647 1 1
|
||||
} {}
|
||||
do_test printf-1.17.3 {
|
||||
sqlite3_mprintf_int {abd: %*d %x} -2147483648 1 1
|
||||
} {abd: 1 1}
|
||||
do_test printf-1.17.4 {
|
||||
sqlite3_mprintf_int {abd: %.2147483648d %x %x} 1 1 1
|
||||
} {/.*/}
|
||||
do_test printf-2.1.1.1 {
|
||||
sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 0.001
|
||||
} {abc: (0.0) :xyz}
|
||||
@ -526,6 +538,9 @@ do_test printf-2.1.2.8 {
|
||||
do_test printf-2.1.2.9 {
|
||||
sqlite3_mprintf_double {abc: %d %d (%1.1g) :xyz} 1 1 1.0e-20
|
||||
} {abc: 1 1 (1e-20) :xyz}
|
||||
do_test printf-2.1.2.10 {
|
||||
sqlite3_mprintf_double {abc: %*.*f} 2000000000 1000000000 1.0e-20
|
||||
} {abc: }
|
||||
do_test printf-2.1.3.1 {
|
||||
sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 1.0
|
||||
} {abc: (1.0) :xyz}
|
||||
@ -3466,6 +3481,15 @@ do_test printf-3.5 {
|
||||
do_test printf-3.6 {
|
||||
sqlite3_mprintf_str {%d %d A String: (%-30s)} 1 2 {This is the string}
|
||||
} [format {%d %d A String: (%-30s)} 1 2 {This is the string}]
|
||||
do_test printf-3.7 {
|
||||
sqlite3_mprintf_str {%d A String: (%*s)} 1 2147483647 {This is the string}
|
||||
} []
|
||||
do_test printf-3.8 {
|
||||
sqlite3_mprintf_str {%d A String: (%*s)} 1 -2147483648 {This is the string}
|
||||
} {1 A String: (This is the string)}
|
||||
do_test printf-3.9 {
|
||||
sqlite3_mprintf_str {%d A String: (%.*s)} 1 -2147483648 {This is the string}
|
||||
} {1 A String: (This is the string)}
|
||||
do_test snprintf-3.11 {
|
||||
sqlite3_snprintf_str 2 {x%d %d %s} 10 10 {This is the string}
|
||||
} {x}
|
||||
@ -3685,6 +3709,9 @@ do_test printf-13.5 {
|
||||
do_test printf-13.6 {
|
||||
sqlite3_mprintf_hexdouble %.20f fff8000000000000
|
||||
} {NaN}
|
||||
do_test printf-13.7 {
|
||||
sqlite3_mprintf_hexdouble %2147483648.10000f 4693b8b5b5056e17
|
||||
} {/100000000000000000000000000000000.00/}
|
||||
|
||||
do_test printf-14.1 {
|
||||
sqlite3_mprintf_str {abc-%y-123} 0 0 {not used}
|
||||
|
@ -58,6 +58,9 @@ do_execsql_test printf2-1.10 {
|
||||
do_execsql_test printf2-1.11 {
|
||||
SELECT printf('%lld%n',314159.2653,'hi');
|
||||
} {314159}
|
||||
do_execsql_test printf2-1.12 {
|
||||
SELECT printf('%n',0);
|
||||
} {{}}
|
||||
|
||||
# EVIDENCE-OF: R-17002-27534 The %z format is interchangeable with %s.
|
||||
#
|
||||
|
@ -14,6 +14,7 @@ optional) are:
|
||||
--config CONFIGNAME (Run only CONFIGNAME)
|
||||
--quick (Run "veryquick.test" only)
|
||||
--veryquick (Run "make smoketest" only)
|
||||
--msvc (Use MSVC as the compiler)
|
||||
--buildonly (Just build testfixture - do not run)
|
||||
--dryrun (Print what would have happened)
|
||||
--info (Show diagnostic info)
|
||||
@ -22,8 +23,9 @@ The default value for --srcdir is the parent of the directory holding
|
||||
this script.
|
||||
|
||||
The script determines the default value for --platform using the
|
||||
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
|
||||
platforms are "Linux-x86", "Linux-x86_64" and "Darwin-i386".
|
||||
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
|
||||
platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386",
|
||||
"Darwin-x86_64", "Windows NT-intel", and "Windows NT-amd64".
|
||||
|
||||
Every test begins with a fresh run of the configure script at the top
|
||||
of the SQLite source tree.
|
||||
@ -238,6 +240,10 @@ array set ::Platforms [strip_comments {
|
||||
"Default" "mptest fulltestonly"
|
||||
"Have-Not" test
|
||||
}
|
||||
"Windows NT-amd64" {
|
||||
"Default" "mptest fulltestonly"
|
||||
"Have-Not" test
|
||||
}
|
||||
|
||||
# The Failure-Detection platform runs various tests that deliberately
|
||||
# fail. This is used as a test of this script to verify that this script
|
||||
@ -296,6 +302,13 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
|
||||
set errmsg $msg
|
||||
}
|
||||
}
|
||||
if {[regexp {fatal error +(.*)} $line all msg]} {
|
||||
incr ::NERRCASE
|
||||
if {$rc==0} {
|
||||
set rc 1
|
||||
set errmsg $msg
|
||||
}
|
||||
}
|
||||
if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
|
||||
incr ::NERRCASE
|
||||
if {$rc==0} {
|
||||
@ -314,7 +327,13 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
|
||||
}
|
||||
}
|
||||
close $fd
|
||||
if {!$seen} {
|
||||
if {$::BUILDONLY} {
|
||||
if {$rc==0} {
|
||||
set errmsg "Build complete"
|
||||
} else {
|
||||
set errmsg "Build failed"
|
||||
}
|
||||
} elseif {!$seen} {
|
||||
set rc 1
|
||||
set errmsg "Test did not complete"
|
||||
if {[file readable core]} {
|
||||
@ -329,7 +348,7 @@ proc run_test_suite {name testtarget config} {
|
||||
# CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
|
||||
# CFLAGS is only passed to gcc.
|
||||
#
|
||||
set cflags "-g"
|
||||
set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
|
||||
set opts ""
|
||||
set title ${name}($testtarget)
|
||||
set configOpts ""
|
||||
@ -349,7 +368,14 @@ proc run_test_suite {name testtarget config} {
|
||||
|
||||
set cflags [join $cflags " "]
|
||||
set opts [join $opts " "]
|
||||
append opts " -DSQLITE_NO_SYNC=1 -DHAVE_USLEEP"
|
||||
append opts " -DSQLITE_NO_SYNC=1"
|
||||
|
||||
# Some configurations already set HAVE_USLEEP; in that case, skip it.
|
||||
#
|
||||
if {![regexp { -DHAVE_USLEEP$} $opts]
|
||||
&& ![regexp { -DHAVE_USLEEP[ =]+} $opts]} {
|
||||
append opts " -DHAVE_USLEEP=1"
|
||||
}
|
||||
|
||||
# Set the sub-directory to use.
|
||||
#
|
||||
@ -390,10 +416,10 @@ proc run_test_suite {name testtarget config} {
|
||||
if {$rc} {
|
||||
puts " FAIL $tm"
|
||||
incr ::NERR
|
||||
if {$errmsg!=""} {puts " $errmsg"}
|
||||
} else {
|
||||
puts " Ok $tm"
|
||||
}
|
||||
if {$errmsg!=""} {puts " $errmsg"}
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,6 +427,7 @@ proc run_test_suite {name testtarget config} {
|
||||
# the current platform, which may be Windows (via MinGW, etc).
|
||||
#
|
||||
proc configureCommand {opts} {
|
||||
if {$::MSVC} return [list]; # This is not needed for MSVC.
|
||||
set result [list trace_cmd exec]
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
lappend result sh
|
||||
@ -414,7 +441,14 @@ proc configureCommand {opts} {
|
||||
# specified targets, compiler flags, and options.
|
||||
#
|
||||
proc makeCommand { targets cflags opts } {
|
||||
set result [list trace_cmd exec make clean]
|
||||
set result [list trace_cmd exec]
|
||||
if {$::MSVC} {
|
||||
set nmakeDir [file nativename $::SRCDIR]
|
||||
set nmakeFile [file join $nmakeDir Makefile.msc]
|
||||
lappend result nmake /f $nmakeFile TOP=$nmakeDir clean
|
||||
} else {
|
||||
lappend result make clean
|
||||
}
|
||||
foreach target $targets {
|
||||
lappend result $target
|
||||
}
|
||||
@ -443,6 +477,7 @@ proc trace_cmd {args} {
|
||||
proc process_options {argv} {
|
||||
set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]]
|
||||
set ::QUICK 0
|
||||
set ::MSVC 0
|
||||
set ::BUILDONLY 0
|
||||
set ::DRYRUN 0
|
||||
set ::EXEC exec
|
||||
@ -476,6 +511,10 @@ proc process_options {argv} {
|
||||
set config [lindex $argv $i]
|
||||
}
|
||||
|
||||
-msvc {
|
||||
set ::MSVC 1
|
||||
}
|
||||
|
||||
-buildonly {
|
||||
set ::BUILDONLY 1
|
||||
}
|
||||
@ -494,6 +533,7 @@ proc process_options {argv} {
|
||||
puts " --platform [list $platform]"
|
||||
puts " --config [list $config]"
|
||||
if {$::QUICK} {puts " --quick"}
|
||||
if {$::MSVC} {puts " --msvc"}
|
||||
if {$::BUILDONLY} {puts " --buildonly"}
|
||||
if {$::DRYRUN} {puts " --dryrun"}
|
||||
if {$::TRACE} {puts " --trace"}
|
||||
@ -507,7 +547,15 @@ proc process_options {argv} {
|
||||
}
|
||||
exit
|
||||
}
|
||||
-g -
|
||||
|
||||
-g {
|
||||
if {$::MSVC} {
|
||||
lappend ::EXTRACONFIG -Zi
|
||||
} else {
|
||||
lappend ::EXTRACONFIG [lindex $argv $i]
|
||||
}
|
||||
}
|
||||
|
||||
-D* -
|
||||
-O* -
|
||||
-enable-* -
|
||||
@ -547,6 +595,7 @@ proc process_options {argv} {
|
||||
puts -nonewline "Flags:"
|
||||
if {$::DRYRUN} {puts -nonewline " --dryrun"}
|
||||
if {$::BUILDONLY} {puts -nonewline " --buildonly"}
|
||||
if {$::MSVC} {puts -nonewline " --msvc"}
|
||||
switch -- $::QUICK {
|
||||
1 {puts -nonewline " --quick"}
|
||||
2 {puts -nonewline " --veryquick"}
|
||||
@ -570,12 +619,20 @@ proc main {argv} {
|
||||
set ::SQLITE_VERSION {}
|
||||
set STARTTIME [clock seconds]
|
||||
foreach {zConfig target} $::CONFIGLIST {
|
||||
if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target
|
||||
|| "valgrindtest" in $target)} {
|
||||
puts "Skipping $zConfig / $target for MSVC..."
|
||||
continue
|
||||
}
|
||||
if {$target ne "checksymbols"} {
|
||||
switch -- $::QUICK {
|
||||
1 {set target test}
|
||||
2 {set target smoketest}
|
||||
}
|
||||
if {$::BUILDONLY} {set target testfixture}
|
||||
if {$::BUILDONLY} {
|
||||
set target testfixture
|
||||
if {$::MSVC} {append target .exe}
|
||||
}
|
||||
}
|
||||
set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]
|
||||
|
||||
|
@ -307,6 +307,9 @@ do_test select1-4.4 {
|
||||
set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {misuse of aggregate: min()}}
|
||||
do_catchsql_test select1-4.5 {
|
||||
INSERT INTO test1(f1) SELECT f1 FROM test1 ORDER BY min(f1);
|
||||
} {1 {misuse of aggregate: min()}}
|
||||
|
||||
# The restriction not allowing constants in the ORDER BY clause
|
||||
# has been removed. See ticket #1768
|
||||
@ -1072,5 +1075,10 @@ if {[db one {PRAGMA locking_mode}]=="normal"} {
|
||||
do_test select1-16.1 {
|
||||
catchsql {SELECT 1 FROM (SELECT *)}
|
||||
} {1 {no tables specified}}
|
||||
|
||||
# 2015-04-17: assertion fix.
|
||||
do_catchsql_test select1-16.2 {
|
||||
SELECT 1 FROM sqlite_master LIMIT 1,#1;
|
||||
} {1 {near "#1": syntax error}}
|
||||
|
||||
finish_test
|
||||
|
@ -118,6 +118,10 @@ do_test select4-1.3 {
|
||||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION ALL not before}}
|
||||
do_catchsql_test select4-1.4 {
|
||||
SELECT (VALUES(0) INTERSECT SELECT(0) UNION SELECT(0) ORDER BY 1 UNION
|
||||
SELECT 0 UNION SELECT 0 ORDER BY 1);
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
|
||||
# Union operator
|
||||
#
|
||||
@ -148,6 +152,12 @@ do_test select4-2.3 {
|
||||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
do_test select4-2.4 {
|
||||
set v [catch {execsql {
|
||||
SELECT 0 ORDER BY (SELECT 0) UNION SELECT 0;
|
||||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
|
||||
# Except operator
|
||||
#
|
||||
@ -799,6 +809,11 @@ do_test select4-11.15 {
|
||||
SELECT x FROM t2
|
||||
}
|
||||
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
|
||||
do_test select4-11.16 {
|
||||
catchsql {
|
||||
INSERT INTO t2(rowid) VALUES(2) UNION SELECT 3,4 UNION SELECT 5,6 ORDER BY 1;
|
||||
}
|
||||
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
|
||||
|
||||
do_test select4-12.1 {
|
||||
sqlite3 db2 :memory:
|
||||
@ -863,5 +878,23 @@ do_execsql_test select4-14.8 {
|
||||
do_execsql_test select4-14.9 {
|
||||
SELECT * FROM t14 UNION ALL VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3);
|
||||
} {1 2 3 4 5 6 3 2 1 2 3 1 1 2 3 2 1 3}
|
||||
do_execsql_test select4-14.10 {
|
||||
SELECT (VALUES(1),(2),(3),(4))
|
||||
} {1}
|
||||
do_execsql_test select4-14.11 {
|
||||
SELECT (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4)
|
||||
} {1}
|
||||
do_execsql_test select4-14.12 {
|
||||
VALUES(1) UNION VALUES(2);
|
||||
} {1 2}
|
||||
do_execsql_test select4-14.13 {
|
||||
VALUES(1),(2),(3) EXCEPT VALUES(2);
|
||||
} {1 3}
|
||||
do_execsql_test select4-14.14 {
|
||||
VALUES(1),(2),(3) EXCEPT VALUES(1),(3);
|
||||
} {2}
|
||||
do_execsql_test select4-14.15 {
|
||||
SELECT * FROM (SELECT 123), (SELECT 456) ON likely(0 OR 1) OR 0;
|
||||
} {123 456}
|
||||
|
||||
finish_test
|
||||
|
@ -1375,4 +1375,64 @@ do_execsql_test 4.2.2 {
|
||||
} {/2 . 3 . 4 . 5 . 6 . 7 ./}
|
||||
|
||||
|
||||
proc strip_rnd {explain} {
|
||||
regexp -all {sqlite_sq_[0123456789ABCDEF]*} $explain sqlite_sq
|
||||
}
|
||||
|
||||
proc do_same_test {tn q1 args} {
|
||||
set r2 [strip_rnd [db eval "EXPLAIN $q1"]]
|
||||
set i 1
|
||||
foreach q $args {
|
||||
set tst [subst -nocommands {strip_rnd [db eval "EXPLAIN $q"]}]
|
||||
uplevel do_test $tn.$i [list $tst] [list $r2]
|
||||
incr i
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t8(a, b);
|
||||
CREATE TABLE t9(c, d);
|
||||
} {}
|
||||
|
||||
do_same_test 5.1 {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY a;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t8.a;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY 1;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY c;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t9.c;
|
||||
}
|
||||
|
||||
do_same_test 5.2 {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t8.a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY 1 COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY c COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t9.c COLLATE NOCASE
|
||||
}
|
||||
|
||||
do_same_test 5.3 {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY b, c COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY 2, 1 COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT * FROM t9 ORDER BY t9.d, c COLLATE NOCASE
|
||||
} {
|
||||
SELECT * FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, t8.a COLLATE NOCASE
|
||||
}
|
||||
|
||||
do_catchsql_test 5.4 {
|
||||
SELECT * FROM t8 UNION SELECT * FROM t9 ORDER BY a+b COLLATE NOCASE
|
||||
} {1 {1st ORDER BY term does not match any column in the result set}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user