Merge the latest trunk changes into this branch.

FossilOrigin-Name: 9d9b6c883b4f7d69c615cedfb59a2385aac47b74
This commit is contained in:
dan 2015-03-24 18:21:41 +00:00
commit 6da7a0a93d
64 changed files with 2312 additions and 523 deletions

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

130
manifest
View File

@ -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

View File

@ -1 +1 @@
6326fd3249bee267da0172f8afd1e7b3f71521b9
9d9b6c883b4f7d69c615cedfb59a2385aac47b74

View File

@ -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';

View File

@ -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 ){

View File

@ -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

View File

@ -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;
}

View File

@ -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--;

View File

@ -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.
*/

View File

@ -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);

View File

@ -3183,6 +3183,7 @@ Index *sqlite3CreateIndex(
pIdx->onError = pIndex->onError;
}
}
pRet = pIdx;
goto exit_create_index;
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -75,6 +75,13 @@ static SQLITE_WSD struct Mem0Global {
#define mem0 GLOBAL(struct Mem0Global, mem0)
/*
** Return the memory allocator mutex. sqlite3_status() needs it.
*/
sqlite3_mutex *sqlite3MallocMutex(void){
return mem0.mutex;
}
/*
** This routine runs when the memory allocator sees that the
** total memory allocation is about to exceed the soft heap
@ -97,7 +104,7 @@ static int sqlite3MemoryAlarm(
void *pArg,
sqlite3_int64 iThreshold
){
int nUsed;
sqlite3_int64 nUsed;
sqlite3_mutex_enter(mem0.mutex);
mem0.alarmCallback = xCallback;
mem0.alarmArg = pArg;
@ -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 ){

View File

@ -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 ){

View File

@ -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");

View File

@ -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

View File

@ -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
);

View File

@ -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;

View File

@ -49,6 +49,13 @@ extern "C" {
# define SQLITE_EXTERN extern
#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
@ -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
);
/*

View File

@ -594,6 +594,20 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
*/
typedef INT16_TYPE LogEst;
/*
** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
*/
#ifndef SQLITE_PTRSIZE
# if defined(__SIZEOF_POINTER__)
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(_M_ARM) || defined(__arm__) || defined(__x86)
# define SQLITE_PTRSIZE 4
# else
# define SQLITE_PTRSIZE 8
# endif
#endif
/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
@ -1098,6 +1112,7 @@ struct sqlite3 {
int nVdbeRead; /* Number of active VDBEs that read or write */
int nVdbeWrite; /* Number of active VDBEs that read and write */
int nVdbeExec; /* Number of nested calls to VdbeExec() */
int nVDestroy; /* Number of active OP_VDestroy operations */
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
void (*xTrace)(void*,const char*); /* Trace function */
@ -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 *);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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,20 +3235,6 @@ case OP_SetCookie: { /* in3 */
** See also OpenRead.
*/
case OP_ReopenIdx: {
VdbeCursor *pCur;
assert( pOp->p5==0 );
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;
}
/* 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;
@ -3258,8 +3244,20 @@ case OP_OpenWrite: {
VdbeCursor *pCur;
Db *pDb;
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || 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 */
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:
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) ){

View File

@ -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 */

View File

@ -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;

View File

@ -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 ){

View File

@ -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){
@ -1134,6 +1134,113 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
return sqlite3ValueNew(db);
}
/*
** 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
@ -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;

View File

@ -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 |

View File

@ -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 );

View File

@ -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

View File

@ -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);
if( res<0 ){
iMin = iTest+1;
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{
i = iTest;
n = iTest + 1;
}
}while( res && iMin<i );
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{
iSample = iTest;
iCol = n-1;
}
}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));
}
}

View File

@ -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

127
test/analyzeF.test Normal file
View File

@ -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

View File

@ -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

80
test/crashM.test Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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}

127
test/incrcorrupt.test Normal file
View File

@ -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

View File

@ -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 } {
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
}
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" } {
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
}
if { $line == "OVER" } {
uplevel #0 $script [list [lindex $::tfnb($chan) 1]]
unset ::tfnb($chan)
fileevent $chan readable ""
} else {
append ::tfnb($chan) $line
}
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

117
test/walblock.test Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
)
)
)
)
)
)

View File

@ -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;