Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f82b92643 | |||
| 540ebf8271 | |||
| 60a7523bd3 | |||
| 37f58e9902 | |||
| 8a7c142887 | |||
| 9265d0bdc2 | |||
| 2a78169563 | |||
| 597a8c5f32 | |||
| 0f104d5700 | |||
| 4d9d1f4722 | |||
| e0d058c6d8 | |||
| 19038f1b79 | |||
| 373cfbc760 | |||
| 9454876ddc | |||
| b5b407e5ab | |||
| 67c70142d9 | |||
| af52973724 | |||
| 52fd8e1d0d | |||
| 7a5d80e929 | |||
| 40e6319b61 | |||
| 67ceaa6b9b | |||
| 04f2e3403f | |||
| d5578433ff | |||
| b0367fb8b0 | |||
| f0b9729242 | |||
| d40e208726 | |||
| 7b36ba3da3 | |||
| 606bb3a54e | |||
| 899339154e | |||
| 0efb72c969 | |||
| 8fea5f3b97 | |||
| 2797c21639 | |||
| bfca6a4066 | |||
| fb0a60819b | |||
| 319a170717 | |||
| ed551b95a4 | |||
| 030796df8d | |||
| 2f7d5d8394 | |||
| 484dbef5d9 | |||
| 6154068851 | |||
| 0789377608 | |||
| 4dc3d73d69 | |||
| a6b0a9cb80 | |||
| fc30b042aa | |||
| f2f105d40e | |||
| 36ce6d2341 | |||
| bcebd86f7c | |||
| 8ef0c1fe70 | |||
| 6f92833f9d | |||
| 342ced4b92 | |||
| e74f4651da | |||
| 8b64b3977e | |||
| ec73930adc | |||
| c16eb6934d | |||
| 1700b1c65c | |||
| a0aa13b677 | |||
| 7d6885ae8a | |||
| f64cc49962 | |||
| acf239b589 | |||
| 07f547923e | |||
| 2aba5d96f4 | |||
| 38d073040d | |||
| 81f0740e59 | |||
| 809badc93a | |||
| ab8c4cf3b8 | |||
| 09ac7ec544 | |||
| 243be2b0e1 | |||
| 428c218c90 | |||
| 8c5287ec73 | |||
| e2e2ab3a2d | |||
| a36421ab06 | |||
| dfbfbffd13 | |||
| 50afa2a012 | |||
| 391b36472a | |||
| 6809c96df3 | |||
| 0b5ae72993 | |||
| 78496d55ed | |||
| f2bc4380b2 | |||
| fd0ba2aa22 | |||
| 31856a35b9 | |||
| 486801909c | |||
| 9d0c0ea601 | |||
| c041c16ce1 | |||
| 35d8ac980d | |||
| 2b596da8b7 | |||
| 407fae09ee | |||
| 3b2c9b3250 |
@@ -933,7 +933,9 @@ clean:
|
||||
rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(BEXE) keywordhash.h
|
||||
rm -f $(PUBLISH)
|
||||
rm -f A BAR file http testdb
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -f *.bu *.csv *.db *.db2 *.db-shm *.db-wal *.tcl *.txt *.x
|
||||
rm -rf quota2a quota2b quota2c
|
||||
rm -rf tsrc .target_source
|
||||
rm -f tclsqlite3$(TEXE)
|
||||
@@ -941,6 +943,7 @@ clean:
|
||||
rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
|
||||
rm -f sqlite3.c
|
||||
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
|
||||
rm -f sqlite-output.vsix
|
||||
|
||||
distclean: clean
|
||||
rm -f config.log config.status libtool Makefile sqlite3.pc
|
||||
|
||||
+111
-19
@@ -19,6 +19,12 @@ USE_ICU = 0
|
||||
#
|
||||
USE_CRT_DLL = 0
|
||||
|
||||
# Set this non-0 to attempt setting the native compiler automatically
|
||||
# for cross-compiling the command line tools needed during the compilation
|
||||
# process.
|
||||
#
|
||||
XCOMPILE = 0
|
||||
|
||||
# Set this non-0 to use the native libraries paths for cross-compiling
|
||||
# the command line tools needed during the compilation process.
|
||||
#
|
||||
@@ -30,10 +36,23 @@ USE_NATIVE_LIBPATHS = 0
|
||||
#
|
||||
FOR_WINRT = 0
|
||||
|
||||
# Set this non-0 to skip attempting to look for and/or link with the Tcl
|
||||
# runtime library.
|
||||
#
|
||||
NO_TCL = 0
|
||||
|
||||
# Set this to non-0 to create and use PDBs.
|
||||
#
|
||||
SYMBOLS = 1
|
||||
|
||||
# Set this to non-0 to use the SQLite debugging heap subsystem.
|
||||
#
|
||||
MEMDEBUG = 0
|
||||
|
||||
# Set this to non-0 to use the Win32 native heap subsystem.
|
||||
#
|
||||
WIN32HEAP = 0
|
||||
|
||||
# Set this to one of the following values to enable various debugging
|
||||
# features. Each level includes the debugging options from the previous
|
||||
# levels. Currently, the recognized values for DEBUG are:
|
||||
@@ -63,6 +82,14 @@ CC = cl.exe
|
||||
LD = link.exe
|
||||
!ENDIF
|
||||
|
||||
# Check for the predefined command macro RC. This should point to the resource
|
||||
# compiler binary for the target platform. If it is not defined, simply define
|
||||
# it to the legacy default value 'rc.exe'.
|
||||
#
|
||||
!IFNDEF RC
|
||||
RC = rc.exe
|
||||
!ENDIF
|
||||
|
||||
# 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
|
||||
@@ -71,11 +98,23 @@ LD = link.exe
|
||||
# For example, to use the x86 compiler when cross-compiling for x64, a command
|
||||
# line similar to the following could be used (all on one line):
|
||||
#
|
||||
# nmake /f Makefile.msc
|
||||
# nmake /f Makefile.msc sqlite3.dll
|
||||
# XCOMPILE=1 USE_NATIVE_LIBPATHS=1
|
||||
#
|
||||
# Alternatively, the full path and file name to the compiler binary for the
|
||||
# platform the compilation process is taking place may be specified (all on
|
||||
# one line):
|
||||
#
|
||||
# nmake /f Makefile.msc sqlite3.dll
|
||||
# "NCC=""%VCINSTALLDIR%\bin\cl.exe"""
|
||||
# USE_NATIVE_LIBPATHS=1
|
||||
#
|
||||
!IFNDEF NCC
|
||||
!IFDEF NCC
|
||||
NCC = $(NCC:\\=\)
|
||||
!ELSEIF $(XCOMPILE)!=0
|
||||
NCC = "$(VCINSTALLDIR)\bin\cl.exe"
|
||||
NCC = $(NCC:\\=\)
|
||||
!ELSE
|
||||
NCC = $(CC)
|
||||
!ENDIF
|
||||
|
||||
@@ -87,6 +126,8 @@ NCC = $(CC)
|
||||
NCRTLIBPATH = $(VCINSTALLDIR)\lib
|
||||
!ENDIF
|
||||
|
||||
NCRTLIBPATH = $(NCRTLIBPATH:\\=\)
|
||||
|
||||
# Check for the Platform SDK library path macro. Othertise, this
|
||||
# value will default to the 'lib' directory underneath the Windows
|
||||
# SDK installation directory (the environment variable used appears
|
||||
@@ -97,6 +138,8 @@ NCRTLIBPATH = $(VCINSTALLDIR)\lib
|
||||
NSDKLIBPATH = $(WINDOWSSDKDIR)\lib
|
||||
!ENDIF
|
||||
|
||||
NSDKLIBPATH = $(NSDKLIBPATH:\\=\)
|
||||
|
||||
# C compiler and options for use in building executables that
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
@@ -115,6 +158,7 @@ NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
|
||||
# same unless your are cross-compiling.)
|
||||
#
|
||||
TCC = $(CC) -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise
|
||||
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src
|
||||
|
||||
# When compiling the library for use in the WinRT environment,
|
||||
# the following compile-time options must be used as well to
|
||||
@@ -123,6 +167,9 @@ TCC = $(CC) -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise
|
||||
#
|
||||
!IF $(FOR_WINRT)!=0
|
||||
TCC = $(TCC) -DSQLITE_OS_WINRT=1
|
||||
RCC = $(RCC) -DSQLITE_OS_WINRT=1
|
||||
TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_PARTITION_APP
|
||||
RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_PARTITION_APP
|
||||
!ENDIF
|
||||
|
||||
# Also, we need to dynamically link to the correct MSVC runtime
|
||||
@@ -150,7 +197,9 @@ TCC = $(TCC) -MT
|
||||
#
|
||||
!IF $(USE_AMALGAMATION)==0
|
||||
TCC = $(TCC) -I$(TOP)\ext\fts3
|
||||
RCC = $(RCC) -I$(TOP)\ext\fts3
|
||||
TCC = $(TCC) -I$(TOP)\ext\rtree
|
||||
RCC = $(RCC) -I$(TOP)\ext\rtree
|
||||
!ENDIF
|
||||
|
||||
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
|
||||
@@ -160,18 +209,22 @@ TCC = $(TCC) -I$(TOP)\ext\rtree
|
||||
!IF $(DEBUG)==0
|
||||
TCC = $(TCC) -DNDEBUG
|
||||
BCC = $(BCC) -DNDEBUG
|
||||
RCC = $(RCC) -DNDEBUG
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>1
|
||||
TCC = $(TCC) -DSQLITE_DEBUG
|
||||
RCC = $(RCC) -DSQLITE_DEBUG
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>3
|
||||
TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
|
||||
RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>4
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
|
||||
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
|
||||
!ENDIF
|
||||
|
||||
#
|
||||
@@ -180,23 +233,36 @@ TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
|
||||
#
|
||||
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 native Win32 heap instead of malloc/free?
|
||||
# Use the SQLite debugging heap subsystem?
|
||||
#
|
||||
# TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
|
||||
!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
|
||||
TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
|
||||
RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# The locations of the Tcl header and library files. Also, the library that
|
||||
@@ -254,10 +320,12 @@ LIBREADLINE =
|
||||
# Should the database engine be compiled threadsafe
|
||||
#
|
||||
TCC = $(TCC) -DSQLITE_THREADSAFE=1
|
||||
RCC = $(RCC) -DSQLITE_THREADSAFE=1
|
||||
|
||||
# Do threads override each others locks by default (1), or do we test (-1)
|
||||
#
|
||||
TCC = $(TCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
|
||||
RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
|
||||
|
||||
# Any target libraries which libsqlite must be linked against
|
||||
#
|
||||
@@ -272,6 +340,7 @@ TLIBS =
|
||||
# tables to always be in memory.
|
||||
#
|
||||
TCC = $(TCC) -DSQLITE_TEMP_STORE=1
|
||||
RCC = $(RCC) -DSQLITE_TEMP_STORE=1
|
||||
|
||||
# Enable/disable loadable extensions, and other optional features
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
@@ -289,16 +358,19 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
|
||||
# END required Windows option
|
||||
|
||||
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 symbols are enabled, enable PDBs.
|
||||
# If debugging is enabled, disable all optimizations and enable PDBs.
|
||||
!IF $(DEBUG)>0
|
||||
TCC = $(TCC) -Od -D_DEBUG
|
||||
BCC = $(BCC) -Od -D_DEBUG
|
||||
RCC = $(RCC) -D_DEBUG
|
||||
!ELSE
|
||||
TCC = $(TCC) -O2
|
||||
BCC = $(BCC) -O2
|
||||
@@ -312,12 +384,17 @@ BCC = $(BCC) -Zi
|
||||
# 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
|
||||
TCC = $(TCC) -I$(TOP)\ext\icu
|
||||
RCC = $(RCC) -I$(TOP)\ext\icu
|
||||
TCC = $(TCC) -I$(ICUINCDIR)
|
||||
RCC = $(RCC) -I$(ICUINCDIR)
|
||||
!ENDIF
|
||||
|
||||
# libtool compile/link
|
||||
# Command line prefixes for compiling code, compiling resources,
|
||||
# linking, etc.
|
||||
LTCOMPILE = $(TCC) -Fo$@
|
||||
LTRCOMPILE = $(RCC) -r
|
||||
LTLIB = lib.exe
|
||||
LTLINK = $(TCC) -Fe$@
|
||||
|
||||
@@ -344,8 +421,10 @@ 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
|
||||
@@ -687,10 +766,10 @@ libsqlite3.lib: $(LIBOBJ)
|
||||
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
|
||||
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
|
||||
|
||||
sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib sqlite3.h
|
||||
sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib sqlite3res.lo sqlite3.h
|
||||
$(LTLINK) $(READLINE_FLAGS) \
|
||||
$(TOP)\src\shell.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib sqlite3res.lo $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
@@ -738,6 +817,17 @@ parse.lo: parse.c $(HDR)
|
||||
opcodes.lo: opcodes.c
|
||||
$(LTCOMPILE) -c opcodes.c
|
||||
|
||||
# Rule to build the Win32 resources object file.
|
||||
#
|
||||
sqlite3res.lo: $(TOP)\src\sqlite3.rc $(HDR)
|
||||
echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
|
||||
for /F %%V in ('type VERSION') do ( \
|
||||
echo #define SQLITE_RESOURCE_VERSION %%V \
|
||||
| $(NAWK) "/.*/ { gsub(/[.]/,\",\");print }" >> sqlite3rc.h \
|
||||
)
|
||||
echo #endif >> sqlite3rc.h
|
||||
$(LTRCOMPILE) -fo sqlite3res.lo $(TOP)\src\sqlite3.rc
|
||||
|
||||
# Rules to build individual *.lo files from files in the src directory.
|
||||
#
|
||||
alter.lo: $(TOP)\src\alter.c $(HDR)
|
||||
@@ -953,9 +1043,8 @@ tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
|
||||
tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR)
|
||||
$(LTCOMPILE) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
|
||||
|
||||
tclsqlite3.exe: tclsqlite-shell.lo libsqlite3.lib
|
||||
$(LTLINK) tclsqlite-shell.lo \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LTLIBS) $(TLIBS)
|
||||
tclsqlite3.exe: tclsqlite-shell.lo libsqlite3.lib sqlite3res.lo
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ libsqlite3.lib tclsqlite-shell.lo sqlite3res.lo $(LTLIBS) $(TLIBS)
|
||||
|
||||
# Rules to build opcodes.c and opcodes.h
|
||||
#
|
||||
@@ -1068,11 +1157,11 @@ TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
|
||||
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1)
|
||||
!ENDIF
|
||||
|
||||
testfixture.exe: $(TESTFIXTURE_SRC) $(HDR)
|
||||
testfixture.exe: $(TESTFIXTURE_SRC) sqlite3res.lo $(HDR)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
|
||||
-DBUILD_sqlite -I$(TCLINCDIR) \
|
||||
$(TESTFIXTURE_SRC) \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LTLIBS) $(TLIBS)
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) sqlite3res.lo $(LTLIBS) $(TLIBS)
|
||||
|
||||
fulltest: testfixture.exe sqlite3.exe
|
||||
.\testfixture.exe $(TOP)\test\all.test
|
||||
@@ -1090,13 +1179,15 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TO
|
||||
$(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@
|
||||
echo ; return zMainloop; } >> $@
|
||||
|
||||
sqlite3_analyzer.exe: sqlite3_analyzer.c
|
||||
sqlite3_analyzer.exe: sqlite3_analyzer.c sqlite3res.lo
|
||||
$(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LTLIBS) $(TLIBS)
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) sqlite3res.lo $(LTLIBS) $(TLIBS)
|
||||
|
||||
clean:
|
||||
del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
|
||||
del /Q *.da *.bb *.bbg gmon.out
|
||||
del /Q *.bu *.csv *.db *.db2 *.db-shm *.db-wal *.tcl *.txt *.x
|
||||
del /Q A BAR file http testdb
|
||||
del /Q sqlite3.h opcodes.c opcodes.h
|
||||
del /Q lemon.exe lempar.c parse.*
|
||||
del /Q mkkeywordhash.exe keywordhash.h
|
||||
@@ -1107,14 +1198,15 @@ clean:
|
||||
-rmdir /Q/S quota2c
|
||||
-rmdir /Q/S tsrc
|
||||
del /Q .target_source
|
||||
del /Q tclsqlite3.exe
|
||||
del /Q tclsqlite3.exe tclsqlite3.exp
|
||||
del /Q testfixture.exe testfixture.exp test.db
|
||||
del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
|
||||
del /Q sqlite3.c
|
||||
del /Q sqlite3rc.h
|
||||
del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c
|
||||
del /Q sqlite-output.vsix
|
||||
|
||||
#
|
||||
# Windows section
|
||||
# Dynamic link library section.
|
||||
#
|
||||
dll: sqlite3.dll
|
||||
|
||||
@@ -1124,5 +1216,5 @@ sqlite3.def: libsqlite3.lib
|
||||
| $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \
|
||||
| sort >> sqlite3.def
|
||||
|
||||
sqlite3.dll: $(LIBOBJ) sqlite3.def
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LTLIBS) $(TLIBS)
|
||||
sqlite3.dll: $(LIBOBJ) sqlite3res.lo sqlite3.def
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) sqlite3res.lo $(LTLIBS) $(TLIBS)
|
||||
|
||||
@@ -654,7 +654,9 @@ clean:
|
||||
rm -f *.o sqlite3$(EXE) libsqlite3.a sqlite3.h opcodes.*
|
||||
rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h
|
||||
rm -f $(PUBLISH)
|
||||
rm -f A BAR file http testdb
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -f *.bu *.csv *.db *.db2 *.db-shm *.db-wal *.tcl *.txt *.x
|
||||
rm -rf quota2a quota2b quota2c
|
||||
rm -rf tsrc target_source
|
||||
rm -f testloadext.dll libtestloadext.so
|
||||
|
||||
@@ -12778,14 +12778,16 @@ $as_echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.s
|
||||
fi
|
||||
|
||||
# Start autosearch by asking tclsh
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tcl installation
|
||||
|
||||
+10
-8
@@ -388,14 +388,16 @@ if test "${use_tcl}" = "yes" ; then
|
||||
fi
|
||||
|
||||
# Start autosearch by asking tclsh
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tcl installation
|
||||
|
||||
+1
-1
@@ -481,7 +481,7 @@ as follows:
|
||||
<li> If the precedences are the same and the shift token is
|
||||
right-associative, then resolve in favor of the shift.
|
||||
No parsing conflict is reported.
|
||||
<li> If the precedences are the same the the shift token is
|
||||
<li> If the precedences are the same the shift token is
|
||||
left-associative, then resolve in favor of the reduce.
|
||||
No parsing conflict is reported.
|
||||
<li> Otherwise, resolve the conflict by doing the shift and
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
*** Definition: Two databases (or the same database at two points it time)
|
||||
are said to be "logically equivalent" if they give the same answer to
|
||||
all queries. Note in particular the the content of freelist leaf
|
||||
all queries. Note in particular the content of freelist leaf
|
||||
pages can be changed arbitarily without effecting the logical equivalence
|
||||
of the database.
|
||||
|
||||
|
||||
+1
-1
@@ -5051,7 +5051,7 @@ static int leavesReaderAtEnd(LeavesReader *pReader){
|
||||
** modification to control flow all over the place, though, so for now
|
||||
** just punt.
|
||||
**
|
||||
** Note the the current system assumes that segment merges will run to
|
||||
** Note the current system assumes that segment merges will run to
|
||||
** completion, which is why this particular probably hasn't arisen in
|
||||
** this case. Probably a brittle assumption.
|
||||
*/
|
||||
|
||||
+6
-1
@@ -4436,6 +4436,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
|
||||
fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
|
||||
|
||||
/* Determine which, if any, tokens in the expression should be deferred. */
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
|
||||
Fts3TokenAndCost *aTC;
|
||||
Fts3Expr **apOr;
|
||||
@@ -4466,6 +4467,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
|
||||
sqlite3_free(aTC);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
|
||||
return rc;
|
||||
@@ -4849,6 +4851,7 @@ static int fts3EvalTestExpr(
|
||||
break;
|
||||
|
||||
default: {
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
if( pCsr->pDeferred
|
||||
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
|
||||
){
|
||||
@@ -4860,7 +4863,9 @@ static int fts3EvalTestExpr(
|
||||
*pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
|
||||
bHit = (pPhrase->doclist.pList!=0);
|
||||
pExpr->iDocid = pCsr->iPrevId;
|
||||
}else{
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
|
||||
}
|
||||
break;
|
||||
|
||||
+10
-2
@@ -427,10 +427,20 @@ int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
|
||||
int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
|
||||
int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
|
||||
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
|
||||
int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
|
||||
int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
|
||||
void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
|
||||
int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
|
||||
#else
|
||||
# define sqlite3Fts3FreeDeferredTokens(x)
|
||||
# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK
|
||||
# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK
|
||||
# define sqlite3Fts3FreeDeferredDoclists(x)
|
||||
# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK
|
||||
#endif
|
||||
|
||||
void sqlite3Fts3SegmentsClose(Fts3Table *);
|
||||
int sqlite3Fts3MaxLevel(Fts3Table *, int *);
|
||||
|
||||
@@ -539,8 +549,6 @@ int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
|
||||
int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
|
||||
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
|
||||
|
||||
int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
|
||||
|
||||
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
|
||||
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
|
||||
int sqlite3FtsUnicodeFold(int, int);
|
||||
|
||||
@@ -2969,7 +2969,7 @@ static int fts3SegmentMerge(
|
||||
|
||||
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 the numerically
|
||||
** segment. The level of the new segment is equal to the numerically
|
||||
** greatest segment level currently present in the database for this
|
||||
** index. The idx of the new segment is always 0. */
|
||||
if( csr.nSegment==1 ){
|
||||
@@ -3599,7 +3599,7 @@ static int fts3IncrmergePush(
|
||||
pNode->key.n = nTerm;
|
||||
}
|
||||
}else{
|
||||
/* Otherwise, flush the the current node of layer iLayer to disk.
|
||||
/* Otherwise, flush the current node of layer iLayer to disk.
|
||||
** Then allocate a new, empty sibling node. The key will be written
|
||||
** into the parent of this node. */
|
||||
rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
|
||||
@@ -5046,6 +5046,7 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
/*
|
||||
** Delete all cached deferred doclists. Deferred doclists are cached
|
||||
** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
|
||||
@@ -5183,6 +5184,7 @@ int sqlite3Fts3DeferToken(
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** SQLite value pRowid contains the rowid of a row that may or may not be
|
||||
|
||||
@@ -606,7 +606,9 @@ clean:
|
||||
rm -f lemon lemon.exe lempar.c parse.* sqlite*.tar.gz
|
||||
rm -f mkkeywordhash mkkeywordhash.exe keywordhash.h
|
||||
rm -f $(PUBLISH)
|
||||
rm -f A BAR file http testdb
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -f *.bu *.csv *.db *.db2 *.db-shm *.db-wal *.tcl *.txt *.x
|
||||
rm -rf quota2a quota2b quota2c
|
||||
rm -rf tsrc target_source
|
||||
rm -f testloadext.dll libtestloadext.so
|
||||
@@ -616,3 +618,4 @@ clean:
|
||||
rm -f threadtest3 threadtest3.exe
|
||||
rm -f sqlite3.c fts?amal.c tclsqlite3.c
|
||||
rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
|
||||
rm -f sqlite-output.vsix
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
C Further\stweaks\sto\smalloc\spaths.
|
||||
D 2012-07-19T20:27:14.139
|
||||
C More\stest\scleanup.
|
||||
D 2012-09-10T07:56:40.252
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 8f6d858bf3df9978ba43df19985146a1173025e4
|
||||
F Makefile.in b67da1d811b508b85f0822291e20ca4190d0c1b0
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 56ff0fcc3fc3b275aec7f6acb34b3c0526c684bc
|
||||
F Makefile.vxworks 879f034a64062a364b21000266bbd5bc6e0c19b9
|
||||
F Makefile.msc 4929f86ceb76f8093e9af3a9dfd4d372b6471b25
|
||||
F Makefile.vxworks 0f4fc75a6787e4130e597ec141af76077876ebef
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
F VERSION a71848df48082f1d6585d4b0819d530fc455485d
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -15,11 +15,11 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 8f973617dbc3fca46d26104070b75c17ef70beb7 x
|
||||
F configure.ac 9ee886c21c095b3272137b1553ae416c8b8c8557
|
||||
F configure e2d0e3b67d2b1b1049d389fd671275d79bb80457 x
|
||||
F configure.ac 6e909664785b8184db2179013cd9d574f96ca3a3
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 3091574143dd3415669b6745843ff8d011d33549
|
||||
F doc/pager-invariants.txt 870107036470d7c419e93768676fae2f8749cf9e
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1
|
||||
F ext/async/README.txt 0c541f418b14b415212264cbaaf51c924ec62e5b
|
||||
@@ -41,7 +41,7 @@ F ext/fts1/simple_tokenizer.c 1844d72f7194c3fd3d7e4173053911bf0661b70d
|
||||
F ext/fts1/tokenizer.h 0c53421b832366d20d720d21ea3e1f6e66a36ef9
|
||||
F ext/fts2/README.tokenizers 21e3684ea5a095b55d70f6878b4ce6af5932dfb7
|
||||
F ext/fts2/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts2/fts2.c 238e9e19158ef75fb4155613a870443394fbf7da
|
||||
F ext/fts2/fts2.c 4ef7d7ecf590da0dd416ac54612c53a7d4175790
|
||||
F ext/fts2/fts2.h da5f76c65163301d1068a971fd32f4119e3c95fa
|
||||
F ext/fts2/fts2_hash.c 2689e42e1107ea67207f725cf69cf8972d00cf93
|
||||
F ext/fts2/fts2_hash.h 9a5b1be94664139f93217a0770d7144425cffb3a
|
||||
@@ -55,9 +55,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c bb3107c0e420ea2e26e57050e84cdf0aeaafcd4f
|
||||
F ext/fts3/fts3.c ab90126ee0163539d21d0618d22afa2eb645f7e2
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 81115435f79248ac09017bc665aae27b410d651f
|
||||
F ext/fts3/fts3Int.h 1e58825246b56259267382d2f9902774c049460a
|
||||
F ext/fts3/fts3_aux.c 5205182bd8f372782597888156404766edf5781e
|
||||
F ext/fts3/fts3_expr.c dbc7ba4c3a6061adde0f38ed8e9b349568299551
|
||||
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
|
||||
@@ -72,7 +72,7 @@ F ext/fts3/fts3_tokenizer.h 66dec98e365854b6cd2d54f1a96bb6d428fc5a68
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c 49e36e6ba59f79e6bd6a8bfe434570fe48d20559
|
||||
F ext/fts3/fts3_unicode2.c a863f05f758af36777dffc2facc898bc73fec896
|
||||
F ext/fts3/fts3_write.c 794438f904cdf4516b258e530c0065efadb7b9b5
|
||||
F ext/fts3/fts3_write.c c30c49f3debb9497a07f15cc4c042815e35474ef
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
|
||||
@@ -103,7 +103,7 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F main.mk d109a9342d1fe135d3900aca9f5563f9480a991d
|
||||
F main.mk db1d6b13684677899b99cbca957ff23456e9e28e
|
||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
|
||||
@@ -117,38 +117,38 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c 149cc80d9257971b0bff34e58fb2263e01998289
|
||||
F src/analyze.c 1f05d25f1fb11ba60f95b793e0922757f35355fd
|
||||
F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410
|
||||
F src/attach.c 577bf5675b0c50495fc28549f2fcbdb1bac71143
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 5524df36810668b3b5a6de2d7e3910b98e721e33
|
||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||
F src/backup.c 5b31b24d6814b11de763debf342c8cd0a15a4910
|
||||
F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c f0b71054103cb77eb5e782088c16998ec4f06624
|
||||
F src/btree.h 48a013f8964f12d944d90e4700df47b72dd6d923
|
||||
F src/btreeInt.h 38a639c0542c29fe8331a221c4aed0cb8686249e
|
||||
F src/build.c 4357149e38f95d8034f58ee2c7013423321fa877
|
||||
F src/btree.c 9cf6de113d23d47967df24b8d8ce6501c879d7e6
|
||||
F src/btree.h 4aee02e879211bfcfd3f551769578d2e940ab6c2
|
||||
F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621
|
||||
F src/build.c a3b700afd475e6387da59be6f2e86161e80d6d87
|
||||
F src/callback.c 0cb4228cdcd827dcc5def98fb099edcc9142dbcd
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 500d019da966631ad957c37705642be87524463b
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 4c20ea4f6213b3bc1c6a510586864b679946e05e
|
||||
F src/expr.c 06a7733d19dc725dc46ba51afd9feadb4b85d991
|
||||
F src/delete.c 335f36750dc6ac88d580aa36a6487459be9889de
|
||||
F src/expr.c 217840a107dcc1e5dbb57cea311daad04bedbb9a
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 7d1ec22d7278486c7fe42da43cabfc2a5ed33647
|
||||
F src/fkey.c 9c77d842dc9961d92a06a65abb80c64ef1750296
|
||||
F src/func.c 18dfedfb857e100b05755a1b12e88b389f957879
|
||||
F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b
|
||||
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
|
||||
F src/hash.c a4031441741932da9e7a65bee2b36b5d0e81c073
|
||||
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 0bbffe75c254c62a5686ab5e7f88e29235e16174
|
||||
F src/insert.c b090d0a9fb9ff2dbdeaf66aedccf98cd13b1af60
|
||||
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
|
||||
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
||||
F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
|
||||
F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
|
||||
F src/main.c 6241183d894ff51a2049bd6bf246aea877d648b5
|
||||
F src/malloc.c 57121e3ef46431b95a73651f9b5653f96867e358
|
||||
F src/main.c 02255cf1da50956c5427c469abddb15bccc4ba09
|
||||
F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 7ed7d5cd9a6ec97cc881ea80d996f6a16e8b7426
|
||||
F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa
|
||||
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
|
||||
@@ -160,35 +160,36 @@ F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
|
||||
F src/mutex_w32.c 32a9b3841e2d757355f0012b860b1bc5e01eafa0
|
||||
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c
|
||||
F src/os.h c2ebd26a68a4223fe170b003852b97d9e7211498
|
||||
F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_unix.c d7c96b5d140f550f07345870112fae5d7ef99757
|
||||
F src/os_win.c e3d3d3e26b65a35d4293d753137a58510bd3299b
|
||||
F src/pager.c e381c118b77dc22021a1a59d3fec24815e91df78
|
||||
F src/os_unix.c 69b2fe66316524eebf5f1ce85c1fdfe2952307e9
|
||||
F src/os_win.c 5dec8fe85ee547152075c020db72aec4382f0d0a
|
||||
F src/pager.c 5665fa9ecec51f11dabdfd8eefefa89391856007
|
||||
F src/pager.h 8b8c9bc065a3c66769df8724dfdf492ee1aab3c5
|
||||
F src/parse.y 6548920e5a3ee92c6efc7007e30b03105850ca4c
|
||||
F src/parse.y f29df90bd3adc64b33114ab1de9fb7768fcf2099
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
|
||||
F src/pcache1.c 2234d84f9c003d800a57f00f8535c91667fa4f6c
|
||||
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
|
||||
F src/pragma.c 97f9357f0e7e5fb46a2519f14539550aa07db49f
|
||||
F src/prepare.c 33291b83cca285718048d219c67b8298501fa3a5
|
||||
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c b3c70ab28cac60de33684c9aa9e5138dcf71d6dd
|
||||
F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1
|
||||
F src/select.c 5c9f09de4ca3e12da17d1c5215b851ce3356891c
|
||||
F src/shell.c 076e1c90d594644f36027c8ecff9a392cf2d3a06
|
||||
F src/sqlite.h.in c660e2c8c5b5412d1ce51d58807353fa1dfdbee0
|
||||
F src/resolve.c 9e28280ec98035f31900fdd1db01f86f68ca6c32
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c f843c872a97baa1594c2cc3d4c003409a7bd03af
|
||||
F src/shell.c 87953c5d9c73d9494db97d1607e2e2280418f261
|
||||
F src/sqlite.h.in 39ddd714b62c651bfb5646440c594ca7ff6c7453
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h 42082771dfad5ccc5b46ad97bddfe2829a61eaef
|
||||
F src/sqliteInt.h 053e03a532beb909ead2df0721db67cdb4c48ae8
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c fe5406573e1527957e00dcaf51edd9d8bd31b918
|
||||
F src/test1.c fc2acf0a2db517c8d19e5e55bda8e1237db77378
|
||||
F src/tclsqlite.c 192dd01625381fb0614bc35f686de5b9d5fbe2bf
|
||||
F src/test1.c 3d70f7c5987f186884cfebbfa7151a7d3d67d86e
|
||||
F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
|
||||
F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
|
||||
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
|
||||
F src/test4.c bf9fa9bece01de08e6f5e02314e4af5c13590dfa
|
||||
F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013
|
||||
F src/test6.c 417e1e214734393c24a8ee80b41485a9c4169123
|
||||
F src/test7.c 2e0781754905c8adc3268d8f0967e7633af58843
|
||||
@@ -198,7 +199,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
|
||||
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
|
||||
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
|
||||
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
|
||||
F src/test_config.c 9b37587750f247186ebeb02a02e8f17c611d1866
|
||||
F src/test_config.c 09781397ccc24268cb895be0d4c21b4aad651486
|
||||
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_func.c 3a8dd37c08ab43b76d38eea2836e34a3897bf170
|
||||
@@ -210,7 +211,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
|
||||
F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64
|
||||
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
|
||||
F src/test_malloc.c 3f5903a1528fd32fe4c472a3bd0259128d8faaef
|
||||
F src/test_multiplex.c 66dcfca001ee22f04ef31ad353772ed05a017e53
|
||||
F src/test_multiplex.c ac0fbc1748e5b86a41a1d7a84654fae0d53a881d
|
||||
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
|
||||
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
|
||||
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
|
||||
@@ -221,38 +222,39 @@ F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
|
||||
F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9
|
||||
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
||||
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
|
||||
F src/test_spellfix.c 5ed989693d4040f4d343316c338e25c5a6a1f05d
|
||||
F src/test_spellfix.c 76dd8d3111d2f5354c374f71fa23b752bd0b029c
|
||||
F src/test_stat.c d1569c7a4839f13e80187e2c26b2ab4da2d03935
|
||||
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||
F src/test_syscall.c a992d8c80ea91fbf21fb2dd570db40e77dd7e6ae
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c e286f2173563f2a1747c24bcda6b9d030bf4f4e4
|
||||
F src/test_vfs.c da6d0d982b11756c94c1760196355d33d03ff745
|
||||
F src/test_vfstrace.c 6b28adb2a0e8ecd0f2e3581482e1f658b11b4067
|
||||
F src/test_vfs.c c6260ef238c1142c8f8bd402db02216afd182ae3
|
||||
F src/test_vfstrace.c f60e12754e65c05386aab59db8d2ae086314138d
|
||||
F src/test_wholenumber.c 3d2b9ed1505c40ad5c5ca2ad16ae7a289d6cc251
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c a054f58de63c2d7f5ba69439ef7fc75e7f22c158
|
||||
F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684
|
||||
F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
|
||||
F src/tokenize.c 1e86210d3976717a19238ea7b047fac481fe8c12
|
||||
F src/trigger.c 3f258307040173aff383eb23fb74c44fe829078c
|
||||
F src/update.c 28d2d098b43a2c70dae399896ea8a02f622410ef
|
||||
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
|
||||
F src/util.c 0af2e515dc0dabacec931bca39525f6c3f1c5455
|
||||
F src/vacuum.c 587a52bb8833d7ac15af8916f25437e2575028bd
|
||||
F src/vdbe.c f5ad3c06dc3fe647097065829c013f3f1b9eadca
|
||||
F src/vdbe.c 64de1142b9f3a84f500a6ce964175c828f1e41da
|
||||
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
|
||||
F src/vdbeInt.h 6ff4180a05683566a8835d12f7ec504b22932c82
|
||||
F src/vdbeapi.c 88ea823bbcb4320f5a6607f39cd7c2d3cc4c26b1
|
||||
F src/vdbeaux.c dce80038c3c41f2680e5ab4dd0f7e0d8b7ff9071
|
||||
F src/vdbeInt.h a668b303644377433e31a18d3d9efb87eefb6332
|
||||
F src/vdbeapi.c 4c2418161cf45392ba76a7ca92f9a5f06b96f89c
|
||||
F src/vdbeaux.c 9c293fd3040211687e83d5d27bef2382933146c2
|
||||
F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
|
||||
F src/vdbemem.c cb55e84b8e2c15704968ee05f0fae25883299b74
|
||||
F src/vdbesort.c b25814d385895544ebc8118245c8311ded7f81c9
|
||||
F src/vdbetrace.c 79059ebd17b3c8545fab2a24253713e77e4ab392
|
||||
F src/vtab.c bb8ea3a26608bb1357538a5d2fc72beba6638998
|
||||
F src/wal.c 9294df6f96aae5909ae1a9b733fd1e1b4736978b
|
||||
F src/vdbesort.c 0dc1b274dcb4d4c8e71b0b2b15261f286caba39b
|
||||
F src/vdbetrace.c 8bd5da325fc90f28464335e4cc4ad1407fe30835
|
||||
F src/vtab.c d2c54fd22aa83eb34fc6f7cd9b097f2fc2b1e9de
|
||||
F src/wal.c 5acb3e7bbd31f10ba39acad9ce6b399055337a9d
|
||||
F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 24c7494d8875ead994b4dfe5461340c27fd424ca
|
||||
F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
|
||||
F src/where.c 22783f4275f6fc09b663115a6091837cb5c510e0
|
||||
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 0be144b453e0622a085fae8665c32f5676708e00
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 52fc8dee494092031a556911d404ca30a749a30b
|
||||
F test/alter.test 57d96ec9b320bd07af77567034488dcb6642c748
|
||||
@@ -350,7 +352,7 @@ F test/corruptD.test 99b1999dbfa7cc04aaeac9d695a2445d4e7c7458
|
||||
F test/corruptE.test 1b9eb20a8711251ce57b44a257e241085b39b52d
|
||||
F test/corruptF.test 984b1706c9c0e4248141b056c21124612628d12e
|
||||
F test/count.test 454e1ce985c94d13efeac405ce54439f49336163
|
||||
F test/crash.test 519dc29f6fea151f015a23236e555239353946eb
|
||||
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
|
||||
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
|
||||
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
|
||||
F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
|
||||
@@ -464,7 +466,7 @@ F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
|
||||
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
|
||||
F test/fts3ao.test e7b80272efcced57d1d087a9da5c690dd7c21fd9
|
||||
F test/fts3atoken.test fb398ab50aa232489e2a17f9b29d7ad3a3885f36
|
||||
F test/fts3auto.test b39f3f51227aea145eae6638690355dbdf9abf18
|
||||
F test/fts3auto.test 74315a7377403a57ba82a652a33704197fe1e4be
|
||||
F test/fts3aux1.test 0b02743955d56fc0d4d66236a26177bd1b726de0
|
||||
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
@@ -474,8 +476,8 @@ F test/fts3corrupt.test 7b0f91780ca36118d73324ec803187208ad33b32
|
||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||
F test/fts3d.test bf640d79722b720fa1c81834c48cdaa45d531b1a
|
||||
F test/fts3defer.test 6c2707be1b05b9790ba8ff91d3391d5fb425269e
|
||||
F test/fts3defer2.test 35867d33ba6db03f6c73bd6f5fc333ae14f68c81
|
||||
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
|
||||
F test/fts3defer2.test 83f8744407b7663e36716a9066302d53d49ddf8b
|
||||
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
|
||||
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
||||
F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
|
||||
@@ -484,7 +486,7 @@ F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
|
||||
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3malloc.test b86ea33db9e8c58c0c2f8027a9fcadaf6a1568be
|
||||
F test/fts3matchinfo.test 6507fe1c342e542300d65ea637d4110eccf894e6
|
||||
F test/fts3matchinfo.test 15edde2c4d373d60449658176af7164d622a62f0
|
||||
F test/fts3near.test 2e318ee434d32babd27c167142e2b94ddbab4844
|
||||
F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
|
||||
F test/fts3prefix2.test 477ca96e67f60745b7ac931cfa6e9b080c562da5
|
||||
@@ -493,7 +495,7 @@ F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 8bb266521d7c5495c0ae522bb4d376ad5387d4a2
|
||||
F test/fts3snippet.test 8e956051221a34c7daeb504f023cb54d5fa5a8b2
|
||||
F test/fts3sort.test 95be0b19d7e41c44b29014f13ea8bddd495fd659
|
||||
F test/fts4aa.test 6e7f90420b837b2c685f3bcbe84c868492d40a68
|
||||
F test/fts4aa.test 95f448fb02c4a976968b08d1b4ce134e720946ae
|
||||
F test/fts4check.test 66fa274cab2b615f2fb338b257713aba8fad88a8
|
||||
F test/fts4content.test 17b2360f7d1a9a7e5aa8022783f5c5731b6dfd4f
|
||||
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
|
||||
@@ -531,6 +533,7 @@ F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097
|
||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||
F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
|
||||
F test/index4.test 2983216eb8c86ee62d9ed7cb206b5cc3331c0026
|
||||
F test/index5.test edc8c64ca78bee140c21ce3836820fadf47906bb
|
||||
F test/indexedby.test be501e381b82b2f8ab406309ba7aac46e221f4ad
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
@@ -554,7 +557,7 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe
|
||||
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
|
||||
F test/journal1.test 8b71ef1ed5798bdc0e6eb616d8694e2c2c188d4d
|
||||
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
|
||||
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
|
||||
F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
|
||||
F test/jrnlmode.test 9ee3a78f53d52cca737db69293d15dc41c0cbd36
|
||||
@@ -641,7 +644,7 @@ F test/pageropt.test 9191867ed19a2b3db6c42d1b36b6fbc657cd1ab0
|
||||
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
|
||||
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/permutations.test 2af90e00cea9e7e7c0a6b16d34727cb5bbae14dd
|
||||
F test/permutations.test 1a8ac849b659445a0b3883caf42fa2c2a289f4a1
|
||||
F test/pragma.test a62f73293b0f0d79b0c87f8dd32d46fe53b0bd17
|
||||
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
@@ -657,10 +660,10 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rdonly.test c267d050a1d9a6a321de502b737daf28821a518d
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
|
||||
F test/releasetest.tcl 4014e2bfb93f276d82a604e7a5eda62c129916c9
|
||||
F test/releasetest.tcl e48fd8e0e8abad89f30e08620790533ae4e02010
|
||||
F test/rollback.test a1b4784b864331eae8b2a98c189efa2a8b11ff07
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test e58e0acef38b527ed1b0b70d3ada588f804af287
|
||||
F test/rowid.test f777404492adb0e00868fd706a3721328fd3af48
|
||||
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
|
||||
F test/savepoint.test f5acd87d0c7a5f4ad6c547b47fd18c0e1aeaf048
|
||||
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
|
||||
@@ -675,12 +678,13 @@ F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
|
||||
F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
|
||||
F test/schema5.test 0103e4c0313b3725b5ae5600bdca53006ab53db3
|
||||
F test/securedel.test 87a2561151af1f1e349071a89fdd77059f50113c
|
||||
F test/securedel2.test f13a916155f790a6b9de835049641b14ef312986
|
||||
F test/select1.test deba017eed9daa5af33de868676c997e7eebb931
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test 00179be44e531fe04c1c3f15df216439dff2519d
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test cc25a8650cf9a4d4f74e586c45a75f9836516b18
|
||||
F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2
|
||||
F test/select7.test dad6f00f0d49728a879d6eb6451d4752db0b0abe
|
||||
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
|
||||
F test/select9.test c0ca3cd87a8ebb04de2cb1402c77df55d911a0ea
|
||||
@@ -716,7 +720,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/spellfix.test 936be6f7ba1c4d096adb280c68b32f4848af8d2e
|
||||
F test/spellfix.test 2953e9da0e46dab5f83059ef6bfdebca66e13418
|
||||
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
|
||||
F test/stat.test 08e8185b3fd5b010c90d7ad82b9dd4ea1cbf14b0
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
@@ -926,7 +930,7 @@ F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test 82f463886e18d7f8395a4b6167c91815efe54839
|
||||
F test/wal.test a040047d7f2b9f34bc4d597964e5e7c09609c635
|
||||
F test/wal2.test 7ca814723c487de87d945cdc85c9a0fa45fa8de8
|
||||
F test/wal2.test d4b470f13c87f6d8268b004380afa04c3c67cb90
|
||||
F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test f58ed4b8b542f71c7441da12fbd769d99b362437
|
||||
@@ -945,10 +949,10 @@ F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
|
||||
F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
|
||||
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
|
||||
F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
|
||||
F test/walro.test f183c0003060a64793f9bfafef4c479418ed7fa8
|
||||
F test/walro.test a31deb621033442a76c3a61e44929250d06f81b1
|
||||
F test/walshared.test 6dda2293880c300baf5d791c307f653094585761
|
||||
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
|
||||
F test/walthread.test a2ed5270eb695284d4ad27d252517bdc3317ee2a
|
||||
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
|
||||
F test/where.test 4c9f69987ed2aa0173fa930f2b41ab9879478cd8
|
||||
F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554
|
||||
F test/where3.test 667e75642102c97a00bf9b23d3cb267db321d006
|
||||
@@ -962,18 +966,21 @@ F test/where9.test ae98dc22ef9b6f2bc81e9f164e41b38faa9bda06
|
||||
F test/whereA.test 24c234263c8fe358f079d5e57d884fb569d2da0a
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test 13ff5ec0dba407c0e0c075980c75b3275a6774e5
|
||||
F test/whereD.test 304ccbe3c77e0d0764f37c91d43b8c4792a5e02f
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/win32lock.test b2a539e85ae6b2d78475e016a9636b4451dc7fb9
|
||||
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
|
||||
F test/zerodamage.test 0de750389990b1078bab203c712dc3fefd1d8b82
|
||||
F tool/build-all-msvc.bat 1a18aa39983ae7354d834bc55a850a54fc007576 x
|
||||
F tool/build-shell.sh b64a481901fc9ffe5ca8812a2a9255b6cfb77381
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
|
||||
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
|
||||
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c 8b7afc12a6671e3a932a5209a9e64abbfbd0f025
|
||||
F tool/lemon.c 680980c7935bfa1edec20c804c9e5ba4b1dd96f5
|
||||
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
@@ -982,6 +989,7 @@ F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02
|
||||
F tool/mksqlite3c.tcl 589c7f44e990be1b8443cfe4808dce392b0327fa
|
||||
F tool/mksqlite3h.tcl 78013ad79a5e492e5f764f3c7a8ef834255061f8
|
||||
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
|
||||
F tool/mkvsix.tcl 19b2ab9ea16445953a76568a5bbe4cb864f92dfe
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
@@ -1005,7 +1013,11 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
P defd828e90a5494e58cc2cd14c8f4cce7fd2bb2b
|
||||
R 62a7b8739dbc0504b7043c6629065afd
|
||||
U dan
|
||||
Z f8c7a516451a2fad10c61fa887e0e873
|
||||
F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
|
||||
P f260d7d567a1239c483c437d0b18a95bd0c96724
|
||||
R fcdf0eae4bfdcb06fae02ebef2eaea5c
|
||||
T *branch * testClean
|
||||
T *sym-testClean *
|
||||
T -sym-trunk *
|
||||
U mistachkin
|
||||
Z 27d85d2d177181498586eb7b98a0820b
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
0a33444105e29d79475e267021d33c1a006b85a3
|
||||
b8d5359bb7be9cf725049ee0ae783521bf11b2c9
|
||||
+6
-7
@@ -176,7 +176,7 @@ static void openStatTable(
|
||||
"CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
|
||||
);
|
||||
aRoot[i] = pParse->regRoot;
|
||||
aCreateTbl[i] = 1;
|
||||
aCreateTbl[i] = OPFLAG_P2ISREG;
|
||||
}else{
|
||||
/* The table already exists. If zWhere is not NULL, delete all entries
|
||||
** associated with the table zWhere. If zWhere is NULL, delete the
|
||||
@@ -256,12 +256,11 @@ static void stat3Init(
|
||||
nRow = (tRowcnt)sqlite3_value_int64(argv[0]);
|
||||
mxSample = sqlite3_value_int(argv[1]);
|
||||
n = sizeof(*p) + sizeof(p->a[0])*mxSample;
|
||||
p = sqlite3_malloc( n );
|
||||
p = sqlite3MallocZero( n );
|
||||
if( p==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
memset(p, 0, n);
|
||||
p->a = (struct Stat3Sample*)&p[1];
|
||||
p->nRow = nRow;
|
||||
p->mxSample = mxSample;
|
||||
@@ -932,7 +931,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){
|
||||
int eType; /* Datatype of a sample */
|
||||
IndexSample *pSample; /* A slot in pIdx->aSample[] */
|
||||
|
||||
assert( db->lookaside.sz==0 );
|
||||
assert( db->lookaside.bEnabled==0 );
|
||||
if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -1108,10 +1107,10 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
||||
/* Load the statistics from the sqlite_stat3 table. */
|
||||
#ifdef SQLITE_ENABLE_STAT3
|
||||
if( rc==SQLITE_OK ){
|
||||
int lookasideSz = db->lookaside.sz;
|
||||
db->lookaside.sz = 0;
|
||||
int lookasideEnabled = db->lookaside.bEnabled;
|
||||
db->lookaside.bEnabled = 0;
|
||||
rc = loadStat3(db, sInfo.zDatabase);
|
||||
db->lookaside.sz = lookasideSz;
|
||||
db->lookaside.bEnabled = lookasideEnabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+1
-2
@@ -164,7 +164,7 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
|
||||
** call to sqlite3_backup_init() and is destroyed by a call to
|
||||
** sqlite3_backup_finish(). */
|
||||
p = (sqlite3_backup *)sqlite3_malloc(sizeof(sqlite3_backup));
|
||||
p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
|
||||
if( !p ){
|
||||
sqlite3Error(pDestDb, SQLITE_NOMEM, 0);
|
||||
}
|
||||
@@ -172,7 +172,6 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
|
||||
/* If the allocation succeeded, populate the new object. */
|
||||
if( p ){
|
||||
memset(p, 0, sizeof(sqlite3_backup));
|
||||
p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
|
||||
p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
|
||||
p->pDestDb = pDestDb;
|
||||
|
||||
+1
-2
@@ -340,10 +340,9 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
|
||||
/* Allocate the Bitvec to be tested and a linear array of
|
||||
** bits to act as the reference */
|
||||
pBitvec = sqlite3BitvecCreate( sz );
|
||||
pV = sqlite3_malloc( (sz+7)/8 + 1 );
|
||||
pV = sqlite3MallocZero( (sz+7)/8 + 1 );
|
||||
pTmpSpace = sqlite3_malloc(BITVEC_SZ);
|
||||
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
|
||||
memset(pV, 0, (sz+7)/8 + 1);
|
||||
|
||||
/* NULL pBitvec tests */
|
||||
sqlite3BitvecSet(0, 1);
|
||||
|
||||
+25
-11
@@ -1461,7 +1461,7 @@ static int btreeInitPage(MemPage *pPage){
|
||||
size = get2byte(&data[pc+2]);
|
||||
if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
|
||||
/* Free blocks must be in ascending order. And the last byte of
|
||||
** the free-block must lie on the database page. */
|
||||
** the free-block must lie on the database page. */
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
nFree = nFree + size;
|
||||
@@ -2635,7 +2635,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
|
||||
pBt->nTransaction++;
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
if( p->sharable ){
|
||||
assert( p->lock.pBtree==p && p->lock.iTable==1 );
|
||||
assert( p->lock.pBtree==p && p->lock.iTable==1 );
|
||||
p->lock.eLock = READ_LOCK;
|
||||
p->lock.pNext = pBt->pLock;
|
||||
pBt->pLock = &p->lock;
|
||||
@@ -5926,7 +5926,8 @@ static int balance_nonroot(
|
||||
MemPage *pParent, /* Parent page of siblings being balanced */
|
||||
int iParentIdx, /* Index of "the page" in pParent */
|
||||
u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */
|
||||
int isRoot /* True if pParent is a root-page */
|
||||
int isRoot, /* True if pParent is a root-page */
|
||||
int bBulk /* True if this call is part of a bulk load */
|
||||
){
|
||||
BtShared *pBt; /* The whole database */
|
||||
int nCell = 0; /* Number of cells in apCell[] */
|
||||
@@ -5990,18 +5991,19 @@ static int balance_nonroot(
|
||||
i = pParent->nOverflow + pParent->nCell;
|
||||
if( i<2 ){
|
||||
nxDiv = 0;
|
||||
nOld = i+1;
|
||||
}else{
|
||||
nOld = 3;
|
||||
assert( bBulk==0 || bBulk==1 );
|
||||
if( iParentIdx==0 ){
|
||||
nxDiv = 0;
|
||||
}else if( iParentIdx==i ){
|
||||
nxDiv = i-2;
|
||||
nxDiv = i-2+bBulk;
|
||||
}else{
|
||||
assert( bBulk==0 );
|
||||
nxDiv = iParentIdx-1;
|
||||
}
|
||||
i = 2;
|
||||
i = 2-bBulk;
|
||||
}
|
||||
nOld = i+1;
|
||||
if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
|
||||
pRight = &pParent->aData[pParent->hdrOffset+8];
|
||||
}else{
|
||||
@@ -6081,7 +6083,7 @@ static int balance_nonroot(
|
||||
/*
|
||||
** Load pointers to all cells on sibling pages and the divider cells
|
||||
** into the local apCell[] array. Make copies of the divider cells
|
||||
** into space obtained from aSpace1[] and remove the the divider Cells
|
||||
** into space obtained from aSpace1[] and remove the divider cells
|
||||
** from pParent.
|
||||
**
|
||||
** If the siblings are on leaf pages, then the child pointers of the
|
||||
@@ -6210,7 +6212,9 @@ static int balance_nonroot(
|
||||
d = r + 1 - leafData;
|
||||
assert( d<nMaxCells );
|
||||
assert( r<nMaxCells );
|
||||
while( szRight==0 || szRight+szCell[d]+2<=szLeft-(szCell[r]+2) ){
|
||||
while( szRight==0
|
||||
|| (!bBulk && szRight+szCell[d]+2<=szLeft-(szCell[r]+2))
|
||||
){
|
||||
szRight += szCell[d] + 2;
|
||||
szLeft -= szCell[r] + 2;
|
||||
cntNew[i-1]--;
|
||||
@@ -6257,7 +6261,7 @@ static int balance_nonroot(
|
||||
if( rc ) goto balance_cleanup;
|
||||
}else{
|
||||
assert( i>0 );
|
||||
rc = allocateBtreePage(pBt, &pNew, &pgno, pgno, 0);
|
||||
rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
|
||||
if( rc ) goto balance_cleanup;
|
||||
apNew[i] = pNew;
|
||||
nNew++;
|
||||
@@ -6469,6 +6473,7 @@ static int balance_nonroot(
|
||||
** sibling page j. If the siblings are not leaf pages of an
|
||||
** intkey b-tree, then cell i was a divider cell. */
|
||||
assert( j+1 < ArraySize(apCopy) );
|
||||
assert( j+1 < nOld );
|
||||
pOld = apCopy[++j];
|
||||
iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow;
|
||||
if( pOld->nOverflow ){
|
||||
@@ -6707,7 +6712,7 @@ static int balance(BtCursor *pCur){
|
||||
** pSpace buffer passed to the latter call to balance_nonroot().
|
||||
*/
|
||||
u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
|
||||
rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1);
|
||||
rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints);
|
||||
if( pFree ){
|
||||
/* If pFree is not NULL, it points to the pSpace buffer used
|
||||
** by a previous call to balance_nonroot(). Its contents are
|
||||
@@ -8294,3 +8299,12 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
|
||||
pBt->btsFlags &= ~BTS_NO_WAL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** set the mask of hint flags for cursor pCsr. Currently the only valid
|
||||
** values are 0 and BTREE_BULKLOAD.
|
||||
*/
|
||||
void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
|
||||
assert( mask==BTREE_BULKLOAD || mask==0 );
|
||||
pCsr->hints = mask;
|
||||
}
|
||||
|
||||
+7
-1
@@ -135,6 +135,12 @@ int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
||||
#define BTREE_USER_VERSION 6
|
||||
#define BTREE_INCR_VACUUM 7
|
||||
|
||||
/*
|
||||
** Values that may be OR'd together to form the second argument of an
|
||||
** sqlite3BtreeCursorHints() call.
|
||||
*/
|
||||
#define BTREE_BULKLOAD 0x00000001
|
||||
|
||||
int sqlite3BtreeCursor(
|
||||
Btree*, /* BTree containing table to open */
|
||||
int iTable, /* Index of root page */
|
||||
@@ -178,8 +184,8 @@ struct Pager *sqlite3BtreePager(Btree*);
|
||||
int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
|
||||
void sqlite3BtreeCacheOverflow(BtCursor *);
|
||||
void sqlite3BtreeClearCursor(BtCursor *);
|
||||
|
||||
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
|
||||
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
|
||||
|
||||
#ifndef NDEBUG
|
||||
int sqlite3BtreeCursorIsValid(BtCursor*);
|
||||
|
||||
@@ -510,6 +510,7 @@ struct BtCursor {
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
|
||||
#endif
|
||||
u8 hints; /* As configured by CursorSetHints() */
|
||||
i16 iPage; /* Index of current page in apPage */
|
||||
u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
|
||||
MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
|
||||
|
||||
+7
-9
@@ -534,7 +534,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
|
||||
if( !db || db->pnBytesFreed==0 ){
|
||||
char *zName = pIndex->zName;
|
||||
TESTONLY ( Index *pOld = ) sqlite3HashInsert(
|
||||
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
|
||||
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
|
||||
);
|
||||
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
|
||||
assert( pOld==pIndex || pOld==0 );
|
||||
@@ -1581,7 +1581,7 @@ void sqlite3EndTable(
|
||||
|
||||
assert(pParse->nTab==1);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
|
||||
sqlite3VdbeChangeP5(v, 1);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
|
||||
pParse->nTab = 2;
|
||||
sqlite3SelectDestInit(&dest, SRT_Table, 1);
|
||||
sqlite3Select(pParse, pSelect, &dest);
|
||||
@@ -1816,11 +1816,11 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
assert( pTable->pSelect );
|
||||
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
|
||||
if( pSel ){
|
||||
u16 lookasideSz = db->lookaside.sz;
|
||||
u8 enableLookaside = db->lookaside.bEnabled;
|
||||
n = pParse->nTab;
|
||||
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
|
||||
pTable->nCol = -1;
|
||||
db->lookaside.sz = 0;
|
||||
db->lookaside.bEnabled = 0;
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
xAuth = db->xAuth;
|
||||
db->xAuth = 0;
|
||||
@@ -1829,7 +1829,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
#else
|
||||
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
|
||||
#endif
|
||||
db->lookaside.sz = lookasideSz;
|
||||
db->lookaside.bEnabled = enableLookaside;
|
||||
pParse->nTab = n;
|
||||
if( pSelTab ){
|
||||
assert( pTable->aCol==0 );
|
||||
@@ -2397,9 +2397,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
pKey = sqlite3IndexKeyinfo(pParse, pIndex);
|
||||
sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
|
||||
(char *)pKey, P4_KEYINFO_HANDOFF);
|
||||
if( memRootPage>=0 ){
|
||||
sqlite3VdbeChangeP5(v, 1);
|
||||
}
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
|
||||
|
||||
#ifndef SQLITE_OMIT_MERGE_SORT
|
||||
/* Open the sorter cursor if we are to use one. */
|
||||
@@ -2538,7 +2536,7 @@ Index *sqlite3CreateIndex(
|
||||
assert( pName && pName->z );
|
||||
|
||||
#ifndef SQLITE_OMIT_TEMPDB
|
||||
/* If the index name was unqualified, check if the the table
|
||||
/* If the index name was unqualified, check if the table
|
||||
** is a temp table. If so, set the database to 1. Do not do this
|
||||
** if initialising a database schema.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -371,7 +371,7 @@ void sqlite3DeleteFrom(
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
|
||||
pWInfo = sqlite3WhereBegin(
|
||||
pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
|
||||
pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
|
||||
);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
|
||||
|
||||
+53
-28
@@ -1701,7 +1701,7 @@ int sqlite3CodeSubselect(
|
||||
|
||||
assert( !isRowid );
|
||||
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
|
||||
dest.affinity = (u8)affinity;
|
||||
dest.affSdst = (u8)affinity;
|
||||
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
|
||||
pExpr->x.pSelect->iLimit = 0;
|
||||
if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
|
||||
@@ -1794,11 +1794,11 @@ int sqlite3CodeSubselect(
|
||||
sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
|
||||
if( pExpr->op==TK_SELECT ){
|
||||
dest.eDest = SRT_Mem;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iParm);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm);
|
||||
VdbeComment((v, "Init subquery result"));
|
||||
}else{
|
||||
dest.eDest = SRT_Exists;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
|
||||
VdbeComment((v, "Init EXISTS result"));
|
||||
}
|
||||
sqlite3ExprDelete(pParse->db, pSel->pLimit);
|
||||
@@ -1808,7 +1808,7 @@ int sqlite3CodeSubselect(
|
||||
if( sqlite3Select(pParse, pSel, &dest) ){
|
||||
return 0;
|
||||
}
|
||||
rReg = dest.iParm;
|
||||
rReg = dest.iSDParm;
|
||||
ExprSetIrreducible(pExpr);
|
||||
break;
|
||||
}
|
||||
@@ -3123,9 +3123,12 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
}else{
|
||||
pFarg = pExpr->x.pList;
|
||||
}
|
||||
sqlite3ExplainPrintf(pOut, "%sFUNCTION:%s(",
|
||||
op==TK_AGG_FUNCTION ? "AGG_" : "",
|
||||
pExpr->u.zToken);
|
||||
if( op==TK_AGG_FUNCTION ){
|
||||
sqlite3ExplainPrintf(pOut, "AGG_FUNCTION%d:%s(",
|
||||
pExpr->op2, pExpr->u.zToken);
|
||||
}else{
|
||||
sqlite3ExplainPrintf(pOut, "FUNCTION:%s(", pExpr->u.zToken);
|
||||
}
|
||||
if( pFarg ){
|
||||
sqlite3ExplainExprList(pOut, pFarg);
|
||||
}
|
||||
@@ -3816,38 +3819,60 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the expression callback for sqlite3FunctionUsesOtherSrc().
|
||||
**
|
||||
** Determine if an expression references any table other than one of the
|
||||
** tables in pWalker->u.pSrcList and abort if it does.
|
||||
** An instance of the following structure is used by the tree walker
|
||||
** to count references to table columns in the arguments of an
|
||||
** aggregate function, in order to implement the
|
||||
** sqlite3FunctionThisSrc() routine.
|
||||
*/
|
||||
static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){
|
||||
if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){
|
||||
struct SrcCount {
|
||||
SrcList *pSrc; /* One particular FROM clause in a nested query */
|
||||
int nThis; /* Number of references to columns in pSrcList */
|
||||
int nOther; /* Number of references to columns in other FROM clauses */
|
||||
};
|
||||
|
||||
/*
|
||||
** Count the number of references to columns.
|
||||
*/
|
||||
static int exprSrcCount(Walker *pWalker, Expr *pExpr){
|
||||
/* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
|
||||
** is always called before sqlite3ExprAnalyzeAggregates() and so the
|
||||
** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If
|
||||
** sqlite3FunctionUsesThisSrc() is used differently in the future, the
|
||||
** NEVER() will need to be removed. */
|
||||
if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
|
||||
int i;
|
||||
SrcList *pSrc = pWalker->u.pSrcList;
|
||||
struct SrcCount *p = pWalker->u.pSrcCount;
|
||||
SrcList *pSrc = p->pSrc;
|
||||
for(i=0; i<pSrc->nSrc; i++){
|
||||
if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue;
|
||||
if( pExpr->iTable==pSrc->a[i].iCursor ) break;
|
||||
}
|
||||
if( i<pSrc->nSrc ){
|
||||
p->nThis++;
|
||||
}else{
|
||||
p->nOther++;
|
||||
}
|
||||
return WRC_Abort;
|
||||
}else{
|
||||
return WRC_Continue;
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** Determine if any of the arguments to the pExpr Function references
|
||||
** any SrcList other than pSrcList. Return true if they do. Return
|
||||
** false if pExpr has no argument or has only constant arguments or
|
||||
** only references tables named in pSrcList.
|
||||
** Determine if any of the arguments to the pExpr Function reference
|
||||
** pSrcList. Return true if they do. Also return true if the function
|
||||
** has no arguments or has only constant arguments. Return false if pExpr
|
||||
** references columns but not columns of tables found in pSrcList.
|
||||
*/
|
||||
static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){
|
||||
int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
|
||||
Walker w;
|
||||
struct SrcCount cnt;
|
||||
assert( pExpr->op==TK_AGG_FUNCTION );
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = exprUsesOtherSrc;
|
||||
w.u.pSrcList = pSrcList;
|
||||
if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1;
|
||||
return 0;
|
||||
w.xExprCallback = exprSrcCount;
|
||||
w.u.pSrcCount = &cnt;
|
||||
cnt.pSrc = pSrcList;
|
||||
cnt.nThis = 0;
|
||||
cnt.nOther = 0;
|
||||
sqlite3WalkExprList(&w, pExpr->x.pList);
|
||||
return cnt.nThis>0 || cnt.nOther==0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3966,7 +3991,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
case TK_AGG_FUNCTION: {
|
||||
if( (pNC->ncFlags & NC_InAggFunc)==0
|
||||
&& !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList)
|
||||
&& pWalker->walkerDepth==pExpr->op2
|
||||
){
|
||||
/* Check to see if pExpr is a duplicate of another aggregate
|
||||
** function that is already in the pAggInfo structure
|
||||
|
||||
+5
-5
@@ -560,7 +560,7 @@ static void fkScanChildren(
|
||||
** clause. If the constraint is not deferred, throw an exception for
|
||||
** each row found. Otherwise, for deferred constraints, increment the
|
||||
** deferred constraint counter by nIncr for each row selected. */
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
|
||||
if( nIncr>0 && pFKey->isDeferred==0 ){
|
||||
sqlite3ParseToplevel(pParse)->mayAbort = 1;
|
||||
}
|
||||
@@ -981,7 +981,7 @@ static Trigger *fkActionTrigger(
|
||||
pTrigger = pFKey->apTrigger[iAction];
|
||||
|
||||
if( action!=OE_None && !pTrigger ){
|
||||
u16 lookasideSz; /* Copy of db->lookaside.sz */
|
||||
u8 enableLookaside; /* Copy of db->lookaside.bEnabled */
|
||||
char const *zFrom; /* Name of child table */
|
||||
int nFrom; /* Length in bytes of zFrom */
|
||||
Index *pIdx = 0; /* Parent key index for this FK */
|
||||
@@ -1090,8 +1090,8 @@ static Trigger *fkActionTrigger(
|
||||
}
|
||||
|
||||
/* Disable lookaside memory allocation */
|
||||
lookasideSz = db->lookaside.sz;
|
||||
db->lookaside.sz = 0;
|
||||
enableLookaside = db->lookaside.bEnabled;
|
||||
db->lookaside.bEnabled = 0;
|
||||
|
||||
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
|
||||
sizeof(Trigger) + /* struct Trigger */
|
||||
@@ -1114,7 +1114,7 @@ static Trigger *fkActionTrigger(
|
||||
}
|
||||
|
||||
/* Re-enable the lookaside buffer, if it was disabled earlier. */
|
||||
db->lookaside.sz = lookasideSz;
|
||||
db->lookaside.bEnabled = enableLookaside;
|
||||
|
||||
sqlite3ExprDelete(db, pWhere);
|
||||
sqlite3ExprDelete(db, pWhen);
|
||||
|
||||
+5
-1
@@ -113,7 +113,11 @@ static int rehash(Hash *pH, unsigned int new_size){
|
||||
|
||||
/* The inability to allocates space for a larger hash table is
|
||||
** a performance hit but it is not a fatal error. So mark the
|
||||
** allocation as a benign.
|
||||
** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
|
||||
** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
|
||||
** only zeroes the requested number of bytes whereas this module will
|
||||
** use the actual amount of space allocated for the hash table (which
|
||||
** may be larger than the requested amount).
|
||||
*/
|
||||
sqlite3BeginBenignMalloc();
|
||||
new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
|
||||
|
||||
+7
-7
@@ -597,7 +597,7 @@ void sqlite3Insert(
|
||||
VdbeComment((v, "SELECT eof flag"));
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem);
|
||||
addrSelect = sqlite3VdbeCurrentAddr(v)+2;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iParm);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iSDParm);
|
||||
j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
|
||||
VdbeComment((v, "Jump over SELECT coroutine"));
|
||||
|
||||
@@ -608,15 +608,15 @@ void sqlite3Insert(
|
||||
goto insert_cleanup;
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm); /* yield X */
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); /* yield X */
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
|
||||
VdbeComment((v, "End of SELECT coroutine"));
|
||||
sqlite3VdbeJumpHere(v, j1); /* label B: */
|
||||
|
||||
regFromSelect = dest.iMem;
|
||||
regFromSelect = dest.iSdst;
|
||||
assert( pSelect->pEList );
|
||||
nColumn = pSelect->pEList->nExpr;
|
||||
assert( dest.nMem==nColumn );
|
||||
assert( dest.nSdst==nColumn );
|
||||
|
||||
/* Set useTempTable to TRUE if the result of the SELECT statement
|
||||
** should be written into a temporary table (template 4). Set to
|
||||
@@ -652,7 +652,7 @@ void sqlite3Insert(
|
||||
regRec = sqlite3GetTempReg(pParse);
|
||||
regTempRowid = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
|
||||
addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
|
||||
@@ -789,7 +789,7 @@ void sqlite3Insert(
|
||||
** goto C
|
||||
** D: ...
|
||||
*/
|
||||
addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);
|
||||
addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
|
||||
addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof);
|
||||
}
|
||||
|
||||
@@ -1271,7 +1271,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
case OE_Replace: {
|
||||
/* If there are DELETE triggers on this table and the
|
||||
** recursive-triggers flag is set, call GenerateRowDelete() to
|
||||
** remove the conflicting row from the the table. This will fire
|
||||
** remove the conflicting row from the table. This will fire
|
||||
** the triggers and remove both the table and index b-tree entries.
|
||||
**
|
||||
** Otherwise, if there are no triggers or the recursive-triggers
|
||||
|
||||
+5
-31
@@ -302,17 +302,6 @@ int sqlite3_shutdown(void){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** If a custom memory allocator is configured using the legacy
|
||||
** SQLITE_CONFIG_MALLOC interface, this function is used as the xCalloc()
|
||||
** method.
|
||||
*/
|
||||
static void *syntheticCalloc(int nByte){
|
||||
void *pRet = sqlite3GlobalConfig.m.xMalloc(nByte);
|
||||
if( pRet ) memset(pRet, 0, nByte);
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** This API allows applications to modify the global configuration of
|
||||
** the SQLite library at run-time.
|
||||
@@ -368,33 +357,18 @@ int sqlite3_config(int op, ...){
|
||||
}
|
||||
#endif
|
||||
|
||||
case SQLITE_CONFIG_MALLOC: {
|
||||
/* Specify an alternative malloc implementation */
|
||||
int nCopy = offsetof(sqlite3_mem_methods, xCalloc);
|
||||
memcpy(&sqlite3GlobalConfig.m, va_arg(ap, sqlite3_mem_methods*), nCopy);
|
||||
sqlite3GlobalConfig.m.xCalloc = syntheticCalloc;
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_GETMALLOC: {
|
||||
/* Retrieve the current malloc() implementation */
|
||||
int nCopy = offsetof(sqlite3_mem_methods, xCalloc);
|
||||
if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
|
||||
memcpy(va_arg(ap, sqlite3_mem_methods*), &sqlite3GlobalConfig.m, nCopy);
|
||||
break;
|
||||
}
|
||||
|
||||
case SQLITE_CONFIG_MALLOC2: {
|
||||
case SQLITE_CONFIG_MALLOC: {
|
||||
/* Specify an alternative malloc implementation */
|
||||
sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*);
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_GETMALLOC2: {
|
||||
case SQLITE_CONFIG_GETMALLOC: {
|
||||
/* Retrieve the current malloc() implementation */
|
||||
if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
|
||||
*va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m;
|
||||
break;
|
||||
}
|
||||
|
||||
case SQLITE_CONFIG_MEMSTATUS: {
|
||||
/* Enable or disable the malloc status collection */
|
||||
sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
|
||||
@@ -552,7 +526,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
||||
}
|
||||
db->lookaside.pStart = pStart;
|
||||
db->lookaside.pFree = 0;
|
||||
db->lookaside.szEnabled = db->lookaside.sz = (u16)sz;
|
||||
db->lookaside.sz = (u16)sz;
|
||||
if( pStart ){
|
||||
int i;
|
||||
LookasideSlot *p;
|
||||
@@ -564,12 +538,12 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
||||
p = (LookasideSlot*)&((u8*)p)[sz];
|
||||
}
|
||||
db->lookaside.pEnd = p;
|
||||
db->lookaside.bEnabled = 1;
|
||||
db->lookaside.bMalloced = pBuf==0 ?1:0;
|
||||
assert( db->lookaside.sz>0 );
|
||||
}else{
|
||||
db->lookaside.pEnd = 0;
|
||||
db->lookaside.bEnabled = 0;
|
||||
db->lookaside.bMalloced = 0;
|
||||
db->lookaside.sz = 0;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
+82
-131
@@ -259,27 +259,14 @@ static void sqlite3MallocAlarm(int nByte){
|
||||
** Do a memory allocation with statistics and alarms. Assume the
|
||||
** lock is already held.
|
||||
*/
|
||||
static void *mallocWithAlarm(
|
||||
void *(*xAlloc)(int), /* Memory allocation function */
|
||||
int n /* Bytes of memory to allocate */
|
||||
){
|
||||
void *p; /* Pointer to allocated memory */
|
||||
int nFull; /* Value returned by xRoundup (if required) */
|
||||
|
||||
static int mallocWithAlarm(int n, void **pp){
|
||||
int nFull;
|
||||
void *p;
|
||||
assert( sqlite3_mutex_held(mem0.mutex) );
|
||||
assert( xAlloc==sqlite3GlobalConfig.m.xMalloc
|
||||
|| xAlloc==sqlite3GlobalConfig.m.xCalloc
|
||||
);
|
||||
|
||||
/* Note: At one point this function would call xRoundup() and use the
|
||||
** resulting value as the argument to xAlloc(). However, this is not
|
||||
** required. And it is a (small) drag on performance. */
|
||||
/* nFull = sqlite3GlobalConfig.m.xRoundup(n); */
|
||||
|
||||
nFull = sqlite3GlobalConfig.m.xRoundup(n);
|
||||
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
|
||||
if( mem0.alarmCallback ){
|
||||
if( mem0.alarmCallback!=0 ){
|
||||
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
nFull = sqlite3GlobalConfig.m.xRoundup(n);
|
||||
if( nUsed >= mem0.alarmThreshold - nFull ){
|
||||
mem0.nearlyFull = 1;
|
||||
sqlite3MallocAlarm(nFull);
|
||||
@@ -287,33 +274,27 @@ static void *mallocWithAlarm(
|
||||
mem0.nearlyFull = 0;
|
||||
}
|
||||
}
|
||||
|
||||
p = xAlloc(n);
|
||||
p = sqlite3GlobalConfig.m.xMalloc(nFull);
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
if( p==0 && mem0.alarmCallback ){
|
||||
sqlite3MallocAlarm(nFull);
|
||||
p = xAlloc(nFull);
|
||||
p = sqlite3GlobalConfig.m.xMalloc(nFull);
|
||||
}
|
||||
#endif
|
||||
if( p ){
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p));
|
||||
nFull = sqlite3MallocSize(p);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
}else{
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to allocate %d bytes of memory", n);
|
||||
}
|
||||
|
||||
return p;
|
||||
*pp = p;
|
||||
return nFull;
|
||||
}
|
||||
|
||||
/*
|
||||
** Use allocator function xAlloc to allocate n bytes of memory.
|
||||
** Allocate memory. This routine is like sqlite3_malloc() except that it
|
||||
** assumes the memory subsystem has already been initialized.
|
||||
*/
|
||||
static void *memAllocate(
|
||||
sqlite3 *db,
|
||||
void *(*xAlloc)(int), /* Memory allocation function */
|
||||
int n /* Bytes of space to allocate */
|
||||
){
|
||||
void *sqlite3Malloc(int n){
|
||||
void *p;
|
||||
if( n<=0 /* IMP: R-65312-04917 */
|
||||
|| n>=0x7fffff00
|
||||
@@ -324,42 +305,17 @@ static void *memAllocate(
|
||||
** 255 bytes of overhead. SQLite itself will never use anything near
|
||||
** this amount. The only way to reach the limit is with sqlite3_malloc() */
|
||||
p = 0;
|
||||
}else if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
mallocWithAlarm(n, &p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
p = mallocWithAlarm(xAlloc, n);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
p = xAlloc(n);
|
||||
}
|
||||
if( !p && db ) db->mallocFailed = 1;
|
||||
p = sqlite3GlobalConfig.m.xMalloc(n);
|
||||
}
|
||||
|
||||
assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */
|
||||
if( db ){
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_DB |
|
||||
((db && db->lookaside.sz) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)
|
||||
);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Allocate memory. This routine is like sqlite3_malloc() except that it
|
||||
** assumes the memory subsystem has already been initialized.
|
||||
*/
|
||||
void *sqlite3Malloc(int n){
|
||||
return memAllocate(0, sqlite3GlobalConfig.m.xMalloc, n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate and zero memory.
|
||||
*/
|
||||
void *sqlite3MallocZero(int n){
|
||||
return memAllocate(0, sqlite3GlobalConfig.m.xCalloc, n);
|
||||
}
|
||||
|
||||
/*
|
||||
** This version of the memory allocation is for use by the application.
|
||||
** First make sure the memory subsystem is initialized, then do the
|
||||
@@ -406,11 +362,8 @@ void *sqlite3ScratchMalloc(int n){
|
||||
}else{
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
|
||||
p = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n);
|
||||
if( p ){
|
||||
n = sqlite3MallocSize(p);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
|
||||
}
|
||||
n = mallocWithAlarm(n, &p);
|
||||
if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
@@ -617,42 +570,33 @@ void *sqlite3_realloc(void *pOld, int n){
|
||||
return sqlite3Realloc(pOld, n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to allocate an n byte block from the lookaside buffer of
|
||||
** connection db. If successful, return a pointer to the new allocation.
|
||||
** Otherwise, return a NULL pointer.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_LOOKASIDE
|
||||
static void *lookasideAlloc(sqlite3 *db, int n){
|
||||
assert( db->lookaside.sz==0 || db->lookaside.sz==db->lookaside.szEnabled );
|
||||
if( n>db->lookaside.sz ){
|
||||
/* If db->lookaside.sz is 0, then the lookaside buffer is currently
|
||||
** disabled. In this case do not increment the "size misses" stat. */
|
||||
if( db->lookaside.sz ) db->lookaside.anStat[1]++;
|
||||
}else{
|
||||
LookasideSlot *pBuf;
|
||||
if( (pBuf = db->lookaside.pFree)==0 ){
|
||||
db->lookaside.anStat[2]++;
|
||||
}else{
|
||||
db->lookaside.pFree = pBuf->pNext;
|
||||
db->lookaside.nOut++;
|
||||
db->lookaside.anStat[0]++;
|
||||
if( db->lookaside.nOut>db->lookaside.mxOut ){
|
||||
db->lookaside.mxOut = db->lookaside.nOut;
|
||||
}
|
||||
}
|
||||
sqlite3MemdebugSetType((void *)pBuf, MEMTYPE_DB | MEMTYPE_LOOKASIDE);
|
||||
return (void*)pBuf;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
# define lookasideAlloc(x,y) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Allocate and zero memory. If the allocation fails, set the
|
||||
** mallocFailed flag in the connection pointer.
|
||||
** Allocate and zero memory.
|
||||
*/
|
||||
void *sqlite3MallocZero(int n){
|
||||
void *p = sqlite3Malloc(n);
|
||||
if( p ){
|
||||
memset(p, 0, n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate and zero memory. If the allocation fails, make
|
||||
** the mallocFailed flag in the connection pointer.
|
||||
*/
|
||||
void *sqlite3DbMallocZero(sqlite3 *db, int n){
|
||||
void *p = sqlite3DbMallocRaw(db, n);
|
||||
if( p ){
|
||||
memset(p, 0, n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate and zero memory. If the allocation fails, make
|
||||
** the mallocFailed flag in the connection pointer.
|
||||
**
|
||||
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
|
||||
** failure on the same database connection) then always return 0.
|
||||
@@ -668,37 +612,44 @@ static void *lookasideAlloc(sqlite3 *db, int n){
|
||||
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
|
||||
** that all prior mallocs (ex: "a") worked too.
|
||||
*/
|
||||
void *sqlite3DbMallocZero(sqlite3 *db, int n){
|
||||
void *p;
|
||||
if( db ){
|
||||
if( db->mallocFailed ) return 0;
|
||||
if( (p = lookasideAlloc(db, n)) ){
|
||||
memset(p, 0, n);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return memAllocate(db, sqlite3GlobalConfig.m.xCalloc, n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate memory. If the allocation fails, make the mallocFailed
|
||||
** flag in the connection pointer.
|
||||
**
|
||||
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
|
||||
** failure on the same database connection) then always return 0.
|
||||
** See also comments above sqlite3DbMallocZero() for details.
|
||||
*/
|
||||
void *sqlite3DbMallocRaw(sqlite3 *db, int n){
|
||||
void *p;
|
||||
assert( db==0 || sqlite3_mutex_held(db->mutex) );
|
||||
assert( db==0 || db->pnBytesFreed==0 );
|
||||
#ifndef SQLITE_OMIT_LOOKASIDE
|
||||
if( db ){
|
||||
if( db->mallocFailed ) return 0;
|
||||
if( (p = lookasideAlloc(db, n)) ){
|
||||
return p;
|
||||
LookasideSlot *pBuf;
|
||||
if( db->mallocFailed ){
|
||||
return 0;
|
||||
}
|
||||
if( db->lookaside.bEnabled ){
|
||||
if( n>db->lookaside.sz ){
|
||||
db->lookaside.anStat[1]++;
|
||||
}else if( (pBuf = db->lookaside.pFree)==0 ){
|
||||
db->lookaside.anStat[2]++;
|
||||
}else{
|
||||
db->lookaside.pFree = pBuf->pNext;
|
||||
db->lookaside.nOut++;
|
||||
db->lookaside.anStat[0]++;
|
||||
if( db->lookaside.nOut>db->lookaside.mxOut ){
|
||||
db->lookaside.mxOut = db->lookaside.nOut;
|
||||
}
|
||||
return (void*)pBuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return memAllocate(db, sqlite3GlobalConfig.m.xMalloc, n);
|
||||
#else
|
||||
if( db && db->mallocFailed ){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
p = sqlite3Malloc(n);
|
||||
if( !p && db ){
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_DB |
|
||||
((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -714,12 +665,12 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
|
||||
return sqlite3DbMallocRaw(db, n);
|
||||
}
|
||||
if( isLookaside(db, p) ){
|
||||
if( n<=db->lookaside.szEnabled ){
|
||||
if( n<=db->lookaside.sz ){
|
||||
return p;
|
||||
}
|
||||
pNew = sqlite3DbMallocRaw(db, n);
|
||||
if( pNew ){
|
||||
memcpy(pNew, p, db->lookaside.szEnabled);
|
||||
memcpy(pNew, p, db->lookaside.sz);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
}else{
|
||||
@@ -732,7 +683,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
|
||||
(db->lookaside.sz ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
|
||||
(db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
|
||||
}
|
||||
}
|
||||
return pNew;
|
||||
|
||||
+21
-30
@@ -70,7 +70,6 @@
|
||||
#include <libkern/OSAtomic.h>
|
||||
static malloc_zone_t* _sqliteZone_;
|
||||
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
|
||||
#define SQLITE_CALLOC(x) malloc_zone_calloc(_sqliteZone_, (x), 1)
|
||||
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
|
||||
#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
|
||||
#define SQLITE_MALLOCSIZE(x) \
|
||||
@@ -83,7 +82,6 @@ static malloc_zone_t* _sqliteZone_;
|
||||
** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
|
||||
*/
|
||||
#define SQLITE_MALLOC(x) malloc(x)
|
||||
#define SQLITE_CALLOC(x) calloc((x), 1)
|
||||
#define SQLITE_FREE(x) free(x)
|
||||
#define SQLITE_REALLOC(x,y) realloc((x),(y))
|
||||
|
||||
@@ -102,7 +100,8 @@ static malloc_zone_t* _sqliteZone_;
|
||||
#endif /* __APPLE__ or not __APPLE__ */
|
||||
|
||||
/*
|
||||
** Allocate nByte bytes of memory.
|
||||
** Like malloc(), but remember the size of the allocation
|
||||
** so that we can find it later using sqlite3MemSize().
|
||||
**
|
||||
** For this low-level routine, we are guaranteed that nByte>0 because
|
||||
** cases of nByte<=0 will be intercepted and dealt with by higher level
|
||||
@@ -110,31 +109,24 @@ static malloc_zone_t* _sqliteZone_;
|
||||
*/
|
||||
static void *sqlite3MemMalloc(int nByte){
|
||||
#ifdef SQLITE_MALLOCSIZE
|
||||
return SQLITE_MALLOC( ROUND8(nByte) );
|
||||
void *p = SQLITE_MALLOC( nByte );
|
||||
if( p==0 ){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
|
||||
}
|
||||
return p;
|
||||
#else
|
||||
i64 *p;
|
||||
sqlite3_int64 *p;
|
||||
assert( nByte>0 );
|
||||
nByte = ROUND8(nByte);
|
||||
p = SQLITE_MALLOC(nByte+8);
|
||||
if( p ) *(p++) = (i64)nByte;
|
||||
return (void *)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate and zero nByte bytes of memory.
|
||||
**
|
||||
** For this low-level routine, we are guaranteed that nByte>0 because
|
||||
** cases of nByte<=0 will be intercepted and dealt with by higher level
|
||||
** routines.
|
||||
*/
|
||||
static void *sqlite3MemCalloc(int nByte){
|
||||
#ifdef SQLITE_MALLOCSIZE
|
||||
return SQLITE_CALLOC( ROUND8(nByte) );
|
||||
#else
|
||||
i64 *p;
|
||||
nByte = ROUND8(nByte);
|
||||
p = SQLITE_CALLOC(nByte+8);
|
||||
if( p ) *(p++) = (i64)nByte;
|
||||
p = SQLITE_MALLOC( nByte+8 );
|
||||
if( p ){
|
||||
p[0] = nByte;
|
||||
p++;
|
||||
}else{
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
|
||||
}
|
||||
return (void *)p;
|
||||
#endif
|
||||
}
|
||||
@@ -239,14 +231,14 @@ static int sqlite3MemInit(void *NotUsed){
|
||||
}else{
|
||||
/* only 1 core, use our own zone to contention over global locks,
|
||||
** e.g. we have our own dedicated locks */
|
||||
bool success;
|
||||
bool success;
|
||||
malloc_zone_t* newzone = malloc_create_zone(4096, 0);
|
||||
malloc_set_zone_name(newzone, "Sqlite_Heap");
|
||||
do{
|
||||
success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
|
||||
(void * volatile *)&_sqliteZone_);
|
||||
}while(!_sqliteZone_);
|
||||
if( !success ){
|
||||
if( !success ){
|
||||
/* somebody registered a zone first */
|
||||
malloc_destroy_zone(newzone);
|
||||
}
|
||||
@@ -279,8 +271,7 @@ void sqlite3MemSetDefault(void){
|
||||
sqlite3MemRoundup,
|
||||
sqlite3MemInit,
|
||||
sqlite3MemShutdown,
|
||||
0,
|
||||
sqlite3MemCalloc
|
||||
0
|
||||
};
|
||||
sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
|
||||
}
|
||||
|
||||
@@ -92,8 +92,8 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with WindowsRT (Metro) as this has a different and
|
||||
** incompatible API from win32.
|
||||
** 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
|
||||
|
||||
+12
-12
@@ -715,9 +715,9 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
||||
case EACCES:
|
||||
/* EACCES is like EAGAIN during locking operations, but not any other time*/
|
||||
if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
|
||||
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
|
||||
return SQLITE_BUSY;
|
||||
}
|
||||
/* else fall through */
|
||||
@@ -1052,7 +1052,7 @@ static unixInodeInfo *inodeList = 0;
|
||||
** The first argument passed to the macro should be the error code that
|
||||
** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
|
||||
** The two subsequent arguments should be the name of the OS function that
|
||||
** failed (e.g. "unlink", "open") and the the associated file-system path,
|
||||
** failed (e.g. "unlink", "open") and the associated file-system path,
|
||||
** if any.
|
||||
*/
|
||||
#define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__)
|
||||
@@ -1075,7 +1075,7 @@ static int unixLogErrorAtLine(
|
||||
zErr = aErr;
|
||||
|
||||
/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
|
||||
** assume that the system provides the the GNU version of strerror_r() that
|
||||
** assume that the system provides the GNU version of strerror_r() that
|
||||
** returns a pointer to a buffer containing the error message. That pointer
|
||||
** may point to aErr[], or it may point to some static storage somewhere.
|
||||
** Otherwise, assume that the system provides the POSIX version of
|
||||
@@ -1764,7 +1764,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||
pInode->eFileLock = NO_LOCK;
|
||||
}else{
|
||||
rc = SQLITE_IOERR_UNLOCK;
|
||||
pFile->lastErrno = errno;
|
||||
pFile->lastErrno = errno;
|
||||
pInode->eFileLock = NO_LOCK;
|
||||
pFile->eFileLock = NO_LOCK;
|
||||
}
|
||||
@@ -1780,7 +1780,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||
closePendingFds(pFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
end_unlock:
|
||||
unixLeaveMutex();
|
||||
if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
|
||||
@@ -2047,7 +2047,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, getpid()));
|
||||
pFile->eFileLock, getpid()));
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
|
||||
/* no-op if possible */
|
||||
@@ -2434,7 +2434,7 @@ static int semUnlock(sqlite3_file *id, int eFileLock) {
|
||||
assert( pFile );
|
||||
assert( pSem );
|
||||
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, getpid()));
|
||||
pFile->eFileLock, getpid()));
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
|
||||
/* no-op if possible */
|
||||
@@ -3024,7 +3024,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
|
||||
if( newOffset == -1 ){
|
||||
((unixFile*)id)->lastErrno = errno;
|
||||
}else{
|
||||
((unixFile*)id)->lastErrno = 0;
|
||||
((unixFile*)id)->lastErrno = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -3112,7 +3112,7 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
|
||||
if( newOffset == -1 ){
|
||||
((unixFile*)id)->lastErrno = errno;
|
||||
}else{
|
||||
((unixFile*)id)->lastErrno = 0;
|
||||
((unixFile*)id)->lastErrno = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -5626,7 +5626,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
|
||||
** address in the shared range is taken for a SHARED lock, the entire
|
||||
** shared range is taken for an EXCLUSIVE lock):
|
||||
**
|
||||
** PENDING_BYTE 0x40000000
|
||||
** PENDING_BYTE 0x40000000
|
||||
** RESERVED_BYTE 0x40000001
|
||||
** SHARED_RANGE 0x40000002 -> 0x40000200
|
||||
**
|
||||
|
||||
+80
-8
@@ -46,9 +46,11 @@
|
||||
# define FILE_ATTRIBUTE_MASK (0x0003FFF7)
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/* Forward references */
|
||||
typedef struct winShm winShm; /* A connection to shared-memory */
|
||||
typedef struct winShmNode winShmNode; /* A region of shared-memory */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** WinCE lacks native support for file locking so we have to fake it
|
||||
@@ -76,7 +78,9 @@ struct winFile {
|
||||
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
|
||||
u8 ctrlFlags; /* Flags. See WINFILE_* below */
|
||||
DWORD lastErrno; /* The Windows errno from the last I/O error */
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
winShm *pShm; /* Instance of shared memory on this file */
|
||||
#endif
|
||||
const char *zPath; /* Full pathname of this file */
|
||||
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
|
||||
#if SQLITE_OS_WINCE
|
||||
@@ -101,6 +105,22 @@ struct winFile {
|
||||
# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The value used with sqlite3_win32_set_directory() to specify that
|
||||
* the data directory should be changed.
|
||||
*/
|
||||
#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE
|
||||
# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The value used with sqlite3_win32_set_directory() to specify that
|
||||
* the temporary directory should be changed.
|
||||
*/
|
||||
#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE
|
||||
# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
|
||||
* various Win32 API heap functions instead of our own.
|
||||
@@ -288,7 +308,8 @@ static struct win_syscall {
|
||||
#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
|
||||
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
||||
!defined(SQLITE_OMIT_WAL))
|
||||
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
|
||||
#else
|
||||
{ "CreateFileMappingW", (SYSCALL)0, 0 },
|
||||
@@ -600,7 +621,7 @@ static struct win_syscall {
|
||||
LPOVERLAPPED))aSyscall[45].pCurrent)
|
||||
#endif
|
||||
|
||||
#if !SQLITE_OS_WINRT
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
|
||||
{ "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
|
||||
#else
|
||||
{ "MapViewOfFile", (SYSCALL)0, 0 },
|
||||
@@ -670,7 +691,11 @@ static struct win_syscall {
|
||||
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
||||
LPOVERLAPPED))aSyscall[55].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
|
||||
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
|
||||
#else
|
||||
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[56].pCurrent)
|
||||
|
||||
@@ -702,7 +727,7 @@ static struct win_syscall {
|
||||
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
|
||||
DWORD))aSyscall[60].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINCE
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
|
||||
#else
|
||||
{ "WaitForSingleObjectEx", (SYSCALL)0, 0 },
|
||||
@@ -711,7 +736,7 @@ static struct win_syscall {
|
||||
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
|
||||
BOOL))aSyscall[61].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINCE
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
|
||||
#else
|
||||
{ "SetFilePointerEx", (SYSCALL)0, 0 },
|
||||
@@ -729,7 +754,7 @@ static struct win_syscall {
|
||||
#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
|
||||
FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[63].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
|
||||
{ "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
|
||||
#else
|
||||
{ "MapViewOfFileFromApp", (SYSCALL)0, 0 },
|
||||
@@ -793,7 +818,7 @@ static struct win_syscall {
|
||||
|
||||
#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[71].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
|
||||
{ "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
|
||||
#else
|
||||
{ "CreateFileMappingFromApp", (SYSCALL)0, 0 },
|
||||
@@ -1309,6 +1334,42 @@ char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
|
||||
return zFilenameMbcs;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function sets the data directory or the temporary directory based on
|
||||
** the provided arguments. The type argument must be 1 in order to set the
|
||||
** data directory or 2 in order to set the temporary directory. The zValue
|
||||
** argument is the name of the directory to use. The return value will be
|
||||
** SQLITE_OK if successful.
|
||||
*/
|
||||
int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
|
||||
char **ppDirectory = 0;
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
int rc = sqlite3_initialize();
|
||||
if( rc ) return rc;
|
||||
#endif
|
||||
if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
|
||||
ppDirectory = &sqlite3_data_directory;
|
||||
}else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
|
||||
ppDirectory = &sqlite3_temp_directory;
|
||||
}
|
||||
assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
|
||||
|| type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
|
||||
);
|
||||
assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
|
||||
if( ppDirectory ){
|
||||
char *zValueUtf8 = 0;
|
||||
if( zValue && zValue[0] ){
|
||||
zValueUtf8 = unicodeToUtf8(zValue);
|
||||
if ( zValueUtf8==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
sqlite3_free(*ppDirectory);
|
||||
*ppDirectory = zValueUtf8;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** The return value of getLastErrorMsg
|
||||
@@ -1403,7 +1464,7 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
|
||||
** The first argument passed to the macro should be the error code that
|
||||
** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
|
||||
** The two subsequent arguments should be the name of the OS function that
|
||||
** failed and the the associated file-system path, if any.
|
||||
** failed and the associated file-system path, if any.
|
||||
*/
|
||||
#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
|
||||
static int winLogErrorAtLine(
|
||||
@@ -1925,7 +1986,9 @@ static int winClose(sqlite3_file *id){
|
||||
winFile *pFile = (winFile*)id;
|
||||
|
||||
assert( id!=0 );
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
assert( pFile->pShm==0 );
|
||||
#endif
|
||||
OSTRACE(("CLOSE %d\n", pFile->h));
|
||||
do{
|
||||
rc = osCloseHandle(pFile->h);
|
||||
@@ -3527,6 +3590,13 @@ static int winOpen(
|
||||
assert( id!=0 );
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
if( !sqlite3_temp_directory ){
|
||||
sqlite3_log(SQLITE_ERROR,
|
||||
"sqlite3_temp_directory variable should be set for WinRT");
|
||||
}
|
||||
#endif
|
||||
|
||||
pFile->h = INVALID_HANDLE_VALUE;
|
||||
|
||||
/* If the second argument to this function is NULL, generate a
|
||||
@@ -3675,7 +3745,9 @@ static int winOpen(
|
||||
pFile->h = h;
|
||||
pFile->lastErrno = NO_ERROR;
|
||||
pFile->pVfs = pVfs;
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
pFile->pShm = 0;
|
||||
#endif
|
||||
pFile->zPath = zName;
|
||||
if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
|
||||
pFile->ctrlFlags |= WINFILE_PSOW;
|
||||
@@ -3838,7 +3910,7 @@ static int winAccess(
|
||||
}
|
||||
}else{
|
||||
logIoerr(cnt);
|
||||
if( lastErrno!=ERROR_FILE_NOT_FOUND ){
|
||||
if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
|
||||
winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
|
||||
sqlite3_free(zConverted);
|
||||
return SQLITE_IOERR_ACCESS;
|
||||
|
||||
+2
-2
@@ -75,7 +75,7 @@
|
||||
**
|
||||
** Definition: Two databases (or the same database at two points it time)
|
||||
** are said to be "logically equivalent" if they give the same answer to
|
||||
** all queries. Note in particular the the content of freelist leaf
|
||||
** all queries. Note in particular the content of freelist leaf
|
||||
** pages can be changed arbitarily without effecting the logical equivalence
|
||||
** of the database.
|
||||
**
|
||||
@@ -3849,7 +3849,7 @@ void sqlite3PagerRef(DbPage *pPg){
|
||||
**
|
||||
** If the Pager.noSync flag is set, then this function is a no-op.
|
||||
** Otherwise, the actions required depend on the journal-mode and the
|
||||
** device characteristics of the the file-system, as follows:
|
||||
** device characteristics of the file-system, as follows:
|
||||
**
|
||||
** * If the journal file is an in-memory journal file, no action need
|
||||
** be taken.
|
||||
|
||||
+2
-2
@@ -152,7 +152,7 @@ create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). {
|
||||
sqlite3StartTable(pParse,&Y,&Z,T,0,0,E);
|
||||
}
|
||||
createkw(A) ::= CREATE(X). {
|
||||
pParse->db->lookaside.sz = 0;
|
||||
pParse->db->lookaside.bEnabled = 0;
|
||||
A = X;
|
||||
}
|
||||
%type ifnotexists {int}
|
||||
@@ -1378,7 +1378,7 @@ cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). {
|
||||
sqlite3AlterFinishAddColumn(pParse, &Y);
|
||||
}
|
||||
add_column_fullname ::= fullname(X). {
|
||||
pParse->db->lookaside.sz = 0;
|
||||
pParse->db->lookaside.bEnabled = 0;
|
||||
sqlite3AlterBeginAddColumn(pParse, X);
|
||||
}
|
||||
kwcolumn_opt ::= .
|
||||
|
||||
+2
-4
@@ -396,11 +396,10 @@ static int pcache1ResizeHash(PCache1 *p){
|
||||
|
||||
pcache1LeaveMutex(p->pGroup);
|
||||
if( p->nHash ){ sqlite3BeginBenignMalloc(); }
|
||||
apNew = (PgHdr1 **)sqlite3_malloc(sizeof(PgHdr1 *)*nNew);
|
||||
apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
|
||||
if( p->nHash ){ sqlite3EndBenignMalloc(); }
|
||||
pcache1EnterMutex(p->pGroup);
|
||||
if( apNew ){
|
||||
memset(apNew, 0, sizeof(PgHdr1 *)*nNew);
|
||||
for(i=0; i<p->nHash; i++){
|
||||
PgHdr1 *pPage;
|
||||
PgHdr1 *pNext = p->apHash[i];
|
||||
@@ -584,9 +583,8 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
|
||||
assert( szExtra < 300 );
|
||||
|
||||
sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
|
||||
pCache = (PCache1 *)sqlite3_malloc(sz);
|
||||
pCache = (PCache1 *)sqlite3MallocZero(sz);
|
||||
if( pCache ){
|
||||
memset(pCache, 0, sz);
|
||||
if( separateCache ){
|
||||
pGroup = (PGroup*)&pCache[1];
|
||||
pGroup->mxPinned = 10;
|
||||
|
||||
+48
-9
@@ -18,6 +18,29 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** Walk the expression tree pExpr and increase the aggregate function
|
||||
** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
|
||||
** This needs to occur when copying a TK_AGG_FUNCTION node from an
|
||||
** outer query into an inner subquery.
|
||||
**
|
||||
** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
|
||||
** is a helper function - a callback for the tree walker.
|
||||
*/
|
||||
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
|
||||
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.i;
|
||||
return WRC_Continue;
|
||||
}
|
||||
static void incrAggFunctionDepth(Expr *pExpr, int N){
|
||||
if( N>0 ){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = incrAggDepth;
|
||||
w.u.i = N;
|
||||
sqlite3WalkExpr(&w, pExpr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Turn the pExpr expression into an alias for the iCol-th column of the
|
||||
** result set in pEList.
|
||||
@@ -44,13 +67,20 @@
|
||||
** The result of random()%5 in the GROUP BY clause is probably different
|
||||
** from the result in the result-set. We might fix this someday. Or
|
||||
** then again, we might not...
|
||||
**
|
||||
** The nSubquery parameter specifies how many levels of subquery the
|
||||
** alias is removed from the original expression. The usually value is
|
||||
** zero but it might be more if the alias is contained within a subquery
|
||||
** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
|
||||
** structures must be increased by the nSubquery amount.
|
||||
*/
|
||||
static void resolveAlias(
|
||||
Parse *pParse, /* Parsing context */
|
||||
ExprList *pEList, /* A result set */
|
||||
int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
|
||||
Expr *pExpr, /* Transform this into an alias to the result set */
|
||||
const char *zType /* "GROUP" or "ORDER" or "" */
|
||||
const char *zType, /* "GROUP" or "ORDER" or "" */
|
||||
int nSubquery /* Number of subqueries that the label is moving */
|
||||
){
|
||||
Expr *pOrig; /* The iCol-th column of the result set */
|
||||
Expr *pDup; /* Copy of pOrig */
|
||||
@@ -63,6 +93,7 @@ static void resolveAlias(
|
||||
db = pParse->db;
|
||||
if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
|
||||
pDup = sqlite3ExprDup(db, pOrig, 0);
|
||||
incrAggFunctionDepth(pDup, nSubquery);
|
||||
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
|
||||
if( pDup==0 ) return;
|
||||
if( pEList->a[iCol].iAlias==0 ){
|
||||
@@ -151,9 +182,10 @@ static int lookupName(
|
||||
NameContext *pNC, /* The name context used to resolve the name */
|
||||
Expr *pExpr /* Make this EXPR node point to the selected column */
|
||||
){
|
||||
int i, j; /* Loop counters */
|
||||
int i, j; /* Loop counters */
|
||||
int cnt = 0; /* Number of matching column names */
|
||||
int cntTab = 0; /* Number of matching table names */
|
||||
int nSubquery = 0; /* How many levels of subquery */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
struct SrcList_item *pItem; /* Use for looping over pSrcList items */
|
||||
struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
|
||||
@@ -315,7 +347,7 @@ static int lookupName(
|
||||
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
|
||||
return WRC_Abort;
|
||||
}
|
||||
resolveAlias(pParse, pEList, j, pExpr, "");
|
||||
resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
|
||||
cnt = 1;
|
||||
pMatch = 0;
|
||||
assert( zTab==0 && zDb==0 );
|
||||
@@ -329,6 +361,7 @@ static int lookupName(
|
||||
*/
|
||||
if( cnt==0 ){
|
||||
pNC = pNC->pNext;
|
||||
nSubquery++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,13 +601,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
nId, zId);
|
||||
pNC->nErr++;
|
||||
}
|
||||
if( is_agg ){
|
||||
pExpr->op = TK_AGG_FUNCTION;
|
||||
pNC->ncFlags |= NC_HasAgg;
|
||||
}
|
||||
if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
|
||||
sqlite3WalkExprList(pWalker, pList);
|
||||
if( is_agg ) pNC->ncFlags |= NC_AllowAgg;
|
||||
if( is_agg ){
|
||||
NameContext *pNC2 = pNC;
|
||||
pExpr->op = TK_AGG_FUNCTION;
|
||||
pExpr->op2 = 0;
|
||||
while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
|
||||
pExpr->op2++;
|
||||
pNC2 = pNC2->pNext;
|
||||
}
|
||||
if( pNC2 ) pNC2->ncFlags |= NC_HasAgg;
|
||||
pNC->ncFlags |= NC_AllowAgg;
|
||||
}
|
||||
/* FIX ME: Compute pExpr->affinity based on the expected return
|
||||
** type of the function
|
||||
*/
|
||||
@@ -853,7 +892,7 @@ int sqlite3ResolveOrderGroupBy(
|
||||
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
|
||||
return 1;
|
||||
}
|
||||
resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType);
|
||||
resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -440,7 +440,7 @@ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if element iRowid was inserted into the the rowset as
|
||||
** Check to see if element iRowid was inserted into the rowset as
|
||||
** part of any insert batch prior to iBatch. Return 1 or 0.
|
||||
**
|
||||
** If this is the first test of a new batch and if there exist entires
|
||||
|
||||
+77
-68
@@ -36,10 +36,10 @@ static void clearSelect(sqlite3 *db, Select *p){
|
||||
*/
|
||||
void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
|
||||
pDest->eDest = (u8)eDest;
|
||||
pDest->iParm = iParm;
|
||||
pDest->affinity = 0;
|
||||
pDest->iMem = 0;
|
||||
pDest->nMem = 0;
|
||||
pDest->iSDParm = iParm;
|
||||
pDest->affSdst = 0;
|
||||
pDest->iSdst = 0;
|
||||
pDest->nSdst = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -551,7 +551,7 @@ static void selectInnerLoop(
|
||||
int hasDistinct; /* True if the DISTINCT keyword is present */
|
||||
int regResult; /* Start of memory holding result set */
|
||||
int eDest = pDest->eDest; /* How to dispose of results */
|
||||
int iParm = pDest->iParm; /* First argument to disposal method */
|
||||
int iParm = pDest->iSDParm; /* First argument to disposal method */
|
||||
int nResultCol; /* Number of result columns */
|
||||
|
||||
assert( v );
|
||||
@@ -569,14 +569,14 @@ static void selectInnerLoop(
|
||||
}else{
|
||||
nResultCol = pEList->nExpr;
|
||||
}
|
||||
if( pDest->iMem==0 ){
|
||||
pDest->iMem = pParse->nMem+1;
|
||||
pDest->nMem = nResultCol;
|
||||
if( pDest->iSdst==0 ){
|
||||
pDest->iSdst = pParse->nMem+1;
|
||||
pDest->nSdst = nResultCol;
|
||||
pParse->nMem += nResultCol;
|
||||
}else{
|
||||
assert( pDest->nMem==nResultCol );
|
||||
assert( pDest->nSdst==nResultCol );
|
||||
}
|
||||
regResult = pDest->iMem;
|
||||
regResult = pDest->iSdst;
|
||||
if( nColumn>0 ){
|
||||
for(i=0; i<nColumn; i++){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
|
||||
@@ -655,7 +655,7 @@ static void selectInnerLoop(
|
||||
*/
|
||||
case SRT_Set: {
|
||||
assert( nColumn==1 );
|
||||
p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
|
||||
p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
|
||||
if( pOrderBy ){
|
||||
/* At first glance you would think we could optimize out the
|
||||
** ORDER BY in this case since the order of entries in the set
|
||||
@@ -710,7 +710,7 @@ static void selectInnerLoop(
|
||||
pushOntoSorter(pParse, pOrderBy, p, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
}else if( eDest==SRT_Coroutine ){
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
|
||||
sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);
|
||||
@@ -890,7 +890,7 @@ static void generateSortTail(
|
||||
ExprList *pOrderBy = p->pOrderBy;
|
||||
|
||||
int eDest = pDest->eDest;
|
||||
int iParm = pDest->iParm;
|
||||
int iParm = pDest->iSDParm;
|
||||
|
||||
int regRow;
|
||||
int regRowid;
|
||||
@@ -949,17 +949,17 @@ static void generateSortTail(
|
||||
testcase( eDest==SRT_Output );
|
||||
testcase( eDest==SRT_Coroutine );
|
||||
for(i=0; i<nColumn; i++){
|
||||
assert( regRow!=pDest->iMem+i );
|
||||
sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+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->iMem, nColumn);
|
||||
sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
|
||||
sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
|
||||
}else{
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1398,9 +1398,9 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
|
||||
if( pTab==0 ){
|
||||
return 0;
|
||||
}
|
||||
/* The sqlite3ResultSetOfSelect() should only used in contexts where the
|
||||
** lookaside buffer is disabled. */
|
||||
assert( db->lookaside.sz==0 );
|
||||
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
|
||||
** is disabled */
|
||||
assert( db->lookaside.bEnabled==0 );
|
||||
pTab->nRef = 1;
|
||||
pTab->zName = 0;
|
||||
pTab->nRowEst = 1000000;
|
||||
@@ -1610,7 +1610,7 @@ static int multiSelect(
|
||||
*/
|
||||
if( dest.eDest==SRT_EphemTab ){
|
||||
assert( p->pEList );
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr);
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr);
|
||||
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
|
||||
dest.eDest = SRT_Table;
|
||||
}
|
||||
@@ -1696,7 +1696,7 @@ static int multiSelect(
|
||||
** of a 3-way or more compound */
|
||||
assert( p->pLimit==0 ); /* Not allowed on leftward elements */
|
||||
assert( p->pOffset==0 ); /* Not allowed on leftward elements */
|
||||
unionTab = dest.iParm;
|
||||
unionTab = dest.iSDParm;
|
||||
}else{
|
||||
/* We will need to create our own temporary table to hold the
|
||||
** intermediate results.
|
||||
@@ -1753,7 +1753,7 @@ static int multiSelect(
|
||||
/* Convert the data in the temporary table into whatever form
|
||||
** it is that we currently need.
|
||||
*/
|
||||
assert( unionTab==dest.iParm || dest.eDest!=priorOp );
|
||||
assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
|
||||
if( dest.eDest!=priorOp ){
|
||||
int iCont, iBreak, iStart;
|
||||
assert( p->pEList );
|
||||
@@ -1817,7 +1817,7 @@ static int multiSelect(
|
||||
p->pLimit = 0;
|
||||
pOffset = p->pOffset;
|
||||
p->pOffset = 0;
|
||||
intersectdest.iParm = tab2;
|
||||
intersectdest.iSDParm = tab2;
|
||||
explainSetInteger(iSub2, pParse->iNextSelectId);
|
||||
rc = sqlite3Select(pParse, p, &intersectdest);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
@@ -1911,8 +1911,8 @@ static int multiSelect(
|
||||
}
|
||||
|
||||
multi_select_end:
|
||||
pDest->iMem = dest.iMem;
|
||||
pDest->nMem = dest.nMem;
|
||||
pDest->iSdst = dest.iSdst;
|
||||
pDest->nSdst = dest.nSdst;
|
||||
sqlite3SelectDelete(db, pDelete);
|
||||
return rc;
|
||||
}
|
||||
@@ -1922,8 +1922,8 @@ multi_select_end:
|
||||
** Code an output subroutine for a coroutine implementation of a
|
||||
** SELECT statment.
|
||||
**
|
||||
** The data to be output is contained in pIn->iMem. There are
|
||||
** pIn->nMem columns to be output. pDest is where the output should
|
||||
** The data to be output is contained in pIn->iSdst. There are
|
||||
** pIn->nSdst columns to be output. pDest is where the output should
|
||||
** be sent.
|
||||
**
|
||||
** regReturn is the number of the register holding the subroutine
|
||||
@@ -1961,16 +1961,16 @@ static int generateOutputSubroutine(
|
||||
if( regPrev ){
|
||||
int j1, j2;
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);
|
||||
j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iMem, regPrev+1, pIn->nMem,
|
||||
j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
|
||||
(char*)pKeyInfo, p4type);
|
||||
sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3ExprCodeCopy(pParse, pIn->iMem, regPrev+1, pIn->nMem);
|
||||
sqlite3ExprCodeCopy(pParse, pIn->iSdst, regPrev+1, pIn->nSdst);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
|
||||
}
|
||||
if( pParse->db->mallocFailed ) return 0;
|
||||
|
||||
/* Suppress the the first OFFSET entries if there is an OFFSET clause
|
||||
/* Suppress the first OFFSET entries if there is an OFFSET clause
|
||||
*/
|
||||
codeOffset(v, p, iContinue);
|
||||
|
||||
@@ -1983,9 +1983,9 @@ static int generateOutputSubroutine(
|
||||
int r2 = sqlite3GetTempReg(pParse);
|
||||
testcase( pDest->eDest==SRT_Table );
|
||||
testcase( pDest->eDest==SRT_EphemTab );
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
sqlite3ReleaseTempReg(pParse, r2);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
@@ -1999,13 +1999,13 @@ static int generateOutputSubroutine(
|
||||
*/
|
||||
case SRT_Set: {
|
||||
int r1;
|
||||
assert( pIn->nMem==1 );
|
||||
assert( pIn->nSdst==1 );
|
||||
p->affinity =
|
||||
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity);
|
||||
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1);
|
||||
sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iParm, r1);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &p->affinity, 1);
|
||||
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
break;
|
||||
}
|
||||
@@ -2014,7 +2014,7 @@ static int generateOutputSubroutine(
|
||||
/* If any row exist in the result set, record that fact and abort.
|
||||
*/
|
||||
case SRT_Exists: {
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iParm);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
|
||||
/* The LIMIT clause will terminate the loop for us */
|
||||
break;
|
||||
}
|
||||
@@ -2025,23 +2025,23 @@ static int generateOutputSubroutine(
|
||||
** of the scan loop.
|
||||
*/
|
||||
case SRT_Mem: {
|
||||
assert( pIn->nMem==1 );
|
||||
sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iParm, 1);
|
||||
assert( pIn->nSdst==1 );
|
||||
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
|
||||
/* The LIMIT clause will jump out of the loop for us */
|
||||
break;
|
||||
}
|
||||
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
|
||||
|
||||
/* The results are stored in a sequence of registers
|
||||
** starting at pDest->iMem. Then the co-routine yields.
|
||||
** starting at pDest->iSdst. Then the co-routine yields.
|
||||
*/
|
||||
case SRT_Coroutine: {
|
||||
if( pDest->iMem==0 ){
|
||||
pDest->iMem = sqlite3GetTempRange(pParse, pIn->nMem);
|
||||
pDest->nMem = pIn->nMem;
|
||||
if( pDest->iSdst==0 ){
|
||||
pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst);
|
||||
pDest->nSdst = pIn->nSdst;
|
||||
}
|
||||
sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iMem, pDest->nMem);
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);
|
||||
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst);
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2055,8 +2055,8 @@ static int generateOutputSubroutine(
|
||||
*/
|
||||
default: {
|
||||
assert( pDest->eDest==SRT_Output );
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem);
|
||||
sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst);
|
||||
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2475,7 +2475,7 @@ static int multiSelectOrderBy(
|
||||
*/
|
||||
sqlite3VdbeResolveLabel(v, labelCmpr);
|
||||
sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
|
||||
sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy,
|
||||
sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
|
||||
(char*)pKeyMerge, P4_KEYINFO_HANDOFF);
|
||||
sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
|
||||
|
||||
@@ -2689,6 +2689,12 @@ static void substSelect(
|
||||
** operators have an implied DISTINCT which is disallowed by
|
||||
** restriction (4).
|
||||
**
|
||||
** Also, each component of the sub-query must return the same number
|
||||
** of result columns. This is actually a requirement for any compound
|
||||
** SELECT statement, but all the code here does is make sure that no
|
||||
** such (illegal) sub-query is flattened. The caller will detect the
|
||||
** syntax error and return a detailed message.
|
||||
**
|
||||
** (18) If the sub-query is a compound select, then all terms of the
|
||||
** ORDER by clause of the parent must be simple references to
|
||||
** columns of the sub-query.
|
||||
@@ -2832,6 +2838,7 @@ static int flattenSubquery(
|
||||
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
|
||||
|| (pSub1->pPrior && pSub1->op!=TK_ALL)
|
||||
|| pSub1->pSrc->nSrc<1
|
||||
|| pSub->pEList->nExpr!=pSub1->pEList->nExpr
|
||||
){
|
||||
return 0;
|
||||
}
|
||||
@@ -3149,7 +3156,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
|
||||
|
||||
if( IsVirtual(pTab) ) return 0;
|
||||
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
|
||||
if( pAggInfo->nFunc==0 ) return 0;
|
||||
if( NEVER(pAggInfo->nFunc==0) ) return 0;
|
||||
if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
|
||||
if( pExpr->flags&EP_Distinct ) return 0;
|
||||
|
||||
@@ -3521,7 +3528,7 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
|
||||
|
||||
|
||||
/*
|
||||
** This routine sets of a SELECT statement for processing. The
|
||||
** This routine sets up a SELECT statement for processing. The
|
||||
** following is accomplished:
|
||||
**
|
||||
** * VDBE Cursor numbers are assigned to all FROM-clause terms.
|
||||
@@ -3553,7 +3560,8 @@ void sqlite3SelectPrep(
|
||||
**
|
||||
** The aggregate accumulator is a set of memory cells that hold
|
||||
** intermediate results while calculating an aggregate. This
|
||||
** routine simply stores NULLs in all of those memory cells.
|
||||
** routine generates code that stores NULLs in all of those memory
|
||||
** cells.
|
||||
*/
|
||||
static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
@@ -3721,23 +3729,24 @@ static void explainSimpleCount(
|
||||
**
|
||||
** SRT_Mem Only valid if the result is a single column.
|
||||
** Store the first column of the first result row
|
||||
** in register pDest->iParm then abandon the rest
|
||||
** in register pDest->iSDParm then abandon the rest
|
||||
** of the query. This destination implies "LIMIT 1".
|
||||
**
|
||||
** SRT_Set The result must be a single column. Store each
|
||||
** row of result as the key in table pDest->iParm.
|
||||
** Apply the affinity pDest->affinity before storing
|
||||
** row of result as the key in table pDest->iSDParm.
|
||||
** Apply the affinity pDest->affSdst before storing
|
||||
** results. Used to implement "IN (SELECT ...)".
|
||||
**
|
||||
** SRT_Union Store results as a key in a temporary table pDest->iParm.
|
||||
** SRT_Union Store results as a key in a temporary table
|
||||
** identified by pDest->iSDParm.
|
||||
**
|
||||
** SRT_Except Remove results from the temporary table pDest->iParm.
|
||||
** SRT_Except Remove results from the temporary table pDest->iSDParm.
|
||||
**
|
||||
** SRT_Table Store results in temporary table pDest->iParm.
|
||||
** SRT_Table Store results in temporary table pDest->iSDParm.
|
||||
** This is like SRT_EphemTab except that the table
|
||||
** is assumed to already be open.
|
||||
**
|
||||
** SRT_EphemTab Create an temporary table pDest->iParm and store
|
||||
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
|
||||
** the result there. The cursor is left open after
|
||||
** returning. This is like SRT_Table except that
|
||||
** this destination uses OP_OpenEphemeral to create
|
||||
@@ -3745,9 +3754,9 @@ static void explainSimpleCount(
|
||||
**
|
||||
** SRT_Coroutine Generate a co-routine that returns a new row of
|
||||
** results each time it is invoked. The entry point
|
||||
** of the co-routine is stored in register pDest->iParm.
|
||||
** of the co-routine is stored in register pDest->iSDParm.
|
||||
**
|
||||
** SRT_Exists Store a 1 in memory cell pDest->iParm if the result
|
||||
** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
|
||||
** set is not empty.
|
||||
**
|
||||
** SRT_Discard Throw the results away. This is used by SELECT
|
||||
@@ -3991,7 +4000,7 @@ int sqlite3Select(
|
||||
/* If the output is destined for a temporary table, open that table.
|
||||
*/
|
||||
if( pDest->eDest==SRT_EphemTab ){
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iParm, pEList->nExpr);
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
|
||||
}
|
||||
|
||||
/* Set the limiter.
|
||||
@@ -4022,7 +4031,7 @@ int sqlite3Select(
|
||||
ExprList *pDist = (isDistinct ? p->pEList : 0);
|
||||
|
||||
/* Begin the database scan. */
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0,0);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
|
||||
|
||||
@@ -4195,7 +4204,7 @@ int sqlite3Select(
|
||||
** in the right order to begin with.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0, 0);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( pGroupBy==0 ){
|
||||
/* The optimizer is able to deliver rows in group by order so
|
||||
@@ -4464,7 +4473,7 @@ int sqlite3Select(
|
||||
** of output.
|
||||
*/
|
||||
resetAccumulator(pParse, &sAggInfo);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax,0,flag,0);
|
||||
if( pWInfo==0 ){
|
||||
sqlite3ExprListDelete(db, pDel);
|
||||
goto select_end;
|
||||
|
||||
@@ -64,7 +64,9 @@
|
||||
# include <io.h>
|
||||
#define isatty(h) _isatty(h)
|
||||
#define access(f,m) _access((f),(m))
|
||||
#undef popen
|
||||
#define popen(a,b) _popen((a),(b))
|
||||
#undef pclose
|
||||
#define pclose(x) _pclose(x)
|
||||
#else
|
||||
/* Make sure isatty() has a prototype.
|
||||
|
||||
+33
-12
@@ -512,7 +512,7 @@ int sqlite3_exec(
|
||||
** CAPI3REF: Device Characteristics
|
||||
**
|
||||
** The xDeviceCharacteristics method of the [sqlite3_io_methods]
|
||||
** object returns an integer which is a vector of the these
|
||||
** object returns an integer which is a vector of these
|
||||
** bit values expressing I/O characteristics of the mass storage
|
||||
** device that holds the file that the [sqlite3_io_methods]
|
||||
** refers to.
|
||||
@@ -1341,7 +1341,6 @@ struct sqlite3_mem_methods {
|
||||
int (*xInit)(void*); /* Initialize the memory allocator */
|
||||
void (*xShutdown)(void*); /* Deinitialize the memory allocator */
|
||||
void *pAppData; /* Argument to xInit() and xShutdown() */
|
||||
void *(*xCalloc)(int); /* Zeroed memory allocation function */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1578,8 +1577,8 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
|
||||
#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
|
||||
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
|
||||
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* no xCalloc() */
|
||||
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* no xCalloc() */
|
||||
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
|
||||
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
|
||||
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
|
||||
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
|
||||
#define SQLITE_CONFIG_PCACHE 14 /* no-op */
|
||||
@@ -1588,8 +1587,6 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_URI 17 /* int */
|
||||
#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
|
||||
#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
|
||||
#define SQLITE_CONFIG_MALLOC2 20 /* sqlite3_mem_methods* incl xCalloc() */
|
||||
#define SQLITE_CONFIG_GETMALLOC2 21 /* sqlite3_mem_methods* incl xCalloc() */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@@ -2598,7 +2595,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** an error)^.
|
||||
** ^If "ro" is specified, then the database is opened for read-only
|
||||
** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
|
||||
** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
|
||||
** third argument to sqlite3_open_v2(). ^If the mode option is set to
|
||||
** "rw", then the database is opened for read-write (but not create)
|
||||
** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
|
||||
** been set. ^Value "rwc" is equivalent to setting both
|
||||
@@ -2665,6 +2662,12 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** codepage is currently defined. Filenames containing international
|
||||
** characters must be converted to UTF-8 prior to passing them into
|
||||
** sqlite3_open() or sqlite3_open_v2().
|
||||
**
|
||||
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
|
||||
** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various
|
||||
** features that require the use of temporary files may fail.
|
||||
**
|
||||
** See also: [sqlite3_temp_directory]
|
||||
*/
|
||||
int sqlite3_open(
|
||||
const char *filename, /* Database filename (UTF-8) */
|
||||
@@ -3157,8 +3160,11 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** ^(In those routines that have a fourth argument, its value is the
|
||||
** number of bytes in the parameter. To be clear: the value is the
|
||||
** number of <u>bytes</u> in the value, not the number of characters.)^
|
||||
** ^If the fourth parameter is negative, the length of the string is
|
||||
** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
|
||||
** is negative, then the length of the string is
|
||||
** the number of bytes up to the first zero terminator.
|
||||
** If the fourth parameter to sqlite3_bind_blob() is negative, then
|
||||
** the behavior is undefined.
|
||||
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
|
||||
** or sqlite3_bind_text16() then that parameter must be the byte offset
|
||||
** where the NUL terminator would occur assuming the string were NUL
|
||||
@@ -4155,11 +4161,11 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error()
|
||||
** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
|
||||
**
|
||||
** ^The sqlite3_result_toobig() interface causes SQLite to throw an error
|
||||
** indicating that a string or BLOB is too long to represent.
|
||||
** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an
|
||||
** error indicating that a string or BLOB is too long to represent.
|
||||
**
|
||||
** ^The sqlite3_result_nomem() interface causes SQLite to throw an error
|
||||
** indicating that a memory allocation failed.
|
||||
** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an
|
||||
** error indicating that a memory allocation failed.
|
||||
**
|
||||
** ^The sqlite3_result_int() interface sets the return value
|
||||
** of the application-defined function to be the 32-bit signed integer
|
||||
@@ -4466,6 +4472,21 @@ int sqlite3_sleep(int);
|
||||
** Hence, if this variable is modified directly, either it should be
|
||||
** made NULL or made to point to memory obtained from [sqlite3_malloc]
|
||||
** or else the use of the [temp_store_directory pragma] should be avoided.
|
||||
**
|
||||
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
|
||||
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
|
||||
** features that require the use of temporary files may fail. Here is an
|
||||
** example of how to do this using C++ with the Windows Runtime:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
|
||||
** TemporaryFolder->Path->Data();
|
||||
** char zPathBuf[MAX_PATH + 1];
|
||||
** memset(zPathBuf, 0, sizeof(zPathBuf));
|
||||
** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
|
||||
** NULL, NULL);
|
||||
** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
|
||||
** </pre></blockquote>
|
||||
*/
|
||||
SQLITE_EXTERN char *sqlite3_temp_directory;
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
** 2012 September 2
|
||||
**
|
||||
** 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 and resources that are specific to Windows.
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32_WCE)
|
||||
#include "winresrc.h"
|
||||
#else
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include "sqlite3rc.h"
|
||||
|
||||
/*
|
||||
* English (U.S.) resources
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*
|
||||
* Version
|
||||
*/
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION SQLITE_RESOURCE_VERSION
|
||||
PRODUCTVERSION SQLITE_RESOURCE_VERSION
|
||||
FILEFLAGSMASK 0x3F
|
||||
#if defined(_DEBUG)
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "SQLite Development Team"
|
||||
VALUE "FileDescription", "SQLite is a software library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine."
|
||||
VALUE "FileVersion", SQLITE_VERSION
|
||||
VALUE "InternalName", "sqlite3"
|
||||
VALUE "LegalCopyright", "http://www.sqlite.org/copyright.html"
|
||||
VALUE "ProductName", "SQLite"
|
||||
VALUE "ProductVersion", SQLITE_VERSION
|
||||
VALUE "SourceId", SQLITE_SOURCE_ID
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
+19
-13
@@ -783,14 +783,12 @@ struct Schema {
|
||||
** with a particular database connection. Hence, schema information cannot
|
||||
** be stored in lookaside because in shared cache mode the schema information
|
||||
** is shared by multiple database connections. Therefore, while parsing
|
||||
** schema information, the Lookaside.sz variable is temporarily set to
|
||||
** zero so that lookaside allocations are not used to construct the schema
|
||||
** objects. Lookaside.szEnabled always contains the allocation size that
|
||||
** Lookaside.sz is set to when the buffer is enabled.
|
||||
** schema information, the Lookaside.bEnabled flag is cleared so that
|
||||
** lookaside allocations are not used to construct the schema objects.
|
||||
*/
|
||||
struct Lookaside {
|
||||
u16 sz; /* Size of each buffer in bytes */
|
||||
u16 szEnabled; /* Value of 'sz' when buffer is enabled. */
|
||||
u8 bEnabled; /* False to disable new lookaside allocations */
|
||||
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
|
||||
int nOut; /* Number of buffers currently checked out */
|
||||
int mxOut; /* Highwater mark for nOut */
|
||||
@@ -1692,8 +1690,9 @@ struct Expr {
|
||||
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
||||
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
||||
u8 flags2; /* Second set of flags. EP2_... */
|
||||
u8 op2; /* If a TK_REGISTER, the original value of Expr.op */
|
||||
/* If TK_COLUMN, the value of p5 for OP_Column */
|
||||
u8 op2; /* TK_REGISTER: original value of Expr.op
|
||||
** TK_COLUMN: the value of p5 for OP_Column
|
||||
** TK_AGG_FUNCTION: nesting depth */
|
||||
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
||||
Table *pTab; /* Table for TK_COLUMN expressions. */
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
@@ -1918,7 +1917,7 @@ struct WherePlan {
|
||||
/*
|
||||
** For each nested loop in a WHERE clause implementation, the WhereInfo
|
||||
** structure contains a single instance of this structure. This structure
|
||||
** is intended to be private the the where.c module and should not be
|
||||
** is intended to be private to the where.c module and should not be
|
||||
** access or modified by other modules.
|
||||
**
|
||||
** The pIdxInfo field is used to help pick the best index on a
|
||||
@@ -1948,6 +1947,7 @@ struct WhereLevel {
|
||||
int addrInTop; /* Top of the IN loop */
|
||||
} *aInLoop; /* Information about each nested IN operator */
|
||||
} in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
|
||||
Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
|
||||
} u;
|
||||
|
||||
/* The following field is really not part of the current level. But
|
||||
@@ -2120,10 +2120,10 @@ struct Select {
|
||||
typedef struct SelectDest SelectDest;
|
||||
struct SelectDest {
|
||||
u8 eDest; /* How to dispose of the results */
|
||||
u8 affinity; /* Affinity used when eDest==SRT_Set */
|
||||
int iParm; /* A parameter used by the eDest disposal method */
|
||||
int iMem; /* Base register where results are written */
|
||||
int nMem; /* Number of registers allocated */
|
||||
u8 affSdst; /* Affinity used when eDest==SRT_Set */
|
||||
int iSDParm; /* A parameter used by the eDest disposal method */
|
||||
int iSdst; /* Base register where results are written */
|
||||
int nSdst; /* Number of registers allocated */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2319,6 +2319,8 @@ struct AuthContext {
|
||||
#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
|
||||
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
|
||||
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
|
||||
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
|
||||
#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */
|
||||
|
||||
/*
|
||||
* Each trigger present in the database schema is stored as an instance of
|
||||
@@ -2498,10 +2500,12 @@ struct Walker {
|
||||
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
|
||||
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
|
||||
Parse *pParse; /* Parser context. */
|
||||
int walkerDepth; /* Number of subqueries */
|
||||
union { /* Extra data for callback */
|
||||
NameContext *pNC; /* Naming context */
|
||||
int i; /* Integer value */
|
||||
SrcList *pSrcList; /* FROM clause */
|
||||
struct SrcCount *pSrcCount; /* Counting column references */
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -2803,7 +2807,8 @@ Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *,
|
||||
#endif
|
||||
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
|
||||
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
|
||||
WhereInfo *sqlite3WhereBegin(
|
||||
Parse*,SrcList*,Expr*,ExprList**,ExprList*,u16,int);
|
||||
void sqlite3WhereEnd(WhereInfo*);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
|
||||
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
|
||||
@@ -2835,6 +2840,7 @@ int sqlite3ExprCompare(Expr*, Expr*);
|
||||
int sqlite3ExprListCompare(ExprList*, ExprList*);
|
||||
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
|
||||
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
|
||||
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
|
||||
Vdbe *sqlite3GetVdbe(Parse*);
|
||||
void sqlite3PrngSaveState(void);
|
||||
void sqlite3PrngRestoreState(void);
|
||||
|
||||
+16
-5
@@ -41,6 +41,12 @@
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
** This function is used to translate a return code into an error
|
||||
** message.
|
||||
*/
|
||||
const char *sqlite3ErrStr(int rc);
|
||||
|
||||
/*
|
||||
* Windows needs to know which symbols to export. Unix does not.
|
||||
* BUILD_sqlite should be undefined for Unix.
|
||||
@@ -2929,6 +2935,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
void *pKey = 0;
|
||||
int nKey = 0;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
/* In normal use, each TCL interpreter runs in a single thread. So
|
||||
** by default, we can turn of mutexing on SQLite database connections.
|
||||
@@ -3033,12 +3040,16 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
memset(p, 0, sizeof(*p));
|
||||
zFile = Tcl_GetStringFromObj(objv[2], 0);
|
||||
zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
|
||||
sqlite3_open_v2(zFile, &p->db, flags, zVfs);
|
||||
rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
|
||||
Tcl_DStringFree(&translatedFilename);
|
||||
if( SQLITE_OK!=sqlite3_errcode(p->db) ){
|
||||
zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
|
||||
sqlite3_close(p->db);
|
||||
p->db = 0;
|
||||
if( p->db ){
|
||||
if( SQLITE_OK!=sqlite3_errcode(p->db) ){
|
||||
zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
|
||||
sqlite3_close(p->db);
|
||||
p->db = 0;
|
||||
}
|
||||
}else{
|
||||
zErrMsg = sqlite3_mprintf("%s", sqlite3ErrStr(rc));
|
||||
}
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( p->db ){
|
||||
|
||||
+1
-1
@@ -5928,7 +5928,7 @@ static int optimization_control(
|
||||
sqlite3 *db;
|
||||
const char *zOpt;
|
||||
int onoff;
|
||||
int mask;
|
||||
int mask = 0;
|
||||
static const struct {
|
||||
const char *zOptName;
|
||||
int mask;
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** Code for testing the the SQLite library in a multithreaded environment.
|
||||
** Code for testing the SQLite library in a multithreaded environment.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
|
||||
@@ -319,6 +319,12 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_GET_TABLE
|
||||
Tcl_SetVar2(interp, "sqlite_options", "gettable", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
@@ -502,11 +502,11 @@ static int multiplexOpen(
|
||||
){
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */
|
||||
multiplexGroup *pGroup; /* Corresponding multiplexGroup object */
|
||||
multiplexGroup *pGroup = 0; /* Corresponding multiplexGroup object */
|
||||
sqlite3_file *pSubOpen = 0; /* Real file descriptor */
|
||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
||||
int nName;
|
||||
int sz;
|
||||
int nName = 0;
|
||||
int sz = 0;
|
||||
char *zToFree = 0;
|
||||
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
|
||||
+235
-588
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -361,7 +361,8 @@ static int tvfsWrite(
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
|
||||
tvfsExecTcl(p, "xWrite",
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
|
||||
Tcl_NewWideIntObj(iOfst)
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
}
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@
|
||||
** interprets VFS calls before passing them off to another VFS which does
|
||||
** the actual work. In this case the other VFS - the one that does the
|
||||
** real work - is identified by the second parameter, zOldVfsName. If
|
||||
** the the 2nd parameter is NULL then the default VFS is used. The common
|
||||
** the 2nd parameter is NULL then the default VFS is used. The common
|
||||
** case is for the 2nd parameter to be NULL.
|
||||
**
|
||||
** The third and fourth parameters are the pointer to the output function
|
||||
|
||||
+4
-6
@@ -390,7 +390,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
void *pEngine; /* The LEMON-generated LALR(1) parser */
|
||||
int tokenType; /* type of the next token */
|
||||
int lastTokenParsed = -1; /* type of the previous token */
|
||||
u16 lookasideSz; /* Saved value of db->lookaside.sz */
|
||||
u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
int mxSqlLen; /* Max length of an SQL string */
|
||||
|
||||
@@ -413,10 +413,8 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
assert( pParse->nVar==0 );
|
||||
assert( pParse->nzVar==0 );
|
||||
assert( pParse->azVar==0 );
|
||||
lookasideSz = db->lookaside.sz;
|
||||
if( db->lookaside.pStart ){
|
||||
db->lookaside.sz = db->lookaside.szEnabled;
|
||||
}
|
||||
enableLookaside = db->lookaside.bEnabled;
|
||||
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
|
||||
while( !db->mallocFailed && zSql[i]!=0 ){
|
||||
assert( i>=0 );
|
||||
pParse->sLastToken.z = &zSql[i];
|
||||
@@ -470,7 +468,7 @@ abort_parse:
|
||||
);
|
||||
#endif /* YYDEBUG */
|
||||
sqlite3ParserFree(pEngine, sqlite3_free);
|
||||
db->lookaside.sz = lookasideSz;
|
||||
db->lookaside.bEnabled = enableLookaside;
|
||||
if( db->mallocFailed ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ void sqlite3BeginTrigger(
|
||||
iDb = 1;
|
||||
pName = pName1;
|
||||
}else{
|
||||
/* Figure out the db that the the trigger will be created in */
|
||||
/* Figure out the db that the trigger will be created in */
|
||||
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
||||
if( iDb<0 ){
|
||||
goto trigger_cleanup;
|
||||
|
||||
+1
-1
@@ -313,7 +313,7 @@ void sqlite3Update(
|
||||
*/
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
|
||||
pWInfo = sqlite3WhereBegin(
|
||||
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
|
||||
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
|
||||
);
|
||||
if( pWInfo==0 ) goto update_cleanup;
|
||||
okOnePass = pWInfo->okOnePass;
|
||||
|
||||
+11
-3
@@ -656,7 +656,7 @@ int sqlite3VdbeExec(
|
||||
}
|
||||
#endif
|
||||
|
||||
/* On any opcode with the "out2-prerelase" tag, free any
|
||||
/* On any opcode with the "out2-prerelease" tag, free any
|
||||
** external allocations out of mem[p2] and set mem[p2] to be
|
||||
** an undefined integer. Opcodes will either fill in the integer
|
||||
** value or convert mem[p2] to a different type.
|
||||
@@ -3120,6 +3120,9 @@ case OP_OpenWrite: {
|
||||
VdbeCursor *pCur;
|
||||
Db *pDb;
|
||||
|
||||
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
|
||||
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
|
||||
|
||||
if( p->expired ){
|
||||
rc = SQLITE_ABORT;
|
||||
break;
|
||||
@@ -3143,7 +3146,7 @@ case OP_OpenWrite: {
|
||||
}else{
|
||||
wrFlag = 0;
|
||||
}
|
||||
if( pOp->p5 ){
|
||||
if( pOp->p5 & OPFLAG_P2ISREG ){
|
||||
assert( p2>0 );
|
||||
assert( p2<=p->nMem );
|
||||
pIn2 = &aMem[p2];
|
||||
@@ -3174,6 +3177,8 @@ case OP_OpenWrite: {
|
||||
pCur->isOrdered = 1;
|
||||
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
|
||||
pCur->pKeyInfo = pKeyInfo;
|
||||
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
|
||||
sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
|
||||
|
||||
/* Since it performs no memory allocation or IO, the only value that
|
||||
** sqlite3BtreeCursor() may return is SQLITE_OK. */
|
||||
@@ -6070,7 +6075,10 @@ case OP_Trace: {
|
||||
char *zTrace;
|
||||
char *z;
|
||||
|
||||
if( db->xTrace && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
|
||||
if( db->xTrace
|
||||
&& !p->doingRerun
|
||||
&& (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
|
||||
){
|
||||
z = sqlite3VdbeExpandSql(p, zTrace);
|
||||
db->xTrace(db->pTraceArg, z);
|
||||
sqlite3DbFree(db, z);
|
||||
|
||||
+19
-13
@@ -273,6 +273,11 @@ struct Explain {
|
||||
char zBase[100]; /* Initial space */
|
||||
};
|
||||
|
||||
/* A bitfield type for use inside of structures. Always follow with :N where
|
||||
** N is the number of bits.
|
||||
*/
|
||||
typedef unsigned bft; /* Bit Field Type */
|
||||
|
||||
/*
|
||||
** An instance of the virtual machine. This structure contains the complete
|
||||
** state of the virtual machine.
|
||||
@@ -314,15 +319,16 @@ struct Vdbe {
|
||||
int pc; /* The program counter */
|
||||
int rc; /* Value to return */
|
||||
u8 errorAction; /* Recovery action to do in case of an error */
|
||||
u8 explain; /* True if EXPLAIN present on SQL command */
|
||||
u8 changeCntOn; /* True to update the change-counter */
|
||||
u8 expired; /* True if the VM needs to be recompiled */
|
||||
u8 runOnlyOnce; /* Automatically expire on reset */
|
||||
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
||||
u8 inVtabMethod; /* See comments above */
|
||||
u8 usesStmtJournal; /* True if uses a statement journal */
|
||||
u8 readOnly; /* True for read-only statements */
|
||||
u8 isPrepareV2; /* True if prepared with prepare_v2() */
|
||||
bft explain:2; /* True if EXPLAIN present on SQL command */
|
||||
bft inVtabMethod:2; /* See comments above */
|
||||
bft changeCntOn:1; /* True to update the change-counter */
|
||||
bft expired:1; /* True if the VM needs to be recompiled */
|
||||
bft runOnlyOnce:1; /* Automatically expire on reset */
|
||||
bft usesStmtJournal:1; /* True if uses a statement journal */
|
||||
bft readOnly:1; /* True for read-only statements */
|
||||
bft isPrepareV2:1; /* True if prepared with prepare_v2() */
|
||||
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
|
||||
int nChange; /* Number of db changes made since last reset */
|
||||
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
||||
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
|
||||
@@ -431,11 +437,11 @@ int sqlite3VdbeTransferError(Vdbe *p);
|
||||
#else
|
||||
int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
|
||||
void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
|
||||
int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterCompare(VdbeCursor *, Mem *, int *);
|
||||
int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
||||
|
||||
@@ -478,10 +478,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
}
|
||||
db = v->db;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
v->doingRerun = 0;
|
||||
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
|
||||
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY
|
||||
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
|
||||
sqlite3_reset(pStmt);
|
||||
v->doingRerun = 1;
|
||||
assert( v->expired==0 );
|
||||
}
|
||||
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
|
||||
|
||||
+1
-1
@@ -774,7 +774,7 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
|
||||
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
** Change the comment on the the most recently coded instruction. Or
|
||||
** Change the comment on the most recently coded instruction. Or
|
||||
** insert a No-op and add the comment to that new instruction. This
|
||||
** makes the code easier to read during debugging. None of this happens
|
||||
** in a production build.
|
||||
|
||||
+297
-141
@@ -22,6 +22,7 @@
|
||||
|
||||
typedef struct VdbeSorterIter VdbeSorterIter;
|
||||
typedef struct SorterRecord SorterRecord;
|
||||
typedef struct FileWriter FileWriter;
|
||||
|
||||
/*
|
||||
** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
|
||||
@@ -119,6 +120,24 @@ struct VdbeSorterIter {
|
||||
sqlite3_file *pFile; /* File iterator is reading from */
|
||||
u8 *aAlloc; /* Allocated space */
|
||||
u8 *aKey; /* Pointer to current key */
|
||||
u8 *aBuffer; /* Current read buffer */
|
||||
int nBuffer; /* Size of read buffer in bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of this structure is used to organize the stream of records
|
||||
** being written to files by the merge-sort code into aligned, page-sized
|
||||
** blocks. Doing all I/O in aligned page-sized blocks helps I/O to go
|
||||
** faster on many operating systems.
|
||||
*/
|
||||
struct FileWriter {
|
||||
int eFWErr; /* Non-zero if in an error state */
|
||||
u8 *aBuffer; /* Pointer to write buffer */
|
||||
int nBuffer; /* Size of write buffer in bytes */
|
||||
int iBufStart; /* First byte of buffer to write */
|
||||
int iBufEnd; /* Last byte of buffer to write */
|
||||
i64 iWriteOff; /* Offset of start of buffer in file */
|
||||
sqlite3_file *pFile; /* File to write to */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -144,9 +163,123 @@ struct SorterRecord {
|
||||
*/
|
||||
static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){
|
||||
sqlite3DbFree(db, pIter->aAlloc);
|
||||
sqlite3DbFree(db, pIter->aBuffer);
|
||||
memset(pIter, 0, sizeof(VdbeSorterIter));
|
||||
}
|
||||
|
||||
/*
|
||||
** Read nByte bytes of data from the stream of data iterated by object p.
|
||||
** If successful, set *ppOut to point to a buffer containing the data
|
||||
** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite
|
||||
** error code.
|
||||
**
|
||||
** The buffer indicated by *ppOut may only be considered valid until the
|
||||
** next call to this function.
|
||||
*/
|
||||
static int vdbeSorterIterRead(
|
||||
sqlite3 *db, /* Database handle (for malloc) */
|
||||
VdbeSorterIter *p, /* Iterator */
|
||||
int nByte, /* Bytes of data to read */
|
||||
u8 **ppOut /* OUT: Pointer to buffer containing data */
|
||||
){
|
||||
int iBuf; /* Offset within buffer to read from */
|
||||
int nAvail; /* Bytes of data available in buffer */
|
||||
assert( p->aBuffer );
|
||||
|
||||
/* If there is no more data to be read from the buffer, read the next
|
||||
** p->nBuffer bytes of data from the file into it. Or, if there are less
|
||||
** than p->nBuffer bytes remaining in the PMA, read all remaining data. */
|
||||
iBuf = p->iReadOff % p->nBuffer;
|
||||
if( iBuf==0 ){
|
||||
int nRead; /* Bytes to read from disk */
|
||||
int rc; /* sqlite3OsRead() return code */
|
||||
|
||||
/* Determine how many bytes of data to read. */
|
||||
nRead = (int)(p->iEof - p->iReadOff);
|
||||
if( nRead>p->nBuffer ) nRead = p->nBuffer;
|
||||
assert( nRead>0 );
|
||||
|
||||
/* Read data from the file. Return early if an error occurs. */
|
||||
rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff);
|
||||
assert( rc!=SQLITE_IOERR_SHORT_READ );
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
nAvail = p->nBuffer - iBuf;
|
||||
|
||||
if( nByte<=nAvail ){
|
||||
/* The requested data is available in the in-memory buffer. In this
|
||||
** case there is no need to make a copy of the data, just return a
|
||||
** pointer into the buffer to the caller. */
|
||||
*ppOut = &p->aBuffer[iBuf];
|
||||
p->iReadOff += nByte;
|
||||
}else{
|
||||
/* The requested data is not all available in the in-memory buffer.
|
||||
** In this case, allocate space at p->aAlloc[] to copy the requested
|
||||
** range into. Then return a copy of pointer p->aAlloc to the caller. */
|
||||
int nRem; /* Bytes remaining to copy */
|
||||
|
||||
/* Extend the p->aAlloc[] allocation if required. */
|
||||
if( p->nAlloc<nByte ){
|
||||
int nNew = p->nAlloc*2;
|
||||
while( nByte>nNew ) nNew = nNew*2;
|
||||
p->aAlloc = sqlite3DbReallocOrFree(db, p->aAlloc, nNew);
|
||||
if( !p->aAlloc ) return SQLITE_NOMEM;
|
||||
p->nAlloc = nNew;
|
||||
}
|
||||
|
||||
/* Copy as much data as is available in the buffer into the start of
|
||||
** p->aAlloc[]. */
|
||||
memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail);
|
||||
p->iReadOff += nAvail;
|
||||
nRem = nByte - nAvail;
|
||||
|
||||
/* The following loop copies up to p->nBuffer bytes per iteration into
|
||||
** the p->aAlloc[] buffer. */
|
||||
while( nRem>0 ){
|
||||
int rc; /* vdbeSorterIterRead() return code */
|
||||
int nCopy; /* Number of bytes to copy */
|
||||
u8 *aNext; /* Pointer to buffer to copy data from */
|
||||
|
||||
nCopy = nRem;
|
||||
if( nRem>p->nBuffer ) nCopy = p->nBuffer;
|
||||
rc = vdbeSorterIterRead(db, p, nCopy, &aNext);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
assert( aNext!=p->aAlloc );
|
||||
memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
|
||||
nRem -= nCopy;
|
||||
}
|
||||
|
||||
*ppOut = p->aAlloc;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read a varint from the stream of data accessed by p. Set *pnOut to
|
||||
** the value read.
|
||||
*/
|
||||
static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){
|
||||
int iBuf;
|
||||
|
||||
iBuf = p->iReadOff % p->nBuffer;
|
||||
if( iBuf && (p->nBuffer-iBuf)>=9 ){
|
||||
p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut);
|
||||
}else{
|
||||
u8 aVarint[16], *a;
|
||||
int i = 0, rc;
|
||||
do{
|
||||
rc = vdbeSorterIterRead(db, p, 1, &a);
|
||||
if( rc ) return rc;
|
||||
aVarint[(i++)&0xf] = a[0];
|
||||
}while( (a[0]&0x80)!=0 );
|
||||
sqlite3GetVarint(aVarint, pnOut);
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
|
||||
** no error occurs, or an SQLite error code if one does.
|
||||
@@ -156,96 +289,18 @@ static int vdbeSorterIterNext(
|
||||
VdbeSorterIter *pIter /* Iterator to advance */
|
||||
){
|
||||
int rc; /* Return Code */
|
||||
int nRead; /* Number of bytes read */
|
||||
int nRec = 0; /* Size of record in bytes */
|
||||
int iOff = 0; /* Size of serialized size varint in bytes */
|
||||
u64 nRec = 0; /* Size of record in bytes */
|
||||
|
||||
assert( pIter->iEof>=pIter->iReadOff );
|
||||
if( pIter->iEof-pIter->iReadOff>5 ){
|
||||
nRead = 5;
|
||||
}else{
|
||||
nRead = (int)(pIter->iEof - pIter->iReadOff);
|
||||
}
|
||||
if( nRead<=0 ){
|
||||
if( pIter->iReadOff>=pIter->iEof ){
|
||||
/* This is an EOF condition */
|
||||
vdbeSorterIterZero(db, pIter);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
|
||||
rc = vdbeSorterIterVarint(db, pIter, &nRec);
|
||||
if( rc==SQLITE_OK ){
|
||||
iOff = getVarint32(pIter->aAlloc, nRec);
|
||||
if( (iOff+nRec)>nRead ){
|
||||
int nRead2; /* Number of extra bytes to read */
|
||||
if( (iOff+nRec)>pIter->nAlloc ){
|
||||
int nNew = pIter->nAlloc*2;
|
||||
while( (iOff+nRec)>nNew ) nNew = nNew*2;
|
||||
pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
|
||||
if( !pIter->aAlloc ) return SQLITE_NOMEM;
|
||||
pIter->nAlloc = nNew;
|
||||
}
|
||||
|
||||
nRead2 = iOff + nRec - nRead;
|
||||
rc = sqlite3OsRead(
|
||||
pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
assert( rc!=SQLITE_OK || nRec>0 );
|
||||
pIter->iReadOff += iOff+nRec;
|
||||
pIter->nKey = nRec;
|
||||
pIter->aKey = &pIter->aAlloc[iOff];
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write a single varint, value iVal, to file-descriptor pFile. Return
|
||||
** SQLITE_OK if successful, or an SQLite error code if some error occurs.
|
||||
**
|
||||
** The value of *piOffset when this function is called is used as the byte
|
||||
** offset in file pFile to write to. Before returning, *piOffset is
|
||||
** incremented by the number of bytes written.
|
||||
*/
|
||||
static int vdbeSorterWriteVarint(
|
||||
sqlite3_file *pFile, /* File to write to */
|
||||
i64 iVal, /* Value to write as a varint */
|
||||
i64 *piOffset /* IN/OUT: Write offset in file pFile */
|
||||
){
|
||||
u8 aVarint[9]; /* Buffer large enough for a varint */
|
||||
int nVarint; /* Number of used bytes in varint */
|
||||
int rc; /* Result of write() call */
|
||||
|
||||
nVarint = sqlite3PutVarint(aVarint, iVal);
|
||||
rc = sqlite3OsWrite(pFile, aVarint, nVarint, *piOffset);
|
||||
*piOffset += nVarint;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read a single varint from file-descriptor pFile. Return SQLITE_OK if
|
||||
** successful, or an SQLite error code if some error occurs.
|
||||
**
|
||||
** The value of *piOffset when this function is called is used as the
|
||||
** byte offset in file pFile from whence to read the varint. If successful
|
||||
** (i.e. if no IO error occurs), then *piOffset is set to the offset of
|
||||
** the first byte past the end of the varint before returning. *piVal is
|
||||
** set to the integer value read. If an error occurs, the final values of
|
||||
** both *piOffset and *piVal are undefined.
|
||||
*/
|
||||
static int vdbeSorterReadVarint(
|
||||
sqlite3_file *pFile, /* File to read from */
|
||||
i64 *piOffset, /* IN/OUT: Read offset in pFile */
|
||||
i64 *piVal /* OUT: Value read from file */
|
||||
){
|
||||
u8 aVarint[9]; /* Buffer large enough for a varint */
|
||||
i64 iOff = *piOffset; /* Offset in file to read from */
|
||||
int rc; /* Return code */
|
||||
|
||||
rc = sqlite3OsRead(pFile, aVarint, 9, iOff);
|
||||
if( rc==SQLITE_OK ){
|
||||
*piOffset += getVarint(aVarint, (u64 *)piVal);
|
||||
pIter->nKey = (int)nRec;
|
||||
rc = vdbeSorterIterRead(db, pIter, (int)nRec, &pIter->aKey);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -259,27 +314,52 @@ static int vdbeSorterReadVarint(
|
||||
*/
|
||||
static int vdbeSorterIterInit(
|
||||
sqlite3 *db, /* Database handle */
|
||||
VdbeSorter *pSorter, /* Sorter object */
|
||||
const VdbeSorter *pSorter, /* Sorter object */
|
||||
i64 iStart, /* Start offset in pFile */
|
||||
VdbeSorterIter *pIter, /* Iterator to populate */
|
||||
i64 *pnByte /* IN/OUT: Increment this value by PMA size */
|
||||
){
|
||||
int rc;
|
||||
int rc = SQLITE_OK;
|
||||
int nBuf;
|
||||
|
||||
nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
|
||||
|
||||
assert( pSorter->iWriteOff>iStart );
|
||||
assert( pIter->aAlloc==0 );
|
||||
assert( pIter->aBuffer==0 );
|
||||
pIter->pFile = pSorter->pTemp1;
|
||||
pIter->iReadOff = iStart;
|
||||
pIter->nAlloc = 128;
|
||||
pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
|
||||
if( !pIter->aAlloc ){
|
||||
pIter->nBuffer = nBuf;
|
||||
pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf);
|
||||
|
||||
if( !pIter->aBuffer ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
i64 nByte; /* Total size of PMA in bytes */
|
||||
rc = vdbeSorterReadVarint(pSorter->pTemp1, &pIter->iReadOff, &nByte);
|
||||
*pnByte += nByte;
|
||||
pIter->iEof = pIter->iReadOff + nByte;
|
||||
int iBuf;
|
||||
|
||||
iBuf = iStart % nBuf;
|
||||
if( iBuf ){
|
||||
int nRead = nBuf - iBuf;
|
||||
if( (iStart + nRead) > pSorter->iWriteOff ){
|
||||
nRead = (int)(pSorter->iWriteOff - iStart);
|
||||
}
|
||||
rc = sqlite3OsRead(
|
||||
pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart
|
||||
);
|
||||
assert( rc!=SQLITE_IOERR_SHORT_READ );
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
u64 nByte; /* Size of PMA in bytes */
|
||||
pIter->iEof = pSorter->iWriteOff;
|
||||
rc = vdbeSorterIterVarint(db, pIter, &nByte);
|
||||
pIter->iEof = pIter->iReadOff + nByte;
|
||||
*pnByte += nByte;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = vdbeSorterIterNext(db, pIter);
|
||||
}
|
||||
@@ -303,10 +383,10 @@ static int vdbeSorterIterInit(
|
||||
** has been allocated and contains an unpacked record that is used as key2.
|
||||
*/
|
||||
static void vdbeSorterCompare(
|
||||
VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
|
||||
const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
|
||||
int bOmitRowid, /* Ignore rowid field at end of keys */
|
||||
void *pKey1, int nKey1, /* Left side of comparison */
|
||||
void *pKey2, int nKey2, /* Right side of comparison */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2, /* Right side of comparison */
|
||||
int *pRes /* OUT: Result of comparison */
|
||||
){
|
||||
KeyInfo *pKeyInfo = pCsr->pKeyInfo;
|
||||
@@ -338,7 +418,7 @@ static void vdbeSorterCompare(
|
||||
** multiple b-tree segments. Parameter iOut is the index of the aTree[]
|
||||
** value to recalculate.
|
||||
*/
|
||||
static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
|
||||
static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
int i1;
|
||||
int i2;
|
||||
@@ -464,7 +544,7 @@ static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
|
||||
** Set *ppOut to the head of the new list.
|
||||
*/
|
||||
static void vdbeSorterMerge(
|
||||
VdbeCursor *pCsr, /* For pKeyInfo */
|
||||
const VdbeCursor *pCsr, /* For pKeyInfo */
|
||||
SorterRecord *p1, /* First list to merge */
|
||||
SorterRecord *p2, /* Second list to merge */
|
||||
SorterRecord **ppOut /* OUT: Head of merged list */
|
||||
@@ -498,7 +578,7 @@ static void vdbeSorterMerge(
|
||||
** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
|
||||
** occurs.
|
||||
*/
|
||||
static int vdbeSorterSort(VdbeCursor *pCsr){
|
||||
static int vdbeSorterSort(const VdbeCursor *pCsr){
|
||||
int i;
|
||||
SorterRecord **aSlot;
|
||||
SorterRecord *p;
|
||||
@@ -531,6 +611,91 @@ static int vdbeSorterSort(VdbeCursor *pCsr){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize a file-writer object.
|
||||
*/
|
||||
static void fileWriterInit(
|
||||
sqlite3 *db, /* Database (for malloc) */
|
||||
sqlite3_file *pFile, /* File to write to */
|
||||
FileWriter *p, /* Object to populate */
|
||||
i64 iStart /* Offset of pFile to begin writing at */
|
||||
){
|
||||
int nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
|
||||
|
||||
memset(p, 0, sizeof(FileWriter));
|
||||
p->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf);
|
||||
if( !p->aBuffer ){
|
||||
p->eFWErr = SQLITE_NOMEM;
|
||||
}else{
|
||||
p->iBufEnd = p->iBufStart = (iStart % nBuf);
|
||||
p->iWriteOff = iStart - p->iBufStart;
|
||||
p->nBuffer = nBuf;
|
||||
p->pFile = pFile;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Write nData bytes of data to the file-write object. Return SQLITE_OK
|
||||
** if successful, or an SQLite error code if an error occurs.
|
||||
*/
|
||||
static void fileWriterWrite(FileWriter *p, u8 *pData, int nData){
|
||||
int nRem = nData;
|
||||
while( nRem>0 && p->eFWErr==0 ){
|
||||
int nCopy = nRem;
|
||||
if( nCopy>(p->nBuffer - p->iBufEnd) ){
|
||||
nCopy = p->nBuffer - p->iBufEnd;
|
||||
}
|
||||
|
||||
memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy);
|
||||
p->iBufEnd += nCopy;
|
||||
if( p->iBufEnd==p->nBuffer ){
|
||||
p->eFWErr = sqlite3OsWrite(p->pFile,
|
||||
&p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
|
||||
p->iWriteOff + p->iBufStart
|
||||
);
|
||||
p->iBufStart = p->iBufEnd = 0;
|
||||
p->iWriteOff += p->nBuffer;
|
||||
}
|
||||
assert( p->iBufEnd<p->nBuffer );
|
||||
|
||||
nRem -= nCopy;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush any buffered data to disk and clean up the file-writer object.
|
||||
** The results of using the file-writer after this call are undefined.
|
||||
** Return SQLITE_OK if flushing the buffered data succeeds or is not
|
||||
** required. Otherwise, return an SQLite error code.
|
||||
**
|
||||
** Before returning, set *piEof to the offset immediately following the
|
||||
** last byte written to the file.
|
||||
*/
|
||||
static int fileWriterFinish(sqlite3 *db, FileWriter *p, i64 *piEof){
|
||||
int rc;
|
||||
if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){
|
||||
p->eFWErr = sqlite3OsWrite(p->pFile,
|
||||
&p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
|
||||
p->iWriteOff + p->iBufStart
|
||||
);
|
||||
}
|
||||
*piEof = (p->iWriteOff + p->iBufEnd);
|
||||
sqlite3DbFree(db, p->aBuffer);
|
||||
rc = p->eFWErr;
|
||||
memset(p, 0, sizeof(FileWriter));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write value iVal encoded as a varint to the file-write object. Return
|
||||
** SQLITE_OK if successful, or an SQLite error code if an error occurs.
|
||||
*/
|
||||
static void fileWriterWriteVarint(FileWriter *p, u64 iVal){
|
||||
int nByte;
|
||||
u8 aByte[10];
|
||||
nByte = sqlite3PutVarint(aByte, iVal);
|
||||
fileWriterWrite(p, aByte, nByte);
|
||||
}
|
||||
|
||||
/*
|
||||
** Write the current contents of the in-memory linked-list to a PMA. Return
|
||||
@@ -545,9 +710,12 @@ static int vdbeSorterSort(VdbeCursor *pCsr){
|
||||
** Each record consists of a varint followed by a blob of data (the
|
||||
** key). The varint is the number of bytes in the blob of data.
|
||||
*/
|
||||
static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
|
||||
static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
FileWriter writer;
|
||||
|
||||
memset(&writer, 0, sizeof(FileWriter));
|
||||
|
||||
if( pSorter->nInMemory==0 ){
|
||||
assert( pSorter->pRecord==0 );
|
||||
@@ -565,39 +733,20 @@ static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
i64 iOff = pSorter->iWriteOff;
|
||||
SorterRecord *p;
|
||||
SorterRecord *pNext = 0;
|
||||
static const char eightZeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff);
|
||||
pSorter->nPMA++;
|
||||
rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nInMemory, &iOff);
|
||||
for(p=pSorter->pRecord; rc==SQLITE_OK && p; p=pNext){
|
||||
fileWriterWriteVarint(&writer, pSorter->nInMemory);
|
||||
for(p=pSorter->pRecord; p; p=pNext){
|
||||
pNext = p->pNext;
|
||||
rc = vdbeSorterWriteVarint(pSorter->pTemp1, p->nVal, &iOff);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsWrite(pSorter->pTemp1, p->pVal, p->nVal, iOff);
|
||||
iOff += p->nVal;
|
||||
}
|
||||
|
||||
fileWriterWriteVarint(&writer, p->nVal);
|
||||
fileWriterWrite(&writer, p->pVal, p->nVal);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
|
||||
/* This assert verifies that unless an error has occurred, the size of
|
||||
** the PMA on disk is the same as the expected size stored in
|
||||
** pSorter->nInMemory. */
|
||||
assert( rc!=SQLITE_OK || pSorter->nInMemory==(
|
||||
iOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nInMemory)
|
||||
));
|
||||
|
||||
pSorter->iWriteOff = iOff;
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Terminate each file with 8 extra bytes so that from any offset
|
||||
** in the file we can always read 9 bytes without a SHORT_READ error */
|
||||
rc = sqlite3OsWrite(pSorter->pTemp1, eightZeros, 8, iOff);
|
||||
}
|
||||
pSorter->pRecord = p;
|
||||
rc = fileWriterFinish(db, &writer, &pSorter->iWriteOff);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -608,7 +757,7 @@ static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
|
||||
*/
|
||||
int sqlite3VdbeSorterWrite(
|
||||
sqlite3 *db, /* Database handle */
|
||||
VdbeCursor *pCsr, /* Sorter cursor */
|
||||
const VdbeCursor *pCsr, /* Sorter cursor */
|
||||
Mem *pVal /* Memory cell containing record */
|
||||
){
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
@@ -642,8 +791,14 @@ int sqlite3VdbeSorterWrite(
|
||||
(pSorter->nInMemory>pSorter->mxPmaSize)
|
||||
|| (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
|
||||
)){
|
||||
#ifdef SQLITE_DEBUG
|
||||
i64 nExpect = pSorter->iWriteOff
|
||||
+ sqlite3VarintLen(pSorter->nInMemory)
|
||||
+ pSorter->nInMemory;
|
||||
#endif
|
||||
rc = vdbeSorterListToPMA(db, pCsr);
|
||||
pSorter->nInMemory = 0;
|
||||
assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) );
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -654,7 +809,7 @@ int sqlite3VdbeSorterWrite(
|
||||
*/
|
||||
static int vdbeSorterInitMerge(
|
||||
sqlite3 *db, /* Database handle */
|
||||
VdbeCursor *pCsr, /* Cursor handle for this sorter */
|
||||
const VdbeCursor *pCsr, /* Cursor handle for this sorter */
|
||||
i64 *pnByte /* Sum of bytes in all opened PMAs */
|
||||
){
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
@@ -684,7 +839,7 @@ static int vdbeSorterInitMerge(
|
||||
** Once the sorter has been populated, this function is called to prepare
|
||||
** for iterating through its contents in sorted order.
|
||||
*/
|
||||
int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
|
||||
int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
int rc; /* Return code */
|
||||
sqlite3_file *pTemp2 = 0; /* Second temp file to use */
|
||||
@@ -704,7 +859,7 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
|
||||
return vdbeSorterSort(pCsr);
|
||||
}
|
||||
|
||||
/* Write the current b-tree to a PMA. Close the b-tree cursor. */
|
||||
/* Write the current in-memory list to a PMA. */
|
||||
rc = vdbeSorterListToPMA(db, pCsr);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
@@ -726,8 +881,12 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
|
||||
rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA;
|
||||
iNew++
|
||||
){
|
||||
int rc2; /* Return code from fileWriterFinish() */
|
||||
FileWriter writer; /* Object used to write to disk */
|
||||
i64 nWrite; /* Number of bytes in new PMA */
|
||||
|
||||
memset(&writer, 0, sizeof(FileWriter));
|
||||
|
||||
/* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1,
|
||||
** initialize an iterator for each of them and break out of the loop.
|
||||
** These iterators will be incrementally merged as the VDBE layer calls
|
||||
@@ -749,23 +908,20 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
|
||||
rc = vdbeSorterOpenTempFile(db, &pTemp2);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
int bEof = 0;
|
||||
fileWriterInit(db, pTemp2, &writer, iWrite2);
|
||||
fileWriterWriteVarint(&writer, nWrite);
|
||||
while( rc==SQLITE_OK && bEof==0 ){
|
||||
int nToWrite;
|
||||
VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ];
|
||||
assert( pIter->pFile );
|
||||
nToWrite = pIter->nKey + sqlite3VarintLen(pIter->nKey);
|
||||
rc = sqlite3OsWrite(pTemp2, pIter->aAlloc, nToWrite, iWrite2);
|
||||
iWrite2 += nToWrite;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
|
||||
}
|
||||
|
||||
fileWriterWriteVarint(&writer, pIter->nKey);
|
||||
fileWriterWrite(&writer, pIter->aKey, pIter->nKey);
|
||||
rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
|
||||
}
|
||||
rc2 = fileWriterFinish(db, &writer, &iWrite2);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -792,7 +948,7 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
|
||||
/*
|
||||
** Advance to the next element in the sorter.
|
||||
*/
|
||||
int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
|
||||
int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
int rc; /* Return code */
|
||||
|
||||
@@ -822,7 +978,7 @@ int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
|
||||
** current key.
|
||||
*/
|
||||
static void *vdbeSorterRowkey(
|
||||
VdbeSorter *pSorter, /* Sorter object */
|
||||
const VdbeSorter *pSorter, /* Sorter object */
|
||||
int *pnKey /* OUT: Size of current key in bytes */
|
||||
){
|
||||
void *pKey;
|
||||
@@ -841,7 +997,7 @@ static void *vdbeSorterRowkey(
|
||||
/*
|
||||
** Copy the current sorter key into the memory cell pOut.
|
||||
*/
|
||||
int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
|
||||
int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
void *pKey; int nKey; /* Sorter key to copy into pOut */
|
||||
|
||||
@@ -867,7 +1023,7 @@ int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
|
||||
** key.
|
||||
*/
|
||||
int sqlite3VdbeSorterCompare(
|
||||
VdbeCursor *pCsr, /* Sorter cursor */
|
||||
const VdbeCursor *pCsr, /* Sorter cursor */
|
||||
Mem *pVal, /* Value to compare to current sorter key */
|
||||
int *pRes /* OUT: Result of comparison */
|
||||
){
|
||||
|
||||
+1
-2
@@ -169,9 +169,8 @@ void sqlite3ExplainBegin(Vdbe *pVdbe){
|
||||
if( pVdbe ){
|
||||
Explain *p;
|
||||
sqlite3BeginBenignMalloc();
|
||||
p = sqlite3_malloc( sizeof(Explain) );
|
||||
p = (Explain *)sqlite3MallocZero( sizeof(Explain) );
|
||||
if( p ){
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->pVdbe = pVdbe;
|
||||
sqlite3_free(pVdbe->pExplain);
|
||||
pVdbe->pExplain = p;
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ void sqlite3VtabUnlock(VTable *pVTab){
|
||||
|
||||
assert( db );
|
||||
assert( pVTab->nRef>0 );
|
||||
assert( sqlite3SafetyCheckOk(db) );
|
||||
assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE );
|
||||
|
||||
pVTab->nRef--;
|
||||
if( pVTab->nRef==0 ){
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
** more index blocks.
|
||||
**
|
||||
** The wal-index header contains the total number of frames within the WAL
|
||||
** in the the mxFrame field.
|
||||
** in the mxFrame field.
|
||||
**
|
||||
** Each index block except for the first contains information on
|
||||
** HASHTABLE_NPAGE frames. The first index block contains information on
|
||||
|
||||
+9
-3
@@ -125,12 +125,18 @@ int sqlite3WalkSelect(Walker *pWalker, Select *p){
|
||||
int rc;
|
||||
if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
|
||||
rc = WRC_Continue;
|
||||
while( p ){
|
||||
pWalker->walkerDepth++;
|
||||
while( p ){
|
||||
rc = pWalker->xSelectCallback(pWalker, p);
|
||||
if( rc ) break;
|
||||
if( sqlite3WalkSelectExpr(pWalker, p) ) return WRC_Abort;
|
||||
if( sqlite3WalkSelectFrom(pWalker, p) ) return WRC_Abort;
|
||||
if( sqlite3WalkSelectExpr(pWalker, p)
|
||||
|| sqlite3WalkSelectFrom(pWalker, p)
|
||||
){
|
||||
pWalker->walkerDepth--;
|
||||
return WRC_Abort;
|
||||
}
|
||||
p = p->pPrior;
|
||||
}
|
||||
pWalker->walkerDepth--;
|
||||
return rc & WRC_Abort;
|
||||
}
|
||||
|
||||
+51
-11
@@ -3622,7 +3622,7 @@ static int codeAllEqualityTerms(
|
||||
int r1;
|
||||
int k = pIdx->aiColumn[j];
|
||||
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
|
||||
if( NEVER(pTerm==0) ) break;
|
||||
if( pTerm==0 ) break;
|
||||
/* The following true for indices with redundant columns.
|
||||
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
|
||||
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
|
||||
@@ -4297,6 +4297,8 @@ static Bitmask codeOneLoopStart(
|
||||
*/
|
||||
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
|
||||
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
|
||||
Index *pCov = 0; /* Potential covering index (or NULL) */
|
||||
int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */
|
||||
|
||||
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
|
||||
int regRowset = 0; /* Register for RowSet object */
|
||||
@@ -4315,7 +4317,7 @@ static Bitmask codeOneLoopStart(
|
||||
pLevel->op = OP_Return;
|
||||
pLevel->p1 = regReturn;
|
||||
|
||||
/* Set up a new SrcList ni pOrTab containing the table being scanned
|
||||
/* Set up a new SrcList in pOrTab containing the table being scanned
|
||||
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
|
||||
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
|
||||
*/
|
||||
@@ -4392,8 +4394,10 @@ static Bitmask codeOneLoopStart(
|
||||
/* Loop through table entries that match term pOrTerm. */
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
|
||||
WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
|
||||
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
|
||||
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
|
||||
assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
|
||||
if( pSubWInfo ){
|
||||
WhereLevel *pLvl;
|
||||
explainOneScan(
|
||||
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
|
||||
);
|
||||
@@ -4414,11 +4418,36 @@ static Bitmask codeOneLoopStart(
|
||||
*/
|
||||
if( pSubWInfo->untestedTerms ) untestedTerms = 1;
|
||||
|
||||
/* If all of the OR-connected terms are optimized using the same
|
||||
** index, and the index is opened using the same cursor number
|
||||
** by each call to sqlite3WhereBegin() made by this loop, it may
|
||||
** be possible to use that index as a covering index.
|
||||
**
|
||||
** If the call to sqlite3WhereBegin() above resulted in a scan that
|
||||
** uses an index, and this is either the first OR-connected term
|
||||
** processed or the index is the same as that used by all previous
|
||||
** terms, set pCov to the candidate covering index. Otherwise, set
|
||||
** pCov to NULL to indicate that no candidate covering index will
|
||||
** be available.
|
||||
*/
|
||||
pLvl = &pSubWInfo->a[0];
|
||||
if( (pLvl->plan.wsFlags & WHERE_INDEXED)!=0
|
||||
&& (pLvl->plan.wsFlags & WHERE_TEMP_INDEX)==0
|
||||
&& (ii==0 || pLvl->plan.u.pIdx==pCov)
|
||||
){
|
||||
assert( pLvl->iIdxCur==iCovCur );
|
||||
pCov = pLvl->plan.u.pIdx;
|
||||
}else{
|
||||
pCov = 0;
|
||||
}
|
||||
|
||||
/* Finish the loop through table entries that match term pOrTerm. */
|
||||
sqlite3WhereEnd(pSubWInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
pLevel->u.pCovidx = pCov;
|
||||
pLevel->iIdxCur = iCovCur;
|
||||
if( pAndExpr ){
|
||||
pAndExpr->pLeft = 0;
|
||||
sqlite3ExprDelete(pParse->db, pAndExpr);
|
||||
@@ -4636,7 +4665,8 @@ WhereInfo *sqlite3WhereBegin(
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
|
||||
ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
|
||||
u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */
|
||||
){
|
||||
int i; /* Loop counter */
|
||||
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
|
||||
@@ -4956,7 +4986,13 @@ WhereInfo *sqlite3WhereBegin(
|
||||
testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
|
||||
testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
|
||||
if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
|
||||
pLevel->iIdxCur = pParse->nTab++;
|
||||
if( (wctrlFlags & WHERE_ONETABLE_ONLY)
|
||||
&& (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0
|
||||
){
|
||||
pLevel->iIdxCur = iIdxCur;
|
||||
}else{
|
||||
pLevel->iIdxCur = pParse->nTab++;
|
||||
}
|
||||
}else{
|
||||
pLevel->iIdxCur = -1;
|
||||
}
|
||||
@@ -5057,10 +5093,10 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
|
||||
Index *pIx = pLevel->plan.u.pIdx;
|
||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
|
||||
int iIdxCur = pLevel->iIdxCur;
|
||||
int iIndexCur = pLevel->iIdxCur;
|
||||
assert( pIx->pSchema==pTab->pSchema );
|
||||
assert( iIdxCur>=0 );
|
||||
sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx->tnum, iDb,
|
||||
assert( iIndexCur>=0 );
|
||||
sqlite3VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb,
|
||||
(char*)pKey, P4_KEYINFO_HANDOFF);
|
||||
VdbeComment((v, "%s", pIx->zName));
|
||||
}
|
||||
@@ -5208,6 +5244,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
*/
|
||||
assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
|
||||
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
|
||||
Index *pIdx = 0;
|
||||
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
|
||||
Table *pTab = pTabItem->pTab;
|
||||
assert( pTab!=0 );
|
||||
@@ -5237,12 +5274,15 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
** that reference the table and converts them into opcodes that
|
||||
** reference the index.
|
||||
*/
|
||||
if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 && !db->mallocFailed){
|
||||
if( pLevel->plan.wsFlags & WHERE_INDEXED ){
|
||||
pIdx = pLevel->plan.u.pIdx;
|
||||
}else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
|
||||
pIdx = pLevel->u.pCovidx;
|
||||
}
|
||||
if( pIdx && !db->mallocFailed){
|
||||
int k, j, last;
|
||||
VdbeOp *pOp;
|
||||
Index *pIdx = pLevel->plan.u.pIdx;
|
||||
|
||||
assert( pIdx!=0 );
|
||||
pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
|
||||
last = sqlite3VdbeCurrentAddr(v);
|
||||
for(k=pWInfo->iTop; k<last; k++, pOp++){
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# 2012 August 23
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# This file implements tests for processing aggregate queries with
|
||||
# subqueries in which the subqueries hold the aggregate functions
|
||||
# or in which the subqueries are themselves aggregate queries
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_test aggnested-1.1 {
|
||||
db eval {
|
||||
CREATE TABLE t1(a1 INTEGER);
|
||||
INSERT INTO t1 VALUES(1), (2), (3);
|
||||
CREATE TABLE t2(b1 INTEGER);
|
||||
INSERT INTO t2 VALUES(4), (5);
|
||||
SELECT (SELECT group_concat(a1,'x') FROM t2) FROM t1;
|
||||
}
|
||||
} {1x2x3}
|
||||
do_test aggnested-1.2 {
|
||||
db eval {
|
||||
SELECT
|
||||
(SELECT group_concat(a1,'x') || '-' || group_concat(b1,'y') FROM t2)
|
||||
FROM t1;
|
||||
}
|
||||
} {1x2x3-4y5}
|
||||
do_test aggnested-1.3 {
|
||||
db eval {
|
||||
SELECT (SELECT group_concat(b1,a1) FROM t2) FROM t1;
|
||||
}
|
||||
} {415 425 435}
|
||||
do_test aggnested-1.4 {
|
||||
db eval {
|
||||
SELECT (SELECT group_concat(a1,b1) FROM t2) FROM t1;
|
||||
}
|
||||
} {151 252 353}
|
||||
|
||||
|
||||
# This test case is a copy of the one in
|
||||
# http://www.mail-archive.com/sqlite-users@sqlite.org/msg70787.html
|
||||
#
|
||||
do_test aggnested-2.0 {
|
||||
sqlite3 db2 :memory:
|
||||
db2 eval {
|
||||
CREATE TABLE t1 (A1 INTEGER NOT NULL,A2 INTEGER NOT NULL,A3 INTEGER NOT
|
||||
NULL,A4 INTEGER NOT NULL,PRIMARY KEY(A1));
|
||||
REPLACE INTO t1 VALUES(1,11,111,1111);
|
||||
REPLACE INTO t1 VALUES(2,22,222,2222);
|
||||
REPLACE INTO t1 VALUES(3,33,333,3333);
|
||||
CREATE TABLE t2 (B1 INTEGER NOT NULL,B2 INTEGER NOT NULL,B3 INTEGER NOT
|
||||
NULL,B4 INTEGER NOT NULL,PRIMARY KEY(B1));
|
||||
REPLACE INTO t2 VALUES(1,88,888,8888);
|
||||
REPLACE INTO t2 VALUES(2,99,999,9999);
|
||||
SELECT (SELECT GROUP_CONCAT(CASE WHEN a1=1 THEN'A' ELSE 'B' END) FROM t2),
|
||||
t1.*
|
||||
FROM t1;
|
||||
}
|
||||
} {A,B,B 3 33 333 3333}
|
||||
db2 close
|
||||
|
||||
finish_test
|
||||
+1
-1
@@ -119,7 +119,7 @@ do_test crash-1.11 {
|
||||
} {0 {}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# The following tests test recovery when both the database file and the the
|
||||
# The following tests test recovery when both the database file and the
|
||||
# journal file contain corrupt data. This can happen after pages are
|
||||
# written to the database file before a transaction is committed due to
|
||||
# cache-pressure.
|
||||
|
||||
+9
-5
@@ -67,7 +67,7 @@ proc do_fts3query_test {tn args} {
|
||||
foreach {k v} [lrange $args 0 [expr $nArg-3]] {
|
||||
switch -- $k {
|
||||
-deferred {
|
||||
set deferred $v
|
||||
ifcapable fts4_deferred { set deferred $v }
|
||||
}
|
||||
default {
|
||||
error "bad option \"$k\": must be -deferred"
|
||||
@@ -509,9 +509,9 @@ foreach {tn create} {
|
||||
|
||||
do_fts3query_test 3.$tn.2.1 t1 {a OR c}
|
||||
|
||||
do_test 3.$tn.3 {
|
||||
fts3_zero_long_segments t1 $limit
|
||||
} {1}
|
||||
ifcapable fts4_deferred {
|
||||
do_test 3.$tn.3 { fts3_zero_long_segments t1 $limit } {1}
|
||||
}
|
||||
|
||||
foreach {tn2 expr def} {
|
||||
1 {a NEAR c} {}
|
||||
@@ -550,7 +550,11 @@ foreach {tn create} {
|
||||
do_test 4.$tn.2 {
|
||||
set limit [fts3_make_deferrable t1 five]
|
||||
execsql { INSERT INTO t1(t1) VALUES('optimize') }
|
||||
expr {[fts3_zero_long_segments t1 $limit]>0}
|
||||
ifcapable fts4_deferred {
|
||||
expr {[fts3_zero_long_segments t1 $limit]>0}
|
||||
} else {
|
||||
expr 1
|
||||
}
|
||||
} {1}
|
||||
|
||||
do_fts3query_test 4.$tn.3.1 -deferred five t1 {one AND five}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
ifcapable !fts3 {
|
||||
ifcapable !fts3||!fts4_deferred {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
ifcapable !fts3 { finish_test ; return }
|
||||
ifcapable !fts3||!fts4_deferred {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set testprefix fts3defer2
|
||||
|
||||
|
||||
@@ -275,11 +275,14 @@ do_matchinfo_test 4.3.4 t5 {t5 MATCH 'a a a'} { s {3 1} }
|
||||
do_matchinfo_test 4.3.5 t5 {t5 MATCH '"a b" "a b"'} { s {2} }
|
||||
do_matchinfo_test 4.3.6 t5 {t5 MATCH 'a OR b'} { s {1 2 1 1} }
|
||||
|
||||
do_execsql_test 4.4.0 {
|
||||
INSERT INTO t5(t5) VALUES('optimize');
|
||||
UPDATE t5_segments
|
||||
SET block = zeroblob(length(block))
|
||||
WHERE length(block)>10000;
|
||||
do_execsql_test 4.4.0.1 { INSERT INTO t5(t5) VALUES('optimize') }
|
||||
|
||||
ifcapable fts4_deferred {
|
||||
do_execsql_test 4.4.0.2 {
|
||||
UPDATE t5_segments
|
||||
SET block = zeroblob(length(block))
|
||||
WHERE length(block)>10000;
|
||||
}
|
||||
}
|
||||
|
||||
do_matchinfo_test 4.4.2 t5 {t5 MATCH 'a b'} { s {2} }
|
||||
|
||||
+10
-8
@@ -1655,14 +1655,16 @@ do_test fts4aa-1.8 {
|
||||
SELECT docid FROM t1_docsize EXCEPT SELECT docid FROM t1
|
||||
}
|
||||
} {}
|
||||
do_test fts4aa-1.9 {
|
||||
# Note: Token 'in' is being deferred in the following query.
|
||||
db eval {
|
||||
SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1
|
||||
WHERE t1 MATCH 'joseph died in egypt'
|
||||
ORDER BY docid;
|
||||
}
|
||||
} {1050026 {4 1 1 1 1 1 1 1 2 1 1 1 1 1 1 23 23}}
|
||||
ifcapable fts4_deferred {
|
||||
do_test fts4aa-1.9 {
|
||||
# Note: Token 'in' is being deferred in the following query.
|
||||
db eval {
|
||||
SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1
|
||||
WHERE t1 MATCH 'joseph died in egypt'
|
||||
ORDER BY docid;
|
||||
}
|
||||
} {1050026 {4 1 1 1 1 1 1 1 2 1 1 1 1 1 1 23 23}}
|
||||
}
|
||||
|
||||
# Should get the same search results from FTS3
|
||||
#
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# 2012 August 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix index5
|
||||
|
||||
do_test 1.1 {
|
||||
execsql {
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(x);
|
||||
BEGIN;
|
||||
}
|
||||
for {set i 0} {$i < 100000} {incr i} {
|
||||
execsql { INSERT INTO t1 VALUES(randstr(100,100)) }
|
||||
}
|
||||
execsql COMMIT
|
||||
execsql {
|
||||
CREATE INDEX i1 ON t1(x);
|
||||
DROP INDEX I1;
|
||||
PRAGMA main.page_size;
|
||||
}
|
||||
} {1024}
|
||||
|
||||
db close
|
||||
testvfs tvfs
|
||||
tvfs filter xWrite
|
||||
tvfs script write_cb
|
||||
proc write_cb {xCall file handle iOfst} {
|
||||
if {[file tail $file]=="test.db"} {
|
||||
lappend ::write_list [expr $iOfst/1024]
|
||||
}
|
||||
puts "$xCall $file $args"
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
sqlite3 db test.db -vfs tvfs
|
||||
set ::write_list [list]
|
||||
execsql { CREATE INDEX i1 ON t1(x) }
|
||||
} {}
|
||||
|
||||
do_test 1.3 {
|
||||
set nForward 0
|
||||
set nBackward 0
|
||||
set nNoncont 0
|
||||
set iPrev [lindex $::write_list 0]
|
||||
for {set i 1} {$i < [llength $::write_list]} {incr i} {
|
||||
set iNext [lindex $::write_list $i]
|
||||
if {$iNext==($iPrev+1)} {
|
||||
incr nForward
|
||||
} elseif {$iNext==($iPrev-1)} {
|
||||
incr nBackward
|
||||
} else {
|
||||
incr nNoncont
|
||||
}
|
||||
set iPrev $iNext
|
||||
}
|
||||
|
||||
expr {$nForward > $nBackward}
|
||||
} {1}
|
||||
db close
|
||||
tvfs delete
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ do_test journal1-1.1 {
|
||||
} 8
|
||||
|
||||
# Make changes to the database and save the journal file.
|
||||
# Then delete the database. Replace the the journal file
|
||||
# Then delete the database. Replace the journal file
|
||||
# and try to create a new database with the same name. The
|
||||
# old journal should not attempt to rollback into the new
|
||||
# database.
|
||||
|
||||
@@ -111,7 +111,7 @@ set allquicktests [test_set $alltests -exclude {
|
||||
thread003.test thread004.test thread005.test trans2.test vacuum3.test
|
||||
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
|
||||
walthread.test rtree3.test indexfault.test securedel2.test
|
||||
}]
|
||||
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
|
||||
set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
|
||||
@@ -142,7 +142,7 @@ test_suite "valgrind" -prefix "" -description {
|
||||
Run the "veryquick" test suite with a couple of multi-process tests (that
|
||||
fail under valgrind) omitted.
|
||||
} -files [
|
||||
test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test
|
||||
test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test
|
||||
] -initialize {
|
||||
set ::G(valgrind) 1
|
||||
} -shutdown {
|
||||
|
||||
@@ -151,6 +151,15 @@ array set ::Configs {
|
||||
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
|
||||
-DSQLITE_MAX_ATTACHED=62
|
||||
}
|
||||
"Devkit" {
|
||||
-DSQLITE_DEFAULT_FILE_FORMAT=4
|
||||
-DSQLITE_MAX_ATTACHED=30
|
||||
-DSQLITE_ENABLE_COLUMN_METADATA
|
||||
-DSQLITE_ENABLE_FTS4
|
||||
-DSQLITE_ENABLE_FTS4_PARENTHESIS
|
||||
-DSQLITE_DISABLE_FTS4_DEFERRED
|
||||
-DSQLITE_ENABLE_RTREE
|
||||
}
|
||||
}
|
||||
|
||||
array set ::Platforms {
|
||||
@@ -166,6 +175,7 @@ array set ::Platforms {
|
||||
"Device-One" fulltest
|
||||
}
|
||||
Linux-i686 {
|
||||
"Devkit" test
|
||||
"Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
|
||||
"Device-One" test
|
||||
"Device-Two" test
|
||||
|
||||
+1
-1
@@ -657,7 +657,7 @@ do_test rowid-11.4 {
|
||||
# Test the automatic generation of rowids when the table already contains
|
||||
# a rowid with the maximum value.
|
||||
#
|
||||
# Once the the maximum rowid is taken, rowids are normally chosen at
|
||||
# Once the maximum rowid is taken, rowids are normally chosen at
|
||||
# random. By by reseting the random number generator, we can cause
|
||||
# the rowid guessing loop to collide with prior rowids, and test the
|
||||
# loop out to its limit of 100 iterations. After 100 collisions, the
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# 2012 August 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
# Tests for the secure_delete pragma.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix securedel2
|
||||
|
||||
# Generate 1000 pseudo-random 64-bit blobs.
|
||||
#
|
||||
for {set i 1} {$i <= 1000} {incr i} {
|
||||
set aBlob($i) [string range [db one {SELECT quote(randomblob(8))}] 2 end-1]
|
||||
}
|
||||
|
||||
proc detect_blob_prepare {zFile} {
|
||||
set nByte [file size $zFile]
|
||||
set ::detect_blob_data [hexio_read $zFile 0 $nByte]
|
||||
}
|
||||
|
||||
proc detect_blob {zFile iBlob} {
|
||||
if {$zFile != ""} { detect_blob_prepare $zFile }
|
||||
string match "*$::aBlob($iBlob)*" $::detect_blob_data
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
execsql { PRAGMA secure_delete = 1 }
|
||||
execsql { PRAGMA auto_vacuum = 0 }
|
||||
execsql { CREATE TABLE t1(x, y) }
|
||||
for {set i 1} {$i <= 1000} {incr i} {
|
||||
set x "X'[string repeat $aBlob($i) 1]'"
|
||||
set y "X'[string repeat $aBlob($i) 500]'"
|
||||
execsql "INSERT INTO t1 VALUES($x, $y)"
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 1.2 { detect_blob test.db 1 } {1}
|
||||
|
||||
forcecopy test.db test.db.bak
|
||||
do_execsql_test 1.3.1 { PRAGMA secure_delete = 0 } {0}
|
||||
do_execsql_test 1.3.2 { DELETE FROM t1 WHERE rowid = 1 }
|
||||
do_test 1.3.3 { detect_blob test.db 1 } {1}
|
||||
|
||||
db close
|
||||
forcecopy test.db.bak test.db
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 1.4.1 { PRAGMA secure_delete = 1 } {1}
|
||||
do_execsql_test 1.4.2 { DELETE FROM t1 WHERE rowid = 1 }
|
||||
do_test 1.4.3 { detect_blob test.db 1 } {0}
|
||||
|
||||
do_execsql_test 1.5.1 { DELETE FROM t1 WHERE rowid>850 } {}
|
||||
do_test 1.5.2 {
|
||||
set n 0
|
||||
detect_blob_prepare test.db
|
||||
for {set i 851} {$i <= 1000} {incr i 5} {
|
||||
incr n [detect_blob {} $i]
|
||||
}
|
||||
set n
|
||||
} {0}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_test 1.6.1 {
|
||||
execsql {
|
||||
PRAGMA cache_size = 200;
|
||||
PRAGMA secure_delete = 1;
|
||||
CREATE TABLE t2(x);
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
for {set i 100} {$i < 5000} {incr i} {
|
||||
execsql { INSERT INTO t2 VALUES(randomblob($i)) }
|
||||
}
|
||||
execsql { DELETE FROM t1 }
|
||||
} {}
|
||||
|
||||
do_test 1.6.2 {
|
||||
set n 0
|
||||
detect_blob_prepare test.db
|
||||
for {set i 2} {$i <= 850} {incr i 5} {
|
||||
incr n [detect_blob {} $i]
|
||||
}
|
||||
set n
|
||||
} {0}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -22,6 +22,7 @@ ifcapable !subquery {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
set ::testprefix select6
|
||||
|
||||
do_test select6-1.0 {
|
||||
execsql {
|
||||
@@ -513,5 +514,48 @@ do_test select6-9.11 {
|
||||
} {2 12 3 13 4 14}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that if a UNION ALL sub-query that would otherwise be eligible for
|
||||
# flattening consists of two or more SELECT statements that do not all
|
||||
# return the same number of result columns, the error is detected.
|
||||
#
|
||||
do_execsql_test 10.1 {
|
||||
CREATE TABLE t(i,j,k);
|
||||
CREATE TABLE j(l,m);
|
||||
CREATE TABLE k(o);
|
||||
}
|
||||
|
||||
set err [list 1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}]
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
SELECT * FROM (SELECT * FROM t), j;
|
||||
}
|
||||
do_catchsql_test 10.3 {
|
||||
SELECT * FROM t UNION ALL SELECT * FROM j
|
||||
} $err
|
||||
do_catchsql_test 10.4 {
|
||||
SELECT * FROM (SELECT i FROM t UNION ALL SELECT l, m FROM j)
|
||||
} $err
|
||||
do_catchsql_test 10.5 {
|
||||
SELECT * FROM (SELECT j FROM t UNION ALL SELECT * FROM j)
|
||||
} $err
|
||||
do_catchsql_test 10.6 {
|
||||
SELECT * FROM (SELECT * FROM t UNION ALL SELECT * FROM j)
|
||||
} $err
|
||||
do_catchsql_test 10.7 {
|
||||
SELECT * FROM (
|
||||
SELECT * FROM t UNION ALL
|
||||
SELECT l,m,l FROM j UNION ALL
|
||||
SELECT * FROM k
|
||||
)
|
||||
} $err
|
||||
do_catchsql_test 10.8 {
|
||||
SELECT * FROM (
|
||||
SELECT * FROM k UNION ALL
|
||||
SELECT * FROM t UNION ALL
|
||||
SELECT l,m,l FROM j
|
||||
)
|
||||
} $err
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+14
-10
@@ -14,6 +14,8 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix spellfix
|
||||
|
||||
ifcapable !vtab { finish_test ; return }
|
||||
|
||||
register_spellfix_module db
|
||||
|
||||
set vocab {
|
||||
@@ -66,18 +68,19 @@ do_test 1.1 {
|
||||
} {}
|
||||
|
||||
foreach {tn word res} {
|
||||
1 raxpi* {rasping 5 rasped 5 raspberry 6 rasp 4 rasps 4}
|
||||
2 ril* {rail 4 railway 4 railing 4 rails 4 railways 4}
|
||||
3 rilis* {realist 6 realistic 6 realistically 6 realists 6 realism 6}
|
||||
4 reail* {realities 3 reality 3 real 3 realest 3 realist 3}
|
||||
5 ras* {rasp 3 rash 3 rasped 3 rasping 3 rasps 3}
|
||||
1 raxpi* {rasping 5 rasped 5 ragweed 5 raspberry 6 rasp 4}
|
||||
2 ril* {rail 4 railed 4 railer 4 railers 4 railing 4}
|
||||
3 rilis* {realism 6 realist 6 realistic 6 realistically 6 realists 6}
|
||||
4 reail* {real 3 realest 3 realign 3 realigned 3 realigning 3}
|
||||
5 ras* {rascal 3 rascally 3 rascals 3 rash 3 rasher 3}
|
||||
6 realistss* {realists 8 realigns 8 realistic 9 realistically 9 realest 7}
|
||||
7 realistss {realists 8 realist 7 realigns 8 realistic 9 realest 7}
|
||||
8 rllation* {realities 9 reality 7 rallied 7 railed 4}
|
||||
9 renstom* {rainstorm 8 ransomer 6 ransom 6 ransoming 6 ransoms 6}
|
||||
9 renstom* {rainstorm 8 ransom 6 ransomer 6 ransoming 6 ransoms 6}
|
||||
} {
|
||||
do_execsql_test 1.2.$tn {
|
||||
SELECT word, matchlen FROM t1 WHERE word MATCH $word LIMIT 5
|
||||
SELECT word, matchlen FROM t1 WHERE word MATCH $word
|
||||
ORDER BY score, word LIMIT 5
|
||||
} $res
|
||||
}
|
||||
|
||||
@@ -135,12 +138,13 @@ do_test 3.2 {
|
||||
|
||||
breakpoint
|
||||
foreach {tn word res} {
|
||||
1 kos* {kosher 3 kiosk 4 kudo 2 kappa 1 keypad 1}
|
||||
2 kellj* {killjoy 5 killed 4 killingly 4 kill 4 killer 4}
|
||||
1 kos* {kosher 3 kiosk 4 kudo 2 kiss 3 kissed 3}
|
||||
2 kellj* {killjoy 5 kill 4 killed 4 killer 4 killers 4}
|
||||
3 kellj {kill 4 kills 5 killjoy 7 keel 4 killed 6}
|
||||
} {
|
||||
do_execsql_test 1.2.$tn {
|
||||
SELECT word, matchlen FROM t3 WHERE word MATCH $word LIMIT 5
|
||||
SELECT word, matchlen FROM t3 WHERE word MATCH $word
|
||||
ORDER BY score, word LIMIT 5
|
||||
} $res
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ proc incr_tvfs_hdr {file idx incrval} {
|
||||
#
|
||||
# 2. Attempt to read the database using the reader. Before the reader
|
||||
# has a chance to snapshot the wal-index header, increment one
|
||||
# of the the integer fields (so that the reader ends up with a corrupted
|
||||
# of the integer fields (so that the reader ends up with a corrupted
|
||||
# header).
|
||||
#
|
||||
# 3. Check that the reader recovers the wal-index and reads the correct
|
||||
|
||||
@@ -56,6 +56,7 @@ do_multiclient_test tn {
|
||||
do_test 1.1.1 {
|
||||
code2 { sqlite3 db2 test.db }
|
||||
sql2 {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE t1(x, y);
|
||||
INSERT INTO t1 VALUES('a', 'b');
|
||||
@@ -268,6 +269,7 @@ do_multiclient_test tn {
|
||||
tv filter {}
|
||||
code1 { sqlite3 db test.db }
|
||||
csql1 {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA journal_mode = WAL;
|
||||
BEGIN;
|
||||
CREATE TABLE t2(x, y);
|
||||
|
||||
+2
-2
@@ -277,8 +277,8 @@ do_thread_test2 walthread-1 -seconds $seconds(walthread-1) -init {
|
||||
proc write_transaction {} {
|
||||
db eval {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(randomblob(100));
|
||||
INSERT INTO t1 VALUES(randomblob(100));
|
||||
INSERT INTO t1 VALUES(randomblob(101 + $::E(pid)));
|
||||
INSERT INTO t1 VALUES(randomblob(101 + $::E(pid)));
|
||||
INSERT INTO t1 SELECT md5sum(x) FROM t1;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
# 2012 August 24
|
||||
#
|
||||
# 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 that an index may be used as a covering
|
||||
# index when there are OR expressions in the WHERE clause.
|
||||
#
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix whereD
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t(i,j,k,m,n);
|
||||
CREATE INDEX ijk ON t(i,j,k);
|
||||
CREATE INDEX jmn ON t(j,m,n);
|
||||
|
||||
INSERT INTO t VALUES(3, 3, 'three', 3, 'tres');
|
||||
INSERT INTO t VALUES(2, 2, 'two', 2, 'dos');
|
||||
INSERT INTO t VALUES(1, 1, 'one', 1, 'uno');
|
||||
INSERT INTO t VALUES(4, 4, 'four', 4, 'cuatro');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT k FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2);
|
||||
} {one two}
|
||||
do_execsql_test 1.3 {
|
||||
SELECT k FROM t WHERE (i=1 AND j=1) OR (+i=2 AND j=2);
|
||||
} {one two}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT n FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2);
|
||||
} {uno dos}
|
||||
do_execsql_test 1.5 {
|
||||
SELECT k, n FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2);
|
||||
} {one uno two dos}
|
||||
do_execsql_test 1.6 {
|
||||
SELECT k FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2) OR (i=3 AND j=3);
|
||||
} {one two three}
|
||||
do_execsql_test 1.7 {
|
||||
SELECT n FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2) OR (i=3 AND j=3);
|
||||
} {uno dos tres}
|
||||
do_execsql_test 1.8 {
|
||||
SELECT k FROM t WHERE (i=1 AND j=1) OR (j=2 AND m=2);
|
||||
} {one two}
|
||||
do_execsql_test 1.9 {
|
||||
SELECT k FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2) OR (j=3 AND m=3);
|
||||
} {one two three}
|
||||
do_execsql_test 1.10 {
|
||||
SELECT n FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2) OR (j=3 AND m=3);
|
||||
} {uno dos tres}
|
||||
do_execsql_test 1.11 {
|
||||
SELECT k FROM t WHERE (i=1 AND j=1) OR (j=2 AND m=2) OR (i=3 AND j=3);
|
||||
} {one two three}
|
||||
do_execsql_test 1.12 {
|
||||
SELECT n FROM t WHERE (i=1 AND j=1) OR (j=2 AND m=2) OR (i=3 AND j=3);
|
||||
} {uno dos tres}
|
||||
do_execsql_test 1.13 {
|
||||
SELECT k FROM t WHERE (j=1 AND m=1) OR (i=2 AND j=2) OR (i=3 AND j=3);
|
||||
} {one two three}
|
||||
do_execsql_test 1.14 {
|
||||
SELECT k FROM t WHERE (i=1 AND j=1) OR (j=2 AND i=2) OR (i=3 AND j=3);
|
||||
} {one two three}
|
||||
do_execsql_test 1.15 {
|
||||
SELECT k FROM t WHERE (i=1 AND j=2) OR (i=2 AND j=1) OR (i=3 AND j=4);
|
||||
} {}
|
||||
do_execsql_test 1.16 {
|
||||
SELECT k FROM t WHERE (i=1 AND (j=1 or j=2)) OR (i=3 AND j=3);
|
||||
} {one three}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a,b,c,d);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
CREATE INDEX t1d ON t1(d);
|
||||
CREATE TABLE t2(x,y);
|
||||
CREATE INDEX t2y ON t2(y);
|
||||
|
||||
INSERT INTO t1 VALUES(1,2,3,4);
|
||||
INSERT INTO t1 VALUES(5,6,7,8);
|
||||
INSERT INTO t2 VALUES(1,2);
|
||||
INSERT INTO t2 VALUES(2,7);
|
||||
INSERT INTO t2 VALUES(3,4);
|
||||
} {}
|
||||
do_execsql_test 2.1 {
|
||||
SELECT a, x FROM t1 JOIN t2 ON +y=d OR x=7 ORDER BY a, x;
|
||||
} {1 3}
|
||||
do_execsql_test 2.2 {
|
||||
SELECT a, x FROM t1 JOIN t2 ON y=d OR x=7 ORDER BY a, x;
|
||||
} {1 3}
|
||||
|
||||
|
||||
# Similar to [do_execsql_test], except that two elements are appended
|
||||
# to the result - the string "search" and the number of times test variable
|
||||
# sqlite3_search_count is incremented by running the supplied SQL. e.g.
|
||||
#
|
||||
# do_searchcount_test 1.0 { SELECT * FROM t1 } {x y search 2}
|
||||
#
|
||||
proc do_searchcount_test {tn sql res} {
|
||||
uplevel [subst -nocommands {
|
||||
do_test $tn {
|
||||
set ::sqlite_search_count 0
|
||||
concat [db eval {$sql}] search [set ::sqlite_search_count]
|
||||
} [list $res]
|
||||
}]
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t3(a, b, c);
|
||||
CREATE UNIQUE INDEX i3 ON t3(a, b);
|
||||
INSERT INTO t3 VALUES(1, 'one', 'i');
|
||||
INSERT INTO t3 VALUES(3, 'three', 'iii');
|
||||
INSERT INTO t3 VALUES(6, 'six', 'vi');
|
||||
INSERT INTO t3 VALUES(2, 'two', 'ii');
|
||||
INSERT INTO t3 VALUES(4, 'four', 'iv');
|
||||
INSERT INTO t3 VALUES(5, 'five', 'v');
|
||||
|
||||
CREATE TABLE t4(x PRIMARY KEY, y);
|
||||
INSERT INTO t4 VALUES('a', 'one');
|
||||
INSERT INTO t4 VALUES('b', 'two');
|
||||
}
|
||||
|
||||
do_searchcount_test 3.1 {
|
||||
SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR (a=2 AND b='two')
|
||||
} {1 one 2 two search 2}
|
||||
|
||||
do_searchcount_test 3.2 {
|
||||
SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR (a=2 AND b='two')
|
||||
} {1 i 2 ii search 4}
|
||||
|
||||
do_searchcount_test 3.4.1 {
|
||||
SELECT y FROM t4 WHERE x='a'
|
||||
} {one search 2}
|
||||
do_searchcount_test 3.4.2 {
|
||||
SELECT a, b FROM t3 WHERE
|
||||
(a=1 AND b=(SELECT y FROM t4 WHERE x='a'))
|
||||
OR (a=2 AND b='two')
|
||||
} {1 one 2 two search 4}
|
||||
do_searchcount_test 3.4.3 {
|
||||
SELECT a, b FROM t3 WHERE
|
||||
(a=2 AND b='two')
|
||||
OR (a=1 AND b=(SELECT y FROM t4 WHERE x='a'))
|
||||
} {2 two 1 one search 4}
|
||||
do_searchcount_test 3.4.4 {
|
||||
SELECT a, b FROM t3 WHERE
|
||||
(a=2 AND b=(SELECT y FROM t4 WHERE x='b'))
|
||||
OR (a=1 AND b=(SELECT y FROM t4 WHERE x='a'))
|
||||
} {2 two 1 one search 6}
|
||||
|
||||
do_searchcount_test 3.5.1 {
|
||||
SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4
|
||||
} {1 one 2 two search 2}
|
||||
do_searchcount_test 3.5.2 {
|
||||
SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4
|
||||
} {1 i 2 ii search 2}
|
||||
|
||||
finish_test
|
||||
Executable
+394
@@ -0,0 +1,394 @@
|
||||
@ECHO OFF
|
||||
|
||||
::
|
||||
:: build-all-msvc.bat --
|
||||
::
|
||||
:: Multi-Platform Build Tool for MSVC
|
||||
::
|
||||
|
||||
SETLOCAL
|
||||
|
||||
REM SET __ECHO=ECHO
|
||||
REM SET __ECHO2=ECHO
|
||||
IF NOT DEFINED _AECHO (SET _AECHO=REM)
|
||||
IF NOT DEFINED _CECHO (SET _CECHO=REM)
|
||||
IF NOT DEFINED _VECHO (SET _VECHO=REM)
|
||||
|
||||
%_AECHO% Running %0 %*
|
||||
|
||||
REM SET DFLAGS=/L
|
||||
|
||||
%_VECHO% DFlags = '%DFLAGS%'
|
||||
|
||||
SET FFLAGS=/V /F /G /H /I /R /Y /Z
|
||||
|
||||
%_VECHO% FFlags = '%FFLAGS%'
|
||||
|
||||
SET ROOT=%~dp0\..
|
||||
SET ROOT=%ROOT:\\=\%
|
||||
|
||||
%_VECHO% Root = '%ROOT%'
|
||||
|
||||
REM
|
||||
REM NOTE: The first and only argument to this batch file should be the output
|
||||
REM directory where the platform-specific binary directories should be
|
||||
REM created.
|
||||
REM
|
||||
SET BINARYDIRECTORY=%1
|
||||
|
||||
IF NOT DEFINED BINARYDIRECTORY (
|
||||
GOTO usage
|
||||
)
|
||||
|
||||
%_VECHO% BinaryDirectory = '%BINARYDIRECTORY%'
|
||||
|
||||
SET DUMMY=%2
|
||||
|
||||
IF DEFINED DUMMY (
|
||||
GOTO usage
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: From this point, we need a clean error level. Reset it now.
|
||||
REM
|
||||
CALL :fn_ResetErrorLevel
|
||||
|
||||
REM
|
||||
REM NOTE: Change the current directory to the root of the source tree, saving
|
||||
REM the current directory on the directory stack.
|
||||
REM
|
||||
%__ECHO2% PUSHD "%ROOT%"
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Could not change directory to "%ROOT%".
|
||||
GOTO errors
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: This batch file requires the ComSpec environment variable to be set,
|
||||
REM typically to something like "C:\Windows\System32\cmd.exe".
|
||||
REM
|
||||
IF NOT DEFINED ComSpec (
|
||||
ECHO The ComSpec environment variable must be defined.
|
||||
GOTO errors
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: This batch file requires the VcInstallDir environment variable to be
|
||||
REM set. Tyipcally, this means this batch file needs to be run from an
|
||||
REM MSVC command prompt.
|
||||
REM
|
||||
IF NOT DEFINED VCINSTALLDIR (
|
||||
ECHO The VCINSTALLDIR environment variable must be defined.
|
||||
GOTO errors
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: If the list of platforms is not already set, use the default list.
|
||||
REM
|
||||
IF NOT DEFINED PLATFORMS (
|
||||
SET PLATFORMS=x86 x86_amd64 x86_arm
|
||||
)
|
||||
|
||||
%_VECHO% Platforms = '%PLATFORMS%'
|
||||
|
||||
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
|
||||
REM directories.
|
||||
REM
|
||||
SET x86_NAME=x86
|
||||
SET x86_amd64_NAME=x64
|
||||
SET x86_arm_NAME=ARM
|
||||
|
||||
%_VECHO% x86_Name = '%x86_NAME%'
|
||||
%_VECHO% x86_amd64_Name = '%x86_amd64_NAME%'
|
||||
%_VECHO% x86_arm_Name = '%x86_arm_NAME%'
|
||||
|
||||
REM
|
||||
REM NOTE: Check for the external tools needed during the build process ^(i.e.
|
||||
REM those that do not get compiled as part of the build process itself^)
|
||||
REM along the PATH.
|
||||
REM
|
||||
FOR %%T IN (gawk.exe tclsh85.exe) DO (
|
||||
SET %%T_PATH=%%~dp$PATH:T
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Set the TOOLPATH variable to contain all the directories where the
|
||||
REM external tools were found in the search above.
|
||||
REM
|
||||
SET TOOLPATH=%gawk.exe_PATH%;%tclsh85.exe_PATH%
|
||||
|
||||
%_VECHO% ToolPath = '%TOOLPATH%'
|
||||
|
||||
REM
|
||||
REM NOTE: Check for MSVC 2012 because the Windows SDK directory handling is
|
||||
REM slightly different for that version.
|
||||
REM
|
||||
IF "%VisualStudioVersion%" == "11.0" (
|
||||
SET SET_NSDKLIBPATH=1
|
||||
) ELSE (
|
||||
CALL :fn_UnsetVariable SET_NSDKLIBPATH
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: This is the outer loop. There should be exactly one iteration per
|
||||
REM platform.
|
||||
REM
|
||||
FOR %%P IN (%PLATFORMS%) DO (
|
||||
REM
|
||||
REM NOTE: Using the MSVC platform name, lookup the simpler platform name to
|
||||
REM be used for the name of the platform-specific binary directory via
|
||||
REM the environment variables setup earlier.
|
||||
REM
|
||||
CALL :fn_SetVariable %%P_NAME PLATFORMNAME
|
||||
|
||||
REM
|
||||
REM NOTE: This is the inner loop. There should be exactly one iteration.
|
||||
REM This loop is necessary because the PlatformName environment
|
||||
REM variable was set above and that value is needed by some of the
|
||||
REM commands contained in the inner loop. If these commands were
|
||||
REM directly contained in the outer loop, the PlatformName environment
|
||||
REM variable would be stuck with its initial empty value instead.
|
||||
REM
|
||||
FOR /F "tokens=2* delims==" %%D IN ('SET PLATFORMNAME') DO (
|
||||
REM
|
||||
REM NOTE: Attempt to clean the environment of all variables used by MSVC
|
||||
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 DevEnvDir
|
||||
CALL :fn_UnsetVariable ExtensionSdkDir
|
||||
CALL :fn_UnsetVariable Framework35Version
|
||||
CALL :fn_UnsetVariable FrameworkDir
|
||||
CALL :fn_UnsetVariable FrameworkDir32
|
||||
CALL :fn_UnsetVariable FrameworkVersion
|
||||
CALL :fn_UnsetVariable FrameworkVersion32
|
||||
CALL :fn_UnsetVariable FSHARPINSTALLDIR
|
||||
CALL :fn_UnsetVariable INCLUDE
|
||||
CALL :fn_UnsetVariable LIB
|
||||
CALL :fn_UnsetVariable LIBPATH
|
||||
CALL :fn_UnsetVariable Platform
|
||||
REM CALL :fn_UnsetVariable VCINSTALLDIR
|
||||
CALL :fn_UnsetVariable VSINSTALLDIR
|
||||
CALL :fn_UnsetVariable WindowsSdkDir
|
||||
CALL :fn_UnsetVariable WindowsSdkDir_35
|
||||
CALL :fn_UnsetVariable WindowsSdkDir_old
|
||||
|
||||
REM
|
||||
REM NOTE: Reset the PATH here to the absolute bare minimum required.
|
||||
REM
|
||||
SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
|
||||
|
||||
REM
|
||||
REM NOTE: Launch a nested command shell to perform the following steps:
|
||||
REM
|
||||
REM 1. Setup the MSVC environment for this platform using the
|
||||
REM official batch file.
|
||||
REM
|
||||
REM 2. Make sure that no stale build output files are present.
|
||||
REM
|
||||
REM 3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this
|
||||
REM platform.
|
||||
REM
|
||||
REM 4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this
|
||||
REM platform to the platform-specific directory beneath the
|
||||
REM binary directory.
|
||||
REM
|
||||
"%ComSpec%" /C (
|
||||
REM
|
||||
REM NOTE: Attempt to setup the MSVC environment for this platform.
|
||||
REM
|
||||
%__ECHO% CALL "%VCINSTALLDIR%\vcvarsall.bat" %%P
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Failed to call "%VCINSTALLDIR%\vcvarsall.bat" for platform %%P.
|
||||
GOTO errors
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: If this batch file is not running in "what-if" mode, check to
|
||||
REM be sure we were actually able to setup the MSVC environment as
|
||||
REM current versions of their official batch file do not set the
|
||||
REM exit code upon failure.
|
||||
REM
|
||||
IF NOT DEFINED __ECHO (
|
||||
IF NOT DEFINED WindowsSdkDir (
|
||||
ECHO Cannot build, Windows SDK not found for platform %%P.
|
||||
GOTO errors
|
||||
)
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: When using MSVC 2012, the native SDK path cannot simply use
|
||||
REM the "lib" sub-directory beneath the location specified in the
|
||||
REM WindowsSdkDir environment variable because that location does
|
||||
REM not actually contain the necessary library files for x86.
|
||||
REM This must be done for each iteration because it relies upon
|
||||
REM the WindowsSdkDir environment variable being set by the batch
|
||||
REM file used to setup the MSVC environment.
|
||||
REM
|
||||
IF DEFINED SET_NSDKLIBPATH (
|
||||
CALL :fn_SetVariable WindowsSdkDir NSDKLIBPATH
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC
|
||||
REM makefile to clean any stale build output from previous
|
||||
REM iterations of this loop and/or previous runs of this batch
|
||||
REM file, etc.
|
||||
REM
|
||||
IF NOT DEFINED NOCLEAN (
|
||||
%__ECHO% nmake -f Makefile.msc clean
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Failed to clean for platform %%P.
|
||||
GOTO errors
|
||||
)
|
||||
) ELSE (
|
||||
REM
|
||||
REM NOTE: Even when the cleaning step has been disabled, we still need
|
||||
REM to remove the build output for the files we are specifically
|
||||
REM wanting to build for each platform.
|
||||
REM
|
||||
%__ECHO% DEL /Q sqlite3.dll sqlite3.lib sqlite3.pdb
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Invoke NMAKE with the MSVC makefile to build the "sqlite3.dll"
|
||||
REM binary. The x86 compiler will be used to compile the native
|
||||
REM command line tools needed during the build process itself.
|
||||
REM Also, disable looking for and/or linking to the native Tcl
|
||||
REM runtime library.
|
||||
REM
|
||||
%__ECHO% nmake -f Makefile.msc sqlite3.dll "NCC=""%VCINSTALLDIR%\bin\cl.exe""" USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Failed to build "sqlite3.dll" for platform %%P.
|
||||
GOTO errors
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Copy the "sqlite3.dll" file to the platform-specific directory
|
||||
REM beneath the binary directory.
|
||||
REM
|
||||
%__ECHO% XCOPY sqlite3.dll "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS%
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Failed to copy "sqlite3.dll" to "%BINARYDIRECTORY%\%%D\".
|
||||
GOTO errors
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Copy the "sqlite3.lib" file to the platform-specific directory
|
||||
REM beneath the binary directory.
|
||||
REM
|
||||
%__ECHO% XCOPY sqlite3.lib "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS%
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Failed to copy "sqlite3.lib" to "%BINARYDIRECTORY%\%%D\".
|
||||
GOTO errors
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Copy the "sqlite3.pdb" file to the platform-specific directory
|
||||
REM beneath the binary directory unless we are prevented from doing
|
||||
REM so.
|
||||
REM
|
||||
IF NOT DEFINED NOSYMBOLS (
|
||||
%__ECHO% XCOPY sqlite3.pdb "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS%
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Failed to copy "sqlite3.pdb" to "%BINARYDIRECTORY%\%%D\".
|
||||
GOTO errors
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Handle any errors generated during the nested command shell.
|
||||
REM
|
||||
IF ERRORLEVEL 1 (
|
||||
GOTO errors
|
||||
)
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Restore the saved current directory from the directory stack.
|
||||
REM
|
||||
%__ECHO2% POPD
|
||||
|
||||
IF ERRORLEVEL 1 (
|
||||
ECHO Could not restore directory.
|
||||
GOTO errors
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: If we get to this point, we have succeeded.
|
||||
REM
|
||||
GOTO no_errors
|
||||
|
||||
:fn_ResetErrorLevel
|
||||
VERIFY > NUL
|
||||
GOTO :EOF
|
||||
|
||||
:fn_SetErrorLevel
|
||||
VERIFY MAYBE 2> NUL
|
||||
GOTO :EOF
|
||||
|
||||
:fn_SetVariable
|
||||
SETLOCAL
|
||||
IF NOT DEFINED %1 GOTO :EOF
|
||||
IF "%2" == "" GOTO :EOF
|
||||
SET __ECHO_CMD=ECHO %%%1%%
|
||||
FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
|
||||
SET VALUE=%%V
|
||||
)
|
||||
ENDLOCAL && SET %2=%VALUE%
|
||||
GOTO :EOF
|
||||
|
||||
:fn_UnsetVariable
|
||||
IF NOT "%1" == "" (
|
||||
SET %1=
|
||||
CALL :fn_ResetErrorLevel
|
||||
)
|
||||
GOTO :EOF
|
||||
|
||||
:fn_AppendVariable
|
||||
SET __ECHO_CMD=ECHO %%%1%%
|
||||
IF DEFINED %1 (
|
||||
FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
|
||||
SET %1=%%V%~2
|
||||
)
|
||||
) ELSE (
|
||||
SET %1=%~2
|
||||
)
|
||||
SET __ECHO_CMD=
|
||||
CALL :fn_ResetErrorLevel
|
||||
GOTO :EOF
|
||||
|
||||
:usage
|
||||
ECHO.
|
||||
ECHO Usage: %~nx0 ^<binaryDirectory^>
|
||||
ECHO.
|
||||
GOTO errors
|
||||
|
||||
:errors
|
||||
CALL :fn_SetErrorLevel
|
||||
ENDLOCAL
|
||||
ECHO.
|
||||
ECHO Failure, errors were encountered.
|
||||
GOTO end_of_file
|
||||
|
||||
:no_errors
|
||||
CALL :fn_ResetErrorLevel
|
||||
ENDLOCAL
|
||||
ECHO.
|
||||
ECHO Success, no errors were encountered.
|
||||
GOTO end_of_file
|
||||
|
||||
:end_of_file
|
||||
%__ECHO% EXIT /B %ERRORLEVEL%
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
** This program checks for formatting problems in source code:
|
||||
**
|
||||
** * Any use of tab characters
|
||||
** * White space at the end of a line
|
||||
** * Blank lines at the end of a file
|
||||
**
|
||||
** Any violations are reported.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CR_OK 0x001
|
||||
#define WSEOL_OK 0x002
|
||||
|
||||
static void checkSpacing(const char *zFile, unsigned flags){
|
||||
FILE *in = fopen(zFile, "rb");
|
||||
int i;
|
||||
int seenSpace;
|
||||
int seenTab;
|
||||
int ln = 0;
|
||||
int lastNonspace = 0;
|
||||
char zLine[2000];
|
||||
if( in==0 ){
|
||||
printf("cannot open %s\n", zFile);
|
||||
return;
|
||||
}
|
||||
while( fgets(zLine, sizeof(zLine), in) ){
|
||||
seenSpace = 0;
|
||||
seenTab = 0;
|
||||
ln++;
|
||||
for(i=0; zLine[i]; i++){
|
||||
if( zLine[i]=='\t' && seenTab==0 ){
|
||||
printf("%s:%d: tab (\\t) character\n", zFile, ln);
|
||||
seenTab = 1;
|
||||
}else if( zLine[i]=='\r' ){
|
||||
if( (flags & CR_OK)==0 ){
|
||||
printf("%s:%d: carriage-return (\\r) character\n", zFile, ln);
|
||||
}
|
||||
}else if( zLine[i]==' ' ){
|
||||
seenSpace = 1;
|
||||
}else if( zLine[i]!='\n' ){
|
||||
lastNonspace = ln;
|
||||
seenSpace = 0;
|
||||
}
|
||||
}
|
||||
if( seenSpace && (flags & WSEOL_OK)==0 ){
|
||||
printf("%s:%d: whitespace at end-of-line\n", zFile, ln);
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
if( lastNonspace<ln ){
|
||||
printf("%s:%d: blank lines at end of file (%d)\n",
|
||||
zFile, ln, ln - lastNonspace);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int i;
|
||||
unsigned flags = WSEOL_OK;
|
||||
for(i=1; i<argc; i++){
|
||||
const char *z = argv[i];
|
||||
if( z[0]=='-' ){
|
||||
while( z[0]=='-' ) z++;
|
||||
if( strcmp(z,"crok")==0 ){
|
||||
flags |= CR_OK;
|
||||
}else if( strcmp(z, "wseol")==0 ){
|
||||
flags &= ~WSEOL_OK;
|
||||
}else if( strcmp(z, "help")==0 ){
|
||||
printf("Usage: %s [options] FILE ...\n", argv[0]);
|
||||
printf(" --crok Do not report on carriage-returns\n");
|
||||
printf(" --wseol Complain about whitespace at end-of-line\n");
|
||||
printf(" --help This message\n");
|
||||
}else{
|
||||
printf("unknown command-line option: [%s]\n", argv[i]);
|
||||
printf("use --help for additional information\n");
|
||||
}
|
||||
}else{
|
||||
checkSpacing(argv[i], flags);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+39
-39
@@ -15,7 +15,7 @@
|
||||
|
||||
#ifndef __WIN32__
|
||||
# if defined(_WIN32) || defined(WIN32)
|
||||
# define __WIN32__
|
||||
# define __WIN32__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -653,7 +653,7 @@ void FindRulePrecedences(struct lemon *xp)
|
||||
}
|
||||
}else if( sp->prec>=0 ){
|
||||
rp->precsym = rp->rhs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,12 +711,12 @@ void FindFirstSets(struct lemon *lemp)
|
||||
progress += SetAdd(s1->firstset,s2->subsym[j]->index);
|
||||
}
|
||||
break;
|
||||
}else if( s1==s2 ){
|
||||
}else if( s1==s2 ){
|
||||
if( s1->lambda==LEMON_FALSE ) break;
|
||||
}else{
|
||||
}else{
|
||||
progress += SetUnion(s1->firstset,s2->firstset);
|
||||
if( s2->lambda==LEMON_FALSE ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}while( progress );
|
||||
@@ -959,8 +959,8 @@ void FindFollowSets(struct lemon *lemp)
|
||||
if( change ){
|
||||
plp->cfp->status = INCOMPLETE;
|
||||
progress = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cfp->status = COMPLETE;
|
||||
}
|
||||
}
|
||||
@@ -993,7 +993,7 @@ void FindActions(struct lemon *lemp)
|
||||
** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
|
||||
Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1262,11 +1262,11 @@ void Configlist_closure(struct lemon *lemp)
|
||||
SetAdd(newcfp->fws, xsp->subsym[k]->index);
|
||||
}
|
||||
break;
|
||||
}else{
|
||||
}else{
|
||||
SetUnion(newcfp->fws,xsp->firstset);
|
||||
if( xsp->lambda==LEMON_FALSE ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
|
||||
}
|
||||
}
|
||||
@@ -1996,7 +1996,7 @@ static void parseonetoken(struct pstate *psp)
|
||||
"There is no prior rule upon which to attach the code \
|
||||
fragment which begins on this line.");
|
||||
psp->errorcnt++;
|
||||
}else if( psp->prevrule->code!=0 ){
|
||||
}else if( psp->prevrule->code!=0 ){
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Code fragment beginning on this line is not the first \
|
||||
to follow the previous rule.");
|
||||
@@ -2004,7 +2004,7 @@ to follow the previous rule.");
|
||||
}else{
|
||||
psp->prevrule->line = psp->tokenlineno;
|
||||
psp->prevrule->code = &x[1];
|
||||
}
|
||||
}
|
||||
}else if( x[0]=='[' ){
|
||||
psp->state = PRECEDENCE_MARK_1;
|
||||
}else{
|
||||
@@ -2097,7 +2097,7 @@ to follow the previous rule.");
|
||||
"Can't allocate enough memory for this rule.");
|
||||
psp->errorcnt++;
|
||||
psp->prevrule = 0;
|
||||
}else{
|
||||
}else{
|
||||
int i;
|
||||
rp->ruleline = psp->tokenlineno;
|
||||
rp->rhs = (struct symbol**)&rp[1];
|
||||
@@ -2105,7 +2105,7 @@ to follow the previous rule.");
|
||||
for(i=0; i<psp->nrhs; i++){
|
||||
rp->rhs[i] = psp->rhs[i];
|
||||
rp->rhsalias[i] = psp->alias[i];
|
||||
}
|
||||
}
|
||||
rp->lhs = psp->lhs;
|
||||
rp->lhsalias = psp->lhsalias;
|
||||
rp->nrhs = psp->nrhs;
|
||||
@@ -2117,12 +2117,12 @@ to follow the previous rule.");
|
||||
rp->next = 0;
|
||||
if( psp->firstrule==0 ){
|
||||
psp->firstrule = psp->lastrule = rp;
|
||||
}else{
|
||||
}else{
|
||||
psp->lastrule->next = rp;
|
||||
psp->lastrule = rp;
|
||||
}
|
||||
}
|
||||
psp->prevrule = rp;
|
||||
}
|
||||
}
|
||||
psp->state = WAITING_FOR_DECL_OR_RULE;
|
||||
}else if( isalpha(x[0]) ){
|
||||
if( psp->nrhs>=MAXRHS ){
|
||||
@@ -2131,11 +2131,11 @@ to follow the previous rule.");
|
||||
x);
|
||||
psp->errorcnt++;
|
||||
psp->state = RESYNC_AFTER_RULE_ERROR;
|
||||
}else{
|
||||
}else{
|
||||
psp->rhs[psp->nrhs] = Symbol_new(x);
|
||||
psp->alias[psp->nrhs] = 0;
|
||||
psp->nrhs++;
|
||||
}
|
||||
}
|
||||
}else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
|
||||
struct symbol *msp = psp->rhs[psp->nrhs-1];
|
||||
if( msp->type!=MULTITERMINAL ){
|
||||
@@ -2199,24 +2199,24 @@ to follow the previous rule.");
|
||||
if( strcmp(x,"name")==0 ){
|
||||
psp->declargslot = &(psp->gp->name);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"include")==0 ){
|
||||
}else if( strcmp(x,"include")==0 ){
|
||||
psp->declargslot = &(psp->gp->include);
|
||||
}else if( strcmp(x,"code")==0 ){
|
||||
}else if( strcmp(x,"code")==0 ){
|
||||
psp->declargslot = &(psp->gp->extracode);
|
||||
}else if( strcmp(x,"token_destructor")==0 ){
|
||||
}else if( strcmp(x,"token_destructor")==0 ){
|
||||
psp->declargslot = &psp->gp->tokendest;
|
||||
}else if( strcmp(x,"default_destructor")==0 ){
|
||||
}else if( strcmp(x,"default_destructor")==0 ){
|
||||
psp->declargslot = &psp->gp->vardest;
|
||||
}else if( strcmp(x,"token_prefix")==0 ){
|
||||
}else if( strcmp(x,"token_prefix")==0 ){
|
||||
psp->declargslot = &psp->gp->tokenprefix;
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"syntax_error")==0 ){
|
||||
}else if( strcmp(x,"syntax_error")==0 ){
|
||||
psp->declargslot = &(psp->gp->error);
|
||||
}else if( strcmp(x,"parse_accept")==0 ){
|
||||
}else if( strcmp(x,"parse_accept")==0 ){
|
||||
psp->declargslot = &(psp->gp->accept);
|
||||
}else if( strcmp(x,"parse_failure")==0 ){
|
||||
}else if( strcmp(x,"parse_failure")==0 ){
|
||||
psp->declargslot = &(psp->gp->failure);
|
||||
}else if( strcmp(x,"stack_overflow")==0 ){
|
||||
}else if( strcmp(x,"stack_overflow")==0 ){
|
||||
psp->declargslot = &(psp->gp->overflow);
|
||||
}else if( strcmp(x,"extra_argument")==0 ){
|
||||
psp->declargslot = &(psp->gp->arg);
|
||||
@@ -2245,9 +2245,9 @@ to follow the previous rule.");
|
||||
psp->preccounter++;
|
||||
psp->declassoc = NONE;
|
||||
psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
|
||||
}else if( strcmp(x,"destructor")==0 ){
|
||||
}else if( strcmp(x,"destructor")==0 ){
|
||||
psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
|
||||
}else if( strcmp(x,"type")==0 ){
|
||||
}else if( strcmp(x,"type")==0 ){
|
||||
psp->state = WAITING_FOR_DATATYPE_SYMBOL;
|
||||
}else if( strcmp(x,"fallback")==0 ){
|
||||
psp->fallback = 0;
|
||||
@@ -2259,7 +2259,7 @@ to follow the previous rule.");
|
||||
"Unknown declaration keyword: \"%%%s\".",x);
|
||||
psp->errorcnt++;
|
||||
psp->state = RESYNC_AFTER_DECL_ERROR;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Illegal declaration keyword: \"%s\".",x);
|
||||
@@ -2314,10 +2314,10 @@ to follow the previous rule.");
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Symbol \"%s\" has already be given a precedence.",x);
|
||||
psp->errorcnt++;
|
||||
}else{
|
||||
}else{
|
||||
sp->prec = psp->preccounter;
|
||||
sp->assoc = psp->declassoc;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Can't assign a precedence to \"%s\".",x);
|
||||
@@ -2587,12 +2587,12 @@ void Parse(struct lemon *gp)
|
||||
if( c=='\n' ) lineno++;
|
||||
prevc = c;
|
||||
cp++;
|
||||
}
|
||||
}else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
|
||||
}
|
||||
}else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
|
||||
cp = &cp[2];
|
||||
while( (c= *cp)!=0 && c!='\n' ) cp++;
|
||||
if( c ) lineno++;
|
||||
}else if( c=='\'' || c=='\"' ){ /* String a character literals */
|
||||
}else if( c=='\'' || c=='\"' ){ /* String a character literals */
|
||||
int startchar, prevc;
|
||||
startchar = c;
|
||||
prevc = 0;
|
||||
@@ -2600,8 +2600,8 @@ void Parse(struct lemon *gp)
|
||||
if( c=='\n' ) lineno++;
|
||||
if( prevc=='\\' ) prevc = 0;
|
||||
else prevc = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( c==0 ){
|
||||
ErrorMsg(ps.filename,ps.tokenlineno,
|
||||
|
||||
+419
@@ -0,0 +1,419 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# This script is used to generate a VSIX (Visual Studio Extension) file for
|
||||
# SQLite usable by Visual Studio.
|
||||
|
||||
proc fail { {error ""} {usage false} } {
|
||||
if {[string length $error] > 0} then {
|
||||
puts stdout $error
|
||||
if {!$usage} then {exit 1}
|
||||
}
|
||||
|
||||
puts stdout "usage:\
|
||||
[file tail [info nameofexecutable]]\
|
||||
[file tail [info script]] <binaryDirectory> \[sourceDirectory\]"
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
proc getEnvironmentVariable { name } {
|
||||
#
|
||||
# NOTE: Returns the value of the specified environment variable or an empty
|
||||
# string for environment variables that do not exist in the current
|
||||
# process environment.
|
||||
#
|
||||
return [expr {[info exists ::env($name)] ? $::env($name) : ""}]
|
||||
}
|
||||
|
||||
proc getTemporaryPath {} {
|
||||
#
|
||||
# NOTE: Returns the normalized path to the first temporary directory found
|
||||
# in the typical set of environment variables used for that purpose
|
||||
# or an empty string to signal a failure to locate such a directory.
|
||||
#
|
||||
set names [list]
|
||||
|
||||
foreach name [list TEMP TMP] {
|
||||
lappend names [string toupper $name] [string tolower $name] \
|
||||
[string totitle $name]
|
||||
}
|
||||
|
||||
foreach name $names {
|
||||
set value [getEnvironmentVariable $name]
|
||||
|
||||
if {[string length $value] > 0} then {
|
||||
return [file normalize $value]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
proc appendArgs { args } {
|
||||
#
|
||||
# NOTE: Returns all passed arguments joined together as a single string with
|
||||
# no intervening spaces between arguments.
|
||||
#
|
||||
eval append result $args
|
||||
}
|
||||
|
||||
proc readFile { fileName } {
|
||||
#
|
||||
# NOTE: Reads and returns the entire contents of the specified file, which
|
||||
# may contain binary data.
|
||||
#
|
||||
set file_id [open $fileName RDONLY]
|
||||
fconfigure $file_id -encoding binary -translation binary
|
||||
set result [read $file_id]
|
||||
close $file_id
|
||||
return $result
|
||||
}
|
||||
|
||||
proc writeFile { fileName data } {
|
||||
#
|
||||
# NOTE: Writes the entire contents of the specified file, which may contain
|
||||
# binary data.
|
||||
#
|
||||
set file_id [open $fileName {WRONLY CREAT TRUNC}]
|
||||
fconfigure $file_id -encoding binary -translation binary
|
||||
puts -nonewline $file_id $data
|
||||
close $file_id
|
||||
return ""
|
||||
}
|
||||
|
||||
proc substFile { fileName } {
|
||||
#
|
||||
# NOTE: Performs all Tcl command, variable, and backslash substitutions in
|
||||
# the specified file and then re-writes the contents of that same file
|
||||
# with the substituted data.
|
||||
#
|
||||
return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
|
||||
}
|
||||
|
||||
proc replacePlatform { fileName platformName } {
|
||||
#
|
||||
# NOTE: Returns the specified file name containing the platform name instead
|
||||
# of platform placeholder tokens.
|
||||
#
|
||||
return [string map [list <platform> $platformName] $fileName]
|
||||
}
|
||||
|
||||
set script [file normalize [info script]]
|
||||
|
||||
if {[string length $script] == 0} then {
|
||||
fail "script file currently being evaluated is unknown" true
|
||||
}
|
||||
|
||||
set path [file dirname $script]
|
||||
set rootName [file rootname [file tail $script]]
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Process and verify all the command line arguments.
|
||||
#
|
||||
set argc [llength $argv]
|
||||
if {$argc != 1 && $argc != 2} then {fail}
|
||||
|
||||
set binaryDirectory [lindex $argv 0]
|
||||
|
||||
if {[string length $binaryDirectory] == 0} then {
|
||||
fail "invalid binary directory"
|
||||
}
|
||||
|
||||
if {![file exists $binaryDirectory] || \
|
||||
![file isdirectory $binaryDirectory]} then {
|
||||
fail "binary directory does not exist"
|
||||
}
|
||||
|
||||
if {$argc == 2} then {
|
||||
set sourceDirectory [lindex $argv 1]
|
||||
} else {
|
||||
#
|
||||
# NOTE: Assume that the source directory is the parent directory of the one
|
||||
# that contains this script file.
|
||||
#
|
||||
set sourceDirectory [file dirname $path]
|
||||
}
|
||||
|
||||
if {[string length $sourceDirectory] == 0} then {
|
||||
fail "invalid source directory"
|
||||
}
|
||||
|
||||
if {![file exists $sourceDirectory] || \
|
||||
![file isdirectory $sourceDirectory]} then {
|
||||
fail "source directory does not exist"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Evaluate the user-specific customizations file, if it exists.
|
||||
#
|
||||
set userFile [file join $path [appendArgs \
|
||||
$rootName . $tcl_platform(user) .tcl]]
|
||||
|
||||
if {[file exists $userFile] && \
|
||||
[file isfile $userFile]} then {
|
||||
source $userFile
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
set templateFile [file join $path win sqlite.vsix]
|
||||
|
||||
if {![file exists $templateFile] || \
|
||||
![file isfile $templateFile]} then {
|
||||
fail [appendArgs "template file \"" $templateFile "\" does not exist"]
|
||||
}
|
||||
|
||||
set currentDirectory [pwd]
|
||||
set outputFile [file join $currentDirectory sqlite-output.vsix]
|
||||
|
||||
if {[file exists $outputFile]} then {
|
||||
fail [appendArgs "output file \"" $outputFile "\" already exists"]
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Make sure that a valid temporary directory exists.
|
||||
#
|
||||
set temporaryDirectory [getTemporaryPath]
|
||||
|
||||
if {[string length $temporaryDirectory] == 0 || \
|
||||
![file exists $temporaryDirectory] || \
|
||||
![file isdirectory $temporaryDirectory]} then {
|
||||
fail "cannot locate a usable temporary directory"
|
||||
}
|
||||
|
||||
#
|
||||
# NOTE: Setup the staging directory to have a unique name inside of the
|
||||
# configured temporary directory.
|
||||
#
|
||||
set stagingDirectory [file normalize [file join $temporaryDirectory \
|
||||
[appendArgs $rootName . [pid]]]]
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Configure the external zipping tool. First, see if it has already
|
||||
# been pre-configured. If not, try to query it from the environment.
|
||||
# Finally, fallback on the default of simply "zip", which will then
|
||||
# be assumed to exist somewhere along the PATH.
|
||||
#
|
||||
if {![info exists zip]} then {
|
||||
if {[info exists env(ZipTool)]} then {
|
||||
set zip $env(ZipTool)
|
||||
}
|
||||
if {![info exists zip] || ![file exists $zip]} then {
|
||||
set zip zip
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# NOTE: Configure the external unzipping tool. First, see if it has already
|
||||
# been pre-configured. If not, try to query it from the environment.
|
||||
# Finally, fallback on the default of simply "unzip", which will then
|
||||
# be assumed to exist somewhere along the PATH.
|
||||
#
|
||||
if {![info exists unzip]} then {
|
||||
if {[info exists env(UnZipTool)]} then {
|
||||
set unzip $env(UnZipTool)
|
||||
}
|
||||
if {![info exists unzip] || ![file exists $unzip]} then {
|
||||
set unzip unzip
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Attempt to extract the SQLite version from the "sqlite3.h" header file
|
||||
# in the source directory. This script assumes that the header file has
|
||||
# already been generated by the build process.
|
||||
#
|
||||
set pattern {^#define\s+SQLITE_VERSION\s+"(.*)"$}
|
||||
set data [readFile [file join $sourceDirectory sqlite3.h]]
|
||||
|
||||
if {![regexp -line -- $pattern $data dummy version]} then {
|
||||
fail [appendArgs "cannot locate SQLITE_VERSION value in \"" \
|
||||
[file join $sourceDirectory sqlite3.h] \"]
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Setup the master file list data, including the necessary flags.
|
||||
#
|
||||
if {![info exists fileNames(source)]} then {
|
||||
set fileNames(source) [list "" "" "" \
|
||||
[file join $sourceDirectory sqlite3.h] \
|
||||
[file join $binaryDirectory <platform> sqlite3.lib] \
|
||||
[file join $binaryDirectory <platform> sqlite3.dll]]
|
||||
|
||||
if {![info exists no(symbols)]} then {
|
||||
lappend fileNames(source) \
|
||||
[file join $binaryDirectory <platform> sqlite3.pdb]
|
||||
}
|
||||
}
|
||||
|
||||
if {![info exists fileNames(destination)]} then {
|
||||
set fileNames(destination) [list \
|
||||
[file join $stagingDirectory extension.vsixmanifest] \
|
||||
[file join $stagingDirectory SDKManifest.xml] \
|
||||
[file join $stagingDirectory DesignTime CommonConfiguration \
|
||||
<platform> SQLite.WinRT.props] \
|
||||
[file join $stagingDirectory DesignTime CommonConfiguration \
|
||||
<platform> sqlite3.h] \
|
||||
[file join $stagingDirectory DesignTime CommonConfiguration \
|
||||
<platform> sqlite3.lib] \
|
||||
[file join $stagingDirectory Redist CommonConfiguration \
|
||||
<platform> sqlite3.dll]]
|
||||
|
||||
if {![info exists no(symbols)]} then {
|
||||
lappend fileNames(destination) \
|
||||
[file join $stagingDirectory Redist Debug \
|
||||
<platform> sqlite3.pdb]
|
||||
}
|
||||
}
|
||||
|
||||
if {![info exists fileNames(neutral)]} then {
|
||||
set fileNames(neutral) [list 1 1 1 1 0 0]
|
||||
|
||||
if {![info exists no(symbols)]} then {
|
||||
lappend fileNames(neutral) 0
|
||||
}
|
||||
}
|
||||
|
||||
if {![info exists fileNames(subst)]} then {
|
||||
set fileNames(subst) [list 1 1 1 0 0 0]
|
||||
|
||||
if {![info exists no(symbols)]} then {
|
||||
lappend fileNames(subst) 0
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Setup the list of platforms supported by this script.
|
||||
#
|
||||
if {![info exists platformNames]} then {
|
||||
set platformNames [list x86 x64 ARM]
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Make sure the staging directory exists, creating it if necessary.
|
||||
#
|
||||
file mkdir $stagingDirectory
|
||||
|
||||
#
|
||||
# NOTE: Build the Tcl command used to extract the template package to the
|
||||
# staging directory.
|
||||
#
|
||||
set extractCommand [list exec -- $unzip $templateFile -d $stagingDirectory]
|
||||
|
||||
#
|
||||
# NOTE: Extract the template package to the staging directory.
|
||||
#
|
||||
eval $extractCommand
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Process each file in the master file list. There are actually four
|
||||
# parallel lists that contain the source file names, destination file
|
||||
# names, the platform-neutral flags, and the use-subst flags. When the
|
||||
# platform-neutral flag is non-zero, the file is not platform-specific.
|
||||
# When the use-subst flag is non-zero, the file is considered to be a
|
||||
# text file that may contain Tcl variable and/or command replacements,
|
||||
# to be dynamically replaced during processing. If the source file name
|
||||
# is an empty string, then the destination file name will be assumed to
|
||||
# already exist in the staging directory and will not be copied; however,
|
||||
# dynamic replacements may still be performed on the destination file
|
||||
# prior to the package being re-zipped.
|
||||
#
|
||||
foreach sourceFileName $fileNames(source) \
|
||||
destinationFileName $fileNames(destination) \
|
||||
isNeutral $fileNames(neutral) useSubst $fileNames(subst) {
|
||||
#
|
||||
# NOTE: If the current file is platform-neutral, then only one platform will
|
||||
# be processed for it, namely "neutral"; otherwise, each supported
|
||||
# platform will be processed for it individually.
|
||||
#
|
||||
foreach platformName [expr {$isNeutral ? [list neutral] : $platformNames}] {
|
||||
#
|
||||
# NOTE: Use the actual platform name in the destination file name.
|
||||
#
|
||||
set newDestinationFileName [replacePlatform $destinationFileName \
|
||||
$platformName]
|
||||
|
||||
#
|
||||
# NOTE: Does the source file need to be copied to the destination file?
|
||||
#
|
||||
if {[string length $sourceFileName] > 0} then {
|
||||
#
|
||||
# NOTE: First, make sure the destination directory exists.
|
||||
#
|
||||
file mkdir [file dirname $newDestinationFileName]
|
||||
|
||||
#
|
||||
# NOTE: Then, copy the source file to the destination file verbatim.
|
||||
#
|
||||
file copy [replacePlatform $sourceFileName $platformName] \
|
||||
$newDestinationFileName
|
||||
}
|
||||
|
||||
#
|
||||
# NOTE: Does the destination file contain dynamic replacements that must
|
||||
# be processed now?
|
||||
#
|
||||
if {$useSubst} then {
|
||||
#
|
||||
# NOTE: Perform any dynamic replacements contained in the destination
|
||||
# file and then re-write it in-place.
|
||||
#
|
||||
substFile $newDestinationFileName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Change the current directory to the staging directory so that the
|
||||
# external archive building tool can pickup the necessary files using
|
||||
# relative paths.
|
||||
#
|
||||
cd $stagingDirectory
|
||||
|
||||
#
|
||||
# NOTE: Build the Tcl command used to archive the final package in the
|
||||
# output directory.
|
||||
#
|
||||
set archiveCommand [list exec -- $zip -r $outputFile *]
|
||||
|
||||
#
|
||||
# NOTE: Build the final package archive in the output directory.
|
||||
#
|
||||
eval $archiveCommand
|
||||
|
||||
#
|
||||
# NOTE: Change back to the previously saved current directory.
|
||||
#
|
||||
cd $currentDirectory
|
||||
|
||||
#
|
||||
# NOTE: Cleanup the temporary staging directory.
|
||||
#
|
||||
file delete -force $stagingDirectory
|
||||
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# NOTE: Success, emit the fully qualified path of the generated VSIX file.
|
||||
#
|
||||
puts stdout $outputFile
|
||||
Binary file not shown.
Reference in New Issue
Block a user