mirror of
https://github.com/status-im/sqlcipher.git
synced 2025-02-23 17:28:17 +00:00
Merge branch 'sqlite-release' into prerelease-int
This commit is contained in:
commit
58acc8269f
14
Makefile.in
14
Makefile.in
@ -184,8 +184,8 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
icu.lo insert.lo journal.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
|
||||
notify.lo opcodes.lo os.lo os_os2.lo os_unix.lo os_win.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
|
||||
table.lo tokenize.lo trigger.lo \
|
||||
@ -245,14 +245,12 @@ SRC = \
|
||||
$(TOP)/src/mutex.c \
|
||||
$(TOP)/src/mutex.h \
|
||||
$(TOP)/src/mutex_noop.c \
|
||||
$(TOP)/src/mutex_os2.c \
|
||||
$(TOP)/src/mutex_unix.c \
|
||||
$(TOP)/src/mutex_w32.c \
|
||||
$(TOP)/src/notify.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
@ -415,7 +413,6 @@ TESTSRC2 = \
|
||||
$(TOP)/src/wal.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
@ -677,9 +674,6 @@ mutex.lo: $(TOP)/src/mutex.c $(HDR)
|
||||
mutex_noop.lo: $(TOP)/src/mutex_noop.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_noop.c
|
||||
|
||||
mutex_os2.lo: $(TOP)/src/mutex_os2.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_os2.c
|
||||
|
||||
mutex_unix.lo: $(TOP)/src/mutex_unix.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_unix.c
|
||||
|
||||
@ -707,9 +701,6 @@ os_unix.lo: $(TOP)/src/os_unix.c $(HDR)
|
||||
os_win.lo: $(TOP)/src/os_win.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_win.c
|
||||
|
||||
os_os2.lo: $(TOP)/src/os_os2.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_os2.c
|
||||
|
||||
pragma.lo: $(TOP)/src/pragma.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pragma.c
|
||||
|
||||
@ -970,6 +961,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
|
||||
|
285
Makefile.msc
285
Makefile.msc
@ -15,16 +15,44 @@ USE_AMALGAMATION = 1
|
||||
#
|
||||
USE_ICU = 0
|
||||
|
||||
# Set this non-0 to dynamically link to the MSVC runtime library.
|
||||
#
|
||||
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.
|
||||
#
|
||||
USE_NATIVE_LIBPATHS = 0
|
||||
|
||||
# Set this non-0 to compile binaries suitable for the WinRT environment.
|
||||
# This setting does not apply to any binaries that require Tcl to operate
|
||||
# properly (i.e. the text fixture, etc).
|
||||
#
|
||||
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:
|
||||
@ -38,26 +66,129 @@ SYMBOLS = 1
|
||||
#
|
||||
DEBUG = 0
|
||||
|
||||
# C Compiler and options for use in building executables that
|
||||
# Check for the predefined command macro CC. This should point to the compiler
|
||||
# binary for the target platform. If it is not defined, simply define it to
|
||||
# the legacy default value 'cl.exe'.
|
||||
#
|
||||
!IFNDEF CC
|
||||
CC = cl.exe
|
||||
!ENDIF
|
||||
|
||||
# Check for the command macro LD. This should point to the linker binary for
|
||||
# the target platform. If it is not defined, simply define it to the legacy
|
||||
# default value 'link.exe'.
|
||||
#
|
||||
!IFNDEF LD
|
||||
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
|
||||
# cross-compiling, it is suggested that this macro be modified via the command
|
||||
# line (since nmake itself does not provide a built-in method to guess it).
|
||||
# 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 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
|
||||
#
|
||||
!IFDEF NCC
|
||||
NCC = $(NCC:\\=\)
|
||||
!ELSEIF $(XCOMPILE)!=0
|
||||
NCC = "$(VCINSTALLDIR)\bin\cl.exe"
|
||||
NCC = $(NCC:\\=\)
|
||||
!ELSE
|
||||
NCC = $(CC)
|
||||
!ENDIF
|
||||
|
||||
# Check for the MSVC runtime library path macro. Othertise, this
|
||||
# value will default to the 'lib' directory underneath the MSVC
|
||||
# installation directory.
|
||||
#
|
||||
!IFNDEF NCRTLIBPATH
|
||||
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
|
||||
# to be available when using Visual C++ 2008 or later via the
|
||||
# command line).
|
||||
#
|
||||
!IFNDEF NSDKLIBPATH
|
||||
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.
|
||||
#
|
||||
BCC = cl.exe -W3
|
||||
BCC = $(NCC) -W3
|
||||
|
||||
# C Compile and options for use in building executables that
|
||||
# Check if the native library paths should be used when compiling
|
||||
# the command line tools used during the compilation process. If
|
||||
# so, set the necessary macro now.
|
||||
#
|
||||
!IF $(USE_NATIVE_LIBPATHS)!=0
|
||||
NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
|
||||
!ENDIF
|
||||
|
||||
# C compiler and options for use in building executables that
|
||||
# will run on the target platform. (BCC and TCC are usually the
|
||||
# same unless your are cross-compiling.)
|
||||
#
|
||||
TCC = cl.exe -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise
|
||||
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
|
||||
# disable use of Win32 APIs that are not available and to enable
|
||||
# use of Win32 APIs that are specific to Windows 8 and/or WinRT.
|
||||
# Also, we need to dynamically link to the MSVC runtime when
|
||||
# compiling for WinRT.
|
||||
#
|
||||
!IF $(FOR_WINRT)!=0
|
||||
TCC = $(TCC) -DSQLITE_OS_WINRT=1 -MD
|
||||
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
|
||||
# when compiling for WinRT (e.g. debug or release) OR if the
|
||||
# USE_CRT_DLL option is set to force dynamically linking to the
|
||||
# MSVC runtime library.
|
||||
#
|
||||
!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0
|
||||
!IF $(DEBUG)>0
|
||||
TCC = $(TCC) -MDd
|
||||
!ELSE
|
||||
TCC = $(TCC) -MD
|
||||
!ENDIF
|
||||
!ELSE
|
||||
!IF $(DEBUG)>0
|
||||
TCC = $(TCC) -MTd
|
||||
!ELSE
|
||||
TCC = $(TCC) -MT
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in
|
||||
@ -66,7 +197,9 @@ TCC = $(TCC) -DSQLITE_OS_WINRT=1 -MD
|
||||
#
|
||||
!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)
|
||||
@ -76,36 +209,60 @@ 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
|
||||
|
||||
#
|
||||
# Prevent warnings about "insecure" runtime library functions being used.
|
||||
# Prevent warnings about "insecure" MSVC runtime library functions
|
||||
# being used.
|
||||
#
|
||||
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
|
||||
|
||||
#
|
||||
# Use native Win32 heap instead of malloc/free?
|
||||
# Prevent warnings about "deprecated" POSIX functions being used.
|
||||
#
|
||||
# TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
|
||||
TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
|
||||
BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
|
||||
RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
|
||||
|
||||
#
|
||||
# Use the SQLite debugging heap subsystem?
|
||||
#
|
||||
!IF $(MEMDEBUG)!=0
|
||||
TCC = $(TCC) -DSQLITE_MEMDEBUG=1
|
||||
RCC = $(RCC) -DSQLITE_MEMDEBUG=1
|
||||
|
||||
#
|
||||
# Use native Win32 heap subsystem instead of malloc/free?
|
||||
#
|
||||
!ELSEIF $(WIN32HEAP)!=0
|
||||
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
|
||||
RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
|
||||
|
||||
#
|
||||
# Validate the heap on every call into the native Win32 heap subsystem?
|
||||
#
|
||||
!IF $(DEBUG)>2
|
||||
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
|
||||
@ -114,43 +271,43 @@ TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
|
||||
# prior to running nmake in order to match the actual installed location and
|
||||
# version on this machine.
|
||||
#
|
||||
!if "$(TCLINCDIR)" == ""
|
||||
!IFNDEF TCLINCDIR
|
||||
TCLINCDIR = c:\tcl\include
|
||||
!endif
|
||||
!ENDIF
|
||||
|
||||
!if "$(TCLLIBDIR)" == ""
|
||||
!IFNDEF TCLLIBDIR
|
||||
TCLLIBDIR = c:\tcl\lib
|
||||
!endif
|
||||
!ENDIF
|
||||
|
||||
!if "$(LIBTCL)" == ""
|
||||
!IFNDEF LIBTCL
|
||||
LIBTCL = tcl85.lib
|
||||
!endif
|
||||
!ENDIF
|
||||
|
||||
# The locations of the ICU header and library files. These variables
|
||||
# (ICUINCDIR, ICULIBDIR, and LIBICU) may be overridden via the environment
|
||||
# prior to running nmake in order to match the actual installed location on
|
||||
# this machine.
|
||||
#
|
||||
!if "$(ICUINCDIR)" == ""
|
||||
!IFNDEF ICUINCDIR
|
||||
ICUINCDIR = c:\icu\include
|
||||
!endif
|
||||
!ENDIF
|
||||
|
||||
!if "$(ICULIBDIR)" == ""
|
||||
!IFNDEF ICULIBDIR
|
||||
ICULIBDIR = c:\icu\lib
|
||||
!endif
|
||||
!ENDIF
|
||||
|
||||
!if "$(LIBICU)" == ""
|
||||
!IFNDEF LIBICU
|
||||
LIBICU = icuuc.lib icuin.lib
|
||||
!endif
|
||||
!ENDIF
|
||||
|
||||
# This is the command to use for tclsh - normally just "tclsh", but we may
|
||||
# know the specific version we want to use. This variable (TCLSH_CMD) may be
|
||||
# overridden via the environment prior to running nmake in order to select a
|
||||
# specific Tcl shell to use.
|
||||
#
|
||||
!if "$(TCLSH_CMD)" == ""
|
||||
!IFNDEF TCLSH_CMD
|
||||
TCLSH_CMD = tclsh85
|
||||
!endif
|
||||
!ENDIF
|
||||
|
||||
# Compiler options needed for programs that use the readline() library.
|
||||
#
|
||||
@ -163,16 +320,18 @@ 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
|
||||
#
|
||||
!if "$(TLIBS)" == ""
|
||||
!IFNDEF TLIBS
|
||||
TLIBS =
|
||||
!endif
|
||||
!ENDIF
|
||||
|
||||
# Flags controlling use of the in memory btree implementation
|
||||
#
|
||||
@ -181,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*).
|
||||
@ -198,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
|
||||
@ -221,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$@
|
||||
|
||||
@ -234,7 +402,7 @@ LTLINK = $(TCC) -Fe$@
|
||||
# Note that the vcvars*.bat family of batch files typically
|
||||
# set this for you. Otherwise, the linker will attempt
|
||||
# to deduce the binary type based on the object files.
|
||||
!IF "$(PLATFORM)"!=""
|
||||
!IFDEF PLATFORM
|
||||
LTLINKOPTS = /MACHINE:$(PLATFORM)
|
||||
LTLIBOPTS = /MACHINE:$(PLATFORM)
|
||||
!ENDIF
|
||||
@ -249,13 +417,14 @@ LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
|
||||
|
||||
# If either debugging or symbols are enabled, enable PDBs.
|
||||
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /DEBUG
|
||||
BCC = $(BCC) /DEBUG
|
||||
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
|
||||
@ -282,8 +451,8 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
icu.lo insert.lo journal.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
|
||||
notify.lo opcodes.lo os.lo os_os2.lo os_unix.lo os_win.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
|
||||
table.lo tokenize.lo trigger.lo \
|
||||
@ -345,14 +514,12 @@ SRC = \
|
||||
$(TOP)\src\mutex.c \
|
||||
$(TOP)\src\mutex.h \
|
||||
$(TOP)\src\mutex_noop.c \
|
||||
$(TOP)\src\mutex_os2.c \
|
||||
$(TOP)\src\mutex_unix.c \
|
||||
$(TOP)\src\mutex_w32.c \
|
||||
$(TOP)\src\notify.c \
|
||||
$(TOP)\src\os.c \
|
||||
$(TOP)\src\os.h \
|
||||
$(TOP)\src\os_common.h \
|
||||
$(TOP)\src\os_os2.c \
|
||||
$(TOP)\src\os_unix.c \
|
||||
$(TOP)\src\os_win.c \
|
||||
$(TOP)\src\pager.c \
|
||||
@ -514,7 +681,6 @@ TESTSRC2 = \
|
||||
$(TOP)\src\wal.c \
|
||||
$(TOP)\src\mem5.c \
|
||||
$(TOP)\src\os.c \
|
||||
$(TOP)\src\os_os2.c \
|
||||
$(TOP)\src\os_unix.c \
|
||||
$(TOP)\src\os_win.c \
|
||||
$(TOP)\src\pager.c \
|
||||
@ -600,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
|
||||
@ -637,7 +803,7 @@ lempar.c: $(TOP)\src\lempar.c
|
||||
copy $(TOP)\src\lempar.c .
|
||||
|
||||
lemon.exe: $(TOP)\tool\lemon.c lempar.c
|
||||
$(BCC) -Fe$@ $(TOP)\tool\lemon.c
|
||||
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLIBPATHS)
|
||||
|
||||
# Rules to build individual *.lo files from generated *.c files. This
|
||||
# applies to:
|
||||
@ -651,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)
|
||||
@ -755,9 +932,6 @@ mutex.lo: $(TOP)\src\mutex.c $(HDR)
|
||||
mutex_noop.lo: $(TOP)\src\mutex_noop.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\mutex_noop.c
|
||||
|
||||
mutex_os2.lo: $(TOP)\src\mutex_os2.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\mutex_os2.c
|
||||
|
||||
mutex_unix.lo: $(TOP)\src\mutex_unix.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\mutex_unix.c
|
||||
|
||||
@ -785,9 +959,6 @@ os_unix.lo: $(TOP)\src\os_unix.c $(HDR)
|
||||
os_win.lo: $(TOP)\src\os_win.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\os_win.c
|
||||
|
||||
os_os2.lo: $(TOP)\src\os_os2.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\os_os2.c
|
||||
|
||||
pragma.lo: $(TOP)\src\pragma.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\pragma.c
|
||||
|
||||
@ -872,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
|
||||
#
|
||||
@ -899,7 +1069,7 @@ sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP) > sqlite3.h
|
||||
|
||||
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
|
||||
$(BCC) -Femkkeywordhash.exe $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c
|
||||
$(BCC) -Fe$@ $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLIBPATHS)
|
||||
|
||||
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
.\mkkeywordhash.exe > keywordhash.h
|
||||
@ -987,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
|
||||
@ -1009,9 +1179,9 @@ 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
|
||||
@ -1026,14 +1196,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
|
||||
|
||||
@ -1043,5 +1214,5 @@ sqlite3.def: libsqlite3.lib
|
||||
| $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \
|
||||
| sort >> sqlite3.def
|
||||
|
||||
sqlite3.dll: $(LIBOBJ) sqlite3.def
|
||||
link $(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)
|
||||
|
@ -204,8 +204,8 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
|
||||
icu.o insert.o journal.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
memjournal.o \
|
||||
mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
|
||||
notify.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
|
||||
mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
|
||||
notify.o opcodes.o os.o os_unix.o os_win.o \
|
||||
pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \
|
||||
random.o resolve.o rowset.o rtree.o select.o status.o \
|
||||
table.o tokenize.o trigger.o \
|
||||
@ -256,14 +256,12 @@ SRC = \
|
||||
$(TOP)/src/mutex.c \
|
||||
$(TOP)/src/mutex.h \
|
||||
$(TOP)/src/mutex_noop.c \
|
||||
$(TOP)/src/mutex_os2.c \
|
||||
$(TOP)/src/mutex_unix.c \
|
||||
$(TOP)/src/mutex_w32.c \
|
||||
$(TOP)/src/notify.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
@ -396,7 +394,7 @@ TESTSRC2 = \
|
||||
$(TOP)/src/attach.c $(TOP)/src/backup.c $(TOP)/src/btree.c \
|
||||
$(TOP)/src/build.c $(TOP)/src/ctime.c $(TOP)/src/date.c \
|
||||
$(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \
|
||||
$(TOP)/src/os_os2.c $(TOP)/src/os_unix.c $(TOP)/src/os_win.c \
|
||||
$(TOP)/src/os_unix.c $(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c $(TOP)/src/pragma.c $(TOP)/src/prepare.c \
|
||||
$(TOP)/src/printf.c $(TOP)/src/random.c $(TOP)/src/pcache.c \
|
||||
$(TOP)/src/pcache1.c $(TOP)/src/select.c $(TOP)/src/tokenize.c \
|
||||
|
@ -388,6 +388,7 @@ if test "${use_tcl}" = "yes" ; then
|
||||
fi
|
||||
|
||||
# Start autosearch by asking tclsh
|
||||
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
|
||||
@ -397,6 +398,7 @@ if test "${use_tcl}" = "yes" ; then
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tcl installation
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -199,7 +199,7 @@ static int icuNext(
|
||||
|
||||
while( iStart<iEnd ){
|
||||
int iWhite = iStart;
|
||||
U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
|
||||
U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
|
||||
if( u_isspace(c) ){
|
||||
iStart = iWhite;
|
||||
}else{
|
||||
|
@ -146,7 +146,7 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
||||
}
|
||||
assert( aEntry[0]<key );
|
||||
assert( key>=aEntry[iRes] );
|
||||
return (c >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
|
||||
return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -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
|
||||
|
8
main.mk
8
main.mk
@ -60,8 +60,8 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
|
||||
icu.o insert.o journal.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
memjournal.o \
|
||||
mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
|
||||
notify.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
|
||||
mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
|
||||
notify.o opcodes.o os.o os_unix.o os_win.o \
|
||||
pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \
|
||||
random.o resolve.o rowset.o rtree.o select.o status.o \
|
||||
table.o tokenize.o trigger.o \
|
||||
@ -113,14 +113,12 @@ SRC = \
|
||||
$(TOP)/src/mutex.c \
|
||||
$(TOP)/src/mutex.h \
|
||||
$(TOP)/src/mutex_noop.c \
|
||||
$(TOP)/src/mutex_os2.c \
|
||||
$(TOP)/src/mutex_unix.c \
|
||||
$(TOP)/src/mutex_w32.c \
|
||||
$(TOP)/src/notify.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
@ -282,7 +280,6 @@ TESTSRC2 = \
|
||||
$(TOP)/src/wal.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c \
|
||||
@ -619,3 +616,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
|
||||
|
221
manifest
221
manifest
@ -1,12 +1,12 @@
|
||||
C Version\s3.7.13
|
||||
D 2012-06-11T02:05:22.539
|
||||
C Version\s3.7.14.1
|
||||
D 2012-10-04T19:37:12.994
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in d17fddaa4e81f93a7c9c7c0808aacb3fc95f79f4
|
||||
F Makefile.in abd5c10d21d1395f140d9e50ea999df8fa4d6376
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc fd86027849a59a2f621b791b79eabf3f8ffbd684
|
||||
F Makefile.vxworks 3b7fe7a0571fdadc61363ebc1b23732d2d6363ca
|
||||
F Makefile.msc 2d696f01c228995e98b3b953a08b7bba1d48c130
|
||||
F Makefile.vxworks 879f034a64062a364b21000266bbd5bc6e0c19b9
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
F VERSION 3e857b9b826e818eec9411eafe2c3fa22c1dbb8a
|
||||
F VERSION 9694dff497fc7e53037a5890f30ab069c26e8ab7
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@ -15,11 +15,11 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 79405675c313ce4a5e94afac6ec880bb3e27b4f1 x
|
||||
F configure.ac 9ee886c21c095b3272137b1553ae416c8b8c8557
|
||||
F configure e2c3b28dec7f5d1f72dd7465c87bb37f6af1931f 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,14 +55,14 @@ 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
|
||||
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
|
||||
F ext/fts3/fts3_icu.c 62ec177c55f6a5c6e994dd3e5fd3194b4045c347
|
||||
F ext/fts3/fts3_icu.c b85eca4a52e5ec11b94392de5167974c11906d4a
|
||||
F ext/fts3/fts3_porter.c a465b49fcb8249a755792f87516eff182efa42b3
|
||||
F ext/fts3/fts3_snippet.c bf67520ae9d2352a65368ed101729ff701c08808
|
||||
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
|
||||
@ -71,8 +71,8 @@ F ext/fts3/fts3_tokenizer.c e94a8b901066031437ccfe4769fc76370257cede
|
||||
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 2965d217c37079f1dbbdbd2c58f843be285d73f2
|
||||
F ext/fts3/fts3_write.c 794438f904cdf4516b258e530c0065efadb7b9b5
|
||||
F ext/fts3/fts3_unicode2.c a863f05f758af36777dffc2facc898bc73fec896
|
||||
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 84ed9c324cf0b8f4eb6f276553d1fd092b5ae0f4
|
||||
F main.mk 72026405046ed5b1f0368943b89c0aa29ad558b6
|
||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
|
||||
@ -117,93 +117,92 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c 149cc80d9257971b0bff34e58fb2263e01998289
|
||||
F src/analyze.c 70c46504c0d2543ea5cdca01140b2cd3e1d886e7
|
||||
F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410
|
||||
F src/attach.c 577bf5675b0c50495fc28549f2fcbdb1bac71143
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c d7fb4c6d2ad3fe51a4ce1a897fde7b00f4de5fef
|
||||
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 47c4506afe4bcb4ed1f4b5357582d1cb3402f8ad
|
||||
F src/btree.c 97edf88abd2b66f31886ba977d2b3b2a21d81d4c
|
||||
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 657212460bf5cfd3ae607d12ea62092844c227b5
|
||||
F src/func.c c6b3c94320253a35bda43fb69cc292618e3285d6
|
||||
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 07e05ba330b5994fa20d3b2e8c1c146133587d68
|
||||
F src/main.c 02255cf1da50956c5427c469abddb15bccc4ba09
|
||||
F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1
|
||||
F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa
|
||||
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
|
||||
F src/memjournal.c 0ebce851677a7ac035ba1512a7e65851b34530c6
|
||||
F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
|
||||
F src/mutex.h 2a79e0c10c26412546b501ee0f3d92b42decf63e
|
||||
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
|
||||
F src/mutex_noop.c 7682796b7d8d39bf1c138248858efcd10c9e1553
|
||||
F src/mutex_os2.c 882d735098c07c8c6a5472b8dd66e19675fe117f
|
||||
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
|
||||
F src/mutex_w32.c db8970270841e2385a43602477e84c4b19aff1db
|
||||
F src/mutex_w32.c 32a9b3841e2d757355f0012b860b1bc5e01eafa0
|
||||
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c
|
||||
F src/os.h 38aabd5e3ecd4162332076f55bb09cec02165cca
|
||||
F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
|
||||
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 f29df90bd3adc64b33114ab1de9fb7768fcf2099
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
|
||||
F src/pcache1.c 2234d84f9c003d800a57f00f8535c91667fa4f6c
|
||||
F src/pragma.c eee3e3161f82a1e06f632a8d2a82b29ba3c45889
|
||||
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
|
||||
F src/pragma.c 97f9357f0e7e5fb46a2519f14539550aa07db49f
|
||||
F src/prepare.c 33291b83cca285718048d219c67b8298501fa3a5
|
||||
F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699
|
||||
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c b3c70ab28cac60de33684c9aa9e5138dcf71d6dd
|
||||
F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1
|
||||
F src/select.c f6c4833c4d8e94714761d99013d74f381e084f1d
|
||||
F src/shell.c c16f72e34f611f060546709564c121a67cb2b31b
|
||||
F src/sqlite.h.in 39f041ce71a0d994e2487014fc9e8721595f5bc0
|
||||
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 c447d35212736c4c77d86bc2d00f6cf4d4c12131
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h 29b5348f0056d9b46d0bb94d4853db21568afde9
|
||||
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 d20022c647aa7a871d7b4038c4ec971cafe39744
|
||||
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
|
||||
F src/test8.c 235f1d19716fa768c46fc461ccbf529b2c9e4399
|
||||
F src/test8.c 8bcce65e5ee027fbfd7da41d28371aabbfd369ff
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
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 4f7b8030287d62fe56a1d99e68b41760feae381a
|
||||
F src/test_config.c 09781397ccc24268cb895be0d4c21b4aad651486
|
||||
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_func.c 090f2c3339e85c2c964435f99aed6f3da9d59525
|
||||
F src/test_func.c 3a8dd37c08ab43b76d38eea2836e34a3897bf170
|
||||
F src/test_fuzzer.c 1d26aa965120420bc14807da29d4d4541bfa6148
|
||||
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
|
||||
F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a
|
||||
@ -212,49 +211,50 @@ 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
|
||||
F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c 0af3e1e9a1f22bc5f431dd3efcc32762f4109f58
|
||||
F src/test_quota.c 8ab295092c70903ca6f3209fa4c75f5cb6c1bf8e
|
||||
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 495535f3eb57acdc384572da570e869bb1834bf4
|
||||
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 9d934e111021d56c629efc73a796648c9519ad12
|
||||
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 1e86210d3976717a19238ea7b047fac481fe8c12
|
||||
F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684
|
||||
F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
|
||||
F src/trigger.c 3f258307040173aff383eb23fb74c44fe829078c
|
||||
F src/update.c 28d2d098b43a2c70dae399896ea8a02f622410ef
|
||||
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
|
||||
F src/util.c 4f6cfad661b2e3454b0cdd5b1b9d39a54942d0e3
|
||||
F src/util.c 0af2e515dc0dabacec931bca39525f6c3f1c5455
|
||||
F src/vacuum.c 587a52bb8833d7ac15af8916f25437e2575028bd
|
||||
F src/vdbe.c f5ad3c06dc3fe647097065829c013f3f1b9eadca
|
||||
F src/vdbe.c 9c524bded348fd0a53adc19f2d7cad76ba3442b2
|
||||
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
|
||||
F src/vdbeInt.h 6ff4180a05683566a8835d12f7ec504b22932c82
|
||||
F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91
|
||||
F src/vdbeaux.c d52c8a424fdd4b1d5cf1ac93cc7cd20da023ec5c
|
||||
F src/vdbeInt.h 986b6b11a13c517337355009e5438703ba5b0a40
|
||||
F src/vdbeapi.c 88ea823bbcb4320f5a6607f39cd7c2d3cc4c26b1
|
||||
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 7bb3ad807afc7973406c805d5157ec7a2f65e146
|
||||
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 e74f9ed463b0153e7f2a0e5f291c2be16ae76b35
|
||||
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
|
||||
@ -274,6 +274,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
|
||||
F test/async5.test 0dd8701bd588bf6e70c2557a22ae3f22b2567b4c
|
||||
F test/atof1.test 9bf1d25180a2e05fc12ce3940cc8003033642f68
|
||||
F test/attach.test 0d112b7713611fdf0340260192749737135fda5f
|
||||
F test/attach2.test e54436ed956d3d88bdee61221da59bf3935a0966
|
||||
F test/attach3.test d89ccfe4fe6e2b5e368d480fcdfe4b496c54cf4e
|
||||
@ -288,7 +289,7 @@ F test/autovacuum.test fcaf4616ae5bb18098db1cb36262565e5c841c3c
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
F test/backcompat.test bccbc64769d9c755ad65ee7c2f7336b86e3cc0c8
|
||||
F test/backup.test 717346db953e9e435c2a94916e4af177330d60d3
|
||||
F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
|
||||
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
|
||||
F test/backup_ioerr.test 40d208bc9224b666ee3ed423f49bc9062a36a9d0
|
||||
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
|
||||
@ -351,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
|
||||
@ -363,7 +364,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
|
||||
F test/date.test a18a2ce81add84b17b06559e82ad7bb91bc6ddff
|
||||
F test/date.test f3228180c87bbe5d39c9397bf001c0095c3821b9
|
||||
F test/dbstatus.test 207e5b63fcb7b9c3bb8e1fdf38ebd4654ad0e54b
|
||||
F test/dbstatus2.test b1de8250fde1f3474d6b86f0e89de38d84794f56
|
||||
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
|
||||
@ -464,8 +465,8 @@ F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
|
||||
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
|
||||
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
|
||||
F test/fts3ao.test e7b80272efcced57d1d087a9da5c690dd7c21fd9
|
||||
F test/fts3atoken.test 402ef2f7c2fb4b3d4fa0587df6441c1447e799b3
|
||||
F test/fts3auto.test b39f3f51227aea145eae6638690355dbdf9abf18
|
||||
F test/fts3atoken.test fb398ab50aa232489e2a17f9b29d7ad3a3885f36
|
||||
F test/fts3auto.test 74315a7377403a57ba82a652a33704197fe1e4be
|
||||
F test/fts3aux1.test 0b02743955d56fc0d4d66236a26177bd1b726de0
|
||||
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
@ -475,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
|
||||
@ -485,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
|
||||
@ -494,15 +495,15 @@ 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
|
||||
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
|
||||
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4unicode.test 247e6c64563b5f930aec0f89a5b01ed6b4b129cd
|
||||
F test/func.test 9809b7622d721904a8cc33c1ffb87f46d506ed01
|
||||
F test/fts4unicode.test aad033abdcfa0f87ce5f56468f59fdf2a0acbcef
|
||||
F test/func.test 0d89043dab9a8853358d14c68e028ee0093bf066
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
|
||||
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
|
||||
@ -532,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
|
||||
@ -555,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
|
||||
@ -567,7 +569,7 @@ F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test 7b4aaa4a8192fdec90e0a905984c92a688c51e48
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/limit.test 2db7b3b34fb925b8e847d583d2eb67531d0ce67e
|
||||
F test/loadext.test dab17f7014f8079698dbd4b02705562b0ce6db5f
|
||||
F test/loadext.test 2b5e249c51c986a5aff1f0950cf7ba30976c8f22
|
||||
F test/loadext2.test 0bcaeb4d81cd5b6e883fdfea3c1bdbe1f173cbca
|
||||
F test/lock.test db74fdf5a73bad29ab3d862ea78bf1068972cc1d
|
||||
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
|
||||
@ -617,7 +619,7 @@ F test/misc3.test fe55130a43e444ee75e2156ff75dc96e964b5738
|
||||
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test 4337d84e441f36cee62656f9f7ba8bc22a7ca721
|
||||
F test/misc7.test f00dad9a004da659330013e6f21819d018b683d3
|
||||
F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054
|
||||
F test/multiplex.test e08cc7177bd6d85990ee1d71100bb6c684c02256
|
||||
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
|
||||
@ -642,8 +644,8 @@ 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/pragma.test cb736bcc75b8b629af21ac0ad83ba1d054a2107b
|
||||
F test/permutations.test 1a8ac849b659445a0b3883caf42fa2c2a289f4a1
|
||||
F test/pragma.test a62f73293b0f0d79b0c87f8dd32d46fe53b0bd17
|
||||
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
|
||||
@ -658,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 fa302d03fd9acfce6d910553a33473bfcf561958
|
||||
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
|
||||
@ -676,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
|
||||
@ -717,6 +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 2953e9da0e46dab5f83059ef6bfdebca66e13418
|
||||
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
|
||||
F test/stat.test 08e8185b3fd5b010c90d7ad82b9dd4ea1cbf14b0
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
@ -730,7 +734,7 @@ F test/syscall.test bea9bf329bff733c791310244617c2a76974e64a
|
||||
F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f
|
||||
F test/table.test a59d985ca366e39b17b175f387f9d5db5a18d4e2
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tclsqlite.test 1597d353308531527583481d14d9da52ea8ed0af
|
||||
F test/tclsqlite.test 952b772830bd380c9b5f58c03fb374189be53828
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test 51edd31c65ed1560dd600b1796e8325df96318e2
|
||||
F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d
|
||||
@ -926,8 +930,8 @@ 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 d5021064bebfc717fe2bf4db2536ea030b76a773
|
||||
F test/wal3.test 6504bbf348b2d6dfade64a064f1050fd617e8706
|
||||
F test/wal2.test d4b470f13c87f6d8268b004380afa04c3c67cb90
|
||||
F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test f58ed4b8b542f71c7441da12fbd769d99b362437
|
||||
F test/wal6.test 2e3bc767d9c2ce35c47106148d43fcbd072a93b3
|
||||
@ -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 e6bb27762c9f22601cbb8bff6e0acfd124e74b63
|
||||
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,28 +966,32 @@ F test/where9.test ae98dc22ef9b6f2bc81e9f164e41b38faa9bda06
|
||||
F test/whereA.test 24c234263c8fe358f079d5e57d884fb569d2da0a
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test 13ff5ec0dba407c0e0c075980c75b3275a6774e5
|
||||
F test/whereD.test 11945e79899a97958d87d1e5ac6ae5abd827356b
|
||||
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 90f46af31c92b940fec25b491f39409fd95dcdfa
|
||||
F tool/lemon.c 680980c7935bfa1edec20c804c9e5ba4b1dd96f5
|
||||
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 105023aa86f696a74b1d6a4929d1e1c3baf9471c
|
||||
F tool/mksqlite3c.tcl f289ba51f74f45c71a80c13e6c74a6dd92763253
|
||||
F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02
|
||||
F tool/mksqlite3c.tcl 589c7f44e990be1b8443cfe4808dce392b0327fa
|
||||
F tool/mksqlite3h.tcl 78013ad79a5e492e5f764f3c7a8ef834255061f8
|
||||
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
|
||||
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
|
||||
F tool/mkvsix.tcl 19b2ab9ea16445953a76568a5bbe4cb864f92dfe
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 72a49b8a9a8b0bf213a438180307a0df836d4380
|
||||
F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
@ -1005,10 +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 0ae0ce630a2e11f81dca50a9cfb04c4a41c03b2d
|
||||
R 45dae5fdb66a9a88c8595b45bd7db627
|
||||
F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
|
||||
P 81fd941da62956e32d1c4ffcdb39abecba7a6f3b
|
||||
R a82bf185a73888ab1f23d02429bade9e
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.7.13 *
|
||||
T +sym-version-3.7.14.1 *
|
||||
U drh
|
||||
Z c0babe9c1caac24f66a10b2544a508b6
|
||||
Z 002ec98f7f5b76deaac3a726393245f3
|
||||
|
@ -1 +1 @@
|
||||
f5b5a13f7394dc143aa136f1d4faba6839eaa6dc
|
||||
091570e46d04e84b67228e0bdbcd6e1fb60c6bdb
|
||||
|
@ -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;
|
||||
|
13
src/backup.c
13
src/backup.c
@ -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;
|
||||
@ -543,14 +542,14 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
*/
|
||||
int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
sqlite3_backup **pp; /* Ptr to head of pagers backup list */
|
||||
MUTEX_LOGIC( sqlite3_mutex *mutex; ) /* Mutex to protect source database */
|
||||
sqlite3 *pSrcDb; /* Source database connection */
|
||||
int rc; /* Value to return */
|
||||
|
||||
/* Enter the mutexes */
|
||||
if( p==0 ) return SQLITE_OK;
|
||||
sqlite3_mutex_enter(p->pSrcDb->mutex);
|
||||
pSrcDb = p->pSrcDb;
|
||||
sqlite3_mutex_enter(pSrcDb->mutex);
|
||||
sqlite3BtreeEnter(p->pSrc);
|
||||
MUTEX_LOGIC( mutex = p->pSrcDb->mutex; )
|
||||
if( p->pDestDb ){
|
||||
sqlite3_mutex_enter(p->pDestDb->mutex);
|
||||
}
|
||||
@ -576,7 +575,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
|
||||
/* Exit the mutexes and free the backup context structure. */
|
||||
if( p->pDestDb ){
|
||||
sqlite3_mutex_leave(p->pDestDb->mutex);
|
||||
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
|
||||
}
|
||||
sqlite3BtreeLeave(p->pSrc);
|
||||
if( p->pDestDb ){
|
||||
@ -585,7 +584,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
** sqlite3_backup_finish(). */
|
||||
sqlite3_free(p);
|
||||
}
|
||||
sqlite3_mutex_leave(mutex);
|
||||
sqlite3LeaveMutexAndCloseZombie(pSrcDb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
38
src/btree.c
38
src/btree.c
@ -5922,11 +5922,15 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
|
||||
** If aOvflSpace is set to a null pointer, this function returns
|
||||
** SQLITE_NOMEM.
|
||||
*/
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
|
||||
#pragma optimize("", off)
|
||||
#endif
|
||||
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 +5994,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 +6086,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 +6215,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 +6264,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 +6476,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 ){
|
||||
@ -6547,6 +6555,9 @@ balance_cleanup:
|
||||
|
||||
return rc;
|
||||
}
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@ -6707,7 +6718,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 +8305,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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
79
src/expr.c
79
src/expr.c
@ -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;
|
||||
}
|
||||
return WRC_Abort;
|
||||
if( i<pSrc->nSrc ){
|
||||
p->nThis++;
|
||||
}else{
|
||||
return WRC_Continue;
|
||||
p->nOther++;
|
||||
}
|
||||
}
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
13
src/func.c
13
src/func.c
@ -863,8 +863,19 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
switch( sqlite3_value_type(argv[0]) ){
|
||||
case SQLITE_INTEGER:
|
||||
case SQLITE_FLOAT: {
|
||||
double r1, r2;
|
||||
char zBuf[50];
|
||||
r1 = sqlite3_value_double(argv[0]);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
|
||||
sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
|
||||
if( r1!=r2 ){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
|
||||
}
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER: {
|
||||
sqlite3_result_value(context, argv[0]);
|
||||
break;
|
||||
}
|
||||
|
@ -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) );
|
||||
|
14
src/insert.c
14
src/insert.c
@ -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
|
||||
|
83
src/main.c
83
src/main.c
@ -765,13 +765,25 @@ static void disconnectAllVtab(sqlite3 *db){
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if database connection db has unfinalized prepared
|
||||
** statements or unfinished sqlite3_backup objects.
|
||||
*/
|
||||
static int connectionIsBusy(sqlite3 *db){
|
||||
int j;
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( db->pVdbe ) return 1;
|
||||
for(j=0; j<db->nDb; j++){
|
||||
Btree *pBt = db->aDb[j].pBt;
|
||||
if( pBt && sqlite3BtreeIsInBackup(pBt) ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an existing SQLite database
|
||||
*/
|
||||
int sqlite3_close(sqlite3 *db){
|
||||
HashElem *i; /* Hash table iterator */
|
||||
int j;
|
||||
|
||||
static int sqlite3Close(sqlite3 *db, int forceZombie){
|
||||
if( !db ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -792,25 +804,63 @@ int sqlite3_close(sqlite3 *db){
|
||||
*/
|
||||
sqlite3VtabRollback(db);
|
||||
|
||||
/* If there are any outstanding VMs, return SQLITE_BUSY. */
|
||||
if( db->pVdbe ){
|
||||
sqlite3Error(db, SQLITE_BUSY,
|
||||
"unable to close due to unfinalised statements");
|
||||
/* Legacy behavior (sqlite3_close() behavior) is to return
|
||||
** SQLITE_BUSY if the connection can not be closed immediately.
|
||||
*/
|
||||
if( !forceZombie && connectionIsBusy(db) ){
|
||||
sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized "
|
||||
"statements or unfinished backups");
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_BUSY;
|
||||
}
|
||||
assert( sqlite3SafetyCheckSickOrOk(db) );
|
||||
|
||||
for(j=0; j<db->nDb; j++){
|
||||
Btree *pBt = db->aDb[j].pBt;
|
||||
if( pBt && sqlite3BtreeIsInBackup(pBt) ){
|
||||
sqlite3Error(db, SQLITE_BUSY,
|
||||
"unable to close due to unfinished backup operation");
|
||||
/* Convert the connection into a zombie and then close it.
|
||||
*/
|
||||
db->magic = SQLITE_MAGIC_ZOMBIE;
|
||||
sqlite3LeaveMutexAndCloseZombie(db);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Two variations on the public interface for closing a database
|
||||
** connection. The sqlite3_close() version returns SQLITE_BUSY and
|
||||
** leaves the connection option if there are unfinalized prepared
|
||||
** statements or unfinished sqlite3_backups. The sqlite3_close_v2()
|
||||
** version forces the connection to become a zombie if there are
|
||||
** unclosed resources, and arranges for deallocation when the last
|
||||
** prepare statement or sqlite3_backup closes.
|
||||
*/
|
||||
int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); }
|
||||
int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); }
|
||||
|
||||
|
||||
/*
|
||||
** Close the mutex on database connection db.
|
||||
**
|
||||
** Furthermore, if database connection db is a zombie (meaning that there
|
||||
** has been a prior call to sqlite3_close(db) or sqlite3_close_v2(db)) and
|
||||
** every sqlite3_stmt has now been finalized and every sqlite3_backup has
|
||||
** finished, then free all resources.
|
||||
*/
|
||||
void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
||||
HashElem *i; /* Hash table iterator */
|
||||
int j;
|
||||
|
||||
/* If there are outstanding sqlite3_stmt or sqlite3_backup objects
|
||||
** or if the connection has not yet been closed by sqlite3_close_v2(),
|
||||
** then just leave the mutex and return.
|
||||
*/
|
||||
if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_BUSY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we reach this point, it means that the database connection has
|
||||
** closed all sqlite3_stmt and sqlite3_backup objects and has been
|
||||
** pased to sqlite3_close (meaning that it is a zombie). Therefore,
|
||||
** go ahead and free all resources.
|
||||
*/
|
||||
|
||||
/* Free any outstanding Savepoint structures. */
|
||||
sqlite3CloseSavepoints(db);
|
||||
|
||||
@ -898,7 +948,6 @@ int sqlite3_close(sqlite3 *db){
|
||||
sqlite3_free(db->lookaside.pStart);
|
||||
}
|
||||
sqlite3_free(db);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -36,8 +36,6 @@
|
||||
** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix.
|
||||
**
|
||||
** SQLITE_MUTEX_W32 For multi-threaded applications on Win32.
|
||||
**
|
||||
** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2.
|
||||
*/
|
||||
#if !SQLITE_THREADSAFE
|
||||
# define SQLITE_MUTEX_OMIT
|
||||
@ -47,8 +45,6 @@
|
||||
# define SQLITE_MUTEX_PTHREADS
|
||||
# elif SQLITE_OS_WIN
|
||||
# define SQLITE_MUTEX_W32
|
||||
# elif SQLITE_OS_OS2
|
||||
# define SQLITE_MUTEX_OS2
|
||||
# else
|
||||
# define SQLITE_MUTEX_NOOP
|
||||
# endif
|
||||
|
274
src/mutex_os2.c
274
src/mutex_os2.c
@ -1,274 +0,0 @@
|
||||
/*
|
||||
** 2007 August 28
|
||||
**
|
||||
** 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 the C functions that implement mutexes for OS/2
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
|
||||
** See the mutex.h file for details.
|
||||
*/
|
||||
#ifdef SQLITE_MUTEX_OS2
|
||||
|
||||
/********************** OS/2 Mutex Implementation **********************
|
||||
**
|
||||
** This implementation of mutexes is built using the OS/2 API.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The mutex object
|
||||
** Each recursive mutex is an instance of the following structure.
|
||||
*/
|
||||
struct sqlite3_mutex {
|
||||
HMTX mutex; /* Mutex controlling the lock */
|
||||
int id; /* Mutex type */
|
||||
#ifdef SQLITE_DEBUG
|
||||
int trace; /* True to trace changes */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
#define SQLITE3_MUTEX_INITIALIZER { 0, 0, 0 }
|
||||
#else
|
||||
#define SQLITE3_MUTEX_INITIALIZER { 0, 0 }
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Initialize and deinitialize the mutex subsystem.
|
||||
*/
|
||||
static int os2MutexInit(void){ return SQLITE_OK; }
|
||||
static int os2MutexEnd(void){ return SQLITE_OK; }
|
||||
|
||||
/*
|
||||
** The sqlite3_mutex_alloc() routine allocates a new
|
||||
** mutex and returns a pointer to it. If it returns NULL
|
||||
** that means that a mutex could not be allocated.
|
||||
** SQLite will unwind its stack and return an error. The argument
|
||||
** to sqlite3_mutex_alloc() is one of these integer constants:
|
||||
**
|
||||
** <ul>
|
||||
** <li> SQLITE_MUTEX_FAST
|
||||
** <li> SQLITE_MUTEX_RECURSIVE
|
||||
** <li> SQLITE_MUTEX_STATIC_MASTER
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM2
|
||||
** <li> SQLITE_MUTEX_STATIC_PRNG
|
||||
** <li> SQLITE_MUTEX_STATIC_LRU
|
||||
** <li> SQLITE_MUTEX_STATIC_LRU2
|
||||
** </ul>
|
||||
**
|
||||
** The first two constants cause sqlite3_mutex_alloc() to create
|
||||
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
|
||||
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
|
||||
** The mutex implementation does not need to make a distinction
|
||||
** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
|
||||
** not want to. But SQLite will only request a recursive mutex in
|
||||
** cases where it really needs one. If a faster non-recursive mutex
|
||||
** implementation is available on the host platform, the mutex subsystem
|
||||
** might return such a mutex in response to SQLITE_MUTEX_FAST.
|
||||
**
|
||||
** The other allowed parameters to sqlite3_mutex_alloc() each return
|
||||
** a pointer to a static preexisting mutex. Six static mutexes are
|
||||
** used by the current version of SQLite. Future versions of SQLite
|
||||
** may add additional static mutexes. Static mutexes are for internal
|
||||
** use by SQLite only. Applications that use SQLite mutexes should
|
||||
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
|
||||
** SQLITE_MUTEX_RECURSIVE.
|
||||
**
|
||||
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
|
||||
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
|
||||
** returns a different mutex on every call. But for the static
|
||||
** mutex types, the same mutex is returned on every call that has
|
||||
** the same type number.
|
||||
*/
|
||||
static sqlite3_mutex *os2MutexAlloc(int iType){
|
||||
sqlite3_mutex *p = NULL;
|
||||
switch( iType ){
|
||||
case SQLITE_MUTEX_FAST:
|
||||
case SQLITE_MUTEX_RECURSIVE: {
|
||||
p = sqlite3MallocZero( sizeof(*p) );
|
||||
if( p ){
|
||||
p->id = iType;
|
||||
if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
|
||||
sqlite3_free( p );
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
static volatile int isInit = 0;
|
||||
static sqlite3_mutex staticMutexes[6] = {
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
};
|
||||
if ( !isInit ){
|
||||
APIRET rc;
|
||||
PTIB ptib;
|
||||
PPIB ppib;
|
||||
HMTX mutex;
|
||||
char name[32];
|
||||
DosGetInfoBlocks( &ptib, &ppib );
|
||||
sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x",
|
||||
ppib->pib_ulpid );
|
||||
while( !isInit ){
|
||||
mutex = 0;
|
||||
rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
|
||||
if( rc == NO_ERROR ){
|
||||
unsigned int i;
|
||||
if( !isInit ){
|
||||
for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
|
||||
DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
|
||||
}
|
||||
isInit = 1;
|
||||
}
|
||||
DosCloseMutexSem( mutex );
|
||||
}else if( rc == ERROR_DUPLICATE_NAME ){
|
||||
DosSleep( 1 );
|
||||
}else{
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( iType-2 >= 0 );
|
||||
assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
|
||||
p = &staticMutexes[iType-2];
|
||||
p->id = iType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This routine deallocates a previously allocated mutex.
|
||||
** SQLite is careful to deallocate every mutex that it allocates.
|
||||
*/
|
||||
static void os2MutexFree(sqlite3_mutex *p){
|
||||
#ifdef SQLITE_DEBUG
|
||||
TID tid;
|
||||
PID pid;
|
||||
ULONG ulCount;
|
||||
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
|
||||
assert( ulCount==0 );
|
||||
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
|
||||
#endif
|
||||
DosCloseMutexSem( p->mutex );
|
||||
sqlite3_free( p );
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
|
||||
** intended for use inside assert() statements.
|
||||
*/
|
||||
static int os2MutexHeld(sqlite3_mutex *p){
|
||||
TID tid;
|
||||
PID pid;
|
||||
ULONG ulCount;
|
||||
PTIB ptib;
|
||||
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
|
||||
if( ulCount==0 || ( ulCount>1 && p->id!=SQLITE_MUTEX_RECURSIVE ) )
|
||||
return 0;
|
||||
DosGetInfoBlocks(&ptib, NULL);
|
||||
return tid==ptib->tib_ptib2->tib2_ultid;
|
||||
}
|
||||
static int os2MutexNotheld(sqlite3_mutex *p){
|
||||
TID tid;
|
||||
PID pid;
|
||||
ULONG ulCount;
|
||||
PTIB ptib;
|
||||
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
|
||||
if( ulCount==0 )
|
||||
return 1;
|
||||
DosGetInfoBlocks(&ptib, NULL);
|
||||
return tid!=ptib->tib_ptib2->tib2_ultid;
|
||||
}
|
||||
static void os2MutexTrace(sqlite3_mutex *p, char *pAction){
|
||||
TID tid;
|
||||
PID pid;
|
||||
ULONG ulCount;
|
||||
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
|
||||
printf("%s mutex %p (%d) with nRef=%ld\n", pAction, (void*)p, p->trace, ulCount);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
|
||||
** to enter a mutex. If another thread is already within the mutex,
|
||||
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
|
||||
** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
|
||||
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
|
||||
** be entered multiple times by the same thread. In such cases the,
|
||||
** mutex must be exited an equal number of times before another thread
|
||||
** can enter. If the same thread tries to enter any other kind of mutex
|
||||
** more than once, the behavior is undefined.
|
||||
*/
|
||||
static void os2MutexEnter(sqlite3_mutex *p){
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
|
||||
DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ) os2MutexTrace(p, "enter");
|
||||
#endif
|
||||
}
|
||||
static int os2MutexTry(sqlite3_mutex *p){
|
||||
int rc = SQLITE_BUSY;
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
|
||||
if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR ) {
|
||||
rc = SQLITE_OK;
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ) os2MutexTrace(p, "try");
|
||||
#endif
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_mutex_leave() routine exits a mutex that was
|
||||
** previously entered by the same thread. The behavior
|
||||
** is undefined if the mutex is not currently entered or
|
||||
** is not currently allocated. SQLite will never do either.
|
||||
*/
|
||||
static void os2MutexLeave(sqlite3_mutex *p){
|
||||
assert( os2MutexHeld(p) );
|
||||
DosReleaseMutexSem(p->mutex);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ) os2MutexTrace(p, "leave");
|
||||
#endif
|
||||
}
|
||||
|
||||
sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
|
||||
static const sqlite3_mutex_methods sMutex = {
|
||||
os2MutexInit,
|
||||
os2MutexEnd,
|
||||
os2MutexAlloc,
|
||||
os2MutexFree,
|
||||
os2MutexEnter,
|
||||
os2MutexTry,
|
||||
os2MutexLeave,
|
||||
#ifdef SQLITE_DEBUG
|
||||
os2MutexHeld,
|
||||
os2MutexNotheld
|
||||
#else
|
||||
0,
|
||||
0
|
||||
#endif
|
||||
};
|
||||
|
||||
return &sMutex;
|
||||
}
|
||||
#endif /* SQLITE_MUTEX_OS2 */
|
@ -109,7 +109,7 @@ static int winMutex_isInit = 0;
|
||||
*/
|
||||
static long winMutex_lock = 0;
|
||||
|
||||
extern void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
|
||||
void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
|
||||
|
||||
static int winMutexInit(void){
|
||||
/* The first to increment to 1 does actual initialization */
|
||||
|
30
src/os.h
30
src/os.h
@ -23,7 +23,7 @@
|
||||
/*
|
||||
** Figure out if we are dealing with Unix, Windows, or some other
|
||||
** operating system. After the following block of preprocess macros,
|
||||
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER
|
||||
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
|
||||
** will defined to either 1 or 0. One of the four will be 1. The other
|
||||
** three will be 0.
|
||||
*/
|
||||
@ -33,8 +33,6 @@
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# undef SQLITE_OS_OS2
|
||||
# define SQLITE_OS_OS2 0
|
||||
# else
|
||||
# undef SQLITE_OS_OTHER
|
||||
# endif
|
||||
@ -45,19 +43,12 @@
|
||||
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
|
||||
# define SQLITE_OS_WIN 1
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# define SQLITE_OS_OS2 0
|
||||
# elif defined(__EMX__) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__)
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# define SQLITE_OS_OS2 1
|
||||
# else
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 1
|
||||
# define SQLITE_OS_OS2 0
|
||||
# endif
|
||||
# else
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# define SQLITE_OS_OS2 0
|
||||
# endif
|
||||
#else
|
||||
# ifndef SQLITE_OS_WIN
|
||||
@ -69,21 +60,6 @@
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_OS2
|
||||
# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY)
|
||||
# include <os2safe.h> /* has to be included before os2.h for linking to work */
|
||||
# endif
|
||||
# define INCL_DOSDATETIME
|
||||
# define INCL_DOSFILEMGR
|
||||
# define INCL_DOSERRORS
|
||||
# define INCL_DOSMISC
|
||||
# define INCL_DOSPROCESS
|
||||
# define INCL_DOSMODULEMGR
|
||||
# define INCL_DOSSEMAPHORES
|
||||
# include <os2.h>
|
||||
# include <uconv.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows NT.
|
||||
**
|
||||
@ -116,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
|
||||
|
1924
src/os_os2.c
1924
src/os_os2.c
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
88
src/os_win.c
88
src/os_win.c
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
16
src/pragma.c
16
src/pragma.c
@ -1173,6 +1173,19 @@ void sqlite3Pragma(
|
||||
|
||||
int isQuick = (sqlite3Tolower(zLeft[0])=='q');
|
||||
|
||||
/* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
|
||||
** then iDb is set to the index of the database identified by <db>.
|
||||
** In this case, the integrity of database iDb only is verified by
|
||||
** the VDBE created below.
|
||||
**
|
||||
** Otherwise, if the command was simply "PRAGMA integrity_check" (or
|
||||
** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb
|
||||
** to -1 here, to indicate that the VDBE should verify the integrity
|
||||
** of all attached databases. */
|
||||
assert( iDb>=0 );
|
||||
assert( iDb==0 || pId2->z );
|
||||
if( pId2->z==0 ) iDb = -1;
|
||||
|
||||
/* Initialize the VDBE program */
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
pParse->nMem = 6;
|
||||
@ -1196,6 +1209,7 @@ void sqlite3Pragma(
|
||||
int cnt = 0;
|
||||
|
||||
if( OMIT_TEMPDB && i==1 ) continue;
|
||||
if( iDb>=0 && i!=iDb ) continue;
|
||||
|
||||
sqlite3CodeVerifySchema(pParse, i);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
|
||||
@ -1207,7 +1221,7 @@ void sqlite3Pragma(
|
||||
** Begin by filling registers 2, 3, ... with the root pages numbers
|
||||
** for all tables and indices in the database.
|
||||
*/
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
assert( sqlite3SchemaMutexHeld(db, i, 0) );
|
||||
pTbls = &db->aDb[i].pSchema->tblHash;
|
||||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
|
16
src/printf.c
16
src/printf.c
@ -124,7 +124,8 @@ static const et_info fmtinfo[] = {
|
||||
static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
|
||||
int digit;
|
||||
LONGDOUBLE_TYPE d;
|
||||
if( (*cnt)++ >= 16 ) return '0';
|
||||
if( (*cnt)<=0 ) return '0';
|
||||
(*cnt)--;
|
||||
digit = (int)*val;
|
||||
d = digit;
|
||||
digit += '0';
|
||||
@ -428,9 +429,12 @@ void sqlite3VXPrintf(
|
||||
break;
|
||||
}
|
||||
if( realvalue>0.0 ){
|
||||
while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
|
||||
while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
|
||||
while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
|
||||
LONGDOUBLE_TYPE scale = 1.0;
|
||||
while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
|
||||
while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; }
|
||||
while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; }
|
||||
while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
|
||||
realvalue /= scale;
|
||||
while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
|
||||
while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
|
||||
if( exp>350 ){
|
||||
@ -463,7 +467,7 @@ void sqlite3VXPrintf(
|
||||
xtype = etFLOAT;
|
||||
}
|
||||
}else{
|
||||
flag_rtz = 0;
|
||||
flag_rtz = flag_altform2;
|
||||
}
|
||||
if( xtype==etEXP ){
|
||||
e2 = 0;
|
||||
@ -478,7 +482,7 @@ void sqlite3VXPrintf(
|
||||
}
|
||||
}
|
||||
zOut = bufpt;
|
||||
nsd = 0;
|
||||
nsd = 16 + flag_altform2*10;
|
||||
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
|
||||
/* The sign in front of the number */
|
||||
if( prefix ){
|
||||
|
@ -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 ){
|
||||
@ -154,6 +185,7 @@ static int lookupName(
|
||||
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;
|
||||
|
@ -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
|
||||
|
139
src/select.c
139
src/select.c
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
|
26
src/shell.c
26
src/shell.c
@ -36,7 +36,7 @@
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__)
|
||||
#if !defined(_WIN32) && !defined(WIN32)
|
||||
# include <signal.h>
|
||||
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
# include <pwd.h>
|
||||
@ -45,10 +45,6 @@
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef __OS2__
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EDITLINE
|
||||
# include <editline/editline.h>
|
||||
#endif
|
||||
@ -68,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.
|
||||
@ -92,7 +90,7 @@ static int enableTimer = 0;
|
||||
#define IsDigit(X) isdigit((unsigned char)X)
|
||||
#define ToLower(X) (char)tolower((unsigned char)X)
|
||||
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL)
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
@ -1453,6 +1451,7 @@ static int process_input(struct callback_data *p, FILE *in);
|
||||
*/
|
||||
static void open_db(struct callback_data *p){
|
||||
if( p->db==0 ){
|
||||
sqlite3_initialize();
|
||||
sqlite3_open(p->zDbFilename, &p->db);
|
||||
db = p->db;
|
||||
if( db && sqlite3_errcode(db)==SQLITE_OK ){
|
||||
@ -2468,7 +2467,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
open_db(p);
|
||||
output_file_close(p->traceOut);
|
||||
p->traceOut = output_file_open(azArg[1]);
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
||||
if( p->traceOut==0 ){
|
||||
sqlite3_trace(p->db, 0, 0);
|
||||
}else{
|
||||
@ -2696,12 +2695,14 @@ static char *find_home_dir(void){
|
||||
static char *home_dir = NULL;
|
||||
if( home_dir ) return home_dir;
|
||||
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
{
|
||||
struct passwd *pwent;
|
||||
uid_t uid = getuid();
|
||||
if( (pwent=getpwuid(uid)) != NULL) {
|
||||
home_dir = pwent->pw_dir;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
@ -2710,7 +2711,7 @@ static char *find_home_dir(void){
|
||||
home_dir = "/";
|
||||
#else
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
if (!home_dir) {
|
||||
home_dir = getenv("USERPROFILE");
|
||||
}
|
||||
@ -2720,7 +2721,7 @@ static char *find_home_dir(void){
|
||||
home_dir = getenv("HOME");
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
if (!home_dir) {
|
||||
char *zDrive, *zPath;
|
||||
int n;
|
||||
@ -2773,6 +2774,7 @@ static int process_sqliterc(
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
sqlite3_initialize();
|
||||
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
|
||||
sqliterc = zBuf;
|
||||
}
|
||||
@ -2936,11 +2938,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
}
|
||||
if( i<argc ){
|
||||
#if defined(SQLITE_OS_OS2) && SQLITE_OS_OS2
|
||||
data.zDbFilename = (const char *)convertCpPathToUtf8( argv[i++] );
|
||||
#else
|
||||
data.zDbFilename = argv[i++];
|
||||
#endif
|
||||
}else{
|
||||
#ifndef SQLITE_OMIT_MEMORYDB
|
||||
data.zDbFilename = ":memory:";
|
||||
|
@ -214,7 +214,8 @@ int sqlite3_threadsafe(void);
|
||||
** the opaque structure named "sqlite3". It is useful to think of an sqlite3
|
||||
** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and
|
||||
** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
|
||||
** is its destructor. There are many other interfaces (such as
|
||||
** and [sqlite3_close_v2()] are its destructors. There are many other
|
||||
** interfaces (such as
|
||||
** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
|
||||
** [sqlite3_busy_timeout()] to name but three) that are methods on an
|
||||
** sqlite3 object.
|
||||
@ -261,28 +262,46 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
/*
|
||||
** CAPI3REF: Closing A Database Connection
|
||||
**
|
||||
** ^The sqlite3_close() routine is the destructor for the [sqlite3] object.
|
||||
** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is
|
||||
** successfully destroyed and all associated resources are deallocated.
|
||||
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
|
||||
** for the [sqlite3] object.
|
||||
** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
|
||||
** the [sqlite3] object is successfully destroyed and all associated
|
||||
** resources are deallocated.
|
||||
**
|
||||
** Applications must [sqlite3_finalize | finalize] all [prepared statements]
|
||||
** and [sqlite3_blob_close | close] all [BLOB handles] associated with
|
||||
** the [sqlite3] object prior to attempting to close the object. ^If
|
||||
** ^If the database connection is associated with unfinalized prepared
|
||||
** statements or unfinished sqlite3_backup objects then sqlite3_close()
|
||||
** will leave the database connection open and return [SQLITE_BUSY].
|
||||
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
|
||||
** and unfinished sqlite3_backups, then the database connection becomes
|
||||
** an unusable "zombie" which will automatically be deallocated when the
|
||||
** last prepared statement is finalized or the last sqlite3_backup is
|
||||
** finished. The sqlite3_close_v2() interface is intended for use with
|
||||
** host languages that are garbage collected, and where the order in which
|
||||
** destructors are called is arbitrary.
|
||||
**
|
||||
** Applications should [sqlite3_finalize | finalize] all [prepared statements],
|
||||
** [sqlite3_blob_close | close] all [BLOB handles], and
|
||||
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
|
||||
** with the [sqlite3] object prior to attempting to close the object. ^If
|
||||
** sqlite3_close() is called on a [database connection] that still has
|
||||
** outstanding [prepared statements] or [BLOB handles], then it returns
|
||||
** SQLITE_BUSY.
|
||||
** outstanding [prepared statements], [BLOB handles], and/or
|
||||
** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
|
||||
** of resources is deferred until all [prepared statements], [BLOB handles],
|
||||
** and [sqlite3_backup] objects are also destroyed.
|
||||
**
|
||||
** ^If [sqlite3_close()] is invoked while a transaction is open,
|
||||
** ^If an [sqlite3] object is destroyed while a transaction is open,
|
||||
** the transaction is automatically rolled back.
|
||||
**
|
||||
** The C parameter to [sqlite3_close(C)] must be either a NULL
|
||||
** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
|
||||
** must be either a NULL
|
||||
** pointer or an [sqlite3] object pointer obtained
|
||||
** from [sqlite3_open()], [sqlite3_open16()], or
|
||||
** [sqlite3_open_v2()], and not previously closed.
|
||||
** ^Calling sqlite3_close() with a NULL pointer argument is a
|
||||
** harmless no-op.
|
||||
** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
|
||||
** argument is a harmless no-op.
|
||||
*/
|
||||
int sqlite3_close(sqlite3*);
|
||||
int sqlite3_close_v2(sqlite3*);
|
||||
|
||||
/*
|
||||
** The type for a callback function.
|
||||
@ -493,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.
|
||||
@ -2643,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) */
|
||||
@ -3135,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
|
||||
@ -4133,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
|
||||
@ -4444,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;
|
||||
|
||||
@ -5489,7 +5532,6 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
|
||||
** implementations are available in the SQLite core:
|
||||
**
|
||||
** <ul>
|
||||
** <li> SQLITE_MUTEX_OS2
|
||||
** <li> SQLITE_MUTEX_PTHREADS
|
||||
** <li> SQLITE_MUTEX_W32
|
||||
** <li> SQLITE_MUTEX_NOOP
|
||||
@ -5497,9 +5539,9 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
|
||||
**
|
||||
** ^The SQLITE_MUTEX_NOOP implementation is a set of routines
|
||||
** that does no real locking and is appropriate for use in
|
||||
** a single-threaded application. ^The SQLITE_MUTEX_OS2,
|
||||
** SQLITE_MUTEX_PTHREADS, and SQLITE_MUTEX_W32 implementations
|
||||
** are appropriate for use on OS/2, Unix, and Windows.
|
||||
** a single-threaded application. ^The SQLITE_MUTEX_PTHREADS and
|
||||
** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
|
||||
** and Windows.
|
||||
**
|
||||
** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
|
||||
** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
|
||||
|
69
src/sqlite3.rc
Normal file
69
src/sqlite3.rc
Normal file
@ -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
|
@ -149,6 +149,7 @@
|
||||
**
|
||||
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
|
||||
** SQLITE_WIN32_MALLOC // Use Win32 native heap API
|
||||
** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
|
||||
** SQLITE_MEMDEBUG // Debugging version of system malloc()
|
||||
**
|
||||
** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
|
||||
@ -162,11 +163,19 @@
|
||||
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
|
||||
** the default.
|
||||
*/
|
||||
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
|
||||
# error "At most one of the following compile-time configuration options\
|
||||
is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG"
|
||||
#if defined(SQLITE_SYSTEM_MALLOC) \
|
||||
+ defined(SQLITE_WIN32_MALLOC) \
|
||||
+ defined(SQLITE_ZERO_MALLOC) \
|
||||
+ defined(SQLITE_MEMDEBUG)>1
|
||||
# error "Two or more of the following compile-time configuration options\
|
||||
are defined but at most one is allowed:\
|
||||
SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
|
||||
SQLITE_ZERO_MALLOC"
|
||||
#endif
|
||||
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
|
||||
#if defined(SQLITE_SYSTEM_MALLOC) \
|
||||
+ defined(SQLITE_WIN32_MALLOC) \
|
||||
+ defined(SQLITE_ZERO_MALLOC) \
|
||||
+ defined(SQLITE_MEMDEBUG)==0
|
||||
# define SQLITE_SYSTEM_MALLOC 1
|
||||
#endif
|
||||
|
||||
@ -974,6 +983,7 @@ struct sqlite3 {
|
||||
#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */
|
||||
#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */
|
||||
#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */
|
||||
#define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */
|
||||
|
||||
/*
|
||||
** Each SQL function is defined by an instance of the following
|
||||
@ -1680,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
|
||||
@ -1906,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
|
||||
@ -1936,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
|
||||
@ -2108,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 */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2307,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
|
||||
@ -2486,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;
|
||||
};
|
||||
|
||||
@ -2791,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);
|
||||
@ -2823,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);
|
||||
@ -2835,6 +2853,7 @@ void sqlite3CommitTransaction(Parse*);
|
||||
void sqlite3RollbackTransaction(Parse*);
|
||||
void sqlite3Savepoint(Parse*, int, Token*);
|
||||
void sqlite3CloseSavepoints(sqlite3 *);
|
||||
void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
||||
int sqlite3ExprIsConstant(Expr*);
|
||||
int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*);
|
||||
|
@ -53,15 +53,8 @@
|
||||
#define NUM_PREPARED_STMTS 10
|
||||
#define MAX_PREPARED_STMTS 100
|
||||
|
||||
/*
|
||||
** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
|
||||
** have to do a translation when going between the two. Set the
|
||||
** UTF_TRANSLATION_NEEDED macro to indicate that we need to do
|
||||
** this translation.
|
||||
*/
|
||||
#if defined(TCL_UTF_MAX) && !defined(SQLITE_UTF8)
|
||||
# define UTF_TRANSLATION_NEEDED 1
|
||||
#endif
|
||||
/* Forward declaration */
|
||||
typedef struct SqliteDb SqliteDb;
|
||||
|
||||
/*
|
||||
** New SQL functions can be created as TCL scripts. Each such function
|
||||
@ -71,6 +64,7 @@ typedef struct SqlFunc SqlFunc;
|
||||
struct SqlFunc {
|
||||
Tcl_Interp *interp; /* The TCL interpret to execute the function */
|
||||
Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */
|
||||
SqliteDb *pDb; /* Database connection that owns this function */
|
||||
int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */
|
||||
char *zName; /* Name of this function */
|
||||
SqlFunc *pNext; /* Next function on the list of them all */
|
||||
@ -113,7 +107,6 @@ typedef struct IncrblobChannel IncrblobChannel;
|
||||
** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements.
|
||||
** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used.
|
||||
*/
|
||||
typedef struct SqliteDb SqliteDb;
|
||||
struct SqliteDb {
|
||||
sqlite3 *db; /* The "real" database structure. MUST BE FIRST */
|
||||
Tcl_Interp *interp; /* The interpreter used for this database */
|
||||
@ -431,6 +424,7 @@ static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
|
||||
}
|
||||
}
|
||||
pNew->interp = pDb->interp;
|
||||
pNew->pDb = pDb;
|
||||
pNew->pScript = 0;
|
||||
pNew->pNext = pDb->pFunc;
|
||||
pDb->pFunc = pNew;
|
||||
@ -478,6 +472,7 @@ static void DbDeleteCmd(void *db){
|
||||
while( pDb->pFunc ){
|
||||
SqlFunc *pFunc = pDb->pFunc;
|
||||
pDb->pFunc = pFunc->pNext;
|
||||
assert( pFunc->pDb==pDb );
|
||||
Tcl_DecrRefCount(pFunc->pScript);
|
||||
Tcl_Free((char*)pFunc);
|
||||
}
|
||||
@ -794,7 +789,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
||||
break;
|
||||
}
|
||||
case SQLITE_NULL: {
|
||||
pVal = Tcl_NewStringObj("", 0);
|
||||
pVal = Tcl_NewStringObj(p->pDb->zNull, -1);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -933,26 +928,6 @@ static int auth_callback(
|
||||
}
|
||||
#endif /* SQLITE_OMIT_AUTHORIZATION */
|
||||
|
||||
/*
|
||||
** zText is a pointer to text obtained via an sqlite3_result_text()
|
||||
** or similar interface. This routine returns a Tcl string object,
|
||||
** reference count set to 0, containing the text. If a translation
|
||||
** between iso8859 and UTF-8 is required, it is preformed.
|
||||
*/
|
||||
static Tcl_Obj *dbTextToObj(char const *zText){
|
||||
Tcl_Obj *pVal;
|
||||
#ifdef UTF_TRANSLATION_NEEDED
|
||||
Tcl_DString dCol;
|
||||
Tcl_DStringInit(&dCol);
|
||||
Tcl_ExternalToUtfDString(NULL, zText, -1, &dCol);
|
||||
pVal = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1);
|
||||
Tcl_DStringFree(&dCol);
|
||||
#else
|
||||
pVal = Tcl_NewStringObj(zText, -1);
|
||||
#endif
|
||||
return pVal;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine reads a line of text from FILE in, stores
|
||||
** the text in memory obtained from malloc() and returns a pointer
|
||||
@ -1140,13 +1115,13 @@ static int dbPrepareAndBind(
|
||||
int nByte;
|
||||
|
||||
if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
|
||||
Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( pStmt==0 ){
|
||||
if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
|
||||
/* A compile-time error in the statement. */
|
||||
Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
|
||||
return TCL_ERROR;
|
||||
}else{
|
||||
/* The statement was a no-op. Continue to the next statement
|
||||
@ -1365,7 +1340,7 @@ static void dbEvalRowInfo(
|
||||
if( nCol>0 && (papColName || p->pArray) ){
|
||||
apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
|
||||
for(i=0; i<nCol; i++){
|
||||
apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i));
|
||||
apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
|
||||
Tcl_IncrRefCount(apColName[i]);
|
||||
}
|
||||
p->apColName = apColName;
|
||||
@ -1452,7 +1427,8 @@ static int dbEvalStep(DbEvalContext *p){
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
Tcl_SetObjResult(pDb->interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
|
||||
Tcl_SetObjResult(pDb->interp,
|
||||
Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
|
||||
return TCL_ERROR;
|
||||
}else{
|
||||
dbReleaseStmt(pDb, pPreStmt, 0);
|
||||
@ -1509,11 +1485,11 @@ static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){
|
||||
return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol));
|
||||
}
|
||||
case SQLITE_NULL: {
|
||||
return dbTextToObj(p->pDb->zNull);
|
||||
return Tcl_NewStringObj(p->pDb->zNull, -1);
|
||||
}
|
||||
}
|
||||
|
||||
return dbTextToObj((char *)sqlite3_column_text(pStmt, iCol));
|
||||
return Tcl_NewStringObj(sqlite3_column_text(pStmt, iCol), -1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2433,7 +2409,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
pDb->zNull = 0;
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull));
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(pDb->zNull, -1));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
24
src/test8.c
24
src/test8.c
@ -1370,6 +1370,29 @@ static int declare_vtab(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#include "test_spellfix.c"
|
||||
|
||||
/*
|
||||
** Register the spellfix virtual table module.
|
||||
*/
|
||||
static int register_spellfix_module(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
sqlite3Spellfix1Register(db);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
/*
|
||||
@ -1383,6 +1406,7 @@ int Sqlitetest8_Init(Tcl_Interp *interp){
|
||||
void *clientData;
|
||||
} aObjCmd[] = {
|
||||
{ "register_echo_module", register_echo_module, 0 },
|
||||
{ "register_spellfix_module", register_spellfix_module, 0 },
|
||||
{ "sqlite3_declare_vtab", declare_vtab, 0 },
|
||||
};
|
||||
int i;
|
||||
|
@ -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
|
||||
@ -616,6 +622,21 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
|
||||
Tcl_LinkVar(interp, "TEMP_STORE", (char *)&(cv_TEMP_STORE),
|
||||
TCL_LINK_INT | TCL_LINK_READ_ONLY);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
{
|
||||
static const int cv__MSC_VER = 1;
|
||||
Tcl_LinkVar(interp, "_MSC_VER", (char *)&(cv__MSC_VER),
|
||||
TCL_LINK_INT | TCL_LINK_READ_ONLY);
|
||||
}
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
{
|
||||
static const int cv___GNUC__ = 1;
|
||||
Tcl_LinkVar(interp, "__GNUC__", (char *)&(cv___GNUC__),
|
||||
TCL_LINK_INT | TCL_LINK_READ_ONLY);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -422,6 +422,43 @@ static void testHexToUtf16le(
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** SQL function: real2hex(X)
|
||||
**
|
||||
** If argument X is a real number, then convert it into a string which is
|
||||
** the big-endian hexadecimal representation of the ieee754 encoding of
|
||||
** that number. If X is not a real number, return NULL.
|
||||
*/
|
||||
static void real2hex(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
union {
|
||||
sqlite3_uint64 i;
|
||||
double r;
|
||||
unsigned char x[8];
|
||||
} v;
|
||||
char zOut[20];
|
||||
int i;
|
||||
int bigEndian;
|
||||
v.i = 1;
|
||||
bigEndian = v.x[0]==0;
|
||||
v.r = sqlite3_value_double(argv[0]);
|
||||
for(i=0; i<8; i++){
|
||||
if( bigEndian ){
|
||||
zOut[i*2] = "0123456789abcdef"[v.x[i]>>4];
|
||||
zOut[i*2+1] = "0123456789abcdef"[v.x[i]&0xf];
|
||||
}else{
|
||||
zOut[14-i*2] = "0123456789abcdef"[v.x[i]>>4];
|
||||
zOut[14-i*2+1] = "0123456789abcdef"[v.x[i]&0xf];
|
||||
}
|
||||
}
|
||||
zOut[16] = 0;
|
||||
sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
|
||||
static int registerTestFunctions(sqlite3 *db){
|
||||
static const struct {
|
||||
char *zName;
|
||||
@ -444,6 +481,7 @@ static int registerTestFunctions(sqlite3 *db){
|
||||
{ "test_eval", 1, SQLITE_UTF8, test_eval},
|
||||
{ "test_isolation", 2, SQLITE_UTF8, test_isolation},
|
||||
{ "test_counter", 1, SQLITE_UTF8, counterFunc},
|
||||
{ "real2hex", 1, SQLITE_UTF8, real2hex},
|
||||
};
|
||||
int i;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -48,7 +48,7 @@
|
||||
/*
|
||||
** Figure out if we are dealing with Unix, Windows, or some other
|
||||
** operating system. After the following block of preprocess macros,
|
||||
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER
|
||||
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
|
||||
** will defined to either 1 or 0. One of the four will be 1. The other
|
||||
** three will be 0.
|
||||
*/
|
||||
@ -58,8 +58,6 @@
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# undef SQLITE_OS_WIN
|
||||
# define SQLITE_OS_WIN 0
|
||||
# undef SQLITE_OS_OS2
|
||||
# define SQLITE_OS_OS2 0
|
||||
# else
|
||||
# undef SQLITE_OS_OTHER
|
||||
# endif
|
||||
@ -71,20 +69,12 @@
|
||||
|| defined(__MINGW32__) || defined(__BORLANDC__)
|
||||
# define SQLITE_OS_WIN 1
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# define SQLITE_OS_OS2 0
|
||||
# elif defined(__EMX__) || defined(_OS2) || defined(OS2) \
|
||||
|| defined(_OS2_) || defined(__OS2__)
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# define SQLITE_OS_OS2 1
|
||||
# else
|
||||
# define SQLITE_OS_WIN 0
|
||||
# define SQLITE_OS_UNIX 1
|
||||
# define SQLITE_OS_OS2 0
|
||||
# endif
|
||||
# else
|
||||
# define SQLITE_OS_UNIX 0
|
||||
# define SQLITE_OS_OS2 0
|
||||
# endif
|
||||
#else
|
||||
# ifndef SQLITE_OS_WIN
|
||||
|
1773
src/test_spellfix.c
1773
src/test_spellfix.c
File diff suppressed because it is too large
Load Diff
@ -81,6 +81,7 @@ struct Testvfs {
|
||||
Tcl_Obj *pScript; /* Script to execute */
|
||||
TestvfsBuffer *pBuffer; /* List of shared buffers */
|
||||
int isNoshm;
|
||||
int isFullshm;
|
||||
|
||||
int mask; /* Mask controlling [script] and [ioerr] */
|
||||
|
||||
@ -360,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);
|
||||
}
|
||||
@ -760,6 +762,7 @@ static int tvfsShmOpen(sqlite3_file *pFile){
|
||||
|
||||
pFd = tvfsGetFd(pFile);
|
||||
p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
assert( 0==p->isFullshm );
|
||||
assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 );
|
||||
|
||||
/* Evaluate the Tcl script:
|
||||
@ -820,6 +823,10 @@ static int tvfsShmMap(
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
|
||||
|
||||
if( p->isFullshm ){
|
||||
return sqlite3OsShmMap(pFd->pReal, iPage, pgsz, isWrite, pp);
|
||||
}
|
||||
|
||||
if( 0==pFd->pShm ){
|
||||
rc = tvfsShmOpen(pFile);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@ -864,6 +871,10 @@ static int tvfsShmLock(
|
||||
int nLock;
|
||||
char zLock[80];
|
||||
|
||||
if( p->isFullshm ){
|
||||
return sqlite3OsShmLock(pFd->pReal, ofst, n, flags);
|
||||
}
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){
|
||||
sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n);
|
||||
nLock = (int)strlen(zLock);
|
||||
@ -919,6 +930,11 @@ static void tvfsShmBarrier(sqlite3_file *pFile){
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
|
||||
|
||||
if( p->isFullshm ){
|
||||
sqlite3OsShmBarrier(pFd->pReal);
|
||||
return;
|
||||
}
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
|
||||
tvfsExecTcl(p, "xShmBarrier",
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
|
||||
@ -936,6 +952,10 @@ static int tvfsShmUnmap(
|
||||
TestvfsBuffer *pBuffer = pFd->pShm;
|
||||
TestvfsFd **ppFd;
|
||||
|
||||
if( p->isFullshm ){
|
||||
return sqlite3OsShmUnmap(pFd->pReal, deleteFlag);
|
||||
}
|
||||
|
||||
if( !pBuffer ) return SQLITE_OK;
|
||||
assert( pFd->pShmId && pFd->pShm );
|
||||
|
||||
@ -1350,6 +1370,7 @@ static int testvfs_cmd(
|
||||
|
||||
int i;
|
||||
int isNoshm = 0; /* True if -noshm is passed */
|
||||
int isFullshm = 0; /* True if -fullshm is passed */
|
||||
int isDefault = 0; /* True if -default is passed */
|
||||
int szOsFile = 0; /* Value passed to -szosfile */
|
||||
int mxPathname = -1; /* Value passed to -mxpathname */
|
||||
@ -1365,6 +1386,7 @@ static int testvfs_cmd(
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( isNoshm ) isFullshm = 0;
|
||||
}
|
||||
else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){
|
||||
@ -1386,6 +1408,12 @@ static int testvfs_cmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
else if( nSwitch>2 && 0==strncmp("-fullshm", zSwitch, nSwitch) ){
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isFullshm) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( isFullshm ) isNoshm = 0;
|
||||
}
|
||||
else{
|
||||
goto bad_args;
|
||||
}
|
||||
@ -1427,6 +1455,7 @@ static int testvfs_cmd(
|
||||
pVfs->szOsFile = szOsFile;
|
||||
p->pVfs = pVfs;
|
||||
p->isNoshm = isNoshm;
|
||||
p->isFullshm = isFullshm;
|
||||
p->mask = TESTVFS_ALL_MASK;
|
||||
|
||||
sqlite3_vfs_register(pVfs, isDefault);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -371,7 +371,7 @@ do_atof_calc:
|
||||
/* if exponent, scale significand as appropriate
|
||||
** and store in result. */
|
||||
if( e ){
|
||||
double scale = 1.0;
|
||||
LONGDOUBLE_TYPE scale = 1.0;
|
||||
/* attempt to handle extremely small/large numbers better */
|
||||
if( e>307 && e<342 ){
|
||||
while( e%308 ) { scale *= 1.0e+1; e -= 1; }
|
||||
|
@ -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. */
|
||||
|
@ -431,11 +431,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
|
||||
|
@ -71,17 +71,11 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){
|
||||
}else{
|
||||
Vdbe *v = (Vdbe*)pStmt;
|
||||
sqlite3 *db = v->db;
|
||||
#if SQLITE_THREADSAFE
|
||||
sqlite3_mutex *mutex;
|
||||
#endif
|
||||
if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
|
||||
#if SQLITE_THREADSAFE
|
||||
mutex = v->db->mutex;
|
||||
#endif
|
||||
sqlite3_mutex_enter(mutex);
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
rc = sqlite3VdbeFinalize(v);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
sqlite3_mutex_leave(mutex);
|
||||
sqlite3LeaveMutexAndCloseZombie(db);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -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.
|
||||
@ -2469,6 +2469,7 @@ void sqlite3VdbeDelete(Vdbe *p){
|
||||
|
||||
if( NEVER(p==0) ) return;
|
||||
db = p->db;
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( p->pPrev ){
|
||||
p->pPrev->pNext = p->pNext;
|
||||
}else{
|
||||
|
436
src/vdbesort.c
436
src/vdbesort.c
@ -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 ){
|
||||
|
||||
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 */
|
||||
){
|
||||
|
@ -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;
|
||||
|
@ -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 ){
|
||||
|
13
src/wal.c
13
src/wal.c
@ -142,14 +142,15 @@
|
||||
** byte order of the host computer.
|
||||
**
|
||||
** The purpose of the wal-index is to answer this question quickly: Given
|
||||
** a page number P, return the index of the last frame for page P in the WAL,
|
||||
** or return NULL if there are no frames for page P in the WAL.
|
||||
** a page number P and a maximum frame index M, return the index of the
|
||||
** last frame in the wal before frame M for page P in the WAL, or return
|
||||
** NULL if there are no frames for page P in the WAL prior to M.
|
||||
**
|
||||
** The wal-index consists of a header region, followed by an one or
|
||||
** 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
|
||||
@ -1198,6 +1199,7 @@ finished:
|
||||
pInfo->nBackfill = 0;
|
||||
pInfo->aReadMark[0] = 0;
|
||||
for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
|
||||
if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
|
||||
|
||||
/* If more than one frame was recovered from the log file, report an
|
||||
** event via sqlite3_log(). This is to help with identifying performance
|
||||
@ -1698,7 +1700,7 @@ static int walCheckpoint(
|
||||
assert( y<=pWal->hdr.mxFrame );
|
||||
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
pInfo->aReadMark[i] = READMARK_NOT_USED;
|
||||
pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
|
||||
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
}else if( rc==SQLITE_BUSY ){
|
||||
mxSafeFrame = y;
|
||||
@ -2611,7 +2613,8 @@ static int walRestartLog(Wal *pWal){
|
||||
aSalt[1] = salt1;
|
||||
walIndexWriteHdr(pWal);
|
||||
pInfo->nBackfill = 0;
|
||||
for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
|
||||
pInfo->aReadMark[1] = 0;
|
||||
for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
|
||||
assert( pInfo->aReadMark[0]==0 );
|
||||
walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
|
||||
}else if( rc!=SQLITE_BUSY ){
|
||||
|
10
src/walker.c
10
src/walker.c
@ -125,12 +125,18 @@ int sqlite3WalkSelect(Walker *pWalker, Select *p){
|
||||
int rc;
|
||||
if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
|
||||
rc = WRC_Continue;
|
||||
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;
|
||||
}
|
||||
|
60
src/where.c
60
src/where.c
@ -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;
|
||||
if( 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) ){
|
||||
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++){
|
||||
|
71
test/aggnested.test
Normal file
71
test/aggnested.test
Normal file
@ -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
|
60
test/atof1.test
Normal file
60
test/atof1.test
Normal file
@ -0,0 +1,60 @@
|
||||
# 2012 June 18
|
||||
#
|
||||
# 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 of the sqlite3AtoF() function.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
if {![info exists __GNUC__]} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
expr srand(1)
|
||||
for {set i 1} {$i<20000} {incr i} {
|
||||
set pow [expr {int((rand()-0.5)*100)}]
|
||||
set x [expr {pow((rand()-0.5)*2*rand(),$pow)}]
|
||||
set xf [format %.32e $x]
|
||||
|
||||
# Verify that text->real conversions get exactly same ieee754 floating-
|
||||
# point value in SQLite as they do in TCL.
|
||||
#
|
||||
do_test atof1-1.$i.1 {
|
||||
set y [db eval "SELECT $xf=\$x"]
|
||||
if {!$y} {
|
||||
puts -nonewline \173[db eval "SELECT real2hex($xf), real2hex(\$x)"]\175
|
||||
db eval "SELECT $xf+0.0 AS a, \$x AS b" {
|
||||
puts [format "\n%.60e\n%.60e\n%.60e" $x $a $b]
|
||||
}
|
||||
}
|
||||
set y
|
||||
} {1}
|
||||
|
||||
# Verify that round-trip real->text->real conversions using the quote()
|
||||
# function preserve the bits of the numeric value exactly.
|
||||
#
|
||||
do_test atof1-1.$i.2 {
|
||||
set y [db eval {SELECT $x=CAST(quote($x) AS real)}]
|
||||
if {!$y} {
|
||||
db eval {SELECT real2hex($x) a, real2hex(CAST(quote($x) AS real)) b} {}
|
||||
puts "\nIN: $a $xf"
|
||||
puts [format {QUOTE: %16s %s} {} [db eval {SELECT quote($x)}]]
|
||||
db eval {SELECT CAST(quote($x) AS real) c} {}
|
||||
puts "OUT: $b [format %.32e $c]"
|
||||
}
|
||||
set y
|
||||
} {1}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
@ -423,7 +423,7 @@ do_test backup-4.3.2 {
|
||||
} {SQLITE_BUSY}
|
||||
do_test backup-4.3.3 {
|
||||
sqlite3_errmsg db2
|
||||
} {unable to close due to unfinished backup operation}
|
||||
} {unable to close due to unfinalized statements or unfinished backups}
|
||||
do_test backup-4.3.4 {
|
||||
B step 50
|
||||
} {SQLITE_DONE}
|
||||
|
@ -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.
|
||||
|
@ -151,7 +151,7 @@ datetest 3.2.1 {strftime('pre%fpost','2003-10-31 12:34:56.432')} pre56.432post
|
||||
datetest 3.2.2 {strftime('%f','2003-10-31 12:34:59.9999999')} 59.999
|
||||
datetest 3.3 {strftime('%H','2003-10-31 12:34:56.432')} 12
|
||||
datetest 3.4 {strftime('%j','2003-10-31 12:34:56.432')} 304
|
||||
datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.02426426
|
||||
datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.024264259
|
||||
datetest 3.6 {strftime('%m','2003-10-31 12:34:56.432')} 10
|
||||
datetest 3.7 {strftime('%M','2003-10-31 12:34:56.432')} 34
|
||||
datetest 3.8.1 {strftime('%s','2003-10-31 12:34:56.432')} 1067603696
|
||||
|
@ -174,6 +174,16 @@ ifcapable icu {
|
||||
insert into x1 (name) values (NULL);
|
||||
delete from x1;
|
||||
}
|
||||
|
||||
proc cp_to_str {codepoint_list} {
|
||||
set fmt [string repeat %c [llength $codepoint_list]]
|
||||
eval [list format $fmt] $codepoint_list
|
||||
}
|
||||
|
||||
do_test 5.2 {
|
||||
set str [cp_to_str {19968 26085 32822 32645 27874 23433 20986}]
|
||||
execsql { INSERT INTO x1 VALUES($str) }
|
||||
} {}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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') }
|
||||
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}
|
||||
|
@ -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,12 +275,15 @@ 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');
|
||||
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} }
|
||||
do_matchinfo_test 4.4.1 t5 {t5 MATCH 'a a'} { s {2 1} }
|
||||
|
@ -1655,6 +1655,7 @@ do_test fts4aa-1.8 {
|
||||
SELECT docid FROM t1_docsize EXCEPT SELECT docid FROM t1
|
||||
}
|
||||
} {}
|
||||
ifcapable fts4_deferred {
|
||||
do_test fts4aa-1.9 {
|
||||
# Note: Token 'in' is being deferred in the following query.
|
||||
db eval {
|
||||
@ -1663,6 +1664,7 @@ do_test fts4aa-1.9 {
|
||||
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
|
||||
#
|
||||
|
@ -326,5 +326,62 @@ do_unicode_token_test3 5.11 "tokenchars=\u0301" \
|
||||
"0 hello\u0301world hello\u0301world 1 helloworld helloworld"
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
proc do_tokenize {tokenizer txt} {
|
||||
set res [list]
|
||||
foreach {a b c} [db one {SELECT fts3_tokenizer_test($tokenizer, $txt)}] {
|
||||
lappend res $b
|
||||
}
|
||||
set res
|
||||
}
|
||||
|
||||
# Argument $lCodepoint must be a list of codepoints (integers) that
|
||||
# correspond to whitespace characters. This command creates a string
|
||||
# $W from the codepoints, then tokenizes "${W}hello{$W}world${W}"
|
||||
# using tokenizer $tokenizer. The test passes if the tokenizer successfully
|
||||
# extracts the two 5 character tokens.
|
||||
#
|
||||
proc do_isspace_test {tn tokenizer lCp} {
|
||||
set whitespace [format [string repeat %c [llength $lCp]] {*}$lCp]
|
||||
set txt "${whitespace}hello${whitespace}world${whitespace}"
|
||||
uplevel [list do_test $tn [list do_tokenize $tokenizer $txt] {hello world}]
|
||||
}
|
||||
|
||||
set tokenizers [list unicode61]
|
||||
ifcapable icu { lappend tokenizers icu }
|
||||
|
||||
# Some tests to check that the tokenizers can both identify white-space
|
||||
# codepoints. All codepoints tested below are of type "Zs" in the
|
||||
# UnicodeData.txt file.
|
||||
foreach T $tokenizers {
|
||||
do_isspace_test 6.$T.1 $T 32
|
||||
do_isspace_test 6.$T.2 $T 160
|
||||
do_isspace_test 6.$T.3 $T 5760
|
||||
do_isspace_test 6.$T.4 $T 6158
|
||||
do_isspace_test 6.$T.5 $T 8192
|
||||
do_isspace_test 6.$T.6 $T 8193
|
||||
do_isspace_test 6.$T.7 $T 8194
|
||||
do_isspace_test 6.$T.8 $T 8195
|
||||
do_isspace_test 6.$T.9 $T 8196
|
||||
do_isspace_test 6.$T.10 $T 8197
|
||||
do_isspace_test 6.$T.11 $T 8198
|
||||
do_isspace_test 6.$T.12 $T 8199
|
||||
do_isspace_test 6.$T.13 $T 8200
|
||||
do_isspace_test 6.$T.14 $T 8201
|
||||
do_isspace_test 6.$T.15 $T 8202
|
||||
do_isspace_test 6.$T.16 $T 8239
|
||||
do_isspace_test 6.$T.17 $T 8287
|
||||
do_isspace_test 6.$T.18 $T 12288
|
||||
|
||||
do_isspace_test 6.$T.19 $T {32 160 5760 6158}
|
||||
do_isspace_test 6.$T.19 $T {8192 8193 8194 8195}
|
||||
do_isspace_test 6.$T.19 $T {8196 8197 8198 8199}
|
||||
do_isspace_test 6.$T.19 $T {8200 8201 8202 8239}
|
||||
do_isspace_test 6.$T.19 $T {8287 12288}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
@ -312,7 +312,7 @@ ifcapable floatingpoint {
|
||||
execsql {SELECT round(9999999999999.55,1);}
|
||||
} {9999999999999.6}
|
||||
do_test func-4.38 {
|
||||
execsql {SELECT round(9999999999999.555,2);}
|
||||
execsql {SELECT round(9999999999999.556,2);}
|
||||
} {9999999999999.56}
|
||||
}
|
||||
|
||||
|
75
test/index5.test
Normal file
75
test/index5.test
Normal file
@ -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
|
||||
|
@ -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.
|
||||
|
@ -23,7 +23,7 @@ ifcapable !load_ext {
|
||||
|
||||
# The name of the test extension varies by operating system.
|
||||
#
|
||||
if {$::tcl_platform(platform) eq "windows" || $::tcl_platform(platform) eq "os2"} {
|
||||
if {$::tcl_platform(platform) eq "windows"} {
|
||||
set testextension ./testloadext.dll
|
||||
} else {
|
||||
set testextension ./libtestloadext.so
|
||||
|
@ -377,7 +377,7 @@ do_test misc7-16.X {
|
||||
# These tests do not work on windows due to restrictions in the
|
||||
# windows file system.
|
||||
#
|
||||
if {$tcl_platform(platform)!="windows" && $tcl_platform(platform)!="os2"} {
|
||||
if {$tcl_platform(platform)!="windows"} {
|
||||
|
||||
# Some network filesystems (ex: AFP) do not support setting read-only
|
||||
# permissions. Only run these tests if full unix permission setting
|
||||
|
@ -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 {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix pragma
|
||||
|
||||
# Do not use a codec for tests in this file, as the database file is
|
||||
# manipulated directly using tcl scripts (using the [hexio_write] command).
|
||||
@ -41,6 +42,8 @@ do_not_use_codec
|
||||
# reset when the schema is reloaded.
|
||||
# pragma-16.*: Test proxy locking
|
||||
# pragma-20.*: Test data_store_directory.
|
||||
# pragma-22.*: Test that "PRAGMA [db].integrity_check" respects the "db"
|
||||
# directive - if it is present.
|
||||
#
|
||||
|
||||
ifcapable !pragma {
|
||||
@ -1554,4 +1557,67 @@ do_test pragma-20.8 {
|
||||
forcedelete data_dir
|
||||
} ;# endif windows
|
||||
|
||||
do_test 21.1 {
|
||||
# Create a corrupt database in testerr.db. And a non-corrupt at test.db.
|
||||
#
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA auto_vacuum = 0;
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
}
|
||||
for {set i 0} {$i < 10} {incr i} {
|
||||
execsql { INSERT INTO t1 SELECT a + (1 << $i), b + (1 << $i) FROM t1 }
|
||||
}
|
||||
db close
|
||||
forcecopy test.db testerr.db
|
||||
hexio_write testerr.db 15000 [string repeat 55 100]
|
||||
} {100}
|
||||
|
||||
set mainerr {*** in database main ***
|
||||
Multiple uses for byte 672 of page 15}
|
||||
set auxerr {*** in database aux ***
|
||||
Multiple uses for byte 672 of page 15}
|
||||
|
||||
do_test 22.2 {
|
||||
catch { db close }
|
||||
sqlite3 db testerr.db
|
||||
execsql { PRAGMA integrity_check }
|
||||
} [list $mainerr]
|
||||
|
||||
do_test 22.3.1 {
|
||||
catch { db close }
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
ATTACH 'testerr.db' AS 'aux';
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} [list $auxerr]
|
||||
do_test 22.3.2 {
|
||||
execsql { PRAGMA main.integrity_check; }
|
||||
} {ok}
|
||||
do_test 22.3.3 {
|
||||
execsql { PRAGMA aux.integrity_check; }
|
||||
} [list $auxerr]
|
||||
|
||||
do_test 22.4.1 {
|
||||
catch { db close }
|
||||
sqlite3 db testerr.db
|
||||
execsql {
|
||||
ATTACH 'test.db' AS 'aux';
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} [list $mainerr]
|
||||
do_test 22.4.2 {
|
||||
execsql { PRAGMA main.integrity_check; }
|
||||
} [list $mainerr]
|
||||
do_test 22.4.3 {
|
||||
execsql { PRAGMA aux.integrity_check; }
|
||||
} {ok}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
@ -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
|
||||
@ -218,8 +228,6 @@ proc run_test_suite {name testtarget config} {
|
||||
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
append opts " -DSQLITE_OS_WIN=1"
|
||||
} elseif {$::tcl_platform(platform)=="os2"} {
|
||||
append opts " -DSQLITE_OS_OS2=1"
|
||||
} else {
|
||||
append opts " -DSQLITE_OS_UNIX=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
|
||||
|
95
test/securedel2.test
Normal file
95
test/securedel2.test
Normal file
@ -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
|
||||
|
151
test/spellfix.test
Normal file
151
test/spellfix.test
Normal file
@ -0,0 +1,151 @@
|
||||
# 2012 July 12
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix spellfix
|
||||
|
||||
ifcapable !vtab { finish_test ; return }
|
||||
|
||||
register_spellfix_module db
|
||||
|
||||
set vocab {
|
||||
rabbi rabbit rabbits rabble rabid rabies raccoon raccoons race raced racer
|
||||
racers races racetrack racial racially racing rack racked racket racketeer
|
||||
racketeering racketeers rackets racking racks radar radars radial radially
|
||||
radian radiance radiant radiantly radiate radiated radiates radiating radiation
|
||||
radiations radiator radiators radical radically radicals radices radii radio
|
||||
radioactive radioastronomy radioed radiography radioing radiology radios radish
|
||||
radishes radium radius radix radon raft rafter rafters rafts rag rage raged
|
||||
rages ragged raggedly raggedness raging rags ragweed raid raided raider raiders
|
||||
raiding raids rail railed railer railers railing railroad railroaded railroader
|
||||
railroaders railroading railroads rails railway railways raiment rain rainbow
|
||||
raincoat raincoats raindrop raindrops rained rainfall rainier rainiest raining
|
||||
rains rainstorm rainy raise raised raiser raisers raises raisin raising rake
|
||||
raked rakes raking rallied rallies rally rallying ram ramble rambler rambles
|
||||
rambling ramblings ramification ramifications ramp rampage rampant rampart
|
||||
ramps ramrod rams ran ranch ranched rancher ranchers ranches ranching rancid
|
||||
random randomization randomize randomized randomizes randomly randomness randy
|
||||
rang range ranged rangeland ranger rangers ranges ranging rangy rank ranked
|
||||
ranker rankers rankest ranking rankings rankle rankly rankness ranks ransack
|
||||
ransacked ransacking ransacks ransom ransomer ransoming ransoms rant ranted
|
||||
ranter ranters ranting rants rap rapacious rape raped raper rapes rapid
|
||||
rapidity rapidly rapids rapier raping rapport rapprochement raps rapt raptly
|
||||
rapture raptures rapturous rare rarely rareness rarer rarest rarity rascal
|
||||
rascally rascals rash rasher rashly rashness rasp raspberry rasped rasping
|
||||
rasps raster rat rate rated rater raters rates rather ratification ratified
|
||||
ratifies ratify ratifying rating ratings ratio ration rational rationale
|
||||
rationales rationalities rationality rationalization rationalizations
|
||||
rationalize rationalized rationalizes rationalizing rationally rationals
|
||||
rationing rations ratios rats rattle rattled rattler rattlers rattles
|
||||
rattlesnake rattlesnakes rattling raucous ravage ravaged ravager ravagers
|
||||
ravages ravaging rave raved raven ravening ravenous ravenously ravens raves
|
||||
ravine ravines raving ravings raw rawer rawest rawly rawness ray rays raze
|
||||
razor razors re reabbreviate reabbreviated reabbreviates reabbreviating reach
|
||||
reachability reachable reachably reached reacher reaches reaching reacquired
|
||||
react reacted reacting reaction reactionaries reactionary reactions reactivate
|
||||
reactivated reactivates reactivating reactivation reactive reactively
|
||||
reactivity reactor reactors reacts read readability readable reader readers
|
||||
readied readier readies readiest readily readiness reading readings readjusted
|
||||
readout readouts reads ready readying real realest realign realigned realigning
|
||||
realigns realism realist realistic realistically realists realities reality
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
execsql { CREATE VIRTUAL TABLE t1 USING spellfix1 }
|
||||
foreach word $vocab {
|
||||
execsql { INSERT INTO t1(word) VALUES($word) }
|
||||
}
|
||||
} {}
|
||||
|
||||
foreach {tn word res} {
|
||||
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 ransom 6 ransomer 6 ransoming 6 ransoms 6}
|
||||
} {
|
||||
do_execsql_test 1.2.$tn {
|
||||
SELECT word, matchlen FROM t1 WHERE word MATCH $word
|
||||
ORDER BY score, word LIMIT 5
|
||||
} $res
|
||||
}
|
||||
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
CREATE VIRTUAL TABLE t2 USING spellfix1;
|
||||
INSERT INTO t2 (word, soundslike) VALUES('school', 'skuul');
|
||||
INSERT INTO t2 (word, soundslike) VALUES('psalm', 'sarm');
|
||||
SELECT word, matchlen FROM t2 WHERE word MATCH 'sar*' LIMIT 5;
|
||||
} {psalm 4}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT word, matchlen FROM t2 WHERE word MATCH 'skol*' LIMIT 5;
|
||||
} {school 6}
|
||||
|
||||
set vocab {
|
||||
kangaroo kanji kappa karate keel keeled keeling keels keen keener keenest
|
||||
keenly keenness keep keeper keepers keeping keeps ken kennel kennels kept
|
||||
kerchief kerchiefs kern kernel kernels kerosene ketchup kettle
|
||||
kettles key keyboard keyboards keyed keyhole keying keynote keypad keypads keys
|
||||
keystroke keystrokes keyword keywords kick kicked kicker kickers kicking
|
||||
kickoff kicks kid kidded kiddie kidding kidnap kidnapper kidnappers kidnapping
|
||||
kidnappings kidnaps kidney kidneys kids kill killed killer killers killing
|
||||
killingly killings killjoy kills kilobit kilobits kiloblock kilobyte kilobytes
|
||||
kilogram kilograms kilohertz kilohm kilojoule kilometer kilometers kiloton
|
||||
kilovolt kilowatt kiloword kimono kin kind kinder kindergarten kindest
|
||||
kindhearted kindle kindled kindles kindling kindly kindness kindred kinds
|
||||
kinetic king kingdom kingdoms kingly kingpin kings kink kinky kinship kinsman
|
||||
kiosk kiss kissed kisser kissers kisses kissing kit kitchen kitchenette
|
||||
kitchens kite kited kites kiting kits kitten kittenish kittens kitty klaxon
|
||||
kludge kludges klystron knack knapsack knapsacks knave knaves knead kneads knee
|
||||
kneecap kneed kneeing kneel kneeled kneeling kneels knees knell knells knelt
|
||||
knew knife knifed knifes knifing knight knighted knighthood knighting knightly
|
||||
knights knit knits knives knob knobs knock knockdown knocked knocker knockers
|
||||
knocking knockout knocks knoll knolls knot knots knotted knotting know knowable
|
||||
knower knowhow knowing knowingly knowledge knowledgeable known knows knuckle
|
||||
knuckled knuckles koala kosher kudo
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
CREATE TABLE costs(iLang, cFrom, cTo, iCost);
|
||||
INSERT INTO costs VALUES(0, 'a', 'e', 1);
|
||||
INSERT INTO costs VALUES(0, 'e', 'i', 1);
|
||||
INSERT INTO costs VALUES(0, 'i', 'o', 1);
|
||||
INSERT INTO costs VALUES(0, 'o', 'u', 1);
|
||||
INSERT INTO costs VALUES(0, 'u', 'a', 1);
|
||||
CREATE VIRTUAL TABLE t3 USING spellfix1(edit_cost_table=costs);
|
||||
}
|
||||
|
||||
do_test 3.2 {
|
||||
foreach w $vocab {
|
||||
execsql { INSERT INTO t3(word) VALUES($w) }
|
||||
}
|
||||
} {}
|
||||
|
||||
breakpoint
|
||||
foreach {tn word res} {
|
||||
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
|
||||
ORDER BY score, word LIMIT 5
|
||||
} $res
|
||||
}
|
||||
|
||||
finish_test
|
@ -319,14 +319,23 @@ do_test tcl-8.1 {
|
||||
execsql {INSERT INTO t1 VALUES(30,NULL)}
|
||||
db eval {SELECT * FROM t1 WHERE b IS NULL}
|
||||
} {30 NaN}
|
||||
proc concatFunc args {return [join $args {}]}
|
||||
do_test tcl-8.2 {
|
||||
db function concat concatFunc
|
||||
db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
|
||||
} {aNaNz}
|
||||
do_test tcl-8.3 {
|
||||
db nullvalue NULL
|
||||
db nullvalue
|
||||
} {NULL}
|
||||
do_test tcl-8.3 {
|
||||
do_test tcl-8.4 {
|
||||
db nullvalue {}
|
||||
db eval {SELECT * FROM t1 WHERE b IS NULL}
|
||||
} {30 {}}
|
||||
do_test tcl-8.5 {
|
||||
db function concat concatFunc
|
||||
db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
|
||||
} {az}
|
||||
|
||||
# Test the return type of user-defined functions
|
||||
#
|
||||
|
@ -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
|
||||
@ -126,9 +126,11 @@ set RECOVER [list \
|
||||
{1 7 unlock exclusive} {0 1 unlock exclusive} \
|
||||
]
|
||||
set READ [list \
|
||||
{4 1 lock exclusive} {4 1 unlock exclusive} \
|
||||
{4 1 lock shared} {4 1 unlock shared} \
|
||||
]
|
||||
set INITSLOT [list \
|
||||
{4 1 lock exclusive} {4 1 unlock exclusive} \
|
||||
]
|
||||
|
||||
foreach {tn iInsert res wal_index_hdr_mod wal_locks} "
|
||||
2 5 {5 15} 0 {$RECOVER $READ}
|
||||
@ -141,7 +143,7 @@ foreach {tn iInsert res wal_index_hdr_mod wal_locks} "
|
||||
9 12 {12 78} 7 {$RECOVER $READ}
|
||||
10 13 {13 91} 8 {$RECOVER $READ}
|
||||
11 14 {14 105} 9 {$RECOVER $READ}
|
||||
12 15 {15 120} -1 {$READ}
|
||||
12 15 {15 120} -1 {$INITSLOT $READ}
|
||||
" {
|
||||
|
||||
do_test wal2-1.$tn.1 {
|
||||
|
@ -655,7 +655,7 @@ T filter xShmLock
|
||||
T script lock_callback
|
||||
|
||||
proc lock_callback {method file handle spec} {
|
||||
if {$spec == "4 1 unlock exclusive"} {
|
||||
if {$spec == "1 7 unlock exclusive"} {
|
||||
T filter {}
|
||||
set ::r [catchsql { SELECT * FROM b } db2]
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user