Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eb4e3f8348 | |||
| 3aeec23c29 | |||
| 9da8bf9ae7 | |||
| 3a907ce696 | |||
| b792d9ef4c | |||
| 23a09adc0b | |||
| 1adf686f0c | |||
| 607e10998d | |||
| b3785b8322 | |||
| 80354c6630 | |||
| 66d89de8b4 | |||
| 4427e597b2 | |||
| b5c7f2f235 | |||
| 5efbd06ab3 | |||
| b6f47deb0c | |||
| 8c069147ce | |||
| a30d22a7a6 | |||
| 74b42275ec | |||
| e3cdbad274 | |||
| 4b0000c9a8 | |||
| cf860700e5 | |||
| b33c50f215 | |||
| 62ca61ee61 | |||
| eaf2640237 | |||
| 5f1731f670 | |||
| ccf46d0b90 | |||
| f9d02f3663 | |||
| 4c45196a76 | |||
| 8237f6d180 | |||
| d881ce8fa7 | |||
| 4d2daba467 | |||
| 6b5f0ebe97 | |||
| 1cc0d11a16 | |||
| 96e285692a | |||
| 8773b858e1 | |||
| fe0ba71112 | |||
| bc8a6b31b6 | |||
| 116f0be024 | |||
| 30d1dcabf5 | |||
| ad1e55e55a | |||
| 6f5a37a464 | |||
| 9871a933c1 | |||
| 34a8065f49 | |||
| ccb43714da | |||
| 56d89cbee3 | |||
| 592f0cb15e | |||
| 21aa6a1acb | |||
| f3e8748683 | |||
| 606a357288 | |||
| d2f83139f3 | |||
| cbd3349ab9 | |||
| f94c9485ef | |||
| d69e557940 | |||
| 790fa6ec30 | |||
| 8de1250638 | |||
| 26bbfaa59d | |||
| 59b9b02c1f | |||
| 4756404847 | |||
| 126e9e6347 | |||
| 428630cfcf | |||
| 466fd815fb | |||
| f496a7dc81 | |||
| a68d628291 | |||
| 086723a4a8 | |||
| ada3f2b14f | |||
| d741129e2b | |||
| 2493870d9c | |||
| 062cf27d00 | |||
| 2b4905c81f | |||
| af89fe66ea | |||
| 74893a4cdb | |||
| d425864d33 | |||
| 774f42b6c6 | |||
| 082be63b17 | |||
| 5ac936529c | |||
| 3858cb44b6 | |||
| e10d87f65a | |||
| d2f99333cf | |||
| c435cf75a5 | |||
| b4e0fd26e3 | |||
| 998aaa03ea | |||
| 474640638d | |||
| e56f53ef7c | |||
| 8f9d0b2b25 | |||
| f063685079 | |||
| 299903c6a6 | |||
| 44723ce096 | |||
| e441efb688 | |||
| 1fa509afa1 | |||
| e0997b341b | |||
| 80103fc614 | |||
| 17ba562025 | |||
| 8b3c0ae47c | |||
| 7377945a7b | |||
| b7134d0863 | |||
| e0417626ea | |||
| b77009fdd9 | |||
| ba132c7728 | |||
| 657b4a87e5 | |||
| 2b3f1409db | |||
| d671e66337 | |||
| 5572f7e42e | |||
| a5eaece932 | |||
| f104abba84 | |||
| 05b6048dbd | |||
| 29894b6d2b | |||
| 07b38959a4 | |||
| 75a4d7c3da | |||
| 5f881b8c8d | |||
| 8cdcd87c53 | |||
| c03acf2ea7 | |||
| 8426636cdc | |||
| a0d56aef18 | |||
| a3d0c13654 | |||
| dfac7016a7 | |||
| 3df3059252 | |||
| e9b9f7599a | |||
| 3df79a9a1f | |||
| 3795f3cee3 | |||
| 96f4ad20fd | |||
| 63c088e783 | |||
| 81367381a9 | |||
| a9e03b1b82 | |||
| 0a0d0560ab | |||
| cdcc11d7d4 | |||
| 18bf807689 | |||
| cc285c5ab0 |
+13
-5
@@ -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
|
||||
@@ -1051,7 +1059,7 @@ install: sqlite3$(BEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_instal
|
||||
$(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir)
|
||||
|
||||
pkgIndex.tcl:
|
||||
echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3.so sqlite3]' > $@
|
||||
echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@
|
||||
tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
|
||||
$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
|
||||
$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
|
||||
|
||||
+258
-136
@@ -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 -DSQLITE_STDCALL=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
!ELSE
|
||||
!IFNDEF PLATFORM
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
SHELL_CCONV_OPTS =
|
||||
!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 $(DYNAMIC_SHELL)!=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 $(DYNAMIC_SHELL)!=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 $(DYNAMIC_SHELL)!=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,27 @@ 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)
|
||||
|
||||
MPTEST1 = mptester mptest.db $(TOP)/mptest/crash01.test --repeat 20
|
||||
MPTEST2 = mptester mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
|
||||
|
||||
mptest: mptester.exe
|
||||
del /Q mptest.db 2>NUL
|
||||
$(MPTEST1) --journalmode DELETE
|
||||
$(MPTEST2) --journalmode WAL
|
||||
$(MPTEST1) --journalmode WAL
|
||||
$(MPTEST2) --journalmode PERSIST
|
||||
$(MPTEST1) --journalmode PERSIST
|
||||
$(MPTEST2) --journalmode TRUNCATE
|
||||
$(MPTEST1) --journalmode TRUNCATE
|
||||
$(MPTEST2) --journalmode DELETE
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
@@ -1056,14 +1179,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 +1211,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 +1229,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 +1250,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 +1481,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 +1502,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 +1576,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 +1616,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 +1674,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 +1697,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)
|
||||
|
||||
@@ -884,6 +884,7 @@ TCL_LIB_SPEC
|
||||
TCL_STUB_LIB_FILE
|
||||
TCL_STUB_LIB_FLAG
|
||||
TCL_STUB_LIB_SPEC
|
||||
TCL_SHLIB_SUFFIX
|
||||
HAVE_TCL
|
||||
TARGET_READLINE_LIBS
|
||||
TARGET_READLINE_INC
|
||||
@@ -3724,13 +3725,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3727: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3728: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3730: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3731: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3733: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3734: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -4952,7 +4953,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 4955 "configure"' > conftest.$ac_ext
|
||||
echo '#line 4956 "configure"' > conftest.$ac_ext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6821,11 +6822,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6824: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6825: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6828: \$? = $ac_status" >&5
|
||||
echo "$as_me:6829: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7160,11 +7161,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7163: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7164: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7167: \$? = $ac_status" >&5
|
||||
echo "$as_me:7168: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7265,11 +7266,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7268: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7269: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7272: \$? = $ac_status" >&5
|
||||
echo "$as_me:7273: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -7320,11 +7321,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7323: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7324: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7327: \$? = $ac_status" >&5
|
||||
echo "$as_me:7328: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -10133,7 +10134,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 10136 "configure"
|
||||
#line 10137 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -10229,7 +10230,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 10232 "configure"
|
||||
#line 10233 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -12827,6 +12828,7 @@ $as_echo "file not found" >&6; }
|
||||
|
||||
|
||||
|
||||
|
||||
fi
|
||||
fi
|
||||
if test "${use_tcl}" = "no" ; then
|
||||
|
||||
@@ -430,6 +430,7 @@ if test "${use_tcl}" = "yes" ; then
|
||||
AC_SUBST(TCL_STUB_LIB_FILE)
|
||||
AC_SUBST(TCL_STUB_LIB_FLAG)
|
||||
AC_SUBST(TCL_STUB_LIB_SPEC)
|
||||
AC_SUBST(TCL_SHLIB_SUFFIX)
|
||||
fi
|
||||
fi
|
||||
if test "${use_tcl}" = "no" ; then
|
||||
|
||||
+62
-14
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1097,7 +1108,7 @@ static int fts3InitVtab(
|
||||
const char **aCol; /* Array of column names */
|
||||
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
|
||||
|
||||
int nIndex; /* Size of aIndex[] array */
|
||||
int nIndex = 0; /* Size of aIndex[] array */
|
||||
struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
|
||||
|
||||
/* The results of parsing supported FTS4 key=value options: */
|
||||
@@ -2491,26 +2502,33 @@ static int fts3DoclistOrMerge(
|
||||
**
|
||||
** The right-hand input doclist is overwritten by this function.
|
||||
*/
|
||||
static void fts3DoclistPhraseMerge(
|
||||
static int fts3DoclistPhraseMerge(
|
||||
int bDescDoclist, /* True if arguments are desc */
|
||||
int nDist, /* Distance from left to right (1=adjacent) */
|
||||
char *aLeft, int nLeft, /* Left doclist */
|
||||
char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
|
||||
char **paRight, int *pnRight /* IN/OUT: Right/output doclist */
|
||||
){
|
||||
sqlite3_int64 i1 = 0;
|
||||
sqlite3_int64 i2 = 0;
|
||||
sqlite3_int64 iPrev = 0;
|
||||
char *aRight = *paRight;
|
||||
char *pEnd1 = &aLeft[nLeft];
|
||||
char *pEnd2 = &aRight[*pnRight];
|
||||
char *p1 = aLeft;
|
||||
char *p2 = aRight;
|
||||
char *p;
|
||||
int bFirstOut = 0;
|
||||
char *aOut = aRight;
|
||||
char *aOut;
|
||||
|
||||
assert( nDist>0 );
|
||||
|
||||
if( bDescDoclist ){
|
||||
aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
|
||||
if( aOut==0 ) return SQLITE_NOMEM;
|
||||
}else{
|
||||
aOut = aRight;
|
||||
}
|
||||
p = aOut;
|
||||
|
||||
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
|
||||
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
|
||||
|
||||
@@ -2539,6 +2557,12 @@ static void fts3DoclistPhraseMerge(
|
||||
}
|
||||
|
||||
*pnRight = (int)(p - aOut);
|
||||
if( bDescDoclist ){
|
||||
sqlite3_free(aRight);
|
||||
*paRight = aOut;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2663,8 +2687,22 @@ static int fts3TermSelectMerge(
|
||||
){
|
||||
if( pTS->aaOutput[0]==0 ){
|
||||
/* If this is the first term selected, copy the doclist to the output
|
||||
** buffer using memcpy(). */
|
||||
pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
|
||||
** buffer using memcpy().
|
||||
**
|
||||
** Add FTS3_VARINT_MAX bytes of unused space to the end of the
|
||||
** allocation. This is so as to ensure that the buffer is big enough
|
||||
** to hold the current doclist AND'd with any other doclist. If the
|
||||
** doclists are stored in order=ASC order, this padding would not be
|
||||
** required (since the size of [doclistA AND doclistB] is always less
|
||||
** than or equal to the size of [doclistA] in that case). But this is
|
||||
** not true for order=DESC. For example, a doclist containing (1, -1)
|
||||
** may be smaller than (-1), as in the first example the -1 may be stored
|
||||
** as a single-byte delta, whereas in the second it must be stored as a
|
||||
** FTS3_VARINT_MAX byte varint.
|
||||
**
|
||||
** Similar padding is added in the fts3DoclistOrMerge() function.
|
||||
*/
|
||||
pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1);
|
||||
pTS->anOutput[0] = nDoclist;
|
||||
if( pTS->aaOutput[0] ){
|
||||
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
|
||||
@@ -3920,14 +3958,17 @@ static void fts3EvalAllocateReaders(
|
||||
** This function assumes that pList points to a buffer allocated using
|
||||
** sqlite3_malloc(). This function takes responsibility for eventually
|
||||
** freeing the buffer.
|
||||
**
|
||||
** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs.
|
||||
*/
|
||||
static void fts3EvalPhraseMergeToken(
|
||||
static int fts3EvalPhraseMergeToken(
|
||||
Fts3Table *pTab, /* FTS Table pointer */
|
||||
Fts3Phrase *p, /* Phrase to merge pList/nList into */
|
||||
int iToken, /* Token pList/nList corresponds to */
|
||||
char *pList, /* Pointer to doclist */
|
||||
int nList /* Number of bytes in pList */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
assert( iToken!=p->iDoclistToken );
|
||||
|
||||
if( pList==0 ){
|
||||
@@ -3966,13 +4007,16 @@ static void fts3EvalPhraseMergeToken(
|
||||
nDiff = p->iDoclistToken - iToken;
|
||||
}
|
||||
|
||||
fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight);
|
||||
rc = fts3DoclistPhraseMerge(
|
||||
pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight
|
||||
);
|
||||
sqlite3_free(pLeft);
|
||||
p->doclist.aAll = pRight;
|
||||
p->doclist.nAll = nRight;
|
||||
}
|
||||
|
||||
if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3998,7 +4042,7 @@ static int fts3EvalPhraseLoad(
|
||||
char *pThis = 0;
|
||||
rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
|
||||
if( rc==SQLITE_OK ){
|
||||
fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
|
||||
rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
|
||||
}
|
||||
}
|
||||
assert( pToken->pSegcsr==0 );
|
||||
@@ -4800,9 +4844,13 @@ static int fts3EvalSelectDeferred(
|
||||
char *pList = 0;
|
||||
rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
|
||||
assert( rc==SQLITE_OK || pList==0 );
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3EvalPhraseMergeToken(
|
||||
pTab, pTC->pPhrase, pTC->iToken,pList,nList
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int nCount;
|
||||
fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
|
||||
nCount = fts3DoclistCountDocids(
|
||||
pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -408,6 +408,19 @@ mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) $(THREADLIB)
|
||||
|
||||
MPTEST1=./mptester$(EXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
|
||||
MPTEST2=./mptester$(EXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
|
||||
mptest: mptester$(EXE)
|
||||
rm -f mptest.db
|
||||
$(MPTEST1) --journalmode DELETE
|
||||
$(MPTEST2) --journalmode WAL
|
||||
$(MPTEST1) --journalmode WAL
|
||||
$(MPTEST2) --journalmode PERSIST
|
||||
$(MPTEST1) --journalmode PERSIST
|
||||
$(MPTEST2) --journalmode TRUNCATE
|
||||
$(MPTEST1) --journalmode TRUNCATE
|
||||
$(MPTEST2) --journalmode DELETE
|
||||
|
||||
sqlite3.o: sqlite3.c
|
||||
$(TCCX) -I. -c sqlite3.c
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
C Add\sa\stest\sfor\sthe\schange\son\sthis\sbranch.
|
||||
D 2015-03-17T16:01:29.508
|
||||
C When\schecking\sfor\sthe\sWHERE-clause\spush-down\soptimization,\sverify\sthat\nall\sterms\sof\sthe\scompound\sinner\sSELECT\sare\snon-aggregate,\snot\sjust\sthe\nlast\sterm.\s\sFix\sfor\sticket\s[f7f8c97e97597].
|
||||
D 2017-07-17T19:25:10.921
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2f643d6968dfc0b82d2e546a0525a39079f9e928
|
||||
F Makefile.in 00d12636df7a5b08af09116bcd6c7bfd49b8b3b4
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 529e61cd9d29a3934758b4b3a0bb649b6c653481
|
||||
F Makefile.msc a8d817fa486d8c88dfbd19ae6a6567d9d350de39
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
|
||||
F VERSION 319eb1ced4b4d17a67730f2b7b85f15c1346cb60
|
||||
@@ -38,8 +38,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 613b220c2f2c7adcd50eb5ee4144ab581a150b47 x
|
||||
F configure.ac 6a8d145aea6d81f0b90013340780e43ed74fd5f4
|
||||
F configure 8b18c2378805a1d8aaca85d293671f450dd3c723 x
|
||||
F configure.ac 0b775d383c536bbaafc1e46dd3cbb81a7ea11aeb
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
@@ -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 23bd9d37a777342f5c22a648e9b4b005dde9e58f
|
||||
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
|
||||
@@ -152,40 +152,40 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 04c49c495795b18a7b70053eef285be1e4d43fa4
|
||||
F main.mk 997eee18387a3e69394f2f948c9c6ccf079655a4
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
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 dae6de83eddac3ef97fc4111632f6066760f939a
|
||||
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/analyze.c 91540f835163d5369ccbae78e2e6c74d0dd53c1d
|
||||
F src/alter.c d23d6b6991f66b383934f137fd4384d93fb98c81
|
||||
F src/analyze.c 92d7ab85ded7d16f424ee388d250bd99c64302de
|
||||
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/btreeInt.h 2bfefc01875d8da066504c233ec259fcb3b2ef72
|
||||
F src/build.c ba45ebd02904e84d98839a6ea74c3eb948596587
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 2caf598165f3608fde8abac2b243826616ce54b7
|
||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
||||
F src/build.c 3d1abf90ecf488d49eb0c0a673a9b1f22b3ef4e81b1bffa6cf3dfdb832125d3c
|
||||
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
|
||||
@@ -195,8 +195,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 40e333960d53f7d50ee8ce09d40431c87ea653f2
|
||||
F src/malloc.c 6a370b83d54e4bbf6f94021221c2a311cff26a18
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
@@ -214,32 +214,32 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
|
||||
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c cc903ecc6ebda90ef703d043ddaa7f33de0cab0f
|
||||
F src/os_win.c 8223e7db5b7c4a81d8b161098ac3959400434cdb
|
||||
F src/os_unix.c 25b80a3d167da44226a2084dc9e89a6cb1f02e2e
|
||||
F src/os_win.c 03d27be3a20048ef52a648d5f0a15f5edda9f2a3
|
||||
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
|
||||
F src/printf.c 8da9a2687a396daa19860f4dc90975d319304744
|
||||
F src/printf.c 8ae1fa9d30c1200a9268a390ba9e9cea9197b27a
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c f4d79e31ffa5820c2e3d1740baa5e9b190425f2b
|
||||
F src/resolve.c 41aa91af56d960e9414ce1d7c17cfb68e0d1c6cb
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 94e016b6733b1d39a2f4c8d431155b4c2897d907
|
||||
F src/shell.c cce82ca26392578a4a1ee927dfe55ea3411c7c92
|
||||
F src/sqlite.h.in 4eb59d93caec4b60eada51d3211087746187edef
|
||||
F src/select.c 7922b1e1aaceb8eea4b921d0e6d062e32cfef8d897c6b30015fdd546c9b9f57f
|
||||
F src/shell.c 84a1593bd86aaa14f4da8a8f9b16fbc239d262aa
|
||||
F src/sqlite.h.in 278602140d49575e8708e643161f4263e428a02a
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
F src/sqliteInt.h fae682c2b4dfbe489b134d74521c41c088f16ab1
|
||||
F src/sqliteInt.h 3b055fff776a257d0b2473edec5e121db8724c51c1034452c1be3b0faaf02f45
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 81712116e826b0089bb221b018929536b2b5406f
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
|
||||
F src/tclsqlite.c b290774586f022e16e04ba8ed2f0b8edd86b5b77
|
||||
F src/tclsqlite.c fa72a7c5278662357c105ba7925c1d0972506ff9
|
||||
F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
|
||||
@@ -258,7 +258,7 @@ F src/test_config.c c2d3ff6c129d50183900c7eff14158ff7e9b3f03
|
||||
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
|
||||
@@ -266,7 +266,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
|
||||
@@ -287,28 +287,28 @@ 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 1e2abdaedcbd3697994c4f244ae388b2afbe1e1023537a78abdf0bbf70ef23a7
|
||||
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
|
||||
F src/vdbeInt.h bb56fd199d8af1a2c1b9639ee2f70724b4338e3a
|
||||
F src/vdbeapi.c dac0d0d8009a8aa549cd77d9c29da44c0344f0c4
|
||||
F src/vdbeaux.c 97911edb61074b871ec4aa2d6bb779071643dee5
|
||||
F src/vdbeInt.h d96370101d9109cc476b42951272bd660336a638a6b8ef0d72c0911d6cdffbfd
|
||||
F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75
|
||||
F src/vdbeaux.c c562ac4e1d5803287f5ad2718460eb7e1f22b8356b22603f67f6b849056465e1
|
||||
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 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c eb141b075776e9864d38f279333e2472a8653202
|
||||
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
|
||||
F src/where.c 5e7cf96bd85f5e7cee1cce001031bc0ca1af68b8cfd07c781d1d8da7796eab34
|
||||
F src/whereInt.h 1d1fd0b3b9b56e08f5d3583c70a2c785a3c43941
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
|
||||
@@ -327,19 +327,20 @@ 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
|
||||
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
|
||||
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
|
||||
F test/atof1.test 08a61df9365c341f334a65f4348897312d8f3db7
|
||||
F test/attach.test 0d112b7713611fdf0340260192749737135fda5f
|
||||
F test/attach.test 437107943f14d131cf5efc2ae5305a94d7cb1d58
|
||||
F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
|
||||
F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27
|
||||
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
|
||||
@@ -383,6 +384,7 @@ F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45
|
||||
F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
|
||||
F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
|
||||
F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
|
||||
F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99
|
||||
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
|
||||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
@@ -397,7 +399,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
|
||||
@@ -431,6 +433,7 @@ F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
|
||||
F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
|
||||
F test/corruptI.test 221ad8b7f0a9ac6b80fc577e73b5ad8cdea31243
|
||||
F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91
|
||||
F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318
|
||||
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
|
||||
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
|
||||
@@ -442,6 +445,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
|
||||
@@ -481,7 +485,7 @@ F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
|
||||
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
|
||||
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
|
||||
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
|
||||
F test/e_walauto.test ca70cf75c07a6cb1874ced101dd426da76625649
|
||||
F test/e_walauto.test 6544af03423abc61b53cfb976839385ddc2a0a70
|
||||
F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608
|
||||
F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
@@ -562,7 +566,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
|
||||
@@ -584,15 +588,15 @@ F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
|
||||
F test/fts3expr4.test e1be1248566f43c252d4404d52914f1fc4bfa065
|
||||
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
|
||||
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
|
||||
F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
|
||||
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
||||
F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e
|
||||
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
||||
F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
|
||||
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
|
||||
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
|
||||
@@ -644,6 +648,7 @@ 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
|
||||
@@ -678,7 +683,7 @@ F test/join.test 52d4d49f86d0cf46926672878c4eaf0da399104a
|
||||
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test 5df23eba184f159ed9705a954957e765a10c141d
|
||||
F test/join5.test 8a5c0be6f0c260a5c7177c3b8f07c7856141038a
|
||||
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
|
||||
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
|
||||
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
|
||||
@@ -693,6 +698,7 @@ F test/like.test 4f2a71d36a536233727f71995fef900756705e56
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/like3.test 7b0525a39e4f25c4fd113de7e2e28eb712dcdedf
|
||||
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
|
||||
F test/limit2.test 7e7744cc548d7e4c92e1dd3edc30dd0f86adafd5
|
||||
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b
|
||||
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
|
||||
F test/lock.test b984ab9034e7389be0d863fe4e64cbbc4d2028f5
|
||||
@@ -725,7 +731,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
|
||||
@@ -738,7 +744,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
|
||||
@@ -766,7 +772,7 @@ F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/orderby1.test eb246e377612b21a418fbea57047ba8ea88aaa6b
|
||||
F test/orderby1.test 66ca14d7860a2da02411106968afee910ab1e657
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
||||
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
||||
@@ -792,7 +798,7 @@ F test/permutations.test f9cc1dd987986c9d4949211c7a4ed55ec9aecba1
|
||||
F test/pragma.test ad99d05e411c7687302124be56f3b362204be041
|
||||
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
|
||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test b4acd4bf8734243257f01ddefa17c4fb090acc8a
|
||||
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
@@ -834,13 +840,13 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test fc2a61f226a649393664ad54bc5376631801517c
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test e20e8ce47b558de80616102ef273704cf0d48a3b
|
||||
F test/select4.test ddcaffe16252e84b85550d775b7a03bcf0d390b688122ca653d7199e469e3d5e
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
||||
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
|
||||
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
|
||||
F test/selectA.test 64b88a80271c1710966e50e633380696b60a12a4
|
||||
F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7
|
||||
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
|
||||
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
|
||||
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
|
||||
@@ -863,7 +869,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
|
||||
@@ -906,7 +912,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
|
||||
@@ -1108,8 +1114,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
|
||||
@@ -1139,7 +1145,7 @@ F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
|
||||
F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
|
||||
F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877
|
||||
F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434
|
||||
F test/walblock.test f1290524714232c109fb0b14db28f14d81c3ddd0
|
||||
F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d
|
||||
F test/walcksum.test 9afeb96240296c08c72fc524d199c912cfe34daa
|
||||
F test/walcrash.test 451d79e528add5c42764cea74aa2750754171b25
|
||||
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
|
||||
@@ -1166,19 +1172,20 @@ F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
|
||||
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
|
||||
F test/whereD.test fd9120e262f9da3c45940f52aefeef4d15b904e5
|
||||
F test/whereD.test ac6926e3f518d5b75b61e81c2b7c327565e07a4bd919b6c5c3a003ca0cf19021
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
||||
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
||||
F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767
|
||||
F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
F test/win32lock.test 71642fa56e9b06e5cfffe6bad67cb8c1eb2c555a
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068
|
||||
F test/with1.test 9df5cd8a62148b3d9ef8597aea563e3863018bcd
|
||||
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
|
||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||
F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151
|
||||
@@ -1186,11 +1193,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
|
||||
@@ -1200,7 +1207,7 @@ F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c 1864c4fe4a72b1bb28f1792b60504804fe82c5d2
|
||||
F tool/lemon.c ae5f61e3b164d35955777b20d6febcbaf0950702
|
||||
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
|
||||
F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
|
||||
@@ -1208,9 +1215,9 @@ F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 94f196c9961e0ca3513e29f57125a3197808be2d
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 9ef48e1748dce7b844f67e2450ff9dfeb0fb4ab5
|
||||
F tool/mksqlite3c.tcl 95ab31eda659e7ffb091e04bd83178f260d8edfd
|
||||
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
|
||||
F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e
|
||||
F tool/mksqlite3c.tcl 52a3352f7aa15f1db851e45ac3a5e2173d6fe93c
|
||||
F tool/mksqlite3h.tcl 44730d586c9031638cdd2eb443b801c0d2dbd9f8
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
@@ -1219,8 +1226,9 @@ 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/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
|
||||
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
@@ -1242,7 +1250,8 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P c6e6d5f4e06c3ac0bfb620c0c728fbc7230c4a02
|
||||
R 15a95b25b03827505e198326f8e27a62
|
||||
U dan
|
||||
Z 12b0ab91b3a13b6777d198c7ff155c7d
|
||||
P 52674f948c3e74e5cc32874d4885f2302ad1d5dd0bc45ff6bfda18cf4bea904a
|
||||
Q +ec215f94ac9748c0acd82af0cc9e7a92249462f9
|
||||
R a908a996bcff610704d1aca2821ce465
|
||||
U drh
|
||||
Z 30ce9b14a61bc1a1adc0dcec2dba7a8c
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
e22dde187eb0b389d6d93e2e39a26fd0f4e6196e
|
||||
adc082c1461e0237cd42653b529fbc136f5899baeff6ee32ee943d76184080c1
|
||||
@@ -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';
|
||||
|
||||
+34
-5
@@ -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);
|
||||
@@ -1305,6 +1312,9 @@ int main(int argc, char **argv){
|
||||
GETPID(), iClient);
|
||||
}else{
|
||||
if( g.iTrace>0 ){
|
||||
printf("BEGIN: %s", argv[0]);
|
||||
for(i=1; i<argc; i++) printf(" %s", argv[i]);
|
||||
printf("\n");
|
||||
printf("With SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\n" );
|
||||
for(i=0; (zCOption = sqlite3_compileoption_get(i))!=0; i++){
|
||||
printf("-DSQLITE_%s\n", zCOption);
|
||||
@@ -1317,6 +1327,17 @@ int main(int argc, char **argv){
|
||||
}
|
||||
rc = sqlite3_open_v2(g.zDbFile, &g.db, openFlags, g.zVfs);
|
||||
if( rc ) fatalError("cannot open [%s]", g.zDbFile);
|
||||
if( zJMode ){
|
||||
#if defined(_WIN32)
|
||||
if( sqlite3_stricmp(zJMode,"persist")==0
|
||||
|| sqlite3_stricmp(zJMode,"truncate")==0
|
||||
){
|
||||
printf("Changing journal mode to DELETE from %s", zJMode);
|
||||
zJMode = "DELETE";
|
||||
}
|
||||
#endif
|
||||
runSql("PRAGMA journal_mode=%Q;", zJMode);
|
||||
}
|
||||
sqlite3_enable_load_extension(g.db, 1);
|
||||
sqlite3_busy_handler(g.db, busyHandler, 0);
|
||||
sqlite3_create_function(g.db, "vfsname", 0, SQLITE_UTF8, 0,
|
||||
@@ -1349,6 +1370,9 @@ int main(int argc, char **argv){
|
||||
}
|
||||
if( n>1 ) unrecognizedArguments(argv[0], n, argv+2);
|
||||
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 +1388,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,11 +1417,14 @@ 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 ){
|
||||
printf("Summary: %d errors out of %d tests\n", g.nError, g.nTest);
|
||||
printf("END: %s", argv[0]);
|
||||
for(i=1; i<argc; i++) printf(" %s", argv[i]);
|
||||
printf("\n");
|
||||
}
|
||||
return g.nError>0;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+4
-1
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1619,7 +1619,7 @@ static void initAvgEq(Index *pIdx){
|
||||
}
|
||||
}
|
||||
|
||||
if( nDist100>nSum100 ){
|
||||
if( nDist100>nSum100 && sumEq<nRow ){
|
||||
avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100);
|
||||
}
|
||||
if( avgEq==0 ) avgEq = 1;
|
||||
|
||||
@@ -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--;
|
||||
|
||||
+45
-23
@@ -600,10 +600,15 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){
|
||||
static int saveCursorPosition(BtCursor *pCur){
|
||||
int rc;
|
||||
|
||||
assert( CURSOR_VALID==pCur->eState );
|
||||
assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState );
|
||||
assert( 0==pCur->pKey );
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
|
||||
if( pCur->eState==CURSOR_SKIPNEXT ){
|
||||
pCur->eState = CURSOR_VALID;
|
||||
}else{
|
||||
pCur->skipNext = 0;
|
||||
}
|
||||
rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
|
||||
assert( rc==SQLITE_OK ); /* KeySize() cannot fail */
|
||||
|
||||
@@ -674,7 +679,7 @@ static int SQLITE_NOINLINE saveCursorsOnList(
|
||||
){
|
||||
do{
|
||||
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
|
||||
if( p->eState==CURSOR_VALID ){
|
||||
if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
|
||||
int rc = saveCursorPosition(p);
|
||||
if( SQLITE_OK!=rc ){
|
||||
return rc;
|
||||
@@ -746,17 +751,19 @@ static int btreeMoveto(
|
||||
*/
|
||||
static int btreeRestoreCursorPosition(BtCursor *pCur){
|
||||
int rc;
|
||||
int skipNext;
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->eState>=CURSOR_REQUIRESEEK );
|
||||
if( pCur->eState==CURSOR_FAULT ){
|
||||
return pCur->skipNext;
|
||||
}
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext);
|
||||
rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_free(pCur->pKey);
|
||||
pCur->pKey = 0;
|
||||
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
|
||||
pCur->skipNext |= skipNext;
|
||||
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
|
||||
pCur->eState = CURSOR_SKIPNEXT;
|
||||
}
|
||||
@@ -808,9 +815,10 @@ int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
|
||||
*pDifferentRow = 1;
|
||||
return rc;
|
||||
}
|
||||
if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
|
||||
if( pCur->eState!=CURSOR_VALID ){
|
||||
*pDifferentRow = 1;
|
||||
}else{
|
||||
assert( pCur->skipNext==0 );
|
||||
*pDifferentRow = 0;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
@@ -1951,16 +1959,18 @@ int sqlite3BtreeOpen(
|
||||
*/
|
||||
if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
|
||||
if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
|
||||
int nFilename = sqlite3Strlen30(zFilename)+1;
|
||||
int nFullPathname = pVfs->mxPathname+1;
|
||||
char *zFullPathname = sqlite3Malloc(nFullPathname);
|
||||
char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename));
|
||||
MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
|
||||
|
||||
p->sharable = 1;
|
||||
if( !zFullPathname ){
|
||||
sqlite3_free(p);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( isMemdb ){
|
||||
memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
|
||||
memcpy(zFullPathname, zFilename, nFilename);
|
||||
}else{
|
||||
rc = sqlite3OsFullPathname(pVfs, zFilename,
|
||||
nFullPathname, zFullPathname);
|
||||
@@ -2017,8 +2027,8 @@ int sqlite3BtreeOpen(
|
||||
** the right size. This is to guard against size changes that result
|
||||
** when compiling on a different architecture.
|
||||
*/
|
||||
assert( sizeof(i64)==8 || sizeof(i64)==4 );
|
||||
assert( sizeof(u64)==8 || sizeof(u64)==4 );
|
||||
assert( sizeof(i64)==8 );
|
||||
assert( sizeof(u64)==8 );
|
||||
assert( sizeof(u32)==4 );
|
||||
assert( sizeof(u16)==2 );
|
||||
assert( sizeof(Pgno)==4 );
|
||||
@@ -3625,7 +3635,7 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
|
||||
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
|
||||
int i;
|
||||
if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
|
||||
if( p->eState==CURSOR_VALID ){
|
||||
if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
|
||||
rc = saveCursorPosition(p);
|
||||
if( rc!=SQLITE_OK ){
|
||||
(void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
|
||||
@@ -4031,6 +4041,8 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
|
||||
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( pCur->iPage>=0 );
|
||||
assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
|
||||
assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
|
||||
getCellInfo(pCur);
|
||||
*pSize = pCur->info.nPayload;
|
||||
@@ -4509,7 +4521,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if SQLITE_DEBUG
|
||||
/*
|
||||
** Page pParent is an internal (non-leaf) tree page. This function
|
||||
** asserts that page number iChild is the left-child if the iIdx'th
|
||||
@@ -4518,6 +4530,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
|
||||
** the page.
|
||||
*/
|
||||
static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
|
||||
if( CORRUPT_DB ) return; /* The conditions tested below might not be true
|
||||
** in a corrupt database */
|
||||
assert( iIdx<=pParent->nCell );
|
||||
if( iIdx==pParent->nCell ){
|
||||
assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild );
|
||||
@@ -4542,19 +4556,11 @@ static void moveToParent(BtCursor *pCur){
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( pCur->iPage>0 );
|
||||
assert( pCur->apPage[pCur->iPage] );
|
||||
|
||||
/* UPDATE: It is actually possible for the condition tested by the assert
|
||||
** below to be untrue if the database file is corrupt. This can occur if
|
||||
** one cursor has modified page pParent while a reference to it is held
|
||||
** by a second cursor. Which can only happen if a single page is linked
|
||||
** into more than one b-tree structure in a corrupt database. */
|
||||
#if 0
|
||||
assertParentIndex(
|
||||
pCur->apPage[pCur->iPage-1],
|
||||
pCur->aiIdx[pCur->iPage-1],
|
||||
pCur->apPage[pCur->iPage]->pgno
|
||||
);
|
||||
#endif
|
||||
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
|
||||
|
||||
releasePage(pCur->apPage[pCur->iPage]);
|
||||
@@ -7480,7 +7486,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
|
||||
@@ -7501,6 +7508,7 @@ static int balance(BtCursor *pCur){
|
||||
/* The next iteration of the do-loop balances the parent page. */
|
||||
releasePage(pPage);
|
||||
pCur->iPage--;
|
||||
assert( pCur->iPage>=0 );
|
||||
}
|
||||
}while( rc==SQLITE_OK );
|
||||
|
||||
@@ -7977,9 +7985,13 @@ static int clearDatabasePage(
|
||||
if( pgno>btreePagecount(pBt) ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
|
||||
rc = getAndInitPage(pBt, pgno, &pPage, 0);
|
||||
if( rc ) return rc;
|
||||
if( pPage->bBusy ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto cleardatabasepage_out;
|
||||
}
|
||||
pPage->bBusy = 1;
|
||||
hdr = pPage->hdrOffset;
|
||||
for(i=0; i<pPage->nCell; i++){
|
||||
pCell = findCell(pPage, i);
|
||||
@@ -8004,6 +8016,7 @@ static int clearDatabasePage(
|
||||
}
|
||||
|
||||
cleardatabasepage_out:
|
||||
pPage->bBusy = 0;
|
||||
releasePage(pPage);
|
||||
return rc;
|
||||
}
|
||||
@@ -9143,14 +9156,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.
|
||||
*/
|
||||
|
||||
+14
-1
@@ -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);
|
||||
|
||||
|
||||
@@ -280,6 +280,7 @@ struct MemPage {
|
||||
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
|
||||
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
|
||||
u8 max1bytePayload; /* min(maxLocal,127) */
|
||||
u8 bBusy; /* Prevent endless loops on corrupt database files */
|
||||
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
|
||||
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
|
||||
u16 cellOffset; /* Index in aData of first cell pointer */
|
||||
|
||||
@@ -949,7 +949,11 @@ void sqlite3StartTable(
|
||||
pTable->iPKey = -1;
|
||||
pTable->pSchema = db->aDb[iDb].pSchema;
|
||||
pTable->nRef = 1;
|
||||
#ifdef SQLITE_DEFAULT_ROWEST
|
||||
pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST);
|
||||
#else
|
||||
pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
|
||||
#endif
|
||||
assert( pParse->pNewTable==0 );
|
||||
pParse->pNewTable = pTable;
|
||||
|
||||
@@ -3183,6 +3187,7 @@ Index *sqlite3CreateIndex(
|
||||
pIdx->onError = pIndex->onError;
|
||||
}
|
||||
}
|
||||
pRet = pIdx;
|
||||
goto exit_create_index;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -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);
|
||||
}
|
||||
|
||||
+3
-1
@@ -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;
|
||||
|
||||
+6
-1
@@ -62,7 +62,7 @@ int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
|
||||
** I/O active are written using this function. These messages
|
||||
** are intended for debugging activity only.
|
||||
*/
|
||||
/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0;
|
||||
SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -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
|
||||
|
||||
+32
-22
@@ -75,6 +75,13 @@ static SQLITE_WSD struct Mem0Global {
|
||||
|
||||
#define mem0 GLOBAL(struct Mem0Global, mem0)
|
||||
|
||||
/*
|
||||
** Return the memory allocator mutex. sqlite3_status() needs it.
|
||||
*/
|
||||
sqlite3_mutex *sqlite3MallocMutex(void){
|
||||
return mem0.mutex;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine runs when the memory allocator sees that the
|
||||
** total memory allocation is about to exceed the soft heap
|
||||
@@ -97,7 +104,7 @@ static int sqlite3MemoryAlarm(
|
||||
void *pArg,
|
||||
sqlite3_int64 iThreshold
|
||||
){
|
||||
int nUsed;
|
||||
sqlite3_int64 nUsed;
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
mem0.alarmCallback = xCallback;
|
||||
mem0.alarmArg = pArg;
|
||||
@@ -155,6 +162,7 @@ void sqlite3_soft_heap_limit(int n){
|
||||
** Initialize the memory allocation subsystem.
|
||||
*/
|
||||
int sqlite3MallocInit(void){
|
||||
int rc;
|
||||
if( sqlite3GlobalConfig.m.xMalloc==0 ){
|
||||
sqlite3MemSetDefault();
|
||||
}
|
||||
@@ -190,7 +198,9 @@ int sqlite3MallocInit(void){
|
||||
sqlite3GlobalConfig.szPage = 0;
|
||||
sqlite3GlobalConfig.nPage = 0;
|
||||
}
|
||||
return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
|
||||
rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
|
||||
if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -266,7 +276,7 @@ static int mallocWithAlarm(int n, void **pp){
|
||||
nFull = sqlite3GlobalConfig.m.xRoundup(n);
|
||||
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
|
||||
if( mem0.alarmCallback!=0 ){
|
||||
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
if( nUsed >= mem0.alarmThreshold - nFull ){
|
||||
mem0.nearlyFull = 1;
|
||||
sqlite3MallocAlarm(nFull);
|
||||
@@ -283,8 +293,8 @@ static int mallocWithAlarm(int n, void **pp){
|
||||
#endif
|
||||
if( p ){
|
||||
nFull = sqlite3MallocSize(p);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
}
|
||||
*pp = p;
|
||||
return nFull;
|
||||
@@ -361,14 +371,14 @@ void *sqlite3ScratchMalloc(int n){
|
||||
p = mem0.pScratchFree;
|
||||
mem0.pScratchFree = mem0.pScratchFree->pNext;
|
||||
mem0.nScratchFree--;
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
p = sqlite3Malloc(n);
|
||||
if( sqlite3GlobalConfig.bMemstat && p ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
|
||||
sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
|
||||
@@ -409,19 +419,19 @@ void sqlite3ScratchFree(void *p){
|
||||
mem0.pScratchFree = pSlot;
|
||||
mem0.nScratchFree++;
|
||||
assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
/* Release memory back to the heap */
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
int iSize = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3GlobalConfig.m.xFree(p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
@@ -452,7 +462,7 @@ int sqlite3MallocSize(void *p){
|
||||
}
|
||||
int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
if( db==0 ){
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
return sqlite3MallocSize(p);
|
||||
}else{
|
||||
@@ -461,13 +471,13 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
return db->lookaside.sz;
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_uint64 sqlite3_msize(void *p){
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
@@ -478,11 +488,11 @@ sqlite3_uint64 sqlite3_msize(void *p){
|
||||
void sqlite3_free(void *p){
|
||||
if( p==0 ) return; /* IMP: R-49053-54554 */
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p));
|
||||
sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3GlobalConfig.m.xFree(p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
@@ -523,7 +533,7 @@ void sqlite3DbFree(sqlite3 *db, void *p){
|
||||
}
|
||||
}
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
sqlite3_free(p);
|
||||
@@ -536,7 +546,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
int nOld, nNew, nDiff;
|
||||
void *pNew;
|
||||
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) );
|
||||
if( pOld==0 ){
|
||||
return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */
|
||||
}
|
||||
@@ -570,7 +580,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
}
|
||||
if( pNew ){
|
||||
nNew = sqlite3MallocSize(pNew);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
||||
}
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
@@ -703,7 +713,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
|
||||
}
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
pNew = sqlite3_realloc64(p, n);
|
||||
if( !pNew ){
|
||||
|
||||
+22
-22
@@ -1536,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
|
||||
@@ -1744,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 ){
|
||||
@@ -2171,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 */
|
||||
@@ -2389,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 */
|
||||
@@ -2557,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 */
|
||||
@@ -2771,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
|
||||
@@ -2957,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 ){
|
||||
@@ -3782,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; // Deferred feature */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_LOCKSTATE: {
|
||||
*(int*)pArg = pFile->eFileLock;
|
||||
return SQLITE_OK;
|
||||
@@ -4632,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;
|
||||
}
|
||||
|
||||
@@ -5727,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);
|
||||
}
|
||||
|
||||
@@ -6119,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;
|
||||
@@ -6440,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);
|
||||
@@ -6462,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;
|
||||
}
|
||||
|
||||
@@ -6489,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;
|
||||
}
|
||||
}
|
||||
@@ -6498,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;
|
||||
}
|
||||
|
||||
@@ -6804,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 ){
|
||||
@@ -7014,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);
|
||||
}
|
||||
@@ -7156,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 ){
|
||||
@@ -7228,10 +7232,6 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
|
||||
*/
|
||||
static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_WAL_BLOCK: {
|
||||
id->ctrlFlags |= UNIXFILE_BLOCK;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
if( pFile->pMethod == &proxyIoMethods ){
|
||||
|
||||
+78
-33
@@ -197,8 +197,10 @@ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
|
||||
#endif /* SQLITE_OS_WINRT */
|
||||
|
||||
/*
|
||||
** This file mapping API is common to both Win32 and WinRT.
|
||||
** These file mapping APIs are common to both Win32 and WinRT.
|
||||
*/
|
||||
|
||||
WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T);
|
||||
WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
|
||||
#endif /* SQLITE_WIN32_FILEMAPPING_API */
|
||||
|
||||
@@ -1083,6 +1085,15 @@ static struct win_syscall {
|
||||
#define osUuidCreateSequential \
|
||||
((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
|
||||
|
||||
#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
|
||||
{ "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
|
||||
#else
|
||||
{ "FlushViewOfFile", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osFlushViewOfFile \
|
||||
((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
|
||||
/*
|
||||
@@ -1966,11 +1977,11 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
|
||||
/*
|
||||
** Log a I/O error retry episode.
|
||||
*/
|
||||
static void winLogIoerr(int nRetry){
|
||||
static void winLogIoerr(int nRetry, int lineno){
|
||||
if( nRetry ){
|
||||
sqlite3_log(SQLITE_IOERR,
|
||||
"delayed %dms for lock/sharing conflict",
|
||||
winIoerrRetryDelay*nRetry*(nRetry+1)/2
|
||||
sqlite3_log(SQLITE_NOTICE,
|
||||
"delayed %dms for lock/sharing conflict at line %d",
|
||||
winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2450,7 +2461,8 @@ static int winClose(sqlite3_file *id){
|
||||
assert( pFile->pShm==0 );
|
||||
#endif
|
||||
assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
|
||||
OSTRACE(("CLOSE file=%p\n", pFile->h));
|
||||
OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
winUnmapfile(pFile);
|
||||
@@ -2479,7 +2491,8 @@ static int winClose(sqlite3_file *id){
|
||||
pFile->h = NULL;
|
||||
}
|
||||
OpenCounter(-1);
|
||||
OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
|
||||
OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed"));
|
||||
return rc ? SQLITE_OK
|
||||
: winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
|
||||
"winClose", pFile->zPath);
|
||||
@@ -2507,7 +2520,8 @@ static int winRead(
|
||||
assert( amt>0 );
|
||||
assert( offset>=0 );
|
||||
SimulateIOError(return SQLITE_IOERR_READ);
|
||||
OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
|
||||
"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
|
||||
pFile->h, pBuf, amt, offset, pFile->locktype));
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
@@ -2516,7 +2530,8 @@ static int winRead(
|
||||
if( offset<pFile->mmapSize ){
|
||||
if( offset+amt <= pFile->mmapSize ){
|
||||
memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
|
||||
OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
int nCopy = (int)(pFile->mmapSize - offset);
|
||||
@@ -2530,7 +2545,8 @@ static int winRead(
|
||||
|
||||
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
if( winSeekFile(pFile, offset) ){
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_FULL;
|
||||
}
|
||||
while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
|
||||
@@ -2544,19 +2560,22 @@ static int winRead(
|
||||
DWORD lastErrno;
|
||||
if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
|
||||
pFile->lastErrno = lastErrno;
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
|
||||
"winRead", pFile->zPath);
|
||||
}
|
||||
winLogIoerr(nRetry);
|
||||
winLogIoerr(nRetry, __LINE__);
|
||||
if( nRead<(DWORD)amt ){
|
||||
/* Unread parts of the buffer must be zero-filled */
|
||||
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -2579,7 +2598,8 @@ static int winWrite(
|
||||
SimulateIOError(return SQLITE_IOERR_WRITE);
|
||||
SimulateDiskfullError(return SQLITE_FULL);
|
||||
|
||||
OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
|
||||
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
|
||||
"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
|
||||
pFile->h, pBuf, amt, offset, pFile->locktype));
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
@@ -2588,7 +2608,8 @@ static int winWrite(
|
||||
if( offset<pFile->mmapSize ){
|
||||
if( offset+amt <= pFile->mmapSize ){
|
||||
memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
|
||||
OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
int nCopy = (int)(pFile->mmapSize - offset);
|
||||
@@ -2651,17 +2672,20 @@ static int winWrite(
|
||||
if( rc ){
|
||||
if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
|
||||
|| ( pFile->lastErrno==ERROR_DISK_FULL )){
|
||||
OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
|
||||
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return winLogError(SQLITE_FULL, pFile->lastErrno,
|
||||
"winWrite1", pFile->zPath);
|
||||
}
|
||||
OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
|
||||
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
|
||||
"winWrite2", pFile->zPath);
|
||||
}else{
|
||||
winLogIoerr(nRetry);
|
||||
winLogIoerr(nRetry, __LINE__);
|
||||
}
|
||||
OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -2675,8 +2699,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
|
||||
|
||||
assert( pFile );
|
||||
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
|
||||
OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
|
||||
pFile->h, nByte, pFile->locktype));
|
||||
OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));
|
||||
|
||||
/* If the user has configured a chunk-size for this file, truncate the
|
||||
** file so that it consists of an integer number of chunks (i.e. the
|
||||
@@ -2708,7 +2732,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
|
||||
}
|
||||
#endif
|
||||
|
||||
OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
|
||||
OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc)));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2753,8 +2778,9 @@ static int winSync(sqlite3_file *id, int flags){
|
||||
*/
|
||||
SimulateDiskfullError( return SQLITE_FULL );
|
||||
|
||||
OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
|
||||
pFile->h, flags, pFile->locktype));
|
||||
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h, flags,
|
||||
pFile->locktype));
|
||||
|
||||
#ifndef SQLITE_TEST
|
||||
UNUSED_PARAMETER(flags);
|
||||
@@ -2769,19 +2795,38 @@ static int winSync(sqlite3_file *id, int flags){
|
||||
** no-op
|
||||
*/
|
||||
#ifdef SQLITE_NO_SYNC
|
||||
OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
#else
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
if( pFile->pMapRegion ){
|
||||
if( osFlushViewOfFile(pFile->pMapRegion, 0) ){
|
||||
OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
|
||||
"rc=SQLITE_OK\n", osGetCurrentProcessId(),
|
||||
pFile, pFile->pMapRegion));
|
||||
}else{
|
||||
pFile->lastErrno = osGetLastError();
|
||||
OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
|
||||
"rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(),
|
||||
pFile, pFile->pMapRegion));
|
||||
return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
|
||||
"winSync1", pFile->zPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rc = osFlushFileBuffers(pFile->h);
|
||||
SimulateIOError( rc=FALSE );
|
||||
if( rc ){
|
||||
OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
pFile->lastErrno = osGetLastError();
|
||||
OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
|
||||
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->h));
|
||||
return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
|
||||
"winSync", pFile->zPath);
|
||||
"winSync2", pFile->zPath);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -4752,7 +4797,7 @@ static int winOpen(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
winLogIoerr(cnt);
|
||||
winLogIoerr(cnt, __LINE__);
|
||||
|
||||
OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
|
||||
dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
|
||||
@@ -4936,7 +4981,7 @@ static int winDelete(
|
||||
if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
|
||||
rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
|
||||
}else{
|
||||
winLogIoerr(cnt);
|
||||
winLogIoerr(cnt, __LINE__);
|
||||
}
|
||||
sqlite3_free(zConverted);
|
||||
OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
|
||||
@@ -4986,7 +5031,7 @@ static int winAccess(
|
||||
attr = sAttrData.dwFileAttributes;
|
||||
}
|
||||
}else{
|
||||
winLogIoerr(cnt);
|
||||
winLogIoerr(cnt, __LINE__);
|
||||
if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
|
||||
sqlite3_free(zConverted);
|
||||
return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
|
||||
@@ -5555,7 +5600,7 @@ int sqlite3_os_init(void){
|
||||
|
||||
/* Double-check that the aSyscall[] array has been constructed
|
||||
** correctly. See ticket [bb3a86e890c8e96ab] */
|
||||
assert( ArraySize(aSyscall)==79 );
|
||||
assert( ArraySize(aSyscall)==80 );
|
||||
|
||||
/* get memory map allocation granularity */
|
||||
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
|
||||
|
||||
+3
-3
@@ -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");
|
||||
|
||||
+14
-5
@@ -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
|
||||
|
||||
+23
-9
@@ -261,15 +261,19 @@ void sqlite3VXPrintf(
|
||||
}
|
||||
if( width<0 ){
|
||||
flag_leftjustify = 1;
|
||||
width = -width;
|
||||
width = width >= -2147483647 ? -width : 0;
|
||||
}
|
||||
c = *++fmt;
|
||||
}else{
|
||||
unsigned wx = 0;
|
||||
while( c>='0' && c<='9' ){
|
||||
width = width*10 + c - '0';
|
||||
wx = wx*10 + c - '0';
|
||||
c = *++fmt;
|
||||
}
|
||||
testcase( wx>0x7fffffff );
|
||||
width = wx & 0x7fffffff;
|
||||
}
|
||||
|
||||
/* Get the precision */
|
||||
if( c=='.' ){
|
||||
precision = 0;
|
||||
@@ -280,13 +284,18 @@ void sqlite3VXPrintf(
|
||||
}else{
|
||||
precision = va_arg(ap,int);
|
||||
}
|
||||
if( precision<0 ) precision = -precision;
|
||||
c = *++fmt;
|
||||
if( precision<0 ){
|
||||
precision = precision >= -2147483647 ? -precision : -1;
|
||||
}
|
||||
}else{
|
||||
unsigned px = 0;
|
||||
while( c>='0' && c<='9' ){
|
||||
precision = precision*10 + c - '0';
|
||||
px = px*10 + c - '0';
|
||||
c = *++fmt;
|
||||
}
|
||||
testcase( px>0x7fffffff );
|
||||
precision = px & 0x7fffffff;
|
||||
}
|
||||
}else{
|
||||
precision = -1;
|
||||
@@ -450,7 +459,8 @@ void sqlite3VXPrintf(
|
||||
else prefix = 0;
|
||||
}
|
||||
if( xtype==etGENERIC && precision>0 ) precision--;
|
||||
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
|
||||
testcase( precision>0xfff );
|
||||
for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
|
||||
if( xtype==etFLOAT ) realvalue += rounder;
|
||||
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
|
||||
exp = 0;
|
||||
@@ -505,8 +515,9 @@ void sqlite3VXPrintf(
|
||||
}else{
|
||||
e2 = exp;
|
||||
}
|
||||
if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
|
||||
bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
|
||||
if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){
|
||||
bufpt = zExtra
|
||||
= sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
|
||||
if( bufpt==0 ){
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
return;
|
||||
@@ -738,7 +749,7 @@ void sqlite3VXPrintf(
|
||||
*/
|
||||
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
char *zNew;
|
||||
assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
|
||||
assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
|
||||
if( p->accError ){
|
||||
testcase(p->accError==STRACCUM_TOOBIG);
|
||||
testcase(p->accError==STRACCUM_NOMEM);
|
||||
@@ -787,7 +798,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
** Append N copies of character c to the given string buffer.
|
||||
*/
|
||||
void sqlite3AppendChar(StrAccum *p, int N, char c){
|
||||
if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
|
||||
testcase( p->nChar + (i64)N > 0x7fffffff );
|
||||
if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
|
||||
return;
|
||||
}
|
||||
while( (N--)>0 ) p->zText[p->nChar++] = c;
|
||||
}
|
||||
|
||||
|
||||
@@ -1186,6 +1186,20 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
sqlite3ResolveExprNames(&sNC, p->pOffset) ){
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
/* If the SF_Converted flags is set, then this Select object was
|
||||
** was created by the convertCompoundSelectToSubquery() function.
|
||||
** In this case the ORDER BY clause (p->pOrderBy) should be resolved
|
||||
** as if it were part of the sub-query, not the parent. This block
|
||||
** moves the pOrderBy down to the sub-query. It will be moved back
|
||||
** after the names have been resolved. */
|
||||
if( p->selFlags & SF_Converted ){
|
||||
Select *pSub = p->pSrc->a[0].pSelect;
|
||||
assert( p->pSrc->nSrc==1 && isCompound==0 && p->pOrderBy );
|
||||
assert( pSub->pPrior && pSub->pOrderBy==0 );
|
||||
pSub->pOrderBy = p->pOrderBy;
|
||||
p->pOrderBy = 0;
|
||||
}
|
||||
|
||||
/* Recursively resolve names in all subqueries
|
||||
*/
|
||||
@@ -1268,6 +1282,17 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
sNC.pNext = 0;
|
||||
sNC.ncFlags |= NC_AllowAgg;
|
||||
|
||||
/* If this is a converted compound query, move the ORDER BY clause from
|
||||
** the sub-query back to the parent query. At this point each term
|
||||
** within the ORDER BY clause has been transformed to an integer value.
|
||||
** These integers will be replaced by copies of the corresponding result
|
||||
** set expressions by the call to resolveOrderGroupBy() below. */
|
||||
if( p->selFlags & SF_Converted ){
|
||||
Select *pSub = p->pSrc->a[0].pSelect;
|
||||
p->pOrderBy = pSub->pOrderBy;
|
||||
pSub->pOrderBy = 0;
|
||||
}
|
||||
|
||||
/* Process the ORDER BY clause for singleton SELECT statements.
|
||||
** The ORDER BY clause for compounds SELECT statements is handled
|
||||
** below, after all of the result-sets for all of the elements of
|
||||
|
||||
+278
-62
@@ -53,7 +53,9 @@ struct SortCtx {
|
||||
int regReturn; /* Register holding block-output return address */
|
||||
int labelBkOut; /* Start label for the block-output subroutine */
|
||||
int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */
|
||||
int labelDone; /* Jump here when done, ex: LIMIT reached */
|
||||
u8 sortFlags; /* Zero or more SORTFLAG_* bits */
|
||||
u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */
|
||||
};
|
||||
#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
|
||||
|
||||
@@ -501,6 +503,7 @@ static void pushOntoSorter(
|
||||
int regRecord = ++pParse->nMem; /* Assembled sorter record */
|
||||
int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */
|
||||
int op; /* Opcode to add sorter record to sorter */
|
||||
int iLimit; /* LIMIT counter */
|
||||
|
||||
assert( bSeq==0 || bSeq==1 );
|
||||
if( nPrefixReg ){
|
||||
@@ -510,6 +513,9 @@ static void pushOntoSorter(
|
||||
regBase = pParse->nMem + 1;
|
||||
pParse->nMem += nBase;
|
||||
}
|
||||
assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
|
||||
iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
|
||||
pSort->labelDone = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, SQLITE_ECEL_DUP);
|
||||
if( bSeq ){
|
||||
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
|
||||
@@ -517,7 +523,6 @@ static void pushOntoSorter(
|
||||
if( nPrefixReg==0 ){
|
||||
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
|
||||
}
|
||||
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
|
||||
if( nOBSat>0 ){
|
||||
int regPrevKey; /* The first nOBSat columns of the previous row */
|
||||
@@ -552,6 +557,10 @@ static void pushOntoSorter(
|
||||
pSort->regReturn = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
|
||||
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
|
||||
if( iLimit ){
|
||||
sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, addrFirst);
|
||||
sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat);
|
||||
sqlite3VdbeJumpHere(v, addrJmp);
|
||||
@@ -562,17 +571,32 @@ static void pushOntoSorter(
|
||||
op = OP_IdxInsert;
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
|
||||
if( pSelect->iLimit ){
|
||||
if( iLimit ){
|
||||
int addr;
|
||||
int iLimit;
|
||||
if( pSelect->iOffset ){
|
||||
iLimit = pSelect->iOffset+1;
|
||||
}else{
|
||||
iLimit = pSelect->iLimit;
|
||||
}
|
||||
int r1 = 0;
|
||||
/* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit
|
||||
** register is initialized with value of LIMIT+OFFSET.) After the sorter
|
||||
** fills up, delete the least entry in the sorter after each insert.
|
||||
** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */
|
||||
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
|
||||
if( pSort->bOrderedInnerLoop ){
|
||||
r1 = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1);
|
||||
VdbeComment((v, "seq"));
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
|
||||
if( pSort->bOrderedInnerLoop ){
|
||||
/* If the inner loop is driven by an index such that values from
|
||||
** the same iteration of the inner loop are in sorted order, then
|
||||
** immediately jump to the next iteration of an inner loop if the
|
||||
** entry from the current iteration does not fit into the top
|
||||
** LIMIT+OFFSET entries of the sorter. */
|
||||
int iBrk = sqlite3VdbeCurrentAddr(v) + 2;
|
||||
sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
}
|
||||
@@ -1168,7 +1192,7 @@ static void generateSortTail(
|
||||
SelectDest *pDest /* Write the sorted results here */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe; /* The prepared statement */
|
||||
int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */
|
||||
int addrBreak = pSort->labelDone; /* Jump here to exit loop */
|
||||
int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
|
||||
int addr;
|
||||
int addrOnce = 0;
|
||||
@@ -1187,6 +1211,7 @@ static void generateSortTail(
|
||||
struct ExprList_item *aOutEx = p->pEList->a;
|
||||
#endif
|
||||
|
||||
assert( addrBreak<0 );
|
||||
if( pSort->labelBkOut ){
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak);
|
||||
@@ -2856,10 +2881,11 @@ static int multiSelectOrderBy(
|
||||
** to the right and the left are evaluated, they use the correct
|
||||
** collation.
|
||||
*/
|
||||
aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy);
|
||||
aPermute = sqlite3DbMallocRaw(db, sizeof(int)*(nOrderBy + 1));
|
||||
if( aPermute ){
|
||||
struct ExprList_item *pItem;
|
||||
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
|
||||
aPermute[0] = nOrderBy;
|
||||
for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
|
||||
assert( pItem->u.x.iOrderByCol>0
|
||||
&& pItem->u.x.iOrderByCol<=p->pEList->nExpr );
|
||||
aPermute[i] = pItem->u.x.iOrderByCol - 1;
|
||||
@@ -3723,6 +3749,83 @@ static int flattenSubquery(
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||
|
||||
|
||||
|
||||
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||
/*
|
||||
** Make copies of relevant WHERE clause terms of the outer query into
|
||||
** the WHERE clause of subquery. Example:
|
||||
**
|
||||
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10;
|
||||
**
|
||||
** Transformed into:
|
||||
**
|
||||
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
|
||||
** WHERE x=5 AND y=10;
|
||||
**
|
||||
** The hope is that the terms added to the inner query will make it more
|
||||
** efficient.
|
||||
**
|
||||
** Do not attempt this optimization if:
|
||||
**
|
||||
** (1) The inner query is an aggregate. (In that case, we'd really want
|
||||
** to copy the outer WHERE-clause terms onto the HAVING clause of the
|
||||
** inner query. But they probably won't help there so do not bother.)
|
||||
**
|
||||
** (2) The inner query is the recursive part of a common table expression.
|
||||
**
|
||||
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
|
||||
** close would change the meaning of the LIMIT).
|
||||
**
|
||||
** (4) The inner query is the right operand of a LEFT JOIN. (The caller
|
||||
** enforces this restriction since this routine does not have enough
|
||||
** information to know.)
|
||||
**
|
||||
** (5) The WHERE clause expression originates in the ON or USING clause
|
||||
** of a LEFT JOIN.
|
||||
**
|
||||
** Return 0 if no changes are made and non-zero if one or more WHERE clause
|
||||
** terms are duplicated into the subquery.
|
||||
*/
|
||||
static int pushDownWhereTerms(
|
||||
sqlite3 *db, /* The database connection (for malloc()) */
|
||||
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
|
||||
Expr *pWhere, /* The WHERE clause of the outer query */
|
||||
int iCursor /* Cursor number of the subquery */
|
||||
){
|
||||
Expr *pNew;
|
||||
int nChng = 0;
|
||||
Select *pX; /* For looping over compound SELECTs in pSubq */
|
||||
if( pWhere==0 ) return 0;
|
||||
for(pX=pSubq; pX; pX=pX->pPrior){
|
||||
if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
|
||||
testcase( pX->selFlags & SF_Aggregate );
|
||||
testcase( pX->selFlags & SF_Recursive );
|
||||
testcase( pX!=pSubq );
|
||||
return 0; /* restrictions (1) and (2) */
|
||||
}
|
||||
}
|
||||
if( pSubq->pLimit!=0 ){
|
||||
return 0; /* restriction (3) */
|
||||
}
|
||||
while( pWhere->op==TK_AND ){
|
||||
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
|
||||
pWhere = pWhere->pLeft;
|
||||
}
|
||||
if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */
|
||||
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
|
||||
nChng++;
|
||||
while( pSubq ){
|
||||
pNew = sqlite3ExprDup(db, pWhere, 0);
|
||||
pNew = substExpr(db, pNew, iCursor, pSubq->pEList);
|
||||
pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew);
|
||||
pSubq = pSubq->pPrior;
|
||||
}
|
||||
}
|
||||
return nChng;
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||
|
||||
/*
|
||||
** Based on the contents of the AggInfo structure indicated by the first
|
||||
** argument, this function checks if the following are true:
|
||||
@@ -3884,6 +3987,8 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
|
||||
p->pPrior = 0;
|
||||
p->pNext = 0;
|
||||
p->selFlags &= ~SF_Compound;
|
||||
assert( (p->selFlags & SF_Converted)==0 );
|
||||
p->selFlags |= SF_Converted;
|
||||
assert( pNew->pPrior!=0 );
|
||||
pNew->pPrior->pNext = pNew;
|
||||
pNew->pLimit = 0;
|
||||
@@ -4035,7 +4140,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
|
||||
);
|
||||
@@ -4683,6 +4788,94 @@ static void explainSimpleCount(
|
||||
# define explainSimpleCount(a,b,c)
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
|
||||
/*
|
||||
** Attempt to transform a query of the form
|
||||
**
|
||||
** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2)
|
||||
**
|
||||
** Into this:
|
||||
**
|
||||
** SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2)
|
||||
**
|
||||
** The transformation only works if all of the following are true:
|
||||
**
|
||||
** * The subquery is a UNION ALL of two or more terms
|
||||
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
|
||||
** * The outer query is a simple count(*)
|
||||
**
|
||||
** Return TRUE if the optimization is undertaken.
|
||||
*/
|
||||
static int countOfViewOptimization(Parse *pParse, Select *p){
|
||||
Select *pSub, *pPrior;
|
||||
Expr *pExpr;
|
||||
Expr *pCount;
|
||||
sqlite3 *db;
|
||||
if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate query */
|
||||
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
|
||||
pExpr = p->pEList->a[0].pExpr;
|
||||
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
|
||||
if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Must be count() */
|
||||
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
|
||||
if( p->pSrc->nSrc!=1 ) return 0; /* One table in the FROM clause */
|
||||
pSub = p->pSrc->a[0].pSelect;
|
||||
if( pSub==0 ) return 0; /* The FROM is a subquery */
|
||||
if( pSub->pPrior==0 ) return 0; /* Must be a compound subquery */
|
||||
do{
|
||||
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
|
||||
if( pSub->pWhere ) return 0; /* No WHERE clause */
|
||||
if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
|
||||
pSub = pSub->pPrior; /* Repeat over compound terms */
|
||||
}while( pSub );
|
||||
|
||||
/* If we reach this point, that means it is OK to perform the transformation */
|
||||
|
||||
db = pParse->db;
|
||||
pCount = pExpr;
|
||||
pExpr = 0;
|
||||
pSub = p->pSrc->a[0].pSelect;
|
||||
p->pSrc->a[0].pSelect = 0;
|
||||
sqlite3SrcListDelete(db, p->pSrc);
|
||||
p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
|
||||
while( pSub ){
|
||||
Expr *pTerm;
|
||||
pPrior = pSub->pPrior;
|
||||
pSub->pPrior = 0;
|
||||
pSub->pNext = 0;
|
||||
pSub->selFlags |= SF_Aggregate;
|
||||
pSub->selFlags &= ~SF_Compound;
|
||||
pSub->nSelectRow = 0;
|
||||
sqlite3ExprListDelete(db, pSub->pEList);
|
||||
pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount;
|
||||
pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm);
|
||||
pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
|
||||
if( pTerm ){
|
||||
pTerm->x.pSelect = pSub;
|
||||
ExprSetProperty(pTerm, EP_xIsSelect|EP_Subquery);
|
||||
sqlite3ExprSetHeightAndFlags(pParse, pTerm);
|
||||
if( pExpr==0 ){
|
||||
pExpr = pTerm;
|
||||
}else{
|
||||
pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr, 0);
|
||||
}
|
||||
}else{
|
||||
sqlite3SelectDelete(db, pSub);
|
||||
}
|
||||
pSub = pPrior;
|
||||
}
|
||||
p->pEList->a[0].pExpr = pExpr;
|
||||
p->selFlags &= ~SF_Aggregate;
|
||||
|
||||
#if SELECTTRACE_ENABLED
|
||||
if( sqlite3SelectTrace & 0x400 ){
|
||||
SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */
|
||||
|
||||
/*
|
||||
** Generate code for the SELECT statement given in the p argument.
|
||||
**
|
||||
@@ -4824,59 +5017,71 @@ int sqlite3Select(
|
||||
p->selFlags |= SF_Aggregate;
|
||||
}
|
||||
i = -1;
|
||||
}else if( pTabList->nSrc==1
|
||||
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
|
||||
){
|
||||
/* Implement a co-routine that will return a single row of the result
|
||||
** set on each invocation.
|
||||
*/
|
||||
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
|
||||
VdbeComment((v, "%s", pItem->pTab->zName));
|
||||
pItem->addrFillSub = addrTop;
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
pItem->viaCoroutine = 1;
|
||||
pItem->regResult = dest.iSdst;
|
||||
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
|
||||
sqlite3VdbeJumpHere(v, addrTop-1);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
}else{
|
||||
/* Generate a subroutine that will fill an ephemeral table with
|
||||
** the content of this subquery. pItem->addrFillSub will point
|
||||
** to the address of the generated subroutine. pItem->regReturn
|
||||
** is a register allocated to hold the subroutine return address
|
||||
*/
|
||||
int topAddr;
|
||||
int onceAddr = 0;
|
||||
int retAddr;
|
||||
assert( pItem->addrFillSub==0 );
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
|
||||
pItem->addrFillSub = topAddr+1;
|
||||
if( pItem->isCorrelated==0 ){
|
||||
/* If the subquery is not correlated and if we are not inside of
|
||||
** a trigger, then we only need to compute the value of the subquery
|
||||
** once. */
|
||||
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}else{
|
||||
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
if( (pItem->jointype & JT_OUTER)==0
|
||||
&& pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
|
||||
){
|
||||
#if SELECTTRACE_ENABLED
|
||||
if( sqlite3SelectTrace & 0x100 ){
|
||||
sqlite3DebugPrintf("After WHERE-clause push-down:\n");
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if( pTabList->nSrc==1
|
||||
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
|
||||
){
|
||||
/* Implement a co-routine that will return a single row of the result
|
||||
** set on each invocation.
|
||||
*/
|
||||
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
|
||||
VdbeComment((v, "%s", pItem->pTab->zName));
|
||||
pItem->addrFillSub = addrTop;
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
pItem->viaCoroutine = 1;
|
||||
pItem->regResult = dest.iSdst;
|
||||
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
|
||||
sqlite3VdbeJumpHere(v, addrTop-1);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
}else{
|
||||
/* Generate a subroutine that will fill an ephemeral table with
|
||||
** the content of this subquery. pItem->addrFillSub will point
|
||||
** to the address of the generated subroutine. pItem->regReturn
|
||||
** is a register allocated to hold the subroutine return address
|
||||
*/
|
||||
int topAddr;
|
||||
int onceAddr = 0;
|
||||
int retAddr;
|
||||
assert( pItem->addrFillSub==0 );
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
|
||||
pItem->addrFillSub = topAddr+1;
|
||||
if( pItem->isCorrelated==0 ){
|
||||
/* If the subquery is not correlated and if we are not inside of
|
||||
** a trigger, then we only need to compute the value of the subquery
|
||||
** once. */
|
||||
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}else{
|
||||
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
|
||||
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
|
||||
VdbeComment((v, "end %s", pItem->pTab->zName));
|
||||
sqlite3VdbeChangeP1(v, topAddr, retAddr);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
}
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
|
||||
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
|
||||
VdbeComment((v, "end %s", pItem->pTab->zName));
|
||||
sqlite3VdbeChangeP1(v, topAddr, retAddr);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
}
|
||||
if( /*pParse->nErr ||*/ db->mallocFailed ){
|
||||
if( db->mallocFailed ){
|
||||
goto select_end;
|
||||
}
|
||||
pParse->nHeight -= sqlite3SelectExprHeight(p);
|
||||
@@ -4906,6 +5111,16 @@ int sqlite3Select(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
|
||||
if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
|
||||
&& countOfViewOptimization(pParse, p)
|
||||
){
|
||||
if( db->mallocFailed ) goto select_end;
|
||||
pEList = p->pEList;
|
||||
pTabList = p->pSrc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
|
||||
** if the select-list is the same as the ORDER BY list, then this query
|
||||
** can be rewritten as a GROUP BY. In other words, this:
|
||||
@@ -4999,6 +5214,7 @@ int sqlite3Select(
|
||||
}
|
||||
if( sSort.pOrderBy ){
|
||||
sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
|
||||
sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo);
|
||||
if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
|
||||
sSort.pOrderBy = 0;
|
||||
}
|
||||
|
||||
+12
-12
@@ -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
|
||||
|
||||
@@ -370,7 +370,7 @@ static FILE *iotrace = 0;
|
||||
** is written to iotrace.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
static void iotracePrintf(const char *zFormat, ...){
|
||||
static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
char *z;
|
||||
if( iotrace==0 ) return;
|
||||
@@ -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");
|
||||
@@ -3144,7 +3144,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
|
||||
extern void (*sqlite3IoTrace)(const char*, ...);
|
||||
SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
|
||||
if( iotrace && iotrace!=stdout ) fclose(iotrace);
|
||||
iotrace = 0;
|
||||
if( nArg<2 ){
|
||||
@@ -3803,9 +3803,9 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
azArg[2],
|
||||
integerValue(azArg[3]),
|
||||
integerValue(azArg[4]));
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
}else{
|
||||
fprintf(stderr,"Usage: .testctrl initmode dbName onoff tnum\n");
|
||||
rc = 1;
|
||||
fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+33
-19
@@ -43,11 +43,20 @@ extern "C" {
|
||||
|
||||
|
||||
/*
|
||||
** Add the ability to override 'extern'
|
||||
** Provide the ability to override linkage features of the interface.
|
||||
*/
|
||||
#ifndef SQLITE_EXTERN
|
||||
# define SQLITE_EXTERN extern
|
||||
#endif
|
||||
#ifndef SQLITE_API
|
||||
# define SQLITE_API
|
||||
#endif
|
||||
#ifndef SQLITE_CDECL
|
||||
# define SQLITE_CDECL
|
||||
#endif
|
||||
#ifndef SQLITE_STDCALL
|
||||
# define SQLITE_STDCALL
|
||||
#endif
|
||||
|
||||
/*
|
||||
** These no-op macros are used in front of interfaces to mark those
|
||||
@@ -946,9 +955,9 @@ struct sqlite3_io_methods {
|
||||
** and only needs to be supported when SQLITE_TEST is defined.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_WAL_BLOCK]]
|
||||
** The [SQLITE_FCNTL_WAL_BLOCK] is a single to the VFS layer that it might
|
||||
** 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 ioctl() during some rare
|
||||
** 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.
|
||||
**
|
||||
@@ -1543,7 +1552,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
|
||||
@@ -3000,11 +3009,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.
|
||||
@@ -5618,7 +5629,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 */
|
||||
};
|
||||
@@ -6296,7 +6307,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
|
||||
@@ -6310,19 +6321,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
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
+30
-5
@@ -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 */
|
||||
@@ -1230,6 +1245,7 @@ struct sqlite3 {
|
||||
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
|
||||
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
|
||||
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
|
||||
#define SQLITE_CountOfView 0x1000 /* The count-of-view optimization */
|
||||
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
||||
|
||||
/*
|
||||
@@ -2261,6 +2277,7 @@ struct SrcList {
|
||||
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
||||
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
|
||||
#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
|
||||
#define WHERE_ORDERBY_LIMIT 0x2000 /* ORDERBY+LIMIT on the inner loop */
|
||||
|
||||
/* Allowed return values from sqlite3WhereIsDistinct()
|
||||
*/
|
||||
@@ -2374,6 +2391,7 @@ struct Select {
|
||||
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
|
||||
#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */
|
||||
#define SF_Converted 0x2000 /* By convertCompoundSelectToSubquery() */
|
||||
|
||||
|
||||
/*
|
||||
@@ -2692,7 +2710,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 +3115,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
|
||||
@@ -3267,6 +3291,7 @@ void sqlite3WhereEnd(WhereInfo*);
|
||||
u64 sqlite3WhereOutputRowCount(WhereInfo*);
|
||||
int sqlite3WhereIsDistinct(WhereInfo*);
|
||||
int sqlite3WhereIsOrdered(WhereInfo*);
|
||||
int sqlite3WhereOrderedInnerLoop(WhereInfo*);
|
||||
int sqlite3WhereIsSorted(WhereInfo*);
|
||||
int sqlite3WhereContinueLabel(WhereInfo*);
|
||||
int sqlite3WhereBreakLabel(WhereInfo*);
|
||||
@@ -3479,7 +3504,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 *);
|
||||
@@ -3782,7 +3807,7 @@ void sqlite3Put4byte(u8*, u32);
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
|
||||
void sqlite3VdbeIOTraceSql(Vdbe*);
|
||||
SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
|
||||
SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
|
||||
#else
|
||||
# define IOTRACE(A)
|
||||
# define sqlite3VdbeIOTraceSql(X)
|
||||
|
||||
+81
-13
@@ -21,10 +21,32 @@
|
||||
*/
|
||||
typedef struct sqlite3StatType sqlite3StatType;
|
||||
static SQLITE_WSD struct sqlite3StatType {
|
||||
int nowValue[10]; /* Current value */
|
||||
int mxValue[10]; /* Maximum value */
|
||||
#if SQLITE_PTRSIZE>4
|
||||
sqlite3_int64 nowValue[10]; /* Current value */
|
||||
sqlite3_int64 mxValue[10]; /* Maximum value */
|
||||
#else
|
||||
u32 nowValue[10]; /* Current value */
|
||||
u32 mxValue[10]; /* Maximum value */
|
||||
#endif
|
||||
} sqlite3Stat = { {0,}, {0,} };
|
||||
|
||||
/*
|
||||
** Elements of sqlite3Stat[] are protected by either the memory allocator
|
||||
** mutex, or by the pcache1 mutex. The following array determines which.
|
||||
*/
|
||||
static const char statMutex[] = {
|
||||
0, /* SQLITE_STATUS_MEMORY_USED */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_USED */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */
|
||||
0, /* SQLITE_STATUS_SCRATCH_USED */
|
||||
0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */
|
||||
0, /* SQLITE_STATUS_MALLOC_SIZE */
|
||||
0, /* SQLITE_STATUS_PARSER_STACK */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_SIZE */
|
||||
0, /* SQLITE_STATUS_SCRATCH_SIZE */
|
||||
0, /* SQLITE_STATUS_MALLOC_COUNT */
|
||||
};
|
||||
|
||||
|
||||
/* The "wsdStat" macro will resolve to the status information
|
||||
** state vector. If writable static data is unsupported on the target,
|
||||
@@ -41,33 +63,60 @@ static SQLITE_WSD struct sqlite3StatType {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the current value of a status parameter.
|
||||
** Return the current value of a status parameter. The caller must
|
||||
** be holding the appropriate mutex.
|
||||
*/
|
||||
int sqlite3StatusValue(int op){
|
||||
sqlite3_int64 sqlite3StatusValue(int op){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
return wsdStat.nowValue[op];
|
||||
}
|
||||
|
||||
/*
|
||||
** Add N to the value of a status record. It is assumed that the
|
||||
** caller holds appropriate locks.
|
||||
** Add N to the value of a status record. The caller must hold the
|
||||
** appropriate mutex. (Locking is checked by assert()).
|
||||
**
|
||||
** The StatusUp() routine can accept positive or negative values for N.
|
||||
** The value of N is added to the current status value and the high-water
|
||||
** mark is adjusted if necessary.
|
||||
**
|
||||
** The StatusDown() routine lowers the current value by N. The highwater
|
||||
** mark is unchanged. N must be non-negative for StatusDown().
|
||||
*/
|
||||
void sqlite3StatusAdd(int op, int N){
|
||||
void sqlite3StatusUp(int op, int N){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
wsdStat.nowValue[op] += N;
|
||||
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
}
|
||||
}
|
||||
void sqlite3StatusDown(int op, int N){
|
||||
wsdStatInit;
|
||||
assert( N>=0 );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
wsdStat.nowValue[op] -= N;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the value of a status to X.
|
||||
** Set the value of a status to X. The highwater mark is adjusted if
|
||||
** necessary. The caller must hold the appropriate mutex.
|
||||
*/
|
||||
void sqlite3StatusSet(int op, int X){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
wsdStat.nowValue[op] = X;
|
||||
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
@@ -76,12 +125,14 @@ void sqlite3StatusSet(int op, int X){
|
||||
|
||||
/*
|
||||
** Query status information.
|
||||
**
|
||||
** This implementation assumes that reading or writing an aligned
|
||||
** 32-bit integer is an atomic operation. If that assumption is not true,
|
||||
** then this routine is not threadsafe.
|
||||
*/
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
int sqlite3_status64(
|
||||
int op,
|
||||
sqlite3_int64 *pCurrent,
|
||||
sqlite3_int64 *pHighwater,
|
||||
int resetFlag
|
||||
){
|
||||
sqlite3_mutex *pMutex;
|
||||
wsdStatInit;
|
||||
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
@@ -89,13 +140,30 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex();
|
||||
sqlite3_mutex_enter(pMutex);
|
||||
*pCurrent = wsdStat.nowValue[op];
|
||||
*pHighwater = wsdStat.mxValue[op];
|
||||
if( resetFlag ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
}
|
||||
sqlite3_mutex_leave(pMutex);
|
||||
(void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
sqlite3_int64 iCur, iHwtr;
|
||||
int rc;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
|
||||
if( rc==0 ){
|
||||
*pCurrent = (int)iCur;
|
||||
*pHighwater = (int)iHwtr;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Query status information for a single database connection
|
||||
|
||||
+26
-11
@@ -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;
|
||||
|
||||
+16
-1
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+99
-56
@@ -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 );
|
||||
@@ -1920,11 +1920,15 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
testcase( pIn1->flags & MEM_Int );
|
||||
testcase( pIn1->flags & MEM_Real );
|
||||
sqlite3VdbeMemStringify(pIn1, encoding, 1);
|
||||
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
|
||||
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
|
||||
}
|
||||
if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){
|
||||
testcase( pIn3->flags & MEM_Int );
|
||||
testcase( pIn3->flags & MEM_Real );
|
||||
sqlite3VdbeMemStringify(pIn3, encoding, 1);
|
||||
testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
|
||||
flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
|
||||
}
|
||||
}
|
||||
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
|
||||
@@ -1961,7 +1965,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
}
|
||||
}
|
||||
/* Undo any changes made by applyAffinity() to the input registers. */
|
||||
assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
|
||||
pIn1->flags = flags1;
|
||||
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
|
||||
pIn3->flags = flags3;
|
||||
break;
|
||||
}
|
||||
@@ -1974,11 +1980,14 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
** The permutation is only valid until the next OP_Compare that has
|
||||
** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
|
||||
** occur immediately prior to the OP_Compare.
|
||||
**
|
||||
** The first integer in the P4 integer array is the length of the array
|
||||
** and does not become part of the permutation.
|
||||
*/
|
||||
case OP_Permutation: {
|
||||
assert( pOp->p4type==P4_INTARRAY );
|
||||
assert( pOp->p4.ai );
|
||||
aPermute = pOp->p4.ai;
|
||||
aPermute = pOp->p4.ai + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2284,12 +2293,16 @@ case OP_Column: {
|
||||
u16 fx; /* pDest->flags value */
|
||||
Mem *pReg; /* PseudoTable input register */
|
||||
|
||||
pC = p->apCsr[pOp->p1];
|
||||
p2 = pOp->p2;
|
||||
|
||||
/* If the cursor cache is stale, bring it up-to-date */
|
||||
rc = sqlite3VdbeCursorMoveto(&pC, &p2);
|
||||
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
pDest = &aMem[pOp->p3];
|
||||
memAboutToChange(p, pDest);
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( p2<pC->nField );
|
||||
aOffset = pC->aOffset;
|
||||
@@ -2300,8 +2313,6 @@ case OP_Column: {
|
||||
assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */
|
||||
assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */
|
||||
|
||||
/* If the cursor cache is stale, bring it up-to-date */
|
||||
rc = sqlite3VdbeCursorMoveto(pC);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
if( pC->cacheStatus!=p->cacheCtr ){
|
||||
if( pC->nullRow ){
|
||||
@@ -3235,20 +3246,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 +3255,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 +3331,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 +3602,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
|
||||
@@ -3702,7 +3730,7 @@ case OP_SeekGT: { /* jump, in3 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Seek P1 P2 * * *
|
||||
/* Opcode: Seek P1 P2 P3 P4 *
|
||||
** Synopsis: intkey=r[P2]
|
||||
**
|
||||
** P1 is an open table cursor and P2 is a rowid integer. Arrange
|
||||
@@ -3711,6 +3739,13 @@ case OP_SeekGT: { /* jump, in3 */
|
||||
** This is actually a deferred seek. Nothing actually happens until
|
||||
** the cursor is used to read a record. That way, if no reads
|
||||
** occur, no unnecessary I/O happens.
|
||||
**
|
||||
** P4 may contain an array of integers (type P4_INTARRAY) containing
|
||||
** one entry for each column in the table P1 is open on. If so, then
|
||||
** parameter P3 is a cursor open on a database index. If array entry
|
||||
** a[i] is non-zero, then reading column (a[i]-1) from cursor P3 is
|
||||
** equivalent to performing the deferred seek and then reading column i
|
||||
** from P1.
|
||||
*/
|
||||
case OP_Seek: { /* in2 */
|
||||
VdbeCursor *pC;
|
||||
@@ -3724,6 +3759,9 @@ case OP_Seek: { /* in2 */
|
||||
pIn2 = &aMem[pOp->p2];
|
||||
pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
|
||||
pC->deferredMoveto = 1;
|
||||
assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
|
||||
pC->aAltMap = pOp->p4.ai;
|
||||
pC->pAltCursor = p->apCsr[pOp->p3];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4929,30 +4967,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 +6032,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 +6066,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 +6084,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 +6105,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 +6171,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 +6261,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 +6336,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 +6348,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) ){
|
||||
|
||||
+7
-11
@@ -60,6 +60,7 @@ typedef struct AuxData AuxData;
|
||||
** Every cursor that the virtual machine has open is represented by an
|
||||
** instance of the following structure.
|
||||
*/
|
||||
typedef struct VdbeCursor VdbeCursor;
|
||||
struct VdbeCursor {
|
||||
BtCursor *pCursor; /* The cursor structure of the backend */
|
||||
Btree *pBt; /* Separate file holding temporary table */
|
||||
@@ -83,6 +84,11 @@ struct VdbeCursor {
|
||||
i64 seqCount; /* Sequence counter */
|
||||
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
||||
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
|
||||
VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
|
||||
int *aAltMap; /* Mapping from table to index column numbers */
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
u64 maskUsed; /* Mask of columns used by this cursor */
|
||||
#endif
|
||||
|
||||
/* Cached information about the header for the data record that the
|
||||
** cursor is currently pointing to. Only valid if cacheStatus matches
|
||||
@@ -104,7 +110,6 @@ struct VdbeCursor {
|
||||
** static element declared in the structure. nField total array slots for
|
||||
** aType[] and nField+1 array slots for aOffset[] */
|
||||
};
|
||||
typedef struct VdbeCursor VdbeCursor;
|
||||
|
||||
/*
|
||||
** When a sub-program is executed (OP_Program), a structure of this type
|
||||
@@ -313,14 +318,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 +348,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 */
|
||||
@@ -402,7 +398,7 @@ struct Vdbe {
|
||||
*/
|
||||
void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
|
||||
void sqliteVdbePopStack(Vdbe*,int);
|
||||
int sqlite3VdbeCursorMoveto(VdbeCursor*);
|
||||
int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
|
||||
int sqlite3VdbeCursorRestore(VdbeCursor*);
|
||||
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||
void sqlite3VdbePrintOp(FILE*, int, Op*);
|
||||
|
||||
+27
-7
@@ -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;
|
||||
|
||||
+27
-6
@@ -1118,12 +1118,26 @@ 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
|
||||
case P4_INTARRAY: {
|
||||
sqlite3_snprintf(nTemp, zTemp, "intarray");
|
||||
int i, j;
|
||||
int *ai = pOp->p4.ai;
|
||||
int n = ai[0]; /* The first element of an INTARRAY is always the
|
||||
** count of the number of elements to follow */
|
||||
zTemp[0] = '[';
|
||||
for(i=j=1; i<n && j<nTemp-7; i++){
|
||||
if( j>1 ) zTemp[j++] = ',';
|
||||
sqlite3_snprintf(nTemp-j, zTemp+j, "%d", ai[i]);
|
||||
j += sqlite3Strlen30(zTemp+j);
|
||||
}
|
||||
if( i<n ){
|
||||
memcpy(zTemp+j, ",...]", 6);
|
||||
}else{
|
||||
memcpy(zTemp+j, "]", 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case P4_SUBPROGRAM: {
|
||||
@@ -1782,9 +1796,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 +2157,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 ){
|
||||
@@ -2818,8 +2832,15 @@ int sqlite3VdbeCursorRestore(VdbeCursor *p){
|
||||
** If the cursor is already pointing to the correct row and that row has
|
||||
** not been deleted out from under the cursor, then this routine is a no-op.
|
||||
*/
|
||||
int sqlite3VdbeCursorMoveto(VdbeCursor *p){
|
||||
int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
|
||||
VdbeCursor *p = *pp;
|
||||
if( p->deferredMoveto ){
|
||||
int iMap;
|
||||
if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
|
||||
*pp = p->pAltCursor;
|
||||
*piCol = iMap - 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
return handleDeferredMoveto(p);
|
||||
}
|
||||
if( p->pCursor && sqlite3BtreeCursorHasMoved(p->pCursor) ){
|
||||
|
||||
+120
-1
@@ -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;
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
+13
-6
@@ -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 );
|
||||
|
||||
+371
-69
@@ -42,6 +42,18 @@ int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
|
||||
return pWInfo->nOBSat;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the innermost loop of the WHERE clause implementation
|
||||
** returns rows in ORDER BY order for complete run of the inner loop.
|
||||
**
|
||||
** Across multiple iterations of outer loops, the output rows need not be
|
||||
** sorted. As long as rows are sorted for just the innermost loop, this
|
||||
** routine can return TRUE.
|
||||
*/
|
||||
int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){
|
||||
return pWInfo->bOrderedInnerLoop;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the VDBE address or label to jump to in order to continue
|
||||
** immediately with the next row of a WHERE clause.
|
||||
@@ -770,6 +782,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
|
||||
@@ -794,6 +879,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:
|
||||
**
|
||||
@@ -810,6 +896,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
|
||||
@@ -936,12 +1032,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
|
||||
@@ -1071,7 +1181,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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1266,7 +1376,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;
|
||||
@@ -1302,11 +1412,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);
|
||||
@@ -1314,7 +1423,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);
|
||||
@@ -1931,11 +2040,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 */
|
||||
@@ -1946,67 +2058,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{
|
||||
@@ -2018,7 +2221,11 @@ static int whereKeyStats(
|
||||
iGap = iGap/3;
|
||||
}
|
||||
aStat[0] = iLower + iGap;
|
||||
aStat[1] = pIdx->aAvgEq[nField-1];
|
||||
}
|
||||
|
||||
/* Restore the pRec->nField value before returning. */
|
||||
pRec->nField = nField;
|
||||
return i;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
||||
@@ -3041,6 +3248,55 @@ static void whereLikeOptimizationStringFixup(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains
|
||||
** a rowid value just read from cursor iIdxCur, open on index pIdx. This
|
||||
** function generates code to do a deferred seek of cursor iCur to the
|
||||
** rowid stored in register iRowid.
|
||||
**
|
||||
** Normally, this is just:
|
||||
**
|
||||
** OP_Seek $iCur $iRowid
|
||||
**
|
||||
** However, if the scan currently being coded is a branch of an OR-loop and
|
||||
** the statement currently being coded is a SELECT, then P3 of the OP_Seek
|
||||
** is set to iIdxCur and P4 is set to point to an array of integers
|
||||
** containing one entry for each column of the table cursor iCur is open
|
||||
** on. For each table column, if the column is the i'th column of the
|
||||
** index, then the corresponding array entry is set to (i+1). If the column
|
||||
** does not appear in the index at all, the array entry is set to 0.
|
||||
*/
|
||||
static void codeDeferredSeek(
|
||||
WhereInfo *pWInfo, /* Where clause context */
|
||||
Index *pIdx, /* Index scan is using */
|
||||
int iCur, /* Cursor for IPK b-tree */
|
||||
int iRowid, /* Register containing rowid to seek to */
|
||||
int iIdxCur /* Index cursor */
|
||||
){
|
||||
Parse *pParse = pWInfo->pParse; /* Parse context */
|
||||
Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */
|
||||
|
||||
assert( iIdxCur>0 );
|
||||
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
|
||||
|
||||
sqlite3VdbeAddOp3(v, OP_Seek, iCur, iRowid, iIdxCur);
|
||||
if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)
|
||||
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
|
||||
){
|
||||
int i;
|
||||
Table *pTab = pIdx->pTable;
|
||||
int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1));
|
||||
if( ai ){
|
||||
ai[0] = pTab->nCol;
|
||||
for(i=0; i<pIdx->nColumn-1; i++){
|
||||
assert( pIdx->aiColumn[i]<pTab->nCol );
|
||||
if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1;
|
||||
}
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
||||
** implementation described by pWInfo.
|
||||
@@ -3519,7 +3775,7 @@ static Bitmask codeOneLoopStart(
|
||||
iRowidReg = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
|
||||
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
|
||||
sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
|
||||
codeDeferredSeek(pWInfo, pIdx, iCur, iRowidReg, iIdxCur);
|
||||
}else if( iCur!=iIdxCur ){
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
|
||||
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
||||
@@ -5407,7 +5663,7 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
WhereInfo *pWInfo, /* The WHERE clause */
|
||||
ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */
|
||||
WherePath *pPath, /* The WherePath to check */
|
||||
u16 wctrlFlags, /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */
|
||||
u16 wctrlFlags, /* WHERE_GROUPBY, _DISTINCTBY or _ORDERBY_LIMIT */
|
||||
u16 nLoop, /* Number of entries in pPath->aLoop[] */
|
||||
WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */
|
||||
Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */
|
||||
@@ -5418,6 +5674,7 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */
|
||||
u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */
|
||||
u8 isMatch; /* iColumn matches a term of the ORDER BY clause */
|
||||
u16 eqOpMask; /* Allowed equality operators */
|
||||
u16 nKeyCol; /* Number of key columns in pIndex */
|
||||
u16 nColumn; /* Total number of ordered columns in the index */
|
||||
u16 nOrderBy; /* Number terms in the ORDER BY clause */
|
||||
@@ -5468,8 +5725,16 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
obDone = MASKBIT(nOrderBy)-1;
|
||||
orderDistinctMask = 0;
|
||||
ready = 0;
|
||||
eqOpMask = WO_EQ | WO_ISNULL;
|
||||
if( wctrlFlags & WHERE_ORDERBY_LIMIT ) eqOpMask |= WO_IN;
|
||||
for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
|
||||
if( iLoop>0 ) ready |= pLoop->maskSelf;
|
||||
if( iLoop<nLoop ){
|
||||
pLoop = pPath->aLoop[iLoop];
|
||||
if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue;
|
||||
}else{
|
||||
pLoop = pLast;
|
||||
}
|
||||
pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
|
||||
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
|
||||
if( pLoop->u.vtab.isOrdered ) obSat = obDone;
|
||||
@@ -5488,8 +5753,16 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
if( pOBExpr->op!=TK_COLUMN ) continue;
|
||||
if( pOBExpr->iTable!=iCur ) continue;
|
||||
pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
|
||||
~ready, WO_EQ|WO_ISNULL, 0);
|
||||
~ready, eqOpMask, 0);
|
||||
if( pTerm==0 ) continue;
|
||||
if( pTerm->eOperator==WO_IN ){
|
||||
/* IN terms are only valid for sorting in the ORDER BY LIMIT
|
||||
** optimization, and then only if they are actually used
|
||||
** by the query plan */
|
||||
assert( wctrlFlags & WHERE_ORDERBY_LIMIT );
|
||||
for(j=0; j<pLoop->nLTerm && pTerm!=pLoop->aLTerm[j]; j++){}
|
||||
if( j>=pLoop->nLTerm ) continue;
|
||||
}
|
||||
if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){
|
||||
const char *z1, *z2;
|
||||
pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
|
||||
@@ -5526,10 +5799,12 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
for(j=0; j<nColumn; j++){
|
||||
u8 bOnce; /* True to run the ORDER BY search loop */
|
||||
|
||||
/* Skip over == and IS NULL terms */
|
||||
/* Skip over == and IS NULL terms
|
||||
** (Also skip IN terms when doing WHERE_ORDERBY_LIMIT processing)
|
||||
*/
|
||||
if( j<pLoop->u.btree.nEq
|
||||
&& pLoop->nSkip==0
|
||||
&& ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0
|
||||
&& ((i = pLoop->aLTerm[j]->eOperator) & eqOpMask)!=0
|
||||
){
|
||||
if( i & WO_ISNULL ){
|
||||
testcase( isOrderDistinct );
|
||||
@@ -5805,10 +6080,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 ){
|
||||
@@ -5895,8 +6170,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
** this candidate as not viable. */
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
|
||||
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
|
||||
isOrdered>=0 ? isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
@@ -5914,26 +6189,36 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
pTo = &aTo[jj];
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
|
||||
sqlite3DebugPrintf("New %s cost=%-3d,%3d,%3d order=%c\n",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
|
||||
isOrdered>=0 ? isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
}else{
|
||||
/* Control reaches here if best-so-far path pTo=aTo[jj] covers the
|
||||
** same set of loops and has the sam isOrdered setting as the
|
||||
** same set of loops and has the same isOrdered setting as the
|
||||
** candidate path. Check to see if the candidate should replace
|
||||
** pTo or if the candidate should be skipped */
|
||||
if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
|
||||
** pTo or if the candidate should be skipped.
|
||||
**
|
||||
** The conditional is an expanded vector comparison equivalent to:
|
||||
** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted)
|
||||
*/
|
||||
if( pTo->rCost<rCost
|
||||
|| (pTo->rCost==rCost
|
||||
&& (pTo->nRow<nOut
|
||||
|| (pTo->nRow==nOut && pTo->rUnsorted<=rUnsorted)
|
||||
)
|
||||
)
|
||||
){
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf(
|
||||
"Skip %s cost=%-3d,%3d order=%c",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
|
||||
"Skip %s cost=%-3d,%3d,%3d order=%c",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
|
||||
isOrdered>=0 ? isOrdered+'0' : '?');
|
||||
sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
|
||||
sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n",
|
||||
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
|
||||
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
/* Discard the candidate path from further consideration */
|
||||
@@ -5946,12 +6231,12 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf(
|
||||
"Update %s cost=%-3d,%3d order=%c",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
|
||||
"Update %s cost=%-3d,%3d,%3d order=%c",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
|
||||
isOrdered>=0 ? isOrdered+'0' : '?');
|
||||
sqlite3DebugPrintf(" was %s cost=%-3d,%3d order=%c\n",
|
||||
sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n",
|
||||
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
|
||||
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -6042,8 +6327,19 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
}
|
||||
}else{
|
||||
pWInfo->nOBSat = pFrom->isOrdered;
|
||||
if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
|
||||
pWInfo->revMask = pFrom->revLoop;
|
||||
if( pWInfo->nOBSat<=0 ){
|
||||
pWInfo->nOBSat = 0;
|
||||
if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){
|
||||
Bitmask m = 0;
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
|
||||
WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
|
||||
if( rc==pWInfo->pOrderBy->nExpr ){
|
||||
pWInfo->bOrderedInnerLoop = 1;
|
||||
pWInfo->revMask = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
|
||||
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
|
||||
@@ -6606,6 +6902,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,6 +412,7 @@ struct WhereInfo {
|
||||
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
|
||||
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
|
||||
u8 nLevel; /* Number of nested loop */
|
||||
u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
|
||||
int iTop; /* The very beginning of the WHERE loop */
|
||||
int iContinue; /* Jump here to continue with next record */
|
||||
int iBreak; /* Jump here to break out of the loop */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -859,4 +859,16 @@ do_test attach-10.2 {
|
||||
}] 9 end
|
||||
} {4 noname {} 5 inmem {}}
|
||||
|
||||
# Attach with a very long URI filename.
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db -uri 1
|
||||
do_execsql_test attach-11.1 {
|
||||
ATTACH printf('file:%09000x/x.db?mode=memory&cache=shared',1) AS aux1;
|
||||
CREATE TABLE aux1.t1(x,y);
|
||||
INSERT INTO aux1.t1(x,y) VALUES(1,2),(3,4);
|
||||
SELECT * FROM aux1.t1;
|
||||
} {1 2 3 4}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# 2015-03-25
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# The focus of this script is making multiple calls to saveCursorPosition()
|
||||
# and restoreCursorPosition() when cursors have eState==CURSOR_SKIPNEXT
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
load_static_extension db eval
|
||||
do_execsql_test btree02-100 {
|
||||
CREATE TABLE t1(a TEXT, ax INTEGER, b INT, PRIMARY KEY(a,ax)) WITHOUT ROWID;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,ax,b) SELECT printf('%02x',i), random(), i FROM c;
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE TABLE t2(x,y);
|
||||
CREATE TABLE t3(cnt);
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<4)
|
||||
INSERT INTO t3(cnt) SELECT i FROM c;
|
||||
SELECT count(*) FROM t1;
|
||||
} {10}
|
||||
do_test btree02-110 {
|
||||
db eval BEGIN
|
||||
set i 0
|
||||
db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} {
|
||||
db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)}
|
||||
# puts "a,b,cnt = ($a,$b,$cnt)"
|
||||
incr i
|
||||
if {$i%2==1} {
|
||||
set bx [expr {$b+1000}]
|
||||
# puts "INSERT ($a),$bx"
|
||||
db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)}
|
||||
} else {
|
||||
# puts "DELETE a=$a"
|
||||
db eval {DELETE FROM t1 WHERE a=$a}
|
||||
}
|
||||
db eval {COMMIT; BEGIN}
|
||||
}
|
||||
db one {COMMIT; SELECT count(*) FROM t1;}
|
||||
} {20}
|
||||
|
||||
finish_test
|
||||
+56
-2
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# 2015-03-30
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Corruption consisting of a database page that thinks it is a child
|
||||
# of itself.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix corruptJ
|
||||
|
||||
if {[permutation]=="mmap"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Do not use a codec for tests in this file, as the database file is
|
||||
# manipulated directly using tcl scripts (using the [hexio_write] command).
|
||||
#
|
||||
do_not_use_codec
|
||||
database_may_be_corrupt
|
||||
|
||||
# Initialize the database.
|
||||
#
|
||||
do_execsql_test 1.1 {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=0;
|
||||
CREATE TABLE t1(a,b);
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,b) SELECT i, zeroblob(700) FROM c;
|
||||
} {}
|
||||
db close
|
||||
|
||||
# Corrupt the root page of the t1 table such that the left-child pointer
|
||||
# for the very first cell points back to the root. Then try to DROP the
|
||||
# table. The clearDatabasePage() routine should not loop.
|
||||
#
|
||||
do_test 1.2 {
|
||||
hexio_write test.db [expr {2*1024-2}] 02
|
||||
sqlite3 db test.db
|
||||
catchsql { DROP TABLE t1 }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
# Similar test using a WITHOUT ROWID table
|
||||
#
|
||||
do_test 2.1 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=0;
|
||||
CREATE TABLE t1(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<100)
|
||||
INSERT INTO t1(a,b) SELECT i, zeroblob(200) FROM c;
|
||||
}
|
||||
} {}
|
||||
|
||||
# The table is three levels deep. Corrupt the left child of an intermediate
|
||||
# page so that it points back to the root page.
|
||||
#
|
||||
do_test 2.2 {
|
||||
db close
|
||||
hexio_read test.db [expr {9*1024+391}] 8
|
||||
} {00000008814D0401}
|
||||
do_test 2.2b {
|
||||
hexio_write test.db [expr {9*1024+391}] 00000002
|
||||
sqlite3 db test.db
|
||||
catchsql { PRAGMA secure_delete=ON; DROP TABLE t1; }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
@@ -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
|
||||
@@ -15,6 +15,14 @@ source $testdir/tester.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
set testprefix e_walauto
|
||||
|
||||
# Do not run this test on OpenBSD, as it depends on read() and mmap both
|
||||
# accessing the same coherent view of the "test.db-shm" file. This doesn't
|
||||
# work on OpenBSD.
|
||||
#
|
||||
if {$tcl_platform(os) == "OpenBSD"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc read_nbackfill {} {
|
||||
seek $::shmfd 96
|
||||
|
||||
+23
-1
@@ -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
|
||||
|
||||
@@ -155,4 +155,23 @@ ifcapable fts3_unicode {
|
||||
}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_test 6.0 {
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(x,order=DESC);
|
||||
INSERT INTO t6(docid, x) VALUES(-1,'a b');
|
||||
INSERT INTO t6(docid, x) VALUES(1, 'b');
|
||||
}
|
||||
faultsim_save_and_close
|
||||
} {}
|
||||
|
||||
do_faultsim_test 6.1 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {SELECT * FROM sqlite_master}
|
||||
} -body {
|
||||
execsql { SELECT docid FROM t6 WHERE t6 MATCH '"a* b"' }
|
||||
} -test {
|
||||
faultsim_test_result {0 -1}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -209,5 +209,87 @@ 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}]
|
||||
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(x,order=DESC);
|
||||
INSERT INTO t6(docid, x) VALUES(-1,'a b');
|
||||
INSERT INTO t6(docid, x) VALUES(1, 'b');
|
||||
}
|
||||
do_execsql_test 7.1 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH '"a* b"';
|
||||
} {-1}
|
||||
do_execsql_test 7.2 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH 'a*';
|
||||
} {-1}
|
||||
do_execsql_test 7.3 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH 'a* b';
|
||||
} {-1}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+9
-5
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -161,4 +161,27 @@ do_execsql_test join5-3.3 {
|
||||
SELECT * FROM x1 LEFT JOIN x2 JOIN x3 WHERE x3.d = x2.b;
|
||||
} {}
|
||||
|
||||
# Ticket https://www.sqlite.org/src/tktview/c2a19d81652f40568c770c43 on
|
||||
# 2015-08-20. LEFT JOIN and the push-down optimization.
|
||||
#
|
||||
do_execsql_test join6-4.1 {
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT 'apple' fruit
|
||||
UNION ALL SELECT 'banana'
|
||||
) a
|
||||
JOIN (
|
||||
SELECT 'apple' fruit
|
||||
UNION ALL SELECT 'banana'
|
||||
) b ON a.fruit=b.fruit
|
||||
LEFT JOIN (
|
||||
SELECT 1 isyellow
|
||||
) c ON b.fruit='banana';
|
||||
} {apple apple {} banana banana 1}
|
||||
do_execsql_test join6-4.2 {
|
||||
SELECT *
|
||||
FROM (SELECT 'apple' fruit UNION ALL SELECT 'banana')
|
||||
LEFT JOIN (SELECT 1) ON fruit='banana';
|
||||
} {apple {} banana 1}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
# 2016-05-20
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the LIMIT in combination with ORDER BY
|
||||
# and in particular, the optimizations in the inner loop that cause an
|
||||
# early exit of the inner loop when the LIMIT is reached and the inner
|
||||
# loop is emitting rows in ORDER BY order.
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test limit2-100 {
|
||||
CREATE TABLE t1(a,b);
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
|
||||
INSERT INTO t1(a,b) SELECT 1, (x*17)%1000 + 1000 FROM c;
|
||||
INSERT INTO t1(a,b) VALUES(2,2),(3,1006),(4,4),(5,9999);
|
||||
CREATE INDEX t1ab ON t1(a,b);
|
||||
}
|
||||
set sqlite_search_count 0
|
||||
do_execsql_test limit2-100.1 {
|
||||
SELECT a, b, '|' FROM t1 WHERE a IN (2,4,5,3,1) ORDER BY b LIMIT 5;
|
||||
} {2 2 | 4 4 | 1 1000 | 1 1001 | 1 1002 |}
|
||||
set fast_count $sqlite_search_count
|
||||
set sqlite_search_count 0
|
||||
do_execsql_test limit2-100.2 {
|
||||
SELECT a, b, '|' FROM t1 WHERE a IN (2,4,5,3,1) ORDER BY +b LIMIT 5;
|
||||
} {2 2 | 4 4 | 1 1000 | 1 1001 | 1 1002 |}
|
||||
do_test limit2-100.3 {
|
||||
set slow_count $sqlite_search_count
|
||||
expr {$fast_count < 0.02*$slow_count}
|
||||
} {1}
|
||||
|
||||
do_execsql_test limit2-110 {
|
||||
CREATE TABLE t2(x,y);
|
||||
INSERT INTO t2(x,y) VALUES('a',1),('a',2),('a',3),('a',4);
|
||||
INSERT INTO t2(x,y) VALUES('b',1),('c',2),('d',3),('e',4);
|
||||
CREATE INDEX t2xy ON t2(x,y);
|
||||
}
|
||||
set sqlite_search_count 0
|
||||
do_execsql_test limit2-110.1 {
|
||||
SELECT a, b, '|' FROM t2, t1 WHERE t2.x='a' AND t1.a=t2.y ORDER BY t1.b LIMIT 5;
|
||||
} {2 2 | 4 4 | 1 1000 | 1 1001 | 1 1002 |}
|
||||
set fast_count $sqlite_search_count
|
||||
set sqlite_search_count 0
|
||||
do_execsql_test limit2-110.2 {
|
||||
SELECT a, b, '|' FROM t2, t1 WHERE t2.x='a' AND t1.a=t2.y ORDER BY +t1.b LIMIT 5;
|
||||
} {2 2 | 4 4 | 1 1000 | 1 1001 | 1 1002 |}
|
||||
set slow_count $sqlite_search_count
|
||||
do_test limit2-110.3 {
|
||||
expr {$fast_count < 0.02*$slow_count}
|
||||
} {1}
|
||||
|
||||
do_execsql_test limit2-120 {
|
||||
DROP INDEX t1ab;
|
||||
CREATE INDEX t1ab ON t1(a,b DESC);
|
||||
}
|
||||
set sqlite_search_count 0
|
||||
do_execsql_test limit2-120.1 {
|
||||
SELECT a, b, '|' FROM t1 WHERE a IN (2,4,5,3,1) ORDER BY b DESC LIMIT 5;
|
||||
} {5 9999 | 1 1999 | 1 1998 | 1 1997 | 1 1996 |}
|
||||
set fast_count $sqlite_search_count
|
||||
set sqlite_search_count 0
|
||||
do_execsql_test limit2-120.2 {
|
||||
SELECT a, b, '|' FROM t1 WHERE a IN (2,4,5,3,1) ORDER BY +b DESC LIMIT 5;
|
||||
} {5 9999 | 1 1999 | 1 1998 | 1 1997 | 1 1996 |}
|
||||
do_test limit2-120.3 {
|
||||
set slow_count $sqlite_search_count
|
||||
expr {$fast_count < 0.02*$slow_count}
|
||||
} {1}
|
||||
|
||||
# Bug report against the new ORDER BY LIMIT optimization just prior to
|
||||
# release. (Unreleased so there is no ticket).
|
||||
#
|
||||
# Make sure the optimization is not applied if the inner loop can only
|
||||
# provide a single row of output.
|
||||
#
|
||||
do_execsql_test limit2-200 {
|
||||
CREATE TABLE t200(a, b);
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
|
||||
INSERT INTO t200(a,b) SELECT x, x FROM c;
|
||||
CREATE TABLE t201(x INTEGER PRIMARY KEY, y);
|
||||
INSERT INTO t201(x,y) VALUES(2,12345);
|
||||
|
||||
SELECT *, '|' FROM t200, t201 WHERE x=b ORDER BY y LIMIT 3;
|
||||
} {2 2 2 12345 |}
|
||||
do_execsql_test limit2-210 {
|
||||
SELECT *, '|' FROM t200 LEFT JOIN t201 ON x=b ORDER BY y LIMIT 3;
|
||||
} {1 1 {} {} | 3 3 {} {} | 4 4 {} {} |}
|
||||
|
||||
# Bug in the ORDER BY LIMIT optimization reported on 2016-09-06.
|
||||
# Ticket https://www.sqlite.org/src/info/559733b09e96
|
||||
#
|
||||
do_execsql_test limit2-300 {
|
||||
CREATE TABLE t300(a,b,c);
|
||||
CREATE INDEX t300x ON t300(a,b,c);
|
||||
INSERT INTO t300 VALUES(0,1,99),(0,1,0),(0,0,0);
|
||||
SELECT *,'.' FROM t300 WHERE a=0 AND (c=0 OR c=99) ORDER BY c DESC;
|
||||
} {0 1 99 . 0 0 0 . 0 1 0 .}
|
||||
do_execsql_test limit2-310 {
|
||||
SELECT *,'.' FROM t300 WHERE a=0 AND (c=0 OR c=99) ORDER BY c DESC LIMIT 1;
|
||||
} {0 1 99 .}
|
||||
|
||||
# Make sure the SELECT loop is ordered correctly for the direction of
|
||||
# the ORDER BY
|
||||
#
|
||||
do_execsql_test limit2-400 {
|
||||
CREATE TABLE t400(a,b);
|
||||
CREATE INDEX t400_ab ON t400(a,b);
|
||||
INSERT INTO t400(a,b) VALUES(1,90),(1,40),(2,80),(2,30),(3,70),(3,20);
|
||||
SELECT *,'x' FROM t400 WHERE a IN (1,2,3) ORDER BY b DESC LIMIT 3;
|
||||
SELECT *,'y' FROM t400 WHERE a IN (1,2,3) ORDER BY +b DESC LIMIT 3;
|
||||
} {1 90 x 2 80 x 3 70 x 1 90 y 2 80 y 3 70 y}
|
||||
|
||||
finish_test
|
||||
@@ -143,6 +143,33 @@ do_faultsim_test 7.2 -faults oom* -body {
|
||||
faultsim_test_result [list 0 {}]
|
||||
}
|
||||
|
||||
reset_db
|
||||
|
||||
proc isqrt {i} { expr { int(sqrt($i)) } }
|
||||
db func isqrt isqrt
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
PRAGMA encoding = 'utf-16';
|
||||
CREATE TABLE x2(x TEXT, y TEXT);
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO x2 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400;
|
||||
CREATE INDEX x2x ON x2(x);
|
||||
CREATE INDEX x2y ON x2(y);
|
||||
ANALYZE;
|
||||
DELETE FROM x2;
|
||||
}
|
||||
|
||||
proc str {a} { return $a }
|
||||
db func str -deterministic str
|
||||
|
||||
do_faultsim_test 8 -faults oom* -body {
|
||||
execsql { SELECT * FROM x2 WHERE x = str('19') AND y = str('4') }
|
||||
} -test {
|
||||
faultsim_test_result [list 0 {}]
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+9
-1
@@ -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
|
||||
|
||||
@@ -496,4 +496,21 @@ do_execsql_test 7.0 {
|
||||
} {~/ORDER BY/}
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# https://www.sqlite.org/src/tktview/cb3aa0641d9a413841c004293a4fc06cdc122029
|
||||
#
|
||||
# Adverse interaction between scalar subqueries and the partial-sorting
|
||||
# logic.
|
||||
#
|
||||
do_execsql_test 9.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES(1),(2);
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(y);
|
||||
INSERT INTO t2 VALUES(9),(8),(3),(4);
|
||||
SELECT (SELECT x||y FROM t2, t1 ORDER BY x, y);
|
||||
} {13}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -472,6 +472,18 @@ do_test printf-1.16.7 {
|
||||
sqlite3_mprintf_int {abc: (%#6d) (%#6x) (%#6o) :xyz}\
|
||||
0xff676981 0xff676981 0xff676981
|
||||
} {abc: (-9999999) (0xff676981) (037731664601) :xyz}
|
||||
do_test printf-1.17.1 {
|
||||
sqlite3_mprintf_int {abd: %2147483647d %2147483647x %2147483647o} 1 1 1
|
||||
} {}
|
||||
do_test printf-1.17.2 {
|
||||
sqlite3_mprintf_int {abd: %*d %x} 2147483647 1 1
|
||||
} {}
|
||||
do_test printf-1.17.3 {
|
||||
sqlite3_mprintf_int {abd: %*d %x} -2147483648 1 1
|
||||
} {abd: 1 1}
|
||||
do_test printf-1.17.4 {
|
||||
sqlite3_mprintf_int {abd: %.2147483648d %x %x} 1 1 1
|
||||
} {/.*/}
|
||||
do_test printf-2.1.1.1 {
|
||||
sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 0.001
|
||||
} {abc: (0.0) :xyz}
|
||||
@@ -526,6 +538,9 @@ do_test printf-2.1.2.8 {
|
||||
do_test printf-2.1.2.9 {
|
||||
sqlite3_mprintf_double {abc: %d %d (%1.1g) :xyz} 1 1 1.0e-20
|
||||
} {abc: 1 1 (1e-20) :xyz}
|
||||
do_test printf-2.1.2.10 {
|
||||
sqlite3_mprintf_double {abc: %*.*f} 2000000000 1000000000 1.0e-20
|
||||
} {abc: }
|
||||
do_test printf-2.1.3.1 {
|
||||
sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 1.0
|
||||
} {abc: (1.0) :xyz}
|
||||
@@ -3466,6 +3481,15 @@ do_test printf-3.5 {
|
||||
do_test printf-3.6 {
|
||||
sqlite3_mprintf_str {%d %d A String: (%-30s)} 1 2 {This is the string}
|
||||
} [format {%d %d A String: (%-30s)} 1 2 {This is the string}]
|
||||
do_test printf-3.7 {
|
||||
sqlite3_mprintf_str {%d A String: (%*s)} 1 2147483647 {This is the string}
|
||||
} []
|
||||
do_test printf-3.8 {
|
||||
sqlite3_mprintf_str {%d A String: (%*s)} 1 -2147483648 {This is the string}
|
||||
} {1 A String: (This is the string)}
|
||||
do_test printf-3.9 {
|
||||
sqlite3_mprintf_str {%d A String: (%.*s)} 1 -2147483648 {This is the string}
|
||||
} {1 A String: (This is the string)}
|
||||
do_test snprintf-3.11 {
|
||||
sqlite3_snprintf_str 2 {x%d %d %s} 10 10 {This is the string}
|
||||
} {x}
|
||||
@@ -3685,6 +3709,9 @@ do_test printf-13.5 {
|
||||
do_test printf-13.6 {
|
||||
sqlite3_mprintf_hexdouble %.20f fff8000000000000
|
||||
} {NaN}
|
||||
do_test printf-13.7 {
|
||||
sqlite3_mprintf_hexdouble %2147483648.10000f 4693b8b5b5056e17
|
||||
} {/100000000000000000000000000000000.00/}
|
||||
|
||||
do_test printf-14.1 {
|
||||
sqlite3_mprintf_str {abc-%y-123} 0 0 {not used}
|
||||
|
||||
@@ -864,4 +864,41 @@ do_execsql_test select4-14.9 {
|
||||
SELECT * FROM t14 UNION ALL VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3);
|
||||
} {1 2 3 4 5 6 3 2 1 2 3 1 1 2 3 2 1 3}
|
||||
|
||||
# Ticket https://www.sqlite.org/src/tktview/f7f8c97e975978d45 on 2016-04-25
|
||||
#
|
||||
# The where push-down optimization from 2015-06-02 is suppose to disable
|
||||
# on aggregate subqueries. But if the subquery is a compound where the
|
||||
# last SELECT is non-aggregate but some other SELECT is an aggregate, the
|
||||
# test is incomplete and the optimization is not properly disabled.
|
||||
#
|
||||
# The following test cases verify that the fix works.
|
||||
#
|
||||
do_execsql_test select4-17.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a int, b int);
|
||||
INSERT INTO t1 VALUES(1,2),(1,18),(2,19);
|
||||
SELECT x, y FROM (
|
||||
SELECT 98 AS x, 99 AS y
|
||||
UNION
|
||||
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a
|
||||
) AS w WHERE y>=20
|
||||
ORDER BY +x;
|
||||
} {1 20 98 99}
|
||||
do_execsql_test select4-17.2 {
|
||||
SELECT x, y FROM (
|
||||
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a
|
||||
UNION
|
||||
SELECT 98 AS x, 99 AS y
|
||||
) AS w WHERE y>=20
|
||||
ORDER BY +x;
|
||||
} {1 20 98 99}
|
||||
do_catchsql_test select4-17.3 {
|
||||
SELECT x, y FROM (
|
||||
SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a LIMIT 3
|
||||
UNION
|
||||
SELECT 98 AS x, 99 AS y
|
||||
) AS w WHERE y>=20
|
||||
ORDER BY +x;
|
||||
} {1 {LIMIT clause should come after UNION not before}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1375,4 +1375,64 @@ do_execsql_test 4.2.2 {
|
||||
} {/2 . 3 . 4 . 5 . 6 . 7 ./}
|
||||
|
||||
|
||||
proc strip_rnd {explain} {
|
||||
regexp -all {sqlite_sq_[0123456789ABCDEF]*} $explain sqlite_sq
|
||||
}
|
||||
|
||||
proc do_same_test {tn q1 args} {
|
||||
set r2 [strip_rnd [db eval "EXPLAIN $q1"]]
|
||||
set i 1
|
||||
foreach q $args {
|
||||
set tst [subst -nocommands {strip_rnd [db eval "EXPLAIN $q"]}]
|
||||
uplevel do_test $tn.$i [list $tst] [list $r2]
|
||||
incr i
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t8(a, b);
|
||||
CREATE TABLE t9(c, d);
|
||||
} {}
|
||||
|
||||
do_same_test 5.1 {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY a;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t8.a;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY 1;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY c;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t9.c;
|
||||
}
|
||||
|
||||
do_same_test 5.2 {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t8.a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY 1 COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY c COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t9.c COLLATE NOCASE
|
||||
}
|
||||
|
||||
do_same_test 5.3 {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY b, c COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY 2, 1 COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT * FROM t9 ORDER BY t9.d, c COLLATE NOCASE
|
||||
} {
|
||||
SELECT * FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, t8.a COLLATE NOCASE
|
||||
}
|
||||
|
||||
do_catchsql_test 5.4 {
|
||||
SELECT * FROM t8 UNION SELECT * FROM t9 ORDER BY a+b COLLATE NOCASE
|
||||
} {1 {1st ORDER BY term does not match any column in the result set}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+22
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+21
-1
@@ -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
|
||||
|
||||
|
||||
+3
-6
@@ -15,6 +15,7 @@ source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
finish_test; return; # Feature currently not implemented.
|
||||
ifcapable !wal {finish_test ; return }
|
||||
if {$::tcl_platform(platform)!="unix"} { finish_test ; return }
|
||||
set testprefix walblock
|
||||
@@ -92,9 +93,9 @@ proc barrier_callback {method args} {
|
||||
set ::out ""
|
||||
testfixture $::C { db eval { SELECT * FROM t1 } } {set ::out}
|
||||
|
||||
do_test "1.2.2.(blocking 5 seconds)" {
|
||||
do_test "1.2.2.(blocking 10 seconds)" {
|
||||
set ::continue 0
|
||||
after 5000 {set ::continue 1}
|
||||
after 10000 {set ::continue 1}
|
||||
vwait ::continue
|
||||
set ::out
|
||||
} {}
|
||||
@@ -111,7 +112,3 @@ do_test "1.2.3.(blocking 0.5 seconds)" {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+72
-1
@@ -156,7 +156,7 @@ do_searchcount_test 3.4.4 {
|
||||
|
||||
do_searchcount_test 3.5.1 {
|
||||
SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4
|
||||
} {1 one 2 two search 2}
|
||||
} {1 one 2 two search 1}
|
||||
do_searchcount_test 3.5.2 {
|
||||
SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4
|
||||
} {1 i 2 ii search 2}
|
||||
@@ -271,5 +271,76 @@ do_execsql_test 5.3 {
|
||||
c16=1 or c17=1;
|
||||
} {1 {} {} {} {} {} {} {} {} {} {} {} {} {} {} 1 {} {}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 6.1 {
|
||||
CREATE TABLE x1(a, b, c, d, e);
|
||||
CREATE INDEX x1a ON x1(a);
|
||||
CREATE INDEX x1bc ON x1(b, c);
|
||||
CREATE INDEX x1cd ON x1(c, d);
|
||||
|
||||
INSERT INTO x1 VALUES(1, 2, 3, 4, 'A');
|
||||
INSERT INTO x1 VALUES(5, 6, 7, 8, 'B');
|
||||
INSERT INTO x1 VALUES(9, 10, 11, 12, 'C');
|
||||
INSERT INTO x1 VALUES(13, 14, 15, 16, 'D');
|
||||
}
|
||||
|
||||
do_searchcount_test 6.2.1 {
|
||||
SELECT e FROM x1 WHERE b=2 OR c=7;
|
||||
} {A B search 6}
|
||||
do_searchcount_test 6.2.2 {
|
||||
SELECT c FROM x1 WHERE b=2 OR c=7;
|
||||
} {3 7 search 4}
|
||||
|
||||
do_searchcount_test 6.3.1 {
|
||||
SELECT e FROM x1 WHERE a=1 OR b=10;
|
||||
} {A C search 6}
|
||||
do_searchcount_test 6.3.2 {
|
||||
SELECT c FROM x1 WHERE a=1 OR b=10;
|
||||
} {3 11 search 5}
|
||||
do_searchcount_test 6.3.3 {
|
||||
SELECT rowid FROM x1 WHERE a=1 OR b=10;
|
||||
} {1 3 search 4}
|
||||
|
||||
do_searchcount_test 6.4.1 {
|
||||
SELECT a FROM x1 WHERE b BETWEEN 1 AND 4 OR c BETWEEN 8 AND 12
|
||||
} {1 9 search 6}
|
||||
do_searchcount_test 6.4.2 {
|
||||
SELECT b, c FROM x1 WHERE b BETWEEN 1 AND 4 OR c BETWEEN 8 AND 12
|
||||
} {2 3 10 11 search 5}
|
||||
do_searchcount_test 6.4.3 {
|
||||
SELECT rowid, c FROM x1 WHERE b BETWEEN 1 AND 4 OR c BETWEEN 8 AND 12
|
||||
} {1 3 3 11 search 4}
|
||||
|
||||
db eval {
|
||||
WITH RECURSIVE c(x) AS (VALUES(1000) UNION ALL SELECT x+1 FROM c WHERE x<2000)
|
||||
INSERT INTO x1(rowid,a,b,c,d,e) SELECT x,x,x,x,x,x FROM c;
|
||||
}
|
||||
|
||||
do_searchcount_test 6.5.1 {
|
||||
SELECT a FROM x1 WHERE rowid = 2 OR c=11
|
||||
} {5 9 search 3}
|
||||
do_searchcount_test 6.5.2 {
|
||||
SELECT d FROM x1 WHERE rowid = 2 OR c=11
|
||||
} {8 12 search 2}
|
||||
do_searchcount_test 6.5.3 {
|
||||
SELECT d FROM x1 WHERE c=11 OR rowid = 2
|
||||
} {12 8 search 2}
|
||||
do_searchcount_test 6.5.4 {
|
||||
SELECT a FROM x1 WHERE c=11 OR rowid = 2
|
||||
} {9 5 search 3}
|
||||
|
||||
do_searchcount_test 6.6.1 {
|
||||
SELECT rowid FROM x1 WHERE a=1 OR b=6 OR c=11
|
||||
} {1 2 3 search 6}
|
||||
do_searchcount_test 6.6.2 {
|
||||
SELECT c FROM x1 WHERE a=1 OR b=6 OR c=11
|
||||
} {3 7 11 search 7}
|
||||
do_searchcount_test 6.6.3 {
|
||||
SELECT c FROM x1 WHERE c=11 OR a=1 OR b=6
|
||||
} {11 3 7 search 7}
|
||||
do_searchcount_test 6.6.4 {
|
||||
SELECT c FROM x1 WHERE b=6 OR c=11 OR a=1
|
||||
} {7 11 3 search 7}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# 2015-03-16
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing OR expressions where terms can be
|
||||
# factored from either side of the OR and combined into a single new
|
||||
# AND term that is beneficial to the search. Examples:
|
||||
#
|
||||
# (x>A OR x=A) --> ... AND (x>=A)
|
||||
# (x>A OR (x=A AND y>=B) --> ... AND (x>=A)
|
||||
#
|
||||
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix whereK
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<99)
|
||||
INSERT INTO t1(a,b,c) SELECT x, x/10, x%10 FROM c;
|
||||
CREATE INDEX t1bc ON t1(b,c);
|
||||
SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a;
|
||||
} {90 91 92 93 94 95 96 97 98 99}
|
||||
do_execsql_test 1.1eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a;
|
||||
} {88 89 90 91 92 93 94 95 96 97 98 99}
|
||||
do_execsql_test 1.2eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a;
|
||||
} {88 89 90 91 92 93 94 95 96 97 98 99}
|
||||
do_execsql_test 1.3eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR 8<b ORDER BY +a;
|
||||
} {88 89 90 91 92 93 94 95 96 97 98 99}
|
||||
do_execsql_test 1.4eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR 8<b ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR (b>8 AND c NOT IN (4,5,6))
|
||||
ORDER BY +a;
|
||||
} {88 89 90 91 92 93 97 98 99}
|
||||
do_execsql_test 1.5eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR (b>8 AND c NOT IN (4,5,6))
|
||||
ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
finish_test
|
||||
@@ -64,6 +64,7 @@ while {1} {
|
||||
if {[info exists ::log] && $::log!=""} {
|
||||
do_test win32lock-1.2-$delay1-log1 {
|
||||
regsub {\d+} $::log # x
|
||||
regsub { at line \d+} $x "" x
|
||||
set x
|
||||
} {{delayed #ms for lock/sharing conflict}}
|
||||
}
|
||||
@@ -112,6 +113,7 @@ while {1} {
|
||||
if {[info exists ::log] && $::log!=""} {
|
||||
do_test win32lock-2.2-$delay1-log1 {
|
||||
regsub {\d+} $::log # x
|
||||
regsub { at line \d+} $x "" x
|
||||
set x
|
||||
} {{delayed #ms for lock/sharing conflict}}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+76
-4
@@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
+3
-3
@@ -1731,7 +1731,7 @@ static char *msort(
|
||||
char *ep;
|
||||
char *set[LISTSIZE];
|
||||
int i;
|
||||
offset = (unsigned long)next - (unsigned long)list;
|
||||
offset = (unsigned long)((char*)next - (char*)list);
|
||||
for(i=0; i<LISTSIZE; i++) set[i] = 0;
|
||||
while( list ){
|
||||
ep = list;
|
||||
@@ -1875,7 +1875,7 @@ static int handleswitch(int i, FILE *err)
|
||||
if( *end ){
|
||||
if( err ){
|
||||
fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
|
||||
errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
|
||||
errline(i,(int)((char*)end-(char*)argv[i]),err);
|
||||
}
|
||||
errcnt++;
|
||||
}
|
||||
@@ -1886,7 +1886,7 @@ static int handleswitch(int i, FILE *err)
|
||||
if( *end ){
|
||||
if( err ){
|
||||
fprintf(err,"%sillegal character in integer argument.\n",emsg);
|
||||
errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
|
||||
errline(i,(int)((char*)end-(char*)argv[i]),err);
|
||||
}
|
||||
errcnt++;
|
||||
}
|
||||
|
||||
+68
-26
@@ -17,13 +17,13 @@
|
||||
# After the "tsrc" directory has been created and populated, run
|
||||
# this script:
|
||||
#
|
||||
# tclsh mksqlite3c.tcl
|
||||
# tclsh mksqlite3c-noext.tcl
|
||||
#
|
||||
# The amalgamated SQLite code will be written into sqlite3.c
|
||||
#
|
||||
|
||||
# Begin by reading the "sqlite3.h" header file. Extract the version number
|
||||
# from in this file. The versioon number is needed to generate the header
|
||||
# from in this file. The version number is needed to generate the header
|
||||
# comment of the amalgamation.
|
||||
#
|
||||
if {[lsearch $argv --nostatic]>=0} {
|
||||
@@ -80,9 +80,6 @@ if {$addstatic} {
|
||||
puts $out \
|
||||
{#ifndef SQLITE_PRIVATE
|
||||
# define SQLITE_PRIVATE static
|
||||
#endif
|
||||
#ifndef SQLITE_API
|
||||
# define SQLITE_API
|
||||
#endif}
|
||||
}
|
||||
|
||||
@@ -106,6 +103,7 @@ foreach hdr {
|
||||
pager.h
|
||||
parse.h
|
||||
pcache.h
|
||||
pragma.h
|
||||
sqlite3ext.h
|
||||
sqlite3.h
|
||||
sqliteicu.h
|
||||
@@ -113,12 +111,31 @@ foreach hdr {
|
||||
sqliteLimit.h
|
||||
vdbe.h
|
||||
vdbeInt.h
|
||||
vxworks.h
|
||||
wal.h
|
||||
whereInt.h
|
||||
} {
|
||||
set available_hdr($hdr) 1
|
||||
}
|
||||
set available_hdr(sqliteInt.h) 0
|
||||
|
||||
# These headers should be copied into the amalgamation without modifying any
|
||||
# of their function declarations or definitions.
|
||||
set varonly_hdr(sqlite3.h) 1
|
||||
|
||||
# These are the functions that accept a variable number of arguments. They
|
||||
# always need to use the "cdecl" calling convention even when another calling
|
||||
# convention (e.g. "stcall") is being used for the rest of the library.
|
||||
set cdecllist {
|
||||
sqlite3_config
|
||||
sqlite3_db_config
|
||||
sqlite3_log
|
||||
sqlite3_mprintf
|
||||
sqlite3_snprintf
|
||||
sqlite3_test_control
|
||||
sqlite3_vtab_config
|
||||
}
|
||||
|
||||
# 78 stars used for comment formatting.
|
||||
set s78 \
|
||||
{*****************************************************************************}
|
||||
@@ -135,21 +152,21 @@ proc section_comment {text} {
|
||||
|
||||
# Read the source file named $filename and write it into the
|
||||
# sqlite3.c output file. If any #include statements are seen,
|
||||
# process them approprately.
|
||||
# process them appropriately.
|
||||
#
|
||||
proc copy_file {filename} {
|
||||
global seen_hdr available_hdr out addstatic linemacros
|
||||
global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
|
||||
set ln 0
|
||||
set tail [file tail $filename]
|
||||
section_comment "Begin file $tail"
|
||||
if {$linemacros} {puts $out "#line 1 \"$filename\""}
|
||||
set in [open $filename r]
|
||||
set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
|
||||
set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(}
|
||||
set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
|
||||
if {[file extension $filename]==".h"} {
|
||||
set declpattern " *$declpattern"
|
||||
}
|
||||
set declpattern ^$declpattern
|
||||
set declpattern ^$declpattern\$
|
||||
while {![eof $in]} {
|
||||
set line [gets $in]
|
||||
incr ln
|
||||
@@ -165,42 +182,67 @@ proc copy_file {filename} {
|
||||
if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
|
||||
}
|
||||
} elseif {![info exists seen_hdr($hdr)]} {
|
||||
set seen_hdr($hdr) 1
|
||||
if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
|
||||
set seen_hdr($hdr) 1
|
||||
}
|
||||
puts $out $line
|
||||
} elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
|
||||
# This include file must be kept because there was a "keep"
|
||||
# directive inside of a line comment.
|
||||
puts $out $line
|
||||
} else {
|
||||
puts $out "/* $line */"
|
||||
# Comment out the entire line, replacing any nested comment
|
||||
# begin/end markers with the harmless substring "**".
|
||||
puts $out "/* [string map [list /* ** */ **] $line] */"
|
||||
}
|
||||
} elseif {[regexp {^#ifdef __cplusplus} $line]} {
|
||||
puts $out "#if 0"
|
||||
} elseif {!$linemacros && [regexp {^#line} $line]} {
|
||||
# Skip #line directives.
|
||||
} elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
if {[regexp $declpattern $line all funcname]} {
|
||||
# Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
|
||||
# functions if this header file does not need it.
|
||||
if {![info exists varonly_hdr($tail)]
|
||||
&& [regexp $declpattern $line all rettype funcname rest]} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
# Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
|
||||
# so that linkage can be modified at compile-time.
|
||||
if {[regexp {^sqlite3_} $funcname]} {
|
||||
puts $out "SQLITE_API $line"
|
||||
set line SQLITE_API
|
||||
append line " " [string trim $rettype]
|
||||
if {[string index $rettype end] ne "*"} {
|
||||
append line " "
|
||||
}
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL
|
||||
} else {
|
||||
append line SQLITE_STDCALL
|
||||
}
|
||||
append line " " $funcname $rest
|
||||
puts $out $line
|
||||
} else {
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
}
|
||||
} elseif {[regexp $varpattern $line all varname]} {
|
||||
# Add the SQLITE_PRIVATE before variable declarations or
|
||||
# definitions for internal use
|
||||
if {![regexp {^sqlite3_} $varname]} {
|
||||
regsub {^extern } $line {} line
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
} else {
|
||||
if {[regexp {const char sqlite3_version\[\];} $line]} {
|
||||
set line {const char sqlite3_version[] = SQLITE_VERSION;}
|
||||
# Add the SQLITE_PRIVATE before variable declarations or
|
||||
# definitions for internal use
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
if {![regexp {^sqlite3_} $varname]} {
|
||||
regsub {^extern } $line {} line
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
} else {
|
||||
if {[regexp {const char sqlite3_version\[\];} $line]} {
|
||||
set line {const char sqlite3_version[] = SQLITE_VERSION;}
|
||||
}
|
||||
regsub {^SQLITE_EXTERN } $line {} line
|
||||
puts $out "SQLITE_API $line"
|
||||
}
|
||||
regsub {^SQLITE_EXTERN } $line {} line
|
||||
puts $out "SQLITE_API $line"
|
||||
}
|
||||
} elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
regsub {^SQLITE_EXTERN } $line {} line
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
puts $out $line
|
||||
} elseif {[regexp {^void \(\*sqlite3Os} $line]} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
} else {
|
||||
puts $out $line
|
||||
|
||||
+51
-20
@@ -80,9 +80,6 @@ if {$addstatic} {
|
||||
puts $out \
|
||||
{#ifndef SQLITE_PRIVATE
|
||||
# define SQLITE_PRIVATE static
|
||||
#endif
|
||||
#ifndef SQLITE_API
|
||||
# define SQLITE_API
|
||||
#endif}
|
||||
}
|
||||
|
||||
@@ -127,6 +124,23 @@ foreach hdr {
|
||||
}
|
||||
set available_hdr(sqliteInt.h) 0
|
||||
|
||||
# These headers should be copied into the amalgamation without modifying any
|
||||
# of their function declarations or definitions.
|
||||
set varonly_hdr(sqlite3.h) 1
|
||||
|
||||
# These are the functions that accept a variable number of arguments. They
|
||||
# always need to use the "cdecl" calling convention even when another calling
|
||||
# convention (e.g. "stcall") is being used for the rest of the library.
|
||||
set cdecllist {
|
||||
sqlite3_config
|
||||
sqlite3_db_config
|
||||
sqlite3_log
|
||||
sqlite3_mprintf
|
||||
sqlite3_snprintf
|
||||
sqlite3_test_control
|
||||
sqlite3_vtab_config
|
||||
}
|
||||
|
||||
# 78 stars used for comment formatting.
|
||||
set s78 \
|
||||
{*****************************************************************************}
|
||||
@@ -146,18 +160,18 @@ proc section_comment {text} {
|
||||
# process them appropriately.
|
||||
#
|
||||
proc copy_file {filename} {
|
||||
global seen_hdr available_hdr out addstatic linemacros
|
||||
global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
|
||||
set ln 0
|
||||
set tail [file tail $filename]
|
||||
section_comment "Begin file $tail"
|
||||
if {$linemacros} {puts $out "#line 1 \"$filename\""}
|
||||
set in [open $filename r]
|
||||
set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
|
||||
set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(}
|
||||
set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
|
||||
if {[file extension $filename]==".h"} {
|
||||
set declpattern " *$declpattern"
|
||||
}
|
||||
set declpattern ^$declpattern
|
||||
set declpattern ^$declpattern\$
|
||||
while {![eof $in]} {
|
||||
set line [gets $in]
|
||||
incr ln
|
||||
@@ -191,32 +205,49 @@ proc copy_file {filename} {
|
||||
} elseif {!$linemacros && [regexp {^#line} $line]} {
|
||||
# Skip #line directives.
|
||||
} elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
if {[regexp $declpattern $line all funcname]} {
|
||||
# Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
|
||||
# functions if this header file does not need it.
|
||||
if {![info exists varonly_hdr($tail)]
|
||||
&& [regexp $declpattern $line all rettype funcname rest]} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
# Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
|
||||
# so that linkage can be modified at compile-time.
|
||||
if {[regexp {^sqlite3_} $funcname]} {
|
||||
puts $out "SQLITE_API $line"
|
||||
set line SQLITE_API
|
||||
append line " " [string trim $rettype]
|
||||
if {[string index $rettype end] ne "*"} {
|
||||
append line " "
|
||||
}
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL
|
||||
} else {
|
||||
append line SQLITE_STDCALL
|
||||
}
|
||||
append line " " $funcname $rest
|
||||
puts $out $line
|
||||
} else {
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
}
|
||||
} elseif {[regexp $varpattern $line all varname]} {
|
||||
# Add the SQLITE_PRIVATE before variable declarations or
|
||||
# definitions for internal use
|
||||
if {![regexp {^sqlite3_} $varname]} {
|
||||
regsub {^extern } $line {} line
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
} else {
|
||||
if {[regexp {const char sqlite3_version\[\];} $line]} {
|
||||
set line {const char sqlite3_version[] = SQLITE_VERSION;}
|
||||
# Add the SQLITE_PRIVATE before variable declarations or
|
||||
# definitions for internal use
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
if {![regexp {^sqlite3_} $varname]} {
|
||||
regsub {^extern } $line {} line
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
} else {
|
||||
if {[regexp {const char sqlite3_version\[\];} $line]} {
|
||||
set line {const char sqlite3_version[] = SQLITE_VERSION;}
|
||||
}
|
||||
regsub {^SQLITE_EXTERN } $line {} line
|
||||
puts $out "SQLITE_API $line"
|
||||
}
|
||||
regsub {^SQLITE_EXTERN } $line {} line
|
||||
puts $out "SQLITE_API $line"
|
||||
}
|
||||
} elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
regsub {^SQLITE_EXTERN } $line {} line
|
||||
puts $out $line
|
||||
} elseif {[regexp {^void \(\*sqlite3Os} $line]} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
} else {
|
||||
puts $out $line
|
||||
|
||||
+30
-15
@@ -63,7 +63,7 @@ close $in
|
||||
# Set up patterns for recognizing API declarations.
|
||||
#
|
||||
set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+sqlite3_[_a-zA-Z0-9]+(\[|;| =)}
|
||||
set declpattern {^ *[a-zA-Z][a-zA-Z_0-9 ]+ \**sqlite3_[_a-zA-Z0-9]+\(}
|
||||
set declpattern {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3_[_a-zA-Z0-9]+)(\(.*)$}
|
||||
|
||||
# Force the output to use unix line endings, even on Windows.
|
||||
fconfigure stdout -translation lf
|
||||
@@ -73,6 +73,19 @@ set filelist [subst {
|
||||
$TOP/ext/rtree/sqlite3rtree.h
|
||||
}]
|
||||
|
||||
# These are the functions that accept a variable number of arguments. They
|
||||
# always need to use the "cdecl" calling convention even when another calling
|
||||
# convention (e.g. "stcall") is being used for the rest of the library.
|
||||
set cdecllist {
|
||||
sqlite3_config
|
||||
sqlite3_db_config
|
||||
sqlite3_log
|
||||
sqlite3_mprintf
|
||||
sqlite3_snprintf
|
||||
sqlite3_test_control
|
||||
sqlite3_vtab_config
|
||||
}
|
||||
|
||||
# Process the source files.
|
||||
#
|
||||
foreach file $filelist {
|
||||
@@ -89,21 +102,23 @@ foreach file $filelist {
|
||||
regsub -- --VERS-- $line $zVersion line
|
||||
regsub -- --VERSION-NUMBER-- $line $nVersion line
|
||||
regsub -- --SOURCE-ID-- $line "$zDate $zUuid" line
|
||||
|
||||
if {[regexp {define SQLITE_EXTERN extern} $line]} {
|
||||
puts $line
|
||||
puts [gets $in]
|
||||
puts ""
|
||||
puts "#ifndef SQLITE_API"
|
||||
puts "# define SQLITE_API"
|
||||
puts "#endif"
|
||||
set line ""
|
||||
}
|
||||
|
||||
if {([regexp $varpattern $line] && ![regexp {^ *typedef} $line])
|
||||
|| ([regexp $declpattern $line])
|
||||
} {
|
||||
|
||||
if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} {
|
||||
set line "SQLITE_API $line"
|
||||
} else {
|
||||
if {[regexp $declpattern $line all rettype funcname rest]} {
|
||||
set line SQLITE_API
|
||||
append line " " [string trim $rettype]
|
||||
if {[string index $rettype end] ne "*"} {
|
||||
append line " "
|
||||
}
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL
|
||||
} else {
|
||||
append line SQLITE_STDCALL
|
||||
}
|
||||
append line " " $funcname $rest
|
||||
}
|
||||
}
|
||||
puts $line
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
** This file implements a simple command-line utility that shows all of the
|
||||
** Posix Advisory Locks on a file.
|
||||
**
|
||||
** Usage:
|
||||
**
|
||||
** showlocks FILENAME
|
||||
**
|
||||
** To compile: gcc -o showlocks showlocks.c
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* This utility only looks for locks in the first 2 billion bytes */
|
||||
#define MX_LCK 2147483647
|
||||
|
||||
/*
|
||||
** Print all locks on the inode of "fd" that occur in between
|
||||
** lwr and upr, inclusive.
|
||||
*/
|
||||
static int showLocksInRange(int fd, off_t lwr, off_t upr){
|
||||
int cnt = 0;
|
||||
struct flock x;
|
||||
|
||||
x.l_type = F_WRLCK;
|
||||
x.l_whence = SEEK_SET;
|
||||
x.l_start = lwr;
|
||||
x.l_len = upr-lwr;
|
||||
fcntl(fd, F_GETLK, &x);
|
||||
if( x.l_type==F_UNLCK ) return 0;
|
||||
printf("start: %-12d len: %-5d pid: %-5d type: %s\n",
|
||||
(int)x.l_start, (int)x.l_len,
|
||||
x.l_pid, x.l_type==F_WRLCK ? "WRLCK" : "RDLCK");
|
||||
cnt++;
|
||||
if( x.l_start>lwr ){
|
||||
cnt += showLocksInRange(fd, lwr, x.l_start-1);
|
||||
}
|
||||
if( x.l_start+x.l_len<upr ){
|
||||
cnt += showLocksInRange(fd, x.l_start+x.l_len+1, upr);
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int fd;
|
||||
int cnt;
|
||||
|
||||
if( argc!=2 ){
|
||||
fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
fd = open(argv[1], O_RDWR, 0);
|
||||
if( fd<0 ){
|
||||
fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]);
|
||||
return 1;
|
||||
}
|
||||
cnt = showLocksInRange(fd, 0, MX_LCK);
|
||||
if( cnt==0 ) printf("no locks\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user