Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f61e13f72 | |||
| 5c8b293c75 | |||
| df5e9e977b | |||
| 04de790b09 | |||
| 83dca19e9f | |||
| df24cf81a6 | |||
| 5a7dbc70ea | |||
| dfea45330e | |||
| 449cb9a5af | |||
| 0d3a4085e5 | |||
| d94d4ee7bd | |||
| f7f425d600 | |||
| e18e90ebaf | |||
| 0d51def29e | |||
| 2fc7bc08bd | |||
| 7bd3c89114 | |||
| a09c8855b7 | |||
| e500747cfe | |||
| 84de690b4f | |||
| 2ae56f50ce | |||
| 79211e194d | |||
| a7bf23c6b5 | |||
| c7f6c148d9 | |||
| 012e133772 | |||
| 7a0fd192cc | |||
| fb0d6e56d6 | |||
| f690c14280 | |||
| 0ff435a782 | |||
| 3de4df27dd | |||
| 9e0ed8d4ec | |||
| 46a06bbe47 | |||
| 958d261bb8 | |||
| e9af1894e3 | |||
| a9f43d735b | |||
| 31a0bfde9b | |||
| db30fc4ff2 | |||
| 7f0a24b7bf | |||
| 22ace89179 | |||
| 1a088a8ef5 | |||
| 9c1586ec7c | |||
| f77ceba594 | |||
| 92a20dde1f | |||
| be3018c18f | |||
| 82a8a9f120 | |||
| 4be4c406fa | |||
| d30ab3d9dd | |||
| bf20a35d5f | |||
| f7da5555da | |||
| 85462ed939 | |||
| 8daefc2af0 | |||
| 6b5d4759ce | |||
| 1aca5caa88 | |||
| 8930c2ab0c | |||
| 6e4cc55e1f | |||
| a634fb1577 | |||
| ac4f0039c0 | |||
| dd95d30f82 | |||
| 8d8f56296b | |||
| fad9f9a8a6 | |||
| 578e1ca8d7 | |||
| 38fdead890 | |||
| b3f56fdb69 | |||
| 853c4a7621 | |||
| e7c84cc7e3 | |||
| ff9fce4d60 | |||
| 73e7d8b2bb | |||
| 2f17001521 | |||
| 7c8e9c78c8 | |||
| 6971952c65 | |||
| face087212 | |||
| bfa463696b | |||
| 664eb14d8e | |||
| e6c7b09df6 | |||
| ab1dcc1a4b | |||
| 78d5843245 | |||
| 3c863634ef | |||
| 5c2b314222 | |||
| dd23c6bfb4 | |||
| fd0a2f9756 | |||
| 3f802ebce2 | |||
| 83553eefaf | |||
| 70f624c3a9 | |||
| d345a66428 | |||
| f45f2326a2 | |||
| f87684189d | |||
| c625ba7f4f | |||
| 6ddecb753a | |||
| daa3ce4b08 | |||
| e22724ee54 | |||
| a806475f86 | |||
| 572df3b1e4 | |||
| da0e47109e | |||
| f51446a38c |
+5
-5
@@ -177,7 +177,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
|
||||
table.lo tokenize.lo trigger.lo \
|
||||
table.lo threads.lo tokenize.lo trigger.lo \
|
||||
update.lo util.lo vacuum.lo \
|
||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
|
||||
@@ -239,10 +239,8 @@ SRC = \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_setup.h \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/parse.y \
|
||||
@@ -263,6 +261,7 @@ SRC = \
|
||||
$(TOP)/src/sqliteInt.h \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/table.c \
|
||||
$(TOP)/src/threads.c \
|
||||
$(TOP)/src/tclsqlite.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/trigger.c \
|
||||
@@ -459,8 +458,6 @@ HDR = \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_setup.h \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/pcache.h \
|
||||
parse.h \
|
||||
@@ -736,6 +733,9 @@ status.lo: $(TOP)/src/status.c $(HDR)
|
||||
table.lo: $(TOP)/src/table.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/table.c
|
||||
|
||||
threads.lo: $(TOP)/src/threads.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/threads.c
|
||||
|
||||
tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c
|
||||
|
||||
|
||||
+34
-106
@@ -1,9 +1,6 @@
|
||||
#
|
||||
# nmake Makefile for SQLite
|
||||
#
|
||||
###############################################################################
|
||||
############################## START OF OPTIONS ###############################
|
||||
###############################################################################
|
||||
|
||||
# The toplevel directory of the source tree. This is the directory
|
||||
# that contains this "Makefile.msc".
|
||||
@@ -16,13 +13,6 @@ TOP = .
|
||||
USE_AMALGAMATION = 1
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to use the library paths and other options necessary for
|
||||
# Windows Phone 8.1.
|
||||
#
|
||||
!IFNDEF USE_WP81_OPTS
|
||||
USE_WP81_OPTS = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to split the SQLite amalgamation file into chunks to
|
||||
# be used for debugging with Visual Studio.
|
||||
#
|
||||
@@ -126,25 +116,6 @@ DEBUG = 0
|
||||
OPTIMIZATIONS = 2
|
||||
!ENDIF
|
||||
|
||||
# These are the "standard" SQLite compilation options used when compiling for
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
###############################################################################
|
||||
############################### END OF OPTIONS ################################
|
||||
###############################################################################
|
||||
|
||||
# This assumes that MSVC is always installed in 32-bit Program Files directory
|
||||
# and sets the variable for use in locating other 32-bit installs accordingly.
|
||||
#
|
||||
PROGRAMFILES_X86 = $(VCINSTALLDIR)\..\..
|
||||
PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\)
|
||||
|
||||
# Check for the predefined command macro CC. This should point to the compiler
|
||||
# binary for the target platform. If it is not defined, simply define it to
|
||||
# the legacy default value 'cl.exe'.
|
||||
@@ -169,15 +140,6 @@ LD = link.exe
|
||||
RC = rc.exe
|
||||
!ENDIF
|
||||
|
||||
# Check for the MSVC runtime library path macro. Othertise, this value will
|
||||
# default to the 'lib' directory underneath the MSVC installation directory.
|
||||
#
|
||||
!IFNDEF CRTLIBPATH
|
||||
CRTLIBPATH = $(VCINSTALLDIR)\lib
|
||||
!ENDIF
|
||||
|
||||
CRTLIBPATH = $(CRTLIBPATH:\\=\)
|
||||
|
||||
# Check for the command macro NCC. This should point to the compiler binary
|
||||
# for the platform the compilation process is taking place on. If it is not
|
||||
# defined, simply define it to have the same value as the CC macro. When
|
||||
@@ -206,8 +168,8 @@ NCC = $(NCC:\\=\)
|
||||
NCC = $(CC)
|
||||
!ENDIF
|
||||
|
||||
# Check for the MSVC native runtime library path macro. Othertise,
|
||||
# this value will default to the 'lib' directory underneath the MSVC
|
||||
# Check for the MSVC runtime library path macro. Othertise, this
|
||||
# value will default to the 'lib' directory underneath the MSVC
|
||||
# installation directory.
|
||||
#
|
||||
!IFNDEF NCRTLIBPATH
|
||||
@@ -344,6 +306,7 @@ TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
|
||||
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
|
||||
!ENDIF
|
||||
|
||||
#
|
||||
# Prevent warnings about "insecure" MSVC runtime library functions
|
||||
# being used.
|
||||
#
|
||||
@@ -351,24 +314,28 @@ TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
|
||||
BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
|
||||
RCC = $(RCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#
|
||||
# Prevent warnings about "deprecated" POSIX functions being used.
|
||||
#
|
||||
TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
|
||||
BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
|
||||
RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
|
||||
|
||||
#
|
||||
# Use the SQLite debugging heap subsystem?
|
||||
#
|
||||
!IF $(MEMDEBUG)!=0
|
||||
TCC = $(TCC) -DSQLITE_MEMDEBUG=1
|
||||
RCC = $(RCC) -DSQLITE_MEMDEBUG=1
|
||||
|
||||
#
|
||||
# Use native Win32 heap subsystem instead of malloc/free?
|
||||
#
|
||||
!ELSEIF $(WIN32HEAP)!=0
|
||||
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
|
||||
RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
|
||||
|
||||
#
|
||||
# Validate the heap on every call into the native Win32 heap subsystem?
|
||||
#
|
||||
!IF $(DEBUG)>2
|
||||
@@ -463,25 +430,25 @@ RCC = $(RCC) -DSQLITE_TEMP_STORE=1
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
# LEMON parser generator and the mkkeywordhash tool as well.
|
||||
|
||||
# These are the required SQLite compilation options used when compiling for
|
||||
# the Windows platform.
|
||||
#
|
||||
REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
|
||||
# BEGIN standard options
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
# END standard options
|
||||
|
||||
# Add the required and optional SQLite compilation options into the command
|
||||
# lines used to invoke the MSVC code and resource compilers.
|
||||
#
|
||||
TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS)
|
||||
RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS)
|
||||
# BEGIN required Windows option
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
|
||||
# END required Windows option
|
||||
|
||||
# Add in any optional parameters specified on the commane line, e.g.
|
||||
# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
|
||||
#
|
||||
TCC = $(TCC) $(OPT_FEATURE_FLAGS)
|
||||
RCC = $(RCC) $(OPT_FEATURE_FLAGS)
|
||||
|
||||
# Add in any optional parameters specified on the make commane line
|
||||
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
|
||||
TCC = $(TCC) $(OPTS)
|
||||
RCC = $(RCC) $(OPTS)
|
||||
|
||||
# If compiling for debugging, add some defines.
|
||||
#
|
||||
!IF $(DEBUG)>0
|
||||
TCC = $(TCC) -D_DEBUG
|
||||
BCC = $(BCC) -D_DEBUG
|
||||
@@ -490,7 +457,6 @@ RCC = $(RCC) -D_DEBUG
|
||||
|
||||
# If optimizations are enabled or disabled (either implicitly or
|
||||
# explicitly), add the necessary flags.
|
||||
#
|
||||
!IF $(DEBUG)>0 || $(OPTIMIZATIONS)==0
|
||||
TCC = $(TCC) -Od
|
||||
BCC = $(BCC) -Od
|
||||
@@ -506,14 +472,12 @@ BCC = $(BCC) -O1
|
||||
!ENDIF
|
||||
|
||||
# If symbols are enabled (or compiling for debugging), enable PDBs.
|
||||
#
|
||||
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
|
||||
TCC = $(TCC) -Zi
|
||||
BCC = $(BCC) -Zi
|
||||
!ENDIF
|
||||
|
||||
# If ICU support is enabled, add the compiler options for it.
|
||||
#
|
||||
!IF $(USE_ICU)!=0
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_ICU=1
|
||||
RCC = $(RCC) -DSQLITE_ENABLE_ICU=1
|
||||
@@ -525,7 +489,6 @@ RCC = $(RCC) -I$(ICUINCDIR)
|
||||
|
||||
# Command line prefixes for compiling code, compiling resources,
|
||||
# linking, etc.
|
||||
#
|
||||
LTCOMPILE = $(TCC) -Fo$@
|
||||
LTRCOMPILE = $(RCC) -r
|
||||
LTLIB = lib.exe
|
||||
@@ -547,71 +510,36 @@ LTLIBOPTS = /MACHINE:$(PLATFORM)
|
||||
!IF $(FOR_WINRT)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
|
||||
!IF "$(VISUALSTUDIOVERSION)"=="12.0"
|
||||
!IFNDEF STORELIBPATH
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
STORELIBPATH = $(CRTLIBPATH)\store
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store"
|
||||
!ELSEIF "$(PLATFORM)"=="x64"
|
||||
STORELIBPATH = $(CRTLIBPATH)\store\amd64
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store\amd64"
|
||||
!ELSEIF "$(PLATFORM)"=="ARM"
|
||||
STORELIBPATH = $(CRTLIBPATH)\store\arm
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store\arm"
|
||||
!ELSE
|
||||
STORELIBPATH = $(CRTLIBPATH)\store
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store"
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
STORELIBPATH = $(STORELIBPATH:\\=\)
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(STORELIBPATH)"
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# When compiling for Windows Phone 8.1, an extra library path is
|
||||
# required.
|
||||
#
|
||||
!IF $(USE_WP81_OPTS)!=0
|
||||
!IFNDEF WP81LIBPATH
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
|
||||
!ELSEIF "$(PLATFORM)"=="ARM"
|
||||
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\ARM
|
||||
!ELSE
|
||||
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# When compiling for Windows Phone 8.1, some extra linker options
|
||||
# are also required.
|
||||
#
|
||||
!IF $(USE_WP81_OPTS)!=0
|
||||
!IFDEF WP81LIBPATH
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(WP81LIBPATH)"
|
||||
!ENDIF
|
||||
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE
|
||||
LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib
|
||||
LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
|
||||
!ENDIF
|
||||
|
||||
# If either debugging or symbols are enabled, enable PDBs.
|
||||
#
|
||||
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
|
||||
LDFLAGS = /DEBUG
|
||||
!ENDIF
|
||||
|
||||
# Start with the Tcl related linker options.
|
||||
#
|
||||
!IF $(NO_TCL)==0
|
||||
LTLIBPATHS = /LIBPATH:$(TCLLIBDIR)
|
||||
LTLIBS = $(LIBTCL)
|
||||
!ENDIF
|
||||
|
||||
# If ICU support is enabled, add the linker options for it.
|
||||
#
|
||||
!IF $(USE_ICU)!=0
|
||||
LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR)
|
||||
LTLIBS = $(LTLIBS) $(LIBICU)
|
||||
!ENDIF
|
||||
|
||||
# nawk compatible awk.
|
||||
#
|
||||
!IFNDEF NAWK
|
||||
NAWK = gawk.exe
|
||||
!ENDIF
|
||||
@@ -636,7 +564,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
|
||||
table.lo tokenize.lo trigger.lo \
|
||||
table.lo threads.lo tokenize.lo trigger.lo \
|
||||
update.lo util.lo vacuum.lo \
|
||||
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
|
||||
@@ -709,10 +637,8 @@ SRC = \
|
||||
$(TOP)\src\os.c \
|
||||
$(TOP)\src\os.h \
|
||||
$(TOP)\src\os_common.h \
|
||||
$(TOP)\src\os_setup.h \
|
||||
$(TOP)\src\os_unix.c \
|
||||
$(TOP)\src\os_win.c \
|
||||
$(TOP)\src\os_win.h \
|
||||
$(TOP)\src\pager.c \
|
||||
$(TOP)\src\pager.h \
|
||||
$(TOP)\src\parse.y \
|
||||
@@ -733,6 +659,7 @@ SRC = \
|
||||
$(TOP)\src\sqliteInt.h \
|
||||
$(TOP)\src\sqliteLimit.h \
|
||||
$(TOP)\src\table.c \
|
||||
$(TOP)\src\threads.c \
|
||||
$(TOP)\src\tclsqlite.c \
|
||||
$(TOP)\src\tokenize.c \
|
||||
$(TOP)\src\trigger.c \
|
||||
@@ -932,8 +859,6 @@ HDR = \
|
||||
opcodes.h \
|
||||
$(TOP)\src\os.h \
|
||||
$(TOP)\src\os_common.h \
|
||||
$(TOP)\src\os_setup.h \
|
||||
$(TOP)\src\os_win.h \
|
||||
$(TOP)\src\pager.h \
|
||||
$(TOP)\src\pcache.h \
|
||||
parse.h \
|
||||
@@ -1030,7 +955,7 @@ lempar.c: $(TOP)\src\lempar.c
|
||||
copy $(TOP)\src\lempar.c .
|
||||
|
||||
lemon.exe: $(TOP)\tool\lemon.c lempar.c
|
||||
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLIBPATHS)
|
||||
|
||||
# Rules to build individual *.lo files from generated *.c files. This
|
||||
# applies to:
|
||||
@@ -1215,6 +1140,9 @@ status.lo: $(TOP)\src\status.c $(HDR)
|
||||
table.lo: $(TOP)\src\table.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\table.c
|
||||
|
||||
threads.lo: $(TOP)\src\threads.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\threads.c
|
||||
|
||||
tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\tokenize.c
|
||||
|
||||
@@ -1290,7 +1218,7 @@ parse.h: parse.c
|
||||
parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk
|
||||
del /Q parse.y parse.h parse.h.temp
|
||||
copy $(TOP)\src\parse.y .
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
|
||||
.\lemon.exe $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
|
||||
move parse.h parse.h.temp
|
||||
$(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h
|
||||
|
||||
@@ -1298,7 +1226,7 @@ sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h
|
||||
|
||||
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
|
||||
$(BCC) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
$(BCC) -Fe$@ $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLIBPATHS)
|
||||
|
||||
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
.\mkkeywordhash.exe > keywordhash.h
|
||||
@@ -1446,8 +1374,8 @@ clean:
|
||||
del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
|
||||
del /Q *.cod *.da *.bb *.bbg gmon.out
|
||||
del /Q sqlite3.h opcodes.c opcodes.h
|
||||
del /Q lemon.* lempar.c parse.*
|
||||
del /Q mkkeywordhash.* keywordhash.h
|
||||
del /Q lemon.exe lempar.c parse.*
|
||||
del /Q mkkeywordhash.exe keywordhash.h
|
||||
del /Q notasharedlib.*
|
||||
-rmdir /Q/S .deps
|
||||
-rmdir /Q/S .libs
|
||||
|
||||
@@ -262,10 +262,8 @@ SRC = \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_setup.h \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/parse.y \
|
||||
@@ -418,8 +416,6 @@ HDR = \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_setup.h \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/pcache.h \
|
||||
parse.h \
|
||||
|
||||
+4
-9
@@ -1333,7 +1333,7 @@ static int fts3InitVtab(
|
||||
p->bHasStat = isFts4;
|
||||
p->bFts4 = isFts4;
|
||||
p->bDescIdx = bDescIdx;
|
||||
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
|
||||
p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */
|
||||
p->zContentTbl = zContent;
|
||||
p->zLanguageid = zLanguageid;
|
||||
zContent = 0;
|
||||
@@ -1376,9 +1376,7 @@ static int fts3InitVtab(
|
||||
int n = (int)strlen(p->azColumn[iCol]);
|
||||
for(i=0; i<nNotindexed; i++){
|
||||
char *zNot = azNotindexed[i];
|
||||
if( zNot && n==(int)strlen(zNot)
|
||||
&& 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n)
|
||||
){
|
||||
if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){
|
||||
p->abNotindexed[iCol] = 1;
|
||||
sqlite3_free(zNot);
|
||||
azNotindexed[i] = 0;
|
||||
@@ -3304,10 +3302,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
||||
Fts3Table *p = (Fts3Table*)pVtab;
|
||||
int rc = sqlite3Fts3PendingTermsFlush(p);
|
||||
|
||||
if( rc==SQLITE_OK
|
||||
&& p->nLeafAdd>(nMinMerge/16)
|
||||
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
|
||||
){
|
||||
if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){
|
||||
int mxLevel = 0; /* Maximum relative level value in db */
|
||||
int A; /* Incr-merge parameter A */
|
||||
|
||||
@@ -3315,7 +3310,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
||||
assert( rc==SQLITE_OK || mxLevel==0 );
|
||||
A = p->nLeafAdd * mxLevel;
|
||||
A += (A/2);
|
||||
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
|
||||
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
|
||||
}
|
||||
sqlite3Fts3SegmentsClose(p);
|
||||
return rc;
|
||||
|
||||
+2
-2
@@ -210,13 +210,13 @@ struct Fts3Table {
|
||||
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
|
||||
char *zContentTbl; /* content=xxx option, or NULL */
|
||||
char *zLanguageid; /* languageid=xxx option, or NULL */
|
||||
int nAutoincrmerge; /* Value configured by 'automerge' */
|
||||
u8 bAutoincrmerge; /* True if automerge=1 */
|
||||
u32 nLeafAdd; /* Number of leaf blocks added this trans */
|
||||
|
||||
/* Precompiled statements used by the implementation. Each of these
|
||||
** statements is run and reset within a single virtual table API call.
|
||||
*/
|
||||
sqlite3_stmt *aStmt[40];
|
||||
sqlite3_stmt *aStmt[37];
|
||||
|
||||
char *zReadExprlist;
|
||||
char *zWriteExprlist;
|
||||
|
||||
+102
-105
@@ -185,23 +185,40 @@ static int getNextToken(
|
||||
int rc;
|
||||
sqlite3_tokenizer_cursor *pCursor;
|
||||
Fts3Expr *pRet = 0;
|
||||
int i = 0;
|
||||
int nConsumed = 0;
|
||||
|
||||
/* Set variable i to the maximum number of bytes of input to tokenize. */
|
||||
for(i=0; i<n; i++){
|
||||
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
|
||||
if( z[i]=='*' || z[i]=='"' ) break;
|
||||
}
|
||||
|
||||
*pnConsumed = i;
|
||||
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
|
||||
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zToken;
|
||||
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
|
||||
int nByte; /* total space to allocate */
|
||||
|
||||
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
if( (rc==SQLITE_OK || rc==SQLITE_DONE) && sqlite3_fts3_enable_parentheses ){
|
||||
int i;
|
||||
if( rc==SQLITE_DONE ) iStart = n;
|
||||
for(i=0; i<iStart; i++){
|
||||
if( z[i]=='(' ){
|
||||
pParse->nNest++;
|
||||
rc = fts3ExprParse(pParse, &z[i+1], n-i-1, &pRet, &nConsumed);
|
||||
if( rc==SQLITE_OK && !pRet ){
|
||||
rc = SQLITE_DONE;
|
||||
}
|
||||
nConsumed = (int)(i + 1 + nConsumed);
|
||||
break;
|
||||
}
|
||||
|
||||
if( z[i]==')' ){
|
||||
rc = SQLITE_DONE;
|
||||
pParse->nNest--;
|
||||
nConsumed = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( nConsumed==0 && rc==SQLITE_OK ){
|
||||
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
|
||||
pRet = (Fts3Expr *)fts3MallocZero(nByte);
|
||||
if( !pRet ){
|
||||
@@ -235,14 +252,13 @@ static int getNextToken(
|
||||
}
|
||||
|
||||
}
|
||||
*pnConsumed = iEnd;
|
||||
}else if( i && rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
nConsumed = iEnd;
|
||||
}
|
||||
|
||||
pModule->xClose(pCursor);
|
||||
}
|
||||
|
||||
*pnConsumed = nConsumed;
|
||||
*ppExpr = pRet;
|
||||
return rc;
|
||||
}
|
||||
@@ -492,21 +508,6 @@ static int getNextNode(
|
||||
return getNextString(pParse, &zInput[1], ii-1, ppExpr);
|
||||
}
|
||||
|
||||
if( sqlite3_fts3_enable_parentheses ){
|
||||
if( *zInput=='(' ){
|
||||
int nConsumed = 0;
|
||||
pParse->nNest++;
|
||||
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
|
||||
if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
|
||||
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
|
||||
return rc;
|
||||
}else if( *zInput==')' ){
|
||||
pParse->nNest--;
|
||||
*pnConsumed = (int)((zInput - z) + 1);
|
||||
*ppExpr = 0;
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If control flows to this point, this must be a regular token, or
|
||||
** the end of the input. Read a regular token using the sqlite3_tokenizer
|
||||
@@ -625,100 +626,96 @@ static int fts3ExprParse(
|
||||
while( rc==SQLITE_OK ){
|
||||
Fts3Expr *p = 0;
|
||||
int nByte = 0;
|
||||
|
||||
rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
|
||||
assert( nByte>0 || (rc!=SQLITE_OK && p==0) );
|
||||
if( rc==SQLITE_OK ){
|
||||
if( p ){
|
||||
int isPhrase;
|
||||
int isPhrase;
|
||||
|
||||
if( !sqlite3_fts3_enable_parentheses
|
||||
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
|
||||
){
|
||||
/* Create an implicit NOT operator. */
|
||||
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pNot ){
|
||||
if( !sqlite3_fts3_enable_parentheses
|
||||
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
|
||||
){
|
||||
/* Create an implicit NOT operator. */
|
||||
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pNot ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
goto exprparse_out;
|
||||
}
|
||||
pNot->eType = FTSQUERY_NOT;
|
||||
pNot->pRight = p;
|
||||
p->pParent = pNot;
|
||||
if( pNotBranch ){
|
||||
pNot->pLeft = pNotBranch;
|
||||
pNotBranch->pParent = pNot;
|
||||
}
|
||||
pNotBranch = pNot;
|
||||
p = pPrev;
|
||||
}else{
|
||||
int eType = p->eType;
|
||||
isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
|
||||
|
||||
/* The isRequirePhrase variable is set to true if a phrase or
|
||||
** an expression contained in parenthesis is required. If a
|
||||
** binary operator (AND, OR, NOT or NEAR) is encounted when
|
||||
** isRequirePhrase is set, this is a syntax error.
|
||||
*/
|
||||
if( !isPhrase && isRequirePhrase ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_ERROR;
|
||||
goto exprparse_out;
|
||||
}
|
||||
|
||||
if( isPhrase && !isRequirePhrase ){
|
||||
/* Insert an implicit AND operator. */
|
||||
Fts3Expr *pAnd;
|
||||
assert( pRet && pPrev );
|
||||
pAnd = fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pAnd ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
goto exprparse_out;
|
||||
}
|
||||
pNot->eType = FTSQUERY_NOT;
|
||||
pNot->pRight = p;
|
||||
p->pParent = pNot;
|
||||
if( pNotBranch ){
|
||||
pNot->pLeft = pNotBranch;
|
||||
pNotBranch->pParent = pNot;
|
||||
}
|
||||
pNotBranch = pNot;
|
||||
p = pPrev;
|
||||
}else{
|
||||
int eType = p->eType;
|
||||
isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
|
||||
pAnd->eType = FTSQUERY_AND;
|
||||
insertBinaryOperator(&pRet, pPrev, pAnd);
|
||||
pPrev = pAnd;
|
||||
}
|
||||
|
||||
/* The isRequirePhrase variable is set to true if a phrase or
|
||||
** an expression contained in parenthesis is required. If a
|
||||
** binary operator (AND, OR, NOT or NEAR) is encounted when
|
||||
** isRequirePhrase is set, this is a syntax error.
|
||||
*/
|
||||
if( !isPhrase && isRequirePhrase ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_ERROR;
|
||||
goto exprparse_out;
|
||||
}
|
||||
|
||||
if( isPhrase && !isRequirePhrase ){
|
||||
/* Insert an implicit AND operator. */
|
||||
Fts3Expr *pAnd;
|
||||
assert( pRet && pPrev );
|
||||
pAnd = fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pAnd ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
goto exprparse_out;
|
||||
}
|
||||
pAnd->eType = FTSQUERY_AND;
|
||||
insertBinaryOperator(&pRet, pPrev, pAnd);
|
||||
pPrev = pAnd;
|
||||
}
|
||||
|
||||
/* This test catches attempts to make either operand of a NEAR
|
||||
** operator something other than a phrase. For example, either of
|
||||
** the following:
|
||||
**
|
||||
** (bracketed expression) NEAR phrase
|
||||
** phrase NEAR (bracketed expression)
|
||||
**
|
||||
** Return an error in either case.
|
||||
*/
|
||||
if( pPrev && (
|
||||
/* This test catches attempts to make either operand of a NEAR
|
||||
** operator something other than a phrase. For example, either of
|
||||
** the following:
|
||||
**
|
||||
** (bracketed expression) NEAR phrase
|
||||
** phrase NEAR (bracketed expression)
|
||||
**
|
||||
** Return an error in either case.
|
||||
*/
|
||||
if( pPrev && (
|
||||
(eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE)
|
||||
|| (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR)
|
||||
)){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_ERROR;
|
||||
goto exprparse_out;
|
||||
}
|
||||
|
||||
if( isPhrase ){
|
||||
if( pRet ){
|
||||
assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
|
||||
pPrev->pRight = p;
|
||||
p->pParent = pPrev;
|
||||
}else{
|
||||
pRet = p;
|
||||
}
|
||||
}else{
|
||||
insertBinaryOperator(&pRet, pPrev, p);
|
||||
}
|
||||
isRequirePhrase = !isPhrase;
|
||||
)){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_ERROR;
|
||||
goto exprparse_out;
|
||||
}
|
||||
pPrev = p;
|
||||
|
||||
if( isPhrase ){
|
||||
if( pRet ){
|
||||
assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
|
||||
pPrev->pRight = p;
|
||||
p->pParent = pPrev;
|
||||
}else{
|
||||
pRet = p;
|
||||
}
|
||||
}else{
|
||||
insertBinaryOperator(&pRet, pPrev, p);
|
||||
}
|
||||
isRequirePhrase = !isPhrase;
|
||||
}
|
||||
assert( nByte>0 );
|
||||
}
|
||||
assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) );
|
||||
nIn -= nByte;
|
||||
zIn += nByte;
|
||||
pPrev = p;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_DONE && pRet && isRequirePhrase ){
|
||||
|
||||
+35
-270
@@ -193,7 +193,6 @@ struct SegmentWriter {
|
||||
int nSize; /* Size of allocation at aData */
|
||||
int nData; /* Bytes of data in aData */
|
||||
char *aData; /* Pointer to block from malloc() */
|
||||
i64 nLeafData; /* Number of bytes of leaf data written */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -269,10 +268,6 @@ struct SegmentNode {
|
||||
#define SQL_SELECT_INDEXES 35
|
||||
#define SQL_SELECT_MXLEVEL 36
|
||||
|
||||
#define SQL_SELECT_LEVEL_RANGE2 37
|
||||
#define SQL_UPDATE_LEVEL_IDX 38
|
||||
#define SQL_UPDATE_LEVEL 39
|
||||
|
||||
/*
|
||||
** This function is used to obtain an SQLite prepared statement handle
|
||||
** for the statement identified by the second argument. If successful,
|
||||
@@ -374,18 +369,7 @@ static int fts3SqlStmt(
|
||||
|
||||
/* SQL_SELECT_MXLEVEL
|
||||
** Return the largest relative level in the FTS index or indexes. */
|
||||
/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'",
|
||||
|
||||
/* Return segments in order from oldest to newest.*/
|
||||
/* 37 */ "SELECT level, idx, end_block "
|
||||
"FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? "
|
||||
"ORDER BY level DESC, idx ASC",
|
||||
|
||||
/* Update statements used while promoting segments */
|
||||
/* 38 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=-1,idx=? "
|
||||
"WHERE level=? AND idx=?",
|
||||
/* 39 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=? WHERE level=-1"
|
||||
|
||||
/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'"
|
||||
};
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt *pStmt;
|
||||
@@ -1926,7 +1910,6 @@ static int fts3WriteSegdir(
|
||||
sqlite3_int64 iStartBlock, /* Value for "start_block" field */
|
||||
sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
|
||||
sqlite3_int64 iEndBlock, /* Value for "end_block" field */
|
||||
sqlite3_int64 nLeafData, /* Bytes of leaf data in segment */
|
||||
char *zRoot, /* Blob value for "root" field */
|
||||
int nRoot /* Number of bytes in buffer zRoot */
|
||||
){
|
||||
@@ -1937,13 +1920,7 @@ static int fts3WriteSegdir(
|
||||
sqlite3_bind_int(pStmt, 2, iIdx);
|
||||
sqlite3_bind_int64(pStmt, 3, iStartBlock);
|
||||
sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
|
||||
if( nLeafData==0 ){
|
||||
sqlite3_bind_int64(pStmt, 5, iEndBlock);
|
||||
}else{
|
||||
char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData);
|
||||
if( !zEnd ) return SQLITE_NOMEM;
|
||||
sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free);
|
||||
}
|
||||
sqlite3_bind_int64(pStmt, 5, iEndBlock);
|
||||
sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_reset(pStmt);
|
||||
@@ -2269,9 +2246,6 @@ static int fts3SegWriterAdd(
|
||||
nDoclist; /* Doclist data */
|
||||
}
|
||||
|
||||
/* Increase the total number of bytes written to account for the new entry. */
|
||||
pWriter->nLeafData += nReq;
|
||||
|
||||
/* If the buffer currently allocated is too small for this entry, realloc
|
||||
** the buffer to make it large enough.
|
||||
*/
|
||||
@@ -2343,13 +2317,13 @@ static int fts3SegWriterFlush(
|
||||
pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3WriteSegdir(p, iLevel, iIdx,
|
||||
pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot);
|
||||
rc = fts3WriteSegdir(
|
||||
p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot);
|
||||
}
|
||||
}else{
|
||||
/* The entire tree fits on the root node. Write it to the segdir table. */
|
||||
rc = fts3WriteSegdir(p, iLevel, iIdx,
|
||||
0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData);
|
||||
rc = fts3WriteSegdir(
|
||||
p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
|
||||
}
|
||||
p->nLeafAdd++;
|
||||
return rc;
|
||||
@@ -2433,37 +2407,6 @@ static int fts3SegmentMaxLevel(
|
||||
return sqlite3_reset(pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** iAbsLevel is an absolute level that may be assumed to exist within
|
||||
** the database. This function checks if it is the largest level number
|
||||
** within its index. Assuming no error occurs, *pbMax is set to 1 if
|
||||
** iAbsLevel is indeed the largest level, or 0 otherwise, and SQLITE_OK
|
||||
** is returned. If an error occurs, an error code is returned and the
|
||||
** final value of *pbMax is undefined.
|
||||
*/
|
||||
static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){
|
||||
|
||||
/* Set pStmt to the compiled version of:
|
||||
**
|
||||
** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
|
||||
**
|
||||
** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
|
||||
*/
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
|
||||
sqlite3_bind_int64(pStmt, 2,
|
||||
((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
|
||||
);
|
||||
|
||||
*pbMax = 0;
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
*pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL;
|
||||
}
|
||||
return sqlite3_reset(pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete all entries in the %_segments table associated with the segment
|
||||
** opened with seg-reader pSeg. This function does not affect the contents
|
||||
@@ -2999,140 +2942,6 @@ void sqlite3Fts3SegReaderFinish(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Decode the "end_block" field, selected by column iCol of the SELECT
|
||||
** statement passed as the first argument.
|
||||
**
|
||||
** The "end_block" field may contain either an integer, or a text field
|
||||
** containing the text representation of two non-negative integers separated
|
||||
** by one or more space (0x20) characters. In the first case, set *piEndBlock
|
||||
** to the integer value and *pnByte to zero before returning. In the second,
|
||||
** set *piEndBlock to the first value and *pnByte to the second.
|
||||
*/
|
||||
static void fts3ReadEndBlockField(
|
||||
sqlite3_stmt *pStmt,
|
||||
int iCol,
|
||||
i64 *piEndBlock,
|
||||
i64 *pnByte
|
||||
){
|
||||
const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
|
||||
if( zText ){
|
||||
int i;
|
||||
int iMul = 1;
|
||||
i64 iVal = 0;
|
||||
for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
|
||||
iVal = iVal*10 + (zText[i] - '0');
|
||||
}
|
||||
*piEndBlock = iVal;
|
||||
while( zText[i]==' ' ) i++;
|
||||
iVal = 0;
|
||||
if( zText[i]=='-' ){
|
||||
i++;
|
||||
iMul = -1;
|
||||
}
|
||||
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
|
||||
iVal = iVal*10 + (zText[i] - '0');
|
||||
}
|
||||
*pnByte = (iVal * (i64)iMul);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** A segment of size nByte bytes has just been written to absolute level
|
||||
** iAbsLevel. Promote any segments that should be promoted as a result.
|
||||
*/
|
||||
static int fts3PromoteSegments(
|
||||
Fts3Table *p, /* FTS table handle */
|
||||
sqlite3_int64 iAbsLevel, /* Absolute level just updated */
|
||||
sqlite3_int64 nByte /* Size of new segment at iAbsLevel */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt *pRange;
|
||||
|
||||
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE2, &pRange, 0);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
int bOk = 0;
|
||||
i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1;
|
||||
i64 nLimit = (nByte*3)/2;
|
||||
|
||||
/* Loop through all entries in the %_segdir table corresponding to
|
||||
** segments in this index on levels greater than iAbsLevel. If there is
|
||||
** at least one such segment, and it is possible to determine that all
|
||||
** such segments are smaller than nLimit bytes in size, they will be
|
||||
** promoted to level iAbsLevel. */
|
||||
sqlite3_bind_int64(pRange, 1, iAbsLevel+1);
|
||||
sqlite3_bind_int64(pRange, 2, iLast);
|
||||
while( SQLITE_ROW==sqlite3_step(pRange) ){
|
||||
i64 nSize = 0, dummy;
|
||||
fts3ReadEndBlockField(pRange, 2, &dummy, &nSize);
|
||||
if( nSize<=0 || nSize>nLimit ){
|
||||
/* If nSize==0, then the %_segdir.end_block field does not not
|
||||
** contain a size value. This happens if it was written by an
|
||||
** old version of FTS. In this case it is not possible to determine
|
||||
** the size of the segment, and so segment promotion does not
|
||||
** take place. */
|
||||
bOk = 0;
|
||||
break;
|
||||
}
|
||||
bOk = 1;
|
||||
}
|
||||
rc = sqlite3_reset(pRange);
|
||||
|
||||
if( bOk ){
|
||||
int iIdx = 0;
|
||||
sqlite3_stmt *pUpdate1;
|
||||
sqlite3_stmt *pUpdate2;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
/* Loop through all %_segdir entries for segments in this index with
|
||||
** levels equal to or greater than iAbsLevel. As each entry is visited,
|
||||
** updated it to set (level = -1) and (idx = N), where N is 0 for the
|
||||
** oldest segment in the range, 1 for the next oldest, and so on.
|
||||
**
|
||||
** In other words, move all segments being promoted to level -1,
|
||||
** setting the "idx" fields as appropriate to keep them in the same
|
||||
** order. The contents of level -1 (which is never used, except
|
||||
** transiently here), will be moved back to level iAbsLevel below. */
|
||||
sqlite3_bind_int64(pRange, 1, iAbsLevel);
|
||||
while( SQLITE_ROW==sqlite3_step(pRange) ){
|
||||
sqlite3_bind_int(pUpdate1, 1, iIdx++);
|
||||
sqlite3_bind_int(pUpdate1, 2, sqlite3_column_int(pRange, 0));
|
||||
sqlite3_bind_int(pUpdate1, 3, sqlite3_column_int(pRange, 1));
|
||||
sqlite3_step(pUpdate1);
|
||||
rc = sqlite3_reset(pUpdate1);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_reset(pRange);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_reset(pRange);
|
||||
}
|
||||
|
||||
/* Move level -1 to level iAbsLevel */
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pUpdate2, 1, iAbsLevel);
|
||||
sqlite3_step(pUpdate2);
|
||||
rc = sqlite3_reset(pUpdate2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Merge all level iLevel segments in the database into a single
|
||||
** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
|
||||
@@ -3157,7 +2966,6 @@ static int fts3SegmentMerge(
|
||||
Fts3SegFilter filter; /* Segment term filter condition */
|
||||
Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
|
||||
int bIgnoreEmpty = 0; /* True to ignore empty segments */
|
||||
i64 iMaxLevel = 0; /* Max level number for this index/langid */
|
||||
|
||||
assert( iLevel==FTS3_SEGCURSOR_ALL
|
||||
|| iLevel==FTS3_SEGCURSOR_PENDING
|
||||
@@ -3169,11 +2977,6 @@ static int fts3SegmentMerge(
|
||||
rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr);
|
||||
if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
|
||||
|
||||
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
|
||||
rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iMaxLevel);
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
}
|
||||
|
||||
if( iLevel==FTS3_SEGCURSOR_ALL ){
|
||||
/* This call is to merge all segments in the database to a single
|
||||
** segment. The level of the new segment is equal to the numerically
|
||||
@@ -3183,21 +2986,21 @@ static int fts3SegmentMerge(
|
||||
rc = SQLITE_DONE;
|
||||
goto finished;
|
||||
}
|
||||
iNewLevel = iMaxLevel;
|
||||
rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel);
|
||||
bIgnoreEmpty = 1;
|
||||
|
||||
}else if( iLevel==FTS3_SEGCURSOR_PENDING ){
|
||||
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0);
|
||||
rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx);
|
||||
}else{
|
||||
/* This call is to merge all segments at level iLevel. find the next
|
||||
** available segment index at level iLevel+1. The call to
|
||||
** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
|
||||
** a single iLevel+2 segment if necessary. */
|
||||
assert( FTS3_SEGCURSOR_PENDING==-1 );
|
||||
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
|
||||
rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
|
||||
bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel);
|
||||
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
|
||||
assert( csr.nSegment>0 );
|
||||
assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
|
||||
assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
|
||||
@@ -3214,7 +3017,7 @@ static int fts3SegmentMerge(
|
||||
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
assert( pWriter || bIgnoreEmpty );
|
||||
assert( pWriter );
|
||||
|
||||
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
|
||||
rc = fts3DeleteSegdir(
|
||||
@@ -3222,14 +3025,7 @@ static int fts3SegmentMerge(
|
||||
);
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
}
|
||||
if( pWriter ){
|
||||
rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( iLevel==FTS3_SEGCURSOR_PENDING || iNewLevel<iMaxLevel ){
|
||||
rc = fts3PromoteSegments(p, iNewLevel, pWriter->nLeafData);
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
|
||||
|
||||
finished:
|
||||
fts3SegWriterFree(pWriter);
|
||||
@@ -3239,7 +3035,7 @@ static int fts3SegmentMerge(
|
||||
|
||||
|
||||
/*
|
||||
** Flush the contents of pendingTerms to level 0 segments.
|
||||
** Flush the contents of pendingTerms to level 0 segments.
|
||||
*/
|
||||
int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
|
||||
int rc = SQLITE_OK;
|
||||
@@ -3255,19 +3051,14 @@ int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
|
||||
** estimate the number of leaf blocks of content to be written
|
||||
*/
|
||||
if( rc==SQLITE_OK && p->bHasStat
|
||||
&& p->nAutoincrmerge==0xff && p->nLeafAdd>0
|
||||
&& p->bAutoincrmerge==0xff && p->nLeafAdd>0
|
||||
){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
p->nAutoincrmerge = sqlite3_column_int(pStmt, 0);
|
||||
if( p->nAutoincrmerge==1 ) p->nAutoincrmerge = 8;
|
||||
}else if( rc==SQLITE_DONE ){
|
||||
p->nAutoincrmerge = 0;
|
||||
}
|
||||
p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0));
|
||||
rc = sqlite3_reset(pStmt);
|
||||
}
|
||||
}
|
||||
@@ -3635,8 +3426,6 @@ struct IncrmergeWriter {
|
||||
int iIdx; /* Index of *output* segment in iAbsLevel+1 */
|
||||
sqlite3_int64 iStart; /* Block number of first allocated block */
|
||||
sqlite3_int64 iEnd; /* Block number of last allocated block */
|
||||
sqlite3_int64 nLeafData; /* Bytes of leaf page data so far */
|
||||
u8 bNoLeafData; /* If true, store 0 for segment size */
|
||||
NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
|
||||
};
|
||||
|
||||
@@ -3975,8 +3764,8 @@ static int fts3IncrmergeAppend(
|
||||
nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
|
||||
}
|
||||
|
||||
pWriter->nLeafData += nSpace;
|
||||
blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pLeaf->block.n==0 ){
|
||||
pLeaf->block.n = 1;
|
||||
@@ -4075,7 +3864,6 @@ static void fts3IncrmergeRelease(
|
||||
pWriter->iStart, /* start_block */
|
||||
pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */
|
||||
pWriter->iEnd, /* end_block */
|
||||
(pWriter->bNoLeafData==0 ? pWriter->nLeafData : 0), /* end_block */
|
||||
pRoot->block.a, pRoot->block.n /* root */
|
||||
);
|
||||
}
|
||||
@@ -4177,11 +3965,7 @@ static int fts3IncrmergeLoad(
|
||||
if( sqlite3_step(pSelect)==SQLITE_ROW ){
|
||||
iStart = sqlite3_column_int64(pSelect, 1);
|
||||
iLeafEnd = sqlite3_column_int64(pSelect, 2);
|
||||
fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData);
|
||||
if( pWriter->nLeafData<0 ){
|
||||
pWriter->nLeafData = pWriter->nLeafData * -1;
|
||||
}
|
||||
pWriter->bNoLeafData = (pWriter->nLeafData==0);
|
||||
iEnd = sqlite3_column_int64(pSelect, 3);
|
||||
nRoot = sqlite3_column_bytes(pSelect, 4);
|
||||
aRoot = sqlite3_column_blob(pSelect, 4);
|
||||
}else{
|
||||
@@ -4782,11 +4566,11 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
|
||||
/*
|
||||
** Attempt an incremental merge that writes nMerge leaf blocks.
|
||||
**
|
||||
** Incremental merges happen nMin segments at a time. The segments
|
||||
** to be merged are the nMin oldest segments (the ones with the smallest
|
||||
** values for the _segdir.idx field) in the highest level that contains
|
||||
** at least nMin segments. Multiple merges might occur in an attempt to
|
||||
** write the quota of nMerge leaf blocks.
|
||||
** Incremental merges happen nMin segments at a time. The two
|
||||
** segments to be merged are the nMin oldest segments (the ones with
|
||||
** the smallest indexes) in the highest level that contains at least
|
||||
** nMin segments. Multiple merges might occur in an attempt to write the
|
||||
** quota of nMerge leaf blocks.
|
||||
*/
|
||||
int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
int rc; /* Return code */
|
||||
@@ -4811,7 +4595,6 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
|
||||
sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
|
||||
int bUseHint = 0; /* True if attempting to append */
|
||||
int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
|
||||
|
||||
/* Search the %_segdir table for the absolute level with the smallest
|
||||
** relative level number that contains at least nMin segments, if any.
|
||||
@@ -4865,19 +4648,6 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
** to start work on some other level. */
|
||||
memset(pWriter, 0, nAlloc);
|
||||
pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
|
||||
assert( bUseHint==1 || bUseHint==0 );
|
||||
if( iIdx==0 || (bUseHint && iIdx==1) ){
|
||||
int bIgnore = 0;
|
||||
rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore);
|
||||
if( bIgnore ){
|
||||
pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
|
||||
}
|
||||
@@ -4885,12 +4655,16 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
|
||||
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
|
||||
){
|
||||
if( bUseHint && iIdx>0 ){
|
||||
const char *zKey = pCsr->zTerm;
|
||||
int nKey = pCsr->nTerm;
|
||||
rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
|
||||
}else{
|
||||
rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
|
||||
int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
|
||||
rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( bUseHint && iIdx>0 ){
|
||||
const char *zKey = pCsr->zTerm;
|
||||
int nKey = pCsr->nTerm;
|
||||
rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
|
||||
}else{
|
||||
rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pWriter->nLeafEst ){
|
||||
@@ -4912,13 +4686,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
}
|
||||
}
|
||||
|
||||
if( nSeg!=0 ){
|
||||
pWriter->nLeafData = pWriter->nLeafData * -1;
|
||||
}
|
||||
fts3IncrmergeRelease(p, pWriter, &rc);
|
||||
if( nSeg==0 && pWriter->bNoLeafData==0 ){
|
||||
fts3PromoteSegments(p, iAbsLevel+1, pWriter->nLeafData);
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3Fts3SegReaderFinish(pCsr);
|
||||
@@ -5005,10 +4773,7 @@ static int fts3DoAutoincrmerge(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
p->nAutoincrmerge = fts3Getint(&zParam);
|
||||
if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
|
||||
p->nAutoincrmerge = 8;
|
||||
}
|
||||
p->bAutoincrmerge = fts3Getint(&zParam)!=0;
|
||||
if( !p->bHasStat ){
|
||||
assert( p->bFts4==0 );
|
||||
sqlite3Fts3CreateStatTable(&rc, p);
|
||||
@@ -5017,7 +4782,7 @@ static int fts3DoAutoincrmerge(
|
||||
rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
|
||||
if( rc ) return rc;
|
||||
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
|
||||
sqlite3_bind_int(pStmt, 2, p->nAutoincrmerge);
|
||||
sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_reset(pStmt);
|
||||
return rc;
|
||||
|
||||
@@ -66,7 +66,7 @@ LIBOBJ+= vdbe.o parse.o \
|
||||
notify.o opcodes.o os.o os_unix.o os_win.o \
|
||||
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
|
||||
random.o resolve.o rowset.o rtree.o select.o status.o \
|
||||
table.o tokenize.o trigger.o \
|
||||
table.o threads.o tokenize.o trigger.o \
|
||||
update.o util.o vacuum.o \
|
||||
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
|
||||
vdbetrace.o wal.o walker.o where.o utf.o vtab.o
|
||||
@@ -121,10 +121,8 @@ SRC = \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_setup.h \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/parse.y \
|
||||
@@ -146,6 +144,7 @@ SRC = \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/table.c \
|
||||
$(TOP)/src/tclsqlite.c \
|
||||
$(TOP)/src/threads.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/trigger.c \
|
||||
$(TOP)/src/utf.c \
|
||||
@@ -210,7 +209,6 @@ SRC += \
|
||||
$(TOP)/ext/icu/sqliteicu.h \
|
||||
$(TOP)/ext/icu/icu.c
|
||||
SRC += \
|
||||
$(TOP)/ext/rtree/sqlite3rtree.h \
|
||||
$(TOP)/ext/rtree/rtree.h \
|
||||
$(TOP)/ext/rtree/rtree.c
|
||||
|
||||
@@ -314,6 +312,7 @@ TESTSRC2 = \
|
||||
$(TOP)/src/pcache.c \
|
||||
$(TOP)/src/pcache1.c \
|
||||
$(TOP)/src/select.c \
|
||||
$(TOP)/src/threads.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/utf.c \
|
||||
$(TOP)/src/util.c \
|
||||
@@ -342,8 +341,6 @@ HDR = \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_setup.h \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/pcache.h \
|
||||
parse.h \
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
C Add\sextra\schecking\sof\sthe\sdatabase\sextended\serror\scode.
|
||||
D 2014-05-30T16:54:09.869
|
||||
C Fix\sseveral\sharmless\scompiler\swarnings.
|
||||
D 2014-05-09T00:36:06.204
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in dd2b1aba364ff9b05de41086f74407f285c57670
|
||||
F Makefile.in ad0921c4b2780d01868cf69b419a4f102308d125
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 52911c6bfeaf9b40f47ef4615ab66d98ab0f2b3d
|
||||
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
|
||||
F Makefile.msc 7d6981e8e14d8189a2a2f9b4a485f40b2032cb2e
|
||||
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
|
||||
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
|
||||
F VERSION 9f823c026c6a32fc5f84d212a8aae0a221dba45c
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -78,11 +78,11 @@ 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 20bc65862cfcea0a39bb64a819f8fe92a8e144c1
|
||||
F ext/fts3/fts3.c 41b1920b9a8657963f09cb93b208c2671c5568db
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 16cddf2d7b0e5f3681615ae1d8ca0e45fca44918
|
||||
F ext/fts3/fts3Int.h bdeb9015405e8facffb8fc7e09174521a2a780f4
|
||||
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
|
||||
F ext/fts3/fts3_expr.c 351395fad6fcb16ecfc61db0861008a70101330c
|
||||
F ext/fts3/fts3_expr.c 5165c365cb5a035f5be8bb296f7aa3211d43e4ac
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
|
||||
@@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c 92391b4b4fb043564c6539ea9b8661e3bcba47b9
|
||||
F ext/fts3/fts3_unicode2.c 0113d3acf13429e6dc38e0647d1bc71211c31a4d
|
||||
F ext/fts3/fts3_write.c 5ee9d894da74a5d15a3c317414fb8c84f1694fa4
|
||||
F ext/fts3/fts3_write.c 74c00329006c3ed6325ba4e5ab7c9b5fc99c8934
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
|
||||
@@ -144,7 +144,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff
|
||||
F main.mk cfa185eed4e0f7e9d28a2e3167cecaa9d6cb39f3
|
||||
F main.mk f51f401a87fd07be255bcecae8b03105ca2024e8
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
@@ -159,16 +159,16 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
|
||||
F src/analyze.c e8c8a9d20beb2ad156321330e8f4fea002d8deee
|
||||
F src/analyze.c 3596f863bb80126fe56ba217df5932749271efc8
|
||||
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 70c60a3807b2072982f184d9614e020d2953f89c
|
||||
F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a
|
||||
F src/btree.c e14daeed62b5b1499835a6523f9a47d660c297c8
|
||||
F src/btree.h d79306df4ed9181b48916737fe8871a4392c4594
|
||||
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
|
||||
F src/build.c 927e39b6aaf872c7b28f154f6acfeb9a05a72442
|
||||
F src/build.c 9c522b6e5af1485c38b12a55f9d946e66fca61b6
|
||||
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
|
||||
@@ -176,18 +176,18 @@ F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
|
||||
F src/expr.c 4f9e497c66e2f25a4d139357a778c84d5713207c
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c a549cff9fe8b736cdae21650ea0af6de29b77619
|
||||
F src/func.c 2e16316ec3a6365a0dc3e553c586f91b20f7f6c8
|
||||
F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4
|
||||
F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf
|
||||
F src/func.c 2945bb2c4cdc0ac43733046285a4434310be1811
|
||||
F src/global.c b7943ff485c31660ec0b17c68467034804df01b1
|
||||
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
|
||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c a038daeadfb818aaadafa854f40f5623b6929d84
|
||||
F src/insert.c ab34bea5af4fee9f956a0805a32463fb7f674d00
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
|
||||
F src/main.c 40d0837e5d0597eadc47c3acc2fc95bdbd9250b8
|
||||
F src/main.c 2ba4f6eeb84cf8efd8bb632c1abe203dc86adcac
|
||||
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
|
||||
@@ -195,20 +195,18 @@ F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c 74670012946c4adc8a6ad84d03acc80959c3e529
|
||||
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
|
||||
F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
|
||||
F src/mutex.c 84a073c9a23a8d7bdd2ea832522d1730df18812c
|
||||
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
|
||||
F src/mutex_noop.c 7682796b7d8d39bf1c138248858efcd10c9e1553
|
||||
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
|
||||
F src/mutex_w32.c 9bcab6e699fdb20eae784237c36b299830fb3316
|
||||
F src/mutex_noop.c 4222773e5f61e506f232aedc9ad9e16ca00c1399
|
||||
F src/mutex_unix.c 56e22c1bc6aabfa2f9736317a8f56acd5d0c5f7c
|
||||
F src/mutex_w32.c c4726d3bfe80996665a39d27598ebd056e2d6b89
|
||||
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
|
||||
F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e
|
||||
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c ae4b5240af4619d711301d7992396e182585269f
|
||||
F src/os_win.c 8dbf6c11780fe2eb96c1f289e664d0c7b2911d37
|
||||
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
|
||||
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
|
||||
F src/os_win.c 5024065c68c50739aeef6d490db88e5b682fcc30
|
||||
F src/pager.c ab62a24218d87dda1be641f6c5ad291bff78fd94
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
|
||||
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
|
||||
@@ -220,18 +218,18 @@ F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
|
||||
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
||||
F src/select.c 7df17ec5506c2427576d412bee0e6ea740e12563
|
||||
F src/shell.c bfac06fb15f3cd0d447e2e72ab3a283fac301813
|
||||
F src/sqlite.h.in a98eb3e8c86c934ea6f5bcfc6b69653dde2f4ed4
|
||||
F src/select.c a5ed3fdc82ebab5b9b095ea1971515a7f8a303d2
|
||||
F src/shell.c 6946aea9f21af551fa84bc6b2a8de55d93bf0004
|
||||
F src/sqlite.h.in ed6d0cc90da850340c3863c84351e6e164c0ef00
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h fccdc735c27b3dc12322fec7cdad8bc76be8d00b
|
||||
F src/sqliteInt.h 851003126071d4a3bac86a0db75c48197fbd0ff0
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd
|
||||
F src/test1.c 4edf8810c86d77ae7ac6d56d563965a9beeea2ce
|
||||
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
|
||||
F src/test1.c a0e59104fec5626bb1d1bd746157f43e85245e4b
|
||||
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
|
||||
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
|
||||
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
|
||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||
@@ -243,7 +241,7 @@ F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
|
||||
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
|
||||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c dabaa32868974e1ae39770cc17d7e066a9c38e6d
|
||||
F src/test_config.c bf2e0bf49ebd8fe3dccabb4542157f9571fe48fa
|
||||
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
@@ -254,15 +252,15 @@ F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61
|
||||
F src/test_intarray.h 2ece66438cfd177b78d1bfda7a4180cd3a10844d
|
||||
F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c 1ff5b1243d96124c9a180f3b89424820a1f337f3
|
||||
F src/test_malloc.c 27047a841f5bff1cb638123806a2c30714771307
|
||||
F src/test_multiplex.c 9f304bf04170c91c0318238d512df2da039eb1c8
|
||||
F src/test_multiplex.h 110a8c4d356e0aa464ca8730375608a9a0b61ae1
|
||||
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
|
||||
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
|
||||
F src/test_osinst.c 3d0340bc31a9f3d8a3547e0272373e80f78dde25
|
||||
F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c 65f6348fec0f2b3020c907247fb47556b214abb9
|
||||
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
|
||||
F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0
|
||||
F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
|
||||
F src/test_rtree.c fdd8d29ca5165c7857987a2ba263fac5c69e231f
|
||||
F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6
|
||||
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
|
||||
@@ -272,29 +270,30 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
|
||||
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
|
||||
F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c b9daffcb6ae3a9c080da37b905e790d45a8f99db
|
||||
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
|
||||
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
|
||||
F src/update.c 01564b3c430f6c7b0a35afaf7aba7987206fa3a5
|
||||
F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115
|
||||
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
|
||||
F src/util.c 049fe1d3c0e2209c1bee107aec2fcff6285f909f
|
||||
F src/util.c 2b5fb283a190aacdb286f7835a447c45b345b83c
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 9bfe6becfc094382ae213656fbe511055ad83a54
|
||||
F src/vdbe.c 89ab2ded5123e823b47293aedd7931a4742fb6bd
|
||||
F src/vdbe.h 394464909ed682334aa3d5831aae0c2fe2abef94
|
||||
F src/vdbeInt.h e6d83e5bfd62fc6685ba1ed6153f7099f82de9f7
|
||||
F src/vdbeInt.h c78ace64dc37495806dd50596eded1f6cd2b5a64
|
||||
F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4
|
||||
F src/vdbeaux.c e493f38758c4b8f4ca2007cf6a700bd405d192f3
|
||||
F src/vdbeaux.c 44d4d1f5711f71eaf0d624de5c3e4976fe4e180b
|
||||
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
|
||||
F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
|
||||
F src/vdbesort.c 44441d73b08b3a638dcdb725afffb87c6574ad27
|
||||
F src/vdbesort.c b36070436d33372237541e9eaa6068e1a61bc402
|
||||
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
|
||||
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c b3be5eb4193b6327c4a02fe91411df503fe770e8
|
||||
F src/where.c 91dfd382273c3f67fcdc0ac4728f9140f91c6ab3
|
||||
F src/whereInt.h 6804c2e5010378568c2bb1350477537755296a46
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -336,7 +335,7 @@ F test/autoindex1.test 762ff3f8e25d852aae55c6462ca166a80c0cde61
|
||||
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
F test/backcompat.test 19a1f337c68419b020a7481dd272a472c4ad8ef4
|
||||
F test/backcompat.test 5f8ad58b3eaebc78cd2c66c65476a42e6f32b2ad
|
||||
F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
|
||||
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
|
||||
F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4
|
||||
@@ -456,7 +455,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
|
||||
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
|
||||
F test/eqp.test 90b56d03a93a2e7bb90f88be6083a8ea53f11a0e
|
||||
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
|
||||
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
|
||||
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
|
||||
@@ -539,16 +538,15 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
|
||||
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||
F test/fts3d.test 95c17d1b67b33a5eac0bf5a0d11116a0c0ac7a3a
|
||||
F test/fts3d.test 597b0b76e41f0d672e2731c4d7b631d628efd13f
|
||||
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
|
||||
F test/fts3defer2.test e880e3b65bdf999f4746cdaefa65f14a98b9b724
|
||||
F test/fts3defer2.test a3b6cbeabaf28c9398652a4d101ea224d9358479
|
||||
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
|
||||
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
|
||||
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
||||
F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162
|
||||
F test/fts3expr.test 06f1a96facc8f3e4b1ad5cc001dc5c8e83e68b9f
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
|
||||
F test/fts3expr4.test 0713d94ab951ed88a8c3629a4889a48c55c4067c
|
||||
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
|
||||
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
@@ -570,24 +568,22 @@ F test/fts4aa.test 0c3152322c7f0b548cc942ad763eaba0da87ccca
|
||||
F test/fts4check.test 66fa274cab2b615f2fb338b257713aba8fad88a8
|
||||
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
|
||||
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
||||
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
|
||||
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
|
||||
F test/fts4incr.test 361960ed3550e781f3f313e17e2182ef9cefc0e9
|
||||
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
|
||||
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
|
||||
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 9695c7c6c32480ea9fc20a2b38ed1de0640bcaec
|
||||
F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
|
||||
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
|
||||
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
|
||||
F test/func.test c2cbfc23d554c5bf8678d0fb271aa4f8ef94839c
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
|
||||
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
|
||||
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
|
||||
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
|
||||
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
|
||||
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
|
||||
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
|
||||
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
@@ -622,7 +618,7 @@ F test/index7.test a3baf9a625bda7fd49471e99aeae04095fbfeecf
|
||||
F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
F test/insert.test acf909b067b838eb55338d619e800e148c17f1f5
|
||||
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
|
||||
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
|
||||
F test/insert4.test 4791662c50518bdd37d394cae9a7a8014e845bb3
|
||||
@@ -669,7 +665,7 @@ F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
|
||||
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
|
||||
F test/main.test 39c4bb8a157f57298ed1659d6df89d9f35aaf2c8
|
||||
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test fd368e31fe98d4779ed80442f311ed9f03bcd1f7
|
||||
F test/malloc.test ada8ae15193ffc6415bf431a6db31d4ec507dbfe
|
||||
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
|
||||
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
|
||||
F test/malloc5.test fafce0aa9157060445cd1a56ad50fc79d82f28c3
|
||||
@@ -677,7 +673,7 @@ F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
|
||||
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
|
||||
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
|
||||
F test/malloc9.test 2307c6ee3703b0a21391f3ea92388b4b73f9105e
|
||||
F test/mallocA.test 1ba0367fb5434e7bc2fa4afcb30b14174d91b160
|
||||
F test/mallocA.test c049224adeb0244b8f6eb770c1fa6ac40f9b3518
|
||||
F test/mallocAll.test 98f1be74bc9f49a858bc4f361fc58e26486798be
|
||||
F test/mallocB.test bc475ab850cda896142ab935bbfbc74c24e51ed6
|
||||
F test/mallocC.test 3dffe16532f109293ce1ccecd0c31dca55ef08c4
|
||||
@@ -700,7 +696,7 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
|
||||
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 536a3360470633a177e42fbc19660d146b51daef
|
||||
F test/misc1.test 1201a037c24f982cc0e956cdaa34fcaf6439c417
|
||||
F test/misc1.test 441a0fafc7087f841db09fbfca54e7aea9f5a84c
|
||||
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
@@ -718,7 +714,6 @@ F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
|
||||
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
|
||||
F test/nolock.test 0540dd96f39b8876e3ffdd8814fad0ea425efeee
|
||||
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
F test/notify2.test ce23eb522c9e1fff6443f96376fe67872202061c
|
||||
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
|
||||
@@ -746,7 +741,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
|
||||
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
|
||||
F test/permutations.test d8946218493c77806ec1029df473d8ed4ad9aef6
|
||||
F test/permutations.test 33e7e239ba494fdb30e2f4ffc64c508b145ff42f
|
||||
F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0
|
||||
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
@@ -761,7 +756,7 @@ F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
|
||||
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a
|
||||
F test/rdonly.test c267d050a1d9a6a321de502b737daf28821a518d
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
|
||||
@@ -817,16 +812,20 @@ F test/shell1.test f2a1d471e5cd2b42f7a65b166dc1ace2b8d11583
|
||||
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
|
||||
F test/shell5.test fa5583230c0aea5c9ff33f0ac1e26b1e3f03d153
|
||||
F test/shell5.test bb755ea9144b8078a752fc56223582627070b5f1
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test 28c7faa41a0d7265040ecb0a0abd90c0904270b2
|
||||
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
|
||||
F test/skipscan1.test bed8cbe9d554c8c27afb6c88500f704c86a9196f
|
||||
F test/skipscan2.test d77f79cdbba25f0f6f35298136cff21a7d7a553a
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
|
||||
F test/sort.test 688468cef8c9a66fcc1d54235de8e4deac745690
|
||||
F test/sort2.test c5e25eb674689e291d06b5209fe8d337ae0ec010
|
||||
F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2
|
||||
F test/sort4.test 971452fd4e2928e6fc05c3868396ad7d5f9ce2ad
|
||||
F test/sortfault.test 1a12b6e27d475f50658a8164aaa34f0080a86b36
|
||||
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
|
||||
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
|
||||
F test/speed1p.test b180e98609c7677382cf618c0ec9b69f789033a8
|
||||
@@ -835,7 +834,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c d29c8048beb7ea9254191f3fde9414709166a920
|
||||
F test/speedtest1.c f452891e50571627f7060c0e1262359127055717
|
||||
F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe
|
||||
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
|
||||
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
|
||||
@@ -855,7 +854,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
F test/tester.tcl f31bea1483ea1d39620f982130026e76f872d744
|
||||
F test/tester.tcl bc0889a2f86d9c17307992ca1e70391794780265
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1008,7 +1007,7 @@ F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
|
||||
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/tpch01.test 8f4ac52f62f3e9f6bce0889105aecdf0275e331b
|
||||
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
|
||||
F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382
|
||||
F test/trace2.test e7a988fdd982cdec62f1f1f34b0360e6476d01a0
|
||||
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 373ac5183cc56be69f48ae44090e7f672939f732
|
||||
@@ -1106,11 +1105,10 @@ F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
||||
F test/whereG.test 0ac23e5e8311b69d87245f4a85112de321031658
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
F test/win32lock.test 71642fa56e9b06e5cfffe6bad67cb8c1eb2c555a
|
||||
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068
|
||||
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
|
||||
@@ -1123,7 +1121,7 @@ F test/without_rowid5.test b4a639a367f04d382d20e8f44fc1be4f2d57d107
|
||||
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 e0917e787df675b020d250d60a00de8abaa4e30a x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
|
||||
@@ -1141,11 +1139,11 @@ F tool/mkkeywordhash.c c9e05e4a7bcab8fab9f583d5b321fb72f565ad97
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 1712d3d71256ca1f297046619c89e77a4d7c8f6d
|
||||
F tool/mksqlite3c.tcl ba274df71f5e6534b0a913c7c48eabfcbd0934b6
|
||||
F tool/mksqlite3c-noext.tcl 752f1a9d3287f6c0ef5738b1c4add0b96fbe0854
|
||||
F tool/mksqlite3c.tcl 8da823522f27608494997e1dba19cd426572ba80
|
||||
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
|
||||
F tool/mksqlite3internalh.tcl b6514145a7d5321b47e64e19b8116cc44f973eb1
|
||||
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
|
||||
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
|
||||
F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
@@ -1171,9 +1169,9 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
|
||||
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P ed5a9eb4f30a395bc641e79254217c7d7cf0aa5d
|
||||
R 35776e018c929a9d3407d29571ba8a8f
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P dc7f84dfcc8415fad4af041fd30c20b3fd91be45
|
||||
R dab57784c4183d6467c4fe813ebf5ee5
|
||||
U mistachkin
|
||||
Z b80ed398d4e8aaa5357d010e1790f177
|
||||
Z bd4d9a5acb160a48faa7ad2a8521ce0e
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
f2906c44519d76db5bc36013369ae498b80655a8
|
||||
360c0fd1cf9db5f1e4f670a4b95971daaeaa5879
|
||||
+1
-1
@@ -1002,7 +1002,7 @@ static void analyzeOneTable(
|
||||
if( aGotoChng==0 ) continue;
|
||||
|
||||
/* Populate the register containing the index name. */
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
||||
if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
|
||||
zIdxName = pTab->zName;
|
||||
}else{
|
||||
zIdxName = pIdx->zName;
|
||||
|
||||
+12
-10
@@ -4218,6 +4218,12 @@ static const void *fetchPayload(
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
|
||||
assert( pCur->info.nSize>0 );
|
||||
#if 0
|
||||
if( pCur->info.nSize==0 ){
|
||||
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
|
||||
&pCur->info);
|
||||
}
|
||||
#endif
|
||||
*pAmt = pCur->info.nLocal;
|
||||
return (void*)(pCur->info.pCell + pCur->info.nHeader);
|
||||
}
|
||||
@@ -4603,7 +4609,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
|
||||
if( pIdxKey ){
|
||||
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
|
||||
pIdxKey->isCorrupt = 0;
|
||||
pIdxKey->errCode = 0;
|
||||
assert( pIdxKey->default_rc==1
|
||||
|| pIdxKey->default_rc==0
|
||||
|| pIdxKey->default_rc==-1
|
||||
@@ -4727,7 +4733,10 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
|
||||
sqlite3_free(pCellKey);
|
||||
}
|
||||
assert( pIdxKey->isCorrupt==0 || c==0 );
|
||||
assert(
|
||||
(pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
|
||||
&& (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
|
||||
);
|
||||
if( c<0 ){
|
||||
lwr = idx+1;
|
||||
}else if( c>0 ){
|
||||
@@ -4737,7 +4746,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
*pRes = 0;
|
||||
rc = SQLITE_OK;
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT;
|
||||
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
if( lwr>upr ) break;
|
||||
@@ -8520,10 +8529,3 @@ void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
|
||||
assert( mask==BTREE_BULKLOAD || mask==0 );
|
||||
pCsr->hints = mask;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the given Btree is read-only.
|
||||
*/
|
||||
int sqlite3BtreeIsReadonly(Btree *p){
|
||||
return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
|
||||
}
|
||||
|
||||
@@ -194,7 +194,6 @@ void sqlite3BtreeIncrblobCursor(BtCursor *);
|
||||
void sqlite3BtreeClearCursor(BtCursor *);
|
||||
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
|
||||
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
|
||||
int sqlite3BtreeIsReadonly(Btree *pBt);
|
||||
|
||||
#ifndef NDEBUG
|
||||
int sqlite3BtreeCursorIsValid(BtCursor*);
|
||||
|
||||
+12
-16
@@ -757,7 +757,7 @@ int sqlite3CheckObjectName(Parse *pParse, const char *zName){
|
||||
*/
|
||||
Index *sqlite3PrimaryKeyIndex(Table *pTab){
|
||||
Index *p;
|
||||
for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){}
|
||||
for(p=pTab->pIndex; p && p->autoIndex!=2; p=p->pNext){}
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1286,7 +1286,7 @@ void sqlite3AddPrimaryKey(
|
||||
p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
|
||||
0, sortOrder, 0);
|
||||
if( p ){
|
||||
p->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
|
||||
p->autoIndex = 2;
|
||||
if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
|
||||
}
|
||||
pList = 0;
|
||||
@@ -1306,10 +1306,7 @@ void sqlite3AddCheckConstraint(
|
||||
){
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
Table *pTab = pParse->pNewTable;
|
||||
sqlite3 *db = pParse->db;
|
||||
if( pTab && !IN_DECLARE_VTAB
|
||||
&& !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
|
||||
){
|
||||
if( pTab && !IN_DECLARE_VTAB ){
|
||||
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
|
||||
if( pParse->constraintName.n ){
|
||||
sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
|
||||
@@ -1661,7 +1658,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
assert( pParse->pNewTable==pTab );
|
||||
pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
|
||||
if( pPk==0 ) return;
|
||||
pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
|
||||
pPk->autoIndex = 2;
|
||||
pTab->iPKey = -1;
|
||||
}else{
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
@@ -1684,7 +1681,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
*/
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
int n;
|
||||
if( IsPrimaryKeyIndex(pIdx) ) continue;
|
||||
if( pIdx->autoIndex==2 ) continue;
|
||||
for(i=n=0; i<nPk; i++){
|
||||
if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
|
||||
}
|
||||
@@ -2672,7 +2669,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
|
||||
/* Open the sorter cursor if we are to use one. */
|
||||
iSorter = pParse->nTab++;
|
||||
sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)
|
||||
sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*)
|
||||
sqlite3KeyInfoRef(pKey), P4_KEYINFO);
|
||||
|
||||
/* Open the table. Loop through all rows of the table, inserting index
|
||||
@@ -2764,7 +2761,7 @@ Index *sqlite3AllocateIndexObject(
|
||||
**
|
||||
** If the index is created successfully, return a pointer to the new Index
|
||||
** structure. This is used by sqlite3AddPrimaryKey() to mark the index
|
||||
** as the tables primary key (Index.idxType==SQLITE_IDXTYPE_PRIMARYKEY)
|
||||
** as the tables primary key (Index.autoIndex==2).
|
||||
*/
|
||||
Index *sqlite3CreateIndex(
|
||||
Parse *pParse, /* All information about this parse */
|
||||
@@ -2979,7 +2976,7 @@ Index *sqlite3CreateIndex(
|
||||
pIndex->pTable = pTab;
|
||||
pIndex->onError = (u8)onError;
|
||||
pIndex->uniqNotNull = onError!=OE_None;
|
||||
pIndex->idxType = pName ? SQLITE_IDXTYPE_APPDEF : SQLITE_IDXTYPE_UNIQUE;
|
||||
pIndex->autoIndex = (u8)(pName==0);
|
||||
pIndex->pSchema = db->aDb[iDb].pSchema;
|
||||
pIndex->nKeyCol = pList->nExpr;
|
||||
if( pPIWhere ){
|
||||
@@ -3021,7 +3018,7 @@ Index *sqlite3CreateIndex(
|
||||
pParse->checkSchema = 1;
|
||||
goto exit_create_index;
|
||||
}
|
||||
assert( pTab->nCol<=0x7fff && j<=0x7fff );
|
||||
assert( j<=0x7fff );
|
||||
pIndex->aiColumn[i] = (i16)j;
|
||||
if( pListItem->pExpr ){
|
||||
int nColl;
|
||||
@@ -3091,7 +3088,7 @@ Index *sqlite3CreateIndex(
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
int k;
|
||||
assert( pIdx->onError!=OE_None );
|
||||
assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
|
||||
assert( pIdx->autoIndex );
|
||||
assert( pIndex->onError!=OE_None );
|
||||
|
||||
if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
|
||||
@@ -3314,7 +3311,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
|
||||
pParse->checkSchema = 1;
|
||||
goto exit_drop_index;
|
||||
}
|
||||
if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
|
||||
if( pIndex->autoIndex ){
|
||||
sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
|
||||
"or PRIMARY KEY constraint cannot be dropped", 0);
|
||||
goto exit_drop_index;
|
||||
@@ -3973,8 +3970,7 @@ void sqlite3UniqueConstraint(
|
||||
}
|
||||
zErr = sqlite3StrAccumFinish(&errMsg);
|
||||
sqlite3HaltConstraint(pParse,
|
||||
IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY
|
||||
: SQLITE_CONSTRAINT_UNIQUE,
|
||||
(pIdx->autoIndex==2)?SQLITE_CONSTRAINT_PRIMARYKEY:SQLITE_CONSTRAINT_UNIQUE,
|
||||
onError, zErr, P4_DYNAMIC, P5_ConstraintUnique);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -233,8 +233,8 @@ int sqlite3FkLocateIndex(
|
||||
if( zKey==0 ){
|
||||
/* If zKey is NULL, then this foreign key is implicitly mapped to
|
||||
** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
|
||||
** identified by the test. */
|
||||
if( IsPrimaryKeyIndex(pIdx) ){
|
||||
** identified by the test (Index.autoIndex==2). */
|
||||
if( pIdx->autoIndex==2 ){
|
||||
if( aiCol ){
|
||||
int i;
|
||||
for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom;
|
||||
|
||||
+1
-1
@@ -1541,7 +1541,7 @@ static void groupConcatStep(
|
||||
}
|
||||
zVal = (char*)sqlite3_value_text(argv[0]);
|
||||
nVal = sqlite3_value_bytes(argv[0]);
|
||||
if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
|
||||
if( nVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
|
||||
}
|
||||
}
|
||||
static void groupConcatFinalize(sqlite3_context *context){
|
||||
|
||||
+4
-10
@@ -167,28 +167,22 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
0, /* nPage */
|
||||
0, /* mxParserStack */
|
||||
0, /* sharedCacheEnabled */
|
||||
SQLITE_DEFAULT_WORKER_THREADS, /* nWorker */
|
||||
/* All the rest should always be initialized to zero */
|
||||
0, /* isInit */
|
||||
0, /* inProgress */
|
||||
0, /* isMutexInit */
|
||||
0, /* isMallocInit */
|
||||
0, /* isPCacheInit */
|
||||
0, /* nRefInitMutex */
|
||||
0, /* pInitMutex */
|
||||
0, /* nRefInitMutex */
|
||||
0, /* xLog */
|
||||
0, /* pLogArg */
|
||||
0, /* bLocaltimeFault */
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
0, /* xSqllog */
|
||||
0, /* pSqllogArg */
|
||||
0 /* pSqllogArg */
|
||||
#endif
|
||||
#ifdef SQLITE_VDBE_COVERAGE
|
||||
0, /* xVdbeBranch */
|
||||
0, /* pVbeBranchArg */
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
0, /* xTestCallback */
|
||||
#endif
|
||||
0 /* bLocaltimeFault */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+3
-4
@@ -614,7 +614,6 @@ void sqlite3Insert(
|
||||
if( j>=pTab->nCol ){
|
||||
if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
|
||||
ipkColumn = i;
|
||||
bIdListInOrder = 0;
|
||||
}else{
|
||||
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
|
||||
pTabList, 0, pColumn->a[i].zName);
|
||||
@@ -1463,7 +1462,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
** KEY values of this row before the update. */
|
||||
int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
|
||||
int op = OP_Ne;
|
||||
int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR);
|
||||
int regCmp = (pIdx->autoIndex==2 ? regIdx : regR);
|
||||
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
|
||||
@@ -1564,7 +1563,7 @@ void sqlite3CompleteInsertion(
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
|
||||
pik_flags = 0;
|
||||
if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
||||
if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
|
||||
assert( pParse->nested==0 );
|
||||
pik_flags |= OPFLAG_NCHANGE;
|
||||
}
|
||||
@@ -1650,7 +1649,7 @@ int sqlite3OpenTableAndIndices(
|
||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||
int iIdxCur = iBase++;
|
||||
assert( pIdx->pSchema==pTab->pSchema );
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){
|
||||
if( pIdx->autoIndex==2 && !HasRowid(pTab) && piDataCur ){
|
||||
*piDataCur = iIdxCur;
|
||||
}
|
||||
if( aToOpen==0 || aToOpen[i+1] ){
|
||||
|
||||
+16
-23
@@ -515,6 +515,13 @@ int sqlite3_config(int op, ...){
|
||||
}
|
||||
#endif
|
||||
|
||||
case SQLITE_CONFIG_WORKER_THREADS: {
|
||||
int n = va_arg(ap, int);
|
||||
if( n>SQLITE_MAX_WORKER_THREADS ) n = SQLITE_MAX_WORKER_THREADS;
|
||||
if( n>=0 ) sqlite3GlobalConfig.nWorker = n;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
@@ -2497,6 +2504,7 @@ static int openDatabase(
|
||||
db->nextAutovac = -1;
|
||||
db->szMmap = sqlite3GlobalConfig.szMmap;
|
||||
db->nextPagesize = 0;
|
||||
db->nMaxSorterMmap = 0x7FFFFFFF;
|
||||
db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
|
||||
#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
|
||||
| SQLITE_AutoIndex
|
||||
@@ -3114,28 +3122,6 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_test_control(FAULT_INSTALL, xCallback)
|
||||
**
|
||||
** Arrange to invoke xCallback() whenever sqlite3FaultSim() is called,
|
||||
** if xCallback is not NULL.
|
||||
**
|
||||
** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0)
|
||||
** is called immediately after installing the new callback and the return
|
||||
** value from sqlite3FaultSim(0) becomes the return from
|
||||
** sqlite3_test_control().
|
||||
*/
|
||||
case SQLITE_TESTCTRL_FAULT_INSTALL: {
|
||||
/* MSVC is picky about pulling func ptrs from va lists.
|
||||
** http://support.microsoft.com/kb/47961
|
||||
** sqlite3Config.xTestCallback = va_arg(ap, int(*)(int));
|
||||
*/
|
||||
typedef int(*TESTCALLBACKFUNC_t)(int);
|
||||
sqlite3Config.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
|
||||
rc = sqlite3FaultSim(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
|
||||
**
|
||||
@@ -3361,6 +3347,13 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, nMax); */
|
||||
case SQLITE_TESTCTRL_SORTER_MMAP: {
|
||||
sqlite3 *db = va_arg(ap, sqlite3*);
|
||||
db->nMaxSorterMmap = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
va_end(ap);
|
||||
#endif /* SQLITE_OMIT_BUILTIN_TEST */
|
||||
@@ -3445,5 +3438,5 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
|
||||
*/
|
||||
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
|
||||
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
|
||||
return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
|
||||
return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
|
||||
}
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ int sqlite3MutexEnd(void){
|
||||
*/
|
||||
sqlite3_mutex *sqlite3_mutex_alloc(int id){
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
|
||||
#endif
|
||||
return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
|
||||
}
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ static int debugMutexEnd(void){ return SQLITE_OK; }
|
||||
** that means that a mutex could not be allocated.
|
||||
*/
|
||||
static sqlite3_mutex *debugMutexAlloc(int id){
|
||||
static sqlite3_debug_mutex aStatic[6];
|
||||
static sqlite3_debug_mutex aStatic[8];
|
||||
sqlite3_debug_mutex *pNew = 0;
|
||||
switch( id ){
|
||||
case SQLITE_MUTEX_FAST:
|
||||
|
||||
+5
-1
@@ -96,10 +96,12 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
|
||||
** <li> SQLITE_MUTEX_RECURSIVE
|
||||
** <li> SQLITE_MUTEX_STATIC_MASTER
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM2
|
||||
** <li> SQLITE_MUTEX_STATIC_OPEN
|
||||
** <li> SQLITE_MUTEX_STATIC_PRNG
|
||||
** <li> SQLITE_MUTEX_STATIC_LRU
|
||||
** <li> SQLITE_MUTEX_STATIC_PMEM
|
||||
** <li> SQLITE_MUTEX_STATIC_APP1
|
||||
** <li> SQLITE_MUTEX_STATIC_APP2
|
||||
** </ul>
|
||||
**
|
||||
** The first two constants cause sqlite3_mutex_alloc() to create
|
||||
@@ -133,6 +135,8 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER
|
||||
};
|
||||
sqlite3_mutex *p;
|
||||
|
||||
+6
-9
@@ -13,13 +13,6 @@
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
#if SQLITE_OS_WIN
|
||||
/*
|
||||
** Include the header file for the Windows VFS.
|
||||
*/
|
||||
#include "os_win.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The code in this file is only used if we are compiling multithreaded
|
||||
** on a win32 system.
|
||||
@@ -100,7 +93,9 @@ static int winMutexNotheld(sqlite3_mutex *p){
|
||||
/*
|
||||
** Initialize and deinitialize the mutex subsystem.
|
||||
*/
|
||||
static sqlite3_mutex winMutex_staticMutexes[6] = {
|
||||
static sqlite3_mutex winMutex_staticMutexes[] = {
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
@@ -166,10 +161,12 @@ static int winMutexEnd(void){
|
||||
** <li> SQLITE_MUTEX_RECURSIVE
|
||||
** <li> SQLITE_MUTEX_STATIC_MASTER
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM2
|
||||
** <li> SQLITE_MUTEX_STATIC_OPEN
|
||||
** <li> SQLITE_MUTEX_STATIC_PRNG
|
||||
** <li> SQLITE_MUTEX_STATIC_LRU
|
||||
** <li> SQLITE_MUTEX_STATIC_PMEM
|
||||
** <li> SQLITE_MUTEX_STATIC_APP1
|
||||
** <li> SQLITE_MUTEX_STATIC_APP2
|
||||
** </ul>
|
||||
**
|
||||
** The first two constants cause sqlite3_mutex_alloc() to create
|
||||
|
||||
@@ -21,10 +21,83 @@
|
||||
#define _SQLITE_OS_H_
|
||||
|
||||
/*
|
||||
** Attempt to automatically detect the operating system and setup the
|
||||
** necessary pre-processor macros for it.
|
||||
** Figure out if we are dealing with Unix, Windows, or some other
|
||||
** operating system. After the following block of preprocess macros,
|
||||
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
|
||||
** will defined to either 1 or 0. One of the four will be 1. The other
|
||||
** three will be 0.
|
||||
*/
|
||||
#include "os_setup.h"
|
||||
#if defined(SQLITE_OS_OTHER)
|
||||
# if SQLITE_OS_OTHER==1
|
||||
# undef SQLITE_OS_UNIX
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# else
|
||||
# undef SQLITE_OS_OTHER
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
|
||||
# define SQLITE_OS_OTHER 0
|
||||
# ifndef SQLITE_OS_WIN
|
||||
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
|
||||
# define SQLITE_OS_WIN 1
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# else
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 1
|
||||
# endif
|
||||
# else
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# endif
|
||||
#else
|
||||
# ifndef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_WIN
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows NT.
|
||||
**
|
||||
** We ought to be able to determine if we are compiling for win98 or winNT
|
||||
** using the _WIN32_WINNT macro as follows:
|
||||
**
|
||||
** #if defined(_WIN32_WINNT)
|
||||
** # define SQLITE_OS_WINNT 1
|
||||
** #else
|
||||
** # define SQLITE_OS_WINNT 0
|
||||
** #endif
|
||||
**
|
||||
** However, vs2005 does not set _WIN32_WINNT by default, as it ought to,
|
||||
** so the above test does not work. We'll just assume that everything is
|
||||
** winNT unless the programmer explicitly says otherwise by setting
|
||||
** SQLITE_OS_WINNT to 0.
|
||||
*/
|
||||
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
|
||||
# define SQLITE_OS_WINNT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with WindowsCE - which has a much
|
||||
** reduced API.
|
||||
*/
|
||||
#if defined(_WIN32_WCE)
|
||||
# define SQLITE_OS_WINCE 1
|
||||
#else
|
||||
# define SQLITE_OS_WINCE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with WinRT, which provides only a subset of
|
||||
** the full Win32 API.
|
||||
*/
|
||||
#if !defined(SQLITE_OS_WINRT)
|
||||
# define SQLITE_OS_WINRT 0
|
||||
#endif
|
||||
|
||||
/* If the SET_FULLSYNC macro is not defined above, then make it
|
||||
** a no-op
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
** 2013 November 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 contains pre-processor directives related to operating system
|
||||
** detection and/or setup.
|
||||
*/
|
||||
#ifndef _OS_SETUP_H_
|
||||
#define _OS_SETUP_H_
|
||||
|
||||
/*
|
||||
** Figure out if we are dealing with Unix, Windows, or some other operating
|
||||
** system.
|
||||
**
|
||||
** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
|
||||
** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of
|
||||
** the three will be 1. The other two will be 0.
|
||||
*/
|
||||
#if defined(SQLITE_OS_OTHER)
|
||||
# if SQLITE_OS_OTHER==1
|
||||
# undef SQLITE_OS_UNIX
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# else
|
||||
# undef SQLITE_OS_OTHER
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
|
||||
# define SQLITE_OS_OTHER 0
|
||||
# ifndef SQLITE_OS_WIN
|
||||
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
|
||||
defined(__MINGW32__) || defined(__BORLANDC__)
|
||||
# define SQLITE_OS_WIN 1
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# else
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 1
|
||||
# endif
|
||||
# else
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# endif
|
||||
#else
|
||||
# ifndef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _OS_SETUP_H_ */
|
||||
+128
-75
@@ -15,16 +15,16 @@
|
||||
#include "sqliteInt.h"
|
||||
#if SQLITE_OS_WIN /* This file is used for Windows only */
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
# include <sys/cygwin.h>
|
||||
# include <errno.h> /* amalgamator: keep */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
*/
|
||||
#include "os_common.h"
|
||||
|
||||
/*
|
||||
** Include the header file for the Windows VFS.
|
||||
*/
|
||||
#include "os_win.h"
|
||||
|
||||
/*
|
||||
** Compiling and using WAL mode requires several APIs that are only
|
||||
** available in Windows platforms based on the NT kernel.
|
||||
@@ -267,6 +267,7 @@ struct winFile {
|
||||
sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
|
||||
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
|
||||
#endif
|
||||
SQLiteThread *preCacheThread; /* Thread used to pre-cache file contents */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -948,11 +949,7 @@ static struct win_syscall {
|
||||
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
|
||||
DWORD))aSyscall[63].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
|
||||
#else
|
||||
{ "WaitForSingleObjectEx", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
|
||||
BOOL))aSyscall[64].pCurrent)
|
||||
@@ -1048,6 +1045,11 @@ static struct win_syscall {
|
||||
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
|
||||
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
|
||||
|
||||
{ "DuplicateHandle", (SYSCALL)DuplicateHandle, 0 },
|
||||
|
||||
#define osDuplicateHandle ((BOOL(WINAPI*)(HANDLE, \
|
||||
HANDLE,HANDLE,LPHANDLE,DWORD,BOOL,DWORD))aSyscall[76].pCurrent)
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
|
||||
/*
|
||||
@@ -1279,6 +1281,13 @@ void sqlite3_win32_sleep(DWORD milliseconds){
|
||||
#endif
|
||||
}
|
||||
|
||||
DWORD sqlite3Win32Wait(HANDLE hObject){
|
||||
DWORD rc;
|
||||
while( (rc = osWaitForSingleObjectEx(hObject, INFINITE,
|
||||
TRUE))==WAIT_IO_COMPLETION ){}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
|
||||
** or WinCE. Return false (zero) for Win95, Win98, or WinME.
|
||||
@@ -1836,32 +1845,6 @@ static int winLogErrorAtLine(
|
||||
static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
|
||||
static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
|
||||
|
||||
/*
|
||||
** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
|
||||
** error code obtained via GetLastError() is eligible to be retried. It
|
||||
** must accept the error code DWORD as its only argument and should return
|
||||
** non-zero if the error code is transient in nature and the operation
|
||||
** responsible for generating the original error might succeed upon being
|
||||
** retried. The argument to this macro should be a variable.
|
||||
**
|
||||
** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it
|
||||
** is defined, it will be consulted only when the macro "winIoerrCanRetry1"
|
||||
** returns zero. The "winIoerrCanRetry2" macro is completely optional and
|
||||
** may be used to include additional error codes in the set that should
|
||||
** result in the failing I/O operation being retried by the caller. If
|
||||
** defined, the "winIoerrCanRetry2" macro must exhibit external semantics
|
||||
** identical to those of the "winIoerrCanRetry1" macro.
|
||||
*/
|
||||
#if !defined(winIoerrCanRetry1)
|
||||
#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \
|
||||
((a)==ERROR_SHARING_VIOLATION) || \
|
||||
((a)==ERROR_LOCK_VIOLATION) || \
|
||||
((a)==ERROR_DEV_NOT_EXIST) || \
|
||||
((a)==ERROR_NETNAME_DELETED) || \
|
||||
((a)==ERROR_SEM_TIMEOUT) || \
|
||||
((a)==ERROR_NETWORK_UNREACHABLE))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If a ReadFile() or WriteFile() error occurs, invoke this routine
|
||||
** to see if it should be retried. Return TRUE to retry. Return FALSE
|
||||
@@ -1875,18 +1858,13 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if( winIoerrCanRetry1(e) ){
|
||||
if( e==ERROR_ACCESS_DENIED ||
|
||||
e==ERROR_LOCK_VIOLATION ||
|
||||
e==ERROR_SHARING_VIOLATION ){
|
||||
sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
|
||||
++*pnRetry;
|
||||
return 1;
|
||||
}
|
||||
#if defined(winIoerrCanRetry2)
|
||||
else if( winIoerrCanRetry2(e) ){
|
||||
sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
|
||||
++*pnRetry;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
if( pError ){
|
||||
*pError = e;
|
||||
}
|
||||
@@ -2382,6 +2360,13 @@ static int winClose(sqlite3_file *id){
|
||||
assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
|
||||
OSTRACE(("CLOSE file=%p\n", pFile->h));
|
||||
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
if( pFile->preCacheThread ){
|
||||
void *pOut = 0;
|
||||
sqlite3ThreadJoin(pFile->preCacheThread, &pOut);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
winUnmapfile(pFile);
|
||||
#endif
|
||||
@@ -2825,7 +2810,7 @@ static int winGetReadLock(winFile *pFile){
|
||||
pFile->lastErrno = osGetLastError();
|
||||
/* No need to log a failure to lock */
|
||||
}
|
||||
OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res));
|
||||
OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2849,7 +2834,7 @@ static int winUnlockReadLock(winFile *pFile){
|
||||
winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
|
||||
"winUnlockReadLock", pFile->zPath);
|
||||
}
|
||||
OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res));
|
||||
OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2924,16 +2909,8 @@ static int winLock(sqlite3_file *id, int locktype){
|
||||
** If you are using this code as a model for alternative VFSes, do not
|
||||
** copy this retry logic. It is a hack intended for Windows only.
|
||||
*/
|
||||
lastErrno = osGetLastError();
|
||||
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
|
||||
pFile->h, cnt, res));
|
||||
if( lastErrno==ERROR_INVALID_HANDLE ){
|
||||
pFile->lastErrno = lastErrno;
|
||||
rc = SQLITE_IOERR_LOCK;
|
||||
OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
|
||||
pFile->h, cnt, sqlite3ErrName(rc)));
|
||||
return rc;
|
||||
}
|
||||
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
|
||||
pFile->h, cnt, sqlite3ErrName(res)));
|
||||
if( cnt ) sqlite3_win32_sleep(1);
|
||||
}
|
||||
gotPendingLock = res;
|
||||
@@ -3018,7 +2995,7 @@ static int winLock(sqlite3_file *id, int locktype){
|
||||
** non-zero, otherwise zero.
|
||||
*/
|
||||
static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
int res;
|
||||
int rc;
|
||||
winFile *pFile = (winFile*)id;
|
||||
|
||||
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
||||
@@ -3026,17 +3003,17 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
|
||||
assert( id!=0 );
|
||||
if( pFile->locktype>=RESERVED_LOCK ){
|
||||
res = 1;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res));
|
||||
rc = 1;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
|
||||
}else{
|
||||
res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
|
||||
if( res ){
|
||||
rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
|
||||
if( rc ){
|
||||
winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
|
||||
}
|
||||
res = !res;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res));
|
||||
rc = !rc;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
|
||||
}
|
||||
*pResOut = res;
|
||||
*pResOut = rc;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
|
||||
pFile->h, pResOut, *pResOut));
|
||||
return SQLITE_OK;
|
||||
@@ -3177,17 +3154,6 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#ifdef SQLITE_TEST
|
||||
case SQLITE_FCNTL_WIN32_SET_HANDLE: {
|
||||
LPHANDLE phFile = (LPHANDLE)pArg;
|
||||
HANDLE hOldFile = pFile->h;
|
||||
pFile->h = *phFile;
|
||||
*phFile = hOldFile;
|
||||
OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
|
||||
hOldFile, pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
case SQLITE_FCNTL_TEMPFILENAME: {
|
||||
char *zTFile = 0;
|
||||
int rc = winGetTempname(pFile->pVfs, &zTFile);
|
||||
@@ -3245,6 +3211,84 @@ static int winDeviceCharacteristics(sqlite3_file *id){
|
||||
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
|
||||
}
|
||||
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
/*
|
||||
** Thread routine that attempts to read the entire file. This is used to
|
||||
** provide a hint to the operating system that the entire file should be held
|
||||
** in the cache.
|
||||
*/
|
||||
static void *winPreCacheThread(void *pCtx){
|
||||
winFile *pFile = (winFile*)pCtx;
|
||||
void *pBuf = 0;
|
||||
DWORD lastErrno;
|
||||
HANDLE dupHandle = NULL;
|
||||
DWORD dwSize, dwRet;
|
||||
DWORD dwAmt;
|
||||
DWORD nRead;
|
||||
|
||||
if( !osDuplicateHandle(GetCurrentProcess(), pFile->h, GetCurrentProcess(),
|
||||
&dupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) ){
|
||||
pFile->lastErrno = osGetLastError();
|
||||
OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR\n", dupHandle));
|
||||
return SQLITE_INT_TO_PTR(winLogError(SQLITE_IOERR, pFile->lastErrno,
|
||||
"winPreCacheThread1", pFile->zPath));
|
||||
}
|
||||
dwSize = osSetFilePointer(dupHandle, 0, 0, FILE_END);
|
||||
if( (dwSize==INVALID_SET_FILE_POINTER
|
||||
&& ((lastErrno = osGetLastError())!=NO_ERROR)) ){
|
||||
pFile->lastErrno = lastErrno;
|
||||
osCloseHandle(dupHandle);
|
||||
OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_SEEK\n", dupHandle));
|
||||
return SQLITE_INT_TO_PTR(winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
|
||||
"winPreCacheThread2", pFile->zPath));
|
||||
}
|
||||
dwRet = osSetFilePointer(dupHandle, 0, 0, FILE_BEGIN);
|
||||
if( (dwRet==INVALID_SET_FILE_POINTER
|
||||
&& ((lastErrno = osGetLastError())!=NO_ERROR)) ){
|
||||
pFile->lastErrno = lastErrno;
|
||||
osCloseHandle(dupHandle);
|
||||
OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_SEEK\n", dupHandle));
|
||||
return SQLITE_INT_TO_PTR(winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
|
||||
"winPreCacheThread3", pFile->zPath));
|
||||
}
|
||||
dwAmt = 4194304; /* TODO: Tuning. */
|
||||
if( dwSize<dwAmt ){
|
||||
dwAmt = dwSize;
|
||||
}
|
||||
pBuf = sqlite3MallocZero( dwAmt );
|
||||
if( pBuf==0 ){
|
||||
osCloseHandle(dupHandle);
|
||||
OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_NOMEM\n", dupHandle));
|
||||
return SQLITE_INT_TO_PTR(SQLITE_IOERR_NOMEM);
|
||||
}
|
||||
while( 1 ){
|
||||
if( !osReadFile(dupHandle, pBuf, dwAmt, &nRead, 0) ){
|
||||
pFile->lastErrno = osGetLastError();
|
||||
sqlite3_free(pBuf);
|
||||
osCloseHandle(dupHandle);
|
||||
OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_READ\n", dupHandle));
|
||||
return SQLITE_INT_TO_PTR(winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
|
||||
"winPreCacheThread4", pFile->zPath));
|
||||
}
|
||||
if( nRead<dwAmt ){
|
||||
sqlite3_free(pBuf);
|
||||
osCloseHandle(dupHandle);
|
||||
OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_SHORT_READ\n", dupHandle));
|
||||
return SQLITE_INT_TO_PTR(winLogError(SQLITE_IOERR_SHORT_READ,
|
||||
pFile->lastErrno,
|
||||
"winPreCacheThread5", pFile->zPath));
|
||||
}
|
||||
dwSize -= dwAmt;
|
||||
if( dwSize==0 ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3_free(pBuf);
|
||||
osCloseHandle(dupHandle);
|
||||
return SQLITE_INT_TO_PTR(SQLITE_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Windows will only let you create file view mappings
|
||||
** on allocation size granularity boundaries.
|
||||
@@ -4751,6 +4795,15 @@ static int winOpen(
|
||||
pFile->mmapSizeActual = 0;
|
||||
pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
|
||||
#endif
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
sqlite3ThreadCreate(&pFile->preCacheThread, winPreCacheThread, pFile);
|
||||
|
||||
{
|
||||
void *pOut = 0;
|
||||
sqlite3ThreadJoin(pFile->preCacheThread, &pOut);
|
||||
pFile->preCacheThread = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
OpenCounter(+1);
|
||||
return rc;
|
||||
@@ -5469,7 +5522,7 @@ int sqlite3_os_init(void){
|
||||
|
||||
/* Double-check that the aSyscall[] array has been constructed
|
||||
** correctly. See ticket [bb3a86e890c8e96ab] */
|
||||
assert( ArraySize(aSyscall)==76 );
|
||||
assert( ArraySize(aSyscall)==77 );
|
||||
|
||||
/* get memory map allocation granularity */
|
||||
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
** 2013 November 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 contains code that is specific to Windows.
|
||||
*/
|
||||
#ifndef _OS_WIN_H_
|
||||
#define _OS_WIN_H_
|
||||
|
||||
/*
|
||||
** Include the primary Windows SDK header file.
|
||||
*/
|
||||
#include "windows.h"
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
# include <sys/cygwin.h>
|
||||
# include <errno.h> /* amalgamator: dontcache */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows NT.
|
||||
**
|
||||
** We ought to be able to determine if we are compiling for Windows 9x or
|
||||
** Windows NT using the _WIN32_WINNT macro as follows:
|
||||
**
|
||||
** #if defined(_WIN32_WINNT)
|
||||
** # define SQLITE_OS_WINNT 1
|
||||
** #else
|
||||
** # define SQLITE_OS_WINNT 0
|
||||
** #endif
|
||||
**
|
||||
** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
|
||||
** it ought to, so the above test does not work. We'll just assume that
|
||||
** everything is Windows NT unless the programmer explicitly says otherwise
|
||||
** by setting SQLITE_OS_WINNT to 0.
|
||||
*/
|
||||
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
|
||||
# define SQLITE_OS_WINNT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows CE - which has a much reduced
|
||||
** API.
|
||||
*/
|
||||
#if defined(_WIN32_WCE)
|
||||
# define SQLITE_OS_WINCE 1
|
||||
#else
|
||||
# define SQLITE_OS_WINCE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with WinRT, which provides only a subset of
|
||||
** the full Win32 API.
|
||||
*/
|
||||
#if !defined(SQLITE_OS_WINRT)
|
||||
# define SQLITE_OS_WINRT 0
|
||||
#endif
|
||||
|
||||
#endif /* _OS_WIN_H_ */
|
||||
+27
-37
@@ -626,8 +626,7 @@ struct Pager {
|
||||
u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
|
||||
u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
|
||||
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
|
||||
u8 tempFile; /* zFilename is a temporary or immutable file */
|
||||
u8 noLock; /* Do not lock (except in WAL mode) */
|
||||
u8 tempFile; /* zFilename is a temporary file */
|
||||
u8 readOnly; /* True for a read-only database */
|
||||
u8 memDb; /* True to inhibit all file I/O */
|
||||
|
||||
@@ -1092,7 +1091,7 @@ static int pagerUnlockDb(Pager *pPager, int eLock){
|
||||
assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
|
||||
if( isOpen(pPager->fd) ){
|
||||
assert( pPager->eLock>=eLock );
|
||||
rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
|
||||
rc = sqlite3OsUnlock(pPager->fd, eLock);
|
||||
if( pPager->eLock!=UNKNOWN_LOCK ){
|
||||
pPager->eLock = (u8)eLock;
|
||||
}
|
||||
@@ -1116,7 +1115,7 @@ static int pagerLockDb(Pager *pPager, int eLock){
|
||||
|
||||
assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
|
||||
if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
|
||||
rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock);
|
||||
rc = sqlite3OsLock(pPager->fd, eLock);
|
||||
if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
|
||||
pPager->eLock = (u8)eLock;
|
||||
IOTRACE(("LOCK %p %d\n", pPager, eLock))
|
||||
@@ -4675,38 +4674,30 @@ int sqlite3PagerOpen(
|
||||
** + The value returned by sqlite3OsSectorSize()
|
||||
** + The largest page size that can be written atomically.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
|
||||
if( !readOnly ){
|
||||
setSectorSize(pPager);
|
||||
assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
|
||||
if( szPageDflt<pPager->sectorSize ){
|
||||
if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
|
||||
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
|
||||
}else{
|
||||
szPageDflt = (u32)pPager->sectorSize;
|
||||
}
|
||||
if( rc==SQLITE_OK && !readOnly ){
|
||||
setSectorSize(pPager);
|
||||
assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
|
||||
if( szPageDflt<pPager->sectorSize ){
|
||||
if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
|
||||
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
|
||||
}else{
|
||||
szPageDflt = (u32)pPager->sectorSize;
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
{
|
||||
int ii;
|
||||
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
|
||||
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
|
||||
assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
|
||||
for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
|
||||
if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
|
||||
szPageDflt = ii;
|
||||
}
|
||||
{
|
||||
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
|
||||
int ii;
|
||||
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
|
||||
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
|
||||
assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
|
||||
for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
|
||||
if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
|
||||
szPageDflt = ii;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
|
||||
if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
|
||||
|| sqlite3_uri_boolean(zFilename, "immutable", 0) ){
|
||||
vfsFlags |= SQLITE_OPEN_READONLY;
|
||||
goto act_like_temp_file;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* If a temporary file is requested, it is not opened immediately.
|
||||
@@ -4716,14 +4707,10 @@ int sqlite3PagerOpen(
|
||||
** This branch is also run for an in-memory database. An in-memory
|
||||
** database is the same as a temp-file that is never written out to
|
||||
** disk and uses an in-memory rollback journal.
|
||||
**
|
||||
** This branch also runs for files marked as immutable.
|
||||
*/
|
||||
act_like_temp_file:
|
||||
tempFile = 1;
|
||||
pPager->eState = PAGER_READER; /* Pretend we already have a lock */
|
||||
pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE locking mode */
|
||||
pPager->noLock = 1; /* Do no locking */
|
||||
pPager->eState = PAGER_READER;
|
||||
pPager->eLock = EXCLUSIVE_LOCK;
|
||||
readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
|
||||
}
|
||||
|
||||
@@ -4764,6 +4751,9 @@ act_like_temp_file:
|
||||
/* pPager->nPage = 0; */
|
||||
pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
|
||||
/* pPager->state = PAGER_UNLOCK; */
|
||||
#if 0
|
||||
assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
|
||||
#endif
|
||||
/* pPager->errMask = 0; */
|
||||
pPager->tempFile = (u8)tempFile;
|
||||
assert( tempFile==PAGER_LOCKINGMODE_NORMAL
|
||||
|
||||
+92
-64
@@ -455,28 +455,43 @@ static KeyInfo *keyInfoFromExprList(
|
||||
);
|
||||
|
||||
/*
|
||||
** Insert code into "v" that will push the record in register regData
|
||||
** into the sorter.
|
||||
** Generate code that will push the record in registers regData
|
||||
** through regData+nData-1 onto the sorter.
|
||||
*/
|
||||
static void pushOntoSorter(
|
||||
Parse *pParse, /* Parser context */
|
||||
SortCtx *pSort, /* Information about the ORDER BY clause */
|
||||
Select *pSelect, /* The whole SELECT statement */
|
||||
int regData /* Register holding data to be sorted */
|
||||
int regData, /* First register holding data to be sorted */
|
||||
int nData, /* Number of elements in the data array */
|
||||
int nPrefixReg /* No. of reg prior to regData available for use */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int nExpr = pSort->pOrderBy->nExpr;
|
||||
int regRecord = ++pParse->nMem;
|
||||
int regBase = pParse->nMem+1;
|
||||
int nOBSat = pSort->nOBSat;
|
||||
int op;
|
||||
Vdbe *v = pParse->pVdbe; /* Stmt under construction */
|
||||
int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0);
|
||||
int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */
|
||||
int nBase = nExpr + bSeq + nData; /* Fields in sorter record */
|
||||
int regBase; /* Regs for sorter record */
|
||||
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 */
|
||||
|
||||
pParse->nMem += nExpr+2; /* nExpr+2 registers allocated at regBase */
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
|
||||
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat,regRecord);
|
||||
assert( bSeq==0 || bSeq==1 );
|
||||
if( nPrefixReg ){
|
||||
assert( nPrefixReg==nExpr+bSeq );
|
||||
regBase = regData - nExpr - bSeq;
|
||||
}else{
|
||||
regBase = pParse->nMem + 1;
|
||||
pParse->nMem += nBase;
|
||||
}
|
||||
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, SQLITE_ECEL_DUP);
|
||||
if( bSeq ){
|
||||
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
|
||||
}
|
||||
if( nPrefixReg==0 ){
|
||||
sqlite3VdbeAddOp3(v, OP_Move, 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 */
|
||||
int addrFirst; /* Address of the OP_IfNot opcode */
|
||||
@@ -487,12 +502,17 @@ static void pushOntoSorter(
|
||||
|
||||
regPrevKey = pParse->nMem+1;
|
||||
pParse->nMem += pSort->nOBSat;
|
||||
nKey = nExpr - pSort->nOBSat + 1;
|
||||
addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); VdbeCoverage(v);
|
||||
nKey = nExpr - pSort->nOBSat + bSeq;
|
||||
if( bSeq ){
|
||||
addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr);
|
||||
}else{
|
||||
addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor);
|
||||
}
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
|
||||
pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
|
||||
if( pParse->db->mallocFailed ) return;
|
||||
pOp->p2 = nKey + 1;
|
||||
pOp->p2 = nKey + nData;
|
||||
pKI = pOp->p4.pKeyInfo;
|
||||
memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
|
||||
@@ -627,6 +647,7 @@ static void selectInnerLoop(
|
||||
int eDest = pDest->eDest; /* How to dispose of results */
|
||||
int iParm = pDest->iSDParm; /* First argument to disposal method */
|
||||
int nResultCol; /* Number of result columns */
|
||||
int nPrefixReg = 0; /* Number of extra registers before regResult */
|
||||
|
||||
assert( v );
|
||||
assert( pEList!=0 );
|
||||
@@ -642,6 +663,11 @@ static void selectInnerLoop(
|
||||
nResultCol = pEList->nExpr;
|
||||
|
||||
if( pDest->iSdst==0 ){
|
||||
if( pSort ){
|
||||
nPrefixReg = pSort->pOrderBy->nExpr;
|
||||
if( !(pSort->sortFlags & SORTFLAG_UseSorter) ) nPrefixReg++;
|
||||
pParse->nMem += nPrefixReg;
|
||||
}
|
||||
pDest->iSdst = pParse->nMem+1;
|
||||
pParse->nMem += nResultCol;
|
||||
}else if( pDest->iSdst+nResultCol > pParse->nMem ){
|
||||
@@ -758,10 +784,10 @@ static void selectInnerLoop(
|
||||
case SRT_DistFifo:
|
||||
case SRT_Table:
|
||||
case SRT_EphemTab: {
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1);
|
||||
testcase( eDest==SRT_Table );
|
||||
testcase( eDest==SRT_EphemTab );
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
if( eDest==SRT_DistFifo ){
|
||||
/* If the destination is DistFifo, then cursor (iParm+1) is open
|
||||
@@ -776,7 +802,7 @@ static void selectInnerLoop(
|
||||
}
|
||||
#endif
|
||||
if( pSort ){
|
||||
pushOntoSorter(pParse, pSort, p, r1);
|
||||
pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, 1, nPrefixReg);
|
||||
}else{
|
||||
int r2 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
|
||||
@@ -784,7 +810,7 @@ static void selectInnerLoop(
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
sqlite3ReleaseTempReg(pParse, r2);
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -802,7 +828,7 @@ static void selectInnerLoop(
|
||||
** ORDER BY in this case since the order of entries in the set
|
||||
** does not matter. But there might be a LIMIT clause, in which
|
||||
** case the order does matter */
|
||||
pushOntoSorter(pParse, pSort, p, regResult);
|
||||
pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg);
|
||||
}else{
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
|
||||
@@ -828,7 +854,7 @@ static void selectInnerLoop(
|
||||
case SRT_Mem: {
|
||||
assert( nResultCol==1 );
|
||||
if( pSort ){
|
||||
pushOntoSorter(pParse, pSort, p, regResult);
|
||||
pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg);
|
||||
}else{
|
||||
sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
|
||||
/* The LIMIT clause will jump out of the loop for us */
|
||||
@@ -842,10 +868,7 @@ static void selectInnerLoop(
|
||||
testcase( eDest==SRT_Coroutine );
|
||||
testcase( eDest==SRT_Output );
|
||||
if( pSort ){
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
|
||||
pushOntoSorter(pParse, pSort, p, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
pushOntoSorter(pParse, pSort, p, regResult, nResultCol, nPrefixReg);
|
||||
}else if( eDest==SRT_Coroutine ){
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
|
||||
}else{
|
||||
@@ -1125,46 +1148,62 @@ static void generateSortTail(
|
||||
int addr;
|
||||
int addrOnce = 0;
|
||||
int iTab;
|
||||
int pseudoTab = 0;
|
||||
ExprList *pOrderBy = pSort->pOrderBy;
|
||||
int eDest = pDest->eDest;
|
||||
int iParm = pDest->iSDParm;
|
||||
int regRow;
|
||||
int regRowid;
|
||||
int nKey;
|
||||
int iSortTab; /* Sorter cursor to read from */
|
||||
int nSortData; /* Trailing values to read from sorter */
|
||||
u8 p5; /* p5 parameter for 1st OP_Column */
|
||||
int i;
|
||||
int bSeq; /* True if sorter record includes seq. no. */
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
struct ExprList_item *aOutEx = p->pEList->a;
|
||||
#endif
|
||||
|
||||
if( pSort->labelBkOut ){
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak);
|
||||
sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
|
||||
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
}
|
||||
iTab = pSort->iECursor;
|
||||
regRow = sqlite3GetTempReg(pParse);
|
||||
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
|
||||
pseudoTab = pParse->nTab++;
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
|
||||
regRowid = 0;
|
||||
regRow = pDest->iSdst;
|
||||
nSortData = nColumn;
|
||||
}else{
|
||||
regRowid = sqlite3GetTempReg(pParse);
|
||||
regRow = sqlite3GetTempReg(pParse);
|
||||
nSortData = 1;
|
||||
}
|
||||
nKey = pOrderBy->nExpr - pSort->nOBSat;
|
||||
if( pSort->sortFlags & SORTFLAG_UseSorter ){
|
||||
int regSortOut = ++pParse->nMem;
|
||||
int ptab2 = pParse->nTab++;
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, nKey+2);
|
||||
iSortTab = pParse->nTab++;
|
||||
if( pSort->labelBkOut ){
|
||||
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData);
|
||||
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
|
||||
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
|
||||
VdbeCoverage(v);
|
||||
codeOffset(v, p->iOffset, addrContinue);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, ptab2, nKey+1, regRow);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
|
||||
p5 = OPFLAG_CLEARCACHE;
|
||||
bSeq = 0;
|
||||
}else{
|
||||
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
|
||||
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
|
||||
codeOffset(v, p->iOffset, addrContinue);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iTab, nKey+1, regRow);
|
||||
iSortTab = iTab;
|
||||
p5 = 0;
|
||||
bSeq = 1;
|
||||
}
|
||||
for(i=0; i<nSortData; i++){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
|
||||
if( i==0 ) sqlite3VdbeChangeP5(v, p5);
|
||||
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
|
||||
}
|
||||
switch( eDest ){
|
||||
case SRT_Table:
|
||||
@@ -1193,17 +1232,9 @@ static void generateSortTail(
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
int i;
|
||||
assert( eDest==SRT_Output || eDest==SRT_Coroutine );
|
||||
testcase( eDest==SRT_Output );
|
||||
testcase( eDest==SRT_Coroutine );
|
||||
for(i=0; i<nColumn; i++){
|
||||
assert( regRow!=pDest->iSdst+i );
|
||||
sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iSdst+i);
|
||||
if( i==0 ){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
|
||||
}
|
||||
}
|
||||
if( eDest==SRT_Output ){
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
|
||||
sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
|
||||
@@ -1213,9 +1244,10 @@ static void generateSortTail(
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, regRow);
|
||||
sqlite3ReleaseTempReg(pParse, regRowid);
|
||||
|
||||
if( regRowid ){
|
||||
sqlite3ReleaseTempReg(pParse, regRow);
|
||||
sqlite3ReleaseTempReg(pParse, regRowid);
|
||||
}
|
||||
/* The bottom of the loop
|
||||
*/
|
||||
sqlite3VdbeResolveLabel(v, addrContinue);
|
||||
@@ -1226,9 +1258,6 @@ static void generateSortTail(
|
||||
}
|
||||
if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
|
||||
sqlite3VdbeResolveLabel(v, addrBreak);
|
||||
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
|
||||
sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4498,11 +4527,10 @@ static void explainSimpleCount(
|
||||
Index *pIdx /* Index used to optimize scan, or NULL */
|
||||
){
|
||||
if( pParse->explain==2 ){
|
||||
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
|
||||
char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
|
||||
pTab->zName,
|
||||
bCover ? " USING COVERING INDEX " : "",
|
||||
bCover ? pIdx->zName : ""
|
||||
pTab->zName,
|
||||
pIdx ? " USING COVERING INDEX " : "",
|
||||
pIdx ? pIdx->zName : ""
|
||||
);
|
||||
sqlite3VdbeAddOp4(
|
||||
pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
|
||||
@@ -4759,8 +4787,9 @@ int sqlite3Select(
|
||||
sSort.iECursor = pParse->nTab++;
|
||||
sSort.addrSortIndex =
|
||||
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
|
||||
sSort.iECursor, sSort.pOrderBy->nExpr+2, 0,
|
||||
(char*)pKeyInfo, P4_KEYINFO);
|
||||
sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0,
|
||||
(char*)pKeyInfo, P4_KEYINFO
|
||||
);
|
||||
}else{
|
||||
sSort.addrSortIndex = -1;
|
||||
}
|
||||
@@ -4891,7 +4920,7 @@ int sqlite3Select(
|
||||
sNC.pSrcList = pTabList;
|
||||
sNC.pAggInfo = &sAggInfo;
|
||||
sAggInfo.mnReg = pParse->nMem+1;
|
||||
sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
|
||||
sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
|
||||
sAggInfo.pGroupBy = pGroupBy;
|
||||
sqlite3ExprAnalyzeAggList(&sNC, pEList);
|
||||
sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
|
||||
@@ -4984,8 +5013,8 @@ int sqlite3Select(
|
||||
|
||||
groupBySort = 1;
|
||||
nGroupBy = pGroupBy->nExpr;
|
||||
nCol = nGroupBy + 1;
|
||||
j = nGroupBy+1;
|
||||
nCol = nGroupBy;
|
||||
j = nGroupBy;
|
||||
for(i=0; i<sAggInfo.nColumn; i++){
|
||||
if( sAggInfo.aCol[i].iSorterColumn>=j ){
|
||||
nCol++;
|
||||
@@ -4995,8 +5024,7 @@ int sqlite3Select(
|
||||
regBase = sqlite3GetTempRange(pParse, nCol);
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
|
||||
j = nGroupBy+1;
|
||||
j = nGroupBy;
|
||||
for(i=0; i<sAggInfo.nColumn; i++){
|
||||
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
|
||||
if( pCol->iSorterColumn>=j ){
|
||||
|
||||
+3
-4
@@ -697,8 +697,7 @@ static void output_csv(struct callback_data *p, const char *z, int bSep){
|
||||
*/
|
||||
static void interrupt_handler(int NotUsed){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
seenInterrupt++;
|
||||
if( seenInterrupt>2 ) exit(1);
|
||||
seenInterrupt = 1;
|
||||
if( db ) sqlite3_interrupt(db);
|
||||
}
|
||||
#endif
|
||||
@@ -2431,7 +2430,6 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
nByte = strlen30(zSql);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
csv_append_char(&sCsv, 0); /* To ensure sCsv.z is allocated */
|
||||
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
|
||||
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
|
||||
char cSep = '(';
|
||||
@@ -3538,7 +3536,8 @@ static void main_init(struct callback_data *data) {
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
|
||||
sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
|
||||
sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
|
||||
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
|
||||
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
|
||||
sqlite3_config(SQLITE_CONFIG_WORKER_THREADS, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+22
-42
@@ -555,10 +555,7 @@ int sqlite3_exec(
|
||||
** file that were written at the application level might have changed
|
||||
** and that adjacent bytes, even bytes within the same sector are
|
||||
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
||||
** flag indicate that a file cannot be deleted when open. The
|
||||
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
|
||||
** read-only media and cannot be changed even by processes with
|
||||
** elevated privileges.
|
||||
** flag indicate that a file cannot be deleted when open.
|
||||
*/
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
@@ -573,7 +570,6 @@ int sqlite3_exec(
|
||||
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
|
||||
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
|
||||
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
|
||||
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
|
||||
|
||||
/*
|
||||
** CAPI3REF: File Locking Levels
|
||||
@@ -942,12 +938,6 @@ struct sqlite3_io_methods {
|
||||
** on whether or not the file has been renamed, moved, or deleted since it
|
||||
** was first opened.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
|
||||
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
|
||||
** opcode causes the xFileControl method to swap the file handle with the one
|
||||
** pointed to by the pArg argument. This capability is used during testing
|
||||
** and only needs to be supported when SQLITE_TEST is defined.
|
||||
**
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
@@ -971,7 +961,6 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_HAS_MOVED 20
|
||||
#define SQLITE_FCNTL_SYNC 21
|
||||
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
|
||||
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
@@ -1726,6 +1715,16 @@ struct sqlite3_mem_methods {
|
||||
** SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
|
||||
** that specifies the maximum size of the created heap.
|
||||
** </dl>
|
||||
**
|
||||
** [[SQLITE_CONFIG_WORKER_THREADS]]
|
||||
** <dt>SQLITE_CONFIG_WORKER_THREADS
|
||||
** <dd>^SQLITE_CONFIG_WORKER_THREADS takes a single argument of type int.
|
||||
** It is used to set the number of background worker threads that may be
|
||||
** launched when sorting large amounts of data. A value of 0 means launch
|
||||
** no background threads at all. The maximum number of background threads
|
||||
** allowed is configured at build-time by the SQLITE_MAX_WORKER_THREADS
|
||||
** pre-processor option.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
|
||||
@@ -1750,6 +1749,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
|
||||
#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
|
||||
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
|
||||
#define SQLITE_CONFIG_WORKER_THREADS 24 /* int nWorker */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@@ -2785,30 +2785,6 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
|
||||
** a URI filename, its value overrides any behavior requested by setting
|
||||
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
|
||||
**
|
||||
** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
|
||||
** "1") or "false" (or "off" or "no" or "0") to indicate that the
|
||||
** [powersafe overwrite] property does or does not apply to the
|
||||
** storage media on which the database file resides. ^The psow query
|
||||
** parameter only works for the built-in unix and Windows VFSes.
|
||||
**
|
||||
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
|
||||
** which if set disables file locking in rollback journal modes. This
|
||||
** is useful for accessing a database on a filesystem that does not
|
||||
** support locking. Caution: Database corruption might result if two
|
||||
** or more processes write to the same database and any one of those
|
||||
** processes uses nolock=1.
|
||||
**
|
||||
** <li> <b>immutable</b>: ^The immutable parameter is a boolean query
|
||||
** parameter that indicates that the database file is stored on
|
||||
** read-only media. ^When immutable is set, SQLite assumes that the
|
||||
** database file cannot be changed, even by a process with higher
|
||||
** privilege, and so the database is opened read-only and all locking
|
||||
** and change detection is disabled. Caution: Setting the immutable
|
||||
** property on a database file that does in fact change can result
|
||||
** in incorrect query results and/or [SQLITE_CORRUPT] errors.
|
||||
** See also: [SQLITE_IOCAP_IMMUTABLE].
|
||||
**
|
||||
** </ul>
|
||||
**
|
||||
** ^Specifying an unknown parameter in the query component of a URI is not an
|
||||
@@ -2838,9 +2814,8 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** Open file "data.db" in the current directory for read-only access.
|
||||
** Regardless of whether or not shared-cache mode is enabled by
|
||||
** default, use a private cache.
|
||||
** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
|
||||
** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
|
||||
** that uses dot-files in place of posix advisory locking.
|
||||
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
|
||||
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
|
||||
** <tr><td> file:data.db?mode=readonly <td>
|
||||
** An error. "readonly" is not a valid option for the "mode" parameter.
|
||||
** </table>
|
||||
@@ -5853,10 +5828,12 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
|
||||
** <li> SQLITE_MUTEX_RECURSIVE
|
||||
** <li> SQLITE_MUTEX_STATIC_MASTER
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM2
|
||||
** <li> SQLITE_MUTEX_STATIC_OPEN
|
||||
** <li> SQLITE_MUTEX_STATIC_PRNG
|
||||
** <li> SQLITE_MUTEX_STATIC_LRU
|
||||
** <li> SQLITE_MUTEX_STATIC_LRU2
|
||||
** <li> SQLITE_MUTEX_STATIC_PMEM
|
||||
** <li> SQLITE_MUTEX_STATIC_APP1
|
||||
** <li> SQLITE_MUTEX_STATIC_APP2
|
||||
** </ul>)^
|
||||
**
|
||||
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
|
||||
@@ -6060,6 +6037,8 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
|
||||
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
|
||||
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
|
||||
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
|
||||
#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
|
||||
#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Retrieve the mutex for a database connection
|
||||
@@ -6155,7 +6134,8 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
|
||||
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
|
||||
#define SQLITE_TESTCTRL_BYTEORDER 22
|
||||
#define SQLITE_TESTCTRL_LAST 22
|
||||
#define SQLITE_TESTCTRL_SORTER_MMAP 23
|
||||
#define SQLITE_TESTCTRL_LAST 23
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
|
||||
+42
-23
@@ -422,6 +422,26 @@
|
||||
# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if
|
||||
** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it
|
||||
** to zero.
|
||||
*/
|
||||
#if SQLITE_TEMP_STORE==3
|
||||
# undef SQLITE_MAX_WORKER_THREADS
|
||||
#endif
|
||||
#ifndef SQLITE_MAX_WORKER_THREADS
|
||||
# define SQLITE_MAX_WORKER_THREADS 0
|
||||
#endif
|
||||
#ifndef SQLITE_DEFAULT_WORKER_THREADS
|
||||
# define SQLITE_DEFAULT_WORKER_THREADS 0
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_WORKER_THREADS>SQLITE_MAX_WORKER_THREADS
|
||||
# undef SQLITE_MAX_WORKER_THREADS
|
||||
# define SQLITE_MAX_WORKER_THREADS SQLITE_DEFAULT_WORKER_THREADS
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** GCC does not define the offsetof() macro so we'll have to do it
|
||||
** ourselves.
|
||||
@@ -805,6 +825,7 @@ typedef struct PrintfArguments PrintfArguments;
|
||||
typedef struct RowSet RowSet;
|
||||
typedef struct Savepoint Savepoint;
|
||||
typedef struct Select Select;
|
||||
typedef struct SQLiteThread SQLiteThread;
|
||||
typedef struct SelectDest SelectDest;
|
||||
typedef struct SrcList SrcList;
|
||||
typedef struct StrAccum StrAccum;
|
||||
@@ -984,6 +1005,7 @@ struct sqlite3 {
|
||||
int nChange; /* Value returned by sqlite3_changes() */
|
||||
int nTotalChange; /* Value returned by sqlite3_total_changes() */
|
||||
int aLimit[SQLITE_N_LIMIT]; /* Limits */
|
||||
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
|
||||
struct sqlite3InitInfo { /* Information used during initialization */
|
||||
int newTnum; /* Rootpage of table being initialized */
|
||||
u8 iDb; /* Which db file is being initialized */
|
||||
@@ -1644,7 +1666,7 @@ struct UnpackedRecord {
|
||||
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
||||
u16 nField; /* Number of entries in apMem[] */
|
||||
i8 default_rc; /* Comparison result if keys are equal */
|
||||
u8 isCorrupt; /* Corruption detected by xRecordCompare() */
|
||||
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
|
||||
Mem *aMem; /* Values */
|
||||
int r1; /* Value to return if (lhs > rhs) */
|
||||
int r2; /* Value to return if (rhs < lhs) */
|
||||
@@ -1694,7 +1716,7 @@ struct Index {
|
||||
u16 nKeyCol; /* Number of columns forming the key */
|
||||
u16 nColumn; /* Number of columns stored in the index */
|
||||
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
|
||||
unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
|
||||
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
|
||||
unsigned bUnordered:1; /* Use this index for == or IN queries only */
|
||||
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
|
||||
unsigned isResized:1; /* True if resizeIndexObject() has been called */
|
||||
@@ -1707,16 +1729,6 @@ struct Index {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values for Index.idxType
|
||||
*/
|
||||
#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
|
||||
#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
|
||||
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
|
||||
|
||||
/* Return true if index X is a PRIMARY KEY index */
|
||||
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
|
||||
|
||||
/*
|
||||
** Each sample stored in the sqlite_stat3 table is represented in memory
|
||||
** using a structure of this type. See documentation at the top of the
|
||||
@@ -2712,6 +2724,7 @@ struct Sqlite3Config {
|
||||
int nPage; /* Number of pages in pPage[] */
|
||||
int mxParserStack; /* maximum depth of the parser stack */
|
||||
int sharedCacheEnabled; /* true if shared-cache mode enabled */
|
||||
int nWorker; /* Number of worker threads to use */
|
||||
/* The above might be initialized to non-zero. The following need to always
|
||||
** initially be zero, however. */
|
||||
int isInit; /* True after initialization has finished */
|
||||
@@ -2719,10 +2732,11 @@ struct Sqlite3Config {
|
||||
int isMutexInit; /* True after mutexes are initialized */
|
||||
int isMallocInit; /* True after malloc is initialized */
|
||||
int isPCacheInit; /* True after malloc is initialized */
|
||||
int nRefInitMutex; /* Number of users of pInitMutex */
|
||||
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
|
||||
int nRefInitMutex; /* Number of users of pInitMutex */
|
||||
void (*xLog)(void*,int,const char*); /* Function for logging */
|
||||
void *pLogArg; /* First argument to xLog() */
|
||||
int bLocaltimeFault; /* True to fail localtime() calls */
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
void(*xSqllog)(void*,sqlite3*,const char*, int);
|
||||
void *pSqllogArg;
|
||||
@@ -2734,10 +2748,6 @@ struct Sqlite3Config {
|
||||
void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
|
||||
void *pVdbeBranchArg; /* 1st argument */
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
||||
#endif
|
||||
int bLocaltimeFault; /* True to fail localtime() calls */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3039,12 +3049,6 @@ int sqlite3ParseUri(const char*,const char*,unsigned int*,
|
||||
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
|
||||
int sqlite3CodeOnce(Parse *);
|
||||
|
||||
#ifdef SQLITE_OMIT_BUILTIN_TEST
|
||||
# define sqlite3FaultSim(X) SQLITE_OK
|
||||
#else
|
||||
int sqlite3FaultSim(int);
|
||||
#endif
|
||||
|
||||
Bitvec *sqlite3BitvecCreate(u32);
|
||||
int sqlite3BitvecTest(Bitvec*, u32);
|
||||
int sqlite3BitvecSet(Bitvec*, u32);
|
||||
@@ -3672,4 +3676,19 @@ SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
|
||||
#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
|
||||
#define MEMTYPE_DB 0x10 /* Uses sqlite3DbMalloc, not sqlite_malloc */
|
||||
|
||||
/*
|
||||
** Threading interface
|
||||
*/
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
|
||||
int sqlite3ThreadJoin(SQLiteThread*, void**);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Win32 interface
|
||||
*/
|
||||
#if SQLITE_OS_WIN
|
||||
DWORD sqlite3Win32Wait(HANDLE hObject);
|
||||
#endif
|
||||
|
||||
#endif /* _SQLITEINT_H_ */
|
||||
|
||||
+164
-54
@@ -14,10 +14,6 @@
|
||||
** testing of the SQLite library.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#if SQLITE_OS_WIN
|
||||
# include "os_win.h"
|
||||
#endif
|
||||
|
||||
#include "vdbeInt.h"
|
||||
#include "tcl.h"
|
||||
#include <stdlib.h>
|
||||
@@ -117,16 +113,6 @@ int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#if SQLITE_OS_WIN
|
||||
/*
|
||||
** Decode a Win32 HANDLE object.
|
||||
*/
|
||||
int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
|
||||
*phFile = (HANDLE)sqlite3TestTextToPtr(zA);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern const char *sqlite3ErrName(int);
|
||||
#define t1ErrorName sqlite3ErrName
|
||||
|
||||
@@ -2717,6 +2703,46 @@ bad_args:
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: add_test_utf16bin_collate <db ptr>
|
||||
**
|
||||
** Add a utf-16 collation sequence named "utf16bin" to the database
|
||||
** handle. This collation sequence compares arguments in the same way as the
|
||||
** built-in collation "binary".
|
||||
*/
|
||||
static int test_utf16bin_collate_func(
|
||||
void *pCtx,
|
||||
int nA, const void *zA,
|
||||
int nB, const void *zB
|
||||
){
|
||||
int nCmp = (nA>nB ? nB : nA);
|
||||
int res = memcmp(zA, zB, nCmp);
|
||||
if( res==0 ) res = nA - nB;
|
||||
return res;
|
||||
}
|
||||
static int test_utf16bin_collate(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
if( objc!=2 ) goto bad_args;
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
|
||||
test_utf16bin_collate_func
|
||||
);
|
||||
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
||||
return TCL_OK;
|
||||
|
||||
bad_args:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** When the collation needed callback is invoked, record the name of
|
||||
** the requested collating function here. The recorded name is linked
|
||||
@@ -5220,7 +5246,6 @@ static int file_control_lockproxy_test(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#if SQLITE_OS_WIN
|
||||
/*
|
||||
** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
|
||||
**
|
||||
@@ -5254,42 +5279,6 @@ static int file_control_win32_av_retry(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: file_control_win32_set_handle DB HANDLE
|
||||
**
|
||||
** This TCL command runs the sqlite3_file_control interface with
|
||||
** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
|
||||
*/
|
||||
static int file_control_win32_set_handle(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
HANDLE hFile = NULL;
|
||||
char z[100];
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
|
||||
(void*)&hFile);
|
||||
sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
|
||||
Tcl_AppendResult(interp, z, (char*)0);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** tclcmd: file_control_persist_wal DB PERSIST-FLAG
|
||||
**
|
||||
@@ -5895,6 +5884,7 @@ static int test_test_control(
|
||||
int i;
|
||||
} aVerb[] = {
|
||||
{ "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
|
||||
{ "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
|
||||
};
|
||||
int iVerb;
|
||||
int iFlag;
|
||||
@@ -5922,6 +5912,19 @@ static int test_test_control(
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
|
||||
break;
|
||||
}
|
||||
|
||||
case SQLITE_TESTCTRL_SORTER_MMAP: {
|
||||
int val;
|
||||
sqlite3 *db;
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
@@ -6333,6 +6336,113 @@ static int tclLoadStaticExtensionCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sorter_test_fakeheap BOOL
|
||||
**
|
||||
*/
|
||||
static int sorter_test_fakeheap(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int bArg;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( bArg ){
|
||||
if( sqlite3GlobalConfig.pHeap==0 ){
|
||||
sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
|
||||
}
|
||||
}else{
|
||||
if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
|
||||
sqlite3GlobalConfig.pHeap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sorter_test_sort4_helper DB SQL1 NSTEP SQL2
|
||||
**
|
||||
** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
|
||||
** check that the leftmost and rightmost columns returned are both integers,
|
||||
** and that both contain the same value.
|
||||
**
|
||||
** Then execute statement $SQL2. Check that the statement returns the same
|
||||
** set of integers in the same order as in the previous step (using $SQL1).
|
||||
*/
|
||||
static int sorter_test_sort4_helper(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
const char *zSql1;
|
||||
const char *zSql2;
|
||||
int nStep;
|
||||
int iStep;
|
||||
int iCksum1 = 0;
|
||||
int iCksum2 = 0;
|
||||
int rc;
|
||||
int iB;
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
if( objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
zSql1 = Tcl_GetString(objv[2]);
|
||||
if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
|
||||
zSql2 = Tcl_GetString(objv[4]);
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
|
||||
iB = sqlite3_column_count(pStmt)-1;
|
||||
for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
|
||||
int a = sqlite3_column_int(pStmt, 0);
|
||||
if( a!=sqlite3_column_int(pStmt, iB) ){
|
||||
Tcl_AppendResult(interp, "data error: (a!=b)", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
iCksum1 += (iCksum1 << 3) + a;
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
|
||||
int a = sqlite3_column_int(pStmt, 0);
|
||||
iCksum2 += (iCksum2 << 3) + a;
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
|
||||
if( iCksum1!=iCksum2 ){
|
||||
Tcl_AppendResult(interp, "checksum mismatch", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
sql_error:
|
||||
Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register commands with the TCL interpreter.
|
||||
@@ -6519,10 +6629,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
|
||||
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
|
||||
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
|
||||
#if SQLITE_OS_WIN
|
||||
{ "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
|
||||
{ "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
|
||||
#endif
|
||||
{ "file_control_persist_wal", file_control_persist_wal, 0 },
|
||||
{ "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
|
||||
{ "file_control_vfsname", file_control_vfsname, 0 },
|
||||
@@ -6535,6 +6642,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "add_test_collate", test_collate, 0 },
|
||||
{ "add_test_collate_needed", test_collate_needed, 0 },
|
||||
{ "add_test_function", test_function, 0 },
|
||||
{ "add_test_utf16bin_collate", test_utf16bin_collate, 0 },
|
||||
#endif
|
||||
{ "sqlite3_test_errstr", test_errstr, 0 },
|
||||
{ "tcl_variable_type", tcl_variable_type, 0 },
|
||||
@@ -6568,6 +6676,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "getrusage", test_getrusage },
|
||||
#endif
|
||||
{ "load_static_extension", tclLoadStaticExtensionCmd },
|
||||
{ "sorter_test_fakeheap", sorter_test_fakeheap },
|
||||
{ "sorter_test_sort4_helper", sorter_test_sort4_helper },
|
||||
};
|
||||
static int bitmask_size = sizeof(Bitmask)*8;
|
||||
int i;
|
||||
|
||||
+2
-86
@@ -568,90 +568,7 @@ static int testPendingByte(
|
||||
rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3FaultSim() callback:
|
||||
*/
|
||||
static Tcl_Interp *faultSimInterp = 0;
|
||||
static int faultSimScriptSize = 0;
|
||||
static char *faultSimScript;
|
||||
static int faultSimCallback(int x){
|
||||
char zInt[30];
|
||||
int i;
|
||||
int isNeg;
|
||||
int rc;
|
||||
if( x==0 ){
|
||||
memcpy(faultSimScript+faultSimScriptSize, "0", 2);
|
||||
}else{
|
||||
/* Convert x to text without using any sqlite3 routines */
|
||||
if( x<0 ){
|
||||
isNeg = 1;
|
||||
x = -x;
|
||||
}else{
|
||||
isNeg = 0;
|
||||
}
|
||||
zInt[sizeof(zInt)-1] = 0;
|
||||
for(i=sizeof(zInt)-2; i>0 && x>0; i--, x /= 10){
|
||||
zInt[i] = (x%10) + '0';
|
||||
}
|
||||
if( isNeg ) zInt[i--] = '-';
|
||||
memcpy(faultSimScript+faultSimScriptSize, zInt+i+1, sizeof(zInt)-i);
|
||||
}
|
||||
rc = Tcl_Eval(faultSimInterp, faultSimScript);
|
||||
if( rc ){
|
||||
fprintf(stderr, "fault simulator script failed: [%s]", faultSimScript);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = atoi(Tcl_GetStringResult(faultSimInterp));
|
||||
}
|
||||
Tcl_ResetResult(faultSimInterp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_test_control_fault_install SCRIPT
|
||||
**
|
||||
** Arrange to invoke SCRIPT with the integer argument to sqlite3FaultSim()
|
||||
** appended, whenever sqlite3FaultSim() is called. Or, if SCRIPT is the
|
||||
** empty string, cancel the sqlite3FaultSim() callback.
|
||||
*/
|
||||
static int faultInstallCmd(
|
||||
void *NotUsed,
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int argc, /* Number of arguments */
|
||||
const char **argv /* Text of each argument */
|
||||
){
|
||||
const char *zScript;
|
||||
int nScript;
|
||||
int rc;
|
||||
if( argc!=1 && argc!=2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" SCRIPT\"", (void*)0);
|
||||
}
|
||||
zScript = argc==2 ? argv[1] : "";
|
||||
nScript = (int)strlen(zScript);
|
||||
if( faultSimScript ){
|
||||
free(faultSimScript);
|
||||
faultSimScript = 0;
|
||||
}
|
||||
if( nScript==0 ){
|
||||
rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, 0);
|
||||
}else{
|
||||
faultSimScript = malloc( nScript+100 );
|
||||
if( faultSimScript==0 ){
|
||||
Tcl_AppendResult(interp, "out of memory", (void*)0);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
memcpy(faultSimScript, zScript, nScript);
|
||||
faultSimScript[nScript] = ' ';
|
||||
faultSimScriptSize = nScript+1;
|
||||
faultSimInterp = interp;
|
||||
rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, faultSimCallback);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3BitvecBuiltinTest SIZE PROGRAM
|
||||
@@ -721,8 +638,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
|
||||
{ "fake_big_file", (Tcl_CmdProc*)fake_big_file },
|
||||
#endif
|
||||
{ "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest },
|
||||
{ "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte },
|
||||
{ "sqlite3_test_control_fault_install", (Tcl_CmdProc*)faultInstallCmd },
|
||||
{ "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte },
|
||||
};
|
||||
int i;
|
||||
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
|
||||
|
||||
+4
-4
@@ -20,10 +20,6 @@
|
||||
#include "sqliteLimit.h"
|
||||
|
||||
#include "sqliteInt.h"
|
||||
#if SQLITE_OS_WIN
|
||||
# include "os_win.h"
|
||||
#endif
|
||||
|
||||
#include "tcl.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -103,6 +99,10 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "mmap", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
Tcl_SetVar2(interp, "sqlite_options", "worker_threads",
|
||||
STRINGVALUE(SQLITE_MAX_WORKER_THREADS), TCL_GLOBAL_ONLY
|
||||
);
|
||||
|
||||
#if 1 /* def SQLITE_MEMDEBUG */
|
||||
Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
@@ -1253,6 +1253,32 @@ static int test_config_cis(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_config_worker_threads N
|
||||
*/
|
||||
static int test_config_worker_threads(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int rc;
|
||||
int nThread;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "N");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIntFromObj(interp, objv[1], &nThread) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = sqlite3_config(SQLITE_CONFIG_WORKER_THREADS, nThread);
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_dump_memsys3 FILENAME
|
||||
** sqlite3_dump_memsys5 FILENAME
|
||||
@@ -1506,6 +1532,7 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_config_error", test_config_error ,0 },
|
||||
{ "sqlite3_config_uri", test_config_uri ,0 },
|
||||
{ "sqlite3_config_cis", test_config_cis ,0 },
|
||||
{ "sqlite3_config_worker_threads", test_config_worker_threads ,0 },
|
||||
{ "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
|
||||
{ "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
|
||||
{ "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
|
||||
|
||||
+1
-6
@@ -70,12 +70,6 @@
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
#include "os_setup.h"
|
||||
#if SQLITE_OS_WIN
|
||||
# include "os_win.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -227,6 +221,7 @@ static sqlite3_uint64 vfslog_time(){
|
||||
return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
|
||||
}
|
||||
#elif SQLITE_OS_WIN
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
static sqlite3_uint64 vfslog_time(){
|
||||
FILETIME ft;
|
||||
|
||||
+38
-2
@@ -44,13 +44,49 @@
|
||||
#define sqlite3_mutex_notheld(X) ((void)(X),1)
|
||||
#endif /* SQLITE_THREADSAFE==0 */
|
||||
|
||||
#include "os_setup.h"
|
||||
|
||||
/*
|
||||
** Figure out if we are dealing with Unix, Windows, or some other
|
||||
** operating system. After the following block of preprocess macros,
|
||||
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
|
||||
** will defined to either 1 or 0. One of the four will be 1. The other
|
||||
** three will be 0.
|
||||
*/
|
||||
#if defined(SQLITE_OS_OTHER)
|
||||
# if SQLITE_OS_OTHER==1
|
||||
# undef SQLITE_OS_UNIX
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# else
|
||||
# undef SQLITE_OS_OTHER
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
|
||||
# define SQLITE_OS_OTHER 0
|
||||
# ifndef SQLITE_OS_WIN
|
||||
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) \
|
||||
|| defined(__MINGW32__) || defined(__BORLANDC__)
|
||||
# define SQLITE_OS_WIN 1
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# else
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 1
|
||||
# endif
|
||||
# else
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# endif
|
||||
#else
|
||||
# ifndef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_UNIX
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#if SQLITE_OS_WIN
|
||||
# include "os_win.h"
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -31,6 +31,12 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#if SQLITE_OS_UNIX
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#if SQLITE_OS_WIN
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
/* Make this callable from C++ */
|
||||
#ifdef __cplusplus
|
||||
|
||||
+20
-53
@@ -127,10 +127,8 @@ struct Testvfs {
|
||||
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
|
||||
#define TESTVFS_READ_MASK 0x00010000
|
||||
#define TESTVFS_UNLOCK_MASK 0x00020000
|
||||
#define TESTVFS_LOCK_MASK 0x00040000
|
||||
#define TESTVFS_CKLOCK_MASK 0x00080000
|
||||
|
||||
#define TESTVFS_ALL_MASK 0x000FFFFF
|
||||
#define TESTVFS_ALL_MASK 0x0003FFFF
|
||||
|
||||
|
||||
#define TESTVFS_MAX_PAGES 1024
|
||||
@@ -468,15 +466,8 @@ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
** Lock an tvfs-file.
|
||||
*/
|
||||
static int tvfsLock(sqlite3_file *pFile, int eLock){
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){
|
||||
char zLock[30];
|
||||
sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
|
||||
tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1),
|
||||
Tcl_NewStringObj(zLock, -1), 0, 0);
|
||||
}
|
||||
return sqlite3OsLock(pFd->pReal, eLock);
|
||||
TestvfsFd *p = tvfsGetFd(pFile);
|
||||
return sqlite3OsLock(p->pReal, eLock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -485,12 +476,6 @@ static int tvfsLock(sqlite3_file *pFile, int eLock){
|
||||
static int tvfsUnlock(sqlite3_file *pFile, int eLock){
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){
|
||||
char zLock[30];
|
||||
sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
|
||||
tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1),
|
||||
Tcl_NewStringObj(zLock, -1), 0, 0);
|
||||
}
|
||||
if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
|
||||
return SQLITE_IOERR_UNLOCK;
|
||||
}
|
||||
@@ -501,13 +486,8 @@ static int tvfsUnlock(sqlite3_file *pFile, int eLock){
|
||||
** Check if another file-handle holds a RESERVED lock on an tvfs-file.
|
||||
*/
|
||||
static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){
|
||||
tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1),
|
||||
0, 0, 0);
|
||||
}
|
||||
return sqlite3OsCheckReservedLock(pFd->pReal, pResOut);
|
||||
TestvfsFd *p = tvfsGetFd(pFile);
|
||||
return sqlite3OsCheckReservedLock(p->pReal, pResOut);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1131,32 +1111,26 @@ static int testvfs_obj_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
/* TESTVFS filter METHOD-LIST
|
||||
**
|
||||
** Activate special processing for those methods contained in the list
|
||||
*/
|
||||
case CMD_FILTER: {
|
||||
static struct VfsMethod {
|
||||
char *zName;
|
||||
int mask;
|
||||
} vfsmethod [] = {
|
||||
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
|
||||
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
|
||||
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
|
||||
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
|
||||
{ "xShmMap", TESTVFS_SHMMAP_MASK },
|
||||
{ "xSync", TESTVFS_SYNC_MASK },
|
||||
{ "xDelete", TESTVFS_DELETE_MASK },
|
||||
{ "xWrite", TESTVFS_WRITE_MASK },
|
||||
{ "xRead", TESTVFS_READ_MASK },
|
||||
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
|
||||
{ "xOpen", TESTVFS_OPEN_MASK },
|
||||
{ "xClose", TESTVFS_CLOSE_MASK },
|
||||
{ "xAccess", TESTVFS_ACCESS_MASK },
|
||||
{ "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
|
||||
{ "xUnlock", TESTVFS_UNLOCK_MASK },
|
||||
{ "xLock", TESTVFS_LOCK_MASK },
|
||||
{ "xCheckReservedLock", TESTVFS_CKLOCK_MASK },
|
||||
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
|
||||
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
|
||||
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
|
||||
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
|
||||
{ "xShmMap", TESTVFS_SHMMAP_MASK },
|
||||
{ "xSync", TESTVFS_SYNC_MASK },
|
||||
{ "xDelete", TESTVFS_DELETE_MASK },
|
||||
{ "xWrite", TESTVFS_WRITE_MASK },
|
||||
{ "xRead", TESTVFS_READ_MASK },
|
||||
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
|
||||
{ "xOpen", TESTVFS_OPEN_MASK },
|
||||
{ "xClose", TESTVFS_CLOSE_MASK },
|
||||
{ "xAccess", TESTVFS_ACCESS_MASK },
|
||||
{ "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
|
||||
{ "xUnlock", TESTVFS_UNLOCK_MASK },
|
||||
};
|
||||
Tcl_Obj **apElem = 0;
|
||||
int nElem = 0;
|
||||
@@ -1188,12 +1162,6 @@ static int testvfs_obj_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** TESTVFS script ?SCRIPT?
|
||||
**
|
||||
** Query or set the script to be run when filtered VFS events
|
||||
** occur.
|
||||
*/
|
||||
case CMD_SCRIPT: {
|
||||
if( objc==3 ){
|
||||
int nByte;
|
||||
@@ -1280,7 +1248,6 @@ static int testvfs_obj_cmd(
|
||||
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND },
|
||||
{ "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN },
|
||||
{ "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
|
||||
{ "immutable", SQLITE_IOCAP_IMMUTABLE },
|
||||
{ 0, 0 }
|
||||
};
|
||||
Tcl_Obj *pRet;
|
||||
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
** 2012 July 21
|
||||
**
|
||||
** 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 presents a simple cross-platform threading interface for
|
||||
** use internally by SQLite.
|
||||
**
|
||||
** A "thread" can be created using sqlite3ThreadCreate(). This thread
|
||||
** runs independently of its creator until it is joined using
|
||||
** sqlite3ThreadJoin(), at which point it terminates.
|
||||
**
|
||||
** Threads do not have to be real. It could be that the work of the
|
||||
** "thread" is done by the main thread at either the sqlite3ThreadCreate()
|
||||
** or sqlite3ThreadJoin() call. This is, in fact, what happens in
|
||||
** single threaded systems. Nothing in SQLite requires multiple threads.
|
||||
** This interface exists so that applications that want to take advantage
|
||||
** of multiple cores can do so, while also allowing applications to stay
|
||||
** single-threaded if desired.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
|
||||
/********************************* Unix Pthreads ****************************/
|
||||
#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0
|
||||
|
||||
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
|
||||
#include <pthread.h>
|
||||
|
||||
/* A running thread */
|
||||
struct SQLiteThread {
|
||||
pthread_t tid; /* Thread ID */
|
||||
int done; /* Set to true when thread finishes */
|
||||
void *pOut; /* Result returned by the thread */
|
||||
void *(*xTask)(void*); /* The thread routine */
|
||||
void *pIn; /* Argument to the thread */
|
||||
};
|
||||
|
||||
/* Create a new thread */
|
||||
int sqlite3ThreadCreate(
|
||||
SQLiteThread **ppThread, /* OUT: Write the thread object here */
|
||||
void *(*xTask)(void*), /* Routine to run in a separate thread */
|
||||
void *pIn /* Argument passed into xTask() */
|
||||
){
|
||||
SQLiteThread *p;
|
||||
|
||||
assert( ppThread!=0 );
|
||||
assert( xTask!=0 );
|
||||
*ppThread = 0;
|
||||
p = sqlite3Malloc(sizeof(*p));
|
||||
if( p==0 ) return SQLITE_NOMEM;
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->xTask = xTask;
|
||||
p->pIn = pIn;
|
||||
if( sqlite3GlobalConfig.bCoreMutex==0
|
||||
|| pthread_create(&p->tid, 0, xTask, pIn)!=0
|
||||
){
|
||||
p->done = 1;
|
||||
p->pOut = xTask(pIn);
|
||||
}
|
||||
*ppThread = p;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Get the results of the thread */
|
||||
int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
||||
int rc;
|
||||
|
||||
assert( ppOut!=0 );
|
||||
if( p==0 ) return SQLITE_NOMEM;
|
||||
if( p->done ){
|
||||
*ppOut = p->pOut;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = pthread_join(p->tid, ppOut);
|
||||
}
|
||||
sqlite3_free(p);
|
||||
return rc ? SQLITE_ERROR : SQLITE_OK;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
|
||||
/******************************** End Unix Pthreads *************************/
|
||||
|
||||
|
||||
/********************************* Win32 Threads ****************************/
|
||||
#if SQLITE_OS_WIN && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
|
||||
|
||||
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
|
||||
#include <process.h>
|
||||
|
||||
/* A running thread */
|
||||
struct SQLiteThread {
|
||||
uintptr_t tid; /* The thread handle */
|
||||
void *(*xTask)(void*); /* The routine to run as a thread */
|
||||
void *pIn; /* Argument to xTask */
|
||||
void *pResult; /* Result of xTask */
|
||||
};
|
||||
|
||||
/* Thread procedure Win32 compatibility shim */
|
||||
static void sqlite3ThreadProc(
|
||||
void *pArg /* IN: Pointer to the SQLiteThread structure */
|
||||
){
|
||||
SQLiteThread *p = (SQLiteThread *)pArg;
|
||||
|
||||
assert( p!=0 );
|
||||
assert( p->xTask!=0 );
|
||||
p->pResult = p->xTask(p->pIn);
|
||||
_endthread();
|
||||
}
|
||||
|
||||
/* Create a new thread */
|
||||
int sqlite3ThreadCreate(
|
||||
SQLiteThread **ppThread, /* OUT: Write the thread object here */
|
||||
void *(*xTask)(void*), /* Routine to run in a separate thread */
|
||||
void *pIn /* Argument passed into xTask() */
|
||||
){
|
||||
SQLiteThread *p;
|
||||
|
||||
assert( ppThread!=0 );
|
||||
assert( xTask!=0 );
|
||||
*ppThread = 0;
|
||||
p = sqlite3Malloc(sizeof(*p));
|
||||
if( p==0 ) return SQLITE_NOMEM;
|
||||
if( sqlite3GlobalConfig.bCoreMutex==0 ){
|
||||
memset(p, 0, sizeof(*p));
|
||||
}else{
|
||||
p->xTask = xTask;
|
||||
p->pIn = pIn;
|
||||
p->tid = _beginthread(sqlite3ThreadProc, 0, p);
|
||||
if( p->tid==(uintptr_t)-1 ){
|
||||
memset(p, 0, sizeof(*p));
|
||||
}
|
||||
}
|
||||
if( p->xTask==0 ){
|
||||
p->pResult = xTask(pIn);
|
||||
}
|
||||
*ppThread = p;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Get the results of the thread */
|
||||
int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
||||
DWORD rc;
|
||||
|
||||
assert( ppOut!=0 );
|
||||
if( p==0 ) return SQLITE_NOMEM;
|
||||
if( p->xTask==0 ){
|
||||
rc = WAIT_OBJECT_0;
|
||||
}else{
|
||||
rc = sqlite3Win32Wait((HANDLE)p->tid);
|
||||
assert( rc!=WAIT_IO_COMPLETION );
|
||||
}
|
||||
if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
|
||||
sqlite3_free(p);
|
||||
return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINRT */
|
||||
/******************************** End Win32 Threads *************************/
|
||||
|
||||
|
||||
/********************************* Single-Threaded **************************/
|
||||
#ifndef SQLITE_THREADS_IMPLEMENTED
|
||||
/*
|
||||
** This implementation does not actually create a new thread. It does the
|
||||
** work of the thread in the main thread, when either the thread is created
|
||||
** or when it is joined
|
||||
*/
|
||||
|
||||
/* A running thread */
|
||||
struct SQLiteThread {
|
||||
void *(*xTask)(void*); /* The routine to run as a thread */
|
||||
void *pIn; /* Argument to xTask */
|
||||
void *pResult; /* Result of xTask */
|
||||
};
|
||||
|
||||
/* Create a new thread */
|
||||
int sqlite3ThreadCreate(
|
||||
SQLiteThread **ppThread, /* OUT: Write the thread object here */
|
||||
void *(*xTask)(void*), /* Routine to run in a separate thread */
|
||||
void *pIn /* Argument passed into xTask() */
|
||||
){
|
||||
SQLiteThread *p;
|
||||
|
||||
assert( ppThread!=0 );
|
||||
assert( xTask!=0 );
|
||||
*ppThread = 0;
|
||||
p = sqlite3Malloc(sizeof(*p));
|
||||
if( p==0 ) return SQLITE_NOMEM;
|
||||
if( (SQLITE_PTR_TO_INT(p)/17)&1 ){
|
||||
p->xTask = xTask;
|
||||
p->pIn = pIn;
|
||||
}else{
|
||||
p->xTask = 0;
|
||||
p->pResult = xTask(pIn);
|
||||
}
|
||||
*ppThread = p;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Get the results of the thread */
|
||||
int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
||||
|
||||
assert( ppOut!=0 );
|
||||
if( p==0 ) return SQLITE_NOMEM;
|
||||
if( p->xTask ){
|
||||
*ppOut = p->xTask(p->pIn);
|
||||
}else{
|
||||
*ppOut = p->pResult;
|
||||
}
|
||||
sqlite3_free(p);
|
||||
|
||||
#if defined(SQLITE_TEST)
|
||||
{
|
||||
void *pTstAlloc = sqlite3Malloc(10);
|
||||
if (!pTstAlloc) return SQLITE_NOMEM;
|
||||
sqlite3_free(pTstAlloc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */
|
||||
/****************************** End Single-Threaded *************************/
|
||||
#endif /* SQLITE_MAX_WORKER_THREADS>0 */
|
||||
+1
-1
@@ -187,7 +187,7 @@ void sqlite3Update(
|
||||
iIdxCur = iDataCur+1;
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
|
||||
if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){
|
||||
if( pIdx->autoIndex==2 && pPk!=0 ){
|
||||
iDataCur = pParse->nTab;
|
||||
pTabList->a[0].iCursor = iDataCur;
|
||||
}
|
||||
|
||||
-18
@@ -31,24 +31,6 @@ void sqlite3Coverage(int x){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Give a callback to the test harness that can be used to simulate faults
|
||||
** in places where it is difficult or expensive to do so purely by means
|
||||
** of inputs.
|
||||
**
|
||||
** The intent of the integer argument is to let the fault simulator know
|
||||
** which of multiple sqlite3FaultSim() calls has been hit.
|
||||
**
|
||||
** Return whatever integer value the test callback returns, or return
|
||||
** SQLITE_OK if no test callback is installed.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
int sqlite3FaultSim(int iTest){
|
||||
int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
|
||||
return xCallback ? xCallback(iTest) : SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** Return true if the floating point value is Not a Number (NaN).
|
||||
|
||||
+32
-9
@@ -3390,11 +3390,15 @@ case OP_OpenEphemeral: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SorterOpen P1 P2 * P4 *
|
||||
/* Opcode: SorterOpen P1 P2 P3 P4 *
|
||||
**
|
||||
** This opcode works like OP_OpenEphemeral except that it opens
|
||||
** a transient index that is specifically designed to sort large
|
||||
** tables using an external merge-sort algorithm.
|
||||
**
|
||||
** If argument P3 is non-zero, then it indicates that the sorter may
|
||||
** assume that a stable sort considering the first P3 fields of each
|
||||
** key is sufficient to produce the required results.
|
||||
*/
|
||||
case OP_SorterOpen: {
|
||||
VdbeCursor *pCx;
|
||||
@@ -3406,7 +3410,25 @@ case OP_SorterOpen: {
|
||||
pCx->pKeyInfo = pOp->p4.pKeyInfo;
|
||||
assert( pCx->pKeyInfo->db==db );
|
||||
assert( pCx->pKeyInfo->enc==ENC(db) );
|
||||
rc = sqlite3VdbeSorterInit(db, pCx);
|
||||
rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SequenceTest P1 P2 * * *
|
||||
** Synopsis: if( cursor[P1].ctr++ ) pc = P2
|
||||
**
|
||||
** P1 is a sorter cursor. If the sequence counter is currently zero, jump
|
||||
** to P2. Regardless of whether or not the jump is taken, increment the
|
||||
** the sequence value.
|
||||
*/
|
||||
case OP_SequenceTest: {
|
||||
VdbeCursor *pC;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC->pSorter );
|
||||
if( (pC->seqCount++)==0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3464,7 +3486,7 @@ case OP_Close: {
|
||||
** is greater than or equal to the key value. If there are no records
|
||||
** greater than or equal to the key and P2 is not zero, then jump to P2.
|
||||
**
|
||||
** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
|
||||
** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
|
||||
*/
|
||||
/* Opcode: SeekGt P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
@@ -3478,7 +3500,7 @@ case OP_Close: {
|
||||
** is greater than the key value. If there are no records greater than
|
||||
** the key and P2 is not zero, then jump to P2.
|
||||
**
|
||||
** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
|
||||
** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
|
||||
*/
|
||||
/* Opcode: SeekLt P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
@@ -3492,7 +3514,7 @@ case OP_Close: {
|
||||
** is less than the key value. If there are no records less than
|
||||
** the key and P2 is not zero, then jump to P2.
|
||||
**
|
||||
** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
|
||||
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
|
||||
*/
|
||||
/* Opcode: SeekLe P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
@@ -3506,7 +3528,7 @@ case OP_Close: {
|
||||
** is less than or equal to the key value. If there are no records
|
||||
** less than or equal to the key and P2 is not zero, then jump to P2.
|
||||
**
|
||||
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
|
||||
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
|
||||
*/
|
||||
case OP_SeekLT: /* jump, in3 */
|
||||
case OP_SeekLE: /* jump, in3 */
|
||||
@@ -4212,6 +4234,7 @@ case OP_SorterCompare: {
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
nIgnore = pOp->p4.i;
|
||||
res = 0;
|
||||
rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res);
|
||||
VdbeBranchTaken(res!=0,2);
|
||||
if( res ){
|
||||
@@ -4462,7 +4485,7 @@ case OP_Rewind: { /* jump */
|
||||
assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
|
||||
res = 1;
|
||||
if( isSorter(pC) ){
|
||||
rc = sqlite3VdbeSorterRewind(db, pC, &res);
|
||||
rc = sqlite3VdbeSorterRewind(pC, &res);
|
||||
}else{
|
||||
pCrsr = pC->pCursor;
|
||||
assert( pCrsr );
|
||||
@@ -4621,7 +4644,7 @@ case OP_IdxInsert: { /* in2 */
|
||||
rc = ExpandBlob(pIn2);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( isSorter(pC) ){
|
||||
rc = sqlite3VdbeSorterWrite(db, pC, pIn2);
|
||||
rc = sqlite3VdbeSorterWrite(pC, pIn2);
|
||||
}else{
|
||||
nKey = pIn2->n;
|
||||
zKey = pIn2->z;
|
||||
@@ -6281,7 +6304,7 @@ case OP_Init: { /* jump */
|
||||
if( zTrace ){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( (MASKBIT(i) & p->btreeMask)==0 ) continue;
|
||||
if( MASKBIT(i) & p->btreeMask)==0 ) continue;
|
||||
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -437,13 +437,13 @@ void sqlite3VdbeFrameDelete(VdbeFrame*);
|
||||
int sqlite3VdbeFrameRestore(VdbeFrame *);
|
||||
int sqlite3VdbeTransferError(Vdbe *p);
|
||||
|
||||
int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
|
||||
int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
|
||||
void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
|
||||
void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
|
||||
int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
|
||||
|
||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
||||
|
||||
+35
-30
@@ -3137,10 +3137,14 @@ void sqlite3VdbeRecordUnpack(
|
||||
** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
|
||||
** in assert() statements to ensure that the optimized code in
|
||||
** sqlite3VdbeRecordCompare() returns results with these two primitives.
|
||||
**
|
||||
** Return true if the result of comparison is equivalent to desiredResult.
|
||||
** Return false if there is a disagreement.
|
||||
*/
|
||||
static int vdbeRecordCompareDebug(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
const UnpackedRecord *pPKey2 /* Right key */
|
||||
const UnpackedRecord *pPKey2, /* Right key */
|
||||
int desiredResult /* Correct answer */
|
||||
){
|
||||
u32 d1; /* Offset into aKey[] of next data element */
|
||||
u32 idx1; /* Offset into aKey[] of next header element */
|
||||
@@ -3152,6 +3156,7 @@ static int vdbeRecordCompareDebug(
|
||||
Mem mem1;
|
||||
|
||||
pKeyInfo = pPKey2->pKeyInfo;
|
||||
if( pKeyInfo->db==0 ) return 1;
|
||||
mem1.enc = pKeyInfo->enc;
|
||||
mem1.db = pKeyInfo->db;
|
||||
/* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
|
||||
@@ -3202,7 +3207,7 @@ static int vdbeRecordCompareDebug(
|
||||
if( pKeyInfo->aSortOrder[i] ){
|
||||
rc = -rc; /* Invert the result for DESC sort order. */
|
||||
}
|
||||
return rc;
|
||||
goto debugCompareEnd;
|
||||
}
|
||||
i++;
|
||||
}while( idx1<szHdr1 && i<pPKey2->nField );
|
||||
@@ -3216,7 +3221,15 @@ static int vdbeRecordCompareDebug(
|
||||
/* rc==0 here means that one of the keys ran out of fields and
|
||||
** all the fields up to that point were equal. Return the the default_rc
|
||||
** value. */
|
||||
return pPKey2->default_rc;
|
||||
rc = pPKey2->default_rc;
|
||||
|
||||
debugCompareEnd:
|
||||
if( desiredResult==0 && rc==0 ) return 1;
|
||||
if( desiredResult<0 && rc<0 ) return 1;
|
||||
if( desiredResult>0 && rc>0 ) return 1;
|
||||
if( CORRUPT_DB ) return 1;
|
||||
if( pKeyInfo->db->mallocFailed ) return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3229,7 +3242,8 @@ static int vdbeRecordCompareDebug(
|
||||
static int vdbeCompareMemString(
|
||||
const Mem *pMem1,
|
||||
const Mem *pMem2,
|
||||
const CollSeq *pColl
|
||||
const CollSeq *pColl,
|
||||
u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */
|
||||
){
|
||||
if( pMem1->enc==pColl->enc ){
|
||||
/* The strings are already in the correct encoding. Call the
|
||||
@@ -3252,6 +3266,7 @@ static int vdbeCompareMemString(
|
||||
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
|
||||
sqlite3VdbeMemRelease(&c1);
|
||||
sqlite3VdbeMemRelease(&c2);
|
||||
if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -3334,7 +3349,7 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
|
||||
assert( !pColl || pColl->xCmp );
|
||||
|
||||
if( pColl ){
|
||||
return vdbeCompareMemString(pMem1, pMem2, pColl);
|
||||
return vdbeCompareMemString(pMem1, pMem2, pColl, 0);
|
||||
}
|
||||
/* If a NULL pointer was passed as the collate function, fall through
|
||||
** to the blob case and use memcmp(). */
|
||||
@@ -3406,8 +3421,10 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
|
||||
** fields that appear in both keys are equal, then pPKey2->default_rc is
|
||||
** returned.
|
||||
**
|
||||
** If database corruption is discovered, set pPKey2->isCorrupt to non-zero
|
||||
** and return 0.
|
||||
** If database corruption is discovered, set pPKey2->errCode to
|
||||
** SQLITE_CORRUPT and return 0. If an OOM error is encountered,
|
||||
** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
|
||||
** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
|
||||
*/
|
||||
int sqlite3VdbeRecordCompare(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
@@ -3438,7 +3455,7 @@ int sqlite3VdbeRecordCompare(
|
||||
idx1 = getVarint32(aKey1, szHdr1);
|
||||
d1 = szHdr1;
|
||||
if( d1>(unsigned)nKey1 ){
|
||||
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}
|
||||
i = 0;
|
||||
@@ -3517,14 +3534,16 @@ int sqlite3VdbeRecordCompare(
|
||||
testcase( (d1+mem1.n)==(unsigned)nKey1 );
|
||||
testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
|
||||
if( (d1+mem1.n) > (unsigned)nKey1 ){
|
||||
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}else if( pKeyInfo->aColl[i] ){
|
||||
mem1.enc = pKeyInfo->enc;
|
||||
mem1.db = pKeyInfo->db;
|
||||
mem1.flags = MEM_Str;
|
||||
mem1.z = (char*)&aKey1[d1];
|
||||
rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
|
||||
rc = vdbeCompareMemString(
|
||||
&mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode
|
||||
);
|
||||
}else{
|
||||
int nCmp = MIN(mem1.n, pRhs->n);
|
||||
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
|
||||
@@ -3544,7 +3563,7 @@ int sqlite3VdbeRecordCompare(
|
||||
testcase( (d1+nStr)==(unsigned)nKey1 );
|
||||
testcase( (d1+nStr+1)==(unsigned)nKey1 );
|
||||
if( (d1+nStr) > (unsigned)nKey1 ){
|
||||
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}else{
|
||||
int nCmp = MIN(nStr, pRhs->n);
|
||||
@@ -3564,11 +3583,7 @@ int sqlite3VdbeRecordCompare(
|
||||
if( pKeyInfo->aSortOrder[i] ){
|
||||
rc = -rc;
|
||||
}
|
||||
assert( CORRUPT_DB
|
||||
|| (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|
||||
|| (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|
||||
|| pKeyInfo->db->mallocFailed
|
||||
);
|
||||
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
|
||||
assert( mem1.zMalloc==0 ); /* See comment below */
|
||||
return rc;
|
||||
}
|
||||
@@ -3587,9 +3602,7 @@ int sqlite3VdbeRecordCompare(
|
||||
/* rc==0 here means that one or both of the keys ran out of fields and
|
||||
** all the fields up to that point were equal. Return the the default_rc
|
||||
** value. */
|
||||
assert( CORRUPT_DB
|
||||
|| pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)
|
||||
);
|
||||
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) );
|
||||
return pPKey2->default_rc;
|
||||
}
|
||||
|
||||
@@ -3686,11 +3699,7 @@ static int vdbeRecordCompareInt(
|
||||
res = pPKey2->default_rc;
|
||||
}
|
||||
|
||||
assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
|
||||
|| (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|
||||
|| (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|
||||
|| CORRUPT_DB
|
||||
);
|
||||
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) );
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3724,7 +3733,7 @@ static int vdbeRecordCompareString(
|
||||
|
||||
nStr = (serial_type-12) / 2;
|
||||
if( (szHdr + nStr) > nKey1 ){
|
||||
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}
|
||||
nCmp = MIN( pPKey2->aMem[0].n, nStr );
|
||||
@@ -3750,11 +3759,7 @@ static int vdbeRecordCompareString(
|
||||
}
|
||||
}
|
||||
|
||||
assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
|
||||
|| (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|
||||
|| (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|
||||
|| CORRUPT_DB
|
||||
);
|
||||
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
+1813
-500
File diff suppressed because it is too large
Load Diff
+24
-104
@@ -2718,20 +2718,13 @@ static void explainOneScan(
|
||||
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0
|
||||
&& ALWAYS(pLoop->u.btree.pIndex!=0)
|
||||
){
|
||||
const char *zFmt;
|
||||
Index *pIdx = pLoop->u.btree.pIndex;
|
||||
char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
|
||||
assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
|
||||
if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
|
||||
zFmt = zWhere ? "%s USING PRIMARY KEY%.0s%s" : "%s%.0s%s";
|
||||
}else if( flags & WHERE_AUTO_INDEX ){
|
||||
zFmt = "%s USING AUTOMATIC COVERING INDEX%.0s%s";
|
||||
}else if( flags & WHERE_IDX_ONLY ){
|
||||
zFmt = "%s USING COVERING INDEX %s%s";
|
||||
}else{
|
||||
zFmt = "%s USING INDEX %s%s";
|
||||
}
|
||||
zMsg = sqlite3MAppendf(db, zMsg, zFmt, zMsg, pIdx->zName, zWhere);
|
||||
zMsg = sqlite3MAppendf(db, zMsg,
|
||||
((flags & WHERE_AUTO_INDEX) ?
|
||||
"%s USING AUTOMATIC %sINDEX%.0s%s" :
|
||||
"%s USING %sINDEX %s%s"),
|
||||
zMsg, ((flags & WHERE_IDX_ONLY) ? "COVERING " : ""),
|
||||
pLoop->u.btree.pIndex->zName, zWhere);
|
||||
sqlite3DbFree(db, zWhere);
|
||||
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
|
||||
zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
|
||||
@@ -3223,7 +3216,7 @@ static Bitmask codeOneLoopStart(
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
|
||||
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
|
||||
sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
|
||||
}else if( iCur!=iIdxCur ){
|
||||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
|
||||
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
||||
for(j=0; j<pPk->nKeyCol; j++){
|
||||
@@ -3293,10 +3286,6 @@ static Bitmask codeOneLoopStart(
|
||||
**
|
||||
** B: <after the loop>
|
||||
**
|
||||
** Added 2014-05-26: If the table is a WITHOUT ROWID table, then
|
||||
** use an ephermeral index instead of a RowSet to record the primary
|
||||
** keys of the rows we have already seen.
|
||||
**
|
||||
*/
|
||||
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
|
||||
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
|
||||
@@ -3311,7 +3300,6 @@ static Bitmask codeOneLoopStart(
|
||||
int untestedTerms = 0; /* Some terms not completely tested */
|
||||
int ii; /* Loop counter */
|
||||
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
|
||||
Table *pTab = pTabItem->pTab;
|
||||
|
||||
pTerm = pLoop->aLTerm[0];
|
||||
assert( pTerm!=0 );
|
||||
@@ -3344,8 +3332,7 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
|
||||
/* Initialize the rowset register to contain NULL. An SQL NULL is
|
||||
** equivalent to an empty rowset. Or, create an ephermeral index
|
||||
** capable of holding primary keys in the case of a WITHOUT ROWID.
|
||||
** equivalent to an empty rowset.
|
||||
**
|
||||
** Also initialize regReturn to contain the address of the instruction
|
||||
** immediately following the OP_Return at the bottom of the loop. This
|
||||
@@ -3356,16 +3343,9 @@ static Bitmask codeOneLoopStart(
|
||||
** called on an uninitialized cursor.
|
||||
*/
|
||||
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
|
||||
if( HasRowid(pTab) ){
|
||||
regRowset = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
regRowset = pParse->nTab++;
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
|
||||
}
|
||||
regRowset = ++pParse->nMem;
|
||||
regRowid = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
}
|
||||
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
|
||||
|
||||
@@ -3401,16 +3381,11 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
}
|
||||
|
||||
/* Run a separate WHERE clause for each term of the OR clause. After
|
||||
** eliminating duplicates from other WHERE clauses, the action for each
|
||||
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
|
||||
*/
|
||||
for(ii=0; ii<pOrWc->nTerm; ii++){
|
||||
WhereTerm *pOrTerm = &pOrWc->a[ii];
|
||||
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
||||
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
||||
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
|
||||
int j1 = 0; /* Address of jump operation */
|
||||
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
||||
Expr *pOrExpr = pOrTerm->pExpr;
|
||||
if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
|
||||
pAndExpr->pLeft = pOrExpr;
|
||||
pOrExpr = pAndExpr;
|
||||
@@ -3425,63 +3400,17 @@ static Bitmask codeOneLoopStart(
|
||||
explainOneScan(
|
||||
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
|
||||
);
|
||||
/* This is the sub-WHERE clause body. First skip over
|
||||
** duplicate rows from prior sub-WHERE clauses, and record the
|
||||
** rowid (or PRIMARY KEY) for the current row so that the same
|
||||
** row will be skipped in subsequent sub-WHERE clauses.
|
||||
*/
|
||||
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
|
||||
int r;
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
if( HasRowid(pTab) ){
|
||||
r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0);
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, r,iSet);
|
||||
VdbeCoverage(v);
|
||||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
int nPk = pPk->nKeyCol;
|
||||
int iPk;
|
||||
|
||||
/* Read the PK into an array of temp registers. */
|
||||
r = sqlite3GetTempRange(pParse, nPk);
|
||||
for(iPk=0; iPk<nPk; iPk++){
|
||||
int iCol = pPk->aiColumn[iPk];
|
||||
sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur, r+iPk, 0);
|
||||
}
|
||||
|
||||
/* Check if the temp table already contains this key. If so,
|
||||
** the row has already been included in the result set and
|
||||
** can be ignored (by jumping past the Gosub below). Otherwise,
|
||||
** insert the key into the temp table and proceed with processing
|
||||
** the row.
|
||||
**
|
||||
** Use some of the same optimizations as OP_RowSetTest: If iSet
|
||||
** is zero, assume that the key cannot already be present in
|
||||
** the temp table. And if iSet is -1, assume that there is no
|
||||
** need to insert the key into the temp table, as it will never
|
||||
** be tested for. */
|
||||
if( iSet ){
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( iSet>=0 ){
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0);
|
||||
if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
}
|
||||
|
||||
/* Release the array of temp registers */
|
||||
sqlite3ReleaseTempRange(pParse, r, nPk);
|
||||
}
|
||||
int r;
|
||||
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
|
||||
regRowid, 0);
|
||||
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
|
||||
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
|
||||
/* Invoke the main loop body as a subroutine */
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
|
||||
|
||||
/* Jump here (skipping the main loop body subroutine) if the
|
||||
** current sub-WHERE row is a duplicate from prior sub-WHEREs. */
|
||||
if( j1 ) sqlite3VdbeJumpHere(v, j1);
|
||||
|
||||
/* The pSubWInfo->untestedTerms flag means that this OR term
|
||||
** contained one or more AND term from a notReady table. The
|
||||
** terms from the notReady table could not be tested and will
|
||||
@@ -3505,7 +3434,6 @@ static Bitmask codeOneLoopStart(
|
||||
assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
|
||||
if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
|
||||
&& (ii==0 || pSubLoop->u.btree.pIndex==pCov)
|
||||
&& (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
|
||||
){
|
||||
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
|
||||
pCov = pSubLoop->u.btree.pIndex;
|
||||
@@ -3833,7 +3761,7 @@ static int whereLoopCheaperProperSubset(
|
||||
if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */
|
||||
if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */
|
||||
}
|
||||
for(i=pX->nLTerm-1; i>=0; i--){
|
||||
for(j=0, i=pX->nLTerm-1; i>=0; i--){
|
||||
for(j=pY->nLTerm-1; j>=0; j--){
|
||||
if( pY->aLTerm[j]==pX->aLTerm[i] ) break;
|
||||
}
|
||||
@@ -4831,6 +4759,7 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
pNew = pBuilder->pNew;
|
||||
memset(&sSum, 0, sizeof(sSum));
|
||||
pItem = pWInfo->pTabList->a + pNew->iTab;
|
||||
if( !HasRowid(pItem->pTab) ) return SQLITE_OK;
|
||||
iCur = pItem->iCursor;
|
||||
|
||||
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
|
||||
@@ -6079,14 +6008,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
int op = OP_OpenRead;
|
||||
/* iIdxCur is always set if to a positive value if ONEPASS is possible */
|
||||
assert( iIdxCur!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
|
||||
if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx)
|
||||
&& (wctrlFlags & WHERE_ONETABLE_ONLY)!=0
|
||||
){
|
||||
/* This is one term of an OR-optimization using the PRIMARY KEY of a
|
||||
** WITHOUT ROWID table. No need for a separate index */
|
||||
iIndexCur = pLevel->iTabCur;
|
||||
op = 0;
|
||||
}else if( pWInfo->okOnePass ){
|
||||
if( pWInfo->okOnePass ){
|
||||
Index *pJ = pTabItem->pTab->pIndex;
|
||||
iIndexCur = iIdxCur;
|
||||
assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
|
||||
@@ -6104,11 +6026,9 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pLevel->iIdxCur = iIndexCur;
|
||||
assert( pIx->pSchema==pTab->pSchema );
|
||||
assert( iIndexCur>=0 );
|
||||
if( op ){
|
||||
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
|
||||
VdbeComment((v, "%s", pIx->zName));
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
|
||||
VdbeComment((v, "%s", pIx->zName));
|
||||
}
|
||||
if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
|
||||
notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
|
||||
|
||||
@@ -58,24 +58,12 @@ proc do_backcompat_test {rv bin1 bin2 script} {
|
||||
code1 { sqlite3 db test.db }
|
||||
code2 { sqlite3 db test.db }
|
||||
|
||||
foreach c {code1 code2} {
|
||||
$c {
|
||||
set v [split [db version] .]
|
||||
if {[llength $v]==3} {lappend v 0}
|
||||
set ::sqlite_libversion [format \
|
||||
"%d%.2d%.2d%2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
uplevel $script
|
||||
|
||||
catch { code1 { db close } }
|
||||
catch { code2 { db close } }
|
||||
catch { close $::bc_chan2 }
|
||||
catch { close $::bc_chan1 }
|
||||
|
||||
|
||||
}
|
||||
|
||||
array set ::incompatible [list]
|
||||
@@ -393,48 +381,6 @@ ifcapable fts3 {
|
||||
} {
|
||||
do_test backcompat-3.7 [list sql1 $q] [sql2 $q]
|
||||
}
|
||||
|
||||
# Now test that an incremental merge can be started by one version
|
||||
# and finished by another. And that the integrity-check still
|
||||
# passes.
|
||||
do_test backcompat-3.8 {
|
||||
sql1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(docid, words);
|
||||
CREATE VIRTUAL TABLE t2 USING fts3(words);
|
||||
}
|
||||
code1 [list source $testdir/genesis.tcl]
|
||||
code1 { fts_kjv_genesis }
|
||||
sql1 {
|
||||
INSERT INTO t2 SELECT words FROM t1;
|
||||
INSERT INTO t2 SELECT words FROM t1;
|
||||
INSERT INTO t2 SELECT words FROM t1;
|
||||
INSERT INTO t2 SELECT words FROM t1;
|
||||
INSERT INTO t2 SELECT words FROM t1;
|
||||
INSERT INTO t2 SELECT words FROM t1;
|
||||
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
|
||||
}
|
||||
} {0 {0 1 2 3 4 5}}
|
||||
|
||||
if {[code1 { set ::sqlite_libversion }] >=3071200
|
||||
&& [code2 { set ::sqlite_libversion }] >=3071200
|
||||
} {
|
||||
do_test backcompat-3.9 {
|
||||
sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
|
||||
sql2 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
|
||||
sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
|
||||
sql2 { INSERT INTO t2(t2) VALUES('merge=2500,4'); }
|
||||
sql2 {
|
||||
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
|
||||
}
|
||||
} {0 {0 1} 1 0}
|
||||
|
||||
do_test backcompat-3.10 {
|
||||
sql1 { INSERT INTO t2(t2) VALUES('integrity-check') }
|
||||
sql2 { INSERT INTO t2(t2) VALUES('integrity-check') }
|
||||
} {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,49 +598,5 @@ det 7.5 "SELECT count(*) FROM t2" {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests - eqp-8.* - test that queries that use the OP_Count
|
||||
# optimization return something sensible with EQP.
|
||||
#
|
||||
drop_all_tables
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
|
||||
CREATE TABLE t2(a, b, c);
|
||||
}
|
||||
|
||||
det 8.1.1 "SELECT * FROM t2" {
|
||||
0 0 0 {SCAN TABLE t2}
|
||||
}
|
||||
|
||||
det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
|
||||
0 0 0 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
}
|
||||
|
||||
det 8.1.3 "SELECT count(*) FROM t2" {
|
||||
0 0 0 {SCAN TABLE t2}
|
||||
}
|
||||
|
||||
det 8.2.1 "SELECT * FROM t1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
|
||||
det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
|
||||
0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)}
|
||||
}
|
||||
|
||||
det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
|
||||
0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)}
|
||||
}
|
||||
|
||||
det 8.2.4 "SELECT count(*) FROM t1" {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+9
-10
@@ -213,17 +213,16 @@ do_test fts3d-4.matches {
|
||||
{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} \
|
||||
{0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}]
|
||||
|
||||
puts [db eval {SELECT c FROM t1 } ]
|
||||
check_terms_all fts3d-4.1 {a four is test that this was}
|
||||
check_terms_all fts3d-4.1 {a four is one test that this three two was}
|
||||
check_doclist_all fts3d-4.1.1 a {[1 0[2]] [2 0[2]] [3 0[2]]}
|
||||
check_doclist_all fts3d-4.1.2 four {}
|
||||
check_doclist_all fts3d-4.1.3 is {[1 0[1]] [3 0[1]]}
|
||||
#check_doclist_all fts3d-4.1.4 one {}
|
||||
check_doclist_all fts3d-4.1.4 one {}
|
||||
check_doclist_all fts3d-4.1.5 test {[1 0[3]] [2 0[3]] [3 0[3]]}
|
||||
check_doclist_all fts3d-4.1.6 that {[2 0[0]]}
|
||||
check_doclist_all fts3d-4.1.7 this {[1 0[0]] [3 0[0]]}
|
||||
#check_doclist_all fts3d-4.1.8 three {}
|
||||
#check_doclist_all fts3d-4.1.9 two {}
|
||||
check_doclist_all fts3d-4.1.8 three {}
|
||||
check_doclist_all fts3d-4.1.9 two {}
|
||||
check_doclist_all fts3d-4.1.10 was {[2 0[1]]}
|
||||
|
||||
check_terms fts3d-4.2 0 0 {a four test that was}
|
||||
@@ -240,16 +239,16 @@ check_doclist fts3d-4.3.3 0 1 is {[3 0[1]]}
|
||||
check_doclist fts3d-4.3.4 0 1 test {[3 0[3]]}
|
||||
check_doclist fts3d-4.3.5 0 1 this {[3 0[0]]}
|
||||
|
||||
check_terms fts3d-4.4 1 0 {a four is test that this was}
|
||||
check_terms fts3d-4.4 1 0 {a four is one test that this three two was}
|
||||
check_doclist fts3d-4.4.1 1 0 a {[1 0[2]] [2 0[2]] [3 0[2]]}
|
||||
check_doclist fts3d-4.4.2 1 0 four {[2 0[4]] [3 0[4]]}
|
||||
check_doclist fts3d-4.4.2 1 0 four {[1] [2 0[4]] [3 0[4]]}
|
||||
check_doclist fts3d-4.4.3 1 0 is {[1 0[1]] [3 0[1]]}
|
||||
#check_doclist fts3d-4.4.4 1 0 one {[1] [2] [3]}
|
||||
check_doclist fts3d-4.4.4 1 0 one {[1] [2] [3]}
|
||||
check_doclist fts3d-4.4.5 1 0 test {[1 0[3]] [2 0[3]] [3 0[3]]}
|
||||
check_doclist fts3d-4.4.6 1 0 that {[2 0[0]]}
|
||||
check_doclist fts3d-4.4.7 1 0 this {[1 0[0]] [3 0[0]]}
|
||||
#check_doclist fts3d-4.4.8 1 0 three {[1] [2] [3]}
|
||||
#check_doclist fts3d-4.4.9 1 0 two {[1] [2] [3]}
|
||||
check_doclist fts3d-4.4.8 1 0 three {[1] [2] [3]}
|
||||
check_doclist fts3d-4.4.9 1 0 two {[1] [2] [3]}
|
||||
check_doclist fts3d-4.4.10 1 0 was {[2 0[1]]}
|
||||
|
||||
# Optimize should leave the result in the level of the highest-level
|
||||
|
||||
@@ -59,7 +59,6 @@ do_execsql_test 1.2.1 {
|
||||
SELECT content FROM t1 WHERE t1 MATCH 'f (e NEAR/2 a)';
|
||||
} {{a b c d e f a x y}}
|
||||
|
||||
|
||||
do_execsql_test 1.2.2 {
|
||||
SELECT snippet(t1, '[', ']'), offsets(t1), mit(matchinfo(t1, 'pcxnal'))
|
||||
FROM t1 WHERE t1 MATCH 'f (e NEAR/2 a)';
|
||||
|
||||
@@ -509,9 +509,4 @@ do_test fts3expr-8.7 { test_fts3expr "((((blah!))))" } {PHRASE 3 0 blah}
|
||||
do_test fts3expr-8.8 { test_fts3expr "(,(blah-),)" } {PHRASE 3 0 blah}
|
||||
|
||||
set sqlite_fts3_enable_parentheses 0
|
||||
|
||||
do_test fts3expr-9.1 {
|
||||
test_fts3expr "f (e NEAR/2 a)"
|
||||
} {AND {PHRASE 3 0 f} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# 2014 May 7
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS3 module.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts3expr4
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3||!icu {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set sqlite_fts3_enable_parentheses 1
|
||||
|
||||
proc test_icu_fts3expr {expr} {
|
||||
db one {SELECT fts3_exprtest('icu', $expr, 'a', 'b', 'c')}
|
||||
}
|
||||
|
||||
proc do_icu_expr_test {tn expr res} {
|
||||
uplevel [list do_test $tn [list test_icu_fts3expr $expr] $res]
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_icu_expr_test 1.1 "abcd" {PHRASE 3 0 abcd}
|
||||
do_icu_expr_test 1.2 " tag " {PHRASE 3 0 tag}
|
||||
do_icu_expr_test 1.3 {"x y z"} {PHRASE 3 0 x y z}
|
||||
do_icu_expr_test 1.4 {x OR y} {OR {PHRASE 3 0 x} {PHRASE 3 0 y}}
|
||||
do_icu_expr_test 1.5 {(x OR y)} {OR {PHRASE 3 0 x} {PHRASE 3 0 y}}
|
||||
do_icu_expr_test 1.6 { "(x OR y)" } {PHRASE 3 0 ( x or y )}
|
||||
|
||||
# In "col:word", if "col" is not the name of a column, the entire thing
|
||||
# is passed to the tokenizer.
|
||||
#
|
||||
do_icu_expr_test 1.7 {a:word} {PHRASE 0 0 word}
|
||||
do_icu_expr_test 1.8 {d:word} {PHRASE 3 0 d:word}
|
||||
|
||||
set sqlite_fts3_enable_parentheses 0
|
||||
|
||||
do_icu_expr_test 2.1 {
|
||||
f (e NEAR/2 a)
|
||||
} {AND {AND {AND {PHRASE 3 0 f} {PHRASE 3 0 (}} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}} {PHRASE 3 0 )}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,437 +0,0 @@
|
||||
# 2014 May 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS4 module.
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts4growth
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
source $testdir/genesis.tcl
|
||||
|
||||
do_execsql_test 1.1 { CREATE VIRTUAL TABLE x1 USING fts3; }
|
||||
|
||||
do_test 1.2 {
|
||||
foreach L {
|
||||
{"See here, young man," said Mulga Bill, "from Walgett to the sea,}
|
||||
{From Conroy's Gap to Castlereagh, there's none can ride like me.}
|
||||
{I'm good all round at everything as everybody knows,}
|
||||
{Although I'm not the one to talk -- I hate a man that blows.}
|
||||
} {
|
||||
execsql { INSERT INTO x1 VALUES($L) }
|
||||
}
|
||||
execsql { SELECT end_block, length(root) FROM x1_segdir }
|
||||
} {{0 114} 114 {0 118} 118 {0 95} 95 {0 115} 115}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
INSERT INTO x1(x1) VALUES('optimize');
|
||||
SELECT level, end_block, length(root) FROM x1_segdir;
|
||||
} {0 {0 394} 394}
|
||||
|
||||
do_test 1.4 {
|
||||
foreach L {
|
||||
{But riding is my special gift, my chiefest, sole delight;}
|
||||
{Just ask a wild duck can it swim, a wildcat can it fight.}
|
||||
{There's nothing clothed in hair or hide, or built of flesh or steel,}
|
||||
{There's nothing walks or jumps, or runs, on axle, hoof, or wheel,}
|
||||
{But what I'll sit, while hide will hold and girths and straps are tight:}
|
||||
{I'll ride this here two-wheeled concern right straight away at sight."}
|
||||
} {
|
||||
execsql { INSERT INTO x1 VALUES($L) }
|
||||
}
|
||||
execsql {
|
||||
INSERT INTO x1(x1) VALUES('merge=4,4');
|
||||
SELECT level, end_block, length(root) FROM x1_segdir;
|
||||
}
|
||||
} {0 {0 110} 110 0 {0 132} 132 0 {0 129} 129 1 {128 658} 2}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
SELECT length(block) FROM x1_segments;
|
||||
} {658 {}}
|
||||
|
||||
do_test 1.6 {
|
||||
foreach L {
|
||||
{'Twas Mulga Bill, from Eaglehawk, that sought his own abode,}
|
||||
{That perched above Dead Man's Creek, beside the mountain road.}
|
||||
{He turned the cycle down the hill and mounted for the fray,}
|
||||
{But 'ere he'd gone a dozen yards it bolted clean away.}
|
||||
{It left the track, and through the trees, just like a silver steak,}
|
||||
{It whistled down the awful slope towards the Dead Man's Creek.}
|
||||
{It shaved a stump by half an inch, it dodged a big white-box:}
|
||||
{The very wallaroos in fright went scrambling up the rocks,}
|
||||
{The wombats hiding in their caves dug deeper underground,}
|
||||
{As Mulga Bill, as white as chalk, sat tight to every bound.}
|
||||
{It struck a stone and gave a spring that cleared a fallen tree,}
|
||||
{It raced beside a precipice as close as close could be;}
|
||||
{And then as Mulga Bill let out one last despairing shriek}
|
||||
{It made a leap of twenty feet into the Dead Man's Creek.}
|
||||
} {
|
||||
execsql { INSERT INTO x1 VALUES($L) }
|
||||
}
|
||||
execsql {
|
||||
SELECT level, end_block, length(root) FROM x1_segdir;
|
||||
}
|
||||
} {1 {128 658} 2 1 {130 1377} 6 0 {0 117} 117}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (129, 130);
|
||||
} {1377}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TABLE t1(docid, words);
|
||||
CREATE VIRTUAL TABLE x2 USING fts4;
|
||||
}
|
||||
fts_kjv_genesis
|
||||
do_test 2.2 {
|
||||
foreach id [db eval {SELECT docid FROM t1}] {
|
||||
execsql {
|
||||
INSERT INTO x2(docid, content) SELECT $id, words FROM t1 WHERE docid=$id
|
||||
}
|
||||
}
|
||||
foreach id [db eval {SELECT docid FROM t1}] {
|
||||
execsql {
|
||||
INSERT INTO x2(docid, content) SELECT NULL, words FROM t1 WHERE docid=$id
|
||||
}
|
||||
if {[db one {SELECT count(*) FROM x2_segdir WHERE level<2}]==2} break
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT count(*) FROM x2_segdir WHERE level=2;
|
||||
SELECT count(*) FROM x2_segdir WHERE level=3;
|
||||
} {6 0}
|
||||
|
||||
do_execsql_test 2.4 {
|
||||
INSERT INTO x2(x2) VALUES('merge=4,4');
|
||||
SELECT count(*) FROM x2_segdir WHERE level=2;
|
||||
SELECT count(*) FROM x2_segdir WHERE level=3;
|
||||
} {6 1}
|
||||
|
||||
do_execsql_test 2.5 {
|
||||
SELECT end_block FROM x2_segdir WHERE level=3;
|
||||
INSERT INTO x2(x2) VALUES('merge=4,4');
|
||||
SELECT end_block FROM x2_segdir WHERE level=3;
|
||||
INSERT INTO x2(x2) VALUES('merge=4,4');
|
||||
SELECT end_block FROM x2_segdir WHERE level=3;
|
||||
} {{3828 -3430} {3828 -10191} {3828 -14109}}
|
||||
|
||||
do_execsql_test 2.6 {
|
||||
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
|
||||
blockid BETWEEN start_block AND leaves_end_block
|
||||
AND level=3
|
||||
} {14109}
|
||||
|
||||
do_execsql_test 2.7 {
|
||||
INSERT INTO x2(x2) VALUES('merge=1000,4');
|
||||
SELECT end_block FROM x2_segdir WHERE level=3;
|
||||
} {{3828 86120}}
|
||||
|
||||
do_execsql_test 2.8 {
|
||||
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
|
||||
blockid BETWEEN start_block AND leaves_end_block
|
||||
AND level=3
|
||||
} {86120}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test that delete markers are removed from FTS segments when possible.
|
||||
# It is only possible to remove delete markers when the output of the
|
||||
# merge operation will become the oldest segment in the index.
|
||||
#
|
||||
# 3.1 - when the oldest segment is created by an 'optimize'.
|
||||
# 3.2 - when the oldest segment is created by an incremental merge.
|
||||
# 3.3 - by a crisis merge.
|
||||
#
|
||||
|
||||
proc insert_doc {args} {
|
||||
foreach iDoc $args {
|
||||
set L [lindex {
|
||||
{In your eagerness to engage the Trojans,}
|
||||
{don’t any of you charge ahead of others,}
|
||||
{trusting in your strength and horsemanship.}
|
||||
{And don’t lag behind. That will hurt our charge.}
|
||||
{Any man whose chariot confronts an enemy’s}
|
||||
{should thrust with his spear at him from there.}
|
||||
{That’s the most effective tactic, the way}
|
||||
{men wiped out city strongholds long ago —}
|
||||
{their chests full of that style and spirit.}
|
||||
} [expr $iDoc%9]]
|
||||
execsql { REPLACE INTO x3(docid, content) VALUES($iDoc, $L) }
|
||||
}
|
||||
}
|
||||
|
||||
proc delete_doc {args} {
|
||||
foreach iDoc $args {
|
||||
execsql { DELETE FROM x3 WHERE docid = $iDoc }
|
||||
}
|
||||
}
|
||||
|
||||
proc second {x} { lindex $x 1 }
|
||||
db func second second
|
||||
|
||||
do_execsql_test 3.0 { CREATE VIRTUAL TABLE x3 USING fts4 }
|
||||
|
||||
do_test 3.1.1 {
|
||||
db transaction { insert_doc 1 2 3 4 5 6 }
|
||||
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
|
||||
} {0 0 412}
|
||||
do_test 3.1.2 {
|
||||
delete_doc 1 2 3 4 5 6
|
||||
execsql { SELECT count(*) FROM x3_segdir }
|
||||
} {0}
|
||||
do_test 3.1.3 {
|
||||
db transaction {
|
||||
insert_doc 1 2 3 4 5 6 7 8 9
|
||||
delete_doc 9 8 7
|
||||
}
|
||||
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
|
||||
} {0 0 591 0 1 65 0 2 72 0 3 76}
|
||||
do_test 3.1.4 {
|
||||
execsql { INSERT INTO x3(x3) VALUES('optimize') }
|
||||
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
|
||||
} {0 0 412}
|
||||
|
||||
do_test 3.2.1 {
|
||||
execsql { DELETE FROM x3 }
|
||||
insert_doc 8 7 6 5 4 3 2 1
|
||||
delete_doc 7 8
|
||||
execsql { SELECT count(*) FROM x3_segdir }
|
||||
} {10}
|
||||
do_test 3.2.2 {
|
||||
execsql { INSERT INTO x3(x3) VALUES('merge=500,10') }
|
||||
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
|
||||
} {1 0 412}
|
||||
|
||||
# This assumes the crisis merge happens when there are already 16
|
||||
# segments and one more is added.
|
||||
#
|
||||
do_test 3.3.1 {
|
||||
execsql { DELETE FROM x3 }
|
||||
insert_doc 1 2 3 4 5 6 7 8 9 10 11
|
||||
delete_doc 11 10 9 8 7
|
||||
execsql { SELECT count(*) FROM x3_segdir }
|
||||
} {16}
|
||||
|
||||
do_test 3.3.2 {
|
||||
insert_doc 12
|
||||
execsql { SELECT level, idx, second(end_block) FROM x3_segdir WHERE level=1 }
|
||||
} {1 0 412}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check a theory on a bug in fts4 - that segments with idx==0 were not
|
||||
# being incrementally merged correctly. Theory turned out to be false.
|
||||
#
|
||||
do_execsql_test 4.1 {
|
||||
DROP TABLE IF EXISTS x4;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(docid, words);
|
||||
CREATE VIRTUAL TABLE x4 USING fts4(words);
|
||||
}
|
||||
do_test 4.2 {
|
||||
fts_kjv_genesis
|
||||
execsql { INSERT INTO x4 SELECT words FROM t1 }
|
||||
execsql { INSERT INTO x4 SELECT words FROM t1 }
|
||||
} {}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
SELECT level, idx, second(end_block) FROM x4_segdir
|
||||
} {0 0 117483 0 1 118006}
|
||||
|
||||
do_execsql_test 4.4 {
|
||||
INSERT INTO x4(x4) VALUES('merge=10,2');
|
||||
SELECT count(*) FROM x4_segdir;
|
||||
} {3}
|
||||
|
||||
do_execsql_test 4.5 {
|
||||
INSERT INTO x4(x4) VALUES('merge=10,2');
|
||||
SELECT count(*) FROM x4_segdir;
|
||||
} {3}
|
||||
|
||||
do_execsql_test 4.6 {
|
||||
INSERT INTO x4(x4) VALUES('merge=1000,2');
|
||||
SELECT count(*) FROM x4_segdir;
|
||||
} {1}
|
||||
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check that segments are not promoted if the "end_block" field does not
|
||||
# contain a size.
|
||||
#
|
||||
do_execsql_test 5.1 {
|
||||
DROP TABLE IF EXISTS x2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(docid, words);
|
||||
CREATE VIRTUAL TABLE x2 USING fts4;
|
||||
}
|
||||
fts_kjv_genesis
|
||||
|
||||
proc first {L} {lindex $L 0}
|
||||
db func first first
|
||||
|
||||
do_test 5.2 {
|
||||
foreach r [db eval { SELECT rowid FROM t1 }] {
|
||||
execsql {
|
||||
INSERT INTO x2(docid, content) SELECT docid, words FROM t1 WHERE rowid=$r
|
||||
}
|
||||
}
|
||||
foreach d [db eval { SELECT docid FROM t1 LIMIT -1 OFFSET 20 }] {
|
||||
execsql { DELETE FROM x2 WHERE docid = $d }
|
||||
}
|
||||
|
||||
execsql {
|
||||
INSERT INTO x2(x2) VALUES('optimize');
|
||||
SELECT level, idx, end_block FROM x2_segdir
|
||||
}
|
||||
} {2 0 {752 1926}}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
UPDATE x2_segdir SET end_block = CAST( first(end_block) AS INTEGER );
|
||||
SELECT end_block, typeof(end_block) FROM x2_segdir;
|
||||
} {752 integer}
|
||||
|
||||
do_execsql_test 5.4 {
|
||||
INSERT INTO x2 SELECT words FROM t1 LIMIT 50;
|
||||
SELECT level, idx, end_block FROM x2_segdir
|
||||
} {2 0 752 0 0 {758 5174}}
|
||||
|
||||
do_execsql_test 5.5 {
|
||||
UPDATE x2_segdir SET end_block = end_block || ' 1926' WHERE level=2;
|
||||
INSERT INTO x2 SELECT words FROM t1 LIMIT 40;
|
||||
SELECT level, idx, end_block FROM x2_segdir
|
||||
} {0 0 {752 1926} 0 1 {758 5174} 0 2 {763 4170}}
|
||||
|
||||
proc t1_to_x2 {} {
|
||||
foreach id [db eval {SELECT docid FROM t1 LIMIT 2}] {
|
||||
execsql {
|
||||
DELETE FROM x2 WHERE docid=$id;
|
||||
INSERT INTO x2(docid, content) SELECT $id, words FROM t1 WHERE docid=$id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check that segments created by auto-merge are not promoted until they
|
||||
# are completed.
|
||||
#
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
CREATE VIRTUAL TABLE x5 USING fts4;
|
||||
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 0;
|
||||
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 25;
|
||||
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 50;
|
||||
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 75;
|
||||
SELECT count(*) FROM x5_segdir
|
||||
} {4}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
INSERT INTO x5(x5) VALUES('merge=2,4');
|
||||
SELECT level, idx, end_block FROM x5_segdir;
|
||||
} {0 0 {10 9216} 0 1 {21 9330} 0 2 {31 8850} 0 3 {40 8689} 1 0 {1320 -3117}}
|
||||
|
||||
do_execsql_test 6.3 {
|
||||
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 100;
|
||||
SELECT level, idx, end_block FROM x5_segdir;
|
||||
} {
|
||||
0 0 {10 9216} 0 1 {21 9330} 0 2 {31 8850}
|
||||
0 3 {40 8689} 1 0 {1320 -3117} 0 4 {1329 8297}
|
||||
}
|
||||
|
||||
do_execsql_test 6.4 {
|
||||
INSERT INTO x5(x5) VALUES('merge=200,4');
|
||||
SELECT level, idx, end_block FROM x5_segdir;
|
||||
} {0 0 {1329 8297} 1 0 {1320 28009}}
|
||||
|
||||
do_execsql_test 6.5 {
|
||||
INSERT INTO x5 SELECT words FROM t1;
|
||||
SELECT level, idx, end_block FROM x5_segdir;
|
||||
} {
|
||||
0 1 {1329 8297} 0 0 {1320 28009} 0 2 {1449 118006}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Ensure that if part of an incremental merge is performed by an old
|
||||
# version that does not support storing segment sizes in the end_block
|
||||
# field, no size is stored in the final segment (as it would be incorrect).
|
||||
#
|
||||
do_execsql_test 7.1 {
|
||||
CREATE VIRTUAL TABLE x6 USING fts4;
|
||||
INSERT INTO x6 SELECT words FROM t1;
|
||||
INSERT INTO x6 SELECT words FROM t1;
|
||||
INSERT INTO x6 SELECT words FROM t1;
|
||||
INSERT INTO x6 SELECT words FROM t1;
|
||||
INSERT INTO x6 SELECT words FROM t1;
|
||||
INSERT INTO x6 SELECT words FROM t1;
|
||||
SELECT level, idx, end_block FROM x6_segdir;
|
||||
} {
|
||||
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
|
||||
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
|
||||
}
|
||||
|
||||
do_execsql_test 7.2 {
|
||||
INSERT INTO x6(x6) VALUES('merge=25,4');
|
||||
SELECT level, idx, end_block FROM x6_segdir;
|
||||
} {
|
||||
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
|
||||
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
|
||||
1 0 {16014 -51226}
|
||||
}
|
||||
|
||||
do_execsql_test 7.3 {
|
||||
UPDATE x6_segdir SET end_block = first(end_block) WHERE level=1;
|
||||
SELECT level, idx, end_block FROM x6_segdir;
|
||||
} {
|
||||
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
|
||||
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
|
||||
1 0 16014
|
||||
}
|
||||
|
||||
do_execsql_test 7.4 {
|
||||
INSERT INTO x6(x6) VALUES('merge=25,4');
|
||||
SELECT level, idx, end_block FROM x6_segdir;
|
||||
} {
|
||||
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
|
||||
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
|
||||
1 0 16014
|
||||
}
|
||||
|
||||
do_execsql_test 7.5 {
|
||||
INSERT INTO x6(x6) VALUES('merge=2500,4');
|
||||
SELECT level, idx, end_block FROM x6_segdir;
|
||||
} {
|
||||
0 0 {598 118006} 0 1 {718 118006} 1 0 16014
|
||||
}
|
||||
|
||||
do_execsql_test 7.6 {
|
||||
INSERT INTO x6(x6) VALUES('merge=2500,2');
|
||||
SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir;
|
||||
} {
|
||||
2 0 23695 24147 {41262 633507}
|
||||
}
|
||||
|
||||
do_execsql_test 7.7 {
|
||||
SELECT sum(length(block)) FROM x6_segments
|
||||
WHERE blockid BETWEEN 23695 AND 24147
|
||||
} {633507}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
# 2014 May 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS4 module.
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts4growth2
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
source $testdir/genesis.tcl
|
||||
|
||||
do_execsql_test 1.0 { CREATE TABLE t1(docid, words); }
|
||||
fts_kjv_genesis
|
||||
|
||||
proc structure {} {
|
||||
puts [ db eval {SELECT level, count(*) FROM x1_segdir GROUP BY level} ]
|
||||
}
|
||||
|
||||
proc tt {val} {
|
||||
execsql {
|
||||
DELETE FROM x1
|
||||
WHERE docid IN (SELECT docid FROM t1 WHERE (rowid-1)%4==$val+0);
|
||||
}
|
||||
execsql {
|
||||
INSERT INTO x1(docid, content)
|
||||
SELECT docid, words FROM t1 WHERE (rowid%4)==$val+0;
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts4;
|
||||
INSERT INTO x1(x1) VALUES('automerge=2');
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
for {set i 0} {$i < 40} {incr i} {
|
||||
tt 0 ; tt 1 ; tt 2 ; tt 3
|
||||
}
|
||||
execsql {
|
||||
SELECT max(level) FROM x1_segdir;
|
||||
SELECT count(*) FROM x1_segdir WHERE level=2;
|
||||
}
|
||||
} {2 1}
|
||||
|
||||
do_test 1.3 {
|
||||
for {set i 0} {$i < 40} {incr i} {
|
||||
tt 0 ; tt 1 ; tt 2 ; tt 3
|
||||
}
|
||||
execsql {
|
||||
SELECT max(level) FROM x1_segdir;
|
||||
SELECT count(*) FROM x1_segdir WHERE level=2;
|
||||
}
|
||||
} {2 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 2.1 {
|
||||
DELETE FROM t1 WHERE rowid>16;
|
||||
DROP TABLE IF EXISTS x1;
|
||||
CREATE VIRTUAL TABLE x1 USING fts4;
|
||||
}
|
||||
|
||||
db func second second
|
||||
proc second {L} {lindex $L 1}
|
||||
|
||||
for {set tn 0} {$tn < 40} {incr tn} {
|
||||
do_test 2.2.$tn {
|
||||
for {set i 0} {$i < 100} {incr i} {
|
||||
tt 0 ; tt 1 ; tt 2 ; tt 3
|
||||
}
|
||||
execsql { SELECT max(level) FROM x1_segdir }
|
||||
} {1}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -53,50 +53,6 @@ do_execsql_test 2.2 { SELECT count(*) FROM t1_segdir; } 35
|
||||
do_execsql_test 2.3 { INSERT INTO t1(t1) VALUES('optimize') } {}
|
||||
do_execsql_test 2.4 { SELECT count(*) FROM t1_segdir; } 1
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Now test that the automerge=? option appears to work.
|
||||
#
|
||||
do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING fts4; }
|
||||
|
||||
set doc ""
|
||||
foreach c1 "a b c d e f g h i j" {
|
||||
foreach c2 "a b c d e f g h i j" {
|
||||
foreach c3 "a b c d e f g h i j" {
|
||||
lappend doc "$c1$c2$c3"
|
||||
}
|
||||
}
|
||||
}
|
||||
set doc [string repeat $doc 10]
|
||||
|
||||
foreach {tn am expected} {
|
||||
1 {automerge=2} {1 1 2 1 4 1 6 1}
|
||||
2 {automerge=4} {1 2 2 1 3 1}
|
||||
3 {automerge=8} {0 4 1 3 2 1}
|
||||
4 {automerge=1} {0 4 1 3 2 1}
|
||||
} {
|
||||
foreach {tn2 openclose} {1 {} 2 { db close ; sqlite3 db test.db }} {
|
||||
do_test 2.2.$tn.$tn2 {
|
||||
execsql { DELETE FROM t2 }
|
||||
execsql { INSERT INTO t2(t2) VALUES($am) };
|
||||
|
||||
eval $openclose
|
||||
|
||||
for {set i 0} {$i < 100} {incr i} {
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES($doc);
|
||||
INSERT INTO t2 VALUES($doc);
|
||||
INSERT INTO t2 VALUES($doc);
|
||||
INSERT INTO t2 VALUES($doc);
|
||||
INSERT INTO t2 VALUES($doc);
|
||||
COMMIT;
|
||||
}
|
||||
}
|
||||
|
||||
execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
|
||||
} [list {*}$expected]
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_enable_shared_cache $::enable_shared_cache
|
||||
finish_test
|
||||
|
||||
@@ -165,51 +165,6 @@ do_execsql_test 5.4 { SELECT docid FROM t2 WHERE t2 MATCH 'c' } {3}
|
||||
|
||||
do_execsql_test 5.x { DROP TABLE t2 }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that if an indexed column name is a prefix of a notindexed column
|
||||
# name, the column is still correctly tokenized. This was a problem at one
|
||||
# point.
|
||||
do_execsql_test 6.1.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(
|
||||
poiCategory, poiCategoryId, notindexed=poiCategoryId
|
||||
);
|
||||
INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
|
||||
}
|
||||
|
||||
do_execsql_test 6.1.2 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
|
||||
} { Restaurant 6021 }
|
||||
do_execsql_test 6.1.3 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 're*';
|
||||
} { Restaurant 6021 }
|
||||
do_execsql_test 6.1.4 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH '6021';
|
||||
} {}
|
||||
do_execsql_test 6.1.5 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH '60*';
|
||||
} {}
|
||||
|
||||
do_execsql_test 6.2.1 {
|
||||
DROP TABLE t1;
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(
|
||||
poiCategory, poiCategoryId, notindexed=poiCategory
|
||||
);
|
||||
INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
|
||||
}
|
||||
|
||||
do_execsql_test 6.2.2 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
|
||||
} {}
|
||||
do_execsql_test 6.2.3 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 're*';
|
||||
} {}
|
||||
do_execsql_test 6.2.4 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH '6021';
|
||||
} { Restaurant 6021 }
|
||||
do_execsql_test 6.2.5 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH '60*';
|
||||
} { Restaurant 6021 }
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -1194,18 +1194,6 @@ do_test func-24.12 {
|
||||
WHEN 'program' THEN null ELSE t1 END) FROM tbl1
|
||||
}
|
||||
} {,is,free,software}
|
||||
# Tests to verify ticket http://www.sqlite.org/src/tktview/55746f9e65f8587c0
|
||||
do_test func-24.13 {
|
||||
execsql {
|
||||
SELECT typeof(group_concat(x)) FROM (SELECT '' AS x);
|
||||
}
|
||||
} {text}
|
||||
do_test func-24.14 {
|
||||
execsql {
|
||||
SELECT typeof(group_concat(x,''))
|
||||
FROM (SELECT '' AS x UNION ALL SELECT '');
|
||||
}
|
||||
} {text}
|
||||
|
||||
|
||||
# Use the test_isolation function to make sure that type conversions
|
||||
|
||||
+1
-1
@@ -285,7 +285,7 @@ do_test fuzz-1.18 {
|
||||
)
|
||||
))
|
||||
}
|
||||
} {0 {{}}}
|
||||
} {0 -4294967298}
|
||||
|
||||
# At one point the following INSERT statement caused an assert() to fail.
|
||||
#
|
||||
|
||||
@@ -413,29 +413,6 @@ do_execsql_test insert-11.1 {
|
||||
} {123456789 '123456789' '123456789'}
|
||||
|
||||
|
||||
# More columns of input than there are columns in the table.
|
||||
# Ticket http://www.sqlite.org/src/info/e9654505cfda9361
|
||||
#
|
||||
do_execsql_test insert-12.1 {
|
||||
CREATE TABLE t12a(a,b,c,d,e,f,g);
|
||||
INSERT INTO t12a VALUES(101,102,103,104,105,106,107);
|
||||
CREATE TABLE t12b(x);
|
||||
INSERT INTO t12b(x,rowid,x,x,x,x,x) SELECT * FROM t12a;
|
||||
SELECT rowid, x FROM t12b;
|
||||
} {102 101}
|
||||
do_execsql_test insert-12.2 {
|
||||
CREATE TABLE tab1( value INTEGER);
|
||||
INSERT INTO tab1 (value, _rowid_) values( 11, 1);
|
||||
INSERT INTO tab1 (value, _rowid_) SELECT 22,999;
|
||||
SELECT * FROM tab1;
|
||||
} {11 22}
|
||||
do_execsql_test insert-12.3 {
|
||||
CREATE TABLE t12c(a, b DEFAULT 'xyzzy', c);
|
||||
INSERT INTO t12c(a, rowid, c) SELECT 'one', 999, 'two';
|
||||
SELECT * FROM t12c;
|
||||
} {one xyzzy two}
|
||||
|
||||
|
||||
integrity_check insert-99.0
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -880,6 +880,48 @@ do_malloc_test 39 -tclprep {
|
||||
db close
|
||||
}
|
||||
|
||||
reset_db
|
||||
add_test_utf16bin_collate db
|
||||
do_execsql_test 40.1 {
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES('fghij');
|
||||
INSERT INTO t1 VALUES('pqrst');
|
||||
INSERT INTO t1 VALUES('abcde');
|
||||
INSERT INTO t1 VALUES('uvwxy');
|
||||
INSERT INTO t1 VALUES('klmno');
|
||||
}
|
||||
do_execsql_test 40.2 {
|
||||
SELECT * FROM t1 ORDER BY 1 COLLATE utf16bin;
|
||||
} {abcde fghij klmno pqrst uvwxy}
|
||||
do_faultsim_test 40.3 -faults oom-trans* -body {
|
||||
execsql {
|
||||
SELECT * FROM t1 ORDER BY 1 COLLATE utf16bin;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {abcde fghij klmno pqrst uvwxy}}
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
reset_db
|
||||
add_test_utf16bin_collate db
|
||||
set big [string repeat x 200]
|
||||
do_execsql_test 41.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a COLLATE utf16bin);
|
||||
INSERT INTO t1 VALUES('fghij' || $::big);
|
||||
INSERT INTO t1 VALUES('pqrst' || $::big);
|
||||
INSERT INTO t1 VALUES('abcde' || $::big);
|
||||
INSERT INTO t1 VALUES('uvwxy' || $::big);
|
||||
INSERT INTO t1 VALUES('klmno' || $::big);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
}
|
||||
do_faultsim_test 41.2 -faults oom* -body {
|
||||
execsql { SELECT * FROM t1 WHERE a = ('abcde' || $::big)}
|
||||
} -test {
|
||||
faultsim_test_result [list 0 "abcde$::big"]
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
# Ensure that no file descriptors were leaked.
|
||||
do_test malloc-99.X {
|
||||
catch {db close}
|
||||
|
||||
+22
-1
@@ -25,7 +25,6 @@ if {!$MEMDEBUG} {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# Construct a test database
|
||||
#
|
||||
forcedelete test.db.bu
|
||||
@@ -116,6 +115,28 @@ ifcapable stat3 {
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
PRAGMA cache_size = 5;
|
||||
}
|
||||
do_faultsim_test 7 -faults oom-trans* -prep {
|
||||
if {$iFail < 500} { set iFail 2000 }
|
||||
if {$iFail > 1215} { set iFail 2000 }
|
||||
} -body {
|
||||
execsql {
|
||||
WITH r(x,y) AS (
|
||||
SELECT 1, randomblob(100)
|
||||
UNION ALL
|
||||
SELECT x+1, randomblob(100) FROM r
|
||||
LIMIT 1000
|
||||
)
|
||||
SELECT count(x), length(y) FROM r GROUP BY (x%5)
|
||||
}
|
||||
} -test {
|
||||
set res [list 200 100 200 100 200 100 200 100 200 100]
|
||||
faultsim_test_result [list 0 $res]
|
||||
}
|
||||
|
||||
|
||||
# Ensure that no file descriptors were leaked.
|
||||
do_test malloc-99.X {
|
||||
catch {db close}
|
||||
|
||||
@@ -604,21 +604,5 @@ do_execsql_test misc1-19.2 {
|
||||
SELECT * FROM t19b;
|
||||
} {4 5 6}
|
||||
|
||||
# 2014-05-16: Tests for the SQLITE_TESTCTRL_FAULT_INSTALL feature.
|
||||
#
|
||||
unset -nocomplain fault_callbacks
|
||||
set fault_callbacks {}
|
||||
proc fault_callback {n} {
|
||||
lappend ::fault_callbacks $n
|
||||
return 0
|
||||
}
|
||||
do_test misc1-19.1 {
|
||||
sqlite3_test_control_fault_install fault_callback
|
||||
set fault_callbacks
|
||||
} {0}
|
||||
do_test misc1-19.2 {
|
||||
sqlite3_test_control_fault_install
|
||||
set fault_callbacks
|
||||
} {0}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
# 2014-05-07
|
||||
#
|
||||
# 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 nolock=1 and immutable=1 query
|
||||
# parameters and the SQLITE_IOCAP_IMMUTABLE device characteristic.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
unset -nocomplain tvfs_calls
|
||||
proc tvfs_reset {} {
|
||||
global tvfs_calls
|
||||
array set tvfs_calls {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
|
||||
}
|
||||
proc tvfs_callback {op args} {
|
||||
global tvfs_calls
|
||||
incr tvfs_calls($op)
|
||||
return SQLITE_OK
|
||||
}
|
||||
tvfs_reset
|
||||
|
||||
testvfs tvfs
|
||||
tvfs script tvfs_callback
|
||||
tvfs filter {xLock xUnlock xCheckReservedLock xAccess}
|
||||
|
||||
############################################################################
|
||||
# Verify that the nolock=1 query parameter for URI filenames disables all
|
||||
# calls to xLock and xUnlock for rollback databases.
|
||||
#
|
||||
do_test nolock-1.0 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
tvfs_reset
|
||||
sqlite db test.db -vfs tvfs
|
||||
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
|
||||
} {xLock 7 xUnlock 5 xCheckReservedLock 0}
|
||||
|
||||
do_test nolock-1.1 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
tvfs_reset
|
||||
sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1
|
||||
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
|
||||
} {xLock 7 xUnlock 5 xCheckReservedLock 0}
|
||||
|
||||
do_test nolock-1.2 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
tvfs_reset
|
||||
sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1
|
||||
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
|
||||
} {xLock 0 xUnlock 0 xCheckReservedLock 0}
|
||||
|
||||
do_test nolock-1.3 {
|
||||
db close
|
||||
tvfs_reset
|
||||
sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1 -readonly 1
|
||||
db eval {SELECT * FROM t1}
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
|
||||
} {xLock 2 xUnlock 2 xCheckReservedLock 0}
|
||||
|
||||
do_test nolock-1.4 {
|
||||
db close
|
||||
tvfs_reset
|
||||
sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1 -readonly 1
|
||||
db eval {SELECT * FROM t1}
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
|
||||
} {xLock 0 xUnlock 0 xCheckReservedLock 0}
|
||||
|
||||
#############################################################################
|
||||
# Verify that immutable=1 disables both locking and xAccess calls to the
|
||||
# journal files.
|
||||
#
|
||||
do_test nolock-2.0 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
# begin by creating a test database
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1 VALUES('hello','world');
|
||||
CREATE TABLE t2(x,y);
|
||||
INSERT INTO t2 VALUES(12345,67890);
|
||||
SELECT * FROM t1, t2;
|
||||
}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-2.1 {
|
||||
tvfs_reset
|
||||
sqlite3 db2 test.db -vfs tvfs
|
||||
db2 eval {SELECT * FROM t1, t2}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-2.2 {
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
|
||||
xAccess $::tvfs_calls(xAccess)
|
||||
} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
|
||||
|
||||
|
||||
do_test nolock-2.11 {
|
||||
db2 close
|
||||
tvfs_reset
|
||||
sqlite3 db2 file:test.db?immutable=0 -vfs tvfs -uri 1
|
||||
db2 eval {SELECT * FROM t1, t2}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-2.12 {
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
|
||||
xAccess $::tvfs_calls(xAccess)
|
||||
} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
|
||||
|
||||
|
||||
do_test nolock-2.21 {
|
||||
db2 close
|
||||
tvfs_reset
|
||||
sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1
|
||||
db2 eval {SELECT * FROM t1, t2}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-2.22 {
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
|
||||
xAccess $::tvfs_calls(xAccess)
|
||||
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
|
||||
|
||||
do_test nolock-2.31 {
|
||||
db2 close
|
||||
tvfs_reset
|
||||
sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1 -readonly 1
|
||||
db2 eval {SELECT * FROM t1, t2}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-2.32 {
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
|
||||
xAccess $::tvfs_calls(xAccess)
|
||||
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
|
||||
|
||||
############################################################################
|
||||
# Verify that the SQLITE_IOCAP_IMMUTABLE flag works
|
||||
#
|
||||
do_test nolock-3.1 {
|
||||
db2 close
|
||||
tvfs devchar immutable
|
||||
tvfs_reset
|
||||
sqlite3 db2 test.db -vfs tvfs
|
||||
db2 eval {SELECT * FROM t1, t2}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-3.2 {
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
|
||||
xAccess $::tvfs_calls(xAccess)
|
||||
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
|
||||
|
||||
do_test nolock-3.11 {
|
||||
db2 close
|
||||
tvfs_reset
|
||||
sqlite3 db2 test.db -vfs tvfs -readonly 1
|
||||
db2 eval {SELECT * FROM t1, t2}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-3.12 {
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
|
||||
xAccess $::tvfs_calls(xAccess)
|
||||
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
|
||||
|
||||
db2 close
|
||||
db close
|
||||
tvfs delete
|
||||
finish_test
|
||||
@@ -112,7 +112,7 @@ set allquicktests [test_set $alltests -exclude {
|
||||
incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test
|
||||
vtab_err.test walslow.test walcrash.test walcrash3.test
|
||||
walthread.test rtree3.test indexfault.test securedel2.test
|
||||
fts4growth.test fts4growth2.test
|
||||
sort3.test sort4.test
|
||||
}]
|
||||
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
|
||||
set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
|
||||
@@ -197,7 +197,6 @@ test_suite "fts3" -prefix "" -description {
|
||||
fts3corrupt2.test fts3first.test fts4langid.test fts4merge.test
|
||||
fts4check.test fts4unicode.test fts4noti.test
|
||||
fts3varint.test
|
||||
fts4growth.test fts4growth2.test
|
||||
}
|
||||
|
||||
test_suite "nofaultsim" -prefix "" -description {
|
||||
@@ -333,6 +332,12 @@ test_suite "coverage-analyze" -description {
|
||||
analyze.test analyzeB.test mallocA.test
|
||||
}
|
||||
|
||||
test_suite "coverage-sorter" -description {
|
||||
Coverage tests for file vdbesort.c.
|
||||
} -files {
|
||||
sort.test sortfault.test
|
||||
}
|
||||
|
||||
|
||||
lappend ::testsuitelist xxx
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -464,7 +469,7 @@ test_suite "multithread" -description {
|
||||
} -files {
|
||||
delete.test delete2.test insert.test rollback.test select1.test
|
||||
select2.test trans.test update.test vacuum.test types.test
|
||||
types2.test types3.test
|
||||
types2.test types3.test sort4.test
|
||||
} -shutdown {
|
||||
catch {db close}
|
||||
sqlite3_shutdown
|
||||
|
||||
@@ -32,9 +32,6 @@ do_test rdonly-1.1 {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1}
|
||||
do_test rdonly-1.1.1 {
|
||||
sqlite3_db_readonly db main
|
||||
} {0}
|
||||
|
||||
# Changes the write version from 1 to 3. Verify that the database
|
||||
# can be read but not written.
|
||||
@@ -50,9 +47,6 @@ do_test rdonly-1.3 {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1}
|
||||
do_test rdonly-1.3.1 {
|
||||
sqlite3_db_readonly db main
|
||||
} {1}
|
||||
do_test rdonly-1.4 {
|
||||
catchsql {
|
||||
INSERT INTO t1 VALUES(2)
|
||||
|
||||
+2
-54
@@ -302,60 +302,8 @@ do_test shell5-1.11 {
|
||||
sqlite3 db test.db
|
||||
db eval {SELECT *, '|' FROM t1}
|
||||
} {a b { } | x y {} | p q r |}
|
||||
|
||||
|
||||
db close
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
sqlite3 db test.db
|
||||
do_test shell5-2.1 {
|
||||
set fd [open shell5.csv w]
|
||||
puts $fd ",hello"
|
||||
close $fd
|
||||
catchcmd test.db [string trim {
|
||||
.mode csv
|
||||
CREATE TABLE t1(a, b);
|
||||
.import shell5.csv t1
|
||||
}]
|
||||
db eval { SELECT * FROM t1 }
|
||||
} {{} hello}
|
||||
|
||||
do_test shell5-2.2 {
|
||||
set fd [open shell5.csv w]
|
||||
puts $fd {"",hello}
|
||||
close $fd
|
||||
catchcmd test.db [string trim {
|
||||
.mode csv
|
||||
CREATE TABLE t2(a, b);
|
||||
.import shell5.csv t2
|
||||
}]
|
||||
db eval { SELECT * FROM t2 }
|
||||
} {{} hello}
|
||||
|
||||
do_test shell5-2.3 {
|
||||
set fd [open shell5.csv w]
|
||||
puts $fd {"x""y",hello}
|
||||
close $fd
|
||||
catchcmd test.db [string trim {
|
||||
.mode csv
|
||||
CREATE TABLE t3(a, b);
|
||||
.import shell5.csv t3
|
||||
}]
|
||||
db eval { SELECT * FROM t3 }
|
||||
} {x\"y hello}
|
||||
|
||||
do_test shell5-2.4 {
|
||||
set fd [open shell5.csv w]
|
||||
puts $fd {"xy""",hello}
|
||||
close $fd
|
||||
catchcmd test.db [string trim {
|
||||
.mode csv
|
||||
CREATE TABLE t4(a, b);
|
||||
.import shell5.csv t4
|
||||
}]
|
||||
db eval { SELECT * FROM t4 }
|
||||
} {xy\" hello}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -181,7 +181,7 @@ do_execsql_test skipscan1-3.2 {
|
||||
do_execsql_test skipscan1-3.2eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
|
||||
} {/* PRIMARY KEY (ANY(a) AND b=?)*/}
|
||||
} {/* INDEX sqlite_autoindex_t3_1 (ANY(a) AND b=?)*/}
|
||||
do_execsql_test skipscan1-3.2sort {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
|
||||
|
||||
@@ -186,20 +186,6 @@ do_execsql_test skipscan2-2.5eqp {
|
||||
SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
|
||||
} {/*INDEX peoplew_idx1 */}
|
||||
|
||||
# A skip-scan on a PK index of a WITHOUT ROWID table.
|
||||
#
|
||||
do_execsql_test skipscan2-3.1 {
|
||||
CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
|
||||
}
|
||||
do_test skipscan2-3.2 {
|
||||
for {set i 0} {$i < 1000} {incr i} {
|
||||
execsql { INSERT INTO t3 VALUES($i%2, $i, 'xyz') }
|
||||
}
|
||||
execsql { ANALYZE }
|
||||
} {}
|
||||
do_eqp_test skipscan2-3.3eqp {
|
||||
SELECT * FROM t3 WHERE b=42;
|
||||
} {0 0 0 {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+176
-3
@@ -8,10 +8,10 @@
|
||||
# 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 CREATE TABLE statement.
|
||||
#
|
||||
# $Id: sort.test,v 1.25 2005/11/14 22:29:06 drh Exp $
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the sorter (code in vdbesort.c).
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -464,4 +464,177 @@ do_test sort-12.1 {
|
||||
}
|
||||
} {1 2 xxx 1 3 yyy 1 1 zzz}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that the sorter in vdbesort.c sorts in a stable fashion.
|
||||
#
|
||||
do_execsql_test sort-13.0 {
|
||||
CREATE TABLE t10(a, b);
|
||||
}
|
||||
do_test sort-13.1 {
|
||||
db transaction {
|
||||
for {set i 0} {$i < 100000} {incr i} {
|
||||
execsql { INSERT INTO t10 VALUES( $i/10, $i%10 ) }
|
||||
}
|
||||
}
|
||||
} {}
|
||||
do_execsql_test sort-13.2 {
|
||||
SELECT a, b FROM t10 ORDER BY a;
|
||||
} [db eval {SELECT a, b FROM t10 ORDER BY a, b}]
|
||||
do_execsql_test sort-13.3 {
|
||||
PRAGMA cache_size = 5;
|
||||
SELECT a, b FROM t10 ORDER BY a;
|
||||
} [db eval {SELECT a, b FROM t10 ORDER BY a, b}]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Sort some large ( > 4KiB) records.
|
||||
#
|
||||
proc cksum {x} {
|
||||
set i1 1
|
||||
set i2 2
|
||||
binary scan $x c* L
|
||||
foreach {a b} $L {
|
||||
set i1 [expr (($i2<<3) + $a) & 0x7FFFFFFF]
|
||||
set i2 [expr (($i1<<3) + $b) & 0x7FFFFFFF]
|
||||
}
|
||||
list $i1 $i2
|
||||
}
|
||||
db func cksum cksum
|
||||
|
||||
do_execsql_test sort-14.0 {
|
||||
PRAGMA cache_size = 5;
|
||||
CREATE TABLE t11(a, b);
|
||||
INSERT INTO t11 VALUES(randomblob(5000), NULL);
|
||||
INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --2
|
||||
INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --3
|
||||
INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --4
|
||||
INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --5
|
||||
INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --6
|
||||
INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --7
|
||||
INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --8
|
||||
INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --9
|
||||
UPDATE t11 SET b = cksum(a);
|
||||
}
|
||||
|
||||
foreach {tn mmap_limit} {
|
||||
1 0
|
||||
2 1000000
|
||||
} {
|
||||
do_test sort-14.$tn {
|
||||
sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $mmap_limit
|
||||
set prev ""
|
||||
db eval { SELECT * FROM t11 ORDER BY b } {
|
||||
if {$b != [cksum $a]} {error "checksum failed"}
|
||||
if {[string compare $b $prev] < 0} {error "sort failed"}
|
||||
set prev $b
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
foreach {tn mmap_limit nWorker tmpstore coremutex fakeheap softheaplimit} {
|
||||
1 0 3 file true false 0
|
||||
2 0 3 file true true 0
|
||||
3 0 0 file true false 0
|
||||
4 1000000 3 file true false 0
|
||||
5 0 0 memory false true 0
|
||||
6 0 0 file false true 1000000
|
||||
7 0 0 file false true 10000
|
||||
} {
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_worker_threads $nWorker
|
||||
if {$coremutex} {
|
||||
sqlite3_config multithread
|
||||
} else {
|
||||
sqlite3_config singlethread
|
||||
}
|
||||
sqlite3_initialize
|
||||
sorter_test_fakeheap $fakeheap
|
||||
sqlite3_soft_heap_limit $softheaplimit
|
||||
|
||||
reset_db
|
||||
sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $mmap_limit
|
||||
execsql "PRAGMA temp_store = $tmpstore"
|
||||
|
||||
set ten [string repeat X 10300]
|
||||
set one [string repeat y 200]
|
||||
|
||||
if {$softheaplimit} {
|
||||
execsql { PRAGMA cache_size = 20 };
|
||||
} else {
|
||||
execsql { PRAGMA cache_size = 5 };
|
||||
}
|
||||
|
||||
do_execsql_test 15.$tn.1 {
|
||||
WITH rr AS (
|
||||
SELECT 4, $ten UNION ALL
|
||||
SELECT 2, $one UNION ALL
|
||||
SELECT 1, $ten UNION ALL
|
||||
SELECT 3, $one
|
||||
)
|
||||
SELECT * FROM rr ORDER BY 1;
|
||||
} [list 1 $ten 2 $one 3 $one 4 $ten]
|
||||
|
||||
do_execsql_test 15.$tn.2 {
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES(4);
|
||||
INSERT INTO t1 VALUES(5);
|
||||
INSERT INTO t1 VALUES(3);
|
||||
INSERT INTO t1 VALUES(2);
|
||||
INSERT INTO t1 VALUES(6);
|
||||
INSERT INTO t1 VALUES(1);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
do_execsql_test 15.$tn.3 {
|
||||
WITH rr AS (
|
||||
SELECT 4, $ten UNION ALL
|
||||
SELECT 2, $one
|
||||
)
|
||||
SELECT * FROM rr ORDER BY 1;
|
||||
} [list 2 $one 4 $ten]
|
||||
|
||||
sorter_test_fakeheap 0
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_worker_threads 0
|
||||
set t(0) singlethread
|
||||
set t(1) multithread
|
||||
set t(2) serialized
|
||||
sqlite3_config $t($sqlite_options(threadsafe))
|
||||
sqlite3_initialize
|
||||
sqlite3_soft_heap_limit 0
|
||||
|
||||
reset_db
|
||||
do_catchsql_test 16.1 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(1, NULL, 3);
|
||||
INSERT INTO t1 VALUES(NULL, 2, 3);
|
||||
INSERT INTO t1 VALUES(1, 2, NULL);
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
CREATE UNIQUE INDEX i1 ON t1(b, a, c);
|
||||
} {0 {}}
|
||||
reset_db
|
||||
do_catchsql_test 16.2 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(1, NULL, 3);
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(1, 2, NULL);
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
CREATE UNIQUE INDEX i1 ON t1(b, a, c);
|
||||
} {1 {UNIQUE constraint failed: t1.b, t1.a, t1.c}}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 17.1 {
|
||||
SELECT * FROM sqlite_master ORDER BY sql;
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
# 2014 March 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.
|
||||
#
|
||||
# Specifically, the tests in this file attempt to verify that
|
||||
# multi-threaded sorting works.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix sort2
|
||||
|
||||
foreach {tn script} {
|
||||
1 { }
|
||||
2 {
|
||||
catch { db close }
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_worker_threads 7
|
||||
reset_db
|
||||
}
|
||||
} {
|
||||
|
||||
eval $script
|
||||
|
||||
do_execsql_test $tn.1 {
|
||||
PRAGMA cache_size = 5;
|
||||
WITH r(x,y) AS (
|
||||
SELECT 1, randomblob(100)
|
||||
UNION ALL
|
||||
SELECT x+1, randomblob(100) FROM r
|
||||
LIMIT 100000
|
||||
)
|
||||
SELECT count(x), length(y) FROM r GROUP BY (x%5)
|
||||
} {
|
||||
20000 100 20000 100 20000 100 20000 100 20000 100
|
||||
}
|
||||
|
||||
do_execsql_test $tn.2.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
WITH r(x,y) AS (
|
||||
SELECT 1, randomblob(100)
|
||||
UNION ALL
|
||||
SELECT x+1, randomblob(100) FROM r
|
||||
LIMIT 10000
|
||||
) INSERT INTO t1 SELECT * FROM r;
|
||||
}
|
||||
|
||||
do_execsql_test $tn.2.2 {
|
||||
CREATE UNIQUE INDEX i1 ON t1(b, a);
|
||||
}
|
||||
|
||||
do_execsql_test $tn.2.3 {
|
||||
CREATE UNIQUE INDEX i2 ON t1(a);
|
||||
}
|
||||
|
||||
do_execsql_test $tn.2.4 { PRAGMA integrity_check } {ok}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test $tn.3 {
|
||||
PRAGMA cache_size = 5;
|
||||
WITH r(x,y) AS (
|
||||
SELECT 1, randomblob(100)
|
||||
UNION ALL
|
||||
SELECT x+1, randomblob(100) FROM r
|
||||
LIMIT 1000000
|
||||
)
|
||||
SELECT count(x), length(y) FROM r GROUP BY (x%5)
|
||||
} {
|
||||
200000 100 200000 100 200000 100 200000 100 200000 100
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_worker_threads 0
|
||||
sqlite3_initialize
|
||||
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# 2014 March 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 tests in this file verify that sorting works when the library is
|
||||
# configured to use mmap(), but the temporary files generated by the
|
||||
# sorter are too large to be completely mapped.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix sort3
|
||||
|
||||
# Sort roughly 20MB of data. Once with a mmap limit of 5MB and once without.
|
||||
#
|
||||
foreach {itest limit} {
|
||||
1 5000000
|
||||
2 0x7FFFFFFF
|
||||
} {
|
||||
sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $limit
|
||||
do_execsql_test 1.$itest {
|
||||
WITH r(x,y) AS (
|
||||
SELECT 1, randomblob(1000)
|
||||
UNION ALL
|
||||
SELECT x+1, randomblob(1000) FROM r
|
||||
LIMIT 20000
|
||||
)
|
||||
SELECT count(*), sum(length(y)) FROM r GROUP BY (x%5);
|
||||
} {
|
||||
4000 4000000
|
||||
4000 4000000
|
||||
4000 4000000
|
||||
4000 4000000
|
||||
4000 4000000
|
||||
}
|
||||
}
|
||||
|
||||
# Sort more than 2GB of data. At one point this was causing a problem.
|
||||
# This test might take one minute or more to run.
|
||||
#
|
||||
do_execsql_test 2 {
|
||||
PRAGMA cache_size = 20000;
|
||||
WITH r(x,y) AS (
|
||||
SELECT 1, randomblob(1000)
|
||||
UNION ALL
|
||||
SELECT x+1, randomblob(1000) FROM r
|
||||
LIMIT 2200000
|
||||
)
|
||||
SELECT count(*), sum(length(y)) FROM r GROUP BY (x%5);
|
||||
} {
|
||||
440000 440000000
|
||||
440000 440000000
|
||||
440000 440000000
|
||||
440000 440000000
|
||||
440000 440000000
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
# 2014 May 6.
|
||||
#
|
||||
# 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 tests in this file are brute force tests of the multi-threaded
|
||||
# sorter.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix sort4
|
||||
|
||||
# Configure the sorter to use 3 background threads.
|
||||
catch { db close }
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_worker_threads 3
|
||||
sqlite3_initialize
|
||||
reset_db
|
||||
|
||||
# Minimum number of seconds to run for. If the value is 0, each test
|
||||
# is run exactly once. Otherwise, tests are repeated until the timeout
|
||||
# expires.
|
||||
set SORT4TIMEOUT 0
|
||||
if {[permutation] == "multithread"} { set SORT4TIMEOUT 300 }
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Set up a table "t1" containing $nRow rows. Each row contains also
|
||||
# contains blob fields that collectively contain at least $nPayload
|
||||
# bytes of content. The table schema is as follows:
|
||||
#
|
||||
# CREATE TABLE t1(a INTEGER, <extra-columns>, b INTEGER);
|
||||
#
|
||||
# For each row, the values of columns "a" and "b" are set to the same
|
||||
# pseudo-randomly selected integer. The "extra-columns", of which there
|
||||
# are at most eight, are named c0, c1, c2 etc. Column c0 contains a 4
|
||||
# byte string. Column c1 an 8 byte string. Field c2 16 bytes, and so on.
|
||||
#
|
||||
# This table is intended to be used for testing queries of the form:
|
||||
#
|
||||
# SELECT a, <cols>, b FROM t1 ORDER BY a;
|
||||
#
|
||||
# The test code checks that rows are returned in order, and that the
|
||||
# values of "a" and "b" are the same for each row (the idea being that
|
||||
# if field "b" at the end of the sorter record has not been corrupted,
|
||||
# the rest of the record is probably Ok as well).
|
||||
#
|
||||
proc populate_table {nRow nPayload} {
|
||||
set nCol 0
|
||||
|
||||
set n 0
|
||||
for {set nCol 0} {$n < $nPayload} {incr nCol} {
|
||||
incr n [expr (4 << $nCol)]
|
||||
}
|
||||
|
||||
set cols [lrange [list xxx c0 c1 c2 c3 c4 c5 c6 c7] 1 $nCol]
|
||||
set data [lrange [list xxx \
|
||||
randomblob(4) randomblob(8) randomblob(16) randomblob(32) \
|
||||
randomblob(64) randomblob(128) randomblob(256) randomblob(512) \
|
||||
] 1 $nCol]
|
||||
|
||||
execsql { DROP TABLE IF EXISTS t1 }
|
||||
|
||||
db transaction {
|
||||
execsql "CREATE TABLE t1(a, [join $cols ,], b);"
|
||||
set insert "INSERT INTO t1 VALUES(:k, [join $data ,], :k)"
|
||||
for {set i 0} {$i < $nRow} {incr i} {
|
||||
set k [expr int(rand()*1000000000)]
|
||||
execsql $insert
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Helper for [do_sorter_test]
|
||||
#
|
||||
proc sorter_test {nRow nRead nPayload} {
|
||||
set res [list]
|
||||
|
||||
set nLoad [expr ($nRow > $nRead) ? $nRead : $nRow]
|
||||
|
||||
set nPayload [expr (($nPayload+3)/4) * 4]
|
||||
set cols [list]
|
||||
foreach {mask col} {
|
||||
0x04 c0 0x08 c1 0x10 c2 0x20 c3
|
||||
0x40 c4 0x80 c5 0x100 c6 0x200 c7
|
||||
} {
|
||||
if {$nPayload & $mask} { lappend cols $col }
|
||||
}
|
||||
|
||||
# Create two SELECT statements. Statement $sql1 uses the sorter to sort
|
||||
# $nRow records of a bit over $nPayload bytes each read from the "t1"
|
||||
# table created by [populate_table] proc above. Rows are sorted in order
|
||||
# of the integer field in each "t1" record.
|
||||
#
|
||||
# The second SQL statement sorts the same set of rows as the first, but
|
||||
# uses a LIMIT clause, causing SQLite to use a temp table instead of the
|
||||
# sorter for sorting.
|
||||
#
|
||||
set sql1 "SELECT a, [join $cols ,], b FROM t1 WHERE rowid<=$nRow ORDER BY a"
|
||||
set sql2 "SELECT a FROM t1 WHERE rowid<=$nRow ORDER BY a LIMIT $nRead"
|
||||
|
||||
# Pass the two SQL statements to a helper command written in C. This
|
||||
# command steps statement $sql1 $nRead times and compares the integer
|
||||
# values in the rows returned with the results of executing $sql2. If
|
||||
# the comparison fails (indicating some bug in the sorter), a Tcl
|
||||
# exception is thrown.
|
||||
#
|
||||
sorter_test_sort4_helper db $sql1 $nRead $sql2
|
||||
set {} {}
|
||||
}
|
||||
|
||||
# Usage:
|
||||
#
|
||||
# do_sorter_test <testname> <args>...
|
||||
#
|
||||
# where <args> are any of the following switches:
|
||||
#
|
||||
# -rows N (number of rows to have sorter sort)
|
||||
# -read N (number of rows to read out of sorter)
|
||||
# -payload N (bytes of payload to read with each row)
|
||||
# -cachesize N (Value for "PRAGMA cache_size = ?")
|
||||
# -repeats N (number of times to repeat test)
|
||||
# -fakeheap BOOL (true to use separate allocations for in-memory records)
|
||||
#
|
||||
proc do_sorter_test {tn args} {
|
||||
set a(-rows) 1000
|
||||
set a(-repeats) 1
|
||||
set a(-read) 100
|
||||
set a(-payload) 100
|
||||
set a(-cachesize) 100
|
||||
set a(-fakeheap) 0
|
||||
|
||||
foreach {s val} $args {
|
||||
if {[info exists a($s)]==0} {
|
||||
unset a(-cachesize)
|
||||
set optlist "[join [array names a] ,] or -cachesize"
|
||||
error "Unknown option $s, expected $optlist"
|
||||
}
|
||||
set a($s) $val
|
||||
}
|
||||
if {[permutation] == "memsys3" || [permutation] == "memsys5"} {
|
||||
set a(-fakeheap) 0
|
||||
}
|
||||
if {$a(-fakeheap)} { sorter_test_fakeheap 1 }
|
||||
|
||||
|
||||
db eval "PRAGMA cache_size = $a(-cachesize)"
|
||||
do_test $tn [subst -nocommands {
|
||||
for {set i 0} {[set i] < $a(-repeats)} {incr i} {
|
||||
sorter_test $a(-rows) $a(-read) $a(-payload)
|
||||
}
|
||||
}] {}
|
||||
|
||||
if {$a(-fakeheap)} { sorter_test_fakeheap 0 }
|
||||
}
|
||||
|
||||
proc clock_seconds {} {
|
||||
db one {SELECT strftime('%s')}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Begin tests here.
|
||||
|
||||
# Create a test database.
|
||||
do_test 1 {
|
||||
execsql "PRAGMA page_size = 4096"
|
||||
populate_table 100000 500
|
||||
} {}
|
||||
|
||||
set iTimeLimit [expr [clock_seconds] + $SORT4TIMEOUT]
|
||||
|
||||
for {set t 2} {1} {incr tn} {
|
||||
do_sorter_test $t.2 -repeats 10 -rows 1000 -read 100
|
||||
do_sorter_test $t.3 -repeats 10 -rows 100000 -read 1000
|
||||
do_sorter_test $t.4 -repeats 10 -rows 100000 -read 1000 -payload 500
|
||||
do_sorter_test $t.5 -repeats 10 -rows 100000 -read 100000 -payload 8
|
||||
do_sorter_test $t.6 -repeats 10 -rows 100000 -read 10 -payload 8
|
||||
do_sorter_test $t.7 -repeats 10 -rows 10000 -read 10000 -payload 8 -fakeheap 1
|
||||
do_sorter_test $t.8 -repeats 10 -rows 100000 -read 10000 -cachesize 250
|
||||
|
||||
set iNow [clock_seconds]
|
||||
if {$iNow>=$iTimeLimit} break
|
||||
do_test "$testprefix-([expr $iTimeLimit-$iNow] seconds remain)" {} {}
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_worker_threads 0
|
||||
sqlite3_initialize
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
# 2014 March 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.
|
||||
#
|
||||
# Specifically, it tests the effects of fault injection on the sorter
|
||||
# module (code in vdbesort.c).
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix sortfault
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA cache_size = 5;
|
||||
}
|
||||
|
||||
foreach {tn mmap_limit nWorker tmpstore threadsmode fakeheap lookaside} {
|
||||
1 0 0 file multithread false false
|
||||
2 100000 0 file multithread false false
|
||||
3 100000 1 file multithread false false
|
||||
4 2000000 0 file singlethread false true
|
||||
} {
|
||||
if {$sqlite_options(threadsafe)} { set threadsmode singlethread }
|
||||
|
||||
catch { db close }
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_worker_threads $nWorker
|
||||
sqlite3_config $threadsmode
|
||||
if { $lookaside } {
|
||||
sqlite3_config_lookaside 100 500
|
||||
} else {
|
||||
sqlite3_config_lookaside 0 0
|
||||
}
|
||||
sqlite3_initialize
|
||||
sorter_test_fakeheap $fakeheap
|
||||
|
||||
set str [string repeat a 1000]
|
||||
puts $threadsmode
|
||||
|
||||
do_faultsim_test 1.$tn -prep {
|
||||
sqlite3 db test.db
|
||||
sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $::mmap_limit
|
||||
execsql { PRAGMA cache_size = 5 }
|
||||
} -body {
|
||||
execsql {
|
||||
WITH r(x,y) AS (
|
||||
SELECT 1, $::str
|
||||
UNION ALL
|
||||
SELECT x+1, $::str FROM r
|
||||
LIMIT 200
|
||||
)
|
||||
SELECT count(x), length(y) FROM r GROUP BY (x%5)
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {40 1000 40 1000 40 1000 40 1000 40 1000}}
|
||||
}
|
||||
|
||||
do_faultsim_test 2.$tn -faults oom* -prep {
|
||||
sqlite3 db test.db
|
||||
sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $::mmap_limit
|
||||
add_test_utf16bin_collate db
|
||||
execsql { PRAGMA cache_size = 5 }
|
||||
} -body {
|
||||
execsql {
|
||||
WITH r(x,y) AS (
|
||||
SELECT 100, $::str
|
||||
UNION ALL
|
||||
SELECT x-1, $::str FROM r
|
||||
LIMIT 100
|
||||
)
|
||||
SELECT count(x), length(y) FROM r GROUP BY y COLLATE utf16bin, (x%5)
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {20 1000 20 1000 20 1000 20 1000 20 1000}}
|
||||
}
|
||||
|
||||
if {$mmap_limit > 1000000} {
|
||||
set str2 [string repeat $str 10]
|
||||
|
||||
sqlite3_memdebug_vfs_oom_test 0
|
||||
sqlite3 db test.db
|
||||
sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $::mmap_limit
|
||||
execsql { PRAGMA cache_size = 5 }
|
||||
|
||||
do_faultsim_test 3.$tn -faults oom-trans* -body {
|
||||
execsql {
|
||||
WITH r(x,y) AS (
|
||||
SELECT 300, $::str2
|
||||
UNION ALL
|
||||
SELECT x-1, $::str2 FROM r
|
||||
LIMIT 300
|
||||
)
|
||||
SELECT count(x), length(y) FROM r GROUP BY y, (x%5)
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {60 10000 60 10000 60 10000 60 10000 60 10000}}
|
||||
}
|
||||
|
||||
sqlite3_memdebug_vfs_oom_test 1
|
||||
}
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_worker_threads 0
|
||||
set t(0) singlethread
|
||||
set t(1) multithread
|
||||
set t(2) serialized
|
||||
sqlite3_config $t($sqlite_options(threadsafe))
|
||||
sqlite3_config_lookaside 100 500
|
||||
sqlite3_initialize
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
}
|
||||
do_test 4.1 {
|
||||
for {set i 0} {$i < 256} {incr i} {
|
||||
execsql {
|
||||
INSERT INTO t1 SELECT
|
||||
((a<<3) + b) & 2147483647,
|
||||
((b<<3) + c) & 2147483647,
|
||||
((c<<3) + a) & 2147483647
|
||||
FROM t1 ORDER BY rowid DESC LIMIT 1;
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 4.2 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql { CREATE UNIQUE INDEX i1 ON t1(a,b,c) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
set a [string repeat a 500]
|
||||
set b [string repeat b 500]
|
||||
set c [string repeat c 500]
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
INSERT INTO t1 VALUES($a, $b, $c);
|
||||
INSERT INTO t1 VALUES($c, $b, $a);
|
||||
}
|
||||
|
||||
do_faultsim_test 5.1 -faults oom* -body {
|
||||
execsql { SELECT * FROM t1 ORDER BY a }
|
||||
} -test {
|
||||
faultsim_test_result [list 0 [list $::a $::b $::c $::c $::b $::a]]
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -27,6 +27,7 @@ static const char zHelp[] =
|
||||
" --stats Show statistics at the end\n"
|
||||
" --testset T Run test-set T\n"
|
||||
" --trace Turn on SQL tracing\n"
|
||||
" --threads N Use up to N threads for sorting\n"
|
||||
" --utf16be Set text encoding to UTF-16BE\n"
|
||||
" --utf16le Set text encoding to UTF-16LE\n"
|
||||
" --verify Run additional verification steps.\n"
|
||||
@@ -1141,6 +1142,7 @@ int main(int argc, char **argv){
|
||||
int nPCache = 0, szPCache = 0;/* --pcache configuration */
|
||||
int nScratch = 0, szScratch=0;/* --scratch configuration */
|
||||
int showStats = 0; /* True for --stats */
|
||||
int nThread = 0; /* --threads value */
|
||||
const char *zTSet = "main"; /* Which --testset torun */
|
||||
int doTrace = 0; /* True for --trace */
|
||||
const char *zEncoding = 0; /* --utf16be or --utf16le */
|
||||
@@ -1225,6 +1227,9 @@ int main(int argc, char **argv){
|
||||
zTSet = argv[++i];
|
||||
}else if( strcmp(z,"trace")==0 ){
|
||||
doTrace = 1;
|
||||
}else if( strcmp(z,"threads")==0 ){
|
||||
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
|
||||
nThread = integerValue(argv[++i]);
|
||||
}else if( strcmp(z,"utf16le")==0 ){
|
||||
zEncoding = "utf16le";
|
||||
}else if( strcmp(z,"utf16be")==0 ){
|
||||
@@ -1273,6 +1278,11 @@ int main(int argc, char **argv){
|
||||
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
|
||||
if( rc ) fatal_error("scratch configuration failed: %d\n", rc);
|
||||
}
|
||||
#ifdef SQLITE_CONFIG_WORKER_THREADS
|
||||
if( nThread>0 ){
|
||||
sqlite3_config(SQLITE_CONFIG_WORKER_THREADS, nThread);
|
||||
}
|
||||
#endif
|
||||
if( nLook>0 ){
|
||||
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1076,6 +1076,7 @@ proc explain_i {sql {db db}} {
|
||||
foreach opcode {
|
||||
Seek SeekGe SeekGt SeekLe SeekLt NotFound Last Rewind
|
||||
NoConflict Next Prev VNext VPrev VFilter
|
||||
SorterSort SorterNext
|
||||
} {
|
||||
set color($opcode) $B
|
||||
}
|
||||
@@ -1098,6 +1099,7 @@ proc explain_i {sql {db db}} {
|
||||
|
||||
if {$opcode=="Next" || $opcode=="Prev"
|
||||
|| $opcode=="VNext" || $opcode=="VPrev"
|
||||
|| $opcode=="SorterNext"
|
||||
} {
|
||||
for {set i $p2} {$i<$addr} {incr i} {
|
||||
incr x($i) 2
|
||||
|
||||
@@ -136,7 +136,6 @@ ifcapable fts3 {
|
||||
"-- SELECT (SELECT max(idx) FROM 'main'.'x1_segdir' WHERE level = ?) + 1"
|
||||
"-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
|
||||
"-- REPLACE INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)"
|
||||
"-- SELECT level, idx, end_block FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ? ORDER BY level DESC, idx ASC"
|
||||
}
|
||||
|
||||
do_trace_test 2.3 {
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
# 2014-03-31
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# The focus of this file is testing the OR optimization on WITHOUT ROWID
|
||||
# tables.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix whereI
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
|
||||
INSERT INTO t1 VALUES(1, 'a', 'z');
|
||||
INSERT INTO t1 VALUES(2, 'b', 'y');
|
||||
INSERT INTO t1 VALUES(3, 'c', 'x');
|
||||
INSERT INTO t1 VALUES(4, 'd', 'w');
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
CREATE INDEX i2 ON t1(c);
|
||||
}
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT a FROM t1 WHERE b='b' OR c='x'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b=?)}
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT a FROM t1 WHERE b='b' OR c='x'
|
||||
} {2 3}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT a FROM t1 WHERE b='a' OR c='z'
|
||||
} {1}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Try that again, this time with non integer PRIMARY KEY values.
|
||||
#
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t2(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
|
||||
INSERT INTO t2 VALUES('i', 'a', 'z');
|
||||
INSERT INTO t2 VALUES('ii', 'b', 'y');
|
||||
INSERT INTO t2 VALUES('iii', 'c', 'x');
|
||||
INSERT INTO t2 VALUES('iv', 'd', 'w');
|
||||
CREATE INDEX i3 ON t2(b);
|
||||
CREATE INDEX i4 ON t2(c);
|
||||
}
|
||||
|
||||
do_eqp_test 2.1 {
|
||||
SELECT a FROM t2 WHERE b='b' OR c='x'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX i3 (b=?)}
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT a FROM t2 WHERE b='b' OR c='x'
|
||||
} {ii iii}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT a FROM t2 WHERE b='a' OR c='z'
|
||||
} {i}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# On a table with a multi-column PK.
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t3(a, b, c, d, PRIMARY KEY(c, b)) WITHOUT ROWID;
|
||||
|
||||
INSERT INTO t3 VALUES('f', 1, 1, 'o');
|
||||
INSERT INTO t3 VALUES('o', 2, 1, 't');
|
||||
INSERT INTO t3 VALUES('t', 1, 2, 't');
|
||||
INSERT INTO t3 VALUES('t', 2, 2, 'f');
|
||||
|
||||
CREATE INDEX t3i1 ON t3(d);
|
||||
CREATE INDEX t3i2 ON t3(a);
|
||||
|
||||
SELECT c||'.'||b FROM t3 WHERE a='t' OR d='t'
|
||||
} {
|
||||
2.1 2.2 1.2
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+2
-48
@@ -24,7 +24,7 @@ db close
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log xLog
|
||||
proc xLog {error_code msg} {
|
||||
lappend ::log $msg
|
||||
lappend ::log $msg
|
||||
}
|
||||
sqlite3 db test.db
|
||||
db eval {PRAGMA mmap_size=0}
|
||||
@@ -128,53 +128,7 @@ while {1} {
|
||||
file_control_win32_av_retry db 10 25
|
||||
sqlite3_test_control_pending_byte $old_pending_byte
|
||||
db close
|
||||
forcedelete test.db
|
||||
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
|
||||
do_test win32lock-3.0 {
|
||||
db eval {
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t1 VALUES(2);
|
||||
INSERT INTO t1 VALUES(3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test win32lock-3.1 {
|
||||
db eval {
|
||||
BEGIN EXCLUSIVE;
|
||||
INSERT INTO t1 VALUES(4);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test win32lock-3.2 {
|
||||
catchsql {
|
||||
BEGIN EXCLUSIVE;
|
||||
INSERT INTO t1 VALUES(5);
|
||||
COMMIT;
|
||||
} db2
|
||||
} {1 {database is locked}}
|
||||
|
||||
do_test win32lock-3.3 {
|
||||
db eval {
|
||||
COMMIT;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test win32lock-3.4 {
|
||||
set handle [lindex [file_control_win32_set_handle db 0] end]
|
||||
list [catchsql {
|
||||
BEGIN EXCLUSIVE;
|
||||
INSERT INTO t1 VALUES(6);
|
||||
COMMIT;
|
||||
}] [file_control_win32_set_handle db $handle] [sqlite3_extended_errcode db]
|
||||
} {{1 {disk I/O error}} {0 0} SQLITE_IOERR_LOCK}
|
||||
|
||||
db2 close
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log
|
||||
test_sqlite3_log
|
||||
sqlite3_initialize
|
||||
finish_test
|
||||
|
||||
+5
-25
@@ -146,17 +146,6 @@ IF NOT DEFINED CONFIGURATIONS (
|
||||
|
||||
%_VECHO% Configurations = '%CONFIGURATIONS%'
|
||||
|
||||
REM
|
||||
REM NOTE: If the command used to invoke NMAKE is not already set, use the
|
||||
REM default.
|
||||
REM
|
||||
IF NOT DEFINED NMAKE_CMD (
|
||||
SET NMAKE_CMD=nmake -B -f Makefile.msc
|
||||
)
|
||||
|
||||
%_VECHO% NmakeCmd = '%NMAKE_CMD%'
|
||||
%_VECHO% NmakeArgs = '%NMAKE_ARGS%'
|
||||
|
||||
REM
|
||||
REM NOTE: Setup environment variables to translate between the MSVC platform
|
||||
REM names and the names to be used for the platform-specific binary
|
||||
@@ -249,7 +238,6 @@ GOTO set_vcvarsall_done
|
||||
:set_vcvarsall_phone
|
||||
SET VCVARSALL=%VCINSTALLDIR%\WPSDK\WP80\vcvarsphoneall.bat
|
||||
:set_vcvarsall_done
|
||||
SET VCVARSALL=%VCVARSALL:\\=\%
|
||||
|
||||
REM
|
||||
REM NOTE: This is the outer loop. There should be exactly one iteration per
|
||||
@@ -277,11 +265,9 @@ FOR %%P IN (%PLATFORMS%) DO (
|
||||
REM and/or Visual Studio. This block may need to be updated in the
|
||||
REM future to account for additional environment variables.
|
||||
REM
|
||||
CALL :fn_UnsetVariable CommandPromptType
|
||||
CALL :fn_UnsetVariable DevEnvDir
|
||||
CALL :fn_UnsetVariable ExtensionSdkDir
|
||||
CALL :fn_UnsetVariable Framework35Version
|
||||
CALL :fn_UnsetVariable Framework40Version
|
||||
CALL :fn_UnsetVariable FrameworkDir
|
||||
CALL :fn_UnsetVariable FrameworkDir32
|
||||
CALL :fn_UnsetVariable FrameworkVersion
|
||||
@@ -297,8 +283,6 @@ FOR %%P IN (%PLATFORMS%) DO (
|
||||
CALL :fn_UnsetVariable WindowsSdkDir
|
||||
CALL :fn_UnsetVariable WindowsSdkDir_35
|
||||
CALL :fn_UnsetVariable WindowsSdkDir_old
|
||||
CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x86
|
||||
CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x64
|
||||
|
||||
REM
|
||||
REM NOTE: Reset the PATH here to the absolute bare minimum required.
|
||||
@@ -315,8 +299,6 @@ FOR %%P IN (%PLATFORMS%) DO (
|
||||
REM environment variables to be picked up by the MSVC makefile
|
||||
REM itself.
|
||||
REM
|
||||
%_AECHO% Building the %%B configuration for platform %%P with name %%D...
|
||||
|
||||
IF /I "%%B" == "Debug" (
|
||||
SET DEBUG=2
|
||||
SET MEMDEBUG=1
|
||||
@@ -392,12 +374,11 @@ FOR %%P IN (%PLATFORMS%) DO (
|
||||
|
||||
REM
|
||||
REM NOTE: The Windows 8.1 SDK has a slightly different directory
|
||||
REM naming convention.
|
||||
REM naming convention. Currently, this tool assumes that
|
||||
REM the Windows 8.1 SDK should only be used with MSVC 2013.
|
||||
REM
|
||||
IF DEFINED USE_WINV63_NSDKLIBPATH (
|
||||
IF "%VisualStudioVersion%" == "12.0" (
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86
|
||||
) ELSE IF "%VisualStudioVersion%" == "12.0" (
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
|
||||
) ELSE (
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
|
||||
)
|
||||
@@ -411,7 +392,7 @@ FOR %%P IN (%PLATFORMS%) DO (
|
||||
REM file, etc.
|
||||
REM
|
||||
IF NOT DEFINED NOCLEAN (
|
||||
%__ECHO% %NMAKE_CMD% clean
|
||||
%__ECHO% nmake -f Makefile.msc clean
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Failed to clean for platform %%P.
|
||||
@@ -423,7 +404,6 @@ FOR %%P IN (%PLATFORMS%) DO (
|
||||
REM need to remove the build output for 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
|
||||
)
|
||||
|
||||
@@ -434,7 +414,7 @@ FOR %%P IN (%PLATFORMS%) DO (
|
||||
REM Also, disable looking for and/or linking to the native Tcl
|
||||
REM runtime library.
|
||||
REM
|
||||
%__ECHO% %NMAKE_CMD% sqlite3.dll XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
|
||||
%__ECHO% nmake -f Makefile.msc sqlite3.dll XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Failed to build %%B "sqlite3.dll" for platform %%P.
|
||||
|
||||
@@ -99,8 +99,6 @@ foreach hdr {
|
||||
mutex.h
|
||||
opcodes.h
|
||||
os_common.h
|
||||
os_setup.h
|
||||
os_win.h
|
||||
os.h
|
||||
pager.h
|
||||
parse.h
|
||||
@@ -239,6 +237,7 @@ foreach file {
|
||||
malloc.c
|
||||
printf.c
|
||||
random.c
|
||||
threads.c
|
||||
utf.c
|
||||
util.c
|
||||
hash.c
|
||||
|
||||
+2
-5
@@ -103,8 +103,6 @@ foreach hdr {
|
||||
mutex.h
|
||||
opcodes.h
|
||||
os_common.h
|
||||
os_setup.h
|
||||
os_win.h
|
||||
os.h
|
||||
pager.h
|
||||
parse.h
|
||||
@@ -170,9 +168,7 @@ proc copy_file {filename} {
|
||||
if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
|
||||
}
|
||||
} elseif {![info exists seen_hdr($hdr)]} {
|
||||
if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
|
||||
set seen_hdr($hdr) 1
|
||||
}
|
||||
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"
|
||||
@@ -253,6 +249,7 @@ foreach file {
|
||||
malloc.c
|
||||
printf.c
|
||||
random.c
|
||||
threads.c
|
||||
utf.c
|
||||
util.c
|
||||
hash.c
|
||||
|
||||
@@ -60,8 +60,6 @@ foreach hdr {
|
||||
keywordhash.h
|
||||
opcodes.h
|
||||
os_common.h
|
||||
os_setup.h
|
||||
os_win.h
|
||||
os.h
|
||||
pager.h
|
||||
parse.h
|
||||
|
||||
+56
-202
@@ -65,16 +65,12 @@
|
||||
# argument is optional and if present must contain the name of the directory
|
||||
# containing the root of the source tree for SQLite. The third argument is
|
||||
# optional and if present must contain the flavor the VSIX package to build.
|
||||
# Currently, the only supported package flavors are "WinRT", "WinRT81", "WP80",
|
||||
# "WP81", and "Win32". The fourth argument is optional and if present must be
|
||||
# a string containing a list of platforms to include in the VSIX package. The
|
||||
# platform list is "platform1,platform2,platform3". The fifth argument is
|
||||
# optional and if present must contain the version of Visual Studio required by
|
||||
# the package. Currently, the only supported versions are "2012" and "2013".
|
||||
# The package flavors "WinRT81" and "WP81" are only supported when the Visual
|
||||
# Studio version is "2013". Typically, when on Windows, this script is
|
||||
# executed using commands similar to the following from a normal Windows
|
||||
# command prompt:
|
||||
# Currently, the only supported package flavors are "WinRT", "WinRT81", and
|
||||
# "WP80". The fourth argument is optional and if present must be a string
|
||||
# containing a list of platforms to include in the VSIX package. The format
|
||||
# of the platform list string is "platform1,platform2,platform3". Typically,
|
||||
# when on Windows, this script is executed using commands similar to the
|
||||
# following from a normal Windows command prompt:
|
||||
#
|
||||
# CD /D C:\dev\sqlite\core
|
||||
# tclsh85 tool\mkvsix.tcl C:\Temp
|
||||
@@ -104,7 +100,7 @@ proc fail { {error ""} {usage false} } {
|
||||
puts stdout "usage:\
|
||||
[file tail [info nameofexecutable]]\
|
||||
[file tail [info script]] <binaryDirectory> \[sourceDirectory\]\
|
||||
\[packageFlavor\] \[platformNames\] \[vsVersion\]"
|
||||
\[packageFlavor\] \[platformNames\]"
|
||||
|
||||
exit 1
|
||||
}
|
||||
@@ -174,81 +170,13 @@ proc writeFile { fileName data } {
|
||||
return ""
|
||||
}
|
||||
|
||||
proc getMinVsVersionXmlChunk { vsVersion } {
|
||||
switch -exact $vsVersion {
|
||||
2012 {
|
||||
return [appendArgs \
|
||||
"\r\n " {MinVSVersion="11.0"}]
|
||||
}
|
||||
2013 {
|
||||
return [appendArgs \
|
||||
"\r\n " {MinVSVersion="12.0"}]
|
||||
}
|
||||
default {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } {
|
||||
proc substFile { fileName } {
|
||||
#
|
||||
# NOTE: Only Visual Studio 2013 supports this SDK manifest attribute.
|
||||
# NOTE: Performs all Tcl command, variable, and backslash substitutions in
|
||||
# the specified file and then rewrites the contents of that same file
|
||||
# with the substituted data.
|
||||
#
|
||||
if {![string equal $vsVersion 2013]} then {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch -exact $packageFlavor {
|
||||
WinRT {
|
||||
return [appendArgs \
|
||||
"\r\n " {MaxPlatformVersion="8.0"}]
|
||||
}
|
||||
WinRT81 {
|
||||
return [appendArgs \
|
||||
"\r\n " {MaxPlatformVersion="8.1"}]
|
||||
}
|
||||
WP80 {
|
||||
return [appendArgs \
|
||||
"\r\n " {MaxPlatformVersion="8.0"}]
|
||||
}
|
||||
WP81 {
|
||||
return [appendArgs \
|
||||
"\r\n " {MaxPlatformVersion="8.1"}]
|
||||
}
|
||||
default {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc getExtraFileListXmlChunk { packageFlavor vsVersion } {
|
||||
#
|
||||
# NOTE: Windows Phone 8.0 does not require any extra attributes in its VSIX
|
||||
# package SDK manifests; however, it appears that Windows Phone 8.1
|
||||
# does.
|
||||
#
|
||||
if {[string equal $packageFlavor WP80]} then {
|
||||
return ""
|
||||
}
|
||||
|
||||
set appliesTo [expr {[string equal $packageFlavor Win32] ? \
|
||||
"VisualC" : "WindowsAppContainer"}]
|
||||
|
||||
switch -exact $vsVersion {
|
||||
2012 {
|
||||
return [appendArgs \
|
||||
"\r\n " AppliesTo=\" $appliesTo \" \
|
||||
"\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
|
||||
}
|
||||
2013 {
|
||||
return [appendArgs \
|
||||
"\r\n " AppliesTo=\" $appliesTo \" \
|
||||
"\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
|
||||
}
|
||||
default {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
|
||||
}
|
||||
|
||||
proc replaceFileNameTokens { fileName name buildName platformName } {
|
||||
@@ -260,15 +188,6 @@ proc replaceFileNameTokens { fileName name buildName platformName } {
|
||||
<name> $name] $fileName]
|
||||
}
|
||||
|
||||
proc substFile { fileName } {
|
||||
#
|
||||
# NOTE: Performs all Tcl command, variable, and backslash substitutions in
|
||||
# the specified file and then rewrites the contents of that same file
|
||||
# with the substituted data.
|
||||
#
|
||||
return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
|
||||
}
|
||||
|
||||
#
|
||||
# NOTE: This is the entry point for this script.
|
||||
#
|
||||
@@ -287,7 +206,7 @@ set rootName [file rootname [file tail $script]]
|
||||
# NOTE: Process and verify all the command line arguments.
|
||||
#
|
||||
set argc [llength $argv]
|
||||
if {$argc < 1 || $argc > 5} then {fail}
|
||||
if {$argc < 1 || $argc > 4} then {fail}
|
||||
|
||||
set binaryDirectory [lindex $argv 0]
|
||||
|
||||
@@ -332,123 +251,58 @@ if {[string length $packageFlavor] == 0} then {
|
||||
fail "invalid package flavor"
|
||||
}
|
||||
|
||||
if {[string equal -nocase $packageFlavor WinRT]} then {
|
||||
set shortName SQLite.WinRT
|
||||
set displayName "SQLite for Windows Runtime"
|
||||
set targetPlatformIdentifier Windows
|
||||
set targetPlatformVersion v8.0
|
||||
set minVsVersion 11.0
|
||||
set extraSdkPath ""
|
||||
set extraFileListAttributes [appendArgs \
|
||||
"\r\n " {AppliesTo="WindowsAppContainer"} \
|
||||
"\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
|
||||
} elseif {[string equal -nocase $packageFlavor WinRT81]} then {
|
||||
set shortName SQLite.WinRT81
|
||||
set displayName "SQLite for Windows Runtime (Windows 8.1)"
|
||||
set targetPlatformIdentifier Windows
|
||||
set targetPlatformVersion v8.1
|
||||
set minVsVersion 12.0
|
||||
set extraSdkPath ""
|
||||
set extraFileListAttributes [appendArgs \
|
||||
"\r\n " {AppliesTo="WindowsAppContainer"} \
|
||||
"\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
|
||||
} elseif {[string equal -nocase $packageFlavor WP80]} then {
|
||||
set shortName SQLite.WP80
|
||||
set displayName "SQLite for Windows Phone"
|
||||
set targetPlatformIdentifier "Windows Phone"
|
||||
set targetPlatformVersion v8.0
|
||||
set minVsVersion 11.0
|
||||
set extraSdkPath "\\..\\$targetPlatformIdentifier"
|
||||
set extraFileListAttributes ""
|
||||
} elseif {[string equal -nocase $packageFlavor Win32]} then {
|
||||
set shortName SQLite.Win32
|
||||
set displayName "SQLite for Windows"
|
||||
set targetPlatformIdentifier Windows
|
||||
set targetPlatformVersion v8.0
|
||||
set minVsVersion 11.0
|
||||
set extraSdkPath ""
|
||||
set extraFileListAttributes [appendArgs \
|
||||
"\r\n " {AppliesTo="VisualC"} \
|
||||
"\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
|
||||
} else {
|
||||
fail "unsupported package flavor, must be one of: WinRT WinRT81 WP80 Win32"
|
||||
}
|
||||
|
||||
if {$argc >= 4} then {
|
||||
set platformNames [list]
|
||||
|
||||
foreach platformName [split [lindex $argv 3] ", "] {
|
||||
set platformName [string trim $platformName]
|
||||
|
||||
if {[string length $platformName] > 0} then {
|
||||
lappend platformNames $platformName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {$argc >= 5} then {
|
||||
set vsVersion [lindex $argv 4]
|
||||
} else {
|
||||
set vsVersion 2012
|
||||
}
|
||||
|
||||
if {[string length $vsVersion] == 0} then {
|
||||
fail "invalid Visual Studio version"
|
||||
}
|
||||
|
||||
if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013]} then {
|
||||
fail [appendArgs \
|
||||
"unsupported Visual Studio version, must be one of: " \
|
||||
[list 2012 2013]]
|
||||
}
|
||||
|
||||
set shortNames(WinRT,2012) SQLite.WinRT
|
||||
set shortNames(WinRT,2013) SQLite.WinRT.2013
|
||||
set shortNames(WinRT81,2013) SQLite.WinRT81
|
||||
set shortNames(WP80,2012) SQLite.WP80
|
||||
set shortNames(WP80,2013) SQLite.WP80.2013
|
||||
set shortNames(WP81,2013) SQLite.WP81
|
||||
set shortNames(Win32,2012) SQLite.Win32
|
||||
set shortNames(Win32,2013) SQLite.Win32.2013
|
||||
|
||||
set displayNames(WinRT,2012) "SQLite for Windows Runtime"
|
||||
set displayNames(WinRT,2013) "SQLite for Windows Runtime"
|
||||
set displayNames(WinRT81,2013) "SQLite for Windows Runtime (Windows 8.1)"
|
||||
set displayNames(WP80,2012) "SQLite for Windows Phone"
|
||||
set displayNames(WP80,2013) "SQLite for Windows Phone"
|
||||
set displayNames(WP81,2013) "SQLite for Windows Phone 8.1"
|
||||
set displayNames(Win32,2012) "SQLite for Windows"
|
||||
set displayNames(Win32,2013) "SQLite for Windows"
|
||||
|
||||
if {[string equal $packageFlavor WinRT]} then {
|
||||
set shortName $shortNames($packageFlavor,$vsVersion)
|
||||
set displayName $displayNames($packageFlavor,$vsVersion)
|
||||
set targetPlatformIdentifier Windows
|
||||
set targetPlatformVersion v8.0
|
||||
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
|
||||
set maxPlatformVersion \
|
||||
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
|
||||
set extraSdkPath ""
|
||||
set extraFileListAttributes \
|
||||
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
|
||||
} elseif {[string equal $packageFlavor WinRT81]} then {
|
||||
if {$vsVersion ne "2013"} then {
|
||||
fail [appendArgs \
|
||||
"unsupported combination, package flavor " $packageFlavor \
|
||||
" is only supported with Visual Studio 2013"]
|
||||
}
|
||||
set shortName $shortNames($packageFlavor,$vsVersion)
|
||||
set displayName $displayNames($packageFlavor,$vsVersion)
|
||||
set targetPlatformIdentifier Windows
|
||||
set targetPlatformVersion v8.1
|
||||
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
|
||||
set maxPlatformVersion \
|
||||
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
|
||||
set extraSdkPath ""
|
||||
set extraFileListAttributes \
|
||||
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
|
||||
} elseif {[string equal $packageFlavor WP80]} then {
|
||||
set shortName $shortNames($packageFlavor,$vsVersion)
|
||||
set displayName $displayNames($packageFlavor,$vsVersion)
|
||||
set targetPlatformIdentifier "Windows Phone"
|
||||
set targetPlatformVersion v8.0
|
||||
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
|
||||
set maxPlatformVersion \
|
||||
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
|
||||
set extraSdkPath "\\..\\$targetPlatformIdentifier"
|
||||
set extraFileListAttributes \
|
||||
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
|
||||
} elseif {[string equal $packageFlavor WP81]} then {
|
||||
if {$vsVersion ne "2013"} then {
|
||||
fail [appendArgs \
|
||||
"unsupported combination, package flavor " $packageFlavor \
|
||||
" is only supported with Visual Studio 2013"]
|
||||
}
|
||||
set shortName $shortNames($packageFlavor,$vsVersion)
|
||||
set displayName $displayNames($packageFlavor,$vsVersion)
|
||||
set targetPlatformIdentifier WindowsPhoneApp
|
||||
set targetPlatformVersion v8.1
|
||||
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
|
||||
set maxPlatformVersion \
|
||||
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
|
||||
set extraSdkPath "\\..\\$targetPlatformIdentifier"
|
||||
set extraFileListAttributes \
|
||||
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
|
||||
} elseif {[string equal $packageFlavor Win32]} then {
|
||||
set shortName $shortNames($packageFlavor,$vsVersion)
|
||||
set displayName $displayNames($packageFlavor,$vsVersion)
|
||||
set targetPlatformIdentifier Windows
|
||||
set targetPlatformVersion v8.0
|
||||
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
|
||||
set maxPlatformVersion \
|
||||
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
|
||||
set extraSdkPath ""
|
||||
set extraFileListAttributes \
|
||||
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
|
||||
} else {
|
||||
fail [appendArgs \
|
||||
"unsupported package flavor, must be one of: " \
|
||||
[list WinRT WinRT81 WP80 WP81 Win32]]
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
@@ -636,7 +490,7 @@ if {![info exists buildNames]} then {
|
||||
# overridden via the command line or the user-specific customizations
|
||||
# file.
|
||||
#
|
||||
if {![info exists platformNames] || [llength $platformNames] == 0} then {
|
||||
if {![info exists platformNames]} then {
|
||||
set platformNames [list x86 x64 ARM]
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# compiler warnings in SQLite.
|
||||
#
|
||||
rm -f sqlite3.c
|
||||
make sqlite3.c
|
||||
make sqlite3.c-debug
|
||||
echo '********** No optimizations. Includes FTS4 and RTREE *********'
|
||||
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
|
||||
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user