aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordan <dan@noemail.net>2015-03-24 18:21:41 +0000
committerdan <dan@noemail.net>2015-03-24 18:21:41 +0000
commit6da7a0a93da31b48081f50e92d4e7b5ffe19522d (patch)
tree3e9128ad52de6f69aa11508109f8eb28d1bb2309
parentf37120a416aee4703f5305e68c7535927678cc87 (diff)
parent126e9e6347216e47b538e4e8f24cfc2d752d89b3 (diff)
downloadsqlite-6da7a0a93da31b48081f50e92d4e7b5ffe19522d.tar.gz
sqlite-6da7a0a93da31b48081f50e92d4e7b5ffe19522d.zip
Merge the latest trunk changes into this branch.
FossilOrigin-Name: 9d9b6c883b4f7d69c615cedfb59a2385aac47b74
-rw-r--r--Makefile.in16
-rw-r--r--Makefile.msc380
-rw-r--r--ext/fts3/fts3.c17
-rw-r--r--ext/fts3/fts3_tokenizer.c10
-rw-r--r--ext/fts3/fts3_write.c5
-rw-r--r--ext/fts3/tool/fts3view.c4
-rw-r--r--manifest130
-rw-r--r--manifest.uuid2
-rw-r--r--mptest/crash01.test4
-rw-r--r--mptest/mptest.c23
-rw-r--r--mptest/multiwrite01.test10
-rw-r--r--src/alter.c5
-rw-r--r--src/btmutex.c1
-rw-r--r--src/btree.c22
-rw-r--r--src/btree.h15
-rw-r--r--src/build.c1
-rw-r--r--src/expr.c8
-rw-r--r--src/func.c4
-rw-r--r--src/main.c5
-rw-r--r--src/malloc.c49
-rw-r--r--src/os_unix.c64
-rw-r--r--src/parse.y6
-rw-r--r--src/pcache1.c19
-rw-r--r--src/select.c2
-rw-r--r--src/shell.c16
-rw-r--r--src/sqlite.h.in57
-rw-r--r--src/sqliteInt.h29
-rw-r--r--src/status.c93
-rw-r--r--src/tclsqlite.c37
-rw-r--r--src/test_func.c17
-rw-r--r--src/test_multiplex.c3
-rw-r--r--src/test_vfs.c13
-rw-r--r--src/tokenize.c2
-rw-r--r--src/vdbe.c120
-rw-r--r--src/vdbeInt.h9
-rw-r--r--src/vdbeapi.c34
-rw-r--r--src/vdbeaux.c8
-rw-r--r--src/vdbemem.c121
-rw-r--r--src/vdbesort.c1
-rw-r--r--src/vtab.c19
-rw-r--r--src/wal.c17
-rw-r--r--src/where.c293
-rw-r--r--test/analyze9.test112
-rw-r--r--test/analyzeF.test127
-rw-r--r--test/collate1.test58
-rw-r--r--test/crashM.test80
-rw-r--r--test/fts3atoken.test24
-rw-r--r--test/fts3prefix.test64
-rw-r--r--test/fts3query.test14
-rw-r--r--test/incrblob2.test14
-rw-r--r--test/incrcorrupt.test127
-rw-r--r--test/lock_common.tcl58
-rw-r--r--test/malloc5.test29
-rw-r--r--test/mallocK.test27
-rw-r--r--test/misc1.test10
-rw-r--r--test/shell4.test24
-rw-r--r--test/tclsqlite.test2
-rw-r--r--test/vtab1.test54
-rw-r--r--test/vtab2.test22
-rw-r--r--test/walblock.test117
-rw-r--r--test/with1.test15
-rw-r--r--test/without_rowid6.test76
-rwxr-xr-xtool/build-all-msvc.bat80
-rw-r--r--tool/showdb.c2
64 files changed, 2308 insertions, 519 deletions
diff --git a/Makefile.in b/Makefile.in
index 058a13a65..4ac06938f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -540,11 +540,19 @@ mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
$(TLIBS) -rpath "$(libdir)"
+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 mptest1.db
- ./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test
- rm -f mptest2.db
- ./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test
+ 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
+
# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
diff --git a/Makefile.msc b/Makefile.msc
index 58d370fcd..249e3c284 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -22,8 +22,22 @@ USE_AMALGAMATION = 1
USE_FULLWARN = 0
!ENDIF
+# Set this non-0 to use "stdcall" calling convention for the core library
+# and shell executable.
+#
+!IFNDEF USE_STDCALL
+USE_STDCALL = 0
+!ENDIF
+
+# Set this non-0 to have the shell executable link against the core dynamic
+# link library.
+#
+!IFNDEF DYNAMIC_SHELL
+DYNAMIC_SHELL = 0
+!ENDIF
+
# If necessary, create a list of harmless compiler warnings to disable when
-# compiling the build tools. For the SQLite source code itself, warnings,
+# compiling the various tools. For the SQLite source code itself, warnings,
# if any, will be disabled from within it.
#
!IFNDEF NO_WARN
@@ -256,9 +270,9 @@ NSDKLIBPATH = $(NSDKLIBPATH:\\=\)
# will run on the platform that is doing the build.
#
!IF $(USE_FULLWARN)!=0
-BCC = $(NCC) -W4
+BCC = $(NCC) -nologo -W4
!ELSE
-BCC = $(NCC) -W3
+BCC = $(NCC) -nologo -W3
!ENDIF
# Check if assembly code listings should be generated for the source
@@ -281,14 +295,106 @@ NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
# same unless your are cross-compiling.)
#
!IF $(USE_FULLWARN)!=0
-TCC = $(CC) -W4 -DINCLUDE_MSVC_H=1
+TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1
!ELSE
-TCC = $(CC) -W3
+TCC = $(CC) -nologo -W3
!ENDIF
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src
+# Check if we want to use the "stdcall" calling convention when compiling.
+# This is not supported by the compilers for non-x86 platforms. It should
+# also be noted here that building any target with these "stdcall" options
+# will most likely fail if the Tcl library is also required. This is due
+# to how the Tcl library functions are declared and exported (i.e. without
+# an explicit calling convention, which results in "cdecl").
+#
+!IF $(USE_STDCALL)!=0
+!IF "$(PLATFORM)"=="x86"
+CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
+SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
+!ELSE
+!IFNDEF PLATFORM
+CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
+SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
+!ELSE
+CORE_CCONV_OPTS =
+SHELL_CCONV_OPTS =
+!ENDIF
+!ENDIF
+!ELSE
+CORE_CCONV_OPTS =
+SHELL_CCONV_OPTS =
+!ENDIF
+
+# These are additional compiler options used for the core library.
+#
+!IFNDEF CORE_COMPILE_OPTS
+!IF $(USE_STDCALL)!=0
+CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport)
+!ELSE
+CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
+!ENDIF
+!ENDIF
+
+# These are the additional targets that the core library should depend on
+# when linking.
+#
+!IFNDEF CORE_LINK_DEP
+!IF $(USE_STDCALL)!=0
+CORE_LINK_DEP =
+!ELSE
+CORE_LINK_DEP = sqlite3.def
+!ENDIF
+!ENDIF
+
+# These are additional linker options used for the core library.
+#
+!IFNDEF CORE_LINK_OPTS
+!IF $(USE_STDCALL)!=0
+CORE_LINK_OPTS =
+!ELSE
+CORE_LINK_OPTS = /DEF:sqlite3.def
+!ENDIF
+!ENDIF
+
+# These are additional compiler options used for the shell executable.
+#
+!IFNDEF SHELL_COMPILE_OPTS
+!IF $(DYNAMIC_SHELL)!=0
+SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
+!ELSE
+SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS)
+!ENDIF
+!ENDIF
+
+# This is the core library that the shell executable should depend on.
+#
+!IFNDEF SHELL_CORE_DEP
+!IF $(DYNAMIC_SHELL)!=0
+SHELL_CORE_DEP = sqlite3.dll
+!ELSE
+SHELL_CORE_DEP = libsqlite3.lib
+!ENDIF
+!ENDIF
+
+# This is the core library that the shell executable should link with.
+#
+!IFNDEF SHELL_CORE_LIB
+!IF $(DYNAMIC_SHELL)!=0
+SHELL_CORE_LIB = sqlite3.lib
+!ELSE
+SHELL_CORE_LIB = libsqlite3.lib
+!ENDIF
+!ENDIF
+
+# These are additional linker options used for the shell executable.
+#
+!IFNDEF SHELL_LINK_OPTS
+SHELL_LINK_OPTS = $(SHELL_CORE_LIB)
+!ENDIF
+
# Check if assembly code listings should be generated for the source
# code files to be compiled.
#
@@ -587,8 +693,11 @@ LTLINK = $(LTLINK) rpcrt4.lib
# set this for you. Otherwise, the linker will attempt
# to deduce the binary type based on the object files.
!IFDEF PLATFORM
-LTLINKOPTS = /MACHINE:$(PLATFORM)
-LTLIBOPTS = /MACHINE:$(PLATFORM)
+LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
+LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
+!ELSE
+LTLINKOPTS = /NOLOGO
+LTLIBOPTS = /NOLOGO
!ENDIF
# When compiling for use in the WinRT environment, the following
@@ -1041,13 +1150,13 @@ libsqlite3.lib: $(LIBOBJ)
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
-sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
- $(LTLINK) $(READLINE_FLAGS) $(TOP)\src\shell.c \
- /link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
+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)
-mptester.exe: $(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
- $(LTLINK) $(TOP)\mptest\mptest.c \
- /link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
+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)
# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
@@ -1056,14 +1165,14 @@ mptester.exe: $(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
# all that automatic generation.
#
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl
- -rmdir /S/Q tsrc
+ -rmdir /Q/S tsrc 2>NUL
-mkdir tsrc
for %i in ($(SRC1)) do copy /Y %i tsrc
for %i in ($(SRC2)) do copy /Y %i tsrc
for %i in ($(SRC3)) do copy /Y %i tsrc
for %i in ($(SRC4)) do copy /Y %i tsrc
for %i in ($(SRC5)) do copy /Y %i tsrc
- del /Q tsrc\sqlite.h.in tsrc\parse.y
+ del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
move vdbe.new tsrc\vdbe.c
echo > .target_source
@@ -1088,7 +1197,7 @@ SQLITE3C = sqlite3.c
# Rule to build the amalgamation
#
sqlite3.lo: $(SQLITE3C)
- $(LTCOMPILE) -c $(SQLITE3C)
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C)
# Rules to build the LEMON compiler generator
#
@@ -1106,10 +1215,10 @@ lemon.exe: $(TOP)\tool\lemon.c lempar.c
# opcodes.lo
#
parse.lo: parse.c $(HDR)
- $(LTCOMPILE) -c parse.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c parse.c
opcodes.lo: opcodes.c
- $(LTCOMPILE) -c opcodes.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c opcodes.c
# Rule to build the Win32 resources object file.
#
@@ -1127,223 +1236,223 @@ $(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(HDR)
# Rules to build individual *.lo files from files in the src directory.
#
alter.lo: $(TOP)\src\alter.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\alter.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\alter.c
analyze.lo: $(TOP)\src\analyze.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\analyze.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\analyze.c
attach.lo: $(TOP)\src\attach.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\attach.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\attach.c
auth.lo: $(TOP)\src\auth.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\auth.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\auth.c
backup.lo: $(TOP)\src\backup.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\backup.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\backup.c
bitvec.lo: $(TOP)\src\bitvec.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\bitvec.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\bitvec.c
btmutex.lo: $(TOP)\src\btmutex.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\btmutex.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\btmutex.c
btree.lo: $(TOP)\src\btree.c $(HDR) $(TOP)\src\pager.h
- $(LTCOMPILE) -c $(TOP)\src\btree.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\btree.c
build.lo: $(TOP)\src\build.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\build.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\build.c
callback.lo: $(TOP)\src\callback.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\callback.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\callback.c
complete.lo: $(TOP)\src\complete.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\complete.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\complete.c
ctime.lo: $(TOP)\src\ctime.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\ctime.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\ctime.c
date.lo: $(TOP)\src\date.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\date.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
delete.lo: $(TOP)\src\delete.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\delete.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\delete.c
expr.lo: $(TOP)\src\expr.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\expr.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\expr.c
fault.lo: $(TOP)\src\fault.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\fault.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\fault.c
fkey.lo: $(TOP)\src\fkey.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\fkey.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\fkey.c
func.lo: $(TOP)\src\func.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\func.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\func.c
global.lo: $(TOP)\src\global.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\global.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\global.c
hash.lo: $(TOP)\src\hash.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\hash.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\hash.c
insert.lo: $(TOP)\src\insert.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\insert.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\insert.c
journal.lo: $(TOP)\src\journal.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\journal.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\journal.c
legacy.lo: $(TOP)\src\legacy.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\legacy.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\legacy.c
loadext.lo: $(TOP)\src\loadext.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\loadext.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\loadext.c
main.lo: $(TOP)\src\main.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\main.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\main.c
malloc.lo: $(TOP)\src\malloc.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\malloc.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\malloc.c
mem0.lo: $(TOP)\src\mem0.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mem0.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem0.c
mem1.lo: $(TOP)\src\mem1.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mem1.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem1.c
mem2.lo: $(TOP)\src\mem2.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mem2.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem2.c
mem3.lo: $(TOP)\src\mem3.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mem3.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem3.c
mem5.lo: $(TOP)\src\mem5.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mem5.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem5.c
memjournal.lo: $(TOP)\src\memjournal.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\memjournal.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memjournal.c
mutex.lo: $(TOP)\src\mutex.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mutex.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex.c
mutex_noop.lo: $(TOP)\src\mutex_noop.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mutex_noop.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_noop.c
mutex_unix.lo: $(TOP)\src\mutex_unix.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mutex_unix.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_unix.c
mutex_w32.lo: $(TOP)\src\mutex_w32.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\mutex_w32.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_w32.c
notify.lo: $(TOP)\src\notify.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\notify.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\notify.c
pager.lo: $(TOP)\src\pager.c $(HDR) $(TOP)\src\pager.h
- $(LTCOMPILE) -c $(TOP)\src\pager.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pager.c
pcache.lo: $(TOP)\src\pcache.c $(HDR) $(TOP)\src\pcache.h
- $(LTCOMPILE) -c $(TOP)\src\pcache.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pcache.c
pcache1.lo: $(TOP)\src\pcache1.c $(HDR) $(TOP)\src\pcache.h
- $(LTCOMPILE) -c $(TOP)\src\pcache1.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pcache1.c
os.lo: $(TOP)\src\os.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\os.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os.c
os_unix.lo: $(TOP)\src\os_unix.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\os_unix.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_unix.c
os_win.lo: $(TOP)\src\os_win.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\os_win.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_win.c
pragma.lo: $(TOP)\src\pragma.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\pragma.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pragma.c
prepare.lo: $(TOP)\src\prepare.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\prepare.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\prepare.c
printf.lo: $(TOP)\src\printf.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\printf.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\printf.c
random.lo: $(TOP)\src\random.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\random.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\random.c
resolve.lo: $(TOP)\src\resolve.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\resolve.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\resolve.c
rowset.lo: $(TOP)\src\rowset.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\rowset.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\rowset.c
select.lo: $(TOP)\src\select.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\select.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\select.c
status.lo: $(TOP)\src\status.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\status.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\status.c
table.lo: $(TOP)\src\table.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\table.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\table.c
threads.lo: $(TOP)\src\threads.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\threads.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\threads.c
tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\tokenize.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\tokenize.c
trigger.lo: $(TOP)\src\trigger.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\trigger.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c
update.lo: $(TOP)\src\update.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\update.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\update.c
utf.lo: $(TOP)\src\utf.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\utf.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\utf.c
util.lo: $(TOP)\src\util.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\util.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\util.c
vacuum.lo: $(TOP)\src\vacuum.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vacuum.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vacuum.c
vdbe.lo: $(TOP)\src\vdbe.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vdbe.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbe.c
vdbeapi.lo: $(TOP)\src\vdbeapi.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vdbeapi.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeapi.c
vdbeaux.lo: $(TOP)\src\vdbeaux.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vdbeaux.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeaux.c
vdbeblob.lo: $(TOP)\src\vdbeblob.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vdbeblob.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeblob.c
vdbemem.lo: $(TOP)\src\vdbemem.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vdbemem.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbemem.c
vdbesort.lo: $(TOP)\src\vdbesort.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vdbesort.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbesort.c
vdbetrace.lo: $(TOP)\src\vdbetrace.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vdbetrace.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbetrace.c
vtab.lo: $(TOP)\src\vtab.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\vtab.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vtab.c
wal.lo: $(TOP)\src\wal.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\wal.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wal.c
walker.lo: $(TOP)\src\walker.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\walker.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\walker.c
where.lo: $(TOP)\src\where.c $(HDR)
- $(LTCOMPILE) -c $(TOP)\src\where.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\where.c
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
- $(LTCOMPILE) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
+ $(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR)
- $(LTCOMPILE) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
+ $(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
-tclsqlite3.exe: tclsqlite-shell.lo libsqlite3.lib $(LIBRESOBJS)
- $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ libsqlite3.lib tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
+tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(LIBRESOBJS)
+ $(LTLINK) $(SQLITE3C) /link $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
# Rules to build opcodes.c and opcodes.h
#
@@ -1358,7 +1467,7 @@ opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\mkopcodeh.awk
parse.h: parse.c
parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk
- del /Q parse.y parse.h parse.h.temp
+ del /Q parse.y parse.h parse.h.temp 2>NUL
copy $(TOP)\src\parse.y .
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
move parse.h parse.h.temp
@@ -1379,67 +1488,67 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
# Rules to build the extension objects.
#
icu.lo: $(TOP)\ext\icu\icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\icu\icu.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\icu\icu.c
fts2.lo: $(TOP)\ext\fts2\fts2.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2.c
fts2_hash.lo: $(TOP)\ext\fts2\fts2_hash.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_hash.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_hash.c
fts2_icu.lo: $(TOP)\ext\fts2\fts2_icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_icu.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_icu.c
fts2_porter.lo: $(TOP)\ext\fts2\fts2_porter.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_porter.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_porter.c
fts2_tokenizer.lo: $(TOP)\ext\fts2\fts2_tokenizer.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer.c
fts2_tokenizer1.lo: $(TOP)\ext\fts2\fts2_tokenizer1.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer1.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer1.c
fts3.lo: $(TOP)\ext\fts3\fts3.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3.c
fts3_aux.lo: $(TOP)\ext\fts3\fts3_aux.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_aux.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_aux.c
fts3_expr.lo: $(TOP)\ext\fts3\fts3_expr.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_expr.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_expr.c
fts3_hash.lo: $(TOP)\ext\fts3\fts3_hash.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_hash.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_hash.c
fts3_icu.lo: $(TOP)\ext\fts3\fts3_icu.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_icu.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_icu.c
fts3_snippet.lo: $(TOP)\ext\fts3\fts3_snippet.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_snippet.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_snippet.c
fts3_porter.lo: $(TOP)\ext\fts3\fts3_porter.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_porter.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_porter.c
fts3_tokenizer.lo: $(TOP)\ext\fts3\fts3_tokenizer.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer.c
fts3_tokenizer1.lo: $(TOP)\ext\fts3\fts3_tokenizer1.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c
fts3_tokenize_vtab.lo: $(TOP)\ext\fts3\fts3_tokenize_vtab.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenize_vtab.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenize_vtab.c
fts3_unicode.lo: $(TOP)\ext\fts3\fts3_unicode.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c
fts3_unicode2.lo: $(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c
fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c
rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR)
- $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c
# Rules to build the 'testfixture' application.
@@ -1453,7 +1562,7 @@ TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
-TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) libsqlite3.lib
+TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) $(SHELL_CORE_DEP)
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
!IF $(USE_AMALGAMATION)==0
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
@@ -1493,52 +1602,52 @@ sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(
echo ; return zMainloop; } >> $@
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
- $(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
+ $(LTLINK) $(NO_WARN) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
testloadext.lo: $(TOP)\src\test_loadext.c
- $(LTCOMPILE) -c $(TOP)\src\test_loadext.c
+ $(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
testloadext.dll: testloadext.lo
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C)
- $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showdb.c $(SQLITE3C)
showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C)
- $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showstat4.c $(SQLITE3C)
showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C)
- $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showjournal.c $(SQLITE3C)
showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C)
- $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showwal.c $(SQLITE3C)
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C)
- $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C)
rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C)
- $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\rollback-test.c $(SQLITE3C)
LogEst.exe: $(TOP)\tool\logest.c sqlite3.h
- $(LTLINK) -Fe$@ $(TOP)\tool\LogEst.c
+ $(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C)
- $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\wordcount.c $(SQLITE3C)
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C)
- $(LTLINK) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
+ $(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\speedtest1.c $(SQLITE3C)
clean:
- del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib 2>NUL
+ del /Q *.exp *.lo *.ilk *.lib *.obj *.pdb 2>NUL
del /Q *.cod *.da *.bb *.bbg gmon.out 2>NUL
del /Q sqlite3.h opcodes.c opcodes.h 2>NUL
del /Q lemon.* lempar.c parse.* 2>NUL
@@ -1551,19 +1660,18 @@ clean:
-rmdir /Q/S quota2c 2>NUL
-rmdir /Q/S tsrc 2>NUL
del /Q .target_source 2>NUL
- del /Q tclsqlite3.exe tclsqlite3.exp 2>NUL
- del /Q testloadext.dll testloadext.exp 2>NUL
- del /Q testfixture.exe testfixture.exp test.db 2>NUL
+ del /Q tclsqlite3.exe 2>NUL
+ del /Q testloadext.dll 2>NUL
+ del /Q testfixture.exe test.db 2>NUL
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
- del /Q wordcount.exe 2>NUL
- del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def 2>NUL
+ del /Q mptester.exe wordcount.exe 2>NUL
+ del /Q sqlite3.exe sqlite3.dll sqlite3.def 2>NUL
del /Q sqlite3.c sqlite3-*.c 2>NUL
del /Q sqlite3rc.h 2>NUL
del /Q shell.c sqlite3ext.h 2>NUL
- del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c 2>NUL
+ del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
del /Q sqlite-*-output.vsix 2>NUL
- del /Q mptester.exe 2>NUL
# Dynamic link library section.
#
@@ -1575,5 +1683,5 @@ sqlite3.def: libsqlite3.lib
| $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \
| sort >> sqlite3.def
-sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) sqlite3.def
- $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
+sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
+ $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
index a31d3f13f..c92463204 100644
--- a/ext/fts3/fts3.c
+++ b/ext/fts3/fts3.c
@@ -910,11 +910,16 @@ 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 int MAX_NPREFIX = 10000000;
const char *p; /* Iterator pointer */
int nInt = 0; /* Output value */
for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
nInt = nInt * 10 + (p[0] - '0');
+ if( nInt>MAX_NPREFIX ){
+ nInt = 0;
+ break;
+ }
}
if( p==*pp ) return SQLITE_ERROR;
*pnOut = nInt;
@@ -957,7 +962,6 @@ static int fts3PrefixParameter(
aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
*apIndex = aIndex;
- *pnIndex = nIndex;
if( !aIndex ){
return SQLITE_NOMEM;
}
@@ -967,13 +971,20 @@ static int fts3PrefixParameter(
const char *p = zParam;
int i;
for(i=1; i<nIndex; i++){
- int nPrefix;
+ int nPrefix = 0;
if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR;
- aIndex[i].nPrefix = nPrefix;
+ assert( nPrefix>=0 );
+ if( nPrefix==0 ){
+ nIndex--;
+ i--;
+ }else{
+ aIndex[i].nPrefix = nPrefix;
+ }
p++;
}
}
+ *pnIndex = nIndex;
return SQLITE_OK;
}
diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c
index 04f84460e..2b985f5f3 100644
--- a/ext/fts3/fts3_tokenizer.c
+++ b/ext/fts3/fts3_tokenizer.c
@@ -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);
@@ -161,6 +163,10 @@ int sqlite3Fts3InitTokenizer(
zEnd = &zCopy[strlen(zCopy)];
z = (char *)sqlite3Fts3NextToken(zCopy, &n);
+ if( z==0 ){
+ assert( n==0 );
+ z = zCopy;
+ }
z[n] = '\0';
sqlite3Fts3Dequote(z);
diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c
index 09294bc45..a16070766 100644
--- a/ext/fts3/fts3_write.c
+++ b/ext/fts3/fts3_write.c
@@ -1625,7 +1625,10 @@ int sqlite3Fts3SegReaderNew(
** an array of pending terms by term. This occurs as part of flushing
** the contents of the pending-terms hash table to the database.
*/
-static int fts3CompareElemByTerm(const void *lhs, const void *rhs){
+static int SQLITE_CDECL fts3CompareElemByTerm(
+ const void *lhs,
+ const void *rhs
+){
char *z1 = fts3HashKey(*(Fts3HashElem **)lhs);
char *z2 = fts3HashKey(*(Fts3HashElem **)rhs);
int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs);
diff --git a/ext/fts3/tool/fts3view.c b/ext/fts3/tool/fts3view.c
index 3dc1ba80f..6dada352b 100644
--- a/ext/fts3/tool/fts3view.c
+++ b/ext/fts3/tool/fts3view.c
@@ -504,7 +504,7 @@ static void showSegdirMap(sqlite3 *db, const char *zTab){
sqlite3_column_int64(pStmt,5));
printf(" root %9s\n", rtag);
if( iLEnd>iStart ){
- sqlite3_int64 iLower, iPrev, iX;
+ sqlite3_int64 iLower, iPrev = 0, iX;
if( iLEnd+1<=iEnd ){
sqlite3_bind_int64(pStmt2, 1, iLEnd+1);
sqlite3_bind_int64(pStmt2, 2, iEnd);
@@ -548,7 +548,7 @@ static void decodeSegment(
const unsigned char *aData, /* Content to print */
int nData /* Number of bytes of content */
){
- sqlite3_int64 iChild;
+ sqlite3_int64 iChild = 0;
sqlite3_int64 iPrefix;
sqlite3_int64 nTerm;
sqlite3_int64 n;
diff --git a/manifest b/manifest
index f5a7bb25c..31331069b 100644
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C When\sthe\sOTA\smodule\supdates\sor\sdeletes\sa\srow,\ssave\sonly\sthose\sfields\sthat\sare\spart\sof\san\sindex\sor\sprimary\skey\sto\sthe\sota\supdate\sdatabase.
-D 2015-03-24T18:03:29.870
+C Merge\sthe\slatest\strunk\schanges\sinto\sthis\sbranch.
+D 2015-03-24T18:21:41.611
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
-F Makefile.in 2f643d6968dfc0b82d2e546a0525a39079f9e928
+F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
-F Makefile.msc 529e61cd9d29a3934758b4b3a0bb649b6c653481
+F Makefile.msc cd626b52ebeec0e2c0dd929243bdd25b0df19a71
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
F VERSION 319eb1ced4b4d17a67730f2b7b85f15c1346cb60
@@ -78,7 +78,7 @@ 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 56a78f7e65e9e59bd0e75a1e10ce406f62034ca8
+F ext/fts3/fts3.c 2a1cf23133d0c75ce296d17440c44115f8413ec7
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 394858c12a17740f7a1f6bd372c4606d4425a8d1
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
@@ -91,15 +91,15 @@ 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 bbdc731bc91338050675c6d1da9ab82147391e16
+F ext/fts3/fts3_tokenizer.c b7e586baeb8d0a061cf01a0f7081d88f3935eecf
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
-F ext/fts3/fts3_write.c 9b3a32cbecf40a1f41cb08c00df8c066c23c7a25
+F ext/fts3/fts3_write.c 7104ec015474ee61a8a570349b925f35c6b0a294
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
-F ext/fts3/tool/fts3view.c 3986531f2fc0ceca0c89c31ec7d0589b6adb19d6
+F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl a2567f9d6ad6779879a2e394c120ad8718557e65
@@ -176,34 +176,34 @@ F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
-F mptest/crash01.test cce8e306d8596d5a2e497e27112dae1f6e5e3538
+F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
-F mptest/mptest.c 24c5f72415df2eab7088ef8c9f99f163aed590c8
-F mptest/multiwrite01.test 499ad0310da8dff8e8f98d2e272fc2a8aa741b2e
+F mptest/mptest.c 1e464f41f1bbc6578d6925043da56170f83aea96
+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 ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
+F src/alter.c d23d6b6991f66b383934f137fd4384d93fb98c81
F src/analyze.c 91540f835163d5369ccbae78e2e6c74d0dd53c1d
F src/attach.c 880f9b8641a829c563e52dd13c452ce457ae4dd8
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
-F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
-F src/btree.c a31ac00e30fb7bb49e90e48ce29ef8a61591be96
-F src/btree.h 9cbbb92aab22ef8b50493c40aa3f8de87c43a2fb
+F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
+F src/btree.c 3e320cac836546c905bd90007074d887980aa70e
+F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 2bfefc01875d8da066504c233ec259fcb3b2ef72
-F src/build.c ba45ebd02904e84d98839a6ea74c3eb948596587
+F src/build.c 0419bba592c22f6d00e6d57a2ca7136720d02c1a
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
-F src/expr.c 3ef111b88ae2941b84b6b6ea4be8d501ba1af0cb
+F src/expr.c d09dac67d53c78880ba31d56e8ba2be3a6490553
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12
-F src/func.c 44512c557d6d4a40e51f3980c5854ae3e92862d6
+F src/func.c 1414c24c873c48796ad45942257a179a423ba42f
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
@@ -213,8 +213,8 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
-F src/main.c fa997fa27d95febc16d57095299384b667a7f762
-F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
+F src/main.c 569d45ba9eb4fbdd631d53f440bcdb4a35ab1505
+F src/malloc.c e818a0db9ac0898f9dc74002f3a5baca32232d05
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -232,15 +232,15 @@ 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 49d06acee4053920e4a6429844f440b5f975cea4
+F src/os_unix.c a4dadbc2da41599e99093e91e276c38c17a73b89
F src/os_win.c 8223e7db5b7c4a81d8b161098ac3959400434cdb
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
-F src/parse.y 0f8e7d60f0ab3cb53d270adef69259ac307d83a8
+F src/parse.y 1299c66e7b1707322ccd8af43a359b8fb0d46d72
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
-F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf
+F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9
F src/pragma.c ac4f3f856b4234e85f55b0f069698a4766011100
F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f
F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9
@@ -248,16 +248,16 @@ F src/printf.c 8da9a2687a396daa19860f4dc90975d319304744
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c f4d79e31ffa5820c2e3d1740baa5e9b190425f2b
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
-F src/select.c 94e016b6733b1d39a2f4c8d431155b4c2897d907
-F src/shell.c cce82ca26392578a4a1ee927dfe55ea3411c7c92
-F src/sqlite.h.in 95df7ba81981e1de0729ba14d1acbd8c4c6a9697
+F src/select.c 72ffb62e2879956302140e9f6e6ae88aee36b0e5
+F src/shell.c 3ae1e53878d2804fe77b8c8f1f6ca287a0e5d80e
+F src/sqlite.h.in 8ee1be5d82b093354c418e06e272deeb29f6f5c0
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
-F src/sqliteInt.h fae682c2b4dfbe489b134d74521c41c088f16ab1
+F src/sqliteInt.h bedf15914c09bfb5fe3ec4e3f211a4a6fc42cd33
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
-F src/status.c 81712116e826b0089bb221b018929536b2b5406f
+F src/status.c 2e5c86866ff2f30988ce10ddbaa7ba2eaf6d4146
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
-F src/tclsqlite.c fb310fcbb6f8b6c9af0cb3efda805fd04a6faf45
+F src/tclsqlite.c 796b427293e8f0e2769d3956c23df66880fe5535
F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
@@ -276,7 +276,7 @@ F src/test_config.c 7d28ede476189eefd75252fa9acaadc6ba93a733
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
-F src/test_func.c 14e543ae4d905ee31dc322b2f8d31bfac1769d45
+F src/test_func.c f1ac201465472e76a73e2f3695c3553c63e7322a
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
@@ -284,7 +284,7 @@ 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 61edf02530f7511a0529352cd8139ead3af4c401
+F src/test_multiplex.c 97813565daa7ee480abcc5dd1e9984ed1f71eb8c
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
@@ -301,31 +301,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 5a14c63da9579ba148138c1fb233100f2eb58ebb
+F src/test_vfs.c b7e6831e6fcf04c5090accff30640ec5c9630739
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
-F src/tokenize.c 05e52378c46efbc1fd63cbbbf7f3c555f840f4bf
+F src/tokenize.c a8d270b06e5f709930f7b67cf70a847969cb5bf3
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec
-F src/vdbe.c 94cbc2115075b1a562a2a702c29ba48e74f85d34
+F src/vdbe.c bbfede5a8a6908b3ddcd55fdb0b2301288dd4754
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
-F src/vdbeInt.h bb56fd199d8af1a2c1b9639ee2f70724b4338e3a
-F src/vdbeapi.c dac0d0d8009a8aa549cd77d9c29da44c0344f0c4
-F src/vdbeaux.c 97911edb61074b871ec4aa2d6bb779071643dee5
+F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0
+F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75
+F src/vdbeaux.c 413dc496248ac18eb0c19e35e86bb1ffd47b8907
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
-F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f
-F src/vdbesort.c 6d64c5448b64851b99931ede980addc3af70d5e2
+F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9
+F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
-F src/vtab.c 699f2b8d509cfe379c33dde33827875d5b030e01
+F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
-F src/wal.c 39303f2c9db02a4e422cd8eb2c8760420c6a51fe
+F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
-F src/where.c 67c115096fac6c286ab517939d368cfb12ed0d2d
+F src/where.c d336e91893370787853733e177d4dcd4db0a0283
F src/whereInt.h c1fd5690f91d9551c0c42aa44205248bbd3f7650
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -345,12 +345,13 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82
-F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a
+F test/analyze9.test 3dd9e203fad353ec8027b18a6d9a92af59f4e727
F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
+F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@@ -415,7 +416,7 @@ F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
-F test/collate1.test 73b91005f264b7c403e2d63a6708d150679ac99a
+F test/collate1.test 7fcfe78f9613dc4a7e247d6bd27749955f108741
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
F test/collate3.test 79558a286362cb9ed603c6fa543f1cda7f563f0f
F test/collate4.test f04d5168685f2eef637ecfa2d4ddf8ec0d600177
@@ -460,6 +461,7 @@ F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
F test/crash8.test 61442a9964ab6b124fc5254e4258b45747842e6f
+F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
@@ -580,7 +582,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 fca30fd86db9241d571c637751e9a8a2f50f1451
+F test/fts3atoken.test e3a126365131a6db52efc20a9a6053cd44e5f289
F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221
F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
@@ -608,9 +610,9 @@ F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
-F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
+F test/fts3prefix.test 9f68e3598a139c23ec47d09299420e0fc4c72a83
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
-F test/fts3query.test d81ffb0ab1d4e1a2a330b8eb1e160b60603f4745
+F test/fts3query.test c838b18f2b859e15fd31c64be3d79ef1556803ca
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 03c2f3be7d3b7c8bb105ed237f204833392bd57f
@@ -657,11 +659,12 @@ F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
F test/in5.test 1de657472fa9ac2924be25c2c959ac5ca1aae554
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
-F test/incrblob2.test 0d8821730a84f90af78a9dd547fe7a2480a06240
+F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab
F test/incrblob_err.test af1f12ba60d220c9752073ff2bda2ad59e88960d
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
+F test/incrcorrupt.test 9786cba68c5832f01887fde1c06b43c3904d86f6
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
F test/incrvacuum2.test 676c41428765d58f1da7dbe659ef27726d3d30ac
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
@@ -720,14 +723,14 @@ F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
-F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
+F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
F test/main.test 16131264ea0c2b93b95201f0c92958e85f2ba11a
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 96939d2d1a6f39667bbebe5bc27c6525f2ab614e
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
-F test/malloc5.test fafce0aa9157060445cd1a56ad50fc79d82f28c3
+F test/malloc5.test 79182b8bffd6d62f77b1a5a8ba8e6bf0e5053b8e
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
@@ -743,7 +746,7 @@ F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f
F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
-F test/mallocK.test 223cc80c870c80d4a9c2014e94133efdf0123f82
+F test/mallocK.test da01dcdd316767b8356741f8d33a23a06a23def5
F test/mallocL.test 252ddc7eb4fbf75364eab17b938816085ff1fc17
F test/malloc_common.tcl 3663f9001ce3e29bbaa9677ffe15cd468e3ec7e3
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
@@ -756,7 +759,7 @@ 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 f3f59b3941c84a10860c06c07e86ad367a74ec92
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
@@ -882,7 +885,7 @@ F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test ca88b14a8fc8b1f3543a24e519d019585ac9c903
F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
-F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
+F test/shell4.test ddf0a99044e2245a87fc17423e3aaa1445b3243b
F test/shell5.test c04e9f9f948305706b88377c464c7f08ce7479f9
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -925,7 +928,7 @@ F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
F test/table.test 06271d61eb13871490d38168433c1ef3dd82bb2a
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
-F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
+F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
@@ -1127,8 +1130,8 @@ 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/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
+F test/vtab1.test c9dc2a73e93331d70b37ce4b246ef6dc18412fef
+F test/vtab2.test 3644649aa8d1daac57fd541f6a5f914cac59203e
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
@@ -1158,6 +1161,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 ffc761cd467a93ccd8cd998a23be2f21b95a83b1
F test/walcksum.test 9afeb96240296c08c72fc524d199c912cfe34daa
F test/walcrash.test 451d79e528add5c42764cea74aa2750754171b25
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
@@ -1197,7 +1201,7 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test 71642fa56e9b06e5cfffe6bad67cb8c1eb2c555a
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
-F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068
+F test/with1.test 9df5cd8a62148b3d9ef8597aea563e3863018bcd
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151
@@ -1205,11 +1209,11 @@ F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test 1081aabf60a1e1123b7f9a8f6ae19954351843b0
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862
-F test/without_rowid6.test deddb78ef539c355bddec00cdfaea6c56efd8b3f
+F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
-F tool/build-all-msvc.bat a0534c971b86fe95f1983f445db5b896d3394818 x
+F tool/build-all-msvc.bat 72e05bc8deca39a547884485c086b915f50a91ed x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
@@ -1238,7 +1242,7 @@ 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 bd073a78bce714a0e42d92ea474b3eb8cb53be5d
+F tool/showdb.c 63cdef19e7fbca0c164b096ef8aef3bb9e9dd222
F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5
F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
@@ -1261,7 +1265,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 858de8a5e7925bd96d7b9c0f00bc16358cf3b295
-R 8b55a1f50bfcaf2003b1038217883d03
+P 6326fd3249bee267da0172f8afd1e7b3f71521b9 cbeb9a1aed8ce3fb569a7717ad03c7c058b68de6
+R 1fefa9d8d8de814a981dd2146a1968d2
U dan
-Z 9f88de65f5585dc798e54fceff613e97
+Z 463c60d6ebf3658e4a29b2b71d7b17dd
diff --git a/manifest.uuid b/manifest.uuid
index c8d380d77..a32f7fa4f 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-6326fd3249bee267da0172f8afd1e7b3f71521b9 \ No newline at end of file
+9d9b6c883b4f7d69c615cedfb59a2385aac47b74 \ No newline at end of file
diff --git a/mptest/crash01.test b/mptest/crash01.test
index 46f170cec..f1483dfa1 100644
--- a/mptest/crash01.test
+++ b/mptest/crash01.test
@@ -32,6 +32,7 @@
--end
--wait 1
--task 2
+ DROP TABLE IF EXISTS t2;
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
INSERT INTO t2 SELECT a, b FROM t1;
UPDATE t1 SET b='x'||a||'y';
@@ -46,6 +47,7 @@
--match 29 28 27 26 25
--end
--task 3
+ DROP TABLE IF EXISTS t3;
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
INSERT INTO t3 SELECT a, b FROM t1;
UPDATE t1 SET b='x'||a||'y';
@@ -60,6 +62,7 @@
--match 29 28 27 26 25
--end
--task 4
+ DROP TABLE IF EXISTS t4;
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
INSERT INTO t4 SELECT a, b FROM t1;
UPDATE t1 SET b='x'||a||'y';
@@ -74,6 +77,7 @@
--match 29 28 27 26 25
--end
--task 5
+ DROP TABLE IF EXISTS t5;
CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
INSERT INTO t5 SELECT a, b FROM t1;
UPDATE t1 SET b='x'||a||'y';
diff --git a/mptest/mptest.c b/mptest/mptest.c
index 7b56b6190..40c14bc87 100644
--- a/mptest/mptest.c
+++ b/mptest/mptest.c
@@ -1252,7 +1252,7 @@ static void unrecognizedArguments(
exit(1);
}
-int main(int argc, char **argv){
+int SQLITE_CDECL main(int argc, char **argv){
const char *zClient;
int iClient;
int n, i;
@@ -1262,6 +1262,9 @@ int main(int argc, char **argv){
int taskId;
const char *zTrace;
const char *zCOption;
+ const char *zJMode;
+ const char *zNRep;
+ int nRep = 1, iRep;
g.argv0 = argv[0];
g.iTrace = 1;
@@ -1277,6 +1280,10 @@ int main(int argc, char **argv){
}
n = argc-2;
sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.mptest", GETPID());
+ zJMode = findOption(argv+2, &n, "journalmode", 1);
+ zNRep = findOption(argv+2, &n, "repeat", 1);
+ if( zNRep ) nRep = atoi(zNRep);
+ if( nRep<1 ) nRep = 1;
g.zVfs = findOption(argv+2, &n, "vfs", 1);
zClient = findOption(argv+2, &n, "client", 1);
g.zErrLog = findOption(argv+2, &n, "errlog", 1);
@@ -1348,7 +1355,11 @@ int 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"
+ "DROP TABLE IF EXISTS client;\n"
"CREATE TABLE task(\n"
" id INTEGER PRIMARY KEY,\n"
" name TEXT,\n"
@@ -1364,10 +1375,12 @@ int main(int argc, char **argv){
"CREATE TABLE client(id INTEGER PRIMARY KEY, wantHalt);\n"
);
zScript = readFile(argv[2]);
- if( g.iTrace ) logMessage("begin script [%s]\n", argv[2]);
- runScript(0, 0, zScript, argv[2]);
+ for(iRep=1; iRep<=nRep; iRep++){
+ if( g.iTrace ) logMessage("begin script [%s] cycle %d\n", argv[2], iRep);
+ runScript(0, 0, zScript, argv[2]);
+ if( g.iTrace ) logMessage("end script [%s] cycle %d\n", argv[2], iRep);
+ }
sqlite3_free(zScript);
- if( g.iTrace ) logMessage("end script [%s]\n", argv[2]);
waitForClient(0, 2000, "during shutdown...\n");
trySql("UPDATE client SET wantHalt=1");
sqlite3_sleep(10);
@@ -1391,7 +1404,7 @@ int main(int argc, char **argv){
}
sqlite3_finalize(pStmt);
}
- sqlite3_close(g.db);
+ sqlite3_close(g.db);
maybeClose(g.pLog);
maybeClose(g.pErrLog);
if( iClient==0 ){
diff --git a/mptest/multiwrite01.test b/mptest/multiwrite01.test
index 4f88a6894..7062ae0d5 100644
--- a/mptest/multiwrite01.test
+++ b/mptest/multiwrite01.test
@@ -361,6 +361,8 @@ PRAGMA integrity_check(10);
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
ORDER BY t3.a LIMIT 7
--match 45 46 47 48 49 50 51
+ PRAGMA integrity_check;
+ --match ok
--end
--task 5
SELECT t1.a FROM t1, t2
@@ -371,6 +373,8 @@ PRAGMA integrity_check(10);
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
ORDER BY t3.a LIMIT 7
--match 45 46 47 48 49 50 51
+ PRAGMA integrity_check;
+ --match ok
--end
--task 3
SELECT t1.a FROM t1, t2
@@ -381,6 +385,8 @@ PRAGMA integrity_check(10);
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
ORDER BY t3.a LIMIT 7
--match 45 46 47 48 49 50 51
+ PRAGMA integrity_check;
+ --match ok
--end
--task 2
SELECT t1.a FROM t1, t2
@@ -391,6 +397,8 @@ PRAGMA integrity_check(10);
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
ORDER BY t3.a LIMIT 7
--match 45 46 47 48 49 50 51
+ PRAGMA integrity_check;
+ --match ok
--end
--task 4
SELECT t1.a FROM t1, t2
@@ -401,5 +409,7 @@ PRAGMA integrity_check(10);
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
ORDER BY t3.a LIMIT 7
--match 45 46 47 48 49 50 51
+ PRAGMA integrity_check;
+ --match ok
--end
--wait all
diff --git a/src/alter.c b/src/alter.c
index dd060248b..03605b25a 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -690,7 +690,10 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
*/
if( pDflt ){
sqlite3_value *pVal = 0;
- if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
+ int rc;
+ rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal);
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ if( rc!=SQLITE_OK ){
db->mallocFailed = 1;
return;
}
diff --git a/src/btmutex.c b/src/btmutex.c
index f9fe5b3dd..c9c8572df 100644
--- a/src/btmutex.c
+++ b/src/btmutex.c
@@ -141,6 +141,7 @@ static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){
** Exit the recursive mutex on a Btree.
*/
void sqlite3BtreeLeave(Btree *p){
+ assert( sqlite3_mutex_held(p->db->mutex) );
if( p->sharable ){
assert( p->wantToLock>0 );
p->wantToLock--;
diff --git a/src/btree.c b/src/btree.c
index 8957b74c1..ac0c87731 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -2017,8 +2017,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 );
@@ -7480,7 +7480,8 @@ static int balance(BtCursor *pCur){
** pSpace buffer passed to the latter call to balance_nonroot().
*/
u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
- rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints);
+ rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1,
+ pCur->hints&BTREE_BULKLOAD);
if( pFree ){
/* If pFree is not NULL, it points to the pSpace buffer used
** by a previous call to balance_nonroot(). Its contents are
@@ -9143,14 +9144,23 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
}
/*
-** set the mask of hint flags for cursor pCsr. Currently the only valid
-** values are 0 and BTREE_BULKLOAD.
+** set the mask of hint flags for cursor pCsr.
*/
void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
- assert( mask==BTREE_BULKLOAD || mask==0 );
+ assert( mask==BTREE_BULKLOAD || mask==BTREE_SEEK_EQ || mask==0 );
pCsr->hints = mask;
}
+#ifdef SQLITE_DEBUG
+/*
+** Return true if the cursor has a hint specified. This routine is
+** only used from within assert() statements
+*/
+int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
+ return (pCsr->hints & mask)!=0;
+}
+#endif
+
/*
** Return true if the given Btree is read-only.
*/
diff --git a/src/btree.h b/src/btree.h
index 77d12f78d..3edc2b3b5 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -152,8 +152,18 @@ int sqlite3BtreeNewDb(Btree *p);
/*
** Values that may be OR'd together to form the second argument of an
** sqlite3BtreeCursorHints() call.
+**
+** The BTREE_BULKLOAD flag is set on index cursors when the index is going
+** to be filled with content that is already in sorted order.
+**
+** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or
+** OP_SeekLE opcodes for a range search, but where the range of entries
+** selected will all have the same key. In other words, the cursor will
+** be used only for equality key searches.
+**
*/
-#define BTREE_BULKLOAD 0x00000001
+#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
+#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
@@ -199,6 +209,9 @@ void sqlite3BtreeIncrblobCursor(BtCursor *);
void sqlite3BtreeClearCursor(BtCursor *);
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
+#ifdef SQLITE_DEBUG
+int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
+#endif
int sqlite3BtreeIsReadonly(Btree *pBt);
int sqlite3HeaderSizeBtree(void);
diff --git a/src/build.c b/src/build.c
index 54dd526b5..fcf96bd42 100644
--- a/src/build.c
+++ b/src/build.c
@@ -3183,6 +3183,7 @@ Index *sqlite3CreateIndex(
pIdx->onError = pIndex->onError;
}
}
+ pRet = pIdx;
goto exit_create_index;
}
}
diff --git a/src/expr.c b/src/expr.c
index 5457a9c06..e6ac0f679 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -69,10 +69,11 @@ char sqlite3ExprAffinity(Expr *pExpr){
Expr *sqlite3ExprAddCollateToken(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* Add the "COLLATE" clause to this expression */
- const Token *pCollName /* Name of collating sequence */
+ const Token *pCollName, /* Name of collating sequence */
+ int dequote /* True to dequote pCollName */
){
if( pCollName->n>0 ){
- Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
+ Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
if( pNew ){
pNew->pLeft = pExpr;
pNew->flags |= EP_Collate|EP_Skip;
@@ -86,7 +87,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
assert( zC!=0 );
s.z = zC;
s.n = sqlite3Strlen30(s.z);
- return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
+ return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0);
}
/*
@@ -396,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);
}
diff --git a/src/func.c b/src/func.c
index d917bdbec..782a24088 100644
--- a/src/func.c
+++ b/src/func.c
@@ -22,7 +22,9 @@
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
- VdbeOp *pOp = &context->pVdbe->aOp[context->iOp-1];
+ VdbeOp *pOp;
+ assert( context->pVdbe!=0 );
+ pOp = &context->pVdbe->aOp[context->iOp-1];
assert( pOp->opcode==OP_CollSeq );
assert( pOp->p4type==P4_COLLSEQ );
return pOp->p4.pColl;
diff --git a/src/main.c b/src/main.c
index 092cbf841..696713114 100644
--- a/src/main.c
+++ b/src/main.c
@@ -128,6 +128,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
diff --git a/src/malloc.c b/src/malloc.c
index 4960f91e0..264d046ec 100644
--- a/src/malloc.c
+++ b/src/malloc.c
@@ -76,6 +76,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
** limit.
@@ -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;
@@ -266,7 +273,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 +290,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 +368,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 +416,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 +459,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 +468,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 +485,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 +530,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 +543,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 +577,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 +710,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 ){
diff --git a/src/os_unix.c b/src/os_unix.c
index 927b9e1c5..a9c883a93 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -248,6 +248,7 @@ static pid_t randomnessPid = 0;
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings issued */
+#define UNIXFILE_BLOCK 0x0200 /* Next SHM lock might block */
/*
** Include code that is common to all os_*.c files
@@ -1535,7 +1536,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
@@ -1743,7 +1744,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 ){
@@ -2170,7 +2171,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 */
@@ -2388,7 +2389,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 */
@@ -2556,7 +2557,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 */
@@ -2770,7 +2771,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
@@ -2956,7 +2957,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 ){
@@ -3781,6 +3782,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;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
@@ -4090,15 +4095,17 @@ struct unixShm {
** otherwise.
*/
static int unixShmSystemLock(
- unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
+ unixFile *pFile, /* Open connection to the WAL file */
int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
int ofst, /* First byte of the locking range */
int n /* Number of bytes to lock */
){
- struct flock f; /* The posix advisory locking structure */
- int rc = SQLITE_OK; /* Result code form fcntl() */
+ unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */
+ struct flock f; /* The posix advisory locking structure */
+ int rc = SQLITE_OK; /* Result code form fcntl() */
/* Access to the unixShmNode object is serialized by the caller */
+ pShmNode = pFile->pInode->pShmNode;
assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
/* Shared locks never span more than one byte */
@@ -4108,6 +4115,7 @@ static int unixShmSystemLock(
assert( n>=1 && n<SQLITE_SHM_NLOCK );
if( pShmNode->h>=0 ){
+ int lkType;
/* Initialize the locking parameters */
memset(&f, 0, sizeof(f));
f.l_type = lockType;
@@ -4115,8 +4123,10 @@ static int unixShmSystemLock(
f.l_start = ofst;
f.l_len = n;
- rc = osFcntl(pShmNode->h, F_SETLK, &f);
+ lkType = (pFile->ctrlFlags & UNIXFILE_BLOCK)!=0 ? F_SETLKW : F_SETLK;
+ rc = osFcntl(pShmNode->h, lkType, &f);
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
+ pFile->ctrlFlags &= ~UNIXFILE_BLOCK;
}
/* Update the global lock state and do debug tracing */
@@ -4326,13 +4336,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** If not, truncate the file to zero length.
*/
rc = SQLITE_OK;
- if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
+ if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
if( robust_ftruncate(pShmNode->h, 0) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
}
}
if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
+ rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1);
}
if( rc ) goto shm_open_err;
}
@@ -4564,7 +4574,7 @@ static int unixShmLock(
/* Unlock the system-level locks */
if( (mask & allMask)==0 ){
- rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+ rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
}else{
rc = SQLITE_OK;
}
@@ -4592,7 +4602,7 @@ static int unixShmLock(
/* Get shared locks at the system level, if necessary */
if( rc==SQLITE_OK ){
if( (allShared & mask)==0 ){
- rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
+ rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
}else{
rc = SQLITE_OK;
}
@@ -4617,7 +4627,7 @@ static int unixShmLock(
** also mark the local connection as being locked.
*/
if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
+ rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
assert( (p->sharedMask & mask)==0 );
p->exclMask |= mask;
@@ -4626,7 +4636,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;
}
@@ -5721,8 +5731,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);
}
@@ -6113,7 +6123,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;
@@ -6434,7 +6444,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);
@@ -6456,7 +6466,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;
}
@@ -6483,7 +6493,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;
}
}
@@ -6492,7 +6502,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;
}
@@ -6798,7 +6808,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 ){
@@ -7008,7 +7018,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);
}
@@ -7150,7 +7160,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 ){
diff --git a/src/parse.y b/src/parse.y
index 78e79cd36..b8ef26810 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -860,7 +860,7 @@ expr(A) ::= VARIABLE(X). {
spanSet(&A, &X, &X);
}
expr(A) ::= expr(E) COLLATE ids(C). {
- A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C);
+ A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C, 1);
A.zStart = E.zStart;
A.zEnd = &C.z[C.n];
}
@@ -1206,14 +1206,14 @@ uniqueflag(A) ::= . {A = OE_None;}
idxlist_opt(A) ::= . {A = 0;}
idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;}
idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). {
- Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C);
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1);
A = sqlite3ExprListAppend(pParse,X, p);
sqlite3ExprListSetName(pParse,A,&Y,1);
sqlite3ExprListCheckLength(pParse, A, "index");
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
}
idxlist(A) ::= nm(Y) collate(C) sortorder(Z). {
- Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C);
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1);
A = sqlite3ExprListAppend(pParse,0, p);
sqlite3ExprListSetName(pParse, A, &Y, 1);
sqlite3ExprListCheckLength(pParse, A, "index");
diff --git a/src/pcache1.c b/src/pcache1.c
index f5f789371..a8755a314 100644
--- a/src/pcache1.c
+++ b/src/pcache1.c
@@ -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
diff --git a/src/select.c b/src/select.c
index a9cecaa39..8fd0f1591 100644
--- a/src/select.c
+++ b/src/select.c
@@ -4035,7 +4035,7 @@ static int withExpand(
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
pEList = pLeft->pEList;
if( pCte->pCols ){
- if( pEList->nExpr!=pCte->pCols->nExpr ){
+ if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){
sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns",
pCte->zName, pEList->nExpr, pCte->pCols->nExpr
);
diff --git a/src/shell.c b/src/shell.c
index cf2481a37..b31ea1633 100644
--- a/src/shell.c
+++ b/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
@@ -2143,7 +2143,7 @@ static void import_append_char(ImportCtx *p, int c){
** EOF on end-of-file.
** + Report syntax errors on stderr
*/
-static char *csv_read_one_field(ImportCtx *p){
+static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
int c;
int cSep = p->cColSep;
int rSep = p->cRowSep;
@@ -2217,7 +2217,7 @@ static char *csv_read_one_field(ImportCtx *p){
** EOF on end-of-file.
** + Report syntax errors on stderr
*/
-static char *ascii_read_one_field(ImportCtx *p){
+static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
int c;
int cSep = p->cColSep;
int rSep = p->cRowSep;
@@ -2911,8 +2911,8 @@ static int do_meta_command(char *zLine, ShellState *p){
int nSep; /* Number of bytes in p->colSeparator[] */
char *zSql; /* An SQL statement */
ImportCtx sCtx; /* Reader context */
- char *(*xRead)(ImportCtx*); /* Procedure to read one value */
- int (*xCloser)(FILE*); /* Procedure to close th3 connection */
+ char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
+ int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
if( nArg!=3 ){
fprintf(stderr, "Usage: .import FILE TABLE\n");
@@ -2955,7 +2955,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sCtx.nLine = 1;
if( sCtx.zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
- fprintf(stderr, "Error: pipes are not supporte in this OS\n");
+ fprintf(stderr, "Error: pipes are not supported in this OS\n");
return 1;
#else
sCtx.in = popen(sCtx.zFile+1, "r");
@@ -3841,12 +3841,12 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
open_db(p, 0);
- output_file_close(p->traceOut);
if( nArg!=2 ){
fprintf(stderr, "Usage: .trace FILE|off\n");
rc = 1;
goto meta_command_exit;
}
+ output_file_close(p->traceOut);
p->traceOut = output_file_open(azArg[1]);
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( p->traceOut==0 ){
@@ -4354,7 +4354,7 @@ static char *cmdline_option_value(int argc, char **argv, int i){
return argv[i];
}
-int main(int argc, char **argv){
+int SQLITE_CDECL main(int argc, char **argv){
char *zErrMsg = 0;
ShellState data;
const char *zInitFile = 0;
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 1326a8793..591700693 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -50,6 +50,13 @@ extern "C" {
#endif
/*
+** Add the ability to override 'cdecl'
+*/
+#ifndef SQLITE_CDECL
+# define SQLITE_CDECL
+#endif
+
+/*
** These no-op macros are used in front of interfaces to mark those
** interfaces as either deprecated or experimental. New applications
** should not use deprecated interfaces - they are supported for backwards
@@ -945,10 +952,16 @@ struct sqlite3_io_methods {
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
+* <li>[[SQLITE_FCNTL_WAL_BLOCK]]
+** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
+** be advantageous to block on the next WAL lock if the lock is not immediately
+** available. The WAL subsystem issues this signal during rare
+** circumstances in order to fix a problem with priority inversion.
+** Applications should <em>not</em> use this file-control.
+**
** <li>[[SQLITE_FCNTL_ZIPVFS]]
** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
** VFS should return SQLITE_NOTFOUND for this opcode.
-**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -973,8 +986,9 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
-#define SQLITE_FCNTL_ZIPVFS 24
-#define SQLITE_FCNTL_OTA 25
+#define SQLITE_FCNTL_WAL_BLOCK 24
+#define SQLITE_FCNTL_ZIPVFS 25
+#define SQLITE_FCNTL_OTA 26
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1541,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
@@ -2998,11 +3012,13 @@ sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
/*
** CAPI3REF: Error Codes And Messages
**
-** ^The sqlite3_errcode() interface returns the numeric [result code] or
-** [extended result code] for the most recent failed sqlite3_* API call
-** associated with a [database connection]. If a prior API call failed
-** but the most recent API call succeeded, the return value from
-** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
+** ^If the most recent sqlite3_* API call associated with
+** [database connection] D failed, then the sqlite3_errcode(D) interface
+** returns the numeric [result code] or [extended result code] for that
+** API call.
+** If the most recent API call was successful,
+** then the return value from sqlite3_errcode() is undefined.
+** ^The sqlite3_extended_errcode()
** interface is the same except that it always returns the
** [extended result code] even when extended result codes are
** disabled.
@@ -5616,7 +5632,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 */
};
@@ -6294,7 +6310,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
@@ -6308,19 +6324,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
+);
/*
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 865976659..9df6d1bc4 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -595,6 +595,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 */
@@ -2692,7 +2707,8 @@ struct AuthContext {
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
-#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */
+#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
+#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
/*
@@ -3096,10 +3112,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
@@ -3479,7 +3500,7 @@ int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*);
+Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
diff --git a/src/status.c b/src/status.c
index 4c2eabb66..aa27f70ef 100644
--- a/src/status.c
+++ b/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,29 @@ 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);
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
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 4e147f594..19f2431d1 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -2320,34 +2320,49 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
/*
- ** $db function NAME [-argcount N] SCRIPT
+ ** $db function NAME [-argcount N] [-deterministic] SCRIPT
**
** Create a new SQL function called NAME. Whenever that function is
** called, invoke SCRIPT to evaluate the function.
*/
case DB_FUNCTION: {
+ int flags = SQLITE_UTF8;
SqlFunc *pFunc;
Tcl_Obj *pScript;
char *zName;
int nArg = -1;
- if( objc==6 ){
- const char *z = Tcl_GetString(objv[3]);
+ int i;
+ if( objc<4 ){
+ Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
+ return TCL_ERROR;
+ }
+ for(i=3; i<(objc-1); i++){
+ const char *z = Tcl_GetString(objv[i]);
int n = strlen30(z);
if( n>2 && strncmp(z, "-argcount",n)==0 ){
- if( Tcl_GetIntFromObj(interp, objv[4], &nArg) ) return TCL_ERROR;
+ if( i==(objc-2) ){
+ Tcl_AppendResult(interp, "option requires an argument: ", z, 0);
+ return TCL_ERROR;
+ }
+ if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR;
if( nArg<0 ){
Tcl_AppendResult(interp, "number of arguments must be non-negative",
(char*)0);
return TCL_ERROR;
}
+ i++;
+ }else
+ if( n>2 && strncmp(z, "-deterministic",n)==0 ){
+ flags |= SQLITE_DETERMINISTIC;
+ }else{
+ Tcl_AppendResult(interp, "bad option \"", z,
+ "\": must be -argcount or -deterministic", 0
+ );
+ return TCL_ERROR;
}
- pScript = objv[5];
- }else if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 2, objv, "NAME [-argcount N] SCRIPT");
- return TCL_ERROR;
- }else{
- pScript = objv[3];
}
+
+ pScript = objv[objc-1];
zName = Tcl_GetStringFromObj(objv[2], 0);
pFunc = findSqlFunc(pDb, zName);
if( pFunc==0 ) return TCL_ERROR;
@@ -2357,7 +2372,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
pFunc->pScript = pScript;
Tcl_IncrRefCount(pScript);
pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
- rc = sqlite3_create_function(pDb->db, zName, nArg, SQLITE_UTF8,
+ rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
pFunc, tclSqlFunc, 0, 0);
if( rc!=SQLITE_OK ){
rc = TCL_ERROR;
diff --git a/src/test_func.c b/src/test_func.c
index c7850631d..2e34fa074 100644
--- a/src/test_func.c
+++ b/src/test_func.c
@@ -600,12 +600,26 @@ static void test_decode(
Tcl_DecrRefCount(pRet);
}
+/*
+** The implementation of scalar SQL function "test_zeroblob()". This is
+** similar to the built-in zeroblob() function, except that it does not
+** check that the integer parameter is within range before passing it
+** to sqlite3_result_zeroblob().
+*/
+static void test_zeroblob(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int nZero = sqlite3_value_int(argv[0]);
+ sqlite3_result_zeroblob(context, nZero);
+}
static int registerTestFunctions(sqlite3 *db){
static const struct {
char *zName;
signed char nArg;
- unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */
+ unsigned int eTextRep; /* 1: UTF-16. 0: UTF-8 */
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
} aFuncs[] = {
{ "randstr", 2, SQLITE_UTF8, randStr },
@@ -626,6 +640,7 @@ static int registerTestFunctions(sqlite3 *db){
{ "real2hex", 1, SQLITE_UTF8, real2hex},
{ "test_decode", 1, SQLITE_UTF8, test_decode},
{ "test_extract", 2, SQLITE_UTF8, test_extract},
+ { "test_zeroblob", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob},
};
int i;
diff --git a/src/test_multiplex.c b/src/test_multiplex.c
index dbd395d62..cd379f18f 100644
--- a/src/test_multiplex.c
+++ b/src/test_multiplex.c
@@ -573,6 +573,9 @@ static int multiplexOpen(
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
if( rc==SQLITE_OK && zName ){
int bExists;
+ if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
+ pGroup->bEnabled = 0;
+ }else
if( sz==0 ){
if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
/* If opening a main journal file and the first chunk is zero
diff --git a/src/test_vfs.c b/src/test_vfs.c
index 561addfcc..2277cf7eb 100644
--- a/src/test_vfs.c
+++ b/src/test_vfs.c
@@ -967,16 +967,15 @@ static void tvfsShmBarrier(sqlite3_file *pFile){
TestvfsFd *pFd = tvfsGetFd(pFile);
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
+ if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
+ const char *z = pFd->pShm ? pFd->pShm->zFile : "";
+ tvfsExecTcl(p, "xShmBarrier", Tcl_NewStringObj(z, -1), pFd->pShmId, 0, 0);
+ }
+
if( p->isFullshm ){
sqlite3OsShmBarrier(pFd->pReal);
return;
}
-
- if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
- tvfsExecTcl(p, "xShmBarrier",
- Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
- );
- }
}
static int tvfsShmUnmap(
@@ -1532,7 +1531,7 @@ static int testvfs_cmd(
return TCL_OK;
bad_args:
- Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?");
+ Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-fullshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?");
return TCL_ERROR;
}
diff --git a/src/tokenize.c b/src/tokenize.c
index 6fb5a35c3..5068742f3 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -459,9 +459,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;
diff --git a/src/vdbe.c b/src/vdbe.c
index f81bfa8a7..ec5e6d744 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -1517,7 +1517,7 @@ arithmetic_result_is_null:
**
** The interface used by the implementation of the aforementioned functions
** to retrieve the collation sequence set by this opcode is not available
-** publicly, only to user functions defined in func.c.
+** publicly. Only built-in functions have access to this feature.
*/
case OP_CollSeq: {
assert( pOp->p4type==P4_COLLSEQ );
@@ -3235,31 +3235,29 @@ case OP_SetCookie: { /* in3 */
** See also OpenRead.
*/
case OP_ReopenIdx: {
+ int nField;
+ KeyInfo *pKeyInfo;
+ int p2;
+ int iDb;
+ int wrFlag;
+ Btree *pX;
VdbeCursor *pCur;
+ Db *pDb;
- assert( pOp->p5==0 );
+ assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( pOp->p4type==P4_KEYINFO );
pCur = p->apCsr[pOp->p1];
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
- break;
+ goto open_cursor_set_hints;
}
/* If the cursor is not currently open or is open on a different
** index, then fall through into OP_OpenRead to force a reopen */
-}
case OP_OpenRead:
-case OP_OpenWrite: {
- int nField;
- KeyInfo *pKeyInfo;
- int p2;
- int iDb;
- int wrFlag;
- Btree *pX;
- VdbeCursor *pCur;
- Db *pDb;
+case OP_OpenWrite:
- assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
- assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
+ assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 );
+ assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( p->bIsReader );
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|| p->readOnly==0 );
@@ -3322,14 +3320,17 @@ case OP_OpenWrite: {
pCur->pgnoRoot = p2;
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
pCur->pKeyInfo = pKeyInfo;
- assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
- sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
-
/* Set the VdbeCursor.isTable variable. Previous versions of
** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has
** since moved into the btree layer. */
pCur->isTable = pOp->p4type!=P4_KEYINFO;
+
+open_cursor_set_hints:
+ assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
+ assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
+ sqlite3BtreeCursorHints(pCur->pCursor,
+ (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
break;
}
@@ -3590,6 +3591,22 @@ case OP_SeekGT: { /* jump, in3 */
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
+
+ /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
+ ** OP_SeekLE opcodes are allowed, and these must be immediately followed
+ ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
+ */
+#ifdef SQLITE_DEBUG
+ if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
+ assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
+ assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
+ assert( pOp[1].p1==pOp[0].p1 );
+ assert( pOp[1].p2==pOp[0].p2 );
+ assert( pOp[1].p3==pOp[0].p3 );
+ assert( pOp[1].p4.i==pOp[0].p4.i );
+ }
+#endif
+
if( pC->isTable ){
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
@@ -4929,30 +4946,15 @@ case OP_IdxGE: { /* jump */
*/
case OP_Destroy: { /* out2-prerelease */
int iMoved;
- int iCnt;
- Vdbe *pVdbe;
int iDb;
assert( p->readOnly==0 );
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- iCnt = 0;
- for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){
- if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader
- && pVdbe->inVtabMethod<2 && pVdbe->pc>=0
- ){
- iCnt++;
- }
- }
-#else
- iCnt = db->nVdbeRead;
-#endif
pOut->flags = MEM_Null;
- if( iCnt>1 ){
+ if( db->nVdbeRead > db->nVDestroy+1 ){
rc = SQLITE_LOCKED;
p->errorAction = OE_Abort;
}else{
iDb = pOp->p3;
- assert( iCnt==1 );
assert( DbMaskTest(p->btreeMask, iDb) );
iMoved = 0; /* Not needed. Only to silence a warning. */
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
@@ -6009,13 +6011,29 @@ case OP_VBegin: {
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VCreate P1 * * P4 *
+/* Opcode: VCreate P1 P2 * * *
**
-** P4 is the name of a virtual table in database P1. Call the xCreate method
-** for that table.
+** P2 is a register that holds the name of a virtual table in database
+** P1. Call the xCreate method for that table.
*/
case OP_VCreate: {
- rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg);
+ Mem sMem; /* For storing the record being decoded */
+ const char *zTab; /* Name of the virtual table */
+
+ memset(&sMem, 0, sizeof(sMem));
+ sMem.db = db;
+ /* Because P2 is always a static string, it is impossible for the
+ ** sqlite3VdbeMemCopy() to fail */
+ assert( (aMem[pOp->p2].flags & MEM_Str)!=0 );
+ assert( (aMem[pOp->p2].flags & MEM_Static)!=0 );
+ rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]);
+ assert( rc==SQLITE_OK );
+ zTab = (const char*)sqlite3_value_text(&sMem);
+ assert( zTab || db->mallocFailed );
+ if( zTab ){
+ rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg);
+ }
+ sqlite3VdbeMemRelease(&sMem);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -6027,9 +6045,9 @@ case OP_VCreate: {
** of that table.
*/
case OP_VDestroy: {
- p->inVtabMethod = 2;
+ db->nVDestroy++;
rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
- p->inVtabMethod = 0;
+ db->nVDestroy--;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -6045,14 +6063,17 @@ case OP_VOpen: {
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
- sqlite3_module *pModule;
+ const sqlite3_module *pModule;
assert( p->bIsReader );
pCur = 0;
pVtabCursor = 0;
pVtab = pOp->p4.pVtab->pVtab;
- pModule = (sqlite3_module *)pVtab->pModule;
- assert(pVtab && pModule);
+ if( pVtab==0 || NEVER(pVtab->pModule==0) ){
+ rc = SQLITE_LOCKED;
+ break;
+ }
+ pModule = pVtab->pModule;
rc = pModule->xOpen(pVtab, &pVtabCursor);
sqlite3VtabImportErrmsg(p, pVtab);
if( SQLITE_OK==rc ){
@@ -6063,6 +6084,7 @@ case OP_VOpen: {
pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
if( pCur ){
pCur->pVtabCursor = pVtabCursor;
+ pVtab->nRef++;
}else{
db->mallocFailed = 1;
pModule->xClose(pVtabCursor);
@@ -6128,9 +6150,7 @@ case OP_VFilter: { /* jump */
apArg[i] = &pArgc[i+1];
}
- p->inVtabMethod = 1;
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
- p->inVtabMethod = 0;
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pVtabCursor);
@@ -6220,9 +6240,7 @@ case OP_VNext: { /* jump */
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
- p->inVtabMethod = 1;
rc = pModule->xNext(pCur->pVtabCursor);
- p->inVtabMethod = 0;
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
@@ -6297,7 +6315,7 @@ case OP_VRename: {
*/
case OP_VUpdate: {
sqlite3_vtab *pVtab;
- sqlite3_module *pModule;
+ const sqlite3_module *pModule;
int nArg;
int i;
sqlite_int64 rowid;
@@ -6309,7 +6327,11 @@ case OP_VUpdate: {
);
assert( p->readOnly==0 );
pVtab = pOp->p4.pVtab->pVtab;
- pModule = (sqlite3_module *)pVtab->pModule;
+ if( pVtab==0 || NEVER(pVtab->pModule==0) ){
+ rc = SQLITE_LOCKED;
+ break;
+ }
+ pModule = pVtab->pModule;
nArg = pOp->p2;
assert( pOp->p4type==P4_VTAB );
if( ALWAYS(pModule->xUpdate) ){
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 877da1143..d3955af31 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -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 */
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index 8c0038e4e..e03640dfb 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -370,7 +370,7 @@ void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode;
pCtx->fErrorOrAux = 1;
#ifdef SQLITE_DEBUG
- pCtx->pVdbe->rcApp = errCode;
+ if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
if( pCtx->pOut->flags & MEM_Null ){
sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1,
@@ -633,16 +633,26 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
}
/*
-** Return the current time for a statement
+** Return the current time for a statement. If the current time
+** is requested more than once within the same run of a single prepared
+** statement, the exact same time is returned for each invocation regardless
+** of the amount of time that elapses between invocations. In other words,
+** the time returned is always the time of the first call.
*/
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
- Vdbe *v = p->pVdbe;
int rc;
- if( v->iCurrentTime==0 ){
- rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, &v->iCurrentTime);
- if( rc ) v->iCurrentTime = 0;
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
+ sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
+ assert( p->pVdbe!=0 );
+#else
+ sqlite3_int64 iTime = 0;
+ sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime;
+#endif
+ if( *piTime==0 ){
+ rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime);
+ if( rc ) *piTime = 0;
}
- return v->iCurrentTime;
+ return *piTime;
}
/*
@@ -712,6 +722,11 @@ void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
AuxData *pAuxData;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
+#if SQLITE_ENABLE_STAT3_OR_STAT4
+ if( pCtx->pVdbe==0 ) return 0;
+#else
+ assert( pCtx->pVdbe!=0 );
+#endif
for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
}
@@ -735,6 +750,11 @@ void sqlite3_set_auxdata(
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
if( iArg<0 ) goto failed;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( pVdbe==0 ) goto failed;
+#else
+ assert( pVdbe!=0 );
+#endif
for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index cd9ecaa69..9c5d9acca 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -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,9 +1782,9 @@ 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
}
@@ -2143,7 +2143,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** doing this the directory is synced again before any individual
** transaction files are deleted.
*/
- rc = sqlite3OsDelete(pVfs, zMaster, 1);
+ rc = sqlite3OsDelete(pVfs, zMaster, needSync);
sqlite3DbFree(db, zMaster);
zMaster = 0;
if( rc ){
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 870fb5bd8..76147442a 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -1090,7 +1090,7 @@ struct ValueNewStat4Ctx {
** Otherwise, if the second argument is non-zero, then this function is
** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
** already been allocated, allocate the UnpackedRecord structure that
-** that function will return to its caller here. Then return a pointer
+** that function will return to its caller here. Then return a pointer to
** an sqlite3_value within the UnpackedRecord.a[] array.
*/
static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
@@ -1135,6 +1135,113 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
}
/*
+** The expression object indicated by the second argument is guaranteed
+** to be a scalar SQL function. If
+**
+** * all function arguments are SQL literals,
+** * the SQLITE_FUNC_CONSTANT function flag is set, and
+** * the SQLITE_FUNC_NEEDCOLL function flag is not set,
+**
+** then this routine attempts to invoke the SQL function. Assuming no
+** error occurs, output parameter (*ppVal) is set to point to a value
+** object containing the result before returning SQLITE_OK.
+**
+** Affinity aff is applied to the result of the function before returning.
+** If the result is a text value, the sqlite3_value object uses encoding
+** enc.
+**
+** If the conditions above are not met, this function returns SQLITE_OK
+** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
+** NULL and an SQLite error code returned.
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static int valueFromFunction(
+ sqlite3 *db, /* The database connection */
+ Expr *p, /* The expression to evaluate */
+ u8 enc, /* Encoding to use */
+ u8 aff, /* Affinity to use */
+ sqlite3_value **ppVal, /* Write the new value here */
+ struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */
+){
+ sqlite3_context ctx; /* Context object for function invocation */
+ sqlite3_value **apVal = 0; /* Function arguments */
+ int nVal = 0; /* Size of apVal[] array */
+ FuncDef *pFunc = 0; /* Function definition */
+ sqlite3_value *pVal = 0; /* New value */
+ int rc = SQLITE_OK; /* Return code */
+ int nName; /* Size of function name in bytes */
+ ExprList *pList = 0; /* Function arguments */
+ int i; /* Iterator variable */
+
+ assert( pCtx!=0 );
+ assert( (p->flags & EP_TokenOnly)==0 );
+ pList = p->x.pList;
+ if( pList ) nVal = pList->nExpr;
+ nName = sqlite3Strlen30(p->u.zToken);
+ pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0);
+ assert( pFunc );
+ if( (pFunc->funcFlags & SQLITE_FUNC_CONSTANT)==0
+ || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
+ ){
+ return SQLITE_OK;
+ }
+
+ if( pList ){
+ apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal);
+ if( apVal==0 ){
+ rc = SQLITE_NOMEM;
+ goto value_from_function_out;
+ }
+ for(i=0; i<nVal; i++){
+ rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]);
+ if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
+ }
+ }
+
+ pVal = valueNew(db, pCtx);
+ if( pVal==0 ){
+ rc = SQLITE_NOMEM;
+ goto value_from_function_out;
+ }
+
+ assert( pCtx->pParse->rc==SQLITE_OK );
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.pOut = pVal;
+ ctx.pFunc = pFunc;
+ pFunc->xFunc(&ctx, nVal, apVal);
+ if( ctx.isError ){
+ rc = ctx.isError;
+ sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
+ }else{
+ sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
+ assert( rc==SQLITE_OK );
+ rc = sqlite3VdbeChangeEncoding(pVal, enc);
+ if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
+ rc = SQLITE_TOOBIG;
+ pCtx->pParse->nErr++;
+ }
+ }
+ pCtx->pParse->rc = rc;
+
+ value_from_function_out:
+ if( rc!=SQLITE_OK ){
+ pVal = 0;
+ }
+ if( apVal ){
+ for(i=0; i<nVal; i++){
+ sqlite3ValueFree(apVal[i]);
+ }
+ sqlite3DbFree(db, apVal);
+ }
+
+ *ppVal = pVal;
+ return rc;
+}
+#else
+# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
+#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
+
+/*
** Extract a value from the supplied expression in the manner described
** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
** using valueNew().
@@ -1166,6 +1273,12 @@ static int valueFromExpr(
while( (op = pExpr->op)==TK_UPLUS ) pExpr = pExpr->pLeft;
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
+ /* Compressed expressions only appear when parsing the DEFAULT clause
+ ** on a table column definition, and hence only when pCtx==0. This
+ ** check ensures that an EP_TokenOnly expression is never passed down
+ ** into valueFromFunction(). */
+ assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );
+
if( op==TK_CAST ){
u8 aff = sqlite3AffinityType(pExpr->u.zToken,0);
rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
@@ -1242,6 +1355,12 @@ static int valueFromExpr(
}
#endif
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ else if( op==TK_FUNCTION && pCtx!=0 ){
+ rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
+ }
+#endif
+
*ppVal = pVal;
return rc;
diff --git a/src/vdbesort.c b/src/vdbesort.c
index 5a43a1054..bbdafa823 100644
--- a/src/vdbesort.c
+++ b/src/vdbesort.c
@@ -1151,6 +1151,7 @@ static int vdbeSorterOpenTempFile(
sqlite3_file **ppFd
){
int rc;
+ if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS;
rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd,
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
diff --git a/src/vtab.c b/src/vtab.c
index 96a1289de..23f49bafc 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -389,6 +389,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
char *zStmt;
char *zWhere;
int iDb;
+ int iReg;
Vdbe *v;
/* Compute the complete text of the CREATE VIRTUAL TABLE statement */
@@ -423,8 +424,10 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
- sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
- pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
+
+ iReg = ++pParse->nMem;
+ sqlite3VdbeAddOp4(v, OP_String8, 0, iReg, 0, pTab->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg);
}
/* If we are rereading the sqlite_master table create the in-memory
@@ -777,11 +780,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 );
diff --git a/src/wal.c b/src/wal.c
index 71f4a3d45..558adbcad 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -788,9 +788,10 @@ static void walUnlockShared(Wal *pWal, int lockIdx){
SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
}
-static int walLockExclusive(Wal *pWal, int lockIdx, int n){
+static int walLockExclusive(Wal *pWal, int lockIdx, int n, int fBlock){
int rc;
if( pWal->exclusiveMode ) return SQLITE_OK;
+ if( fBlock ) sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_WAL_BLOCK, 0);
rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
@@ -1076,7 +1077,7 @@ static int walIndexRecover(Wal *pWal){
assert( pWal->writeLock );
iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
nLock = SQLITE_SHM_NLOCK - iLock;
- rc = walLockExclusive(pWal, iLock, nLock);
+ rc = walLockExclusive(pWal, iLock, nLock, 0);
if( rc ){
return rc;
}
@@ -1610,7 +1611,7 @@ static int walBusyLock(
){
int rc;
do {
- rc = walLockExclusive(pWal, lockIdx, n);
+ rc = walLockExclusive(pWal, lockIdx, n, 0);
}while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
return rc;
}
@@ -2043,7 +2044,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
walUnlockShared(pWal, WAL_WRITE_LOCK);
rc = SQLITE_READONLY_RECOVERY;
}
- }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
+ }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 1)) ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
@@ -2249,7 +2250,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
&& (mxReadMark<pWal->hdr.mxFrame || mxI==0)
){
for(i=1; i<WAL_NREADER; i++){
- rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1, 0);
if( rc==SQLITE_OK ){
mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
mxI = i;
@@ -2505,7 +2506,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
/* Only one writer allowed at a time. Get the write lock. Return
** SQLITE_BUSY if unable.
*/
- rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 0);
if( rc ){
return rc;
}
@@ -2650,7 +2651,7 @@ static int walRestartLog(Wal *pWal){
if( pInfo->nBackfill>0 ){
u32 salt1;
sqlite3_randomness(4, &salt1);
- rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
+ rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1, 0);
if( rc==SQLITE_OK ){
/* If all readers are using WAL_READ_LOCK(0) (in other words if no
** readers are currently using the WAL), then the transactions
@@ -2975,7 +2976,7 @@ int sqlite3WalCheckpoint(
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
** "checkpoint" lock on the database file. */
- rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1, 0);
if( rc ){
/* EVIDENCE-OF: R-10421-19736 If any other process is running a
** checkpoint operation at the same time, the lock cannot be obtained and
diff --git a/src/where.c b/src/where.c
index e95fd57f3..58e35384b 100644
--- a/src/where.c
+++ b/src/where.c
@@ -772,6 +772,79 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
pWC->a[iParent].nChild++;
}
+/*
+** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not
+** a conjunction, then return just pTerm when N==0. If N is exceeds
+** the number of available subterms, return NULL.
+*/
+static WhereTerm *whereNthSubterm(WhereTerm *pTerm, int N){
+ if( pTerm->eOperator!=WO_AND ){
+ return N==0 ? pTerm : 0;
+ }
+ if( N<pTerm->u.pAndInfo->wc.nTerm ){
+ return &pTerm->u.pAndInfo->wc.a[N];
+ }
+ return 0;
+}
+
+/*
+** Subterms pOne and pTwo are contained within WHERE clause pWC. The
+** two subterms are in disjunction - they are OR-ed together.
+**
+** If these two terms are both of the form: "A op B" with the same
+** A and B values but different operators and if the operators are
+** compatible (if one is = and the other is <, for example) then
+** add a new virtual AND term to pWC that is the combination of the
+** two.
+**
+** Some examples:
+**
+** x<y OR x=y --> x<=y
+** x=y OR x=y --> x=y
+** x<=y OR x<y --> x<=y
+**
+** The following is NOT generated:
+**
+** x<y OR x>y --> x!=y
+*/
+static void whereCombineDisjuncts(
+ SrcList *pSrc, /* the FROM clause */
+ WhereClause *pWC, /* The complete WHERE clause */
+ WhereTerm *pOne, /* First disjunct */
+ WhereTerm *pTwo /* Second disjunct */
+){
+ u16 eOp = pOne->eOperator | pTwo->eOperator;
+ sqlite3 *db; /* Database connection (for malloc) */
+ Expr *pNew; /* New virtual expression */
+ int op; /* Operator for the combined expression */
+ int idxNew; /* Index in pWC of the next virtual term */
+
+ if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
+ if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
+ if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
+ && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
+ assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
+ assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
+ if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
+ if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return;
+ /* If we reach this point, it means the two subterms can be combined */
+ if( (eOp & (eOp-1))!=0 ){
+ if( eOp & (WO_LT|WO_LE) ){
+ eOp = WO_LE;
+ }else{
+ assert( eOp & (WO_GT|WO_GE) );
+ eOp = WO_GE;
+ }
+ }
+ db = pWC->pWInfo->pParse->db;
+ pNew = sqlite3ExprDup(db, pOne->pExpr, 0);
+ if( pNew==0 ) return;
+ for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); }
+ pNew->op = op;
+ idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
+ exprAnalyze(pSrc, pWC, idxNew);
+}
+
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
/*
** Analyze a term that consists of two or more OR-connected
@@ -796,6 +869,7 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
+** (F) x>A OR (x=A AND y>=B)
**
** CASE 1:
**
@@ -812,6 +886,16 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
**
** CASE 2:
**
+** If there are exactly two disjuncts one side has x>A and the other side
+** has x=A (for the same x and A) then add a new virtual conjunct term to the
+** WHERE clause of the form "x>=A". Example:
+**
+** x>A OR (x=A AND y>B) adds: x>=A
+**
+** The added conjunct can sometimes be helpful in query planning.
+**
+** CASE 3:
+**
** If all subterms are indexable by a single table T, then set
**
** WhereTerm.eOperator = WO_OR
@@ -938,12 +1022,26 @@ static void exprAnalyzeOrTerm(
}
/*
- ** Record the set of tables that satisfy case 2. The set might be
+ ** Record the set of tables that satisfy case 3. The set might be
** empty.
*/
pOrInfo->indexable = indexable;
pTerm->eOperator = indexable==0 ? 0 : WO_OR;
+ /* For a two-way OR, attempt to implementation case 2.
+ */
+ if( indexable && pOrWc->nTerm==2 ){
+ int iOne = 0;
+ WhereTerm *pOne;
+ while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){
+ int iTwo = 0;
+ WhereTerm *pTwo;
+ while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){
+ whereCombineDisjuncts(pSrc, pWC, pOne, pTwo);
+ }
+ }
+ }
+
/*
** chngToIN holds a set of tables that *might* satisfy case 1. But
** we have to do some additional checking to see if case 1 really
@@ -1073,7 +1171,7 @@ static void exprAnalyzeOrTerm(
}else{
sqlite3ExprListDelete(db, pList);
}
- pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */
+ pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */
}
}
}
@@ -1268,7 +1366,7 @@ static void exprAnalyze(
Expr *pNewExpr2;
int idxNew1;
int idxNew2;
- Token sCollSeqName; /* Name of collating sequence */
+ const char *zCollSeqName; /* Name of collating sequence */
const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
pLeft = pExpr->x.pList->a[1].pExpr;
@@ -1304,11 +1402,10 @@ static void exprAnalyze(
}
*pC = c + 1;
}
- sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
- sCollSeqName.n = 6;
+ zCollSeqName = noCase ? "NOCASE" : "BINARY";
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
- sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
+ sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName),
pStr1, 0);
transferJoinMarkings(pNewExpr1, pExpr);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags);
@@ -1316,7 +1413,7 @@ static void exprAnalyze(
exprAnalyze(pSrc, pWC, idxNew1);
pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
- sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
+ sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName),
pStr2, 0);
transferJoinMarkings(pNewExpr2, pExpr);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags);
@@ -1933,11 +2030,14 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
** Estimate the location of a particular key among all keys in an
** index. Store the results in aStat as follows:
**
-** aStat[0] Est. number of rows less than pVal
-** aStat[1] Est. number of rows equal to pVal
+** aStat[0] Est. number of rows less than pRec
+** aStat[1] Est. number of rows equal to pRec
**
** Return the index of the sample that is the smallest sample that
-** is greater than or equal to pRec.
+** is greater than or equal to pRec. Note that this index is not an index
+** into the aSample[] array - it is an index into a virtual set of samples
+** based on the contents of aSample[] and the number of fields in record
+** pRec.
*/
static int whereKeyStats(
Parse *pParse, /* Database connection */
@@ -1948,67 +2048,158 @@ static int whereKeyStats(
){
IndexSample *aSample = pIdx->aSample;
int iCol; /* Index of required stats in anEq[] etc. */
+ int i; /* Index of first sample >= pRec */
+ int iSample; /* Smallest sample larger than or equal to pRec */
int iMin = 0; /* Smallest sample not yet tested */
- int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */
int iTest; /* Next sample to test */
int res; /* Result of comparison operation */
+ int nField; /* Number of fields in pRec */
+ tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */
#ifndef SQLITE_DEBUG
UNUSED_PARAMETER( pParse );
#endif
assert( pRec!=0 );
- iCol = pRec->nField - 1;
assert( pIdx->nSample>0 );
- assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
+ assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol );
+
+ /* Do a binary search to find the first sample greater than or equal
+ ** to pRec. If pRec contains a single field, the set of samples to search
+ ** is simply the aSample[] array. If the samples in aSample[] contain more
+ ** than one fields, all fields following the first are ignored.
+ **
+ ** If pRec contains N fields, where N is more than one, then as well as the
+ ** samples in aSample[] (truncated to N fields), the search also has to
+ ** consider prefixes of those samples. For example, if the set of samples
+ ** in aSample is:
+ **
+ ** aSample[0] = (a, 5)
+ ** aSample[1] = (a, 10)
+ ** aSample[2] = (b, 5)
+ ** aSample[3] = (c, 100)
+ ** aSample[4] = (c, 105)
+ **
+ ** Then the search space should ideally be the samples above and the
+ ** unique prefixes [a], [b] and [c]. But since that is hard to organize,
+ ** the code actually searches this set:
+ **
+ ** 0: (a)
+ ** 1: (a, 5)
+ ** 2: (a, 10)
+ ** 3: (a, 10)
+ ** 4: (b)
+ ** 5: (b, 5)
+ ** 6: (c)
+ ** 7: (c, 100)
+ ** 8: (c, 105)
+ ** 9: (c, 105)
+ **
+ ** For each sample in the aSample[] array, N samples are present in the
+ ** effective sample array. In the above, samples 0 and 1 are based on
+ ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc.
+ **
+ ** Often, sample i of each block of N effective samples has (i+1) fields.
+ ** Except, each sample may be extended to ensure that it is greater than or
+ ** equal to the previous sample in the array. For example, in the above,
+ ** sample 2 is the first sample of a block of N samples, so at first it
+ ** appears that it should be 1 field in size. However, that would make it
+ ** smaller than sample 1, so the binary search would not work. As a result,
+ ** it is extended to two fields. The duplicates that this creates do not
+ ** cause any problems.
+ */
+ nField = pRec->nField;
+ iCol = 0;
+ iSample = pIdx->nSample * nField;
do{
- iTest = (iMin+i)/2;
- res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
+ int iSamp; /* Index in aSample[] of test sample */
+ int n; /* Number of fields in test sample */
+
+ iTest = (iMin+iSample)/2;
+ iSamp = iTest / nField;
+ if( iSamp>0 ){
+ /* The proposed effective sample is a prefix of sample aSample[iSamp].
+ ** Specifically, the shortest prefix of at least (1 + iTest%nField)
+ ** fields that is greater than the previous effective sample. */
+ for(n=(iTest % nField) + 1; n<nField; n++){
+ if( aSample[iSamp-1].anLt[n-1]!=aSample[iSamp].anLt[n-1] ) break;
+ }
+ }else{
+ n = iTest + 1;
+ }
+
+ pRec->nField = n;
+ res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec);
if( res<0 ){
+ iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1];
+ iMin = iTest+1;
+ }else if( res==0 && n<nField ){
+ iLower = aSample[iSamp].anLt[n-1];
iMin = iTest+1;
+ res = -1;
}else{
- i = iTest;
+ iSample = iTest;
+ iCol = n-1;
}
- }while( res && iMin<i );
+ }while( res && iMin<iSample );
+ i = iSample / nField;
#ifdef SQLITE_DEBUG
/* The following assert statements check that the binary search code
** above found the right answer. This block serves no purpose other
** than to invoke the asserts. */
- if( res==0 ){
- /* If (res==0) is true, then sample $i must be equal to pRec */
- assert( i<pIdx->nSample );
- assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
- || pParse->db->mallocFailed );
- }else{
- /* Otherwise, pRec must be smaller than sample $i and larger than
- ** sample ($i-1). */
- assert( i==pIdx->nSample
- || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
- || pParse->db->mallocFailed );
- assert( i==0
- || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
- || pParse->db->mallocFailed );
+ if( pParse->db->mallocFailed==0 ){
+ if( res==0 ){
+ /* If (res==0) is true, then pRec must be equal to sample i. */
+ assert( i<pIdx->nSample );
+ assert( iCol==nField-1 );
+ pRec->nField = nField;
+ assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
+ || pParse->db->mallocFailed
+ );
+ }else{
+ /* Unless i==pIdx->nSample, indicating that pRec is larger than
+ ** all samples in the aSample[] array, pRec must be smaller than the
+ ** (iCol+1) field prefix of sample i. */
+ assert( i<=pIdx->nSample && i>=0 );
+ pRec->nField = iCol+1;
+ assert( i==pIdx->nSample
+ || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
+ || pParse->db->mallocFailed );
+
+ /* if i==0 and iCol==0, then record pRec is smaller than all samples
+ ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must
+ ** be greater than or equal to the (iCol) field prefix of sample i.
+ ** If (i>0), then pRec must also be greater than sample (i-1). */
+ if( iCol>0 ){
+ pRec->nField = iCol;
+ assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0
+ || pParse->db->mallocFailed );
+ }
+ if( i>0 ){
+ pRec->nField = nField;
+ assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
+ || pParse->db->mallocFailed );
+ }
+ }
}
#endif /* ifdef SQLITE_DEBUG */
- /* At this point, aSample[i] is the first sample that is greater than
- ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less
- ** than pVal. If aSample[i]==pVal, then res==0.
- */
if( res==0 ){
+ /* Record pRec is equal to sample i */
+ assert( iCol==nField-1 );
aStat[0] = aSample[i].anLt[iCol];
aStat[1] = aSample[i].anEq[iCol];
}else{
- tRowcnt iLower, iUpper, iGap;
- if( i==0 ){
- iLower = 0;
- iUpper = aSample[0].anLt[iCol];
+ /* At this point, the (iCol+1) field prefix of aSample[i] is the first
+ ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec
+ ** is larger than all samples in the array. */
+ tRowcnt iUpper, iGap;
+ if( i>=pIdx->nSample ){
+ iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
}else{
- i64 nRow0 = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
- iUpper = i>=pIdx->nSample ? nRow0 : aSample[i].anLt[iCol];
- iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol];
+ iUpper = aSample[i].anLt[iCol];
}
- aStat[1] = pIdx->aAvgEq[iCol];
+
if( iLower>=iUpper ){
iGap = 0;
}else{
@@ -2020,7 +2211,11 @@ static int whereKeyStats(
iGap = iGap/3;
}
aStat[0] = iLower + iGap;
+ aStat[1] = pIdx->aAvgEq[iCol];
}
+
+ /* Restore the pRec->nField value before returning. */
+ pRec->nField = nField;
return i;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
@@ -5807,10 +6002,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
/* Seed the search with a single WherePath containing zero WhereLoops.
**
- ** TUNING: Do not let the number of iterations go above 25. If the cost
- ** of computing an automatic index is not paid back within the first 25
+ ** TUNING: Do not let the number of iterations go above 28. If the cost
+ ** of computing an automatic index is not paid back within the first 28
** rows, then do not use the automatic index. */
- aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
+ aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) );
nFrom = 1;
assert( aFrom[0].isOrdered==0 );
if( nOrderBy ){
@@ -6610,6 +6805,12 @@ WhereInfo *sqlite3WhereBegin(
if( op ){
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
+ if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
+ && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
+ && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
+ ){
+ sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
+ }
VdbeComment((v, "%s", pIx->zName));
}
}
diff --git a/test/analyze9.test b/test/analyze9.test
index 8572cbea0..1ebd69c8d 100644
--- a/test/analyze9.test
+++ b/test/analyze9.test
@@ -1134,4 +1134,116 @@ ifcapable stat4&&cte {
}
}
+#-------------------------------------------------------------------------
+# Check that a problem in they way stat4 data is used has been
+# resolved (see below).
+#
+reset_db
+do_test 26.1.1 {
+ db transaction {
+ execsql {
+ CREATE TABLE t1(x, y, z);
+ CREATE INDEX t1xy ON t1(x, y);
+ CREATE INDEX t1z ON t1(z);
+ }
+ for {set i 0} {$i < 10000} {incr i} {
+ execsql { INSERT INTO t1(x, y) VALUES($i, $i) }
+ }
+ for {set i 0} {$i < 10} {incr i} {
+ execsql {
+ WITH cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt WHERE x<100)
+ INSERT INTO t1(x, y) SELECT 10000+$i, x FROM cnt;
+ INSERT INTO t1(x, y) SELECT 10000+$i, 100;
+ }
+ }
+ execsql {
+ UPDATE t1 SET z = rowid / 20;
+ ANALYZE;
+ }
+ }
+} {}
+
+do_execsql_test 26.1.2 {
+ SELECT count(*) FROM t1 WHERE x = 10000 AND y < 50;
+} {49}
+do_execsql_test 26.1.3 {
+ SELECT count(*) FROM t1 WHERE z = 444;
+} {20}
+
+# The analyzer knows that any (z=?) expression matches 20 rows. So it
+# will use index "t1z" if the estimate of hits for (x=10000 AND y<50)
+# is greater than 20 rows.
+#
+# And it should be. The analyzer has a stat4 sample as follows:
+#
+# sample=(x=10000, y=100) nLt=(10000 10099)
+#
+# There should be no other samples that start with (x=10000). So it knows
+# that (x=10000 AND y<50) must match somewhere between 0 and 99 rows, but
+# know more than that. Guessing less than 20 is therefore unreasonable.
+#
+# At one point though, due to a problem in whereKeyStats(), the planner was
+# estimating that (x=10000 AND y<50) would match only 2 rows.
+#
+do_eqp_test 26.1.4 {
+ SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
+} {
+ 0 0 0 {SEARCH TABLE t1 USING INDEX t1z (z=?)}
+}
+
+
+# This test - 26.2.* - tests that another manifestation of the same problem
+# is no longer present in the library. Assuming:
+#
+# CREATE INDEX t1xy ON t1(x, y)
+#
+# and that have samples for index t1xy as follows:
+#
+#
+# sample=('A', 70) nEq=(100, 2) nLt=(900, 970)
+# sample=('B', 70) nEq=(100, 2) nLt=(1000, 1070)
+#
+# the planner should estimate that (x = 'B' AND y > 25) matches 76 rows
+# (70 * 2/3 + 30). Before, due to the problem, the planner was estimating
+# that this matched 100 rows.
+#
+reset_db
+do_execsql_test 26.2.1 {
+ BEGIN;
+ CREATE TABLE t1(x, y, z);
+ CREATE INDEX i1 ON t1(x, y);
+ CREATE INDEX i2 ON t1(z);
+
+ WITH
+ cnt(y) AS (SELECT 0 UNION ALL SELECT y+1 FROM cnt WHERE y<99),
+ letters(x) AS (
+ SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D'
+ )
+ INSERT INTO t1(x, y) SELECT x, y FROM letters, cnt;
+
+ WITH
+ letters(x) AS (
+ SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D'
+ )
+ INSERT INTO t1(x, y) SELECT x, 70 FROM letters;
+
+ WITH
+ cnt(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM cnt WHERE i<9999)
+ INSERT INTO t1(x, y) SELECT i, i FROM cnt;
+
+ UPDATE t1 SET z = (rowid / 95);
+ ANALYZE;
+ COMMIT;
+}
+
+do_eqp_test 26.2.2 {
+ SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
+} {
+ 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
+}
+
+
finish_test
+
+
+
diff --git a/test/analyzeF.test b/test/analyzeF.test
new file mode 100644
index 000000000..670d178a8
--- /dev/null
+++ b/test/analyzeF.test
@@ -0,0 +1,127 @@
+# 2015-03-12
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# Test that deterministic scalar functions passed constant arguments
+# are used with stat4 data.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set ::testprefix analyzeF
+
+ifcapable {!stat4} {
+ finish_test
+ return
+}
+
+proc isqrt {i} { expr { int(sqrt($i)) } }
+db func isqrt isqrt
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(x INTEGER, y INTEGER);
+ WITH data(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM data
+ )
+ INSERT INTO t1 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400;
+ CREATE INDEX t1x ON t1(x);
+ CREATE INDEX t1y ON t1(y);
+ ANALYZE;
+}
+
+proc str {a} { return $a }
+db func str str
+
+# Note: tests 7 to 12 might be unstable - as they assume SQLite will
+# prefer the expression to the right of the AND clause. Which of
+# course could change.
+#
+# Note 2: tests 9 and 10 depend on the tcl interface creating functions
+# without the SQLITE_DETERMINISTIC flag set.
+#
+foreach {tn where idx} {
+ 1 "x = 4 AND y = 19" {t1x (x=?)}
+ 2 "x = 19 AND y = 4" {t1y (y=?)}
+ 3 "x = '4' AND y = '19'" {t1x (x=?)}
+ 4 "x = '19' AND y = '4'" {t1y (y=?)}
+ 5 "x = substr('5195', 2, 2) AND y = substr('145', 2, 1)" {t1y (y=?)}
+ 6 "x = substr('145', 2, 1) AND y = substr('5195', 2, 2)" {t1x (x=?)}
+
+ 7 "x = substr('5195', 2, 2+0) AND y = substr('145', 2, 1+0)" {t1y (y=?)}
+ 8 "x = substr('145', 2, 1+0) AND y = substr('5195', 2, 2+0)" {t1y (y=?)}
+
+ 9 "x = str('19') AND y = str('4')" {t1y (y=?)}
+ 10 "x = str('4') AND y = str('19')" {t1y (y=?)}
+
+ 11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
+ 12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
+} {
+ set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
+ do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
+}
+
+# Test that functions that do not exist - "func()" - do not cause an error.
+#
+do_catchsql_test 2.1 {
+ SELECT * FROM t1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
+} {1 {no such function: func}}
+do_catchsql_test 2.2 {
+ UPDATE t1 SET y=y+1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
+} {1 {no such function: func}}
+
+
+# Check that functions that accept zero arguments do not cause problems.
+#
+proc ret {x} { return $x }
+
+db func det4 -deterministic [list ret 4]
+db func nondet4 [list ret 4]
+db func det19 -deterministic [list ret 19]
+db func nondet19 [list ret 19]
+
+foreach {tn where idx} {
+ 1 "x = det4() AND y = det19()" {t1x (x=?)}
+ 2 "x = det19() AND y = det4()" {t1y (y=?)}
+
+ 3 "x = nondet4() AND y = nondet19()" {t1y (y=?)}
+ 4 "x = nondet19() AND y = nondet4()" {t1y (y=?)}
+} {
+ set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
+ do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
+}
+
+
+execsql { DELETE FROM t1 }
+
+proc throw_error {err} { error $err }
+db func error -deterministic throw_error
+do_catchsql_test 4.1 {
+ SELECT * FROM t1 WHERE x = error('error one') AND y = 4;
+} {1 {error one}}
+
+do_catchsql_test 4.2 {
+ SELECT * FROM t1 WHERE x = zeroblob(2000000000) AND y = 4;
+} {1 {string or blob too big}}
+
+sqlite3_limit db SQLITE_LIMIT_LENGTH 1000000
+proc dstr {} { return [string repeat x 1100000] }
+db func dstr -deterministic dstr
+do_catchsql_test 4.3 {
+ SELECT * FROM t1 WHERE x = dstr() AND y = 11;
+} {1 {string or blob too big}}
+
+do_catchsql_test 4.4 {
+ SELECT * FROM t1 WHERE x = test_zeroblob(1100000) AND y = 4;
+} {1 {string or blob too big}}
+
+
+finish_test
+
+
+
diff --git a/test/collate1.test b/test/collate1.test
index 20854157d..0716ac743 100644
--- a/test/collate1.test
+++ b/test/collate1.test
@@ -10,12 +10,12 @@
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
-# focus of this script is page cache subsystem.
+# focus of this script is testing collation sequences.
#
-# $Id: collate1.test,v 1.5 2007/02/01 23:02:46 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix collate1
#
# Tests are roughly organised as follows:
@@ -333,4 +333,58 @@ do_test collate1-5.3 {
}
} {1 2}
+
+
+#-------------------------------------------------------------------------
+# Fix problems with handling collation sequences named '"""'.
+#
+do_execsql_test 6.1 {
+ SELECT """""""";
+} {\"\"\"}
+
+do_catchsql_test 6.2 {
+ CREATE TABLE x1(a);
+ SELECT a FROM x1 ORDER BY a COLLATE """""""";
+} {1 {no such collation sequence: """}}
+
+do_catchsql_test 6.3 {
+ SELECT a FROM x1 ORDER BY 1 COLLATE """""""";
+} {1 {no such collation sequence: """}}
+
+do_catchsql_test 6.4 {
+ SELECT 0 UNION SELECT 0 ORDER BY 1 COLLATE """""""";
+} {1 {no such collation sequence: """}}
+
+db collate {"""} [list string compare -nocase]
+
+do_execsql_test 6.5 {
+ PRAGMA foreign_keys = ON;
+ CREATE TABLE p1(a PRIMARY KEY COLLATE '"""');
+ CREATE TABLE c1(x, y REFERENCES p1);
+} {}
+
+do_execsql_test 6.6 {
+ INSERT INTO p1 VALUES('abc');
+ INSERT INTO c1 VALUES(1, 'ABC');
+}
+
+ifcapable foreignkey {
+ do_catchsql_test 6.7 {
+ DELETE FROM p1 WHERE rowid = 1
+ } {1 {FOREIGN KEY constraint failed}}
+}
+
+do_execsql_test 6.8 {
+ INSERT INTO p1 VALUES('abb');
+ INSERT INTO p1 VALUES('wxz');
+ INSERT INTO p1 VALUES('wxy');
+
+ INSERT INTO c1 VALUES(2, 'abb');
+ INSERT INTO c1 VALUES(3, 'wxz');
+ INSERT INTO c1 VALUES(4, 'WXY');
+ SELECT x, y FROM c1 ORDER BY y COLLATE """""""";
+} {2 abb 1 ABC 4 WXY 3 wxz}
+
finish_test
+
+
diff --git a/test/crashM.test b/test/crashM.test
new file mode 100644
index 000000000..de10c4589
--- /dev/null
+++ b/test/crashM.test
@@ -0,0 +1,80 @@
+# 2015 Mar 13
+#
+# 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.
+#
+#***********************************************************************
+#
+# Crash tests for the multiplex module with 8.3 filenames enabled.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix crashM
+
+ifcapable !crashtest||!8_3_names {
+ finish_test
+ return
+}
+
+db close
+sqlite3_shutdown
+sqlite3_config_uri 1
+
+foreach f [glob -nocomplain test1.* test2.*] { forcedelete $f }
+sqlite3_multiplex_initialize "" 1
+sqlite3 db file:test1.db?8_3_names=1
+sqlite3_multiplex_control db main chunk_size [expr 64*1024]
+
+do_execsql_test 1.0 {
+ ATTACH 'file:test2.db?8_3_names=1' AS aux;
+
+ CREATE TABLE t1(x, y);
+ CREATE INDEX t1x ON t1(x);
+ CREATE INDEX t1y ON t1(y);
+
+ CREATE TABLE aux.t2(x, y);
+ CREATE INDEX aux.t2x ON t2(x);
+ CREATE INDEX aux.t2y ON t2(y);
+
+ WITH s(a) AS (
+ SELECT 1 UNION ALL SELECT a+1 FROM s WHERE a<1000
+ )
+ INSERT INTO t1 SELECT a, randomblob(500) FROM s;
+
+ WITH s(a) AS (
+ SELECT 1 UNION ALL SELECT a+1 FROM s WHERE a<1000
+ )
+ INSERT INTO t2 SELECT a, randomblob(500) FROM s;
+} {}
+
+for {set i 0} {$i < 20} {incr i} {
+ do_test 2.$i.1 {
+ crashsql -delay 1 -file test1.db -opendb {
+ sqlite3_shutdown
+ sqlite3_config_uri 1
+ sqlite3_multiplex_initialize crash 1
+ sqlite3 db file:test1.db?8_3_names=1
+ sqlite3_multiplex_control db main chunk_size [expr 64*1024]
+ } {
+ ATTACH 'file:test2.db?8_3_names=1' AS aux;
+ BEGIN;
+ UPDATE t1 SET y = randomblob(500) WHERE (x%10)==0;
+ UPDATE t2 SET y = randomblob(500) WHERE (x%10)==0;
+ COMMIT;
+ }
+ } {1 {child process exited abnormally}}
+
+ do_execsql_test 2.$i.2 {
+ PRAGMA main.integrity_check;
+ PRAGMA aux.integrity_check;
+ } {ok ok}
+}
+
+catch { db close }
+sqlite3_multiplex_shutdown
+finish_test
diff --git a/test/fts3atoken.test b/test/fts3atoken.test
index b7722c7d0..88e3d4f72 100644
--- a/test/fts3atoken.test
+++ b/test/fts3atoken.test
@@ -186,10 +186,32 @@ ifcapable icu {
} {}
}
-
do_test fts3token-internal {
execsql { SELECT fts3_tokenizer_internal_test() }
} {ok}
+#-------------------------------------------------------------------------
+# Test empty tokenizer names.
+#
+do_catchsql_test 6.1.1 {
+ CREATE VIRTUAL TABLE t3 USING fts4(tokenize="");
+} {1 {unknown tokenizer: }}
+do_catchsql_test 6.1.2 {
+ CREATE VIRTUAL TABLE t3 USING fts4(tokenize=);
+} {1 {unknown tokenizer: }}
+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
diff --git a/test/fts3prefix.test b/test/fts3prefix.test
index e7c197da9..8ffabe8d6 100644
--- a/test/fts3prefix.test
+++ b/test/fts3prefix.test
@@ -209,5 +209,69 @@ do_catchsql_test 5.1 {
do_catchsql_test 5.2 {
CREATE VIRTUAL TABLE t4 USING fts4(prefix="");
} {0 {}}
+do_catchsql_test 5.3 {
+ CREATE VIRTUAL TABLE t5 USING fts4(prefix="-1");
+} {1 {error parsing prefix parameter: -1}}
+
+#-------------------------------------------------------------------------
+# Prefix indexes of size 0 are ignored. Demonstrate this by showing that
+# adding prefix=0 does not change the contents of the %_segdir table.
+#
+reset_db
+do_execsql_test 6.1.1 {
+ CREATE VIRTUAL TABLE t1 USING fts4(prefix=0);
+ CREATE VIRTUAL TABLE t2 USING fts4;
+ INSERT INTO t1 VALUES('Twas Mulga Bill, from Eaglehawk, ');
+ INSERT INTO t2 VALUES('Twas Mulga Bill, from Eaglehawk, ');
+} {}
+do_execsql_test 6.1.2 {
+ SELECT md5sum(quote(root)) FROM t1_segdir;
+} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
+
+reset_db
+do_execsql_test 6.2.1 {
+ CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,0,2");
+ CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2");
+ INSERT INTO t1 VALUES('that caught the cycling craze;');
+ INSERT INTO t2 VALUES('that caught the cycling craze;');
+} {}
+do_execsql_test 6.2.2 {
+ SELECT md5sum(quote(root)) FROM t1_segdir;
+} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
+
+reset_db
+do_execsql_test 6.3.1 {
+ CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,3,2");
+ CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2");
+ INSERT INTO t1 VALUES('He turned away the good old horse');
+ INSERT INTO t2 VALUES('He turned away the good old horse');
+} {}
+do_test 6.3.2 {
+ set one [db eval {SELECT md5sum(quote(root)) FROM t1_segdir}]
+ set two [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
+ expr {$one == $two}
+} 0
+
+reset_db
+do_execsql_test 6.4.1 {
+ CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,600,2");
+ CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2");
+ INSERT INTO t1 VALUES('that served him many days;');
+ INSERT INTO t2 VALUES('that served him many days;');
+} {}
+do_execsql_test 6.4.2 {
+ SELECT md5sum(quote(root)) FROM t1_segdir;
+} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
+
+reset_db
+do_execsql_test 6.5.1 {
+ CREATE VIRTUAL TABLE t1 USING fts4(prefix="2147483647,2147483648,2147483649");
+ CREATE VIRTUAL TABLE t2 USING fts4(prefix=);
+ INSERT INTO t1 VALUES('He dressed himself in cycling clothes');
+ INSERT INTO t2 VALUES('He dressed himself in cycling clothes');
+} {}
+do_execsql_test 6.5.2 {
+ SELECT md5sum(quote(root)) FROM t1_segdir;
+} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
finish_test
diff --git a/test/fts3query.test b/test/fts3query.test
index 0b3c2ce1b..06019d14e 100644
--- a/test/fts3query.test
+++ b/test/fts3query.test
@@ -252,15 +252,21 @@ foreach {tn iFirst iLast} [subst {
do_execsql_test 7.2.$tn.1.[llength $res] {
SELECT rowid FROM ft4 WHERE rowid BETWEEN $iFirst AND $iLast
} $res
+ set res [db eval {
+ SELECT rowid FROM t4 WHERE rowid BETWEEN $iFirst AND $iLast
+ ORDER BY +rowid DESC
+ } ]
do_execsql_test 7.2.$tn.2.[llength $res] {
SELECT rowid FROM ft4 WHERE rowid BETWEEN $iFirst AND $iLast
ORDER BY rowid DESC
- } [lsort -decr -integer $res]
+ } $res
}
foreach ii [db eval {SELECT rowid FROM t4}] {
set res1 [db eval {SELECT rowid FROM t4 WHERE rowid > $ii}]
set res2 [db eval {SELECT rowid FROM t4 WHERE rowid < $ii}]
+ set res1s [db eval {SELECT rowid FROM t4 WHERE rowid > $ii ORDER BY +rowid DESC}]
+ set res2s [db eval {SELECT rowid FROM t4 WHERE rowid < $ii ORDER BY +rowid DESC}]
do_execsql_test 7.3.$ii.1 {
SELECT rowid FROM ft4 WHERE rowid > $ii
@@ -272,13 +278,11 @@ foreach ii [db eval {SELECT rowid FROM t4}] {
do_execsql_test 7.3.$ii.3 {
SELECT rowid FROM ft4 WHERE rowid > $ii ORDER BY rowid DESC
- } [lsort -integer -decr $res1]
+ } $res1s
do_execsql_test 7.3.$ii.4 {
SELECT rowid FROM ft4 WHERE rowid < $ii ORDER BY rowid DESC
- } [lsort -integer -decr $res2]
+ } $res2s
}
finish_test
-
-
diff --git a/test/incrblob2.test b/test/incrblob2.test
index 1a235f7d2..b6c75cd6c 100644
--- a/test/incrblob2.test
+++ b/test/incrblob2.test
@@ -324,11 +324,21 @@ do_test incrblob2-6.2 {
sqlite3_blob_read $rdHandle 0 2
} {AB}
-do_test incrblob2-6.2b {
+if {$::tcl_platform(pointerSize)>=8} {
+ do_test incrblob2-6.2b {
+ set rc [catch {
+ # Prior to 2015-02-07, the following caused a segfault due to
+ # integer overflow.
+ sqlite3_blob_read $rdHandle 2147483647 2147483647
+ } errmsg]
+ lappend rc $errmsg
+ } {1 SQLITE_ERROR}
+}
+do_test incrblob2-6.2c {
set rc [catch {
# Prior to 2015-02-07, the following caused a segfault due to
# integer overflow.
- sqlite3_blob_read $rdHandle 2147483647 2147483647
+ sqlite3_blob_read $rdHandle 2147483647 100
} errmsg]
lappend rc $errmsg
} {1 SQLITE_ERROR}
diff --git a/test/incrcorrupt.test b/test/incrcorrupt.test
new file mode 100644
index 000000000..eda65e403
--- /dev/null
+++ b/test/incrcorrupt.test
@@ -0,0 +1,127 @@
+# 2001 October 12
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# Test that "PRAGMA incremental_vacuum" detects and reports database
+# corruption properly. And that "PRAGMA auto_vacuum = INCREMENTAL"
+# does as well.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix incrcorrupt
+
+# If this build of the library does not support auto-vacuum, omit this
+# whole file.
+ifcapable {!autovacuum} {
+ finish_test
+ return
+}
+
+do_execsql_test 1.0 {
+ PRAGMA auto_vacuum = 2;
+ CREATE TABLE t1(a PRIMARY KEY, b);
+
+ WITH data(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM data
+ )
+ INSERT INTO t1 SELECT i, randomblob(600) FROM data LIMIT 20;
+ PRAGMA page_count;
+} {24}
+
+do_execsql_test 1.1 {
+ PRAGMA incremental_vacuum;
+} {}
+
+do_test 1.2 {
+ db_save
+ hexio_write test.db 36 00000019
+ catchsql { PRAGMA incremental_vacuum; }
+} {1 {database disk image is malformed}}
+
+do_test 1.3 {
+ set stmt [sqlite3_prepare_v2 db "PRAGMA incremental_vacuum" -1 dummy]
+ sqlite3_step $stmt
+} {SQLITE_CORRUPT}
+do_test 1.4 { sqlite3_errcode db } {SQLITE_CORRUPT}
+do_test 1.5 { sqlite3_errmsg db } {database disk image is malformed}
+do_test 1.6 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
+do_test 1.7 { sqlite3_errcode db } {SQLITE_CORRUPT}
+do_test 1.8 { sqlite3_errmsg db } {database disk image is malformed}
+
+do_test 1.9 {
+ set stmt [sqlite3_prepare_v2 db "PRAGMA incremental_vacuum" -1 dummy]
+ sqlite3_step $stmt
+} {SQLITE_CORRUPT}
+do_test 1.10 { sqlite3_errcode db } {SQLITE_CORRUPT}
+do_test 1.11 { sqlite3_errmsg db } {database disk image is malformed}
+
+do_test 1.12 {
+ set stmt2 [sqlite3_prepare_v2 db "SELECT 1" -1 dummy]
+ sqlite3_finalize $stmt2
+} {SQLITE_OK}
+do_test 1.13 { sqlite3_errcode db } {SQLITE_OK}
+do_test 1.14 { sqlite3_errmsg db } {not an error}
+
+do_test 1.15 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
+do_test 1.16 { sqlite3_errcode db } {SQLITE_CORRUPT}
+do_test 1.17 { sqlite3_errmsg db } {database disk image is malformed}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+
+do_execsql_test 2.1 {
+ PRAGMA auto_vacuum = 1;
+ CREATE TABLE t1(a PRIMARY KEY, b);
+ WITH data(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM data
+ )
+ INSERT INTO t1 SELECT i, randomblob(600) FROM data LIMIT 20;
+ PRAGMA page_count;
+} {24}
+
+do_test 2.2 {
+ db_save
+ set fd [open test.db r+]
+ chan truncate $fd [expr 22*1024]
+ close $fd
+ catchsql { PRAGMA incremental_vacuum; }
+} {1 {database disk image is malformed}}
+
+do_test 2.3 {
+ set stmt [sqlite3_prepare_v2 db "PRAGMA auto_vacuum = INCREMENTAL" -1 dummy]
+ sqlite3_step $stmt
+} {SQLITE_CORRUPT}
+do_test 2.4 { sqlite3_errcode db } {SQLITE_CORRUPT}
+do_test 2.5 { sqlite3_errmsg db } {database disk image is malformed}
+do_test 2.6 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
+do_test 2.7 { sqlite3_errcode db } {SQLITE_CORRUPT}
+do_test 2.8 { sqlite3_errmsg db } {database disk image is malformed}
+
+do_test 2.9 {
+ set stmt [sqlite3_prepare_v2 db "PRAGMA auto_vacuum = INCREMENTAL" -1 dummy]
+ sqlite3_step $stmt
+} {SQLITE_CORRUPT}
+do_test 2.10 { sqlite3_errcode db } {SQLITE_CORRUPT}
+do_test 2.11 { sqlite3_errmsg db } {database disk image is malformed}
+
+do_test 2.12 {
+ set stmt2 [sqlite3_prepare_v2 db "SELECT 1" -1 dummy]
+ sqlite3_finalize $stmt2
+} {SQLITE_OK}
+do_test 2.13 { sqlite3_errcode db } {SQLITE_OK}
+do_test 2.14 { sqlite3_errmsg db } {not an error}
+
+do_test 2.15 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
+do_test 2.16 { sqlite3_errcode db } {SQLITE_CORRUPT}
+do_test 2.17 { sqlite3_errmsg db } {database disk image is malformed}
+
+finish_test
+
diff --git a/test/lock_common.tcl b/test/lock_common.tcl
index bc1eb86bd..a758e7af2 100644
--- a/test/lock_common.tcl
+++ b/test/lock_common.tcl
@@ -86,21 +86,51 @@ proc launch_testfixture {{prg ""}} {
# Execute a command in a child testfixture process, connected by two-way
# channel $chan. Return the result of the command, or an error message.
#
-proc testfixture {chan cmd} {
- puts $chan $cmd
- puts $chan OVER
- set r ""
- while { 1 } {
- set line [gets $chan]
- if { $line == "OVER" } {
- set res [lindex $r 1]
- if { [lindex $r 0] } { error $res }
- return $res
- }
- if {[eof $chan]} {
- return "ERROR: Child process hung up"
+proc testfixture {chan cmd args} {
+
+ if {[llength $args] == 0} {
+ fconfigure $chan -blocking 1
+ puts $chan $cmd
+ puts $chan OVER
+
+ set r ""
+ while { 1 } {
+ set line [gets $chan]
+ if { $line == "OVER" } {
+ set res [lindex $r 1]
+ if { [lindex $r 0] } { error $res }
+ return $res
+ }
+ if {[eof $chan]} {
+ return "ERROR: Child process hung up"
+ }
+ append r $line
}
- append r $line
+ return $r
+ } else {
+ set ::tfnb($chan) ""
+ fconfigure $chan -blocking 0 -buffering none
+ puts $chan $cmd
+ puts $chan OVER
+ fileevent $chan readable [list testfixture_script_cb $chan [lindex $args 0]]
+ return ""
+ }
+}
+
+proc testfixture_script_cb {chan script} {
+ if {[eof $chan]} {
+ append ::tfnb($chan) "ERROR: Child process hung up"
+ set line "OVER"
+ } else {
+ set line [gets $chan]
+ }
+
+ if { $line == "OVER" } {
+ uplevel #0 $script [list [lindex $::tfnb($chan) 1]]
+ unset ::tfnb($chan)
+ fileevent $chan readable ""
+ } else {
+ append ::tfnb($chan) $line
}
}
diff --git a/test/malloc5.test b/test/malloc5.test
index 6abedf79e..c04649926 100644
--- a/test/malloc5.test
+++ b/test/malloc5.test
@@ -71,6 +71,23 @@ do_test malloc5-1.3 {
expr $::pgalloc > 0
} {1}
+# The sizes of memory allocations from system malloc() might vary,
+# depending on the memory allocator algorithms used. The following
+# routine is designed to support answers that fall within a range
+# of values while also supplying easy-to-understand "expected" values
+# when errors occur.
+#
+proc value_in_range {target x args} {
+ set v [lindex $args 0]
+ if {$v!=""} {
+ if {$v<$target*$x} {return $v}
+ if {$v>$target/$x} {return $v}
+ }
+ return "number between [expr {int($target*$x)}] and [expr {int($target/$x)}]"
+}
+set mrange 0.98 ;# plus or minus 2%
+
+
do_test malloc5-1.4 {
# Commit the transaction and open a new one. Read 1 page into the cache.
# Because the page is not dirty, it is eligible for collection even
@@ -81,16 +98,16 @@ do_test malloc5-1.4 {
BEGIN;
SELECT * FROM abc;
}
- sqlite3_release_memory
-} $::pgalloc
+ value_in_range $::pgalloc $::mrange [sqlite3_release_memory]
+} [value_in_range $::pgalloc $::mrange]
do_test malloc5-1.5 {
# Conclude the transaction opened in the previous [do_test] block. This
# causes another page (page 1) to become eligible for recycling.
#
execsql { COMMIT }
- sqlite3_release_memory
-} $::pgalloc
+ value_in_range $::pgalloc $::mrange [sqlite3_release_memory]
+} [value_in_range $::pgalloc $::mrange]
do_test malloc5-1.6 {
# Manipulate the cache so that it contains two unused pages. One requires
@@ -101,8 +118,8 @@ do_test malloc5-1.6 {
SELECT * FROM abc;
CREATE TABLE def(d, e, f);
}
- sqlite3_release_memory 500
-} $::pgalloc
+ value_in_range $::pgalloc $::mrange [sqlite3_release_memory 500]
+} [value_in_range $::pgalloc $::mrange]
do_test malloc5-1.7 {
# Database should not be locked this time.
diff --git a/test/mallocK.test b/test/mallocK.test
index 0a21b9fa0..65791e79e 100644
--- a/test/mallocK.test
+++ b/test/mallocK.test
@@ -143,6 +143,33 @@ do_faultsim_test 7.2 -faults oom* -body {
faultsim_test_result [list 0 {}]
}
+reset_db
+
+proc isqrt {i} { expr { int(sqrt($i)) } }
+db func isqrt isqrt
+
+do_execsql_test 8.0 {
+ PRAGMA encoding = 'utf-16';
+ CREATE TABLE x2(x TEXT, y TEXT);
+ WITH data(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM data
+ )
+ INSERT INTO x2 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400;
+ CREATE INDEX x2x ON x2(x);
+ CREATE INDEX x2y ON x2(y);
+ ANALYZE;
+ DELETE FROM x2;
+}
+
+proc str {a} { return $a }
+db func str -deterministic str
+
+do_faultsim_test 8 -faults oom* -body {
+ execsql { SELECT * FROM x2 WHERE x = str('19') AND y = str('4') }
+} -test {
+ faultsim_test_result [list 0 {}]
+}
+
finish_test
diff --git a/test/misc1.test b/test/misc1.test
index d18223e67..0f4881fb6 100644
--- a/test/misc1.test
+++ b/test/misc1.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,13 @@ 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}}
+
finish_test
diff --git a/test/shell4.test b/test/shell4.test
index c29faf00c..fcb0b2b71 100644
--- a/test/shell4.test
+++ b/test/shell4.test
@@ -12,12 +12,12 @@
# The focus of this file is testing the CLI shell tool.
# These tests are specific to the .stats command.
#
-# $Id: shell4.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $
-#
+# 2015-03-19: Added tests for .trace
# Test plan:
#
# shell4-1.*: Basic tests specific to the "stats" command.
+# shell4-2.*: Basic tests for ".trace"
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -113,4 +113,24 @@ SELECT 1;
[regexp {Autoindex Inserts} $res]
} {1 1 1}
+do_test shell4-2.1 {
+ catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace"
+} {1 {Usage: .trace FILE|off}}
+do_test shell4-2.2 {
+ catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace off\n.trace off\n"
+} {0 {}}
+do_test shell4-2.3 {
+ catchcmd ":memory:" ".trace stdout\n.trace\n.trace off\n.dump\n"
+} {/^1 {PRAGMA.*Usage:.*}$/}
+ifcapable trace {
+do_test shell4-2.4 {
+ catchcmd ":memory:" ".trace stdout\nCREATE TABLE t1(x);SELECT * FROM t1;"
+} {0 {CREATE TABLE t1(x);
+SELECT * FROM t1;}}
+do_test shell4-2.5 {
+ catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace stdout\nSELECT * FROM t1;"
+} {0 {SELECT * FROM t1;}}
+}
+
+
finish_test
diff --git a/test/tclsqlite.test b/test/tclsqlite.test
index 3d9cd46ac..8d7fea0d2 100644
--- a/test/tclsqlite.test
+++ b/test/tclsqlite.test
@@ -118,7 +118,7 @@ do_test tcl-1.14 {
do_test tcl-1.15 {
set v [catch {db function} msg]
lappend v $msg
-} {1 {wrong # args: should be "db function NAME [-argcount N] SCRIPT"}}
+} {1 {wrong # args: should be "db function NAME ?SWITCHES? SCRIPT"}}
do_test tcl-1.16 {
set v [catch {db last_insert_rowid xyz} msg]
lappend v $msg
diff --git a/test/vtab1.test b/test/vtab1.test
index 2929b1e54..dfc989a64 100644
--- a/test/vtab1.test
+++ b/test/vtab1.test
@@ -1437,4 +1437,58 @@ ifcapable fts3 {
} {SQLITE_OK}
}
+
+#-------------------------------------------------------------------------
+# The following tests verify that a DROP TABLE command on a virtual
+# table does not cause other operations to crash.
+#
+# 23.1: Dropping a vtab while a SELECT is running on it.
+#
+# 23.2: Dropping a vtab while a SELECT that will, but has not yet,
+# open a cursor on the vtab, is running. In this case the
+# DROP TABLE succeeds and the SELECT hits an error.
+#
+# 23.3: Dropping a vtab from within a user-defined-function callback
+# in the middle of an "INSERT INTO vtab SELECT ..." statement.
+#
+reset_db
+load_static_extension db wholenumber
+load_static_extension db eval
+register_echo_module db
+
+do_test 23.1 {
+ execsql { CREATE VIRTUAL TABLE t1 USING wholenumber }
+ set res ""
+ db eval { SELECT value FROM t1 WHERE value<10 } {
+ if {$value == 5} {
+ set res [catchsql { DROP TABLE t1 }]
+ }
+ }
+ set res
+} {1 {database table is locked}}
+
+do_test 23.2 {
+ execsql {
+ CREATE TABLE t2(value);
+ INSERT INTO t2 VALUES(1), (2), (3);
+ }
+
+ set res2 [list [catch {
+ db eval {
+ SELECT value FROM t2 UNION ALL
+ SELECT value FROM t1 WHERE value<10
+ } {
+ if {$value == 2} { set res1 [catchsql { DROP TABLE t1 }] }
+ }
+ } msg] $msg]
+ list $res1 $res2
+} {{0 {}} {1 {database table is locked}}}
+
+do_test 23.3.1 {
+ execsql { CREATE VIRTUAL TABLE t1e USING echo(t2) }
+ execsql { INSERT INTO t1e SELECT 4 }
+ catchsql { INSERT INTO t1e SELECT eval('DROP TABLE t1e') }
+} {1 {database table is locked}}
+do_execsql_test 23.3.2 { SELECT * FROM t1e } {1 2 3 4}
+
finish_test
diff --git a/test/vtab2.test b/test/vtab2.test
index 05a4834a1..3884ec57d 100644
--- a/test/vtab2.test
+++ b/test/vtab2.test
@@ -10,10 +10,10 @@
#***********************************************************************
# This file implements regression tests for SQLite library.
#
-# $Id: vtab2.test,v 1.9 2008/10/13 10:37:50 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix vtab2
ifcapable !vtab||!schema_pragmas {
finish_test
@@ -133,4 +133,24 @@ do_test vtab2-4.5 {
execsql { SELECT * FROM fkey }
} {t1 a}
+#-------------------------------------------------------------------------
+#
+ifcapable fts3 {
+ reset_db
+ do_execsql_test 5.1 {
+ PRAGMA encoding='UTF16';
+ }
+
+ do_test 5.2 {
+ sqlite3_exec_hex db { CREATE VIRTUAL TABLE %C8 USING fts3 }
+ } {0 {}}
+
+ do_test 5.3 {
+ sqlite3_exec_hex db { CREATE VIRTUAL TABLE %C9 USING s }
+ } {/1 {malformed database schema.* already exists}/}
+}
+
+
+
finish_test
+
diff --git a/test/walblock.test b/test/walblock.test
new file mode 100644
index 000000000..0b0b2241e
--- /dev/null
+++ b/test/walblock.test
@@ -0,0 +1,117 @@
+# 2015 Mar 17
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+source $testdir/wal_common.tcl
+
+ifcapable !wal {finish_test ; return }
+if {$::tcl_platform(platform)!="unix"} { finish_test ; return }
+set testprefix walblock
+
+catch { db close }
+testvfs tvfs -fullshm 1
+foreach f [glob test.db*] { forcedelete $f }
+
+sqlite3 db test.db -vfs tvfs
+do_execsql_test 1.1.0 {
+ CREATE TABLE t1(x, y);
+ INSERT INTO t1 VALUES(1, 2);
+ INSERT INTO t1 VALUES(3, 4);
+ INSERT INTO t1 VALUES(5, 6);
+ PRAGMA journal_mode = wal;
+ INSERT INTO t1 VALUES(7, 8);
+} {wal}
+
+do_test 1.1.1 {
+ lsort [glob test.db*]
+} {test.db test.db-shm test.db-wal}
+
+do_test 1.1.2 {
+ set C [launch_testfixture]
+ testfixture $C {
+ sqlite3 db test.db
+ db eval { SELECT * FROM t1 }
+ }
+} {1 2 3 4 5 6 7 8}
+
+do_test 1.1.3 {
+ set ::out [list]
+ testfixture $C {
+ db eval { SELECT * FROM t1 }
+ } [list set ::out]
+ set ::out
+} {}
+
+do_test 1.1.4 {
+ vwait ::out
+ set ::out
+} {1 2 3 4 5 6 7 8}
+
+#
+# Test that if a read client cannot read the wal-index header because a
+# write client is in the middle of updating it, the reader blocks until
+# the writer finishes.
+#
+# 1. Open a write transaction using client [db] in this process.
+#
+# 2. Attempt to commit the write transaction. Intercept the xShmBarrier()
+# call made by the writer between updating the two copies of the
+# wal-index header.
+#
+# 3. Within the xShmBarrier() callback, make an asynchronous request to
+# the other process to read from the database. It should block, as it
+# cannot get read the wal-index header.
+#
+# 4. Still in xShmBarrier(), wait for 5 seconds. Check that the other
+# process has not answered the request.
+#
+# 5: Finish committing the transaction. Then wait for 0.5 seconds more.
+# Ensure that the second process has by this stage read the database
+# and that the snapshot it read included the transaction committed in
+# step (4).
+#
+do_execsql_test 1.2.1 {
+ BEGIN;
+ INSERT INTO t1 VALUES(9, 10);
+} {}
+
+tvfs script barrier_callback
+tvfs filter xShmBarrier
+proc barrier_callback {method args} {
+ set ::out ""
+ testfixture $::C { db eval { SELECT * FROM t1 } } {set ::out}
+
+ do_test "1.2.2.(blocking 10 seconds)" {
+ set ::continue 0
+ after 10000 {set ::continue 1}
+ vwait ::continue
+ set ::out
+ } {}
+}
+
+execsql COMMIT
+
+do_test "1.2.3.(blocking 0.5 seconds)" {
+ set ::continue 0
+ after 500 {set ::continue 1}
+ vwait ::continue
+ set ::out
+} {1 2 3 4 5 6 7 8 9 10}
+
+
+finish_test
+
+
+
+
diff --git a/test/with1.test b/test/with1.test
index 42d2277ae..ad88a67c2 100644
--- a/test/with1.test
+++ b/test/with1.test
@@ -827,5 +827,20 @@ WITH RECURSIVE
SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1;
} {2 4 8 10 14 16 20}
+# 2015-03-21
+# Column wildcards on the LHS of a recursive table expression
+#
+do_catchsql_test 13.1 {
+ WITH RECURSIVE c(i) AS (SELECT * UNION ALL SELECT i+1 FROM c WHERE i<10)
+ SELECT i FROM c;
+} {1 {no tables specified}}
+do_catchsql_test 13.2 {
+ WITH RECURSIVE c(i) AS (SELECT 5,* UNION ALL SELECT i+1 FROM c WHERE i<10)
+ SELECT i FROM c;
+} {1 {no tables specified}}
+do_catchsql_test 13.3 {
+ WITH RECURSIVE c(i,j) AS (SELECT 5,* UNION ALL SELECT i+1,11 FROM c WHERE i<10)
+ SELECT i FROM c;
+} {1 {table c has 1 values for 2 columns}}
finish_test
diff --git a/test/without_rowid6.test b/test/without_rowid6.test
index e827ccab9..8ca78ba63 100644
--- a/test/without_rowid6.test
+++ b/test/without_rowid6.test
@@ -37,5 +37,81 @@ do_execsql_test without_rowid6-140 {
SELECT c FROM t1 ORDER BY b LIMIT 5;
} {x1y x2y x3y x4y x5y}
+# Column t1.b starts out as a unique index, but that index is
+# subsequently converted into a PRIMARY KEY.
+#
+do_execsql_test without_rowid6-200 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(
+ a UNIQUE,
+ b UNIQUE,
+ c UNIQUE,
+ PRIMARY KEY(b)
+ ) WITHOUT ROWID;
+ INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9);
+ SELECT a FROM t1 WHERE b>3 ORDER BY b;
+} {4 1}
+do_execsql_test without_rowid6-210 {
+ EXPLAIN QUERY PLAN
+ SELECT a FROM t1 WHERE b>3 ORDER BY b;
+} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
+do_execsql_test without_rowid6-220 {
+ PRAGMA index_list(t1);
+} {/sqlite_autoindex_t1_2 1 pk/}
+
+do_execsql_test without_rowid6-300 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(
+ a UNIQUE,
+ b PRIMARY KEY,
+ c UNIQUE,
+ UNIQUE(b)
+ ) WITHOUT ROWID;
+ INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9);
+ SELECT a FROM t1 WHERE b>3 ORDER BY b;
+} {4 1}
+do_execsql_test without_rowid6-310 {
+ EXPLAIN QUERY PLAN
+ SELECT a FROM t1 WHERE b>3 ORDER BY b;
+} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
+do_execsql_test without_rowid6-320 {
+ PRAGMA index_list(t1);
+} {/sqlite_autoindex_t1_2 1 pk/}
+
+do_execsql_test without_rowid6-400 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(
+ a UNIQUE,
+ b UNIQUE PRIMARY KEY,
+ c UNIQUE
+ ) WITHOUT ROWID;
+ INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9);
+ SELECT a FROM t1 WHERE b>3 ORDER BY b;
+} {4 1}
+do_execsql_test without_rowid6-410 {
+ EXPLAIN QUERY PLAN
+ SELECT a FROM t1 WHERE b>3 ORDER BY b;
+} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
+do_execsql_test without_rowid6-420 {
+ PRAGMA index_list(t1);
+} {/sqlite_autoindex_t1_2 1 pk/}
+
+do_execsql_test without_rowid6-500 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(a,b,c,
+ UNIQUE(b,c),
+ PRIMARY KEY(b,c)
+ ) WITHOUT ROWID;
+ INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9);
+ SELECT a FROM t1 WHERE b>3 ORDER BY b;
+} {4 1}
+do_execsql_test without_rowid6-510 {
+ EXPLAIN QUERY PLAN
+ SELECT a FROM t1 WHERE b>3 ORDER BY b;
+} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
+do_execsql_test without_rowid6-520 {
+ PRAGMA index_list(t1);
+} {/sqlite_autoindex_t1_1 1 pk/}
+
finish_test
diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat
index 1fb61d4df..728183629 100755
--- a/tool/build-all-msvc.bat
+++ b/tool/build-all-msvc.bat
@@ -58,6 +58,9 @@ IF NOT DEFINED _AECHO (SET _AECHO=REM)
IF NOT DEFINED _CECHO (SET _CECHO=REM)
IF NOT DEFINED _VECHO (SET _VECHO=REM)
+SET REDIRECT=^>
+IF DEFINED __ECHO SET REDIRECT=^^^>
+
%_AECHO% Running %0 %*
REM SET DFLAGS=/L
@@ -318,7 +321,18 @@ FOR %%P IN (%PLATFORMS%) DO (
%_AECHO% Building the %%B configuration for platform %%P with name %%D...
IF /I "%%B" == "Debug" (
- SET DEBUG=2
+ REM
+ REM NOTE: Using this level for the DEBUG environment variable should
+ REM disable all compiler optimizations and prevent use of the
+ REM NDEBUG define. Additionally, both SQLITE_ENABLE_API_ARMOR
+ REM and SQLITE_DEBUG defines should be enabled.
+ REM
+ SET DEBUG=3
+
+ REM
+ REM NOTE: Setting this to non-zero should enable the SQLITE_MEMDEBUG
+ REM define.
+ REM
SET MEMDEBUG=1
) ELSE (
CALL :fn_UnsetVariable DEBUG
@@ -420,11 +434,11 @@ FOR %%P IN (%PLATFORMS%) DO (
) ELSE (
REM
REM NOTE: Even when the cleaning step has been disabled, we still
- REM need to remove the build output for the files we are
+ REM need to remove the build output for all the files we are
REM specifically wanting to build for each platform.
REM
- %_AECHO% Cleaning final output files only...
- %__ECHO% DEL /Q *.lo sqlite3.dll sqlite3.lib sqlite3.pdb
+ %_AECHO% Cleaning final core library output files only...
+ %__ECHO% DEL /Q *.lo sqlite3.dll sqlite3.lib sqlite3.pdb 2%REDIRECT% NUL
)
REM
@@ -476,6 +490,64 @@ FOR %%P IN (%PLATFORMS%) DO (
GOTO errors
)
)
+
+ REM
+ REM NOTE: If requested, also build the shell executable.
+ REM
+ IF DEFINED BUILD_ALL_SHELL (
+ REM
+ REM NOTE: If necessary, make sure any previous build output for the
+ REM shell executable is deleted.
+ REM
+ IF DEFINED NOCLEAN (
+ REM
+ REM NOTE: Even when the cleaning step has been disabled, we still
+ REM need to remove the build output for all the files we are
+ REM specifically wanting to build for each platform.
+ REM
+ %_AECHO% Cleaning final shell executable output files only...
+ %__ECHO% DEL /Q sqlite3.exe sqlite3sh.pdb 2%REDIRECT% NUL
+ )
+
+ REM
+ REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.exe"
+ REM binary. The x86 compiler will be used to compile the native
+ REM command line tools needed during the build process itself.
+ REM Also, disable looking for and/or linking to the native Tcl
+ REM runtime library.
+ REM
+ %__ECHO% %NMAKE_CMD% sqlite3.exe XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to build %%B "sqlite3.exe" for platform %%P.
+ GOTO errors
+ )
+
+ REM
+ REM NOTE: Copy the "sqlite3.exe" file to the appropriate directory
+ REM for the build and platform beneath the binary directory.
+ REM
+ %__ECHO% XCOPY sqlite3.exe "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "sqlite3.exe" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
+
+ REM
+ REM NOTE: Copy the "sqlite3sh.pdb" file to the appropriate directory
+ REM for the build and platform beneath the binary directory
+ REM unless we are prevented from doing so.
+ REM
+ IF NOT DEFINED NOSYMBOLS (
+ %__ECHO% XCOPY sqlite3sh.pdb "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "sqlite3sh.pdb" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
+ )
+ )
)
)
)
diff --git a/tool/showdb.c b/tool/showdb.c
index 82b8c9f14..7fdf7c91a 100644
--- a/tool/showdb.c
+++ b/tool/showdb.c
@@ -375,7 +375,7 @@ static void decodeCell(
int szPgHdr, /* Size of the page header. 0 or 100 */
int ofst /* Cell begins at a[ofst] */
){
- int i, j;
+ int i, j = 0;
int leftChild;
i64 k;
i64 nPayload;