Merge all recent trunk enhancements.

FossilOrigin-Name: 9a71d56dcea953cb965f1fdda9a8b8f158cdeff6
This commit is contained in:
drh 2016-01-26 23:32:55 +00:00
commit 8716bfd8cd
48 changed files with 2409 additions and 715 deletions

View File

@ -1180,9 +1180,9 @@ lib_install: libsqlite3.la
$(INSTALL) -d $(DESTDIR)$(libdir) $(INSTALL) -d $(DESTDIR)$(libdir)
$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir) $(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
install: sqlite3$(BEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install} install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install}
$(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) -d $(DESTDIR)$(bindir)
$(LTINSTALL) sqlite3$(BEXE) $(DESTDIR)$(bindir) $(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir)
$(INSTALL) -d $(DESTDIR)$(includedir) $(INSTALL) -d $(DESTDIR)$(includedir)
$(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(includedir) $(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(includedir)
$(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(includedir) $(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(includedir)

View File

@ -10,11 +10,13 @@
# #
TOP = . TOP = .
# <<mark>>
# Set this non-0 to create and use the SQLite amalgamation file. # Set this non-0 to create and use the SQLite amalgamation file.
# #
!IFNDEF USE_AMALGAMATION !IFNDEF USE_AMALGAMATION
USE_AMALGAMATION = 1 USE_AMALGAMATION = 1
!ENDIF !ENDIF
# <</mark>>
# Set this non-0 to enable full warnings (-W4, etc) when compiling. # Set this non-0 to enable full warnings (-W4, etc) when compiling.
# #
@ -68,11 +70,13 @@ USE_WP81_OPTS = 0
SPLIT_AMALGAMATION = 0 SPLIT_AMALGAMATION = 0
!ENDIF !ENDIF
# <<mark>>
# Set this non-0 to use the International Components for Unicode (ICU). # Set this non-0 to use the International Components for Unicode (ICU).
# #
!IFNDEF USE_ICU !IFNDEF USE_ICU
USE_ICU = 0 USE_ICU = 0
!ENDIF !ENDIF
# <</mark>>
# Set this non-0 to dynamically link to the MSVC runtime library. # Set this non-0 to dynamically link to the MSVC runtime library.
# #
@ -130,12 +134,20 @@ FOR_WINRT = 0
FOR_UAP = 0 FOR_UAP = 0
!ENDIF !ENDIF
# Set this non-0 to compile binaries suitable for the Windows 10 platform.
#
!IFNDEF FOR_WIN10
FOR_WIN10 = 0
!ENDIF
# <<mark>>
# Set this non-0 to skip attempting to look for and/or link with the Tcl # Set this non-0 to skip attempting to look for and/or link with the Tcl
# runtime library. # runtime library.
# #
!IFNDEF NO_TCL !IFNDEF NO_TCL
NO_TCL = 0 NO_TCL = 0
!ENDIF !ENDIF
# <</mark>>
# Set this to non-0 to create and use PDBs. # Set this to non-0 to create and use PDBs.
# #
@ -186,6 +198,49 @@ DEBUG = 0
OPTIMIZATIONS = 2 OPTIMIZATIONS = 2
!ENDIF !ENDIF
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
!IFNDEF SQLITE3C
!IF $(SPLIT_AMALGAMATION)!=0
SQLITE3C = sqlite3-all.c
!ELSE
SQLITE3C = sqlite3.c
!ENDIF
!ENDIF
# Set the include code file to be used by executables and libraries when
# they need SQLite.
#
!IFNDEF SQLITE3H
SQLITE3H = sqlite3.h
!ENDIF
# This is the name to use for the SQLite dynamic link library (DLL).
#
!IFNDEF SQLITE3DLL
SQLITE3DLL = sqlite3.dll
!ENDIF
# This is the name to use for the SQLite import library (LIB).
#
!IFNDEF SQLITE3LIB
SQLITE3LIB = sqlite3.lib
!ENDIF
# This is the name to use for the SQLite shell executable (EXE).
#
!IFNDEF SQLITE3EXE
SQLITE3EXE = sqlite3.exe
!ENDIF
# This is the argument used to set the program database (PDB) file for the
# SQLite shell executable (EXE).
#
!IFNDEF SQLITE3EXEPDB
SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
!ENDIF
# These are the "standard" SQLite compilation options used when compiling for # These are the "standard" SQLite compilation options used when compiling for
# the Windows platform. # the Windows platform.
# #
@ -195,6 +250,19 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF !ENDIF
# These are the "extended" SQLite compilation options used when compiling for
# the Windows 10 platform.
#
!IFNDEF EXT_FEATURE_FLAGS
!IF $(FOR_WIN10)!=0
EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1
EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_SYSTEM_MALLOC=1
EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_OMIT_LOCALTIME=1
!ELSE
EXT_FEATURE_FLAGS =
!ENDIF
!ENDIF
############################################################################### ###############################################################################
############################### END OF OPTIONS ################################ ############################### END OF OPTIONS ################################
############################################################################### ###############################################################################
@ -327,9 +395,18 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS) TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
!ENDIF !ENDIF
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise TCC = $(TCC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS) RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
# Adjust the names of the primary targets for use with Windows 10.
#
!IF $(FOR_WIN10)!=0
SQLITE3DLL = winsqlite3.dll
SQLITE3LIB = winsqlite3.lib
SQLITE3EXE = winsqlite3shell.exe
SQLITE3EXEPDB =
!ENDIF
# Check if we want to use the "stdcall" calling convention when compiling. # Check if we want to use the "stdcall" calling convention when compiling.
# This is not supported by the compilers for non-x86 platforms. It should # This is not supported by the compilers for non-x86 platforms. It should
# also be noted here that building any target with these "stdcall" options # also be noted here that building any target with these "stdcall" options
@ -337,7 +414,7 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
# to how the Tcl library functions are declared and exported (i.e. without # to how the Tcl library functions are declared and exported (i.e. without
# an explicit calling convention, which results in "cdecl"). # an explicit calling convention, which results in "cdecl").
# #
!IF $(USE_STDCALL)!=0 !IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
!IF "$(PLATFORM)"=="x86" !IF "$(PLATFORM)"=="x86"
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
@ -358,7 +435,7 @@ SHELL_CCONV_OPTS =
# These are additional compiler options used for the core library. # These are additional compiler options used for the core library.
# #
!IFNDEF CORE_COMPILE_OPTS !IFNDEF CORE_COMPILE_OPTS
!IF $(DYNAMIC_SHELL)!=0 !IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport) CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport)
!ELSE !ELSE
CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
@ -369,7 +446,7 @@ CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
# when linking. # when linking.
# #
!IFNDEF CORE_LINK_DEP !IFNDEF CORE_LINK_DEP
!IF $(DYNAMIC_SHELL)!=0 !IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
CORE_LINK_DEP = CORE_LINK_DEP =
!ELSE !ELSE
CORE_LINK_DEP = sqlite3.def CORE_LINK_DEP = sqlite3.def
@ -379,7 +456,7 @@ CORE_LINK_DEP = sqlite3.def
# These are additional linker options used for the core library. # These are additional linker options used for the core library.
# #
!IFNDEF CORE_LINK_OPTS !IFNDEF CORE_LINK_OPTS
!IF $(DYNAMIC_SHELL)!=0 !IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
CORE_LINK_OPTS = CORE_LINK_OPTS =
!ELSE !ELSE
CORE_LINK_OPTS = /DEF:sqlite3.def CORE_LINK_OPTS = /DEF:sqlite3.def
@ -389,30 +466,41 @@ CORE_LINK_OPTS = /DEF:sqlite3.def
# These are additional compiler options used for the shell executable. # These are additional compiler options used for the shell executable.
# #
!IFNDEF SHELL_COMPILE_OPTS !IFNDEF SHELL_COMPILE_OPTS
!IF $(DYNAMIC_SHELL)!=0 !IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
SHELL_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport) SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
!ELSE !ELSE
SHELL_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 $(SHELL_CCONV_OPTS) SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS)
!ENDIF
!ENDIF
# This is the source code that the shell executable should be compiled
# with.
#
!IFNDEF SHELL_CORE_SRC
!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
SHELL_CORE_SRC =
!ELSE
SHELL_CORE_SRC = $(SQLITE3C)
!ENDIF !ENDIF
!ENDIF !ENDIF
# This is the core library that the shell executable should depend on. # This is the core library that the shell executable should depend on.
# #
!IFNDEF SHELL_CORE_DEP !IFNDEF SHELL_CORE_DEP
!IF $(DYNAMIC_SHELL)!=0 !IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
SHELL_CORE_DEP = sqlite3.dll SHELL_CORE_DEP = $(SQLITE3DLL)
!ELSE !ELSE
SHELL_CORE_DEP = libsqlite3.lib SHELL_CORE_DEP =
!ENDIF !ENDIF
!ENDIF !ENDIF
# This is the core library that the shell executable should link with. # This is the core library that the shell executable should link with.
# #
!IFNDEF SHELL_CORE_LIB !IFNDEF SHELL_CORE_LIB
!IF $(DYNAMIC_SHELL)!=0 !IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
SHELL_CORE_LIB = sqlite3.lib SHELL_CORE_LIB = $(SQLITE3LIB)
!ELSE !ELSE
SHELL_CORE_LIB = libsqlite3.lib SHELL_CORE_LIB =
!ENDIF !ENDIF
!ENDIF !ENDIF
@ -441,12 +529,19 @@ TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
!ENDIF !ENDIF
# C compiler options for the Windows 10 platform (needs MSVC 2015).
#
!IF $(FOR_WIN10)!=0
TCC = $(TCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
BCC = $(BCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
!ENDIF
# Also, we need to dynamically link to the correct MSVC runtime # Also, we need to dynamically link to the correct MSVC runtime
# when compiling for WinRT (e.g. debug or release) OR if the # when compiling for WinRT (e.g. debug or release) OR if the
# USE_CRT_DLL option is set to force dynamically linking to the # USE_CRT_DLL option is set to force dynamically linking to the
# MSVC runtime library. # MSVC runtime library.
# #
!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0 !IF $(FOR_WINRT)!=0 || $(FOR_WIN10)!=0 || $(USE_CRT_DLL)!=0
!IF $(DEBUG)>1 !IF $(DEBUG)>1
TCC = $(TCC) -MDd TCC = $(TCC) -MDd
BCC = $(BCC) -MDd BCC = $(BCC) -MDd
@ -464,6 +559,7 @@ BCC = $(BCC) -MT
!ENDIF !ENDIF
!ENDIF !ENDIF
# <<mark>>
# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in # The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in
# any extension header files by default. For non-amalgamation # any extension header files by default. For non-amalgamation
# builds, we need to make sure the compiler can find these. # builds, we need to make sure the compiler can find these.
@ -487,6 +583,7 @@ MKSQLITE3C_ARGS = --linemacros
MKSQLITE3C_ARGS = MKSQLITE3C_ARGS =
!ENDIF !ENDIF
!ENDIF !ENDIF
# <</mark>>
# Define -DNDEBUG to compile without debugging (i.e., for production usage) # Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and # Omitting the define will cause extra debugging code to be inserted and
@ -498,7 +595,7 @@ BCC = $(BCC) -DNDEBUG
RCC = $(RCC) -DNDEBUG RCC = $(RCC) -DNDEBUG
!ENDIF !ENDIF
!IF $(DEBUG)>0 || $(API_ARMOR)!=0 !IF $(DEBUG)>0 || $(API_ARMOR)!=0 || $(FOR_WIN10)!=0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1 TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1 RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!ENDIF !ENDIF
@ -551,6 +648,7 @@ RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
!ENDIF !ENDIF
!ENDIF !ENDIF
# <<mark>>
# The locations of the Tcl header and library files. Also, the library that # The locations of the Tcl header and library files. Also, the library that
# non-stubs enabled programs using Tcl must link against. These variables # non-stubs enabled programs using Tcl must link against. These variables
# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
@ -602,6 +700,7 @@ LIBICU = icuuc.lib icuin.lib
!IFNDEF TCLSH_CMD !IFNDEF TCLSH_CMD
TCLSH_CMD = tclsh85 TCLSH_CMD = tclsh85
!ENDIF !ENDIF
# <</mark>>
# Compiler options needed for programs that use the readline() library. # Compiler options needed for programs that use the readline() library.
# #
@ -659,8 +758,8 @@ REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_WIN32_USE_UUID=1
# Add the required and optional SQLite compilation options into the command # Add the required and optional SQLite compilation options into the command
# lines used to invoke the MSVC code and resource compilers. # lines used to invoke the MSVC code and resource compilers.
# #
TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS)
RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS)
# Add in any optional parameters specified on the commane line, e.g. # Add in any optional parameters specified on the commane line, e.g.
# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1" # nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
@ -700,6 +799,7 @@ TCC = $(TCC) -Zi
BCC = $(BCC) -Zi BCC = $(BCC) -Zi
!ENDIF !ENDIF
# <<mark>>
# If ICU support is enabled, add the compiler options for it. # If ICU support is enabled, add the compiler options for it.
# #
!IF $(USE_ICU)!=0 !IF $(USE_ICU)!=0
@ -710,6 +810,7 @@ RCC = $(RCC) -I$(TOP)\ext\icu
TCC = $(TCC) -I$(ICUINCDIR) TCC = $(TCC) -I$(ICUINCDIR)
RCC = $(RCC) -I$(ICUINCDIR) RCC = $(RCC) -I$(ICUINCDIR)
!ENDIF !ENDIF
# <</mark>>
# Command line prefixes for compiling code, compiling resources, # Command line prefixes for compiling code, compiling resources,
# linking, etc. # linking, etc.
@ -805,6 +906,7 @@ LDFLAGS = /DEBUG $(LDOPTS)
LDFLAGS = $(LDOPTS) LDFLAGS = $(LDOPTS)
!ENDIF !ENDIF
# <<mark>>
# Start with the Tcl related linker options. # Start with the Tcl related linker options.
# #
!IF $(NO_TCL)==0 !IF $(NO_TCL)==0
@ -818,10 +920,12 @@ LTLIBS = $(LIBTCL)
LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR) LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR)
LTLIBS = $(LTLIBS) $(LIBICU) LTLIBS = $(LTLIBS) $(LIBICU)
!ENDIF !ENDIF
# <</mark>>
# You should not have to change anything below this line # You should not have to change anything below this line
############################################################################### ###############################################################################
# <<mark>>
# Object files for the SQLite library (non-amalgamation). # Object files for the SQLite library (non-amalgamation).
# #
LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
@ -845,6 +949,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
utf.lo vtab.lo utf.lo vtab.lo
# <</mark>>
# Object files for the amalgamation. # Object files for the amalgamation.
# #
@ -852,11 +957,15 @@ LIBOBJS1 = sqlite3.lo
# Determine the real value of LIBOBJ based on the 'configure' script # Determine the real value of LIBOBJ based on the 'configure' script
# #
# <<mark>>
!IF $(USE_AMALGAMATION)==0 !IF $(USE_AMALGAMATION)==0
LIBOBJ = $(LIBOBJS0) LIBOBJ = $(LIBOBJS0)
!ELSE !ELSE
# <</mark>>
LIBOBJ = $(LIBOBJS1) LIBOBJ = $(LIBOBJS1)
# <<mark>>
!ENDIF !ENDIF
# <</mark>>
# Determine if embedded resource compilation and usage are enabled. # Determine if embedded resource compilation and usage are enabled.
# #
@ -866,6 +975,7 @@ LIBRESOBJS = sqlite3res.lo
LIBRESOBJS = LIBRESOBJS =
!ENDIF !ENDIF
# <<mark>>
# All of the source code files. # All of the source code files.
# #
SRC1 = \ SRC1 = \
@ -1024,7 +1134,7 @@ SRC5 = \
opcodes.h \ opcodes.h \
parse.c \ parse.c \
parse.h \ parse.h \
sqlite3.h $(SQLITE3H)
# All source code files. # All source code files.
# #
@ -1168,7 +1278,7 @@ HDR = \
$(TOP)\src\pcache.h \ $(TOP)\src\pcache.h \
parse.h \ parse.h \
$(TOP)\src\pragma.h \ $(TOP)\src\pragma.h \
sqlite3.h \ $(SQLITE3H) \
$(TOP)\src\sqlite3ext.h \ $(TOP)\src\sqlite3ext.h \
$(TOP)\src\sqliteInt.h \ $(TOP)\src\sqliteInt.h \
$(TOP)\src\sqliteLimit.h \ $(TOP)\src\sqliteLimit.h \
@ -1203,7 +1313,7 @@ EXTHDR = $(EXTHDR) \
# #
TESTPROGS = \ TESTPROGS = \
testfixture.exe \ testfixture.exe \
sqlite3.exe \ $(SQLITE3EXE) \
sqlite3_analyzer.exe \ sqlite3_analyzer.exe \
sqldiff.exe sqldiff.exe
@ -1214,45 +1324,75 @@ FUZZDATA = \
$(TOP)\test\fuzzdata2.db \ $(TOP)\test\fuzzdata2.db \
$(TOP)\test\fuzzdata3.db \ $(TOP)\test\fuzzdata3.db \
$(TOP)\test\fuzzdata4.db $(TOP)\test\fuzzdata4.db
# <</mark>>
# Extra compiler options for various shell tools # Additional compiler options for the shell. These are only effective
# when the shell is not being dynamically linked.
# #
SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
!ENDIF
# <<mark>>
# Extra compiler options for various test tools.
#
MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
# Standard options to testfixture # Standard options to testfixture.
# #
TESTOPTS = --verbose=file --output=test-out.txt TESTOPTS = --verbose=file --output=test-out.txt
# <</mark>>
# This is the default Makefile target. The objects listed here # This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments. # are what get build when you type just "make" with no arguments.
# #
all: dll libsqlite3.lib sqlite3.exe libtclsqlite3.lib all: dll libsqlite3.lib shell libtclsqlite3.lib
# Dynamic link library section.
#
dll: $(SQLITE3DLL)
# Shell executable.
#
shell: $(SQLITE3EXE)
libsqlite3.lib: $(LIBOBJ) libsqlite3.lib: $(LIBOBJ)
$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)
# <<mark>>
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS) $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS)
# <</mark>>
sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \ $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
/link /pdb:sqlite3sh.pdb $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h # <<mark>>
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c sqlite3.c /link $(LDFLAGS) $(LTLINKOPTS) sqlite3.def: libsqlite3.lib
echo EXPORTS > sqlite3.def
dumpbin /all libsqlite3.lib \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_.*)$$" \1 \
| sort >> sqlite3.def
# <</mark>>
fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h $(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) \ $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(SHELL_CORE_SRC) \
$(TOP)\tool\fuzzershell.c sqlite3.c /link $(LDFLAGS) $(LTLINKOPTS) /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
fuzzcheck.exe: $(TOP)\test\fuzzcheck.c sqlite3.c sqlite3.h # <<mark>>
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(TOP)\test\fuzzcheck.c sqlite3.c /link $(LDFLAGS) $(LTLINKOPTS) sqldiff.exe: $(TOP)\tool\sqldiff.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \ $(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
fuzzcheck.exe: $(TOP)\test\fuzzcheck.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(TOP)\test\fuzzcheck.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20 MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20
MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20 MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20
@ -1295,21 +1435,14 @@ sqlite3.c: .target_source sqlite3ext.h $(TOP)\tool\mksqlite3c.tcl
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
# <</mark>>
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
!IF $(SPLIT_AMALGAMATION)!=0
SQLITE3C = sqlite3-all.c
!ELSE
SQLITE3C = sqlite3.c
!ENDIF
# Rule to build the amalgamation # Rule to build the amalgamation
# #
sqlite3.lo: $(SQLITE3C) sqlite3.lo: $(SQLITE3C)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C)
# <<mark>>
# Rules to build the LEMON compiler generator # Rules to build the LEMON compiler generator
# #
lempar.c: $(TOP)\tool\lempar.c lempar.c: $(TOP)\tool\lempar.c
@ -1330,11 +1463,13 @@ parse.lo: parse.c $(HDR)
opcodes.lo: opcodes.c opcodes.lo: opcodes.c
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c opcodes.c $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c opcodes.c
# <</mark>>
# Rule to build the Win32 resources object file. # Rule to build the Win32 resources object file.
# #
!IF $(USE_RC)!=0 !IF $(USE_RC)!=0
$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(HDR) # <<block1>>
$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H)
echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
for /F %%V in ('type "$(TOP)\VERSION"') do ( \ for /F %%V in ('type "$(TOP)\VERSION"') do ( \
echo #define SQLITE_RESOURCE_VERSION %%V \ echo #define SQLITE_RESOURCE_VERSION %%V \
@ -1342,8 +1477,10 @@ $(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(HDR)
) )
echo #endif >> sqlite3rc.h echo #endif >> sqlite3rc.h
$(LTRCOMPILE) -fo $(LIBRESOBJS) $(TOP)\src\sqlite3.rc $(LTRCOMPILE) -fo $(LIBRESOBJS) $(TOP)\src\sqlite3.rc
# <</block1>>
!ENDIF !ENDIF
# <<mark>>
# Rules to build individual *.lo files from files in the src directory. # Rules to build individual *.lo files from files in the src directory.
# #
alter.lo: $(TOP)\src\alter.c $(HDR) alter.lo: $(TOP)\src\alter.c $(HDR)
@ -1574,7 +1711,7 @@ tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR)
$(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c $(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(LIBRESOBJS) tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS) $(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
# Rules to build opcodes.c and opcodes.h # Rules to build opcodes.c and opcodes.h
@ -1592,18 +1729,18 @@ parse.h: parse.c
parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
del /Q parse.y parse.h parse.h.temp 2>NUL del /Q parse.y parse.h parse.h.temp 2>NUL
copy $(TOP)\src\parse.y . copy $(TOP)\src\parse.y .
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) parse.y
move parse.h parse.h.temp move parse.h parse.h.temp
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h $(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION $(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H)
sqlite3ext.h: .target_source sqlite3ext.h: .target_source
copy tsrc\sqlite3ext.h . copy tsrc\sqlite3ext.h .
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) \ $(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
$(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS) $(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
@ -1698,7 +1835,7 @@ FTS5_SRC = \
fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
copy $(TOP)\ext\fts5\fts5parse.y . copy $(TOP)\ext\fts5\fts5parse.y .
del /Q fts5parse.h 2>NUL del /Q fts5parse.h 2>NUL
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) fts5parse.y .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) fts5parse.y
fts5parse.h: fts5parse.c fts5parse.h: fts5parse.c
@ -1737,7 +1874,7 @@ TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1) TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1)
!ENDIF !ENDIF
testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR) testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR)
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \ $(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
-DBUILD_sqlite -I$(TCLINCDIR) \ -DBUILD_sqlite -I$(TCLINCDIR) \
$(TESTFIXTURE_SRC) \ $(TESTFIXTURE_SRC) \
@ -1759,7 +1896,7 @@ fulltestonly: $(TESTPROGS) fuzztest
@set PATH=$(LIBTCLPATH);$(PATH) @set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\full.test .\testfixture.exe $(TOP)\test\full.test
queryplantest: testfixture.exe sqlite3.exe queryplantest: testfixture.exe shell
@set PATH=$(LIBTCLPATH);$(PATH) @set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS) .\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS)
@ -1786,7 +1923,7 @@ smoketest: $(TESTPROGS)
@set PATH=$(LIBTCLPATH);$(PATH) @set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS) .\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
echo #define TCLSH 2 > $@ echo #define TCLSH 2 > $@
echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@ echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@
copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@ copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@
@ -1805,49 +1942,51 @@ testloadext.lo: $(TOP)\src\test_loadext.c
testloadext.dll: testloadext.lo testloadext.dll: testloadext.lo
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
LogEst.exe: $(TOP)\tool\logest.c sqlite3.h LogEst.exe: $(TOP)\tool\logest.c $(SQLITE3H)
$(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS) $(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ $(TOP)\ext\rbu\rbu.c $(SQLITE3C) \ $(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ \
/link $(LDFLAGS) $(LTLINKOPTS) $(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
# <</mark>>
clean: clean:
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
del /Q *.bsc *.cod *.da *.bb *.bbg gmon.out 2>NUL del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
del /Q sqlite3.h opcodes.c opcodes.h 2>NUL # <<mark>>
del /Q $(SQLITE3C) $(SQLITE3H) opcodes.c opcodes.h 2>NUL
del /Q lemon.* lempar.c parse.* 2>NUL del /Q lemon.* lempar.c parse.* 2>NUL
del /Q mkkeywordhash.* keywordhash.h 2>NUL del /Q mkkeywordhash.* keywordhash.h 2>NUL
del /Q notasharedlib.* 2>NUL del /Q notasharedlib.* 2>NUL
@ -1864,7 +2003,7 @@ clean:
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
del /Q mptester.exe wordcount.exe rbu.exe 2>NUL del /Q mptester.exe wordcount.exe rbu.exe 2>NUL
del /Q sqlite3.exe sqlite3.dll sqlite3.def 2>NUL del /Q $(SQLITE3EXE) $(SQLITE3DLL) sqlite3.def 2>NUL
del /Q sqlite3.c sqlite3-*.c 2>NUL del /Q sqlite3.c sqlite3-*.c 2>NUL
del /Q sqlite3rc.h 2>NUL del /Q sqlite3rc.h 2>NUL
del /Q shell.c sqlite3ext.h 2>NUL del /Q shell.c sqlite3ext.h 2>NUL
@ -1872,16 +2011,4 @@ clean:
del /Q sqlite-*-output.vsix 2>NUL del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL
del /Q fts5.* fts5parse.* 2>NUL del /Q fts5.* fts5parse.* 2>NUL
# <</mark>>
# Dynamic link library section.
#
dll: sqlite3.dll
sqlite3.def: libsqlite3.lib
echo EXPORTS > sqlite3.def
dumpbin /all libsqlite3.lib \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_.*)$$" \1 \
| sort >> sqlite3.def
sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)

View File

@ -14,7 +14,7 @@ sqlite3_CFLAGS = $(AM_CFLAGS)
include_HEADERS = sqlite3.h sqlite3ext.h include_HEADERS = sqlite3.h sqlite3ext.h
EXTRA_DIST = sqlite3.1 tea EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt
pkgconfigdir = ${libdir}/pkgconfig pkgconfigdir = ${libdir}/pkgconfig
pkgconfig_DATA = sqlite3.pc pkgconfig_DATA = sqlite3.pc

892
autoconf/Makefile.msc Normal file
View File

@ -0,0 +1,892 @@
#### DO NOT EDIT ####
# This makefile is automatically generated from the Makefile.msc at
# the root of the canonical SQLite source tree (not the
# amalgamation tarball) using the tool/mkmsvcmin.tcl
# script.
#
#
# nmake Makefile for SQLite
#
###############################################################################
############################## START OF OPTIONS ###############################
###############################################################################
# The toplevel directory of the source tree. This is the directory
# that contains this "Makefile.msc".
#
TOP = .
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
#
!IFNDEF USE_FULLWARN
USE_FULLWARN = 0
!ENDIF
# Set this non-0 to use "stdcall" calling convention for the core library
# and shell executable.
#
!IFNDEF USE_STDCALL
USE_STDCALL = 0
!ENDIF
# Set this non-0 to have the shell executable link against the core dynamic
# link library.
#
!IFNDEF DYNAMIC_SHELL
DYNAMIC_SHELL = 0
!ENDIF
# Set this non-0 to enable extra code that attempts to detect misuse of the
# SQLite API.
#
!IFNDEF API_ARMOR
API_ARMOR = 0
!ENDIF
# If necessary, create a list of harmless compiler warnings to disable when
# compiling the various tools. For the SQLite source code itself, warnings,
# if any, will be disabled from within it.
#
!IFNDEF NO_WARN
!IF $(USE_FULLWARN)!=0
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
!ENDIF
!ENDIF
# Set this non-0 to use the library paths and other options necessary for
# Windows Phone 8.1.
#
!IFNDEF USE_WP81_OPTS
USE_WP81_OPTS = 0
!ENDIF
# Set this non-0 to split the SQLite amalgamation file into chunks to
# be used for debugging with Visual Studio.
#
!IFNDEF SPLIT_AMALGAMATION
SPLIT_AMALGAMATION = 0
!ENDIF
# Set this non-0 to dynamically link to the MSVC runtime library.
#
!IFNDEF USE_CRT_DLL
USE_CRT_DLL = 0
!ENDIF
# Set this non-0 to link to the RPCRT4 library.
#
!IFNDEF USE_RPCRT4_LIB
USE_RPCRT4_LIB = 0
!ENDIF
# Set this non-0 to generate assembly code listings for the source code
# files.
#
!IFNDEF USE_LISTINGS
USE_LISTINGS = 0
!ENDIF
# Set this non-0 to attempt setting the native compiler automatically
# for cross-compiling the command line tools needed during the compilation
# process.
#
!IFNDEF XCOMPILE
XCOMPILE = 0
!ENDIF
# Set this non-0 to use the native libraries paths for cross-compiling
# the command line tools needed during the compilation process.
#
!IFNDEF USE_NATIVE_LIBPATHS
USE_NATIVE_LIBPATHS = 0
!ENDIF
# Set this 0 to skip the compiling and embedding of version resources.
#
!IFNDEF USE_RC
USE_RC = 1
!ENDIF
# 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).
#
!IFNDEF FOR_WINRT
FOR_WINRT = 0
!ENDIF
# Set this non-0 to compile binaries suitable for the UAP environment.
# This setting does not apply to any binaries that require Tcl to operate
# properly (i.e. the text fixture, etc).
#
!IFNDEF FOR_UAP
FOR_UAP = 0
!ENDIF
# Set this non-0 to compile binaries suitable for the Windows 10 platform.
#
!IFNDEF FOR_WIN10
FOR_WIN10 = 0
!ENDIF
# Set this to non-0 to create and use PDBs.
#
!IFNDEF SYMBOLS
SYMBOLS = 1
!ENDIF
# Set this to non-0 to use the SQLite debugging heap subsystem.
#
!IFNDEF MEMDEBUG
MEMDEBUG = 0
!ENDIF
# Set this to non-0 to use the Win32 native heap subsystem.
#
!IFNDEF WIN32HEAP
WIN32HEAP = 0
!ENDIF
# Set this to non-0 to enable OSTRACE() macros, which can be useful when
# debugging.
#
!IFNDEF OSTRACE
OSTRACE = 0
!ENDIF
# 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:
#
# 0 == NDEBUG: Disables assert() and other runtime diagnostics.
# 1 == SQLITE_ENABLE_API_ARMOR: extra attempts to detect misuse of the API.
# 2 == Disables NDEBUG and all optimizations and then enables PDBs.
# 3 == SQLITE_DEBUG: Enables various diagnostics messages and code.
# 4 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
#
!IFNDEF DEBUG
DEBUG = 0
!ENDIF
# Enable use of available compiler optimizations? Normally, this should be
# non-zero. Setting this to zero, thus disabling all compiler optimizations,
# can be useful for testing.
#
!IFNDEF OPTIMIZATIONS
OPTIMIZATIONS = 2
!ENDIF
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
!IFNDEF SQLITE3C
!IF $(SPLIT_AMALGAMATION)!=0
SQLITE3C = sqlite3-all.c
!ELSE
SQLITE3C = sqlite3.c
!ENDIF
!ENDIF
# Set the include code file to be used by executables and libraries when
# they need SQLite.
#
!IFNDEF SQLITE3H
SQLITE3H = sqlite3.h
!ENDIF
# This is the name to use for the SQLite dynamic link library (DLL).
#
!IFNDEF SQLITE3DLL
SQLITE3DLL = sqlite3.dll
!ENDIF
# This is the name to use for the SQLite import library (LIB).
#
!IFNDEF SQLITE3LIB
SQLITE3LIB = sqlite3.lib
!ENDIF
# This is the name to use for the SQLite shell executable (EXE).
#
!IFNDEF SQLITE3EXE
SQLITE3EXE = sqlite3.exe
!ENDIF
# This is the argument used to set the program database (PDB) file for the
# SQLite shell executable (EXE).
#
!IFNDEF SQLITE3EXEPDB
SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
!ENDIF
# These are the "standard" SQLite compilation options used when compiling for
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
# These are the "extended" SQLite compilation options used when compiling for
# the Windows 10 platform.
#
!IFNDEF EXT_FEATURE_FLAGS
!IF $(FOR_WIN10)!=0
EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1
EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_SYSTEM_MALLOC=1
EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_OMIT_LOCALTIME=1
!ELSE
EXT_FEATURE_FLAGS =
!ENDIF
!ENDIF
###############################################################################
############################### END OF OPTIONS ################################
###############################################################################
# This assumes that MSVC is always installed in 32-bit Program Files directory
# and sets the variable for use in locating other 32-bit installs accordingly.
#
PROGRAMFILES_X86 = $(VCINSTALLDIR)\..\..
PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\)
# Check for the predefined command macro CC. This should point to the compiler
# binary for the target platform. If it is not defined, simply define it to
# the legacy default value 'cl.exe'.
#
!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 MSVC runtime library path macro. Othertise, this value will
# default to the 'lib' directory underneath the MSVC installation directory.
#
!IFNDEF CRTLIBPATH
CRTLIBPATH = $(VCINSTALLDIR)\lib
!ENDIF
CRTLIBPATH = $(CRTLIBPATH:\\=\)
# Check for the command macro NCC. This should point to the compiler binary
# for the platform the compilation process is taking place on. If it is not
# defined, simply define it to have the same value as the CC macro. When
# 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\$(CC)"
NCC = $(NCC:\\=\)
!ELSE
NCC = $(CC)
!ENDIF
# Check for the MSVC native 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.
#
!IF $(USE_FULLWARN)!=0
BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
!ELSE
BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
!ENDIF
# Check if assembly code listings should be generated for the source
# code files to be compiled.
#
!IF $(USE_LISTINGS)!=0
BCC = $(BCC) -FAcs
!ENDIF
# 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)"
!IFDEF NUCRTLIBPATH
NUCRTLIBPATH = $(NUCRTLIBPATH:\\=\)
NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)"
!ENDIF
!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.)
#
!IF $(USE_FULLWARN)!=0
TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
!ELSE
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
!ENDIF
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I$(TOP) -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) $(RCOPTS) $(RCCOPTS)
# Adjust the names of the primary targets for use with Windows 10.
#
!IF $(FOR_WIN10)!=0
SQLITE3DLL = winsqlite3.dll
SQLITE3LIB = winsqlite3.lib
SQLITE3EXE = winsqlite3shell.exe
SQLITE3EXEPDB =
!ENDIF
# Check if we want to use the "stdcall" calling convention when compiling.
# This is not supported by the compilers for non-x86 platforms. It should
# also be noted here that building any target with these "stdcall" options
# will most likely fail if the Tcl library is also required. This is due
# to how the Tcl library functions are declared and exported (i.e. without
# an explicit calling convention, which results in "cdecl").
#
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
!IF "$(PLATFORM)"=="x86"
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
!ELSE
!IFNDEF PLATFORM
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
!ENDIF
!ENDIF
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
!ENDIF
# These are additional compiler options used for the core library.
#
!IFNDEF CORE_COMPILE_OPTS
!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport)
!ELSE
CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
!ENDIF
!ENDIF
# These are the additional targets that the core library should depend on
# when linking.
#
!IFNDEF CORE_LINK_DEP
!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
CORE_LINK_DEP =
!ELSE
CORE_LINK_DEP =
!ENDIF
!ENDIF
# These are additional linker options used for the core library.
#
!IFNDEF CORE_LINK_OPTS
!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
CORE_LINK_OPTS =
!ELSE
CORE_LINK_OPTS =
!ENDIF
!ENDIF
# These are additional compiler options used for the shell executable.
#
!IFNDEF SHELL_COMPILE_OPTS
!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
!ELSE
SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS)
!ENDIF
!ENDIF
# This is the source code that the shell executable should be compiled
# with.
#
!IFNDEF SHELL_CORE_SRC
!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
SHELL_CORE_SRC =
!ELSE
SHELL_CORE_SRC = $(SQLITE3C)
!ENDIF
!ENDIF
# This is the core library that the shell executable should depend on.
#
!IFNDEF SHELL_CORE_DEP
!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
SHELL_CORE_DEP = $(SQLITE3DLL)
!ELSE
SHELL_CORE_DEP =
!ENDIF
!ENDIF
# This is the core library that the shell executable should link with.
#
!IFNDEF SHELL_CORE_LIB
!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0
SHELL_CORE_LIB = $(SQLITE3LIB)
!ELSE
SHELL_CORE_LIB =
!ENDIF
!ENDIF
# These are additional linker options used for the shell executable.
#
!IFNDEF SHELL_LINK_OPTS
SHELL_LINK_OPTS = $(SHELL_CORE_LIB)
!ENDIF
# Check if assembly code listings should be generated for the source
# code files to be compiled.
#
!IF $(USE_LISTINGS)!=0
TCC = $(TCC) -FAcs
!ENDIF
# 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.
#
!IF $(FOR_WINRT)!=0
TCC = $(TCC) -DSQLITE_OS_WINRT=1
RCC = $(RCC) -DSQLITE_OS_WINRT=1
TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
!ENDIF
# C compiler options for the Windows 10 platform (needs MSVC 2015).
#
!IF $(FOR_WIN10)!=0
TCC = $(TCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
BCC = $(BCC) /guard:cf -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
!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 || $(FOR_WIN10)!=0 || $(USE_CRT_DLL)!=0
!IF $(DEBUG)>1
TCC = $(TCC) -MDd
BCC = $(BCC) -MDd
!ELSE
TCC = $(TCC) -MD
BCC = $(BCC) -MD
!ENDIF
!ELSE
!IF $(DEBUG)>1
TCC = $(TCC) -MTd
BCC = $(BCC) -MTd
!ELSE
TCC = $(TCC) -MT
BCC = $(BCC) -MT
!ENDIF
!ENDIF
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#
!IF $(DEBUG)==0
TCC = $(TCC) -DNDEBUG
BCC = $(BCC) -DNDEBUG
RCC = $(RCC) -DNDEBUG
!ENDIF
!IF $(DEBUG)>0 || $(API_ARMOR)!=0 || $(FOR_WIN10)!=0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!ENDIF
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG=1
RCC = $(RCC) -DSQLITE_DEBUG=1
!ENDIF
!IF $(DEBUG)>4 || $(OSTRACE)!=0
TCC = $(TCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
!ENDIF
!IF $(DEBUG)>5
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1
!ENDIF
# 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
# Prevent warnings about "deprecated" POSIX functions being used.
#
TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
# Use the SQLite debugging heap subsystem?
#
!IF $(MEMDEBUG)!=0
TCC = $(TCC) -DSQLITE_MEMDEBUG=1
RCC = $(RCC) -DSQLITE_MEMDEBUG=1
# Use native Win32 heap subsystem instead of malloc/free?
#
!ELSEIF $(WIN32HEAP)!=0
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
# Validate the heap on every call into the native Win32 heap subsystem?
#
!IF $(DEBUG)>3
TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
!ENDIF
!ENDIF
# Compiler options needed for programs that use the readline() library.
#
!IFNDEF READLINE_FLAGS
READLINE_FLAGS = -DHAVE_READLINE=0
!ENDIF
# The library that programs using readline() must link against.
#
!IFNDEF LIBREADLINE
LIBREADLINE =
!ENDIF
# 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
#
!IFNDEF TLIBS
TLIBS =
!ENDIF
# Flags controlling use of the in memory btree implementation
#
# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
# default to file, 2 to default to memory, and 3 to force temporary
# 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*).
# The same set of OMIT and ENABLE flags should be passed to the
# LEMON parser generator and the mkkeywordhash tool as well.
# These are the required SQLite compilation options used when compiling for
# the Windows platform.
#
REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
# If we are linking to the RPCRT4 library, enable features that need it.
#
!IF $(USE_RPCRT4_LIB)!=0
REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_WIN32_USE_UUID=1
!ENDIF
# Add the required and optional SQLite compilation options into the command
# lines used to invoke the MSVC code and resource compilers.
#
TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS)
RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS)
# Add in any optional parameters specified on the commane line, e.g.
# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
#
TCC = $(TCC) $(OPTS)
RCC = $(RCC) $(OPTS)
# If compiling for debugging, add some defines.
#
!IF $(DEBUG)>1
TCC = $(TCC) -D_DEBUG
BCC = $(BCC) -D_DEBUG
RCC = $(RCC) -D_DEBUG
!ENDIF
# If optimizations are enabled or disabled (either implicitly or
# explicitly), add the necessary flags.
#
!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0
TCC = $(TCC) -Od
BCC = $(BCC) -Od
!ELSEIF $(OPTIMIZATIONS)>=3
TCC = $(TCC) -Ox
BCC = $(BCC) -Ox
!ELSEIF $(OPTIMIZATIONS)==2
TCC = $(TCC) -O2
BCC = $(BCC) -O2
!ELSEIF $(OPTIMIZATIONS)==1
TCC = $(TCC) -O1
BCC = $(BCC) -O1
!ENDIF
# If symbols are enabled (or compiling for debugging), enable PDBs.
#
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
TCC = $(TCC) -Zi
BCC = $(BCC) -Zi
!ENDIF
# Command line prefixes for compiling code, compiling resources,
# linking, etc.
#
LTCOMPILE = $(TCC) -Fo$@
LTRCOMPILE = $(RCC) -r
LTLIB = lib.exe
LTLINK = $(TCC) -Fe$@
# If requested, link to the RPCRT4 library.
#
!IF $(USE_RPCRT4_LIB)!=0
LTLINK = $(LTLINK) rpcrt4.lib
!ENDIF
# If a platform was set, force the linker to target that.
# 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.
!IFDEF PLATFORM
LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
!ELSE
LTLINKOPTS = /NOLOGO
LTLIBOPTS = /NOLOGO
!ENDIF
# When compiling for use in the WinRT environment, the following
# linker option must be used to mark the executable as runnable
# only in the context of an application container.
#
!IF $(FOR_WINRT)!=0
LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
!IF "$(VISUALSTUDIOVERSION)"=="12.0" || "$(VISUALSTUDIOVERSION)"=="14.0"
!IFNDEF STORELIBPATH
!IF "$(PLATFORM)"=="x86"
STORELIBPATH = $(CRTLIBPATH)\store
!ELSEIF "$(PLATFORM)"=="x64"
STORELIBPATH = $(CRTLIBPATH)\store\amd64
!ELSEIF "$(PLATFORM)"=="ARM"
STORELIBPATH = $(CRTLIBPATH)\store\arm
!ELSE
STORELIBPATH = $(CRTLIBPATH)\store
!ENDIF
!ENDIF
STORELIBPATH = $(STORELIBPATH:\\=\)
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(STORELIBPATH)"
!ENDIF
!ENDIF
# When compiling for Windows Phone 8.1, an extra library path is
# required.
#
!IF $(USE_WP81_OPTS)!=0
!IFNDEF WP81LIBPATH
!IF "$(PLATFORM)"=="x86"
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
!ELSEIF "$(PLATFORM)"=="ARM"
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\ARM
!ELSE
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
!ENDIF
!ENDIF
!ENDIF
# When compiling for Windows Phone 8.1, some extra linker options
# are also required.
#
!IF $(USE_WP81_OPTS)!=0
!IFDEF WP81LIBPATH
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(WP81LIBPATH)"
!ENDIF
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE
LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib
LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
!ENDIF
# When compiling for UAP, some extra linker options are also required.
#
!IF $(FOR_UAP)!=0
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib
LTLINKOPTS = $(LTLINKOPTS) mincore.lib
!IFDEF PSDKLIBPATH
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)"
!ENDIF
!ENDIF
# If either debugging or symbols are enabled, enable PDBs.
#
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
LDFLAGS = /DEBUG $(LDOPTS)
!ELSE
LDFLAGS = $(LDOPTS)
!ENDIF
# You should not have to change anything below this line
###############################################################################
# Object files for the amalgamation.
#
LIBOBJS1 = sqlite3.lo
# Determine the real value of LIBOBJ based on the 'configure' script
#
LIBOBJ = $(LIBOBJS1)
# Determine if embedded resource compilation and usage are enabled.
#
!IF $(USE_RC)!=0
LIBRESOBJS = sqlite3res.lo
!ELSE
LIBRESOBJS =
!ENDIF
# Additional compiler options for the shell. These are only effective
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
!ENDIF
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
all: dll libsqlite3.lib shell
# Dynamic link library section.
#
dll: $(SQLITE3DLL)
# Shell executable.
#
shell: $(SQLITE3EXE)
libsqlite3.lib: $(LIBOBJ)
$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)
$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
# Rule to build the amalgamation
#
sqlite3.lo: $(SQLITE3C)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C)
# Rule to build the Win32 resources object file.
#
!IF $(USE_RC)!=0
_HASHCHAR=^#
!IF ![echo !IFNDEF VERSION > rcver.vc] && \
![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \
![echo !ENDIF >> rcver.vc]
!INCLUDE rcver.vc
!ENDIF
RESOURCE_VERSION = $(VERSION:^#=)
RESOURCE_VERSION = $(RESOURCE_VERSION:define=)
RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=)
RESOURCE_VERSION = $(RESOURCE_VERSION:"=)
RESOURCE_VERSION = $(RESOURCE_VERSION:.=,)
$(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H)
echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
echo #define SQLITE_RESOURCE_VERSION $(RESOURCE_VERSION) >> sqlite3rc.h
echo #endif >> sqlite3rc.h
$(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc
!ENDIF
clean:
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL

View File

@ -1,32 +0,0 @@
This package contains:
* the SQLite library amalgamation (single file) source code distribution,
* the shell.c file used to build the sqlite3 shell too, and
* the sqlite3.h and sqlite3ext.h header files required to link programs
and sqlite extensions against the installed libary.
* autoconf/automake installation infrastucture.
The generic installation instructions for autoconf/automake are found
in the INSTALL file.
The following SQLite specific boolean options are supported:
--enable-readline use readline in shell tool [default=yes]
--enable-threadsafe build a thread-safe library [default=yes]
--enable-dynamic-extensions support loadable extensions [default=yes]
The default value for the CFLAGS variable (options passed to the C
compiler) includes debugging symbols in the build, resulting in larger
binaries than are necessary. Override it on the configure command
line like this:
$ CFLAGS="-Os" ./configure
to produce a smaller installation footprint.
Other SQLite compilation parameters can also be set using CFLAGS. For
example:
$ CFLAGS="-Os -DSQLITE_OMIT_TRIGGERS" ./configure

113
autoconf/README.txt Normal file
View File

@ -0,0 +1,113 @@
This package contains:
* the SQLite library amalgamation (single file) source code distribution,
* the shell.c file used to build the sqlite3 shell too, and
* the sqlite3.h and sqlite3ext.h header files required to link programs
and sqlite extensions against the installed libary.
* autoconf/automake installation infrastucture for building on POSIX
compliant systems.
* a Makefile.msc and sqlite3.rc for building with Microsoft Visual C++ on
Windows.
SUMMARY OF HOW TO BUILD
=======================
Unix: ./configure; make
Windows: nmake /f Makefile.msc
BUILDING ON POSIX
=================
The generic installation instructions for autoconf/automake are found
in the INSTALL file.
The following SQLite specific boolean options are supported:
--enable-readline use readline in shell tool [default=yes]
--enable-threadsafe build a thread-safe library [default=yes]
--enable-dynamic-extensions support loadable extensions [default=yes]
The default value for the CFLAGS variable (options passed to the C
compiler) includes debugging symbols in the build, resulting in larger
binaries than are necessary. Override it on the configure command
line like this:
$ CFLAGS="-Os" ./configure
to produce a smaller installation footprint.
Other SQLite compilation parameters can also be set using CFLAGS. For
example:
$ CFLAGS="-Os -DSQLITE_OMIT_TRIGGERS" ./configure
BUILDING WITH MICROSOFT VISUAL C++
==================================
To compile for Windows using Microsoft Visual C++:
$ nmake /f Makefile.msc
Using Microsoft Visual C++ 2005 (or later) is recommended. Several Windows
platform variants may be built by adding additional macros to the NMAKE
command line.
Building for WinRT 8.0
----------------------
FOR_WINRT=1
Using Microsoft Visual C++ 2012 (or later) is required. When using the
above, something like the following macro will need to be added to the
NMAKE command line as well:
"NSDKLIBPATH=%WindowsSdkDir%\..\8.0\lib\win8\um\x86"
Building for WinRT 8.1
----------------------
FOR_WINRT=1
Using Microsoft Visual C++ 2013 (or later) is required. When using the
above, something like the following macro will need to be added to the
NMAKE command line as well:
"NSDKLIBPATH=%WindowsSdkDir%\..\8.1\lib\winv6.3\um\x86"
Building for UAP 10.0
---------------------
FOR_WINRT=1 FOR_UAP=1
Using Microsoft Visual C++ 2015 (or later) is required. When using the
above, something like the following macros will need to be added to the
NMAKE command line as well:
"NSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86"
"PSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86"
"NUCRTLIBPATH=%UniversalCRTSdkDir%\..\10\lib\10.0.10586.0\ucrt\x86"
Building for the Windows 10 SDK
-------------------------------
FOR_WIN10=1
Using Microsoft Visual C++ 2015 (or later) is required. When using the
above, no other macros should be needed on the NMAKE command line.
Other preprocessor defines
--------------------------
Additionally, preprocessor defines may be specified by using the OPTS macro
on the NMAKE command line. However, not all possible preprocessor defines
may be specified in this manner as some require the amalgamation to be built
with them enabled (see http://www.sqlite.org/compile.html). For example, the
following will work:
"OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1"
However, the following will not compile unless the amalgamation was built
with it enabled:
"OPTS=-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1"

View File

@ -29,7 +29,7 @@ typedef unsigned short u16;
typedef sqlite3_int64 i64; typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64; typedef sqlite3_uint64 u64;
#define ArraySize(x) (sizeof(x) / sizeof(x[0])) #define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
#define testcase(x) #define testcase(x)
#define ALWAYS(x) 1 #define ALWAYS(x) 1
@ -225,8 +225,8 @@ int sqlite3Fts5ConfigParseRank(const char*, char**, char**);
typedef struct Fts5Buffer Fts5Buffer; typedef struct Fts5Buffer Fts5Buffer;
struct Fts5Buffer { struct Fts5Buffer {
u8 *p; u8 *p;
u32 n; int n;
u32 nSpace; int nSpace;
}; };
int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32); int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32);
@ -247,7 +247,7 @@ char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);
#define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d) #define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d)
#define fts5BufferGrow(pRc,pBuf,nn) ( \ #define fts5BufferGrow(pRc,pBuf,nn) ( \
(pBuf)->n + (nn) <= (pBuf)->nSpace ? 0 : \ (u32)((pBuf)->n) + (u32)(nn) <= (u32)((pBuf)->nSpace) ? 0 : \
sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \ sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \
) )
@ -315,6 +315,12 @@ void sqlite3Fts5TermsetFree(Fts5Termset*);
typedef struct Fts5Index Fts5Index; typedef struct Fts5Index Fts5Index;
typedef struct Fts5IndexIter Fts5IndexIter; typedef struct Fts5IndexIter Fts5IndexIter;
struct Fts5IndexIter {
i64 iRowid;
const u8 *pData;
int nData;
};
/* /*
** Values used as part of the flags argument passed to IndexQuery(). ** Values used as part of the flags argument passed to IndexQuery().
*/ */
@ -382,8 +388,6 @@ int sqlite3Fts5IterEof(Fts5IndexIter*);
int sqlite3Fts5IterNext(Fts5IndexIter*); int sqlite3Fts5IterNext(Fts5IndexIter*);
int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch);
i64 sqlite3Fts5IterRowid(Fts5IndexIter*); i64 sqlite3Fts5IterRowid(Fts5IndexIter*);
int sqlite3Fts5IterPoslist(Fts5IndexIter*,Fts5Colset*, const u8**, int*, i64*);
int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf);
/* /*
** Close an iterator opened by sqlite3Fts5IndexQuery(). ** Close an iterator opened by sqlite3Fts5IndexQuery().
@ -469,8 +473,6 @@ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge);
int sqlite3Fts5IndexLoadConfig(Fts5Index *p); int sqlite3Fts5IndexLoadConfig(Fts5Index *p);
int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*);
/* /*
** End of interface to code in fts5_index.c. ** End of interface to code in fts5_index.c.
**************************************************************************/ **************************************************************************/

View File

@ -544,7 +544,7 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){
int rc = SQLITE_OK; /* Return code */ int rc = SQLITE_OK; /* Return code */
int i; /* To iterate through builtin functions */ int i; /* To iterate through builtin functions */
for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){
rc = pApi->xCreateFunction(pApi, rc = pApi->xCreateFunction(pApi,
aBuiltin[i].zFunc, aBuiltin[i].zFunc,
aBuiltin[i].pUserData, aBuiltin[i].pUserData,

View File

@ -322,7 +322,7 @@ int sqlite3Fts5TermsetAdd(
*pbPresent = 0; *pbPresent = 0;
if( p ){ if( p ){
int i; int i;
int hash = 13; u32 hash = 13;
Fts5TermsetEntry *pEntry; Fts5TermsetEntry *pEntry;
/* Calculate a hash value for this term. This is the same hash checksum /* Calculate a hash value for this term. This is the same hash checksum
@ -339,7 +339,7 @@ int sqlite3Fts5TermsetAdd(
if( pEntry->iIdx==iIdx if( pEntry->iIdx==iIdx
&& pEntry->nTerm==nTerm && pEntry->nTerm==nTerm
&& memcmp(pEntry->pTerm, pTerm, nTerm)==0 && memcmp(pEntry->pTerm, pTerm, nTerm)==0
){ ){
*pbPresent = 1; *pbPresent = 1;
break; break;
} }
@ -363,7 +363,7 @@ int sqlite3Fts5TermsetAdd(
void sqlite3Fts5TermsetFree(Fts5Termset *p){ void sqlite3Fts5TermsetFree(Fts5Termset *p){
if( p ){ if( p ){
int i; u32 i;
for(i=0; i<ArraySize(p->apHash); i++){ for(i=0; i<ArraySize(p->apHash); i++){
Fts5TermsetEntry *pEntry = p->apHash[i]; Fts5TermsetEntry *pEntry = p->apHash[i];
while( pEntry ){ while( pEntry ){

View File

@ -306,7 +306,7 @@ static int fts5ExprSynonymList(
int bCollist, int bCollist,
Fts5Colset *pColset, Fts5Colset *pColset,
i64 iRowid, i64 iRowid,
int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */ Fts5Buffer *pBuf, /* Use this buffer for space if required */
u8 **pa, int *pn u8 **pa, int *pn
){ ){
Fts5PoslistReader aStatic[4]; Fts5PoslistReader aStatic[4];
@ -320,18 +320,7 @@ static int fts5ExprSynonymList(
for(p=pTerm; p; p=p->pSynonym){ for(p=pTerm; p; p=p->pSynonym){
Fts5IndexIter *pIter = p->pIter; Fts5IndexIter *pIter = p->pIter;
if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){ if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){
const u8 *a; if( pIter->nData==0 ) continue;
int n;
if( bCollist ){
rc = sqlite3Fts5IterCollist(pIter, &a, &n);
}else{
i64 dummy;
rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy);
}
if( rc!=SQLITE_OK ) goto synonym_poslist_out;
if( n==0 ) continue;
if( nIter==nAlloc ){ if( nIter==nAlloc ){
int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
@ -344,20 +333,19 @@ static int fts5ExprSynonymList(
if( aIter!=aStatic ) sqlite3_free(aIter); if( aIter!=aStatic ) sqlite3_free(aIter);
aIter = aNew; aIter = aNew;
} }
sqlite3Fts5PoslistReaderInit(a, n, &aIter[nIter]); sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &aIter[nIter]);
assert( aIter[nIter].bEof==0 ); assert( aIter[nIter].bEof==0 );
nIter++; nIter++;
} }
} }
assert( *pbDel==0 );
if( nIter==1 ){ if( nIter==1 ){
*pa = (u8*)aIter[0].a; *pa = (u8*)aIter[0].a;
*pn = aIter[0].n; *pn = aIter[0].n;
}else{ }else{
Fts5PoslistWriter writer = {0}; Fts5PoslistWriter writer = {0};
Fts5Buffer buf = {0,0,0};
i64 iPrev = -1; i64 iPrev = -1;
fts5BufferZero(pBuf);
while( 1 ){ while( 1 ){
int i; int i;
i64 iMin = FTS5_LARGEST_INT64; i64 iMin = FTS5_LARGEST_INT64;
@ -372,15 +360,12 @@ static int fts5ExprSynonymList(
} }
} }
if( iMin==FTS5_LARGEST_INT64 || rc!=SQLITE_OK ) break; if( iMin==FTS5_LARGEST_INT64 || rc!=SQLITE_OK ) break;
rc = sqlite3Fts5PoslistWriterAppend(&buf, &writer, iMin); rc = sqlite3Fts5PoslistWriterAppend(pBuf, &writer, iMin);
iPrev = iMin; iPrev = iMin;
} }
if( rc ){ if( rc==SQLITE_OK ){
sqlite3_free(buf.p); *pa = pBuf->p;
}else{ *pn = pBuf->n;
*pa = buf.p;
*pn = buf.n;
*pbDel = 1;
} }
} }
@ -417,7 +402,7 @@ static int fts5ExprPhraseIsMatch(
/* If the aStatic[] array is not large enough, allocate a large array /* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */ ** using sqlite3_malloc(). This approach could be improved upon. */
if( pPhrase->nTerm>(int)ArraySize(aStatic) ){ if( pPhrase->nTerm>ArraySize(aStatic) ){
int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte); aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
if( !aIter ) return SQLITE_NOMEM; if( !aIter ) return SQLITE_NOMEM;
@ -427,18 +412,23 @@ static int fts5ExprPhraseIsMatch(
/* Initialize a term iterator for each term in the phrase */ /* Initialize a term iterator for each term in the phrase */
for(i=0; i<pPhrase->nTerm; i++){ for(i=0; i<pPhrase->nTerm; i++){
Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; Fts5ExprTerm *pTerm = &pPhrase->aTerm[i];
i64 dummy;
int n = 0; int n = 0;
int bFlag = 0; int bFlag = 0;
const u8 *a = 0; u8 *a = 0;
if( pTerm->pSynonym ){ if( pTerm->pSynonym ){
Fts5Buffer buf = {0, 0, 0};
rc = fts5ExprSynonymList( rc = fts5ExprSynonymList(
pTerm, 0, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n pTerm, 0, pColset, pNode->iRowid, &buf, &a, &n
); );
if( rc ){
sqlite3_free(a);
goto ismatch_out;
}
if( a==buf.p ) bFlag = 1;
}else{ }else{
rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy); a = (u8*)pTerm->pIter->pData;
n = pTerm->pIter->nData;
} }
if( rc!=SQLITE_OK ) goto ismatch_out;
sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
aIter[i].bFlag = (u8)bFlag; aIter[i].bFlag = (u8)bFlag;
if( aIter[i].bEof ) goto ismatch_out; if( aIter[i].bEof ) goto ismatch_out;
@ -553,7 +543,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
/* If the aStatic[] array is not large enough, allocate a large array /* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */ ** using sqlite3_malloc(). This approach could be improved upon. */
if( pNear->nPhrase>(int)ArraySize(aStatic) ){ if( pNear->nPhrase>ArraySize(aStatic) ){
int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte); a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
}else{ }else{
@ -775,6 +765,7 @@ static int fts5ExprNearTest(
for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
Fts5IndexIter *pIter = pTerm->pIter; Fts5IndexIter *pIter = pTerm->pIter;
if( sqlite3Fts5IterEof(pIter)==0 ){ if( sqlite3Fts5IterEof(pIter)==0 ){
#if 0
int n; int n;
i64 iRowid; i64 iRowid;
rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid); rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid);
@ -784,6 +775,10 @@ static int fts5ExprNearTest(
}else if( iRowid==pNode->iRowid && n>0 ){ }else if( iRowid==pNode->iRowid && n>0 ){
pPhrase->poslist.n = 1; pPhrase->poslist.n = 1;
} }
#endif
if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){
pPhrase->poslist.n = 1;
}
} }
} }
return pPhrase->poslist.n; return pPhrase->poslist.n;
@ -800,9 +795,13 @@ static int fts5ExprNearTest(
rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch); rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch);
if( bMatch==0 ) break; if( bMatch==0 ) break;
}else{ }else{
Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData);
#if 0
rc = sqlite3Fts5IterPoslistBuffer( rc = sqlite3Fts5IterPoslistBuffer(
pPhrase->aTerm[0].pIter, &pPhrase->poslist pPhrase->aTerm[0].pIter, &pPhrase->poslist
); );
#endif
} }
} }
@ -823,21 +822,20 @@ static int fts5ExprTokenTest(
** fts5_index.c iterator object. This is much faster than synthesizing ** fts5_index.c iterator object. This is much faster than synthesizing
** a new poslist the way we have to for more complicated phrase or NEAR ** a new poslist the way we have to for more complicated phrase or NEAR
** expressions. */ ** expressions. */
Fts5ExprNearset *pNear = pNode->pNear; Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0];
Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
Fts5Colset *pColset = pNear->pColset;
int rc;
assert( pNode->eType==FTS5_TERM ); assert( pNode->eType==FTS5_TERM );
assert( pNear->nPhrase==1 && pPhrase->nTerm==1 ); assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 );
assert( pPhrase->aTerm[0].pSynonym==0 ); assert( pPhrase->aTerm[0].pSynonym==0 );
rc = sqlite3Fts5IterPoslist(pIter, pColset, pPhrase->poslist.n = pIter->nData;
(const u8**)&pPhrase->poslist.p, (int*)&pPhrase->poslist.n, &pNode->iRowid if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){
); pPhrase->poslist.p = (u8*)pIter->pData;
}
pNode->iRowid = pIter->iRowid;
pNode->bNomatch = (pPhrase->poslist.n==0); pNode->bNomatch = (pPhrase->poslist.n==0);
return rc; return SQLITE_OK;
} }
/* /*
@ -1370,10 +1368,10 @@ static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){
Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; Fts5ExprTerm *pTerm = &pPhrase->aTerm[i];
sqlite3_free(pTerm->zTerm); sqlite3_free(pTerm->zTerm);
sqlite3Fts5IterClose(pTerm->pIter); sqlite3Fts5IterClose(pTerm->pIter);
for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){
pNext = pSyn->pSynonym; pNext = pSyn->pSynonym;
sqlite3Fts5IterClose(pSyn->pIter); sqlite3Fts5IterClose(pSyn->pIter);
fts5BufferFree((Fts5Buffer*)&pSyn[1]);
sqlite3_free(pSyn); sqlite3_free(pSyn);
} }
} }
@ -1461,13 +1459,13 @@ static int fts5ParseTokenize(
assert( pPhrase==0 || pPhrase->nTerm>0 ); assert( pPhrase==0 || pPhrase->nTerm>0 );
if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){ if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){
Fts5ExprTerm *pSyn; Fts5ExprTerm *pSyn;
int nByte = sizeof(Fts5ExprTerm) + nToken+1; int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
if( pSyn==0 ){ if( pSyn==0 ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
}else{ }else{
memset(pSyn, 0, nByte); memset(pSyn, 0, nByte);
pSyn->zTerm = (char*)&pSyn[1]; pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
memcpy(pSyn->zTerm, pToken, nToken); memcpy(pSyn->zTerm, pToken, nToken);
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
@ -2246,7 +2244,7 @@ int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
int rc = SQLITE_OK; int rc = SQLITE_OK;
void *pCtx = (void*)pGlobal; void *pCtx = (void*)pGlobal;
for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aFunc); i++){ for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){
struct Fts5ExprFunc *p = &aFunc[i]; struct Fts5ExprFunc *p = &aFunc[i];
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
} }
@ -2484,26 +2482,21 @@ int sqlite3Fts5ExprPhraseCollist(
int rc = SQLITE_OK; int rc = SQLITE_OK;
assert( iPhrase>=0 && iPhrase<pExpr->nPhrase ); assert( iPhrase>=0 && iPhrase<pExpr->nPhrase );
assert( pExpr->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
if( pNode->bEof==0 if( pNode->bEof==0
&& pNode->iRowid==pExpr->pRoot->iRowid && pNode->iRowid==pExpr->pRoot->iRowid
&& pPhrase->poslist.n>0 && pPhrase->poslist.n>0
){ ){
Fts5ExprTerm *pTerm = &pPhrase->aTerm[0]; Fts5ExprTerm *pTerm = &pPhrase->aTerm[0];
if( pTerm->pSynonym ){ if( pTerm->pSynonym ){
int bDel = 0; Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1];
u8 *a;
rc = fts5ExprSynonymList( rc = fts5ExprSynonymList(
pTerm, 1, 0, pNode->iRowid, &bDel, &a, pnCollist pTerm, 1, 0, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist
); );
if( bDel ){
sqlite3Fts5BufferSet(&rc, &pPhrase->poslist, *pnCollist, a);
*ppCollist = pPhrase->poslist.p;
sqlite3_free(a);
}else{
*ppCollist = a;
}
}else{ }else{
sqlite3Fts5IterCollist(pPhrase->aTerm[0].pIter, ppCollist, pnCollist); *ppCollist = pPhrase->aTerm[0].pIter->pData;
*pnCollist = pPhrase->aTerm[0].pIter->nData;
} }
}else{ }else{
*ppCollist = 0; *ppCollist = 0;

View File

@ -261,6 +261,7 @@ typedef struct Fts5Data Fts5Data;
typedef struct Fts5DlidxIter Fts5DlidxIter; typedef struct Fts5DlidxIter Fts5DlidxIter;
typedef struct Fts5DlidxLvl Fts5DlidxLvl; typedef struct Fts5DlidxLvl Fts5DlidxLvl;
typedef struct Fts5DlidxWriter Fts5DlidxWriter; typedef struct Fts5DlidxWriter Fts5DlidxWriter;
typedef struct Fts5Iter Fts5Iter;
typedef struct Fts5PageWriter Fts5PageWriter; typedef struct Fts5PageWriter Fts5PageWriter;
typedef struct Fts5SegIter Fts5SegIter; typedef struct Fts5SegIter Fts5SegIter;
typedef struct Fts5DoclistIter Fts5DoclistIter; typedef struct Fts5DoclistIter Fts5DoclistIter;
@ -503,10 +504,16 @@ struct Fts5SegIter {
** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
** There is no way to tell if this is populated or not. ** There is no way to tell if this is populated or not.
*/ */
struct Fts5IndexIter { struct Fts5Iter {
Fts5IndexIter base; /* Base class containing output vars */
Fts5Index *pIndex; /* Index that owns this iterator */ Fts5Index *pIndex; /* Index that owns this iterator */
Fts5Structure *pStruct; /* Database structure for this iterator */ Fts5Structure *pStruct; /* Database structure for this iterator */
Fts5Buffer poslist; /* Buffer containing current poslist */ Fts5Buffer poslist; /* Buffer containing current poslist */
Fts5Colset *pColset; /* Restrict matches to these columns */
/* Invoked to set output variables. */
void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*);
int nSeg; /* Size of aSeg[] array */ int nSeg; /* Size of aSeg[] array */
int bRev; /* True to iterate in reverse order */ int bRev; /* True to iterate in reverse order */
@ -1752,7 +1759,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
** points to a delete marker. A delete marker is an entry with a 0 byte ** points to a delete marker. A delete marker is an entry with a 0 byte
** position-list. ** position-list.
*/ */
static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5IndexIter *pIter){ static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){
Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0); return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0);
} }
@ -2406,7 +2413,7 @@ static void fts5SegIterClear(Fts5SegIter *pIter){
** two iterators. ** two iterators.
*/ */
static void fts5AssertComparisonResult( static void fts5AssertComparisonResult(
Fts5IndexIter *pIter, Fts5Iter *pIter,
Fts5SegIter *p1, Fts5SegIter *p1,
Fts5SegIter *p2, Fts5SegIter *p2,
Fts5CResult *pRes Fts5CResult *pRes
@ -2447,7 +2454,7 @@ static void fts5AssertComparisonResult(
** statement used to verify that the contents of the pIter->aFirst[] array ** statement used to verify that the contents of the pIter->aFirst[] array
** are correct. ** are correct.
*/ */
static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5IndexIter *pIter){ static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){
if( p->rc==SQLITE_OK ){ if( p->rc==SQLITE_OK ){
Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
int i; int i;
@ -2492,7 +2499,7 @@ static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5IndexIter *pIter){
** to a key that is a duplicate of another, higher priority, ** to a key that is a duplicate of another, higher priority,
** segment-iterator in the pSeg->aSeg[] array. ** segment-iterator in the pSeg->aSeg[] array.
*/ */
static int fts5MultiIterDoCompare(Fts5IndexIter *pIter, int iOut){ static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){
int i1; /* Index of left-hand Fts5SegIter */ int i1; /* Index of left-hand Fts5SegIter */
int i2; /* Index of right-hand Fts5SegIter */ int i2; /* Index of right-hand Fts5SegIter */
int iRes; int iRes;
@ -2638,7 +2645,7 @@ static void fts5SegIterNextFrom(
/* /*
** Free the iterator object passed as the second argument. ** Free the iterator object passed as the second argument.
*/ */
static void fts5MultiIterFree(Fts5Index *p, Fts5IndexIter *pIter){ static void fts5MultiIterFree(Fts5Index *p, Fts5Iter *pIter){
if( pIter ){ if( pIter ){
int i; int i;
for(i=0; i<pIter->nSeg; i++){ for(i=0; i<pIter->nSeg; i++){
@ -2652,7 +2659,7 @@ static void fts5MultiIterFree(Fts5Index *p, Fts5IndexIter *pIter){
static void fts5MultiIterAdvanced( static void fts5MultiIterAdvanced(
Fts5Index *p, /* FTS5 backend to iterate within */ Fts5Index *p, /* FTS5 backend to iterate within */
Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ Fts5Iter *pIter, /* Iterator to update aFirst[] array for */
int iChanged, /* Index of sub-iterator just advanced */ int iChanged, /* Index of sub-iterator just advanced */
int iMinset /* Minimum entry in aFirst[] to set */ int iMinset /* Minimum entry in aFirst[] to set */
){ ){
@ -2680,8 +2687,9 @@ static void fts5MultiIterAdvanced(
*/ */
static int fts5MultiIterAdvanceRowid( static int fts5MultiIterAdvanceRowid(
Fts5Index *p, /* FTS5 backend to iterate within */ Fts5Index *p, /* FTS5 backend to iterate within */
Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ Fts5Iter *pIter, /* Iterator to update aFirst[] array for */
int iChanged /* Index of sub-iterator just advanced */ int iChanged, /* Index of sub-iterator just advanced */
Fts5SegIter **ppFirst
){ ){
Fts5SegIter *pNew = &pIter->aSeg[iChanged]; Fts5SegIter *pNew = &pIter->aSeg[iChanged];
@ -2714,13 +2722,14 @@ static int fts5MultiIterAdvanceRowid(
} }
} }
*ppFirst = pNew;
return 0; return 0;
} }
/* /*
** Set the pIter->bEof variable based on the state of the sub-iterators. ** Set the pIter->bEof variable based on the state of the sub-iterators.
*/ */
static void fts5MultiIterSetEof(Fts5IndexIter *pIter){ static void fts5MultiIterSetEof(Fts5Iter *pIter){
Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
pIter->bEof = pSeg->pLeaf==0; pIter->bEof = pSeg->pLeaf==0;
pIter->iSwitchRowid = pSeg->iRowid; pIter->iSwitchRowid = pSeg->iRowid;
@ -2735,39 +2744,44 @@ static void fts5MultiIterSetEof(Fts5IndexIter *pIter){
*/ */
static void fts5MultiIterNext( static void fts5MultiIterNext(
Fts5Index *p, Fts5Index *p,
Fts5IndexIter *pIter, Fts5Iter *pIter,
int bFrom, /* True if argument iFrom is valid */ int bFrom, /* True if argument iFrom is valid */
i64 iFrom /* Advance at least as far as this */ i64 iFrom /* Advance at least as far as this */
){ ){
if( p->rc==SQLITE_OK ){ int bUseFrom = bFrom;
int bUseFrom = bFrom; while( p->rc==SQLITE_OK ){
do { int iFirst = pIter->aFirst[1].iFirst;
int iFirst = pIter->aFirst[1].iFirst; int bNewTerm = 0;
int bNewTerm = 0; Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; assert( p->rc==SQLITE_OK );
assert( p->rc==SQLITE_OK ); if( bUseFrom && pSeg->pDlidx ){
if( bUseFrom && pSeg->pDlidx ){ fts5SegIterNextFrom(p, pSeg, iFrom);
fts5SegIterNextFrom(p, pSeg, iFrom); }else{
}else{ pSeg->xNext(p, pSeg, &bNewTerm);
pSeg->xNext(p, pSeg, &bNewTerm); }
}
if( pSeg->pLeaf==0 || bNewTerm if( pSeg->pLeaf==0 || bNewTerm
|| fts5MultiIterAdvanceRowid(p, pIter, iFirst) || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg)
){ ){
fts5MultiIterAdvanced(p, pIter, iFirst, 1); fts5MultiIterAdvanced(p, pIter, iFirst, 1);
fts5MultiIterSetEof(pIter); fts5MultiIterSetEof(pIter);
} pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
fts5AssertMultiIterSetup(p, pIter); if( pSeg->pLeaf==0 ) return;
}
bUseFrom = 0; fts5AssertMultiIterSetup(p, pIter);
}while( pIter->bSkipEmpty && fts5MultiIterIsEmpty(p, pIter) ); assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf );
if( pIter->bSkipEmpty==0 || pSeg->nPos ){
pIter->xSetOutputs(pIter, pSeg);
return;
}
bUseFrom = 0;
} }
} }
static void fts5MultiIterNext2( static void fts5MultiIterNext2(
Fts5Index *p, Fts5Index *p,
Fts5IndexIter *pIter, Fts5Iter *pIter,
int *pbNewTerm /* OUT: True if *might* be new term */ int *pbNewTerm /* OUT: True if *might* be new term */
){ ){
assert( pIter->bSkipEmpty ); assert( pIter->bSkipEmpty );
@ -2780,7 +2794,7 @@ static void fts5MultiIterNext2(
assert( p->rc==SQLITE_OK ); assert( p->rc==SQLITE_OK );
pSeg->xNext(p, pSeg, &bNewTerm); pSeg->xNext(p, pSeg, &bNewTerm);
if( pSeg->pLeaf==0 || bNewTerm if( pSeg->pLeaf==0 || bNewTerm
|| fts5MultiIterAdvanceRowid(p, pIter, iFirst) || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg)
){ ){
fts5MultiIterAdvanced(p, pIter, iFirst, 1); fts5MultiIterAdvanced(p, pIter, iFirst, 1);
fts5MultiIterSetEof(pIter); fts5MultiIterSetEof(pIter);
@ -2794,17 +2808,19 @@ static void fts5MultiIterNext2(
} }
} }
static void fts5IterSetOutputs_Noop(Fts5Iter *pIter, Fts5SegIter *pSeg){
}
static Fts5IndexIter *fts5MultiIterAlloc( static Fts5Iter *fts5MultiIterAlloc(
Fts5Index *p, /* FTS5 backend to iterate within */ Fts5Index *p, /* FTS5 backend to iterate within */
int nSeg int nSeg
){ ){
Fts5IndexIter *pNew; Fts5Iter *pNew;
int nSlot; /* Power of two >= nSeg */ int nSlot; /* Power of two >= nSeg */
for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2); for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
pNew = fts5IdxMalloc(p, pNew = fts5IdxMalloc(p,
sizeof(Fts5IndexIter) + /* pNew */ sizeof(Fts5Iter) + /* pNew */
sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */ sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */
sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
); );
@ -2812,12 +2828,13 @@ static Fts5IndexIter *fts5MultiIterAlloc(
pNew->nSeg = nSlot; pNew->nSeg = nSlot;
pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot]; pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot];
pNew->pIndex = p; pNew->pIndex = p;
pNew->xSetOutputs = fts5IterSetOutputs_Noop;
} }
return pNew; return pNew;
} }
/* /*
** Allocate a new Fts5IndexIter object. ** Allocate a new Fts5Iter object.
** **
** The new object will be used to iterate through data in structure pStruct. ** The new object will be used to iterate through data in structure pStruct.
** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel ** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel
@ -2835,14 +2852,14 @@ static void fts5MultiIterNew(
const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */
int iLevel, /* Level to iterate (-1 for all) */ int iLevel, /* Level to iterate (-1 for all) */
int nSegment, /* Number of segments to merge (iLevel>=0) */ int nSegment, /* Number of segments to merge (iLevel>=0) */
Fts5IndexIter **ppOut /* New object */ Fts5Iter **ppOut /* New object */
){ ){
int nSeg = 0; /* Number of segment-iters in use */ int nSeg = 0; /* Number of segment-iters in use */
int iIter = 0; /* */ int iIter = 0; /* */
int iSeg; /* Used to iterate through segments */ int iSeg; /* Used to iterate through segments */
Fts5Buffer buf = {0,0,0}; /* Buffer used by fts5SegIterSeekInit() */ Fts5Buffer buf = {0,0,0}; /* Buffer used by fts5SegIterSeekInit() */
Fts5StructureLevel *pLvl; Fts5StructureLevel *pLvl;
Fts5IndexIter *pNew; Fts5Iter *pNew;
assert( (pTerm==0 && nTerm==0) || iLevel<0 ); assert( (pTerm==0 && nTerm==0) || iLevel<0 );
@ -2917,16 +2934,16 @@ static void fts5MultiIterNew(
} }
/* /*
** Create an Fts5IndexIter that iterates through the doclist provided ** Create an Fts5Iter that iterates through the doclist provided
** as the second argument. ** as the second argument.
*/ */
static void fts5MultiIterNew2( static void fts5MultiIterNew2(
Fts5Index *p, /* FTS5 backend to iterate within */ Fts5Index *p, /* FTS5 backend to iterate within */
Fts5Data *pData, /* Doclist to iterate through */ Fts5Data *pData, /* Doclist to iterate through */
int bDesc, /* True for descending rowid order */ int bDesc, /* True for descending rowid order */
Fts5IndexIter **ppOut /* New object */ Fts5Iter **ppOut /* New object */
){ ){
Fts5IndexIter *pNew; Fts5Iter *pNew;
pNew = fts5MultiIterAlloc(p, 2); pNew = fts5MultiIterAlloc(p, 2);
if( pNew ){ if( pNew ){
Fts5SegIter *pIter = &pNew->aSeg[1]; Fts5SegIter *pIter = &pNew->aSeg[1];
@ -2961,7 +2978,7 @@ static void fts5MultiIterNew2(
** Return true if the iterator is at EOF or if an error has occurred. ** Return true if the iterator is at EOF or if an error has occurred.
** False otherwise. ** False otherwise.
*/ */
static int fts5MultiIterEof(Fts5Index *p, Fts5IndexIter *pIter){ static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
assert( p->rc assert( p->rc
|| (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->bEof || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->bEof
); );
@ -2973,7 +2990,7 @@ static int fts5MultiIterEof(Fts5Index *p, Fts5IndexIter *pIter){
** to. If the iterator points to EOF when this function is called the ** to. If the iterator points to EOF when this function is called the
** results are undefined. ** results are undefined.
*/ */
static i64 fts5MultiIterRowid(Fts5IndexIter *pIter){ static i64 fts5MultiIterRowid(Fts5Iter *pIter){
assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf ); assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf );
return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid; return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid;
} }
@ -2983,7 +3000,7 @@ static i64 fts5MultiIterRowid(Fts5IndexIter *pIter){
*/ */
static void fts5MultiIterNextFrom( static void fts5MultiIterNextFrom(
Fts5Index *p, Fts5Index *p,
Fts5IndexIter *pIter, Fts5Iter *pIter,
i64 iMatch i64 iMatch
){ ){
while( 1 ){ while( 1 ){
@ -3000,7 +3017,7 @@ static void fts5MultiIterNextFrom(
** Return a pointer to a buffer containing the term associated with the ** Return a pointer to a buffer containing the term associated with the
** entry that the iterator currently points to. ** entry that the iterator currently points to.
*/ */
static const u8 *fts5MultiIterTerm(Fts5IndexIter *pIter, int *pn){ static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){
Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
*pn = p->term.n; *pn = p->term.n;
return p->term.p; return p->term.p;
@ -3582,7 +3599,7 @@ static void fts5WriteInit(
** incremental merge operation. This function is called if the incremental ** incremental merge operation. This function is called if the incremental
** merge step has finished but the input has not been completely exhausted. ** merge step has finished but the input has not been completely exhausted.
*/ */
static void fts5TrimSegments(Fts5Index *p, Fts5IndexIter *pIter){ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
int i; int i;
Fts5Buffer buf; Fts5Buffer buf;
memset(&buf, 0, sizeof(Fts5Buffer)); memset(&buf, 0, sizeof(Fts5Buffer));
@ -3660,7 +3677,7 @@ static void fts5IndexMergeLevel(
Fts5Structure *pStruct = *ppStruct; Fts5Structure *pStruct = *ppStruct;
Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
Fts5StructureLevel *pLvlOut; Fts5StructureLevel *pLvlOut;
Fts5IndexIter *pIter = 0; /* Iterator to read input data */ Fts5Iter *pIter = 0; /* Iterator to read input data */
int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */ int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */
int nInput; /* Number of input segments */ int nInput; /* Number of input segments */
Fts5SegWriter writer; /* Writer object */ Fts5SegWriter writer; /* Writer object */
@ -4342,7 +4359,7 @@ static int fts5IndexExtractCol(
static int fts5AppendRowid( static int fts5AppendRowid(
Fts5Index *p, Fts5Index *p,
i64 iDelta, i64 iDelta,
Fts5IndexIter *pMulti, Fts5Iter *pMulti,
Fts5Colset *pColset, Fts5Colset *pColset,
Fts5Buffer *pBuf Fts5Buffer *pBuf
){ ){
@ -4367,7 +4384,7 @@ static int fts5AppendRowid(
static int fts5AppendPoslist( static int fts5AppendPoslist(
Fts5Index *p, Fts5Index *p,
i64 iDelta, i64 iDelta,
Fts5IndexIter *pMulti, Fts5Iter *pMulti,
Fts5Colset *pColset, Fts5Colset *pColset,
Fts5Buffer *pBuf Fts5Buffer *pBuf
){ ){
@ -4645,14 +4662,14 @@ static void fts5SetupPrefixIter(
const u8 *pToken, /* Buffer containing prefix to match */ const u8 *pToken, /* Buffer containing prefix to match */
int nToken, /* Size of buffer pToken in bytes */ int nToken, /* Size of buffer pToken in bytes */
Fts5Colset *pColset, /* Restrict matches to these columns */ Fts5Colset *pColset, /* Restrict matches to these columns */
Fts5IndexIter **ppIter /* OUT: New iterator */ Fts5Iter **ppIter /* OUT: New iterator */
){ ){
Fts5Structure *pStruct; Fts5Structure *pStruct;
Fts5Buffer *aBuf; Fts5Buffer *aBuf;
const int nBuf = 32; const int nBuf = 32;
void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
int (*xAppend)(Fts5Index*, i64, Fts5IndexIter*, Fts5Colset*, Fts5Buffer*); int (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Colset*, Fts5Buffer*);
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
xMerge = fts5MergeRowidLists; xMerge = fts5MergeRowidLists;
xAppend = fts5AppendRowid; xAppend = fts5AppendRowid;
@ -4668,7 +4685,7 @@ static void fts5SetupPrefixIter(
const int flags = FTS5INDEX_QUERY_SCAN; const int flags = FTS5INDEX_QUERY_SCAN;
int i; int i;
i64 iLastRowid = 0; i64 iLastRowid = 0;
Fts5IndexIter *p1 = 0; /* Iterator used to gather data from index */ Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
Fts5Data *pData; Fts5Data *pData;
Fts5Buffer doclist; Fts5Buffer doclist;
int bNewTerm = 1; int bNewTerm = 1;
@ -4932,6 +4949,179 @@ int sqlite3Fts5IndexWrite(
return rc; return rc;
} }
static int fts5IndexExtractColset (
Fts5Colset *pColset, /* Colset to filter on */
const u8 *pPos, int nPos, /* Position list */
Fts5Buffer *pBuf /* Output buffer */
){
int rc = SQLITE_OK;
int i;
fts5BufferZero(pBuf);
for(i=0; i<pColset->nCol; i++){
const u8 *pSub = pPos;
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
if( nSub ){
fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
}
}
return rc;
}
/*
** xSetOutputs callback used by detail=none tables.
*/
static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){
assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE );
pIter->base.iRowid = pSeg->iRowid;
pIter->base.nData = pSeg->nPos;
}
/*
** xSetOutputs callback used by detail=full and detail=col tables when no
** column filters are specified.
*/
static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){
pIter->base.iRowid = pSeg->iRowid;
pIter->base.nData = pSeg->nPos;
assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE );
assert( pIter->pColset==0 || pIter->bFiltered );
if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
/* All data is stored on the current page. Populate the output
** variables to point into the body of the page object. */
pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset];
}else{
/* The data is distributed over two or more pages. Copy it into the
** Fts5Iter.poslist buffer and then set the output pointer to point
** to this buffer. */
fts5BufferZero(&pIter->poslist);
fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist);
pIter->base.pData = pIter->poslist.p;
}
}
/*
** xSetOutputs callback used by detail=col when there is a column filter
** and there are 100 or more columns. Also called as a fallback from
** fts5IterSetOutputs_Col100 if the column-list spans more than one page.
*/
static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){
fts5BufferZero(&pIter->poslist);
fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist);
pIter->base.iRowid = pSeg->iRowid;
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
}
/*
** xSetOutputs callback used when:
**
** * detail=col,
** * there is a column filter, and
** * the table contains 100 or fewer columns.
**
** The last point is to ensure all column numbers are stored as
** single-byte varints.
*/
static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
assert( pIter->pColset );
if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
fts5IterSetOutputs_Col(pIter, pSeg);
}else{
u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
u8 *pEnd = (u8*)&a[pSeg->nPos];
int iPrev = 0;
int *aiCol = pIter->pColset->aiCol;
int *aiColEnd = &aiCol[pIter->pColset->nCol];
u8 *aOut = pIter->poslist.p;
int iPrevOut = 0;
pIter->base.iRowid = pSeg->iRowid;
while( a<pEnd ){
iPrev += (int)a++[0] - 2;
while( *aiCol<iPrev ){
aiCol++;
if( aiCol==aiColEnd ) goto setoutputs_col_out;
}
if( *aiCol==iPrev ){
*aOut++ = (iPrev - iPrevOut) + 2;
iPrevOut = iPrev;
}
}
setoutputs_col_out:
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = aOut - pIter->poslist.p;
}
}
/*
** xSetOutputs callback used by detail=full when there is a column filter.
*/
static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
Fts5Colset *pColset = pIter->pColset;
pIter->base.iRowid = pSeg->iRowid;
assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL );
assert( pColset );
if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
/* All data is stored on the current page. Populate the output
** variables to point into the body of the page object. */
const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
if( pColset->nCol==1 ){
pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
pIter->base.pData = a;
}else{
fts5BufferZero(&pIter->poslist);
fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist);
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
}
}else{
/* The data is distributed over two or more pages. Copy it into the
** Fts5Iter.poslist buffer and then set the output pointer to point
** to this buffer. */
fts5BufferZero(&pIter->poslist);
fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
}
}
static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
Fts5Config *pConfig = pIter->pIndex->pConfig;
if( pConfig->eDetail==FTS5_DETAIL_NONE ){
pIter->xSetOutputs = fts5IterSetOutputs_None;
}
else if( pIter->pColset==0 || pIter->bFiltered ){
pIter->xSetOutputs = fts5IterSetOutputs_Nocolset;
}
else if( pConfig->eDetail==FTS5_DETAIL_FULL ){
pIter->xSetOutputs = fts5IterSetOutputs_Full;
}
else{
assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS );
if( pConfig->nCol<=100 ){
pIter->xSetOutputs = fts5IterSetOutputs_Col100;
sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol);
}else{
pIter->xSetOutputs = fts5IterSetOutputs_Col;
}
}
}
/* /*
** Open a new iterator to iterate though all rowid that match the ** Open a new iterator to iterate though all rowid that match the
** specified token or token prefix. ** specified token or token prefix.
@ -4944,22 +5134,27 @@ int sqlite3Fts5IndexQuery(
Fts5IndexIter **ppIter /* OUT: New iterator object */ Fts5IndexIter **ppIter /* OUT: New iterator object */
){ ){
Fts5Config *pConfig = p->pConfig; Fts5Config *pConfig = p->pConfig;
Fts5IndexIter *pRet = 0; Fts5Iter *pRet = 0;
int iIdx = 0;
Fts5Buffer buf = {0, 0, 0}; Fts5Buffer buf = {0, 0, 0};
/* If the QUERY_SCAN flag is set, all other flags must be clear. */ /* If the QUERY_SCAN flag is set, all other flags must be clear. */
assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
memcpy(&buf.p[1], pToken, nToken); memcpy(&buf.p[1], pToken, nToken);
#ifdef SQLITE_DEBUG /* Figure out which index to search and set iIdx accordingly. If this
/* If the QUERY_TEST_NOIDX flag was specified, then this must be a ** is a prefix query for which there is no prefix index, set iIdx to
** greater than pConfig->nPrefix to indicate that the query will be
** satisfied by scanning multiple terms in the main index.
**
** If the QUERY_TEST_NOIDX flag was specified, then this must be a
** prefix-query. Instead of using a prefix-index (if one exists), ** prefix-query. Instead of using a prefix-index (if one exists),
** evaluate the prefix query using the main FTS index. This is used ** evaluate the prefix query using the main FTS index. This is used
** for internal sanity checking by the integrity-check in debug ** for internal sanity checking by the integrity-check in debug
** mode only. */ ** mode only. */
#ifdef SQLITE_DEBUG
if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){ if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){
assert( flags & FTS5INDEX_QUERY_PREFIX ); assert( flags & FTS5INDEX_QUERY_PREFIX );
iIdx = 1+pConfig->nPrefix; iIdx = 1+pConfig->nPrefix;
@ -4973,6 +5168,7 @@ int sqlite3Fts5IndexQuery(
} }
if( iIdx<=pConfig->nPrefix ){ if( iIdx<=pConfig->nPrefix ){
/* Straight index lookup */
Fts5Structure *pStruct = fts5StructureRead(p); Fts5Structure *pStruct = fts5StructureRead(p);
buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
if( pStruct ){ if( pStruct ){
@ -4980,17 +5176,25 @@ int sqlite3Fts5IndexQuery(
fts5StructureRelease(pStruct); fts5StructureRelease(pStruct);
} }
}else{ }else{
/* Scan multiple terms in the main index */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
buf.p[0] = FTS5_MAIN_PREFIX; buf.p[0] = FTS5_MAIN_PREFIX;
fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
} }
if( p->rc==SQLITE_OK ){
Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
pRet->pColset = pColset;
fts5IterSetOutputCb(&p->rc, pRet);
if( p->rc==SQLITE_OK && pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
}
if( p->rc ){ if( p->rc ){
sqlite3Fts5IterClose(pRet); sqlite3Fts5IterClose(&pRet->base);
pRet = 0; pRet = 0;
fts5CloseReader(p); fts5CloseReader(p);
} }
*ppIter = pRet;
*ppIter = &pRet->base;
sqlite3Fts5BufferFree(&buf); sqlite3Fts5BufferFree(&buf);
} }
return fts5IndexReturn(p); return fts5IndexReturn(p);
@ -5000,14 +5204,15 @@ int sqlite3Fts5IndexQuery(
** Return true if the iterator passed as the only argument is at EOF. ** Return true if the iterator passed as the only argument is at EOF.
*/ */
int sqlite3Fts5IterEof(Fts5IndexIter *pIter){ int sqlite3Fts5IterEof(Fts5IndexIter *pIter){
assert( pIter->pIndex->rc==SQLITE_OK ); assert( ((Fts5Iter*)pIter)->pIndex->rc==SQLITE_OK );
return pIter->bEof; return ((Fts5Iter*)pIter)->bEof;
} }
/* /*
** Move to the next matching rowid. ** Move to the next matching rowid.
*/ */
int sqlite3Fts5IterNext(Fts5IndexIter *pIter){ int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
assert( pIter->pIndex->rc==SQLITE_OK ); assert( pIter->pIndex->rc==SQLITE_OK );
fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
return fts5IndexReturn(pIter->pIndex); return fts5IndexReturn(pIter->pIndex);
@ -5016,7 +5221,8 @@ int sqlite3Fts5IterNext(Fts5IndexIter *pIter){
/* /*
** Move to the next matching term/rowid. Used by the fts5vocab module. ** Move to the next matching term/rowid. Used by the fts5vocab module.
*/ */
int sqlite3Fts5IterNextScan(Fts5IndexIter *pIter){ int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5Index *p = pIter->pIndex; Fts5Index *p = pIter->pIndex;
assert( pIter->pIndex->rc==SQLITE_OK ); assert( pIter->pIndex->rc==SQLITE_OK );
@ -5039,7 +5245,8 @@ int sqlite3Fts5IterNextScan(Fts5IndexIter *pIter){
** definition of "at or after" depends on whether this iterator iterates ** definition of "at or after" depends on whether this iterator iterates
** in ascending or descending rowid order. ** in ascending or descending rowid order.
*/ */
int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIter, i64 iMatch){ int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
return fts5IndexReturn(pIter->pIndex); return fts5IndexReturn(pIter->pIndex);
} }
@ -5047,121 +5254,26 @@ int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIter, i64 iMatch){
/* /*
** Return the current rowid. ** Return the current rowid.
*/ */
i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIter){ i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIndexIter){
return fts5MultiIterRowid(pIter); return fts5MultiIterRowid((Fts5Iter*)pIndexIter);
} }
/* /*
** Return the current term. ** Return the current term.
*/ */
const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIter, int *pn){ const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
int n; int n;
const char *z = (const char*)fts5MultiIterTerm(pIter, &n); const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
*pn = n-1; *pn = n-1;
return &z[1]; return &z[1];
} }
static int fts5IndexExtractColset (
Fts5Colset *pColset, /* Colset to filter on */
const u8 *pPos, int nPos, /* Position list */
Fts5Buffer *pBuf /* Output buffer */
){
int rc = SQLITE_OK;
int i;
fts5BufferZero(pBuf);
for(i=0; i<pColset->nCol; i++){
const u8 *pSub = pPos;
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
if( nSub ){
fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
}
}
return rc;
}
/*
** Return a pointer to a buffer containing a copy of the position list for
** the current entry. Output variable *pn is set to the size of the buffer
** in bytes before returning.
**
** The returned position list does not include the "number of bytes" varint
** field that starts the position list on disk.
*/
int sqlite3Fts5IterPoslist(
Fts5IndexIter *pIter,
Fts5Colset *pColset, /* Column filter (or NULL) */
const u8 **pp, /* OUT: Pointer to position-list data */
int *pn, /* OUT: Size of position-list in bytes */
i64 *piRowid /* OUT: Current rowid */
){
Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
int eDetail = pIter->pIndex->pConfig->eDetail;
assert( pIter->pIndex->rc==SQLITE_OK );
*piRowid = pSeg->iRowid;
if( eDetail==FTS5_DETAIL_NONE ){
*pn = pSeg->nPos;
}else
if( eDetail==FTS5_DETAIL_FULL
&& pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
){
u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
if( pColset==0 || pIter->bFiltered ){
*pn = pSeg->nPos;
*pp = pPos;
}else if( pColset->nCol==1 ){
*pp = pPos;
*pn = fts5IndexExtractCol(pp, pSeg->nPos, pColset->aiCol[0]);
}else{
fts5BufferZero(&pIter->poslist);
fts5IndexExtractColset(pColset, pPos, pSeg->nPos, &pIter->poslist);
*pp = pIter->poslist.p;
*pn = pIter->poslist.n;
}
}else{
fts5BufferZero(&pIter->poslist);
fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
if( eDetail==FTS5_DETAIL_FULL ){
*pp = pIter->poslist.p;
}
*pn = pIter->poslist.n;
}
return fts5IndexReturn(pIter->pIndex);
}
int sqlite3Fts5IterCollist(
Fts5IndexIter *pIter,
const u8 **pp, /* OUT: Pointer to position-list data */
int *pn /* OUT: Size of position-list in bytes */
){
assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
*pp = pIter->poslist.p;
*pn = pIter->poslist.n;
return SQLITE_OK;
}
/*
** This function is similar to sqlite3Fts5IterPoslist(), except that it
** copies the position list into the buffer supplied as the second
** argument.
*/
int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf){
Fts5Index *p = pIter->pIndex;
Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
assert( p->rc==SQLITE_OK );
fts5BufferZero(pBuf);
fts5SegiterPoslist(p, pSeg, 0, pBuf);
return fts5IndexReturn(p);
}
/* /*
** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery().
*/ */
void sqlite3Fts5IterClose(Fts5IndexIter *pIter){ void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
if( pIter ){ if( pIndexIter ){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5Index *pIndex = pIter->pIndex; Fts5Index *pIndex = pIter->pIndex;
fts5MultiIterFree(pIter->pIndex, pIter); fts5MultiIterFree(pIter->pIndex, pIter);
fts5CloseReader(pIndex); fts5CloseReader(pIndex);
@ -5328,35 +5440,30 @@ static int fts5QueryCksum(
){ ){
int eDetail = p->pConfig->eDetail; int eDetail = p->pConfig->eDetail;
u64 cksum = *pCksum; u64 cksum = *pCksum;
Fts5IndexIter *pIdxIter = 0; Fts5IndexIter *pIter = 0;
Fts5Buffer buf = {0, 0, 0}; int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter);
int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter);
while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){ while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){
i64 rowid = sqlite3Fts5IterRowid(pIdxIter); i64 rowid = sqlite3Fts5IterRowid(pIter);
if( eDetail==FTS5_DETAIL_NONE ){ if( eDetail==FTS5_DETAIL_NONE ){
cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
}else{ }else{
rc = sqlite3Fts5IterPoslistBuffer(pIdxIter, &buf); Fts5PoslistReader sReader;
if( rc==SQLITE_OK ){ for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader);
Fts5PoslistReader sReader; sReader.bEof==0;
for(sqlite3Fts5PoslistReaderInit(buf.p, buf.n, &sReader); sqlite3Fts5PoslistReaderNext(&sReader)
sReader.bEof==0; ){
sqlite3Fts5PoslistReaderNext(&sReader) int iCol = FTS5_POS2COLUMN(sReader.iPos);
){ int iOff = FTS5_POS2OFFSET(sReader.iPos);
int iCol = FTS5_POS2COLUMN(sReader.iPos); cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n);
int iOff = FTS5_POS2OFFSET(sReader.iPos);
cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n);
}
} }
} }
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = sqlite3Fts5IterNext(pIdxIter); rc = sqlite3Fts5IterNext(pIter);
} }
} }
sqlite3Fts5IterClose(pIdxIter); sqlite3Fts5IterClose(pIter);
fts5BufferFree(&buf);
*pCksum = cksum; *pCksum = cksum;
return rc; return rc;
@ -5661,7 +5768,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
int eDetail = p->pConfig->eDetail; int eDetail = p->pConfig->eDetail;
u64 cksum2 = 0; /* Checksum based on contents of indexes */ u64 cksum2 = 0; /* Checksum based on contents of indexes */
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
Fts5IndexIter *pIter; /* Used to iterate through entire index */ Fts5Iter *pIter; /* Used to iterate through entire index */
Fts5Structure *pStruct; /* Index structure */ Fts5Structure *pStruct; /* Index structure */
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG

View File

@ -538,7 +538,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
for(i=0; i<pInfo->nConstraint; i++){ for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
int j; int j;
for(j=0; j<(int)ArraySize(aConstraint); j++){ for(j=0; j<ArraySize(aConstraint); j++){
struct Constraint *pC = &aConstraint[j]; struct Constraint *pC = &aConstraint[j];
if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){ if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
if( p->usable ){ if( p->usable ){
@ -585,7 +585,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
/* Assign argvIndex values to each constraint in use. */ /* Assign argvIndex values to each constraint in use. */
iNext = 1; iNext = 1;
for(i=0; i<(int)ArraySize(aConstraint); i++){ for(i=0; i<ArraySize(aConstraint); i++){
struct Constraint *pC = &aConstraint[i]; struct Constraint *pC = &aConstraint[i];
if( pC->iConsIndex>=0 ){ if( pC->iConsIndex>=0 ){
pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;

View File

@ -338,7 +338,7 @@ int sqlite3Fts5StorageClose(Fts5Storage *p){
int i; int i;
/* Finalize all SQL statements */ /* Finalize all SQL statements */
for(i=0; i<(int)ArraySize(p->aStmt); i++){ for(i=0; i<ArraySize(p->aStmt); i++){
sqlite3_finalize(p->aStmt[i]); sqlite3_finalize(p->aStmt[i]);
} }

View File

@ -1220,7 +1220,7 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
int rc = SQLITE_OK; /* Return code */ int rc = SQLITE_OK; /* Return code */
int i; /* To iterate through builtin functions */ int i; /* To iterate through builtin functions */
for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){
rc = pApi->xCreateTokenizer(pApi, rc = pApi->xCreateTokenizer(pApi,
aBuiltin[i].zName, aBuiltin[i].zName,
(void*)pApi, (void*)pApi,

View File

@ -184,7 +184,7 @@ static int fts5VocabInitVtab(
rc = fts5VocabTableType(zType, pzErr, &eType); rc = fts5VocabTableType(zType, pzErr, &eType);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
assert( eType>=0 && eType<sizeof(azSchema)/sizeof(azSchema[0]) ); assert( eType>=0 && eType<ArraySize(azSchema) );
rc = sqlite3_declare_vtab(db, azSchema[eType]); rc = sqlite3_declare_vtab(db, azSchema[eType]);
} }
@ -407,33 +407,33 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
while( rc==SQLITE_OK ){ while( rc==SQLITE_OK ){
i64 dummy;
const u8 *pPos; int nPos; /* Position list */ const u8 *pPos; int nPos; /* Position list */
i64 iPos = 0; /* 64-bit position read from poslist */ i64 iPos = 0; /* 64-bit position read from poslist */
int iOff = 0; /* Current offset within position list */ int iOff = 0; /* Current offset within position list */
pPos = pCsr->pIter->pData;
nPos = pCsr->pIter->nData;
switch( pCsr->pConfig->eDetail ){ switch( pCsr->pConfig->eDetail ){
case FTS5_DETAIL_FULL: case FTS5_DETAIL_FULL:
rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy); pPos = pCsr->pIter->pData;
if( rc==SQLITE_OK ){ nPos = pCsr->pIter->nData;
if( pTab->eType==FTS5_VOCAB_ROW ){ if( pTab->eType==FTS5_VOCAB_ROW ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
pCsr->aCnt[0]++; pCsr->aCnt[0]++;
} }
pCsr->aDoc[0]++; pCsr->aDoc[0]++;
}else{ }else{
int iCol = -1; int iCol = -1;
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
int ii = FTS5_POS2COLUMN(iPos); int ii = FTS5_POS2COLUMN(iPos);
pCsr->aCnt[ii]++; pCsr->aCnt[ii]++;
if( iCol!=ii ){ if( iCol!=ii ){
if( ii>=nCol ){ if( ii>=nCol ){
rc = FTS5_CORRUPT; rc = FTS5_CORRUPT;
break; break;
}
pCsr->aDoc[ii]++;
iCol = ii;
} }
pCsr->aDoc[ii]++;
iCol = ii;
} }
} }
} }
@ -443,19 +443,14 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( pTab->eType==FTS5_VOCAB_ROW ){ if( pTab->eType==FTS5_VOCAB_ROW ){
pCsr->aDoc[0]++; pCsr->aDoc[0]++;
}else{ }else{
Fts5Buffer buf = {0, 0, 0}; while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
rc = sqlite3Fts5IterPoslistBuffer(pCsr->pIter, &buf); assert_nc( iPos>=0 && iPos<nCol );
if( rc==SQLITE_OK ){ if( iPos>=nCol ){
while( 0==sqlite3Fts5PoslistNext64(buf.p, buf.n, &iOff,&iPos) ){ rc = FTS5_CORRUPT;
assert_nc( iPos>=0 && iPos<nCol ); break;
if( iPos>=nCol ){
rc = FTS5_CORRUPT;
break;
}
pCsr->aDoc[iPos]++;
} }
pCsr->aDoc[iPos]++;
} }
sqlite3Fts5BufferFree(&buf);
} }
break; break;

View File

@ -48,7 +48,8 @@ proc fts5_test_poslist2 {cmd} {
} }
} }
set res #set res
sort_poslist $res
} }
proc fts5_test_collist {cmd} { proc fts5_test_collist {cmd} {

View File

@ -158,8 +158,8 @@ foreach {tn2 sql} {
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
foreach {tn expr} { foreach {tn expr} {
1.2 "a OR b"
1.1 "a AND b" 1.1 "a AND b"
1.2 "a OR b"
1.3 "o" 1.3 "o"
1.4 "b q" 1.4 "b q"
1.5 "e a e" 1.5 "e a e"
@ -250,7 +250,6 @@ foreach {tn2 sql} {
FROM xx WHERE xx match $expr FROM xx WHERE xx match $expr
} $res } $res
set res [fts5_query_data $expr xx DESC] set res [fts5_query_data $expr xx DESC]
do_execsql_test 1.$tn2.$tn.[llength $res].desc { do_execsql_test 1.$tn2.$tn.[llength $res].desc {
SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx) SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx)

View File

@ -0,0 +1,44 @@
# 2015 September 05
#
# 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.
#
#*************************************************************************
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5simple3
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
fts5_aux_test_functions db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, detail=col);
INSERT INTO t1 VALUES('a', 'b', 'c');
INSERT INTO t1 VALUES('x', 'x', 'x');
}
do_execsql_test 1.1 {
SELECT rowid, fts5_test_collist(t1) FROM t1('a:a');
} {1 0.0}
do_execsql_test 1.2 {
SELECT rowid, fts5_test_collist(t1) FROM t1('b:x');
} {2 0.1}
do_execsql_test 1.3 {
SELECT rowid, fts5_test_collist(t1) FROM t1('b:a');
} {}
finish_test

View File

@ -27,6 +27,21 @@ foreach_detail_mode $testprefix {
fts5_tclnum_register db fts5_tclnum_register db
fts5_aux_test_functions db fts5_aux_test_functions db
proc fts5_test_bothlist {cmd} {
for {set i 0} {$i < [$cmd xPhraseCount]} {incr i} {
set bFirst 1
$cmd xPhraseColumnForeach $i c {
lappend CL $i.$c
if {$bFirst} { $cmd xPhraseForeach $i c o { lappend PL $i.$c.$o } }
set bFirst 0
}
}
list [sort_poslist $PL] $CL
}
sqlite3_fts5_create_function db fts5_test_bothlist fts5_test_bothlist
proc fts5_rowid {cmd} { expr [$cmd xColumnText -1] } proc fts5_rowid {cmd} { expr [$cmd xColumnText -1] }
sqlite3_fts5_create_function db fts5_rowid fts5_rowid sqlite3_fts5_create_function db fts5_rowid fts5_rowid
@ -89,6 +104,8 @@ do_execsql_test 1.$tok.0.2 {
} }
foreach {tn expr} { foreach {tn expr} {
2.1 "one OR two OR three OR four"
1.1 "one" 1.2 "two" 1.3 "three" 1.4 "four" 1.1 "one" 1.2 "two" 1.3 "three" 1.4 "four"
1.5 "v" 1.6 "vi" 1.7 "vii" 1.8 "viii" 1.5 "v" 1.6 "vi" 1.7 "vii" 1.8 "viii"
1.9 "9" 1.10 "0" 1.11 "1" 1.12 "2" 1.9 "9" 1.10 "0" 1.11 "1" 1.12 "2"
@ -113,13 +130,31 @@ foreach {tn expr} {
set res [fts5_query_data $expr ss ASC ::tclnum_syn] set res [fts5_query_data $expr ss ASC ::tclnum_syn]
do_execsql_test 1.$tok.$tn.[llength $res].asc.1 { do_execsql_test 1.$tok.$tn.[llength $res].asc.1 {
SELECT rowid, fts5_test_poslist(ss), fts5_test_collist(ss) FROM ss($expr) SELECT rowid, fts5_test_poslist2(ss), fts5_test_collist(ss) FROM ss($expr)
} $res } $res
do_execsql_test 1.$tok.$tn.[llength $res].asc.2 { do_execsql_test 1.$tok.$tn.[llength $res].asc.2 {
SELECT rowid, fts5_test_poslist(ss), fts5_test_collist(ss) FROM ss($expr) SELECT rowid, fts5_test_poslist(ss), fts5_test_collist(ss) FROM ss($expr)
} $res
do_execsql_test 1.$tok.$tn.[llength $res].asc.2 {
SELECT rowid, fts5_test_poslist2(ss), fts5_test_collist(ss) FROM ss($expr)
ORDER BY rank ASC ORDER BY rank ASC
} $res } $res
set res2 [list]
foreach {a b c} $res { lappend res2 $a $c $b }
do_execsql_test 1.$tok.$tn.[llength $res].asc.3 {
SELECT rowid, fts5_test_collist(ss), fts5_test_poslist2(ss) FROM ss($expr)
} $res2
set res3 [list]
foreach {a b c} $res { lappend res3 $a [list $b $c] }
do_execsql_test 1.$tok.$tn.[llength $res].asc.3 {
SELECT rowid, fts5_test_bothlist(ss) FROM ss($expr)
} $res3
} }
} }

View File

@ -11,6 +11,8 @@ set Q {
{1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:t*'"} {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:t*'"}
{1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t* OR b:t* OR c:t* OR d:t* OR e:t* OR f:t* OR g:t*'"} {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t* OR b:t* OR c:t* OR d:t* OR e:t* OR f:t* OR g:t*'"}
{1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t*'"} {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t*'"}
{2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:the'"}
} }
proc usage {} { proc usage {} {

View File

@ -1,13 +1,127 @@
proc usage {} { #-------------------------------------------------------------------------
puts stderr "$::argv0 ?OPTIONS? DATABASE FILE1..." # Command line options processor.
#
proc command_line_error {O E {msg ""}} {
if {$msg != ""} {
puts stderr "Error: $msg"
puts stderr ""
}
set L [list]
foreach o $O {
if {[llength $o]==1} {
lappend L [string toupper $o]
}
}
puts stderr "Usage: $::argv0 ?SWITCHES? $L"
puts stderr "" puts stderr ""
puts stderr "Options are" puts stderr "Switches are:"
puts stderr " -fts5" foreach o $O {
puts stderr " -fts4" if {[llength $o]==3} {
puts stderr " -colsize <list of column sizes>" foreach {a b c} $o {}
puts stderr { puts stderr [format " -%-15s %s (default \"%s\")" "$a VAL" $c $b]
} elseif {[llength $o]==2} {
foreach {a b} $o {}
puts stderr [format " -%-15s %s" $a $b]
}
}
puts stderr ""
puts stderr $E
exit -1
}
proc process_command_line {avar lArgs O E} {
upvar $avar A
set zTrailing "" ;# True if ... is present in $O
set lPosargs [list]
# Populate A() with default values. Also, for each switch in the command
# line spec, set an entry in the idx() array as follows:
#
# {tblname t1 "table name to use"}
# -> [set idx(-tblname) {tblname t1 "table name to use"}
#
# For each position parameter, append its name to $lPosargs. If the ...
# specifier is present, set $zTrailing to the name of the prefix.
#
foreach o $O {
set nm [lindex $o 0]
set nArg [llength $o]
switch -- $nArg {
1 {
if {[string range $nm end-2 end]=="..."} {
set zTrailing [string range $nm 0 end-3]
} else {
lappend lPosargs $nm
}
}
2 {
set A($nm) 0
set idx(-$nm) $o
}
3 {
set A($nm) [lindex $o 1]
set idx(-$nm) $o
}
default {
error "Error in command line specification"
}
}
}
# Set explicitly specified option values
#
set nArg [llength $lArgs]
for {set i 0} {$i < $nArg} {incr i} {
set opt [lindex $lArgs $i]
if {[string range $opt 0 0]!="-" || $opt=="--"} break
set c [array names idx "${opt}*"]
if {[llength $c]==0} { command_line_error $O $E "Unrecognized option: $opt"}
if {[llength $c]>1} { command_line_error $O $E "Ambiguous option: $opt"}
if {[llength $idx($c)]==3} {
if {$i==[llength $lArgs]-1} {
command_line_error $O $E "Option requires argument: $c"
}
incr i
set A([lindex $idx($c) 0]) [lindex $lArgs $i]
} else {
set A([lindex $idx($c) 0]) 1
}
}
# Deal with position arguments.
#
set nPosarg [llength $lPosargs]
set nRem [expr $nArg - $i]
if {$nRem < $nPosarg || ($zTrailing=="" && $nRem > $nPosarg)} {
command_line_error $O $E
}
for {set j 0} {$j < $nPosarg} {incr j} {
set A([lindex $lPosargs $j]) [lindex $lArgs [expr $j+$i]]
}
if {$zTrailing!=""} {
set A($zTrailing) [lrange $lArgs [expr $j+$i] end]
}
}
# End of command line options processor.
#-------------------------------------------------------------------------
process_command_line A $argv {
{fts5 "use fts5"}
{fts4 "use fts4"}
{colsize "10 10 10" "list of column sizes"}
{tblname "t1" "table name to create"}
{detail "full" "Fts5 detail mode to use"}
{repeat 1 "Load each file this many times"}
database
file...
} {
This script is designed to create fts4/5 tables with more than one column. This script is designed to create fts4/5 tables with more than one column.
The -colsize option should be set to a Tcl list of integer values, one for The -colsize option should be set to a Tcl list of integer values, one for
each column in the table. Each value is the number of tokens that will be each column in the table. Each value is the number of tokens that will be
@ -22,59 +136,27 @@ of the -colsize list. The next N2 are used for the second column of the first
row, and so on. Rows are added to the table until the entire list of tokens row, and so on. Rows are added to the table until the entire list of tokens
is exhausted. is exhausted.
} }
exit -1
if {$A(fts4)} {
set A(fts) fts4
} else {
set A(fts) fts5
} }
set O(aColSize) [list 10 10 10] sqlite3 db $A(database)
set O(tblname) t1
set O(fts) fts5
set options_with_values {-colsize}
for {set i 0} {$i < [llength $argv]} {incr i} {
set opt [lindex $argv $i]
if {[string range $opt 0 0]!="-"} break
if {[lsearch $options_with_values $opt]>=0} {
incr i
if {$i==[llength $argv]} usage
set val [lindex $argv $i]
}
switch -- $opt {
-colsize {
set O(aColSize) $val
}
-fts4 {
set O(fts) fts4
}
-fts5 {
set O(fts) fts5
}
}
}
if {$i > [llength $argv]-2} usage
set O(db) [lindex $argv $i]
set O(files) [lrange $argv [expr $i+1] end]
sqlite3 db $O(db)
# Create the FTS table in the db. Return a list of the table columns. # Create the FTS table in the db. Return a list of the table columns.
# #
proc create_table {} { proc create_table {} {
global O global A
set cols [list a b c d e f g h i j k l m n o p q r s t u v w x y z] set cols [list a b c d e f g h i j k l m n o p q r s t u v w x y z]
set nCol [llength $O(aColSize)] set nCol [llength $A(colsize)]
set cols [lrange $cols 0 [expr $nCol-1]] set cols [lrange $cols 0 [expr $nCol-1]]
set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $O(tblname) USING $O(fts) (" set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $A(tblname) USING $A(fts) ("
append sql [join $cols ,] append sql [join $cols ,]
append sql ");" if {$A(fts)=="fts5"} { append sql ",detail=$A(detail));" }
db eval $sql db eval $sql
return $cols return $cols
@ -89,27 +171,35 @@ proc readfile {file} {
split $data split $data
} }
proc repeat {L n} {
set res [list]
for {set i 0} {$i < $n} {incr i} {
set res [concat $res $L]
}
set res
}
# Load all the data into a big list of tokens. # Load all the data into a big list of tokens.
# #
set tokens [list] set tokens [list]
foreach f $O(files) { foreach f $A(file) {
set tokens [concat $tokens [readfile $f]] set tokens [concat $tokens [repeat [readfile $f] $A(repeat)]]
} }
set N [llength $tokens] set N [llength $tokens]
set i 0 set i 0
set cols [create_table] set cols [create_table]
set sql "INSERT INTO $O(tblname) VALUES(\$[lindex $cols 0]" set sql "INSERT INTO $A(tblname) VALUES(\$R([lindex $cols 0])"
foreach c [lrange $cols 1 end] { foreach c [lrange $cols 1 end] {
append sql ", \$A($c)" append sql ", \$R($c)"
} }
append sql ")" append sql ")"
db eval BEGIN db eval BEGIN
while {$i < $N} { while {$i < $N} {
foreach c $cols s $O(aColSize) { foreach c $cols s $A(colsize) {
set A($c) [lrange $tokens $i [expr $i+$s-1]] set R($c) [lrange $tokens $i [expr $i+$s-1]]
incr i $s incr i $s
} }
db eval $sql db eval $sql

View File

@ -365,8 +365,8 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
int *m; /* The cost matrix */ int *m; /* The cost matrix */
char *cx; /* Corresponding character values */ char *cx; /* Corresponding character values */
int *toFree = 0; /* Malloced space */ int *toFree = 0; /* Malloced space */
int mStack[60+15]; /* Stack space to use if not too much is needed */
int nMatch = 0; int nMatch = 0;
int mStack[60+15]; /* Stack space to use if not too much is needed */
/* Early out if either input is NULL */ /* Early out if either input is NULL */
if( zA==0 || zB==0 ) return -1; if( zA==0 || zB==0 ) return -1;
@ -875,6 +875,17 @@ static void updateCost(
} }
} }
/*
** How much stack space (int bytes) to use for Wagner matrix in
** editDist3Core(). If more space than this is required, the entire
** matrix is taken from the heap. To reduce the load on the memory
** allocator, make this value as large as practical for the
** architecture in use.
*/
#ifndef SQLITE_SPELLFIX_STACKALLOC_SZ
# define SQLITE_SPELLFIX_STACKALLOC_SZ (1024)
#endif
/* Compute the edit distance between two strings. /* Compute the edit distance between two strings.
** **
** If an error occurs, return a negative number which is the error code. ** If an error occurs, return a negative number which is the error code.
@ -899,15 +910,24 @@ static int editDist3Core(
EditDist3FromString f = *pFrom; EditDist3FromString f = *pFrom;
EditDist3To *a2; EditDist3To *a2;
unsigned int *m; unsigned int *m;
unsigned int *pToFree;
int szRow; int szRow;
EditDist3Cost *p; EditDist3Cost *p;
int res; int res;
sqlite3_uint64 nByte;
unsigned int stackSpace[SQLITE_SPELLFIX_STACKALLOC_SZ/sizeof(unsigned int)];
/* allocate the Wagner matrix and the aTo[] array for the TO string */ /* allocate the Wagner matrix and the aTo[] array for the TO string */
n = (f.n+1)*(n2+1); n = (f.n+1)*(n2+1);
n = (n+1)&~1; n = (n+1)&~1;
m = sqlite3_malloc( n*sizeof(m[0]) + sizeof(a2[0])*n2 ); nByte = n*sizeof(m[0]) + sizeof(a2[0])*n2;
if( m==0 ) return -1; /* Out of memory */ if( nByte<=sizeof(stackSpace) ){
m = stackSpace;
pToFree = 0;
}else{
m = pToFree = sqlite3_malloc( nByte );
if( m==0 ) return -1; /* Out of memory */
}
a2 = (EditDist3To*)&m[n]; a2 = (EditDist3To*)&m[n];
memset(a2, 0, sizeof(a2[0])*n2); memset(a2, 0, sizeof(a2[0])*n2);
@ -1029,7 +1049,7 @@ static int editDist3Core(
editDist3Abort: editDist3Abort:
for(i2=0; i2<n2; i2++) sqlite3_free(a2[i2].apIns); for(i2=0; i2<n2; i2++) sqlite3_free(a2[i2].apIns);
sqlite3_free(m); sqlite3_free(pToFree);
return res; return res;
} }

100
manifest
View File

@ -1,8 +1,8 @@
C Add\sa\snew\shint\sbit\son\sthe\sflags\sparameter\sof\ssqlite3BtreeDelete().\s\sThe\snew\nBTREE_IDXDELETE\sbit\sindicates\sthat\sthe\scall\sis\sto\sdelete\san\sindex\sentry\s\ncorresponding\sto\sa\stable\srow\sthat\shas\salready\sbeen\sdeleted. C Merge\sall\srecent\strunk\senhancements.
D 2016-01-21T17:06:33.267 D 2016-01-26T23:32:55.750
F Makefile.in 7be88f5b473891e3a8c07245ed60535fcda4f9ee F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc c5ead4aa22ff6f528c755b07ed1e31184ac5b3d2 F Makefile.msc 6fca5455aaecbd14479f33f091aa19df2d3d2969
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 866588d1edf0ccb5b0d33896974338f97564f719 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@ -10,9 +10,10 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am 089e5ecdb5761e64ea1013ded02feb4d8b29927d F autoconf/Makefile.am 1c1657650775960804945dc392e14d9e43c5ed84
F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38 F autoconf/Makefile.msc 68ed752a809b611d97b95d8572a34fe6fd1196f1
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt e9757a381e5ce2553dbaa6247bb8ad00eb8d87aa w autoconf/README
F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1 F autoconf/configure.ac 7b1ea0dcaf49fafba262ce4b0ee8cb3281b555d1
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
@ -97,28 +98,28 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7
F ext/fts5/fts5Int.h 5599703af9c13512900a9f22fec39d48078d619d F ext/fts5/fts5Int.h 6e0f90eb4872654a5b98130dec16965716525c9a
F ext/fts5/fts5_aux.c 2dafc3aee0c70d643140c77d8d70daffa51a9e9e F ext/fts5/fts5_aux.c b9bcce753ef5b451267b2232f0ca153ddeb3951d
F ext/fts5/fts5_buffer.c 7d3f6f01f8fdc45204e6a33925ef8478a67d28dd F ext/fts5/fts5_buffer.c f6e0c6018ffc8e39fc0b333b5daa8b8d528ae6e4
F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238 F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238
F ext/fts5/fts5_expr.c 4ab4504c54bbe24689c83411d8588f4ec99136e9 F ext/fts5/fts5_expr.c a66b9694519d9c336d9bdbd46ea22e7e14aef412
F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955
F ext/fts5/fts5_index.c 716c301835a122ba36910b4f821c87d26ae9a5d9 F ext/fts5/fts5_index.c 5558bfbeaf364cc67f937e25753ceed8757cb6d1
F ext/fts5/fts5_main.c 833db0a3df10ab26e0221a9baa40cf871c450df3 F ext/fts5/fts5_main.c 3886bbfc5ac1d9df29979823ddf2b68241e1127e
F ext/fts5/fts5_storage.c fb2eaec3aa954b680d43096dc539f8270bd6390e F ext/fts5/fts5_storage.c 2a1f44deae090cd711f02cec0c2af8e660360d24
F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966
F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070 F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070
F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be
F ext/fts5/fts5_tokenize.c 504984ac6993323247221eebe3cd55bead01b5f8 F ext/fts5/fts5_tokenize.c 4d5c4f183c7d07d144bc219b92da1ea0e962fae3
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1 F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
F ext/fts5/fts5_vocab.c ee6df1a3be103414d7b7af833ae1885c7b83a9d0 F ext/fts5/fts5_vocab.c 3ef401a8d6932db56368de32f446eb9fe73aa623
F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580 F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl 6d0d74b695c4be055a8ba1dd807f22a2abc95b5e F ext/fts5/test/fts5_common.tcl 61ff0d1a29d98a91c4553b20b3f410d858834ee9
F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084
F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b
F ext/fts5/test/fts5ac.test d5073ca7bd2d9fe8aab0c82c6c75a7e4b0d70ced F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f
F ext/fts5/test/fts5ad.test 0ddaa5b692ff220100ee396228838f4331399eaa F ext/fts5/test/fts5ad.test 0ddaa5b692ff220100ee396228838f4331399eaa
F ext/fts5/test/fts5ae.test 612dcb51f4069226791ff14c17dbfb3138c56f20 F ext/fts5/test/fts5ae.test 612dcb51f4069226791ff14c17dbfb3138c56f20
F ext/fts5/test/fts5af.test be858a96b1f5de66ba6d64f0021bd8b2408e126c F ext/fts5/test/fts5af.test be858a96b1f5de66ba6d64f0021bd8b2408e126c
@ -176,8 +177,9 @@ F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6 F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6
F ext/fts5/test/fts5simple.test 2bc6451cbe887a9215f5b14ae307c70d850344c9 F ext/fts5/test/fts5simple.test 2bc6451cbe887a9215f5b14ae307c70d850344c9
F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46 F ext/fts5/test/fts5simple2.test 98377ae1ff7749a42c21fe1a139c1ed312522c46
F ext/fts5/test/fts5simple3.test e671b36bc4dbd4f5095e66cb04473cba9f680f53
F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48 F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48
F ext/fts5/test/fts5synonym2.test eadb00c73ef0653258873e756b7e9102e0687539 F ext/fts5/test/fts5synonym2.test aa4c43bd3b691ff80f658cb064f5ab40690e834e
F ext/fts5/test/fts5tok1.test beb894c6f3468f10a574302f69ebe4436b0287c7 F ext/fts5/test/fts5tok1.test beb894c6f3468f10a574302f69ebe4436b0287c7
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2 F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89 F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
@ -188,8 +190,8 @@ F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680
F ext/fts5/test/fts5update.test 57c7012a7919889048947addae10e0613df45529 F ext/fts5/test/fts5update.test 57c7012a7919889048947addae10e0613df45529
F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e
F ext/fts5/test/fts5vocab.test 480d780aa6b699816c5066225fbd86f3a0239477 F ext/fts5/test/fts5vocab.test 480d780aa6b699816c5066225fbd86f3a0239477
F ext/fts5/tool/fts5speed.tcl aaee41894b552df8fbf8616aad003b2ea9ba3221 F ext/fts5/tool/fts5speed.tcl 47f0031e6ac564964f4f4805e439ea665e848df2
F ext/fts5/tool/fts5txt2db.tcl c374c4c4797e8cdfadabdfaeeb5412dcd6686e84 F ext/fts5/tool/fts5txt2db.tcl ae308338b2da1646dea456ab66706acdde8c714e
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45 F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
@ -210,7 +212,7 @@ F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4 F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c df6efb90eb668d1860c9b59e4320e985e46dffa7 F ext/misc/spellfix.c db4cc4b7aa12384e6c19a289a39cd232d355413d
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
@ -291,16 +293,16 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c 97cf881292e085ee71faf44f7167b6312965b562 F src/btree.c 97cf881292e085ee71faf44f7167b6312965b562
F src/btree.h c5dfbbc59226fa5fcc2b03befa85fe10ef23c1b5 F src/btree.h c5dfbbc59226fa5fcc2b03befa85fe10ef23c1b5
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
F src/build.c 31af80bba31ac159967951ef58f3144cc7db9d70 F src/build.c b4eba1e84752ec9cae7ff3dacd5a8b6d1ab8deb9
F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261 F src/callback.c 29ae4faba226c7ebb9aee93016b5ce8a8f071261
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20 F src/date.c 997651e3ee6c2818fbf7fcdb7156cef9eb3ece20
F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78 F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c
F src/delete.c f02e46234c5fc86f6c03ae34dc0ba48e93cd5029 F src/delete.c f02e46234c5fc86f6c03ae34dc0ba48e93cd5029
F src/expr.c df0d7c3230d59abd679da22ff5ce4cfd0e3a0e63 F src/expr.c d10c1cdef5810cdbf73adc9f9b383684230b360a
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c e18b3dff7d47c7bcac5ac4fc178a89b9fd322b44 F src/fkey.c c66d3e5b35d4d95b5c1e2ee6c12f5df13a7f9ad6
F src/func.c ba6c03f9e440f5693086c08ee88e6e60212b3504 F src/func.c ba6c03f9e440f5693086c08ee88e6e60212b3504
F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
@ -316,7 +318,7 @@ F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 71f81a11fc5e29a57428761ab38a7bf2ef4ee19d F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85 F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
@ -329,10 +331,10 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c b509b49b40a269e7b75ab511b6e92b2dc9444359 F src/os_unix.c 5bb20172d0c9a6afcfa829a88c406970593c848d
F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c f4e9ac39fbb1e0fde97af85c0f4e00eb90764b67 F src/pager.c 2916c66aee50f69d9ec56a7619b62d9c6a3bee61
F src/pager.h 1c2a49143dfba9e69cc8159ef019f472ed8d260b F src/pager.h 1c2a49143dfba9e69cc8159ef019f472ed8d260b
F src/parse.y caad1e98edeca6960493d0c60d31b76820dd7776 F src/parse.y caad1e98edeca6960493d0c60d31b76820dd7776
F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23
@ -340,21 +342,21 @@ F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
F src/pragma.c ea290193369faa0a26ae2f924e7b86289b4a7987 F src/pragma.c ea290193369faa0a26ae2f924e7b86289b4a7987
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
F src/prepare.c 74855ddbdfad6a1c4a4d5c4b0913ebb01174ba19 F src/prepare.c 8ca7237428f372a04717d558555ea67ee1c5df93
F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32 F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 718954db86277d696c520fe671148db1e9c4ed3c F src/select.c c34292c8ce7fe69c7cf890d933834a22572bd301
F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4 F src/shell.c dcd7a83645ef2a58ee9c6d0ea4714d877d7835c4
F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3 F src/sqlite.h.in 214476a62012e578f42133a9a3b4f97a9aa421a3
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
F src/sqliteInt.h 46e0bac7a3cdab96e8b5afd1436accc25d2c3d6a F src/sqliteInt.h 0faffdeed20201bedb202cf6ec07f14b29158c66
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tclsqlite.c 82979239a896992f9b78efec81cfda05d316a7d0 F src/tclsqlite.c 94ef6e2794220c5b6064d4c78ec7169a8c5cc45d
F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7 F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
@ -405,22 +407,22 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0
F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785 F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785
F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66 F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66
F src/trigger.c 056e51182a3677434423e3be0c74e61b90b4a663 F src/trigger.c 72d876b2d0c66604a112362bdae07dae9b104816
F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3
F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3 F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3
F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c e21a506d17a7397cba16c162d8c9c96e9769c68e F src/vdbe.c 6039096edea4ed25f7b1e28aa5d46b0ee3ba73ef
F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337
F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189 F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189
F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e
F src/vdbeaux.c 07f8f485a6cbc0a62da660f14e303061d45d5cb6 F src/vdbeaux.c 757f86e6fef8efb3dd4226cb31e2e82b9c44c883
F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75 F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75
F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0 F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0
F src/vdbesort.c 0971557e5d3c289e46f56a52aed2197c13251de7 F src/vdbesort.c 3bb1f1f03162e6d223da623714d8e93fcaeac658
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c 320682cca733115b4cbe71320b5c5eeb1074ebde F src/vtab.c 320682cca733115b4cbe71320b5c5eeb1074ebde
F src/vxworks.h 974e7d9a98f602d6310d563e1dc4e08f9fc48e47 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54 F src/wal.c d21b99fd1458159d0b1ecdccc8ee6ada4fdc4c54
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
@ -924,7 +926,7 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test 361346396ae18462c7393c1ac5c3f17237bd89b2 F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799 F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@ -1052,7 +1054,7 @@ F test/spellfix3.test f7bf7b3482971473d32b6b00f6944c5c066cff97
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5 F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142 F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
F test/sqllog.test a8faa2df39610a037dd372ed872d124260d32953 F test/sqllog.test a8faa2df39610a037dd372ed872d124260d32953
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf F test/stat.test fafe6e82dfdb97d8c8be31cd83e36e973079ce0f
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
@ -1061,9 +1063,9 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
F test/symlink.test cbf6cb8c6c4b63a39e9f0f6b0d5c99e249dbc102 F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test 2aa9e111b79fb385681ff8940124def6f8faab87 F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
@ -1376,8 +1378,9 @@ F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d
F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh 5a5441280b509d2bb3bdc71bfb63781b0d570373 F tool/mkautoconfamal.sh a29b14d54302b33fd892958f6895582ea90e4a45
F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8 F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8
F tool/mkmsvcmin.tcl 93167a9e73383465b5716aa8dfa407409fccef1d
F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b
F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
@ -1419,10 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P a3cec529f0238e4ca1196fec420f2de80d28db78 P ac2cbadd8000947c097da5b00c00090fe58fdcff a3d7b8ac53f94d29a11362f193fd1967f30583df
R 76198b2176fddd32b1fb9b7a5f18b4c8 R 7855243eb7d1aae3e5a98345ca05c333
T *branch * btree-fordelete-flag
T *sym-btree-fordelete-flag *
T -sym-trunk *
U drh U drh
Z c987d8ca8053309611f1f75e6c6acde5 Z 6eda54656ca87ef44dc31ff7472a92ee

View File

@ -1 +1 @@
ac2cbadd8000947c097da5b00c00090fe58fdcff 9a71d56dcea953cb965f1fdda9a8b8f158cdeff6

View File

@ -1708,8 +1708,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( pTab->iPKey>=0 ){ if( pTab->iPKey>=0 ){
ExprList *pList; ExprList *pList;
Token ipkToken; Token ipkToken;
ipkToken.z = pTab->aCol[pTab->iPKey].zName; sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
ipkToken.n = sqlite3Strlen30(ipkToken.z);
pList = sqlite3ExprListAppend(pParse, 0, pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
if( pList==0 ) return; if( pList==0 ) return;
@ -3057,8 +3056,7 @@ Index *sqlite3CreateIndex(
*/ */
if( pList==0 ){ if( pList==0 ){
Token prevCol; Token prevCol;
prevCol.z = pTab->aCol[pTab->nCol-1].zName; sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName);
prevCol.n = sqlite3Strlen30(prevCol.z);
pList = sqlite3ExprListAppend(pParse, 0, pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
if( pList==0 ) goto exit_create_index; if( pList==0 ) goto exit_create_index;

View File

@ -149,7 +149,9 @@ static int statConnect(
int iDb; int iDb;
if( argc>=4 ){ if( argc>=4 ){
iDb = sqlite3FindDbName(db, argv[3]); Token nm;
sqlite3TokenInit(&nm, (char*)argv[3]);
iDb = sqlite3FindDb(db, &nm);
if( iDb<0 ){ if( iDb<0 ){
*pzErr = sqlite3_mprintf("no such database: %s", argv[3]); *pzErr = sqlite3_mprintf("no such database: %s", argv[3]);
return SQLITE_ERROR; return SQLITE_ERROR;

View File

@ -85,8 +85,7 @@ Expr *sqlite3ExprAddCollateToken(
Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
Token s; Token s;
assert( zC!=0 ); assert( zC!=0 );
s.z = zC; sqlite3TokenInit(&s, (char*)zC);
s.n = sqlite3Strlen30(s.z);
return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0);
} }

View File

@ -1192,11 +1192,9 @@ static Trigger *fkActionTrigger(
assert( iFromCol>=0 ); assert( iFromCol>=0 );
assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; sqlite3TokenInit(&tToCol,
tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName);
sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName);
tToCol.n = sqlite3Strlen30(tToCol.z);
tFromCol.n = sqlite3Strlen30(tFromCol.z);
/* Create the expression "OLD.zToCol = zFromCol". It is important /* Create the expression "OLD.zToCol = zFromCol". It is important
** that the "OLD.zToCol" term is on the LHS of the = operator, so ** that the "OLD.zToCol" term is on the LHS of the = operator, so

View File

@ -322,11 +322,11 @@ static void memsys5FreeUnsafe(void *pOld){
int iBuddy; int iBuddy;
if( (iBlock>>iLogsize) & 1 ){ if( (iBlock>>iLogsize) & 1 ){
iBuddy = iBlock - size; iBuddy = iBlock - size;
assert( iBuddy>=0 );
}else{ }else{
iBuddy = iBlock + size; iBuddy = iBlock + size;
if( iBuddy>=mem5.nBlock ) break;
} }
assert( iBuddy>=0 );
if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break;
if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
memsys5Unlink(iBuddy, iLogsize); memsys5Unlink(iBuddy, iLogsize);
iLogsize++; iLogsize++;

View File

@ -149,6 +149,11 @@
*/ */
#define MAX_PATHNAME 512 #define MAX_PATHNAME 512
/*
** Maximum supported symbolic links
*/
#define SQLITE_MAX_SYMLINKS 100
/* Always cast the getpid() return type for compatibility with /* Always cast the getpid() return type for compatibility with
** kernel modules in VxWorks. */ ** kernel modules in VxWorks. */
#define osGetpid(X) (pid_t)getpid() #define osGetpid(X) (pid_t)getpid()
@ -475,6 +480,12 @@ static struct unix_syscall {
#endif #endif
#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
#if defined(HAVE_LSTAT)
{ "lstat", (sqlite3_syscall_ptr)lstat, 0 },
#else
{ "lstat", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
}; /* End of the overrideable system calls */ }; /* End of the overrideable system calls */
@ -5927,6 +5938,32 @@ static int unixAccess(
return SQLITE_OK; return SQLITE_OK;
} }
/*
**
*/
static int mkFullPathname(
const char *zPath, /* Input path */
char *zOut, /* Output buffer */
int nOut /* Allocated size of buffer zOut */
){
int nPath = sqlite3Strlen30(zPath);
int iOff = 0;
if( zPath[0]!='/' ){
if( osGetcwd(zOut, nOut-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
}
iOff = sqlite3Strlen30(zOut);
zOut[iOff++] = '/';
}
if( (iOff+nPath+1)>nOut ){
/* SQLite assumes that xFullPathname() nul-terminates the output buffer
** even if it returns an error. */
zOut[iOff] = '\0';
return SQLITE_CANTOPEN_BKPT;
}
sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
return SQLITE_OK;
}
/* /*
** Turn a relative pathname into a full pathname. The relative path ** Turn a relative pathname into a full pathname. The relative path
@ -5943,7 +5980,17 @@ static int unixFullPathname(
int nOut, /* Size of output buffer in bytes */ int nOut, /* Size of output buffer in bytes */
char *zOut /* Output buffer */ char *zOut /* Output buffer */
){ ){
#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT)
return mkFullPathname(zPath, zOut, nOut);
#else
int rc = SQLITE_OK;
int nByte; int nByte;
int nLink = 1; /* Number of symbolic links followed so far */
const char *zIn = zPath; /* Input path for each iteration of loop */
char *zDel = 0;
assert( pVfs->mxPathname==MAX_PATHNAME );
UNUSED_PARAMETER(pVfs);
/* It's odd to simulate an io-error here, but really this is just /* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this ** using the io-error infrastructure to test that SQLite handles this
@ -5952,60 +5999,62 @@ static int unixFullPathname(
*/ */
SimulateIOError( return SQLITE_ERROR ); SimulateIOError( return SQLITE_ERROR );
assert( pVfs->mxPathname==MAX_PATHNAME ); do {
UNUSED_PARAMETER(pVfs);
#if defined(HAVE_READLINK) /* Call stat() on path zIn. Set bLink to true if the path is a symbolic
/* Attempt to resolve the path as if it were a symbolic link. If it is ** link, or false otherwise. */
** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if int bLink = 0;
** the identified file is not a symbolic link or does not exist, then struct stat buf;
** zPath is copied directly into zOut. Either way, nByte is left set to if( osLstat(zIn, &buf)!=0 ){
** the size of the string copied into zOut[] in bytes. */ if( errno!=ENOENT ){
nByte = osReadlink(zPath, zOut, nOut-1); rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
if( nByte<0 ){ }
if( errno!=EINVAL && errno!=ENOENT ){ }else{
return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); bLink = S_ISLNK(buf.st_mode);
} }
sqlite3_snprintf(nOut, zOut, "%s", zPath);
nByte = sqlite3Strlen30(zOut);
}else{
zOut[nByte] = '\0';
}
#endif
/* If buffer zOut[] now contains an absolute path there is nothing more if( bLink ){
** to do. If it contains a relative path, do the following: if( zDel==0 ){
** zDel = sqlite3_malloc(nOut);
** * move the relative path string so that it is at the end of th if( zDel==0 ) rc = SQLITE_NOMEM;
** zOut[] buffer. }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
** * Call getcwd() to read the path of the current working directory rc = SQLITE_CANTOPEN_BKPT;
** into the start of the zOut[] buffer. }
** * Append a '/' character to the cwd string and move the
** relative path back within the buffer so that it immediately if( rc==SQLITE_OK ){
** follows the '/'. nByte = osReadlink(zIn, zDel, nOut-1);
** if( nByte<0 ){
** This code is written so that if the combination of the CWD and relative rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
** path are larger than the allocated size of zOut[] the CWD is silently }else{
** truncated to make it fit. This is Ok, as SQLite refuses to open any if( zDel[0]!='/' ){
** file for which this function returns a full path larger than (nOut-8) int n;
** bytes in size. */ for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
testcase( nByte==nOut-5 ); if( nByte+n+1>nOut ){
testcase( nByte==nOut-4 ); rc = SQLITE_CANTOPEN_BKPT;
if( zOut[0]!='/' && nByte<nOut-4 ){ }else{
int nCwd; memmove(&zDel[n], zDel, nByte+1);
int nRem = nOut-nByte-1; memcpy(zDel, zIn, n);
memmove(&zOut[nRem], zOut, nByte+1); nByte += n;
zOut[nRem-1] = '\0'; }
if( osGetcwd(zOut, nRem-1)==0 ){ }
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); zDel[nByte] = '\0';
}
}
zIn = zDel;
} }
nCwd = sqlite3Strlen30(zOut);
assert( nCwd<=nRem-1 );
zOut[nCwd] = '/';
memmove(&zOut[nCwd+1], &zOut[nRem], nByte+1);
}
return SQLITE_OK; assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' );
if( rc==SQLITE_OK && zIn!=zOut ){
rc = mkFullPathname(zIn, zOut, nOut);
}
if( bLink==0 ) break;
zIn = zOut;
}while( rc==SQLITE_OK );
sqlite3_free(zDel);
return rc;
#endif /* HAVE_READLINK && HAVE_LSTAT */
} }
@ -6187,7 +6236,7 @@ static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
return rc; return rc;
} }
#if 0 /* Not used */ #ifndef SQLITE_OMIT_DEPRECATED
/* /*
** Find the current time (in Universal Coordinated Time). Write the ** Find the current time (in Universal Coordinated Time). Write the
** current time and date as a Julian Day number into *prNow and ** current time and date as a Julian Day number into *prNow and
@ -6205,7 +6254,7 @@ static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
# define unixCurrentTime 0 # define unixCurrentTime 0
#endif #endif
#if 0 /* Not used */ #ifndef SQLITE_OMIT_DEPRECATED
/* /*
** We added the xGetLastError() method with the intention of providing ** We added the xGetLastError() method with the intention of providing
** better low-level error messages when operating-system problems come up ** better low-level error messages when operating-system problems come up
@ -7504,7 +7553,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed /* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */ ** correctly. See ticket [bb3a86e890c8e96ab] */
assert( ArraySize(aSyscall)==27 ); assert( ArraySize(aSyscall)==28 );
/* Register all VFSes defined in the aVfs[] array */ /* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){

View File

@ -428,6 +428,20 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
*/ */
#define MAX_SECTOR_SIZE 0x10000 #define MAX_SECTOR_SIZE 0x10000
/*
** If the option SQLITE_EXTRA_DURABLE option is set at compile-time, then
** SQLite will do extra fsync() operations when synchronous==FULL to help
** ensure that transactions are durable across a power failure. Most
** applications are happy as long as transactions are consistent across
** a power failure, and are perfectly willing to lose the last transaction
** in exchange for the extra performance of avoiding directory syncs.
** And so the default SQLITE_EXTRA_DURABLE setting is off.
*/
#ifndef SQLITE_EXTRA_DURABLE
# define SQLITE_EXTRA_DURABLE 0
#endif
/* /*
** An instance of the following structure is allocated for each active ** An instance of the following structure is allocated for each active
** savepoint and statement transaction in the system. All such structures ** savepoint and statement transaction in the system. All such structures
@ -1983,7 +1997,8 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
); );
sqlite3OsClose(pPager->jfd); sqlite3OsClose(pPager->jfd);
if( bDelete ){ if( bDelete ){
rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal,
pPager->fullSync && SQLITE_EXTRA_DURABLE);
} }
} }
} }

View File

@ -525,7 +525,7 @@ static int sqlite3Prepare(
} }
pParse->pReprepare = pReprepare; pParse->pReprepare = pReprepare;
assert( ppStmt && *ppStmt==0 ); assert( ppStmt && *ppStmt==0 );
assert( !db->mallocFailed ); /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
assert( sqlite3_mutex_held(db->mutex) ); assert( sqlite3_mutex_held(db->mutex) );
/* Check to verify that it is possible to get a read lock on all /* Check to verify that it is possible to get a read lock on all

View File

@ -1860,10 +1860,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
sqlite3ExprCode(pParse, p->pOffset, iOffset); sqlite3ExprCode(pParse, p->pOffset, iOffset);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
VdbeComment((v, "OFFSET counter")); VdbeComment((v, "OFFSET counter"));
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0); sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
VdbeComment((v, "LIMIT+OFFSET")); VdbeComment((v, "LIMIT+OFFSET"));
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1);
} }
} }
} }
@ -2280,9 +2278,8 @@ static int multiSelect(
addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
VdbeComment((v, "Jump ahead if LIMIT reached")); VdbeComment((v, "Jump ahead if LIMIT reached"));
if( p->iOffset ){ if( p->iOffset ){
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0); sqlite3VdbeAddOp3(v, OP_OffsetLimit,
sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1); p->iLimit, p->iOffset+1, p->iOffset);
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1);
} }
} }
explainSetInteger(iSub2, pParse->iNextSelectId); explainSetInteger(iSub2, pParse->iNextSelectId);
@ -4438,8 +4435,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pExpr = pRight; pExpr = pRight;
} }
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
sColname.z = zColname; sqlite3TokenInit(&sColname, zColname);
sColname.n = sqlite3Strlen30(zColname);
sqlite3ExprListSetName(pParse, pNew, &sColname, 0); sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];

View File

@ -39,9 +39,11 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
* Icon * Icon
*/ */
#if !defined(RC_VERONLY)
#define IDI_SQLITE 101 #define IDI_SQLITE 101
IDI_SQLITE ICON "..\\art\\sqlite370.ico" IDI_SQLITE ICON "..\\art\\sqlite370.ico"
#endif /* !defined(RC_VERONLY) */
/* /*
* Version * Version

View File

@ -3325,6 +3325,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
void sqlite3SetString(char **, sqlite3*, const char*); void sqlite3SetString(char **, sqlite3*, const char*);
void sqlite3ErrorMsg(Parse*, const char*, ...); void sqlite3ErrorMsg(Parse*, const char*, ...);
int sqlite3Dequote(char*); int sqlite3Dequote(char*);
void sqlite3TokenInit(Token*,char*);
int sqlite3KeywordCode(const unsigned char*, int); int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*, char **); int sqlite3RunParser(Parse*, const char*, char **);
void sqlite3FinishCoding(Parse*); void sqlite3FinishCoding(Parse*);

View File

@ -153,6 +153,7 @@ struct SqliteDb {
IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */ IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
int nStep, nSort, nIndex; /* Statistics for most recent operation */ int nStep, nSort, nIndex; /* Statistics for most recent operation */
int nTransaction; /* Number of nested [transaction] methods */ int nTransaction; /* Number of nested [transaction] methods */
int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
int bLegacyPrepare; /* True to use sqlite3_prepare() */ int bLegacyPrepare; /* True to use sqlite3_prepare() */
#endif #endif
@ -1750,7 +1751,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
return TCL_ERROR; return TCL_ERROR;
} }
rc = sqlite3_open(zDestFile, &pDest); rc = sqlite3_open_v2(zDestFile, &pDest,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE| pDb->openFlags, 0);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "cannot open target database: ", Tcl_AppendResult(interp, "cannot open target database: ",
sqlite3_errmsg(pDest), (char*)0); sqlite3_errmsg(pDest), (char*)0);
@ -2613,7 +2615,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
return TCL_ERROR; return TCL_ERROR;
} }
rc = sqlite3_open_v2(zSrcFile, &pSrc, SQLITE_OPEN_READONLY, 0); rc = sqlite3_open_v2(zSrcFile, &pSrc,
SQLITE_OPEN_READONLY | pDb->openFlags, 0);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "cannot open source database: ", Tcl_AppendResult(interp, "cannot open source database: ",
sqlite3_errmsg(pSrc), (char*)0); sqlite3_errmsg(pSrc), (char*)0);
@ -3088,6 +3091,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_ERROR; return TCL_ERROR;
} }
p->maxStmt = NUM_PREPARED_STMTS; p->maxStmt = NUM_PREPARED_STMTS;
p->openFlags = flags & SQLITE_OPEN_URI;
p->interp = interp; p->interp = interp;
zArg = Tcl_GetStringFromObj(objv[1], 0); zArg = Tcl_GetStringFromObj(objv[1], 0);
if( DbUseNre() ){ if( DbUseNre() ){

View File

@ -287,8 +287,7 @@ void sqlite3FinishTrigger(
pStepList->pTrig = pTrig; pStepList->pTrig = pTrig;
pStepList = pStepList->pNext; pStepList = pStepList->pNext;
} }
nameToken.z = pTrig->zName; sqlite3TokenInit(&nameToken, pTrig->zName);
nameToken.n = sqlite3Strlen30(nameToken.z);
sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
|| sqlite3FixExpr(&sFix, pTrig->pWhen) || sqlite3FixExpr(&sFix, pTrig->pWhen)

View File

@ -234,6 +234,14 @@ int sqlite3Dequote(char *z){
return j; return j;
} }
/*
** Generate a Token object from a string
*/
void sqlite3TokenInit(Token *p, char *z){
p->z = z;
p->n = sqlite3Strlen30(z);
}
/* Convenient short-hand */ /* Convenient short-hand */
#define UpperToLower sqlite3UpperToLower #define UpperToLower sqlite3UpperToLower

View File

@ -5766,20 +5766,31 @@ case OP_IfPos: { /* jump, in1 */
break; break;
} }
/* Opcode: SetIfNotPos P1 P2 P3 * * /* Opcode: OffsetLimit P1 P2 P3 * *
** Synopsis: if r[P1]<=0 then r[P2]=P3 ** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)
** **
** Register P1 must contain an integer. ** This opcode performs a commonly used computation associated with
** If the value of register P1 is not positive (if it is less than 1) then ** LIMIT and OFFSET process. r[P1] holds the limit counter. r[P3]
** set the value of register P2 to be the integer P3. ** holds the offset counter. The opcode computes the combined value
** of the LIMIT and OFFSET and stores that value in r[P2]. The r[P2]
** value computed is the total number of rows that will need to be
** visited in order to complete the query.
**
** If r[P3] is zero or negative, that means there is no OFFSET
** and r[P2] is set to be the value of the LIMIT, r[P1].
**
** if r[P1] is zero or negative, that means there is no LIMIT
** and r[P2] is set to -1.
**
** Otherwise, r[P2] is set to the sum of r[P1] and r[P3].
*/ */
case OP_SetIfNotPos: { /* in1, in2 */ case OP_OffsetLimit: { /* in1, out2, in3 */
pIn1 = &aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int ); pIn3 = &aMem[pOp->p3];
if( pIn1->u.i<=0 ){ pOut = out2Prerelease(p, pOp);
pOut = out2Prerelease(p, pOp); assert( pIn1->flags & MEM_Int );
pOut->u.i = pOp->p3; assert( pIn3->flags & MEM_Int );
} pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0);
break; break;
} }

View File

@ -1721,41 +1721,43 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
} }
#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ #endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
/* /* An instance of this object describes bulk memory available for use
** Allocate space from a fixed size buffer and return a pointer to ** by subcomponents of a prepared statement. Space is allocated out
** that space. If insufficient space is available, return NULL. ** of a ReusableSpace object by the allocSpace() routine below.
*/
struct ReusableSpace {
u8 *pSpace; /* Available memory */
int nFree; /* Bytes of available memory */
int nNeeded; /* Total bytes that could not be allocated */
};
/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf
** from the ReusableSpace object. Return a pointer to the allocated
** memory on success. If insufficient memory is available in the
** ReusableSpace object, increase the ReusableSpace.nNeeded
** value by the amount needed and return NULL.
** **
** The pBuf parameter is the initial value of a pointer which will ** If pBuf is not initially NULL, that means that the memory has already
** receive the new memory. pBuf is normally NULL. If pBuf is not ** been allocated by a prior call to this routine, so just return a copy
** NULL, it means that memory space has already been allocated and that ** of pBuf and leave ReusableSpace unchanged.
** this routine should not allocate any new memory. When pBuf is not
** NULL simply return pBuf. Only allocate new memory space when pBuf
** is NULL.
** **
** nByte is the number of bytes of space needed. ** This allocator is employed to repurpose unused slots at the end of the
** ** opcode array of prepared state for other memory needs of the prepared
** pFrom points to *pnFrom bytes of available space. New space is allocated ** statement.
** from the end of the pFrom buffer and *pnFrom is decremented.
**
** *pnNeeded is a counter of the number of bytes of space that have failed
** to allocate. If there is insufficient space in pFrom to satisfy the
** request, then increment *pnNeeded by the amount of the request.
*/ */
static void *allocSpace( static void *allocSpace(
void *pBuf, /* Where return pointer will be stored */ struct ReusableSpace *p, /* Bulk memory available for allocation */
int nByte, /* Number of bytes to allocate */ void *pBuf, /* Pointer to a prior allocation */
u8 *pFrom, /* Memory available for allocation */ int nByte /* Bytes of memory needed */
int *pnFrom, /* IN/OUT: Space available at pFrom */
int *pnNeeded /* If allocation cannot be made, increment *pnByte */
){ ){
assert( EIGHT_BYTE_ALIGNMENT(pFrom) ); assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) );
if( pBuf==0 ){ if( pBuf==0 ){
nByte = ROUND8(nByte); nByte = ROUND8(nByte);
if( nByte <= *pnFrom ){ if( nByte <= p->nFree ){
*pnFrom -= nByte; p->nFree -= nByte;
pBuf = &pFrom[*pnFrom]; pBuf = &p->pSpace[p->nFree];
}else{ }else{
*pnNeeded += nByte; p->nNeeded += nByte;
} }
} }
assert( EIGHT_BYTE_ALIGNMENT(pBuf) ); assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
@ -1831,9 +1833,7 @@ void sqlite3VdbeMakeReady(
int nArg; /* Number of arguments in subprograms */ int nArg; /* Number of arguments in subprograms */
int nOnce; /* Number of OP_Once instructions */ int nOnce; /* Number of OP_Once instructions */
int n; /* Loop counter */ int n; /* Loop counter */
int nFree; /* Available free space */ struct ReusableSpace x; /* Reusable bulk memory */
u8 *zCsr; /* Memory available for allocation */
int nByte; /* How much extra memory is needed */
assert( p!=0 ); assert( p!=0 );
assert( p->nOp>0 ); assert( p->nOp>0 );
@ -1851,7 +1851,7 @@ void sqlite3VdbeMakeReady(
/* For each cursor required, also allocate a memory cell. Memory /* For each cursor required, also allocate a memory cell. Memory
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
** the vdbe program. Instead they are used to allocate space for ** the vdbe program. Instead they are used to allocate memory for
** VdbeCursor/BtCursor structures. The blob of memory associated with ** VdbeCursor/BtCursor structures. The blob of memory associated with
** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
** stores the blob of memory associated with cursor 1, etc. ** stores the blob of memory associated with cursor 1, etc.
@ -1860,20 +1860,18 @@ void sqlite3VdbeMakeReady(
*/ */
nMem += nCursor; nMem += nCursor;
/* zCsr will initially point to nFree bytes of unused space at the /* Figure out how much reusable memory is available at the end of the
** end of the opcode array, p->aOp. The computation of nFree is ** opcode array. This extra memory will be reallocated for other elements
** conservative - it might be smaller than the true number of free ** of the prepared statement.
** bytes, but never larger. nFree must be a multiple of 8 - it is
** rounded down if is not.
*/ */
n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */ n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */ x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */ x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
assert( nFree>=0 ); assert( x.nFree>=0 );
if( nFree>0 ){ if( x.nFree>0 ){
memset(zCsr, 0, nFree); memset(x.pSpace, 0, x.nFree);
assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) ); assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
} }
resolveP2Values(p, &nArg); resolveP2Values(p, &nArg);
@ -1883,33 +1881,30 @@ void sqlite3VdbeMakeReady(
} }
p->expired = 0; p->expired = 0;
/* Memory for registers, parameters, cursor, etc, is allocated in two /* Memory for registers, parameters, cursor, etc, is allocated in one or two
** passes. On the first pass, we try to reuse unused space at the ** passes. On the first pass, we try to reuse unused memory at the
** end of the opcode array. If we are unable to satisfy all memory ** end of the opcode array. If we are unable to satisfy all memory
** requirements by reusing the opcode array tail, then the second ** requirements by reusing the opcode array tail, then the second
** pass will fill in the rest using a fresh allocation. ** pass will fill in the remainder using a fresh memory allocation.
** **
** This two-pass approach that reuses as much memory as possible from ** This two-pass approach that reuses as much memory as possible from
** the leftover space at the end of the opcode array can significantly ** the leftover memory at the end of the opcode array. This can significantly
** reduce the amount of memory held by a prepared statement. ** reduce the amount of memory held by a prepared statement.
*/ */
do { do {
nByte = 0; x.nNeeded = 0;
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte); p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte); p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte); p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
zCsr, &nFree, &nByte); p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce);
p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte); p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
#endif #endif
if( nByte ){ if( x.nNeeded==0 ) break;
p->pFree = sqlite3DbMallocZero(db, nByte); x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded);
} x.nFree = x.nNeeded;
zCsr = p->pFree; }while( !db->mallocFailed );
nFree = nByte;
}while( nByte && !db->mallocFailed );
p->nCursor = nCursor; p->nCursor = nCursor;
p->nOnceFlag = nOnce; p->nOnceFlag = nOnce;

View File

@ -1837,7 +1837,9 @@ int sqlite3VdbeSorterWrite(
pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory];
pSorter->iMemory += ROUND8(nReq); pSorter->iMemory += ROUND8(nReq);
pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); if( pSorter->list.pList ){
pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory);
}
}else{ }else{
pNew = (SorterRecord *)sqlite3Malloc(nReq); pNew = (SorterRecord *)sqlite3Malloc(nReq);
if( pNew==0 ){ if( pNew==0 ){

View File

@ -28,4 +28,5 @@
#define OS_VXWORKS 0 #define OS_VXWORKS 0
#define HAVE_FCHOWN 1 #define HAVE_FCHOWN 1
#define HAVE_READLINK 1 #define HAVE_READLINK 1
#define HAVE_LSTAT 1
#endif /* defined(_WRS_KERNEL) */ #endif /* defined(_WRS_KERNEL) */

View File

@ -95,7 +95,7 @@ do_test 1.4.1 {
do_re_test 1.4.2 { do_re_test 1.4.2 {
lindex $::log 0 lindex $::log 0
} {^os_unix.c:\d*: \(\d+\) (open|readlink)\(.*test.db\) - } } {^os_unix.c:\d*: \(\d+\) (open|readlink|lstat)\(.*test.db\) - }
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# Tests oserror-1.* test failures in the unlink() system call. # Tests oserror-1.* test failures in the unlink() system call.

View File

@ -14,6 +14,7 @@
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
set testprefix stat
ifcapable !vtab||!compound { ifcapable !vtab||!compound {
finish_test finish_test
@ -184,4 +185,69 @@ do_catchsql_test stat-6.1 {
CREATE VIRTUAL TABLE temp.s2 USING dbstat(mainx); CREATE VIRTUAL TABLE temp.s2 USING dbstat(mainx);
} {1 {no such database: mainx}} } {1 {no such database: mainx}}
#-------------------------------------------------------------------------
# Test that the argument passed to the dbstat constructor is dequoted
# before it is matched against the names of attached databases.
#
forcedelete test.db2
do_execsql_test 7.1 {
ATTACH 'test.db2' AS '123';
CREATE TABLE "123".x1(a, b);
INSERT INTO x1 VALUES(1, 2);
}
do_execsql_test 7.1.1 {
SELECT * FROM dbstat('123');
} {
sqlite_master / 1 leaf 1 37 875 37 0 1024
x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_execsql_test 7.1.2 {
SELECT * FROM dbstat(123);
} {
sqlite_master / 1 leaf 1 37 875 37 0 1024
x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_execsql_test 7.1.3 {
CREATE VIRTUAL TABLE x2 USING dbstat('123');
SELECT * FROM x2;
} {
sqlite_master / 1 leaf 1 37 875 37 0 1024
x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_execsql_test 7.1.4 {
CREATE VIRTUAL TABLE x3 USING dbstat(123);
SELECT * FROM x3;
} {
sqlite_master / 1 leaf 1 37 875 37 0 1024
x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_execsql_test 7.2 {
DETACH 123;
DROP TABLE x2;
DROP TABLE x3;
ATTACH 'test.db2' AS '123corp';
}
do_execsql_test 7.2.1 {
SELECT * FROM dbstat('123corp');
} {
sqlite_master / 1 leaf 1 37 875 37 0 1024
x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_catchsql_test 7.2.2 {
SELECT * FROM dbstat(123corp);
} {1 {unrecognized token: "123corp"}}
do_execsql_test 7.2.3 {
CREATE VIRTUAL TABLE x2 USING dbstat('123corp');
SELECT * FROM x2;
} {
sqlite_master / 1 leaf 1 37 875 37 0 1024
x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_catchsql_test 7.2.4 {
CREATE VIRTUAL TABLE x3 USING dbstat(123corp);
SELECT * FROM x3;
} {1 {unrecognized token: "123corp"}}
finish_test finish_test

View File

@ -83,38 +83,49 @@ do_test 1.5 {
do_test 2.0 { do_test 2.0 {
catch { db close } catch { db close }
catch { db2 close } catch { db2 close }
forcedelete test.db test.db2 forcedelete test.db test.db2 test.db3
sqlite3 db test.db sqlite3 db test.db
execsql { CREATE TABLE t1(x) } execsql { CREATE TABLE t1(x) }
file link test.db2 test.db file link test.db2 test.db
sqlite3 db2 test.db2 file link test.db3 test.db2
file exists test.db-journal set {} {}
} 0 } {}
do_test 2.1 { foreach {tn f} {1 test.db2 2 test.db3} {
execsql { do_test 2.$tn.1 {
BEGIN; sqlite3 db2 $f
INSERT INTO t1 VALUES(1); file exists test.db-journal
} db2 } 0
file exists test.db-journal do_test 2.$tn.2 {
} 1 execsql {
do_test 2.2 { BEGIN;
file exists test.db2-journal INSERT INTO t1 VALUES(1);
} 0 } db2
do_test 2.3 { file exists test.db-journal
execsql { } 1
COMMIT; do_test 2.$tn.3 {
PRAGMA journal_mode = wal; list [file exists test2.db-journal] [file exists test3.db-journal]
INSERT INTO t1 VALUES(2); } {0 0}
} db2 do_test 2.$tn.4 {
file exists test.db-wal execsql {
} 1 COMMIT;
do_test 2.4 { PRAGMA journal_mode = wal;
file exists test.db2-wal INSERT INTO t1 VALUES(2);
} 0 } db2
do_execsql_test 2.5 { file exists test.db-wal
SELECT * FROM t1; } 1
} {1 2} do_test 2.$tn.5 {
list [file exists test2.db-wal] [file exists test3.db-wal]
} {0 0}
do_execsql_test 2.$tn.6 {
SELECT * FROM t1;
} {1 2}
db2 close
do_execsql_test 2.$tn.7 {
DELETE FROM t1;
PRAGMA journal_mode = delete;
} delete
}
# Try to open a ridiculously long pathname. Bug found by # Try to open a ridiculously long pathname. Bug found by
# Kostya Serebryany using libFuzzer on 2015-11-30. # Kostya Serebryany using libFuzzer on 2015-11-30.
@ -125,5 +136,56 @@ do_test 3.1 {
set res set res
} {unable to open database file} } {unable to open database file}
#-------------------------------------------------------------------------
# Test that relative symlinks that are not located in the cwd work.
#
do_test 4.1 {
forcedelete x y z
file mkdir x
file mkdir y
file mkdir z
sqlite3 db x/test.db
file link y/test.db ../x/test.db
file link z/test.db ../y/test.db
execsql {
PRAGMA journal_mode = wal;
CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES('hello', 'world');
}
} {wal}
do_test 4.2.1 {
db close
sqlite3 db y/test.db
db eval { SELECT * FROM t1 }
} {hello world}
do_test 4.2.2 {
list [file exists x/test.db-wal] [file exists y/test.db-wal]
} {1 0}
do_test 4.3.1 {
db close
sqlite3 db z/test.db
db eval { SELECT * FROM t1 }
} {hello world}
do_test 4.3.2 {
list [file exists x/test.db-wal] [file exists y/test.db-wal] \
[file exists z/test.db-wal]
} {1 0 0}
do_test 4.4.0 {
forcedelete w
file mkdir w
file link w/test.db [file join [pwd] x/test.db]
set {} {}
} {}
do_test 4.4.1 {
db close
sqlite3 db w/test.db
db eval { SELECT * FROM t1 }
} {hello world}
do_test 4.4.2 {
list [file exists x/test.db-wal] [file exists w/test.db-wal]
} {1 0}
finish_test finish_test

View File

@ -61,7 +61,7 @@ foreach s {
fcntl read pread write pwrite fchmod fallocate fcntl read pread write pwrite fchmod fallocate
pread64 pwrite64 unlink openDirectory mkdir rmdir pread64 pwrite64 unlink openDirectory mkdir rmdir
statvfs fchown geteuid umask mmap munmap mremap statvfs fchown geteuid umask mmap munmap mremap
getpagesize readlink getpagesize readlink lstat
} { } {
if {[test_syscall exists $s]} {lappend syscall_list $s} if {[test_syscall exists $s]} {lappend syscall_list $s}
} }

View File

@ -34,14 +34,14 @@ set -e
ARTIFACT=`printf "3%.2d%.2d%.2d" $xx $yy $zz` ARTIFACT=`printf "3%.2d%.2d%.2d" $xx $yy $zz`
rm -rf $TMPSPACE rm -rf $TMPSPACE
cp -R $TOP/autoconf $TMPSPACE cp -R $TOP/autoconf $TMPSPACE
cp sqlite3.c $TMPSPACE
cp sqlite3.c $TMPSPACE cp sqlite3.h $TMPSPACE
cp sqlite3.h $TMPSPACE cp sqlite3ext.h $TMPSPACE
cp sqlite3ext.h $TMPSPACE cp $TOP/sqlite3.1 $TMPSPACE
cp $TOP/sqlite3.1 $TMPSPACE cp $TOP/sqlite3.pc.in $TMPSPACE
cp $TOP/sqlite3.pc.in $TMPSPACE cp $TOP/src/shell.c $TMPSPACE
cp $TOP/src/shell.c $TMPSPACE cp $TOP/src/sqlite3.rc $TMPSPACE
cat $TMPSPACE/configure.ac | cat $TMPSPACE/configure.ac |
sed "s/--SQLITE-VERSION--/$VERSION/" > $TMPSPACE/tmp sed "s/--SQLITE-VERSION--/$VERSION/" > $TMPSPACE/tmp

98
tool/mkmsvcmin.tcl Normal file
View File

@ -0,0 +1,98 @@
#!/usr/bin/tcl
#
# This script reads the regular MSVC makefile (../Makefile.msc) and outputs
# a revised version of that Makefile that is "minimal" in the sense that
# it uses the sqlite3.c amalgamation as input and does not require tclsh.
# The resulting "../Makefile.min.msc" is suitable for use in the amalgamation
# tarballs.
#
if {$argc==0} {
set basedir [file dir [file dir [file normalize $argv0]]]
set fromFileName [file join $basedir Makefile.msc]
set toFileName [file join $basedir autoconf Makefile.msc]
} else {
set fromFileName [lindex $argv 0]
if {![file exists $fromFileName]} {
error "input file \"$fromFileName\" does not exist"
}
set toFileName [lindex $argv 1]
if {[file exists $toFileName]} {
error "output file \"$toFileName\" already exists"
}
}
proc readFile { fileName } {
set file_id [open $fileName RDONLY]
fconfigure $file_id -encoding binary -translation binary
set result [read $file_id]
close $file_id
return $result
}
proc writeFile { fileName data } {
set file_id [open $fileName {WRONLY CREAT TRUNC}]
fconfigure $file_id -encoding binary -translation binary
puts -nonewline $file_id $data
close $file_id
return ""
}
proc escapeSubSpec { data } {
regsub -all -- {&} $data {\\\&} data
regsub -all -- {\\(\d+)} $data {\\\\\1} data
return $data
}
proc substVars { data } {
return [uplevel 1 [list subst -nocommands -nobackslashes $data]]
}
#
# NOTE: This block is used to replace the section marked <<block1>> in
# the Makefile, if it exists.
#
set blocks(1) [string trimleft [string map [list \\\\ \\] {
_HASHCHAR=^#
!IF ![echo !IFNDEF VERSION > rcver.vc] && \\
![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \\
![echo !ENDIF >> rcver.vc]
!INCLUDE rcver.vc
!ENDIF
RESOURCE_VERSION = $(VERSION:^#=)
RESOURCE_VERSION = $(RESOURCE_VERSION:define=)
RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=)
RESOURCE_VERSION = $(RESOURCE_VERSION:"=)
RESOURCE_VERSION = $(RESOURCE_VERSION:.=,)
$(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H)
echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
echo #define SQLITE_RESOURCE_VERSION $(RESOURCE_VERSION) >> sqlite3rc.h
echo #endif >> sqlite3rc.h
$(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc
}]]
set data "#### DO NOT EDIT ####\n"
append data "# This makefile is automatically "
append data "generated from the [file tail $fromFileName] at\n"
append data "# the root of the canonical SQLite source tree (not the\n"
append data "# amalgamation tarball) using the tool/[file tail $argv0]\n"
append data "# script.\n#\n\n"
append data [readFile $fromFileName]
regsub -all -- {# <<mark>>\n.*?# <</mark>>\n} \
$data "" data
foreach i [lsort -integer [array names blocks]] {
regsub -all -- [substVars \
{# <<block${i}>>\n.*?# <</block${i}>>\n}] \
$data [escapeSubSpec $blocks($i)] data
}
set data [string map [list " -I\$(TOP)\\src" ""] $data]
set data [string map [list " /DEF:sqlite3.def" ""] $data]
set data [string map [list " sqlite3.def" ""] $data]
set data [string map [list " libtclsqlite3.lib" ""] $data]
set data [string map [list "\$(TOP)\\src\\" "\$(TOP)\\"] $data]
writeFile $toFileName $data