mirror of
https://github.com/status-im/sqlcipher.git
synced 2026-08-30 22:11:14 +00:00
Merge sqlite-release(3.8.8.3) into prerelease-integration
This commit is contained in:
+76
-8
@@ -15,7 +15,7 @@
|
||||
# The toplevel directory of the source tree. This is the directory
|
||||
# that contains this "Makefile.in" and the "configure.in" script.
|
||||
#
|
||||
TOP = @srcdir@
|
||||
TOP = @abs_srcdir@
|
||||
|
||||
|
||||
# C Compiler and options for use in building executables that
|
||||
@@ -23,11 +23,15 @@ TOP = @srcdir@
|
||||
#
|
||||
BCC = @BUILD_CC@ @BUILD_CFLAGS@
|
||||
|
||||
# C Compile and options for use in building executables that
|
||||
# TCC is the C Compile 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.)
|
||||
# same unless your are cross-compiling.) Separate CC and CFLAGS macros
|
||||
# are provide so that these aspects of the build process can be changed
|
||||
# on the "make" command-line. Ex: "make CC=clang CFLAGS=-fsanitize=undefined"
|
||||
#
|
||||
TCC = @CC@ @CPPFLAGS@ @CFLAGS@ -I. -I${TOP}/src -I${TOP}/ext/rtree
|
||||
CC = @CC@
|
||||
CFLAGS = @CPPFLAGS@ @CFLAGS@
|
||||
TCC = $(CC) $(CFLAGS) -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/fts3
|
||||
|
||||
# Define this for the autoconf-based build, so that the code knows it can
|
||||
# include the generated config.h
|
||||
@@ -38,7 +42,7 @@ TCC += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite
|
||||
# Omitting the define will cause extra debugging code to be inserted and
|
||||
# includes extra comments when "EXPLAIN stmt" is used.
|
||||
#
|
||||
TCC += @TARGET_DEBUG@ @XTHREADCONNECT@
|
||||
TCC += @TARGET_DEBUG@
|
||||
|
||||
# Compiler options needed for programs that use the TCL library.
|
||||
#
|
||||
@@ -196,7 +200,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
|
||||
table.lo tokenize.lo trigger.lo \
|
||||
table.lo threads.lo tokenize.lo trigger.lo \
|
||||
update.lo util.lo vacuum.lo \
|
||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo $(CRYPTOLIBOBJ)
|
||||
@@ -250,6 +254,7 @@ SRC = \
|
||||
$(TOP)/src/mem3.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/memjournal.c \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.c \
|
||||
$(TOP)/src/mutex.h \
|
||||
$(TOP)/src/mutex_noop.c \
|
||||
@@ -283,6 +288,7 @@ SRC = \
|
||||
$(TOP)/src/sqliteInt.h \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/table.c \
|
||||
$(TOP)/src/threads.c \
|
||||
$(TOP)/src/tclsqlite.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/trigger.c \
|
||||
@@ -378,6 +384,7 @@ TESTSRC = \
|
||||
$(TOP)/src/test_autoext.c \
|
||||
$(TOP)/src/test_async.c \
|
||||
$(TOP)/src/test_backup.c \
|
||||
$(TOP)/src/test_blob.c \
|
||||
$(TOP)/src/test_btree.c \
|
||||
$(TOP)/src/test_config.c \
|
||||
$(TOP)/src/test_demovfs.c \
|
||||
@@ -413,6 +420,7 @@ TESTSRC = \
|
||||
TESTSRC += \
|
||||
$(TOP)/ext/misc/amatch.c \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
$(TOP)/ext/misc/eval.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/fuzzer.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
@@ -476,6 +484,7 @@ HDR = \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/hwtime.h \
|
||||
keywordhash.h \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.h \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
@@ -547,6 +556,11 @@ mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) -rpath "$(libdir)"
|
||||
|
||||
mptest: mptester$(EXE)
|
||||
rm -f mptest1.db
|
||||
./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test
|
||||
rm -f mptest2.db
|
||||
./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
@@ -770,6 +784,9 @@ status.lo: $(TOP)/src/status.c $(HDR)
|
||||
table.lo: $(TOP)/src/table.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/table.c
|
||||
|
||||
threads.lo: $(TOP)/src/threads.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/threads.c
|
||||
|
||||
tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c
|
||||
|
||||
@@ -948,19 +965,37 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
|
||||
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
|
||||
|
||||
|
||||
# A very detailed test running most or all test cases
|
||||
fulltest: testfixture$(TEXE) sqlcipher$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/all.test
|
||||
|
||||
# Really really long testing
|
||||
soaktest: testfixture$(TEXE) sqlcipher$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1
|
||||
|
||||
# Do extra testing but not aeverything.
|
||||
fulltestonly: testfixture$(TEXE) sqlcipher$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/full.test
|
||||
|
||||
# This is the common case. Run many tests but not those that take
|
||||
# a really long time.
|
||||
#
|
||||
test: testfixture$(TEXE) sqlcipher$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/veryquick.test
|
||||
|
||||
# Run a test using valgrind. This can take a really long time
|
||||
# because valgrind is so much slower than a native machine.
|
||||
#
|
||||
valgrindtest: testfixture$(TEXE) sqlite3$(TEXE)
|
||||
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind
|
||||
|
||||
# A very fast test that checks basic sanity. The name comes from
|
||||
# the 60s-era electronics testing: "Turn it on and see if smoke
|
||||
# comes out."
|
||||
#
|
||||
smoketest: testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/main.test
|
||||
|
||||
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
||||
echo "#define TCLSH 2" > $@
|
||||
cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@
|
||||
@@ -996,12 +1031,45 @@ wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.c
|
||||
speedtest1$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)
|
||||
|
||||
# This target will fail if the SQLite amalgamation contains any exported
|
||||
# symbols that do not begin with "sqlite3_". It is run as part of the
|
||||
# releasetest.tcl script.
|
||||
#
|
||||
checksymbols: sqlite3.lo
|
||||
nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0
|
||||
echo '0 errors out of 1 tests'
|
||||
|
||||
# Build the amalgamation-autoconf package.
|
||||
#
|
||||
amalgamation-tarball: sqlite3.c
|
||||
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh
|
||||
|
||||
# The next two rules are used to support the "threadtest" target. Building
|
||||
# threadtest runs a few thread-safety tests that are implemented in C. This
|
||||
# target is invoked by the releasetest.tcl script.
|
||||
#
|
||||
THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
|
||||
$(TOP)/test/tt3_checkpoint.c \
|
||||
$(TOP)/test/tt3_index.c \
|
||||
$(TOP)/test/tt3_vacuum.c \
|
||||
$(TOP)/test/tt3_stress.c \
|
||||
$(TOP)/test/tt3_lookaside1.c
|
||||
|
||||
threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
|
||||
$(LTLINK) $(TOP)/test/threadtest3.c sqlite3.lo -o $@ $(TLIBS)
|
||||
|
||||
threadtest: threadtest3$(TEXE)
|
||||
./threadtest3$(TEXE)
|
||||
|
||||
releasetest:
|
||||
$(TCLSH_CMD) $(TOP)/test/releasetest.tcl
|
||||
|
||||
# Standard install and cleanup targets
|
||||
#
|
||||
lib_install: libsqlcipher.la
|
||||
$(INSTALL) -d $(DESTDIR)$(libdir)
|
||||
$(LTINSTALL) libsqlcipher.la $(DESTDIR)$(libdir)
|
||||
|
||||
|
||||
install: sqlcipher$(BEXE) lib_install sqlite3.h sqlcipher.pc ${HAVE_TCL:1=tcl_install}
|
||||
$(INSTALL) -d $(DESTDIR)$(bindir)
|
||||
$(LTINSTALL) sqlcipher$(BEXE) $(DESTDIR)$(bindir)
|
||||
|
||||
+66
-23
@@ -16,6 +16,23 @@ TOP = .
|
||||
USE_AMALGAMATION = 1
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
|
||||
#
|
||||
!IFNDEF USE_FULLWARN
|
||||
USE_FULLWARN = 0
|
||||
!ENDIF
|
||||
|
||||
# If necessary, create a list of harmless compiler warnings to disable when
|
||||
# compiling the build tools. For the SQLite source code itself, warnings,
|
||||
# if any, will be disabled from within it.
|
||||
#
|
||||
!IFNDEF NO_WARN
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4152 -wd4189 -wd4206 -wd4210
|
||||
NO_WARN = $(NO_WARN) -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to use the library paths and other options necessary for
|
||||
# Windows Phone 8.1.
|
||||
#
|
||||
@@ -108,11 +125,12 @@ WIN32HEAP = 0
|
||||
# levels. Currently, the recognized values for DEBUG are:
|
||||
#
|
||||
# 0 == NDEBUG: Disables assert() and other runtime diagnostics.
|
||||
# 1 == Disables NDEBUG and all optimizations and then enables PDBs.
|
||||
# 2 == SQLITE_DEBUG: Enables various diagnostics messages and code.
|
||||
# 3 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
|
||||
# 4 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
|
||||
# 5 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
|
||||
# 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
|
||||
@@ -231,7 +249,11 @@ 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) -W4
|
||||
!ELSE
|
||||
BCC = $(NCC) -W3
|
||||
!ENDIF
|
||||
|
||||
# Check if assembly code listings should be generated for the source
|
||||
# code files to be compiled.
|
||||
@@ -252,7 +274,13 @@ NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
|
||||
# will run on the target platform. (BCC and TCC are usually the
|
||||
# same unless your are cross-compiling.)
|
||||
#
|
||||
TCC = $(CC) -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
TCC = $(CC) -W4 -DINCLUDE_MSVC_H=1
|
||||
!ELSE
|
||||
TCC = $(CC) -W3
|
||||
!ENDIF
|
||||
|
||||
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
|
||||
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src
|
||||
|
||||
# Check if assembly code listings should be generated for the source
|
||||
@@ -280,7 +308,7 @@ RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
|
||||
# MSVC runtime library.
|
||||
#
|
||||
!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0
|
||||
!IF $(DEBUG)>0
|
||||
!IF $(DEBUG)>1
|
||||
TCC = $(TCC) -MDd
|
||||
BCC = $(BCC) -MDd
|
||||
!ELSE
|
||||
@@ -288,7 +316,7 @@ TCC = $(TCC) -MD
|
||||
BCC = $(BCC) -MD
|
||||
!ENDIF
|
||||
!ELSE
|
||||
!IF $(DEBUG)>0
|
||||
!IF $(DEBUG)>1
|
||||
TCC = $(TCC) -MTd
|
||||
BCC = $(BCC) -MTd
|
||||
!ELSE
|
||||
@@ -313,7 +341,7 @@ RCC = $(RCC) -I$(TOP)\ext\rtree
|
||||
# options are necessary in order to allow debugging symbols to
|
||||
# work correctly with Visual Studio when using the amalgamation.
|
||||
#
|
||||
!IF $(DEBUG)>0
|
||||
!IF $(DEBUG)>1
|
||||
MKSQLITE3C_ARGS = --linemacros
|
||||
!ELSE
|
||||
MKSQLITE3C_ARGS =
|
||||
@@ -329,17 +357,22 @@ BCC = $(BCC) -DNDEBUG
|
||||
RCC = $(RCC) -DNDEBUG
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>1
|
||||
!IF $(DEBUG)>0
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR
|
||||
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>2
|
||||
TCC = $(TCC) -DSQLITE_DEBUG
|
||||
RCC = $(RCC) -DSQLITE_DEBUG
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>3
|
||||
!IF $(DEBUG)>4
|
||||
TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
|
||||
RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>4
|
||||
!IF $(DEBUG)>5
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
|
||||
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
|
||||
!ENDIF
|
||||
@@ -371,7 +404,7 @@ RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
|
||||
|
||||
# Validate the heap on every call into the native Win32 heap subsystem?
|
||||
#
|
||||
!IF $(DEBUG)>2
|
||||
!IF $(DEBUG)>3
|
||||
TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
|
||||
RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
|
||||
!ENDIF
|
||||
@@ -482,7 +515,7 @@ RCC = $(RCC) $(OPTS)
|
||||
|
||||
# If compiling for debugging, add some defines.
|
||||
#
|
||||
!IF $(DEBUG)>0
|
||||
!IF $(DEBUG)>1
|
||||
TCC = $(TCC) -D_DEBUG
|
||||
BCC = $(BCC) -D_DEBUG
|
||||
RCC = $(RCC) -D_DEBUG
|
||||
@@ -491,7 +524,7 @@ RCC = $(RCC) -D_DEBUG
|
||||
# If optimizations are enabled or disabled (either implicitly or
|
||||
# explicitly), add the necessary flags.
|
||||
#
|
||||
!IF $(DEBUG)>0 || $(OPTIMIZATIONS)==0
|
||||
!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0
|
||||
TCC = $(TCC) -Od
|
||||
BCC = $(BCC) -Od
|
||||
!ELSEIF $(OPTIMIZATIONS)>=3
|
||||
@@ -507,7 +540,7 @@ BCC = $(BCC) -O1
|
||||
|
||||
# If symbols are enabled (or compiling for debugging), enable PDBs.
|
||||
#
|
||||
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
|
||||
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
|
||||
TCC = $(TCC) -Zi
|
||||
BCC = $(BCC) -Zi
|
||||
!ENDIF
|
||||
@@ -592,7 +625,7 @@ LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
|
||||
|
||||
# If either debugging or symbols are enabled, enable PDBs.
|
||||
#
|
||||
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
|
||||
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
|
||||
LDFLAGS = /DEBUG
|
||||
!ENDIF
|
||||
|
||||
@@ -636,7 +669,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
|
||||
table.lo tokenize.lo trigger.lo \
|
||||
table.lo threads.lo tokenize.lo trigger.lo \
|
||||
update.lo util.lo vacuum.lo \
|
||||
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
|
||||
@@ -707,6 +740,7 @@ SRC = \
|
||||
$(TOP)\src\mem3.c \
|
||||
$(TOP)\src\mem5.c \
|
||||
$(TOP)\src\memjournal.c \
|
||||
$(TOP)\src\msvc.h \
|
||||
$(TOP)\src\mutex.c \
|
||||
$(TOP)\src\mutex.h \
|
||||
$(TOP)\src\mutex_noop.c \
|
||||
@@ -740,6 +774,7 @@ SRC = \
|
||||
$(TOP)\src\sqliteInt.h \
|
||||
$(TOP)\src\sqliteLimit.h \
|
||||
$(TOP)\src\table.c \
|
||||
$(TOP)\src\threads.c \
|
||||
$(TOP)\src\tclsqlite.c \
|
||||
$(TOP)\src\tokenize.c \
|
||||
$(TOP)\src\trigger.c \
|
||||
@@ -834,6 +869,7 @@ TESTSRC = \
|
||||
$(TOP)\src\test_autoext.c \
|
||||
$(TOP)\src\test_async.c \
|
||||
$(TOP)\src\test_backup.c \
|
||||
$(TOP)\src\test_blob.c \
|
||||
$(TOP)\src\test_btree.c \
|
||||
$(TOP)\src\test_config.c \
|
||||
$(TOP)\src\test_demovfs.c \
|
||||
@@ -869,6 +905,7 @@ TESTSRC = \
|
||||
TESTEXT = \
|
||||
$(TOP)\ext\misc\amatch.c \
|
||||
$(TOP)\ext\misc\closure.c \
|
||||
$(TOP)\ext\misc\eval.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\fuzzer.c \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
@@ -936,6 +973,7 @@ HDR = \
|
||||
$(TOP)\src\hash.h \
|
||||
$(TOP)\src\hwtime.h \
|
||||
keywordhash.h \
|
||||
$(TOP)\src\msvc.h \
|
||||
$(TOP)\src\mutex.h \
|
||||
opcodes.h \
|
||||
$(TOP)\src\os.h \
|
||||
@@ -987,8 +1025,7 @@ libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
|
||||
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
|
||||
|
||||
sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(READLINE_FLAGS) \
|
||||
$(TOP)\src\shell.c \
|
||||
$(LTLINK) $(READLINE_FLAGS) $(TOP)\src\shell.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
mptester.exe: $(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
|
||||
@@ -1038,7 +1075,8 @@ lempar.c: $(TOP)\src\lempar.c
|
||||
copy $(TOP)\src\lempar.c .
|
||||
|
||||
lemon.exe: $(TOP)\tool\lemon.c lempar.c
|
||||
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
$(BCC) $(NO_WARN) -Daccess=_access \
|
||||
-Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
|
||||
# Rules to build individual *.lo files from generated *.c files. This
|
||||
# applies to:
|
||||
@@ -1223,6 +1261,9 @@ status.lo: $(TOP)\src\status.c $(HDR)
|
||||
table.lo: $(TOP)\src\table.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\table.c
|
||||
|
||||
threads.lo: $(TOP)\src\threads.c $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\threads.c
|
||||
|
||||
tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
|
||||
$(LTCOMPILE) -c $(TOP)\src\tokenize.c
|
||||
|
||||
@@ -1306,7 +1347,8 @@ sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h
|
||||
|
||||
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
|
||||
$(BCC) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) \
|
||||
$(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
|
||||
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
.\mkkeywordhash.exe > keywordhash.h
|
||||
@@ -1387,7 +1429,8 @@ rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR)
|
||||
# hidden when the library is built via the amalgamation).
|
||||
#
|
||||
TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) libsqlite3.lib
|
||||
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
|
||||
|
||||
@@ -253,6 +253,7 @@ SRC = \
|
||||
$(TOP)/src/mem3.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/memjournal.c \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.c \
|
||||
$(TOP)/src/mutex.h \
|
||||
$(TOP)/src/mutex_noop.c \
|
||||
@@ -414,6 +415,7 @@ HDR = \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/hwtime.h \
|
||||
keywordhash.h \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.h \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
|
||||
@@ -165,3 +165,178 @@ AWK.
|
||||
Contacts:
|
||||
|
||||
http://www.sqlite.org/
|
||||
=======
|
||||
mkdir bld
|
||||
cd bld
|
||||
nmake /f Makefile.msc TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
|
||||
nmake /f Makefile.msc test TOP=..\sqlite
|
||||
|
||||
There are several build options that can be set via the NMAKE command
|
||||
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
|
||||
to the "sqlite3.dll" command line above. When debugging into the SQLite
|
||||
code, adding the "DEBUG=1" argument to one of the above command lines is
|
||||
recommended.
|
||||
|
||||
SQLite does not require [Tcl](http://www.tcl.tk/) to run, but a Tcl installation
|
||||
is required by the makefiles (including those for MSVC). SQLite contains
|
||||
a lot of generated code and Tcl is used to do much of that code generation.
|
||||
The makefiles also require AWK.
|
||||
|
||||
## Source Code Tour
|
||||
|
||||
Most of the core source files are in the **src/** subdirectory. But
|
||||
src/ also contains files used to build the "testfixture" test harness;
|
||||
those file all begin with "test". And src/ contains the "shell.c" file
|
||||
which is the main program for the "sqlite3.exe" command-line shell and
|
||||
the "tclsqlite.c" file which implements the bindings to SQLite from the
|
||||
Tcl programming language. (Historical note: SQLite began as a Tcl
|
||||
extension and only later escaped to the wild as an independent library.)
|
||||
|
||||
Test scripts and programs are found in the **test/** subdirectory.
|
||||
There are other test suites for SQLite (see
|
||||
[How SQLite Is Tested](http://www.sqlite.org/testing.html))
|
||||
but those other test suites are
|
||||
in separate source repositories.
|
||||
|
||||
The **ext/** subdirectory contains code for extensions. The
|
||||
Full-text search engine is in **ext/fts3**. The R-Tree engine is in
|
||||
**ext/rtree**. The **ext/misc** subdirectory contains a number of
|
||||
smaller, single-file extensions, such as a REGEXP operator.
|
||||
|
||||
The **tool/** subdirectory contains various scripts and programs used
|
||||
for building generated source code files or for testing or for generating
|
||||
accessory programs such as "sqlite3_analyzer(.exe)".
|
||||
|
||||
### Generated Source Code Files
|
||||
|
||||
Several of the C-language source files used by SQLite are generated from
|
||||
other sources rather than being typed in manually by a programmer. This
|
||||
section will summarize those automatically-generated files. To create all
|
||||
of the automatically-generated files, simply run "make target_source".
|
||||
The "target_source" make target will create a subdirectory "tsrc/" and
|
||||
fill it with all the source files needed to build SQLite, both
|
||||
manually-edited files and automatically-generated files.
|
||||
|
||||
The SQLite interface is defined by the **sqlite3.h** header file, which is
|
||||
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The
|
||||
[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
|
||||
The manifest.uuid file contains the SHA1 hash of the particular check-in
|
||||
and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file
|
||||
contains the current SQLite version number. The sqlite3.h header is really
|
||||
just a copy of src/sqlite.h.in with the source-id and version number inserted
|
||||
at just the right spots. Note that comment text in the sqlite3.h file is
|
||||
used to generate much of the SQLite API documentation. The Tcl scripts
|
||||
used to generate that documentation are in a separate source repository.
|
||||
|
||||
The SQL language parser is **parse.c** which is generate from a grammar in
|
||||
the src/parse.y file. The conversion of "parse.y" into "parse.c" is done
|
||||
by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
|
||||
for lemon is at tool/lemon.c. Lemon uses a
|
||||
template for generating its parser. A generic template is in tool/lempar.c,
|
||||
but SQLite uses a slightly modified template found in src/lempar.c.
|
||||
|
||||
Lemon also generates the **parse.h** header file, at the same time it
|
||||
generates parse.c. But the parse.h header file is
|
||||
modified further (to add additional symbols) using the ./addopcodes.awk
|
||||
AWK script.
|
||||
|
||||
The **opcodes.h** header file contains macros that define the numbers
|
||||
corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h
|
||||
file is generated by the scanning the src/vdbe.c source file. The
|
||||
AWK script at ./mkopcodeh.awk does this scan and generates opcodes.h.
|
||||
A second AWK script, ./mkopcodec.awk, then scans opcodes.h to generate
|
||||
the **opcodes.c** source file, which contains a reverse mapping from
|
||||
opcode-number to opcode-name that is used for EXPLAIN output.
|
||||
|
||||
The **keywordhash.h** header file contains the definition of a hash table
|
||||
that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into
|
||||
the numeric codes used by the parse.c parser. The keywordhash.h file is
|
||||
generated by a C-language program at tool mkkeywordhash.c.
|
||||
|
||||
### The Amalgamation
|
||||
|
||||
All of the individual C source code and header files (both manually-edited
|
||||
and automatically-generated) can be combined into a single big source file
|
||||
**sqlite3.c** called "the amalgamation". The amalgamation is the recommended
|
||||
way of using SQLite in a larger application. Combining all individual
|
||||
source code files into a single big source code file allows the C compiler
|
||||
to perform more cross-procedure analysis and generate better code. SQLite
|
||||
runs about 5% faster when compiled from the amalgamation versus when compiled
|
||||
from individual source files.
|
||||
|
||||
The amalgamation is generated from the tool/mksqlite3c.tcl Tcl script.
|
||||
First, all of the individual source files must be gathered into the tsrc/
|
||||
subdirectory (using the equivalent of "make target_source") then the
|
||||
tool/mksqlite3c.tcl script is run to copy them all together in just the
|
||||
right order while resolving internal "#include" references.
|
||||
|
||||
The amalgamation source file is more than 100K lines long. Some symbolic
|
||||
debuggers (most notably MSVC) are unable to deal with files longer than 64K
|
||||
lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl,
|
||||
can be run on the amalgamation to break it up into a single small C file
|
||||
called **sqlite3-all.c** that does #include on about five other files
|
||||
named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-5.c**. In this way,
|
||||
all of the source code is contained within a single translation unit so
|
||||
that the compiler can do extra cross-procedure optimization, but no
|
||||
individual source file exceeds 32K lines in length.
|
||||
|
||||
## How It All Fits Together
|
||||
|
||||
SQLite is modular in design.
|
||||
See the [architectural description](http://www.sqlite.org/arch.html)
|
||||
for details. Other documents that are useful in
|
||||
(helping to understand how SQLite works include the
|
||||
[file format](http://www.sqlite.org/fileformat2.html) description,
|
||||
the [virtual machine](http://www.sqlite.org/vdbe.html) that runs
|
||||
prepared statements, the description of
|
||||
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
|
||||
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
|
||||
|
||||
Unfortunately, years of effort have gone into optimizating SQLite, both
|
||||
for small size and high performance. And optimizations tend to result in
|
||||
complex code. So there is a lot of complexity in the SQLite implementation.
|
||||
|
||||
Key files:
|
||||
|
||||
* **sqlite3.h** - This file defines the public interface to the SQLite
|
||||
library. Readers will need to be familiar with this interface before
|
||||
trying to understand how the library works internally.
|
||||
|
||||
* **sqliteInt.h** - this header file defines many of the data objects
|
||||
used internally by SQLite.
|
||||
|
||||
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
|
||||
to parse SQL statements, and the actions that are taken at each stop
|
||||
in the parsing process.
|
||||
|
||||
* **vdbe.c** - This file implements the virtual machine that runs
|
||||
prepared statements. There are various helper files whose names
|
||||
begin with "vdbe". The VDBE has access to the vdbeInt.h header file
|
||||
which defines internal data objects. The rest of SQLite interacts
|
||||
with the VDBE through an interface defined by vdbe.h.
|
||||
|
||||
* **where.c** - This file analyzes the WHERE clause and generates
|
||||
virtual machine code to run queries efficiently. This file is
|
||||
sometimes called the "query optimizer". It has its own private
|
||||
header file, whereInt.h, that defines data objects used internally.
|
||||
|
||||
* **btree.c** - This file contains the implementation of the B-Tree
|
||||
storage engine used by SQLite.
|
||||
|
||||
* **pager.c** - This file contains the "pager" implementation, the
|
||||
module that implements transactions.
|
||||
|
||||
* **os_unix.c** and **os_win.c** - These two files implement the interface
|
||||
between SQLite and the underlying operating system using the run-time
|
||||
pluggable VFS interface.
|
||||
|
||||
|
||||
## Contacts
|
||||
|
||||
The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/)
|
||||
with geographically distributed backup servers at
|
||||
[http://www2.sqlite.org/](http://www2.sqlite.org) and
|
||||
[http://www3.sqlite.org/](http://www3.sqlite.org).
|
||||
|
||||
+8
-54
@@ -1,57 +1,11 @@
|
||||
This directory contains components use to build an autoconf-ready package
|
||||
of the SQLite amalgamation: sqlite-autoconf-30XXXXXX.tar.gz
|
||||
|
||||
This file describes how to use the files in this directory to create a new
|
||||
version of the "autoconf-amalgamation" package.
|
||||
|
||||
1. The following files should have executable permission:
|
||||
|
||||
chmod 755 install-sh
|
||||
chmod 755 missing
|
||||
chmod 755 depcomp
|
||||
chmod 755 config.sub
|
||||
chmod 755 config.guess
|
||||
|
||||
2. Copy new versions of the following SQLite files into this directory:
|
||||
|
||||
sqlite3.c
|
||||
sqlite3.h
|
||||
sqlite3ext.h
|
||||
sqlite3.1
|
||||
sqlite3.pc.in
|
||||
shell.c
|
||||
|
||||
3. Update the SQLite version number in the AC_INIT macro in file
|
||||
configure.ac:
|
||||
|
||||
AC_INIT(sqlite, 3.6.3, http://www.sqlite.org)
|
||||
|
||||
4. Run the following commands to push the version number change through
|
||||
to the generated files.
|
||||
|
||||
aclocal
|
||||
autoconf
|
||||
automake
|
||||
|
||||
5. Create the tclsqlite3.c file in the tea/generic directory. As follows:
|
||||
|
||||
mkdir -p tea/generic
|
||||
echo "#ifdef USE_SYSTEM_SQLITE" > tea/generic/tclsqlite3.c
|
||||
echo "# include <sqlite3.h>" >> tea/generic/tclsqlite3.c
|
||||
echo "#else" >> tea/generic/tclsqlite3.c
|
||||
echo "#include \"../../sqlite3.c\"" >> tea/generic/tclsqlite3.c
|
||||
echo "#endif" >> tea/generic/tclsqlite3.c
|
||||
cat ../src/tclsqlite.c >> tea/generic/tclsqlite3.c
|
||||
|
||||
6. Update the SQLite version in the AC_INIT macro in file tea/configure.in:
|
||||
|
||||
AC_INIT([sqlite], [3.6.3])
|
||||
|
||||
7. From the 'tea' directory, run the following commands:
|
||||
|
||||
autoconf
|
||||
rm -rf autom4te.cache
|
||||
|
||||
8. Run "./configure && make dist". This builds a distribution package
|
||||
named something like "sqlite-3.6.3.tar.gz". Rename to
|
||||
"sqlite-amalgamation-3.6.3.tar.gz" and use.
|
||||
To build the autoconf amalgamation, run from the top-level:
|
||||
|
||||
./configure
|
||||
make amalgamation-tarball
|
||||
|
||||
The amalgamation-tarball target (also available in "main.mk") runs the
|
||||
script tool/mkautoconfamal.sh which does the work. Refer to that script
|
||||
for details.
|
||||
|
||||
@@ -73,6 +73,7 @@ exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
datarootdir = @datarootdir@
|
||||
datadir = @datadir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
|
||||
@@ -166,8 +166,10 @@ AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
|
||||
#--------------------------------------------------------------------
|
||||
# Redefine fdatasync as fsync on systems that lack fdatasync
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync))
|
||||
#
|
||||
#AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync))
|
||||
# Check for library functions that SQLite can optionally use.
|
||||
AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r])
|
||||
|
||||
AC_FUNC_STRERROR_R
|
||||
|
||||
@@ -1641,6 +1641,7 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
|
||||
SHLIB_CFLAGS="-fPIC"
|
||||
SHLIB_LD="${CC} -shared"
|
||||
TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]"
|
||||
TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$[@]"
|
||||
SHLIB_SUFFIX=".so"
|
||||
LDFLAGS=""
|
||||
AS_IF([test $doRpath = yes], [
|
||||
@@ -1651,11 +1652,15 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
|
||||
# Version numbers are dot-stripped by system policy.
|
||||
TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .`
|
||||
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
|
||||
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1'
|
||||
TCL_LIB_VERSIONS_OK=nodots
|
||||
case $system in
|
||||
FreeBSD-3.*)
|
||||
# Version numbers are dot-stripped by system policy.
|
||||
TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
|
||||
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
|
||||
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
|
||||
TCL_LIB_VERSIONS_OK=nodots
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
Darwin-*)
|
||||
CFLAGS_OPTIMIZE="-Os"
|
||||
@@ -1826,8 +1831,8 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
|
||||
SHLIB_CFLAGS="-fPIC -melf"
|
||||
LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
|
||||
], [
|
||||
SHLIB_CFLAGS="-Kpic -belf"
|
||||
LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
|
||||
SHLIB_CFLAGS="-Kpic -belf"
|
||||
LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
|
||||
])
|
||||
SHLIB_LD="ld -G"
|
||||
SHLIB_LD_LIBS=""
|
||||
@@ -4158,8 +4163,6 @@ AC_DEFUN([TEA_PATH_CELIB], [
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# Local Variables:
|
||||
# mode: autoconf
|
||||
# End:
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `isnan' function. */
|
||||
#undef HAVE_ISNAN
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#undef HAVE_LOCALTIME_R
|
||||
|
||||
@@ -48,6 +51,9 @@
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the strchrnul() function */
|
||||
#undef HAVE_STRCHRNUL
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.62 for sqlcipher 3.8.6.
|
||||
# Generated by GNU Autoconf 2.62 for sqlcipher 3.8.8.3.
|
||||
#
|
||||
# This configure script is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy, distribute and modify it.
|
||||
@@ -722,8 +722,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlcipher'
|
||||
PACKAGE_TARNAME='sqlcipher'
|
||||
PACKAGE_VERSION='3.8.6'
|
||||
PACKAGE_STRING='sqlite 3.8.6'
|
||||
PACKAGE_VERSION='3.8.8.3'
|
||||
PACKAGE_STRING='sqlcipher 3.8.8.3'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -763,7 +763,116 @@ ac_includes_default="\
|
||||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='LTLIBOBJS
|
||||
ac_subst_vars='SHELL
|
||||
PATH_SEPARATOR
|
||||
PACKAGE_NAME
|
||||
PACKAGE_TARNAME
|
||||
PACKAGE_VERSION
|
||||
PACKAGE_STRING
|
||||
PACKAGE_BUGREPORT
|
||||
exec_prefix
|
||||
prefix
|
||||
program_transform_name
|
||||
bindir
|
||||
sbindir
|
||||
libexecdir
|
||||
datarootdir
|
||||
datadir
|
||||
sysconfdir
|
||||
sharedstatedir
|
||||
localstatedir
|
||||
includedir
|
||||
oldincludedir
|
||||
docdir
|
||||
infodir
|
||||
htmldir
|
||||
dvidir
|
||||
pdfdir
|
||||
psdir
|
||||
libdir
|
||||
localedir
|
||||
mandir
|
||||
DEFS
|
||||
ECHO_C
|
||||
ECHO_N
|
||||
ECHO_T
|
||||
LIBS
|
||||
build_alias
|
||||
host_alias
|
||||
target_alias
|
||||
LIBTOOL
|
||||
build
|
||||
build_cpu
|
||||
build_vendor
|
||||
build_os
|
||||
host
|
||||
host_cpu
|
||||
host_vendor
|
||||
host_os
|
||||
CC
|
||||
CFLAGS
|
||||
LDFLAGS
|
||||
CPPFLAGS
|
||||
ac_ct_CC
|
||||
EXEEXT
|
||||
OBJEXT
|
||||
SED
|
||||
GREP
|
||||
EGREP
|
||||
FGREP
|
||||
LD
|
||||
DUMPBIN
|
||||
ac_ct_DUMPBIN
|
||||
NM
|
||||
LN_S
|
||||
OBJDUMP
|
||||
AR
|
||||
STRIP
|
||||
RANLIB
|
||||
lt_ECHO
|
||||
DSYMUTIL
|
||||
NMEDIT
|
||||
LIPO
|
||||
OTOOL
|
||||
OTOOL64
|
||||
CPP
|
||||
INSTALL_PROGRAM
|
||||
INSTALL_SCRIPT
|
||||
INSTALL_DATA
|
||||
AWK
|
||||
TCLSH_CMD
|
||||
TCLLIBDIR
|
||||
program_prefix
|
||||
VERSION
|
||||
RELEASE
|
||||
VERSION_NUMBER
|
||||
BUILD_CC
|
||||
SQLITE_THREADSAFE
|
||||
ALLOWRELEASE
|
||||
TEMP_STORE
|
||||
BUILD_EXEEXT
|
||||
SQLITE_OS_UNIX
|
||||
SQLITE_OS_WIN
|
||||
TARGET_EXEEXT
|
||||
TCL_VERSION
|
||||
TCL_BIN_DIR
|
||||
TCL_SRC_DIR
|
||||
TCL_INCLUDE_SPEC
|
||||
TCL_LIB_FILE
|
||||
TCL_LIB_FLAG
|
||||
TCL_LIB_SPEC
|
||||
TCL_STUB_LIB_FILE
|
||||
TCL_STUB_LIB_FLAG
|
||||
TCL_STUB_LIB_SPEC
|
||||
HAVE_TCL
|
||||
TARGET_READLINE_LIBS
|
||||
TARGET_READLINE_INC
|
||||
TARGET_HAVE_READLINE
|
||||
TARGET_DEBUG
|
||||
USE_AMALGAMATION
|
||||
OPT_FEATURE_FLAGS
|
||||
USE_GCOV
|
||||
BUILD_CFLAGS
|
||||
LIBOBJS
|
||||
BUILD_CFLAGS
|
||||
USE_GCOV
|
||||
@@ -887,7 +996,6 @@ enable_fast_install
|
||||
with_gnu_ld
|
||||
enable_libtool_lock
|
||||
enable_largefile
|
||||
with_hints
|
||||
enable_threadsafe
|
||||
with_crypto_lib
|
||||
enable_cross_thread_connections
|
||||
@@ -1453,7 +1561,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlcipher 3.8.6 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlcipher 3.8.8.3 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1518,7 +1626,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlcipher 3.8.6:";;
|
||||
short | recursive ) echo "Configuration of sqlcipher 3.8.8.3:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1532,9 +1640,7 @@ Optional Features:
|
||||
optimize for fast installation [default=yes]
|
||||
--disable-libtool-lock avoid locking (might break parallel builds)
|
||||
--disable-largefile omit support for large files
|
||||
--enable-threadsafe Support threadsafe operation
|
||||
--enable-cross-thread-connections
|
||||
Allow connection sharing across threads
|
||||
--disable-threadsafe Disable mutexing
|
||||
--enable-releasemode Support libtool link to release mode
|
||||
--enable-tempstore Use an in-ram database for temporary tables
|
||||
(never,no,yes,always)
|
||||
@@ -1543,7 +1649,8 @@ Optional Features:
|
||||
--enable-debug enable debugging & verbose explain
|
||||
--disable-amalgamation Disable the amalgamation and instead build all files
|
||||
separately
|
||||
--enable-load-extension Enable loading of external extensions
|
||||
--disable-load-extension
|
||||
Disable loading of external extensions
|
||||
--enable-gcov Enable coverage testing using gcov
|
||||
|
||||
Optional Packages:
|
||||
@@ -1636,7 +1743,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlcipher configure 3.8.6
|
||||
sqlcipher configure 3.8.8.3
|
||||
generated by GNU Autoconf 2.62
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2408,9 +2515,6 @@ as_fn_error $? "configure script is out of date:
|
||||
please regen with autoconf" "$LINENO" 5
|
||||
fi
|
||||
|
||||
# The following RCS revision string applies to configure.in
|
||||
# $Revision: 1.56 $
|
||||
|
||||
#########
|
||||
# Programs needed
|
||||
#
|
||||
@@ -3912,13 +4016,13 @@ if ${lt_cv_nm_interface+:} false; then :
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3923: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3727: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3926: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3730: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3929: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3733: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5124,8 +5228,8 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5135 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
echo '#line 4955 "configure"' > conftest.$ac_ext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
@@ -6649,11 +6753,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6660: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6824: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6664: \$? = $ac_status" >&5
|
||||
echo "$as_me:6828: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -6988,11 +7092,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6999: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7163: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7003: \$? = $ac_status" >&5
|
||||
echo "$as_me:7167: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7093,11 +7197,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7104: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7268: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7108: \$? = $ac_status" >&5
|
||||
echo "$as_me:7272: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -7148,11 +7252,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7159: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7323: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7163: \$? = $ac_status" >&5
|
||||
echo "$as_me:7327: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -9528,7 +9632,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9539 "configure"
|
||||
#line 10136 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9624,7 +9728,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9635 "configure"
|
||||
#line 10232 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -10268,8 +10372,18 @@ fi
|
||||
ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default"
|
||||
if test "x$ac_cv_type_uint64_t" = xyes; then :
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_UINT64_T 1
|
||||
|
||||
|
||||
for ac_func in fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime
|
||||
do
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
$as_echo_n "checking for $ac_func... " >&6; }
|
||||
if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
|
||||
|
||||
@@ -10413,45 +10527,7 @@ $as_echo "$as_me: Version number set to $VERSION_NUMBER" >&6;}
|
||||
|
||||
|
||||
#########
|
||||
# Check to see if the --with-hints=FILE option is used. If there is none,
|
||||
# then check for a files named "$host.hints" and ../$hosts.hints where
|
||||
# $host is the hostname of the build system. If still no hints are
|
||||
# found, try looking in $system.hints and ../$system.hints where
|
||||
# $system is the result of uname -s.
|
||||
#
|
||||
|
||||
# Check whether --with-hints was given.
|
||||
if test "${with_hints+set}" = set; then :
|
||||
withval=$with_hints; hints=$withval
|
||||
fi
|
||||
|
||||
if test "$hints" = ""; then
|
||||
host=`hostname | sed 's/\..*//'`
|
||||
if test -r $host.hints; then
|
||||
hints=$host.hints
|
||||
else
|
||||
if test -r ../$host.hints; then
|
||||
hints=../$host.hints
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "$hints" = ""; then
|
||||
sys=`uname -s`
|
||||
if test -r $sys.hints; then
|
||||
hints=$sys.hints
|
||||
else
|
||||
if test -r ../$sys.hints; then
|
||||
hints=../$sys.hints
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "$hints" != ""; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: reading hints from $hints" >&5
|
||||
$as_echo "reading hints from $hints" >&6; }
|
||||
. $hints
|
||||
fi
|
||||
|
||||
#########
|
||||
# Locate a compiler for the build machine. This compiler should
|
||||
# generate command-line programs that run on the build machine.
|
||||
#
|
||||
@@ -11336,7 +11412,7 @@ fi
|
||||
if test "${enable_load_extension+set}" = set; then :
|
||||
enableval=$enable_load_extension; use_loadextension=$enableval
|
||||
else
|
||||
use_loadextension=no
|
||||
use_loadextension=yes
|
||||
fi
|
||||
|
||||
if test "${use_loadextension}" = "yes" ; then
|
||||
@@ -11986,7 +12062,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlcipher $as_me 3.8.6, which was
|
||||
This file was extended by sqlcipher $as_me 3.8.8.3, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12052,7 +12128,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlcipher config.status 3.8.6
|
||||
sqlcipher config.status 3.8.8.3
|
||||
configured by $0, generated by GNU Autoconf 2.62,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
||||
+5
-58
@@ -69,19 +69,6 @@
|
||||
# The filename extension for executables on the
|
||||
# target platform. "" for Unix and ".exe" for windows.
|
||||
#
|
||||
# The generated configure script will make an attempt to guess
|
||||
# at all of the above parameters. You can override any of
|
||||
# the guesses by setting the environment variable named
|
||||
# "config_AAAA" where "AAAA" is the name of the parameter
|
||||
# described above. (Exception: srcdir cannot be set this way.)
|
||||
# If you have a file that sets one or more of these environment
|
||||
# variables, you can invoke configure as follows:
|
||||
#
|
||||
# configure --with-hints=FILE
|
||||
#
|
||||
# where FILE is the name of the file that sets the environment
|
||||
# variables. FILE should be an absolute pathname.
|
||||
#
|
||||
# This configure.in file is easy to reuse on other projects. Just
|
||||
# change the argument to AC_INIT(). And disable any features that
|
||||
# you don't need (for example BLT) by erasing or commenting out
|
||||
@@ -98,11 +85,6 @@ AC_MSG_ERROR([configure script is out of date:
|
||||
please regen with autoconf])
|
||||
fi
|
||||
|
||||
dnl Put the RCS revision string after AC_INIT so that it will also
|
||||
dnl show in in configure.
|
||||
# The following RCS revision string applies to configure.in
|
||||
# $Revision: 1.56 $
|
||||
|
||||
#########
|
||||
# Programs needed
|
||||
#
|
||||
@@ -127,7 +109,7 @@ AC_CHECK_HEADERS([sys/types.h stdlib.h stdint.h inttypes.h malloc.h])
|
||||
#########
|
||||
# Figure out whether or not we have these functions
|
||||
#
|
||||
AC_CHECK_FUNCS([usleep fdatasync localtime_r gmtime_r localtime_s utime malloc_usable_size])
|
||||
AC_CHECK_FUNCS([fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime])
|
||||
|
||||
#########
|
||||
# By default, we use the amalgamation (this may be changed below...)
|
||||
@@ -179,41 +161,6 @@ VERSION_NUMBER=[`cat $srcdir/VERSION \
|
||||
AC_MSG_NOTICE(Version number set to $VERSION_NUMBER)
|
||||
AC_SUBST(VERSION_NUMBER)
|
||||
|
||||
#########
|
||||
# Check to see if the --with-hints=FILE option is used. If there is none,
|
||||
# then check for a files named "$host.hints" and ../$hosts.hints where
|
||||
# $host is the hostname of the build system. If still no hints are
|
||||
# found, try looking in $system.hints and ../$system.hints where
|
||||
# $system is the result of uname -s.
|
||||
#
|
||||
AC_ARG_WITH(hints,
|
||||
AC_HELP_STRING([--with-hints=FILE],[Read configuration options from FILE]),
|
||||
hints=$withval)
|
||||
if test "$hints" = ""; then
|
||||
host=`hostname | sed 's/\..*//'`
|
||||
if test -r $host.hints; then
|
||||
hints=$host.hints
|
||||
else
|
||||
if test -r ../$host.hints; then
|
||||
hints=../$host.hints
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "$hints" = ""; then
|
||||
sys=`uname -s`
|
||||
if test -r $sys.hints; then
|
||||
hints=$sys.hints
|
||||
else
|
||||
if test -r ../$sys.hints; then
|
||||
hints=../$sys.hints
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "$hints" != ""; then
|
||||
AC_MSG_RESULT(reading hints from $hints)
|
||||
. $hints
|
||||
fi
|
||||
|
||||
#########
|
||||
# Locate a compiler for the build machine. This compiler should
|
||||
# generate command-line programs that run on the build machine.
|
||||
@@ -235,7 +182,7 @@ AC_SUBST(BUILD_CC)
|
||||
# Do we want to support multithreaded use of sqlite
|
||||
#
|
||||
AC_ARG_ENABLE(threadsafe,
|
||||
AC_HELP_STRING([--enable-threadsafe],[Support threadsafe operation]),,enable_threadsafe=yes)
|
||||
AC_HELP_STRING([--disable-threadsafe],[Disable mutexing]),,enable_threadsafe=yes)
|
||||
AC_MSG_CHECKING([whether to support threadsafe operation])
|
||||
if test "$enable_threadsafe" = "no"; then
|
||||
SQLITE_THREADSAFE=0
|
||||
@@ -635,9 +582,9 @@ AC_SUBST(USE_AMALGAMATION)
|
||||
|
||||
#########
|
||||
# See whether we should allow loadable extensions
|
||||
AC_ARG_ENABLE(load-extension, AC_HELP_STRING([--enable-load-extension],
|
||||
[Enable loading of external extensions]),
|
||||
[use_loadextension=$enableval],[use_loadextension=no])
|
||||
AC_ARG_ENABLE(load-extension, AC_HELP_STRING([--disable-load-extension],
|
||||
[Disable loading of external extensions]),
|
||||
[use_loadextension=$enableval],[use_loadextension=yes])
|
||||
if test "${use_loadextension}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS=""
|
||||
AC_SEARCH_LIBS(dlopen, dl)
|
||||
|
||||
+59
-66
@@ -1853,7 +1853,7 @@ static int fts3SelectLeaf(
|
||||
sqlite3_int64 *piLeaf, /* Selected leaf node */
|
||||
sqlite3_int64 *piLeaf2 /* Selected leaf node */
|
||||
){
|
||||
int rc; /* Return code */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int iHeight; /* Height of this node in tree */
|
||||
|
||||
assert( piLeaf || piLeaf2 );
|
||||
@@ -1864,7 +1864,7 @@ static int fts3SelectLeaf(
|
||||
|
||||
if( rc==SQLITE_OK && iHeight>1 ){
|
||||
char *zBlob = 0; /* Blob read from %_segments table */
|
||||
int nBlob; /* Size of zBlob in bytes */
|
||||
int nBlob = 0; /* Size of zBlob in bytes */
|
||||
|
||||
if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
|
||||
rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0);
|
||||
@@ -3086,7 +3086,7 @@ static int fts3FilterMethod(
|
||||
int nVal, /* Number of elements in apVal */
|
||||
sqlite3_value **apVal /* Arguments for the indexing scheme */
|
||||
){
|
||||
int rc;
|
||||
int rc = SQLITE_OK;
|
||||
char *zSql; /* SQL statement used to access %_content */
|
||||
int eSearch;
|
||||
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
|
||||
@@ -3116,6 +3116,7 @@ static int fts3FilterMethod(
|
||||
/* In case the cursor has been used before, clear it now. */
|
||||
sqlite3_finalize(pCsr->pStmt);
|
||||
sqlite3_free(pCsr->aDoclist);
|
||||
sqlite3_free(pCsr->aMatchinfo);
|
||||
sqlite3Fts3ExprFree(pCsr->pExpr);
|
||||
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
|
||||
|
||||
@@ -4426,7 +4427,7 @@ static int fts3EvalIncrPhraseNext(
|
||||
bMaxSet = 1;
|
||||
}
|
||||
}
|
||||
assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 );
|
||||
assert( rc!=SQLITE_OK || (p->nToken>=1 && a[p->nToken-1].bIgnore==0) );
|
||||
assert( rc!=SQLITE_OK || bMaxSet );
|
||||
|
||||
/* Keep advancing iterators until they all point to the same document */
|
||||
@@ -5019,6 +5020,22 @@ static void fts3EvalNextRow(
|
||||
}
|
||||
pExpr->iDocid = pLeft->iDocid;
|
||||
pExpr->bEof = (pLeft->bEof || pRight->bEof);
|
||||
if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
|
||||
if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){
|
||||
Fts3Doclist *pDl = &pRight->pPhrase->doclist;
|
||||
while( *pRc==SQLITE_OK && pRight->bEof==0 ){
|
||||
memset(pDl->pList, 0, pDl->nList);
|
||||
fts3EvalNextRow(pCsr, pRight, pRc);
|
||||
}
|
||||
}
|
||||
if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){
|
||||
Fts3Doclist *pDl = &pLeft->pPhrase->doclist;
|
||||
while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
|
||||
memset(pDl->pList, 0, pDl->nList);
|
||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5391,6 +5408,7 @@ static void fts3EvalRestart(
|
||||
}
|
||||
pPhrase->doclist.pNextDocid = 0;
|
||||
pPhrase->doclist.iDocid = 0;
|
||||
pPhrase->pOrPoslist = 0;
|
||||
}
|
||||
|
||||
pExpr->iDocid = 0;
|
||||
@@ -5636,6 +5654,7 @@ int sqlite3Fts3EvalPhrasePoslist(
|
||||
iDocid = pExpr->iDocid;
|
||||
pIter = pPhrase->doclist.pList;
|
||||
if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
|
||||
int rc = SQLITE_OK;
|
||||
int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
|
||||
int iMul; /* +1 if csr dir matches index dir, else -1 */
|
||||
int bOr = 0;
|
||||
@@ -5661,72 +5680,43 @@ int sqlite3Fts3EvalPhrasePoslist(
|
||||
** an incremental phrase. Load the entire doclist for the phrase
|
||||
** into memory in this case. */
|
||||
if( pPhrase->bIncr ){
|
||||
int rc = SQLITE_OK;
|
||||
int bEofSave = pExpr->bEof;
|
||||
fts3EvalRestart(pCsr, pExpr, &rc);
|
||||
while( rc==SQLITE_OK && !pExpr->bEof ){
|
||||
fts3EvalNextRow(pCsr, pExpr, &rc);
|
||||
if( bEofSave==0 && pExpr->iDocid==iDocid ) break;
|
||||
int bEofSave = pNear->bEof;
|
||||
fts3EvalRestart(pCsr, pNear, &rc);
|
||||
while( rc==SQLITE_OK && !pNear->bEof ){
|
||||
fts3EvalNextRow(pCsr, pNear, &rc);
|
||||
if( bEofSave==0 && pNear->iDocid==iDocid ) break;
|
||||
}
|
||||
pIter = pPhrase->doclist.pList;
|
||||
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
|
||||
iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1);
|
||||
while( bTreeEof==1
|
||||
&& pNear->bEof==0
|
||||
&& (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
fts3EvalNextRow(pCsr, pExpr, &rc);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
iDocid = pExpr->iDocid;
|
||||
pIter = pPhrase->doclist.pList;
|
||||
}
|
||||
|
||||
bEof = (pPhrase->doclist.nAll==0);
|
||||
assert( bDescDoclist==0 || bDescDoclist==1 );
|
||||
assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
|
||||
|
||||
if( bEof==0 ){
|
||||
if( pCsr->bDesc==bDescDoclist ){
|
||||
int dummy;
|
||||
if( pNear->bEof ){
|
||||
/* This expression is already at EOF. So position it to point to the
|
||||
** last entry in the doclist at pPhrase->doclist.aAll[]. Variable
|
||||
** iDocid is already set for this entry, so all that is required is
|
||||
** to set pIter to point to the first byte of the last position-list
|
||||
** in the doclist.
|
||||
**
|
||||
** It would also be correct to set pIter and iDocid to zero. In
|
||||
** this case, the first call to sqltie3Fts4DoclistPrev() below
|
||||
** would also move the iterator to point to the last entry in the
|
||||
** doclist. However, this is expensive, as to do so it has to
|
||||
** iterate through the entire doclist from start to finish (since
|
||||
** it does not know the docid for the last entry). */
|
||||
pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1];
|
||||
fts3ReversePoslist(pPhrase->doclist.aAll, &pIter);
|
||||
}
|
||||
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
|
||||
sqlite3Fts3DoclistPrev(
|
||||
bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
|
||||
&pIter, &iDocid, &dummy, &bEof
|
||||
);
|
||||
}
|
||||
}else{
|
||||
if( pNear->bEof ){
|
||||
pIter = 0;
|
||||
iDocid = 0;
|
||||
}
|
||||
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
|
||||
sqlite3Fts3DoclistNext(
|
||||
bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
|
||||
&pIter, &iDocid, &bEof
|
||||
);
|
||||
}
|
||||
if( bTreeEof ){
|
||||
while( rc==SQLITE_OK && !pNear->bEof ){
|
||||
fts3EvalNextRow(pCsr, pNear, &rc);
|
||||
}
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
pIter = pPhrase->pOrPoslist;
|
||||
iDocid = pPhrase->iOrDocid;
|
||||
if( pCsr->bDesc==bDescDoclist ){
|
||||
bEof = (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll));
|
||||
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
|
||||
sqlite3Fts3DoclistNext(
|
||||
bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
|
||||
&pIter, &iDocid, &bEof
|
||||
);
|
||||
}
|
||||
}else{
|
||||
bEof = !pPhrase->doclist.nAll || (pIter && pIter<=pPhrase->doclist.aAll);
|
||||
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
|
||||
int dummy;
|
||||
sqlite3Fts3DoclistPrev(
|
||||
bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
|
||||
&pIter, &iDocid, &dummy, &bEof
|
||||
);
|
||||
}
|
||||
}
|
||||
pPhrase->pOrPoslist = pIter;
|
||||
pPhrase->iOrDocid = iDocid;
|
||||
|
||||
if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
|
||||
}
|
||||
@@ -5740,10 +5730,13 @@ int sqlite3Fts3EvalPhrasePoslist(
|
||||
}
|
||||
while( iThis<iCol ){
|
||||
fts3ColumnlistCopy(0, &pIter);
|
||||
if( *pIter==0x00 ) return 0;
|
||||
if( *pIter==0x00 ) return SQLITE_OK;
|
||||
pIter++;
|
||||
pIter += fts3GetVarint32(pIter, &iThis);
|
||||
}
|
||||
if( *pIter==0x00 ){
|
||||
pIter = 0;
|
||||
}
|
||||
|
||||
*ppOut = ((iCol==iThis)?pIter:0);
|
||||
return SQLITE_OK;
|
||||
|
||||
@@ -375,6 +375,11 @@ struct Fts3Phrase {
|
||||
int bIncr; /* True if doclist is loaded incrementally */
|
||||
int iDoclistToken;
|
||||
|
||||
/* Used by sqlite3Fts3EvalPhrasePoslist() if this is a descendent of an
|
||||
** OR condition. */
|
||||
char *pOrPoslist;
|
||||
i64 iOrDocid;
|
||||
|
||||
/* Variables below this point are populated by fts3_expr.c when parsing
|
||||
** a MATCH expression. Everything above is part of the evaluation phase.
|
||||
*/
|
||||
|
||||
@@ -190,7 +190,7 @@ static int getNextToken(
|
||||
/* Set variable i to the maximum number of bytes of input to tokenize. */
|
||||
for(i=0; i<n; i++){
|
||||
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
|
||||
if( z[i]=='*' || z[i]=='"' ) break;
|
||||
if( z[i]=='"' ) break;
|
||||
}
|
||||
|
||||
*pnConsumed = i;
|
||||
|
||||
@@ -183,7 +183,7 @@ static int isVowel(const char *z){
|
||||
** by a consonant.
|
||||
**
|
||||
** In this routine z[] is in reverse order. So we are really looking
|
||||
** for an instance of of a consonant followed by a vowel.
|
||||
** for an instance of a consonant followed by a vowel.
|
||||
*/
|
||||
static int m_gt_0(const char *z){
|
||||
while( isVowel(z) ){ z++; }
|
||||
|
||||
+27
-25
@@ -442,37 +442,39 @@ static int fts3BestSnippet(
|
||||
sIter.nSnippet = nSnippet;
|
||||
sIter.nPhrase = nList;
|
||||
sIter.iCurrent = -1;
|
||||
(void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter);
|
||||
rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter);
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
/* Set the *pmSeen output variable. */
|
||||
for(i=0; i<nList; i++){
|
||||
if( sIter.aPhrase[i].pHead ){
|
||||
*pmSeen |= (u64)1 << i;
|
||||
/* Set the *pmSeen output variable. */
|
||||
for(i=0; i<nList; i++){
|
||||
if( sIter.aPhrase[i].pHead ){
|
||||
*pmSeen |= (u64)1 << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop through all candidate snippets. Store the best snippet in
|
||||
** *pFragment. Store its associated 'score' in iBestScore.
|
||||
*/
|
||||
pFragment->iCol = iCol;
|
||||
while( !fts3SnippetNextCandidate(&sIter) ){
|
||||
int iPos;
|
||||
int iScore;
|
||||
u64 mCover;
|
||||
u64 mHighlight;
|
||||
fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight);
|
||||
assert( iScore>=0 );
|
||||
if( iScore>iBestScore ){
|
||||
pFragment->iPos = iPos;
|
||||
pFragment->hlmask = mHighlight;
|
||||
pFragment->covered = mCover;
|
||||
iBestScore = iScore;
|
||||
/* Loop through all candidate snippets. Store the best snippet in
|
||||
** *pFragment. Store its associated 'score' in iBestScore.
|
||||
*/
|
||||
pFragment->iCol = iCol;
|
||||
while( !fts3SnippetNextCandidate(&sIter) ){
|
||||
int iPos;
|
||||
int iScore;
|
||||
u64 mCover;
|
||||
u64 mHighlite;
|
||||
fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover,&mHighlite);
|
||||
assert( iScore>=0 );
|
||||
if( iScore>iBestScore ){
|
||||
pFragment->iPos = iPos;
|
||||
pFragment->hlmask = mHighlite;
|
||||
pFragment->covered = mCover;
|
||||
iBestScore = iScore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*piScore = iBestScore;
|
||||
}
|
||||
sqlite3_free(sIter.aPhrase);
|
||||
*piScore = iBestScore;
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ static int fts3tokConnectMethod(
|
||||
sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
|
||||
char **pzErr /* OUT: sqlite3_malloc'd error message */
|
||||
){
|
||||
Fts3tokTable *pTab;
|
||||
Fts3tokTable *pTab = 0;
|
||||
const sqlite3_tokenizer_module *pMod = 0;
|
||||
sqlite3_tokenizer *pTok = 0;
|
||||
int rc;
|
||||
|
||||
@@ -3082,8 +3082,8 @@ static int fts3PromoteSegments(
|
||||
|
||||
if( bOk ){
|
||||
int iIdx = 0;
|
||||
sqlite3_stmt *pUpdate1;
|
||||
sqlite3_stmt *pUpdate2;
|
||||
sqlite3_stmt *pUpdate1 = 0;
|
||||
sqlite3_stmt *pUpdate2 = 0;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0);
|
||||
|
||||
+1
-1
@@ -398,7 +398,7 @@ static amatch_avl *amatchAvlInsert(amatch_avl **ppHead, amatch_avl *pNew){
|
||||
*/
|
||||
static void amatchAvlRemove(amatch_avl **ppHead, amatch_avl *pOld){
|
||||
amatch_avl **ppParent;
|
||||
amatch_avl *pBalance;
|
||||
amatch_avl *pBalance = 0;
|
||||
/* assert( amatchAvlSearch(*ppHead, pOld->zKey)==pOld ); */
|
||||
ppParent = amatchAvlFromPtr(pOld, ppHead);
|
||||
if( pOld->pBefore==0 && pOld->pAfter==0 ){
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
** 2014-11-10
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This SQLite extension implements SQL function eval() which runs
|
||||
** SQL statements recursively.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** Structure used to accumulate the output
|
||||
*/
|
||||
struct EvalResult {
|
||||
char *z; /* Accumulated output */
|
||||
const char *zSep; /* Separator */
|
||||
int szSep; /* Size of the separator string */
|
||||
sqlite3_int64 nAlloc; /* Number of bytes allocated for z[] */
|
||||
sqlite3_int64 nUsed; /* Number of bytes of z[] actually used */
|
||||
};
|
||||
|
||||
/*
|
||||
** Callback from sqlite_exec() for the eval() function.
|
||||
*/
|
||||
static int callback(void *pCtx, int argc, char **argv, char **colnames){
|
||||
struct EvalResult *p = (struct EvalResult*)pCtx;
|
||||
int i;
|
||||
for(i=0; i<argc; i++){
|
||||
const char *z = argv[i] ? argv[i] : "";
|
||||
size_t sz = strlen(z);
|
||||
if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
|
||||
char *zNew;
|
||||
p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
|
||||
/* Using sqlite3_realloc64() would be better, but it is a recent
|
||||
** addition and will cause a segfault if loaded by an older version
|
||||
** of SQLite. */
|
||||
zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
|
||||
if( zNew==0 ){
|
||||
sqlite3_free(p->z);
|
||||
memset(p, 0, sizeof(*p));
|
||||
return 1;
|
||||
}
|
||||
p->z = zNew;
|
||||
}
|
||||
if( p->nUsed>0 ){
|
||||
memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
|
||||
p->nUsed += p->szSep;
|
||||
}
|
||||
memcpy(&p->z[p->nUsed], z, sz);
|
||||
p->nUsed += sz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the eval(X) and eval(X,Y) SQL functions.
|
||||
**
|
||||
** Evaluate the SQL text in X. Return the results, using string
|
||||
** Y as the separator. If Y is omitted, use a single space character.
|
||||
*/
|
||||
static void sqlEvalFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zSql;
|
||||
sqlite3 *db;
|
||||
char *zErr = 0;
|
||||
int rc;
|
||||
struct EvalResult x;
|
||||
|
||||
memset(&x, 0, sizeof(x));
|
||||
x.zSep = " ";
|
||||
zSql = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zSql==0 ) return;
|
||||
if( argc>1 ){
|
||||
x.zSep = (const char*)sqlite3_value_text(argv[1]);
|
||||
if( x.zSep==0 ) return;
|
||||
}
|
||||
x.szSep = (int)strlen(x.zSep);
|
||||
db = sqlite3_context_db_handle(context);
|
||||
rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}else if( x.zSep==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
sqlite3_free(x.z);
|
||||
}else{
|
||||
sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_eval_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0,
|
||||
sqlEvalFunc, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0,
|
||||
sqlEvalFunc, 0, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
+2
-1
@@ -342,7 +342,8 @@ static int fuzzerLoadOneRule(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pRule, 0, sizeof(*pRule));
|
||||
pRule->zFrom = &pRule->zTo[nTo+1];
|
||||
pRule->zFrom = pRule->zTo;
|
||||
pRule->zFrom += nTo + 1;
|
||||
pRule->nFrom = nFrom;
|
||||
memcpy(pRule->zFrom, zFrom, nFrom+1);
|
||||
memcpy(pRule->zTo, zTo, nTo+1);
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
** 2014-09-21
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This SQLite extension adds a debug "authorizer" callback to the database
|
||||
** connection. The callback merely writes the authorization request to
|
||||
** standard output and returns SQLITE_OK.
|
||||
**
|
||||
** This extension can be used (for example) in the command-line shell to
|
||||
** trace the operation of the authorizer.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
** Display the authorization request
|
||||
*/
|
||||
static int authCallback(
|
||||
void *pClientData,
|
||||
int op,
|
||||
const char *z1,
|
||||
const char *z2,
|
||||
const char *z3,
|
||||
const char *z4
|
||||
){
|
||||
const char *zOp;
|
||||
char zOpSpace[50];
|
||||
switch( op ){
|
||||
case SQLITE_CREATE_INDEX: zOp = "CREATE_INDEX"; break;
|
||||
case SQLITE_CREATE_TABLE: zOp = "CREATE_TABLE"; break;
|
||||
case SQLITE_CREATE_TEMP_INDEX: zOp = "CREATE_TEMP_INDEX"; break;
|
||||
case SQLITE_CREATE_TEMP_TABLE: zOp = "CREATE_TEMP_TABLE"; break;
|
||||
case SQLITE_CREATE_TEMP_TRIGGER: zOp = "CREATE_TEMP_TRIGGER"; break;
|
||||
case SQLITE_CREATE_TEMP_VIEW: zOp = "CREATE_TEMP_VIEW"; break;
|
||||
case SQLITE_CREATE_TRIGGER: zOp = "CREATE_TRIGGER"; break;
|
||||
case SQLITE_CREATE_VIEW: zOp = "CREATE_VIEW"; break;
|
||||
case SQLITE_DELETE: zOp = "DELETE"; break;
|
||||
case SQLITE_DROP_INDEX: zOp = "DROP_INDEX"; break;
|
||||
case SQLITE_DROP_TABLE: zOp = "DROP_TABLE"; break;
|
||||
case SQLITE_DROP_TEMP_INDEX: zOp = "DROP_TEMP_INDEX"; break;
|
||||
case SQLITE_DROP_TEMP_TABLE: zOp = "DROP_TEMP_TABLE"; break;
|
||||
case SQLITE_DROP_TEMP_TRIGGER: zOp = "DROP_TEMP_TRIGGER"; break;
|
||||
case SQLITE_DROP_TEMP_VIEW: zOp = "DROP_TEMP_VIEW"; break;
|
||||
case SQLITE_DROP_TRIGGER: zOp = "DROP_TRIGGER"; break;
|
||||
case SQLITE_DROP_VIEW: zOp = "DROP_VIEW"; break;
|
||||
case SQLITE_INSERT: zOp = "INSERT"; break;
|
||||
case SQLITE_PRAGMA: zOp = "PRAGMA"; break;
|
||||
case SQLITE_READ: zOp = "READ"; break;
|
||||
case SQLITE_SELECT: zOp = "SELECT"; break;
|
||||
case SQLITE_TRANSACTION: zOp = "TRANSACTION"; break;
|
||||
case SQLITE_UPDATE: zOp = "UPDATE"; break;
|
||||
case SQLITE_ATTACH: zOp = "ATTACH"; break;
|
||||
case SQLITE_DETACH: zOp = "DETACH"; break;
|
||||
case SQLITE_ALTER_TABLE: zOp = "ALTER_TABLE"; break;
|
||||
case SQLITE_REINDEX: zOp = "REINDEX"; break;
|
||||
case SQLITE_ANALYZE: zOp = "ANALYZE"; break;
|
||||
case SQLITE_CREATE_VTABLE: zOp = "CREATE_VTABLE"; break;
|
||||
case SQLITE_DROP_VTABLE: zOp = "DROP_VTABLE"; break;
|
||||
case SQLITE_FUNCTION: zOp = "FUNCTION"; break;
|
||||
case SQLITE_SAVEPOINT: zOp = "SAVEPOINT"; break;
|
||||
case SQLITE_COPY: zOp = "COPY"; break;
|
||||
case SQLITE_RECURSIVE: zOp = "RECURSIVE"; break;
|
||||
|
||||
|
||||
default: {
|
||||
sqlite3_snprintf(sizeof(zOpSpace), zOpSpace, "%d", op);
|
||||
zOp = zOpSpace;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( z1==0 ) z1 = "NULL";
|
||||
if( z2==0 ) z2 = "NULL";
|
||||
if( z3==0 ) z3 = "NULL";
|
||||
if( z4==0 ) z4 = "NULL";
|
||||
printf("AUTH: %s,%s,%s,%s,%s\n", zOp, z1, z2, z3, z4);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_showauth_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_set_authorizer(db, authCallback, 0);
|
||||
return rc;
|
||||
}
|
||||
+17
-7
@@ -356,7 +356,7 @@ static int substituteCost(char cPrev, char cFrom, char cTo){
|
||||
static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
int nA, nB; /* Number of characters in zA[] and zB[] */
|
||||
int xA, xB; /* Loop counters for zA[] and zB[] */
|
||||
char cA, cB; /* Current character of zA and zB */
|
||||
char cA = 0, cB; /* Current character of zA and zB */
|
||||
char cAprev, cBprev; /* Previous character of zA and zB */
|
||||
char cAnext, cBnext; /* Next character in zA and zB */
|
||||
int d; /* North-west cost value */
|
||||
@@ -2736,12 +2736,22 @@ static int spellfix1Update(
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
|
||||
spellfix1DbExec(&rc, db,
|
||||
"INSERT INTO \"%w\".\"%w_vocab\"(rank,langid,word,k1,k2) "
|
||||
"VALUES(%d,%d,%Q,%Q,%Q)",
|
||||
p->zDbName, p->zTableName,
|
||||
iRank, iLang, zWord, zK1, zK2
|
||||
);
|
||||
if( sqlite3_value_type(argv[1])==SQLITE_NULL ){
|
||||
spellfix1DbExec(&rc, db,
|
||||
"INSERT INTO \"%w\".\"%w_vocab\"(rank,langid,word,k1,k2) "
|
||||
"VALUES(%d,%d,%Q,%Q,%Q)",
|
||||
p->zDbName, p->zTableName,
|
||||
iRank, iLang, zWord, zK1, zK2
|
||||
);
|
||||
}else{
|
||||
newRowid = sqlite3_value_int64(argv[1]);
|
||||
spellfix1DbExec(&rc, db,
|
||||
"INSERT INTO \"%w\".\"%w_vocab\"(id,rank,langid,word,k1,k2) "
|
||||
"VALUES(%lld,%d,%d,%Q,%Q,%Q)",
|
||||
p->zDbName, p->zTableName,
|
||||
newRowid, iRank, iLang, zWord, zK1, zK2
|
||||
);
|
||||
}
|
||||
*pRowid = sqlite3_last_insert_rowid(db);
|
||||
}else{
|
||||
rowid = sqlite3_value_int64(argv[0]);
|
||||
|
||||
+8
-8
@@ -369,13 +369,12 @@ static int readInt16(u8 *p){
|
||||
return (p[0]<<8) + p[1];
|
||||
}
|
||||
static void readCoord(u8 *p, RtreeCoord *pCoord){
|
||||
u32 i = (
|
||||
pCoord->u = (
|
||||
(((u32)p[0]) << 24) +
|
||||
(((u32)p[1]) << 16) +
|
||||
(((u32)p[2]) << 8) +
|
||||
(((u32)p[3]) << 0)
|
||||
);
|
||||
*(u32 *)pCoord = i;
|
||||
}
|
||||
static i64 readInt64(u8 *p){
|
||||
return (
|
||||
@@ -404,7 +403,7 @@ static int writeCoord(u8 *p, RtreeCoord *pCoord){
|
||||
u32 i;
|
||||
assert( sizeof(RtreeCoord)==4 );
|
||||
assert( sizeof(u32)==4 );
|
||||
i = *(u32 *)pCoord;
|
||||
i = pCoord->u;
|
||||
p[0] = (i>>24)&0xFF;
|
||||
p[1] = (i>>16)&0xFF;
|
||||
p[2] = (i>> 8)&0xFF;
|
||||
@@ -735,14 +734,13 @@ static void nodeGetCell(
|
||||
RtreeCell *pCell /* OUT: Write the cell contents here */
|
||||
){
|
||||
u8 *pData;
|
||||
u8 *pEnd;
|
||||
RtreeCoord *pCoord;
|
||||
int ii;
|
||||
pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
|
||||
pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell);
|
||||
pEnd = pData + pRtree->nDim*8;
|
||||
pCoord = pCell->aCoord;
|
||||
for(; pData<pEnd; pData+=4, pCoord++){
|
||||
readCoord(pData, pCoord);
|
||||
for(ii=0; ii<pRtree->nDim*2; ii++){
|
||||
readCoord(&pData[ii*4], &pCoord[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1182,7 +1180,7 @@ static RtreeSearchPoint *rtreeEnqueue(
|
||||
pNew = pCur->aPoint + i;
|
||||
pNew->rScore = rScore;
|
||||
pNew->iLevel = iLevel;
|
||||
assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH );
|
||||
assert( iLevel<=RTREE_MAX_DEPTH );
|
||||
while( i>0 ){
|
||||
RtreeSearchPoint *pParent;
|
||||
j = (i-1)/2;
|
||||
@@ -2806,6 +2804,8 @@ static int rtreeUpdate(
|
||||
rtreeReference(pRtree);
|
||||
assert(nData>=1);
|
||||
|
||||
cell.iRowid = 0; /* Used only to suppress a compiler warning */
|
||||
|
||||
/* Constraint handling. A write operation on an r-tree table may return
|
||||
** SQLITE_CONSTRAINT for two reasons:
|
||||
**
|
||||
|
||||
@@ -102,7 +102,7 @@ do_eqp_test rtree6.2.4.2 {
|
||||
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1}
|
||||
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)}
|
||||
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)}
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.5 {
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# 2014-08-21
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file contains tests for the r-tree module.
|
||||
#
|
||||
# This file contains test cases for the ticket
|
||||
# [369d57fb8e5ccdff06f197a37147a88f9de95cda] (2014-08-21)
|
||||
#
|
||||
# The following SQL causes an assertion fault while running
|
||||
# sqlite3_prepare() on the DELETE statement:
|
||||
#
|
||||
# CREATE TABLE t1(x);
|
||||
# CREATE TABLE t2(y);
|
||||
# CREATE VIRTUAL TABLE t3 USING rtree(a,b,c);
|
||||
# CREATE TRIGGER t2del AFTER DELETE ON t2 WHEN (SELECT 1 from t1) BEGIN
|
||||
# DELETE FROM t3 WHERE a=old.y;
|
||||
# END;
|
||||
# DELETE FROM t2 WHERE y=1;
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
|
||||
do_execsql_test rtreeF-1.1 {
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE t2(y);
|
||||
CREATE VIRTUAL TABLE t3 USING rtree(a,b,c);
|
||||
CREATE TRIGGER t2dwl AFTER DELETE ON t2 WHEN (SELECT 1 from t1) BEGIN
|
||||
DELETE FROM t3 WHERE a=old.y;
|
||||
END;
|
||||
|
||||
INSERT INTO t1(x) VALUES(999);
|
||||
INSERT INTO t2(y) VALUES(1),(2),(3),(4),(5);
|
||||
INSERT INTO t3(a,b,c) VALUES(1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7);
|
||||
|
||||
SELECT a FROM t3 ORDER BY a;
|
||||
SELECT '|';
|
||||
SELECT y FROM t2 ORDER BY y;
|
||||
} {1 2 3 4 5 | 1 2 3 4 5}
|
||||
do_execsql_test rtreeF-1.2 {
|
||||
DELETE FROM t2 WHERE y=3;
|
||||
|
||||
SELECT a FROM t3 ORDER BY a;
|
||||
SELECT '|';
|
||||
SELECT y FROM t2 ORDER BY y;
|
||||
} {1 2 4 5 | 1 2 4 5}
|
||||
do_execsql_test rtreeF-1.3 {
|
||||
DELETE FROM t1;
|
||||
DELETE FROM t2 WHERE y=5;
|
||||
|
||||
SELECT a FROM t3 ORDER BY a;
|
||||
SELECT '|';
|
||||
SELECT y FROM t2 ORDER BY y;
|
||||
} {1 2 4 5 | 1 2 4}
|
||||
do_execsql_test rtreeF-1.4 {
|
||||
INSERT INTO t1 DEFAULT VALUES;
|
||||
DELETE FROM t2 WHERE y=5;
|
||||
|
||||
SELECT a FROM t3 ORDER BY a;
|
||||
SELECT '|';
|
||||
SELECT y FROM t2 ORDER BY y;
|
||||
} {1 2 4 5 | 1 2 4}
|
||||
do_execsql_test rtreeF-1.5 {
|
||||
DELETE FROM t2 WHERE y=2;
|
||||
|
||||
SELECT a FROM t3 ORDER BY a;
|
||||
SELECT '|';
|
||||
SELECT y FROM t2 ORDER BY y;
|
||||
} {1 4 5 | 1 4}
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
** 2014-09-08
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file contains the application interface definitions for the
|
||||
** user-authentication extension feature.
|
||||
**
|
||||
** To compile with the user-authentication feature, append this file to
|
||||
** end of an SQLite amalgamation header file ("sqlite3.h"), then add
|
||||
** the SQLITE_USER_AUTHENTICATION compile-time option. See the
|
||||
** user-auth.txt file in the same source directory as this file for
|
||||
** additional information.
|
||||
*/
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
|
||||
/*
|
||||
** If a database contains the SQLITE_USER table, then the
|
||||
** sqlite3_user_authenticate() interface must be invoked with an
|
||||
** appropriate username and password prior to enable read and write
|
||||
** access to the database.
|
||||
**
|
||||
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
|
||||
** combination is incorrect or unknown.
|
||||
**
|
||||
** If the SQLITE_USER table is not present in the database file, then
|
||||
** this interface is a harmless no-op returnning SQLITE_OK.
|
||||
*/
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
** to create a new user. When called on a no-authentication-required
|
||||
** database, this routine converts the database into an authentication-
|
||||
** required database, automatically makes the added user an
|
||||
** administrator, and logs in the current connection as that user.
|
||||
** The sqlite3_user_add() interface only works for the "main" database, not
|
||||
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
|
||||
** non-admin user results in an error.
|
||||
*/
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_change() interface can be used to change a users
|
||||
** login credentials or admin privilege. Any user can change their own
|
||||
** login credentials. Only an admin user can change another users login
|
||||
** credentials or admin privilege setting. No user may change their own
|
||||
** admin privilege setting.
|
||||
*/
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const char *aPW, /* New password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
** to delete a user. The currently logged-in user cannot be deleted,
|
||||
** which guarantees that there is always an admin user and hence that
|
||||
** the database cannot be converted into a no-authentication-required
|
||||
** database.
|
||||
*/
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
);
|
||||
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
@@ -0,0 +1,164 @@
|
||||
Activate the user authentication logic by including the
|
||||
ext/userauth/userauth.c source code file in the build and
|
||||
adding the -DSQLITE_USER_AUTHENTICATION compile-time option.
|
||||
The ext/userauth/sqlite3userauth.h header file is available to
|
||||
applications to define the interface.
|
||||
|
||||
When using the SQLite amalgamation, it is sufficient to append
|
||||
the ext/userauth/userauth.c source file onto the end of the
|
||||
amalgamation.
|
||||
|
||||
The following new APIs are available when user authentication is
|
||||
activated:
|
||||
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
);
|
||||
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
);
|
||||
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const void *aPW, /* Modified password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
);
|
||||
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
);
|
||||
|
||||
With this extension, a database can be marked as requiring authentication.
|
||||
By default a database does not require authentication.
|
||||
|
||||
The sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
|
||||
work as before: they open a new database connection. However, if the
|
||||
database being opened requires authentication, then attempts to read
|
||||
or write from the database will fail with an SQLITE_AUTH error until
|
||||
after sqlite3_user_authenticate() has been called successfully. The
|
||||
sqlite3_user_authenticate() call will return SQLITE_OK if the
|
||||
authentication credentials are accepted and SQLITE_ERROR if not.
|
||||
|
||||
Calling sqlite3_user_authenticate() on a no-authentication-required
|
||||
database connection is a harmless no-op.
|
||||
|
||||
If the database is encrypted, then sqlite3_key_v2() must be called first,
|
||||
with the correct decryption key, prior to invoking sqlite3_user_authenticate().
|
||||
|
||||
To recapitulate: When opening an existing unencrypted authentication-
|
||||
required database, the call sequence is:
|
||||
|
||||
sqlite3_open_v2()
|
||||
sqlite3_user_authenticate();
|
||||
/* Database is now usable */
|
||||
|
||||
To open an existing, encrypted, authentication-required database, the
|
||||
call sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_key_v2();
|
||||
sqlite3_user_authenticate();
|
||||
/* Database is now usable */
|
||||
|
||||
When opening a no-authentication-required database, the database
|
||||
connection is treated as if it was authenticated as an admin user.
|
||||
|
||||
When ATTACH-ing new database files to a connection, each newly attached
|
||||
database that is an authentication-required database is checked using
|
||||
the same username and password as supplied to the main database. If that
|
||||
check fails, then the ATTACH command fails with an SQLITE_AUTH error.
|
||||
|
||||
The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
to create a new user. When called on a no-authentication-required
|
||||
database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
|
||||
converts the database into an authentication-required database and
|
||||
logs in the database connection D as user U with password P,N.
|
||||
To convert a no-authentication-required database into an authentication-
|
||||
required database, the isAdmin parameter must be true. If
|
||||
sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
|
||||
database and A is false, then the call fails with an SQLITE_AUTH error.
|
||||
|
||||
Any call to sqlite3_user_add() by a non-admin user results in an error.
|
||||
|
||||
Hence, to create a new, unencrypted, authentication-required database,
|
||||
the call sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_user_add();
|
||||
|
||||
And to create a new, encrypted, authentication-required database, the call
|
||||
sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_key_v2();
|
||||
sqlite3_user_add();
|
||||
|
||||
The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
to delete a user. The currently logged-in user cannot be deleted,
|
||||
which guarantees that there is always an admin user and hence that
|
||||
the database cannot be converted into a no-authentication-required
|
||||
database.
|
||||
|
||||
The sqlite3_user_change() interface can be used to change a users
|
||||
login credentials or admin privilege. Any user can change their own
|
||||
password. Only an admin user can change another users login
|
||||
credentials or admin privilege setting. No user may change their own
|
||||
admin privilege setting.
|
||||
|
||||
The sqlite3_set_authorizer() callback is modified to take a 7th parameter
|
||||
which is the username of the currently logged in user, or NULL for a
|
||||
no-authentication-required database.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Implementation notes:
|
||||
|
||||
An authentication-required database is identified by the presence of a
|
||||
new table:
|
||||
|
||||
CREATE TABLE sqlite_user(
|
||||
uname TEXT PRIMARY KEY,
|
||||
isAdmin BOOLEAN,
|
||||
pw BLOB
|
||||
) WITHOUT ROWID;
|
||||
|
||||
The sqlite_user table is inaccessible (unreadable and unwriteable) to
|
||||
non-admin users and is read-only for admin users. However, if the same
|
||||
database file is opened by a version of SQLite that omits
|
||||
the -DSQLITE_USER_AUTHENTICATION compile-time option, then the sqlite_user
|
||||
table will be readable by anybody and writeable by anybody if
|
||||
the "PRAGMA writable_schema=ON" statement is run first.
|
||||
|
||||
The sqlite_user.pw field is encoded by a built-in SQL function
|
||||
"sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
|
||||
is the plaintext password supplied to the sqlite3_user_authenticate()
|
||||
interface. The second argument is the sqlite_user.pw value and is supplied
|
||||
so that the function can extract the "salt" used by the password encoder.
|
||||
The result of sqlite_crypt(X,Y) is another blob which is the value that
|
||||
ends up being stored in sqlite_user.pw. To verify credentials X supplied
|
||||
by the sqlite3_user_authenticate() routine, SQLite runs:
|
||||
|
||||
sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
|
||||
|
||||
To compute an appropriate sqlite_user.pw value from a new or modified
|
||||
password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
|
||||
when the second argument is NULL.
|
||||
|
||||
The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
|
||||
which prevents passwords from being revealed by searching the raw database
|
||||
for ASCII text, but is otherwise trivally broken. For better password
|
||||
security, the database should be encrypted using the SQLite Encryption
|
||||
Extension or similar technology. Or, the application can use the
|
||||
sqlite3_create_function() interface to provide an alternative
|
||||
implementation of sqlite_crypt() that computes a stronger password hash,
|
||||
perhaps using a cryptographic hash function like SHA1.
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
** 2014-09-08
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file contains the bulk of the implementation of the
|
||||
** user-authentication extension feature. Some parts of the user-
|
||||
** authentication code are contained within the SQLite core (in the
|
||||
** src/ subdirectory of the main source code tree) but those parts
|
||||
** that could reasonable be separated out are moved into this file.
|
||||
**
|
||||
** To compile with the user-authentication feature, append this file to
|
||||
** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
|
||||
** compile-time option. See the user-auth.txt file in the same source
|
||||
** directory as this file for additional information.
|
||||
*/
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
#ifndef _SQLITEINT_H_
|
||||
# include "sqliteInt.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Prepare an SQL statement for use by the user authentication logic.
|
||||
** Return a pointer to the prepared statement on success. Return a
|
||||
** NULL pointer if there is an error of any kind.
|
||||
*/
|
||||
static sqlite3_stmt *sqlite3UserAuthPrepare(
|
||||
sqlite3 *db,
|
||||
const char *zFormat,
|
||||
...
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
char *zSql;
|
||||
int rc;
|
||||
va_list ap;
|
||||
int savedFlags = db->flags;
|
||||
|
||||
va_start(ap, zFormat);
|
||||
zSql = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zSql==0 ) return 0;
|
||||
db->flags |= SQLITE_WriteSchema;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
db->flags = savedFlags;
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
}
|
||||
return pStmt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if the sqlite_user table exists in database zDb.
|
||||
*/
|
||||
static int userTableExists(sqlite3 *db, const char *zDb){
|
||||
int rc;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
if( db->init.busy==0 ){
|
||||
char *zErr = 0;
|
||||
sqlite3Init(db, &zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
}
|
||||
rc = sqlite3FindTable(db, "sqlite_user", zDb)!=0;
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if database zDb has a "sqlite_user" table and if it does
|
||||
** whether that table can authenticate zUser with nPw,zPw. Write one of
|
||||
** the UAUTH_* user authorization level codes into *peAuth and return a
|
||||
** result code.
|
||||
*/
|
||||
static int userAuthCheckLogin(
|
||||
sqlite3 *db, /* The database connection to check */
|
||||
const char *zDb, /* Name of specific database to check */
|
||||
u8 *peAuth /* OUT: One of UAUTH_* constants */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
|
||||
*peAuth = UAUTH_Unknown;
|
||||
if( !userTableExists(db, "main") ){
|
||||
*peAuth = UAUTH_Admin; /* No sqlite_user table. Everybody is admin. */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( db->auth.zAuthUser==0 ){
|
||||
*peAuth = UAUTH_Fail;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
|
||||
" WHERE uname=?2", zDb);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
|
||||
sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
|
||||
*peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
|
||||
}else{
|
||||
*peAuth = UAUTH_Fail;
|
||||
}
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
int sqlite3UserAuthCheckLogin(
|
||||
sqlite3 *db, /* The database connection to check */
|
||||
const char *zDb, /* Name of specific database to check */
|
||||
u8 *peAuth /* OUT: One of UAUTH_* constants */
|
||||
){
|
||||
int rc;
|
||||
u8 savedAuthLevel;
|
||||
assert( zDb!=0 );
|
||||
assert( peAuth!=0 );
|
||||
savedAuthLevel = db->auth.authLevel;
|
||||
db->auth.authLevel = UAUTH_Admin;
|
||||
rc = userAuthCheckLogin(db, zDb, peAuth);
|
||||
db->auth.authLevel = savedAuthLevel;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the current authLevel is UAUTH_Unknown, the take actions to figure
|
||||
** out what authLevel should be
|
||||
*/
|
||||
void sqlite3UserAuthInit(sqlite3 *db){
|
||||
if( db->auth.authLevel==UAUTH_Unknown ){
|
||||
u8 authLevel = UAUTH_Fail;
|
||||
sqlite3UserAuthCheckLogin(db, "main", &authLevel);
|
||||
db->auth.authLevel = authLevel;
|
||||
if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the sqlite_crypt(X,Y) function.
|
||||
**
|
||||
** If Y is NULL then generate a new hash for password X and return that
|
||||
** hash. If Y is not null, then generate a hash for password X using the
|
||||
** same salt as the previous hash Y and return the new hash.
|
||||
*/
|
||||
void sqlite3CryptFunc(
|
||||
sqlite3_context *context,
|
||||
int NotUsed,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zIn;
|
||||
int nIn, ii;
|
||||
u8 *zOut;
|
||||
char zSalt[8];
|
||||
zIn = sqlite3_value_blob(argv[0]);
|
||||
nIn = sqlite3_value_bytes(argv[0]);
|
||||
if( sqlite3_value_type(argv[1])==SQLITE_BLOB
|
||||
&& sqlite3_value_bytes(argv[1])==nIn+sizeof(zSalt)
|
||||
){
|
||||
memcpy(zSalt, sqlite3_value_blob(argv[1]), sizeof(zSalt));
|
||||
}else{
|
||||
sqlite3_randomness(sizeof(zSalt), zSalt);
|
||||
}
|
||||
zOut = sqlite3_malloc( nIn+sizeof(zSalt) );
|
||||
if( zOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
memcpy(zOut, zSalt, sizeof(zSalt));
|
||||
for(ii=0; ii<nIn; ii++){
|
||||
zOut[ii+sizeof(zSalt)] = zIn[ii]^zSalt[ii&0x7];
|
||||
}
|
||||
sqlite3_result_blob(context, zOut, nIn+sizeof(zSalt), sqlite3_free);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If a database contains the SQLITE_USER table, then the
|
||||
** sqlite3_user_authenticate() interface must be invoked with an
|
||||
** appropriate username and password prior to enable read and write
|
||||
** access to the database.
|
||||
**
|
||||
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
|
||||
** combination is incorrect or unknown.
|
||||
**
|
||||
** If the SQLITE_USER table is not present in the database file, then
|
||||
** this interface is a harmless no-op returnning SQLITE_OK.
|
||||
*/
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *zPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
){
|
||||
int rc;
|
||||
u8 authLevel = UAUTH_Fail;
|
||||
db->auth.authLevel = UAUTH_Unknown;
|
||||
sqlite3_free(db->auth.zAuthUser);
|
||||
sqlite3_free(db->auth.zAuthPW);
|
||||
memset(&db->auth, 0, sizeof(db->auth));
|
||||
db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
|
||||
if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
|
||||
db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
|
||||
if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
|
||||
memcpy(db->auth.zAuthPW,zPW,nPW);
|
||||
db->auth.nAuthPW = nPW;
|
||||
rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
|
||||
db->auth.authLevel = authLevel;
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
if( rc ){
|
||||
return rc; /* OOM error, I/O error, etc. */
|
||||
}
|
||||
if( authLevel<UAUTH_User ){
|
||||
return SQLITE_AUTH; /* Incorrect username and/or password */
|
||||
}
|
||||
return SQLITE_OK; /* Successful login */
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
** to create a new user. When called on a no-authentication-required
|
||||
** database, this routine converts the database into an authentication-
|
||||
** required database, automatically makes the added user an
|
||||
** administrator, and logs in the current connection as that user.
|
||||
** The sqlite3_user_add() interface only works for the "main" database, not
|
||||
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
|
||||
** non-admin user results in an error.
|
||||
*/
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
sqlite3UserAuthInit(db);
|
||||
if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
|
||||
if( !userTableExists(db, "main") ){
|
||||
if( !isAdmin ) return SQLITE_AUTH;
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"CREATE TABLE sqlite_user(\n"
|
||||
" uname TEXT PRIMARY KEY,\n"
|
||||
" isAdmin BOOLEAN,\n"
|
||||
" pw BLOB\n"
|
||||
") WITHOUT ROWID;");
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"INSERT INTO sqlite_user(uname,isAdmin,pw)"
|
||||
" VALUES(%Q,%d,sqlite_crypt(?1,NULL))",
|
||||
zUsername, isAdmin!=0);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc ) return rc;
|
||||
if( db->auth.zAuthUser==0 ){
|
||||
assert( isAdmin!=0 );
|
||||
sqlite3_user_authenticate(db, zUsername, aPW, nPW);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_change() interface can be used to change a users
|
||||
** login credentials or admin privilege. Any user can change their own
|
||||
** login credentials. Only an admin user can change another users login
|
||||
** credentials or admin privilege setting. No user may change their own
|
||||
** admin privilege setting.
|
||||
*/
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const char *aPW, /* Modified password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
u8 authLevel;
|
||||
|
||||
authLevel = db->auth.authLevel;
|
||||
if( authLevel<UAUTH_User ){
|
||||
/* Must be logged in to make a change */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( strcmp(db->auth.zAuthUser, zUsername)!=0 ){
|
||||
if( db->auth.authLevel<UAUTH_Admin ){
|
||||
/* Must be an administrator to change a different user */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
}else if( isAdmin!=(authLevel==UAUTH_Admin) ){
|
||||
/* Cannot change the isAdmin setting for self */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
db->auth.authLevel = UAUTH_Admin;
|
||||
if( !userTableExists(db, "main") ){
|
||||
/* This routine is a no-op if the user to be modified does not exist */
|
||||
}else{
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)"
|
||||
" WHERE uname=%Q", isAdmin, zUsername);
|
||||
if( pStmt==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
}
|
||||
}
|
||||
db->auth.authLevel = authLevel;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
** to delete a user. The currently logged-in user cannot be deleted,
|
||||
** which guarantees that there is always an admin user and hence that
|
||||
** the database cannot be converted into a no-authentication-required
|
||||
** database.
|
||||
*/
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
if( db->auth.authLevel<UAUTH_Admin ){
|
||||
/* Must be an administrator to delete a user */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( strcmp(db->auth.zAuthUser, zUsername)==0 ){
|
||||
/* Cannot delete self */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( !userTableExists(db, "main") ){
|
||||
/* This routine is a no-op if the user to be deleted does not exist */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"DELETE FROM sqlite_user WHERE uname=%Q", zUsername);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_step(pStmt);
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
@@ -46,7 +46,7 @@
|
||||
#
|
||||
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
|
||||
TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3
|
||||
TCCX += -I$(TOP)/ext/async
|
||||
TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth
|
||||
|
||||
# Object files for the SQLite library.
|
||||
#
|
||||
@@ -66,8 +66,8 @@ LIBOBJ+= vdbe.o parse.o \
|
||||
notify.o opcodes.o os.o os_unix.o os_win.o \
|
||||
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
|
||||
random.o resolve.o rowset.o rtree.o select.o status.o \
|
||||
table.o tokenize.o trigger.o \
|
||||
update.o util.o vacuum.o \
|
||||
table.o threads.o tokenize.o trigger.o \
|
||||
update.o userauth.o util.o vacuum.o \
|
||||
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
|
||||
vdbetrace.o wal.o walker.o where.o utf.o vtab.o
|
||||
|
||||
@@ -112,6 +112,7 @@ SRC = \
|
||||
$(TOP)/src/mem3.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/memjournal.c \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.c \
|
||||
$(TOP)/src/mutex.h \
|
||||
$(TOP)/src/mutex_noop.c \
|
||||
@@ -146,6 +147,7 @@ SRC = \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/table.c \
|
||||
$(TOP)/src/tclsqlite.c \
|
||||
$(TOP)/src/threads.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/trigger.c \
|
||||
$(TOP)/src/utf.c \
|
||||
@@ -213,7 +215,9 @@ SRC += \
|
||||
$(TOP)/ext/rtree/sqlite3rtree.h \
|
||||
$(TOP)/ext/rtree/rtree.h \
|
||||
$(TOP)/ext/rtree/rtree.c
|
||||
|
||||
SRC += \
|
||||
$(TOP)/ext/userauth/userauth.c \
|
||||
$(TOP)/ext/userauth/sqlite3userauth.h
|
||||
|
||||
# Generated source code files
|
||||
#
|
||||
@@ -243,6 +247,7 @@ TESTSRC = \
|
||||
$(TOP)/src/test_autoext.c \
|
||||
$(TOP)/src/test_async.c \
|
||||
$(TOP)/src/test_backup.c \
|
||||
$(TOP)/src/test_blob.c \
|
||||
$(TOP)/src/test_btree.c \
|
||||
$(TOP)/src/test_config.c \
|
||||
$(TOP)/src/test_demovfs.c \
|
||||
@@ -277,6 +282,7 @@ TESTSRC = \
|
||||
TESTSRC += \
|
||||
$(TOP)/ext/misc/amatch.c \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
$(TOP)/ext/misc/eval.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/fuzzer.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
@@ -315,6 +321,7 @@ TESTSRC2 = \
|
||||
$(TOP)/src/pcache.c \
|
||||
$(TOP)/src/pcache1.c \
|
||||
$(TOP)/src/select.c \
|
||||
$(TOP)/src/threads.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/utf.c \
|
||||
$(TOP)/src/util.c \
|
||||
@@ -339,6 +346,7 @@ HDR = \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/hwtime.h \
|
||||
keywordhash.h \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.h \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
@@ -375,6 +383,8 @@ EXTHDR += \
|
||||
$(TOP)/ext/rtree/rtree.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/icu/sqliteicu.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/userauth/sqlite3userauth.h
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
# are what get build when you type just "make" with no arguments.
|
||||
@@ -556,6 +566,9 @@ fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
|
||||
rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
|
||||
|
||||
userauth.o: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
|
||||
|
||||
|
||||
# Rules for building test programs and for running tests
|
||||
#
|
||||
@@ -614,9 +627,15 @@ test: testfixture$(EXE) sqlite3$(EXE)
|
||||
# threadtest runs a few thread-safety tests that are implemented in C. This
|
||||
# target is invoked by the releasetest.tcl script.
|
||||
#
|
||||
threadtest3$(EXE): sqlite3.o $(TOP)/test/threadtest3.c $(TOP)/test/tt3_checkpoint.c
|
||||
$(TCCX) -O2 sqlite3.o $(TOP)/test/threadtest3.c \
|
||||
-o threadtest3$(EXE) $(THREADLIB)
|
||||
THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
|
||||
$(TOP)/test/tt3_checkpoint.c \
|
||||
$(TOP)/test/tt3_index.c \
|
||||
$(TOP)/test/tt3_vacuum.c \
|
||||
$(TOP)/test/tt3_stress.c \
|
||||
$(TOP)/test/tt3_lookaside1.c
|
||||
|
||||
threadtest3$(EXE): sqlite3.o $(THREADTEST3_SRC)
|
||||
$(TCCX) $(TOP)/test/threadtest3.c sqlite3.o -o $@ $(THREADLIB)
|
||||
|
||||
threadtest: threadtest3$(EXE)
|
||||
./threadtest3$(EXE)
|
||||
@@ -671,7 +690,7 @@ checksymbols: sqlite3.o
|
||||
|
||||
# Build the amalgamation-autoconf package.
|
||||
#
|
||||
dist: sqlite3.c
|
||||
amalgamation-tarball: sqlite3.c
|
||||
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C Version\s3.8.6
|
||||
D 2014-08-15T11:46:33.931
|
||||
C Version\s3.8.8.3
|
||||
D 2015-02-25T13:29:11.692
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
||||
F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 5b04e657cf08a9ac7fc47d876c5c8be962c47d6b
|
||||
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
|
||||
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
|
||||
F VERSION 1c877615a9db323e3cd301e3d57d853f9d5c4a07
|
||||
F Makefile.msc 4c057774e6138b9023fc16ec05639ddd3329b152
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
|
||||
F VERSION 0de46a30a2d0a7a6a686fd35186fbad0ac06ff71
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 8fc2972d92769cf20ab8e4a73ea901b84d69bf44
|
||||
F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38
|
||||
F autoconf/README.first 47dd53221023b18c836ab00dba6e00bd86132453
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x
|
||||
F autoconf/config.sub 1efb390a8fb4bfafd74783a15a8fb5311c84300e x
|
||||
F autoconf/configure.ac ba3e99ba1a8171d0682b68443517088fc5d6f13a
|
||||
@@ -23,23 +23,23 @@ F autoconf/depcomp 0b26f101e3bc9fd1ff0be1da9fb4a82371142f92 x
|
||||
F autoconf/install-sh 06ee6336e63bb845c8439d777c32eb2eccc4fbf1 x
|
||||
F autoconf/ltmain.sh 7a658a24028f02331c1d2446562758083c5eadd1
|
||||
F autoconf/missing d7c9981a81af13370d4ed152b24c0a82b7028585 x
|
||||
F autoconf/tea/Makefile.in 5c3b0bdfb66c20d55ebff59d1718864461570ca9
|
||||
F autoconf/tea/Makefile.in d55bcc63832caf0309c2ff80358756116618cfca
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
F autoconf/tea/configure.in e0466b881b53f31f5a4a69e7a91ad130902fb359
|
||||
F autoconf/tea/configure.ac 93d43c79e936fb16556e22498177d7e8571efa04
|
||||
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
|
||||
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
|
||||
F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
|
||||
F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00
|
||||
F autoconf/tea/tclconfig/tcl.m4 f035b86539a5ab30689e997a11ae9e7fd2e65570
|
||||
F autoconf/tea/tclconfig/tcl.m4 66ddf0a5d5e4b1d29bff472c0985fd7fa89d0fb5
|
||||
F autoconf/tea/win/makefile.vc f89d0184d0eee5f7e356ea407964dcd139939928
|
||||
F autoconf/tea/win/nmakehlp.c 2070e086f39866b353a482d3a14dedaf26196506
|
||||
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
|
||||
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 513f1e2464c3673bcdb5471b13d98e7eeb6f5ca2 x
|
||||
F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a
|
||||
F configure 444b4cd66ec94631b2b624cf24d01142c9aac0ae x
|
||||
F configure.ac 6a8d145aea6d81f0b90013340780e43ed74fd5f4
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
@@ -78,25 +78,25 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 2f5e925bdb9d6d3e488c5a981af60cad4f9cdfe7
|
||||
F ext/fts3/fts3.c 845f20440dacac6e09f5c7735205609b9a86536b
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 53d4eca1fb23eab00681fb028fb82eb5705c1e21
|
||||
F ext/fts3/fts3Int.h 394858c12a17740f7a1f6bd372c4606d4425a8d1
|
||||
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
|
||||
F ext/fts3/fts3_expr.c 351395fad6fcb16ecfc61db0861008a70101330c
|
||||
F ext/fts3/fts3_expr.c 40123785eaa3ebd4c45c9b23407cc44ac0c49905
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
|
||||
F ext/fts3/fts3_porter.c 7f8b4bf5af7c0f20f73b8e87e14fa9298f52e290
|
||||
F ext/fts3/fts3_snippet.c 51beb5c1498176fd9caccaf1c75b55cb803a985a
|
||||
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
|
||||
F ext/fts3/fts3_snippet.c 55c126e07158b2a705f52dee2cdc57208d3e999a
|
||||
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
|
||||
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
|
||||
F ext/fts3/fts3_tokenize_vtab.c 011170fe9eba5ff062f1a31d3188e00267716706
|
||||
F ext/fts3/fts3_tokenize_vtab.c becc661223db7898b213f9e8a23d75bac02408c9
|
||||
F ext/fts3/fts3_tokenizer.c bbdc731bc91338050675c6d1da9ab82147391e16
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
|
||||
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
|
||||
F ext/fts3/fts3_write.c 8260388626516a7005d06a9dce94f9e55c6c2a41
|
||||
F ext/fts3/fts3_write.c 9b3a32cbecf40a1f41cb08c00df8c066c23c7a25
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 3986531f2fc0ceca0c89c31ec7d0589b6adb19d6
|
||||
@@ -106,30 +106,32 @@ F ext/fts3/unicode/mkunicode.tcl a2567f9d6ad6779879a2e394c120ad8718557e65
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c d415ccf984defeb9df2c0e1afcfaa2f6dc05eacb
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/misc/amatch.c 678056a4bfcd83c4e82dea81d37543cd1d6dbee1
|
||||
F ext/misc/amatch.c 17ba78dc9b33601a40d2a7bc54c748b6f3eb7176
|
||||
F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012
|
||||
F ext/misc/compress.c 76e45655f4046e756064ab10c62e18f2eb846b9f
|
||||
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 136533c53cfce0957f0b48fa11dba27e21c5c01d
|
||||
F ext/misc/fuzzer.c e3e18f47252c151b5553d7e806f38e757d37c4cc
|
||||
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/spellfix.c cb016c2dab951ffd7b819a7bc8a750ebd6c26c0f
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 25810dda37fc904b0772a13efd8ca072fb09e355
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 57bec53e1a677ab74217fe1f20a58c3a47261d6b
|
||||
F ext/rtree/rtree.c 14e6239434d4e3f65d3e90320713f26aa24e167f
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 541bbcab74613907fea08b2ecdcdd5b7aa724cc9
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc
|
||||
F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0
|
||||
F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
|
||||
F ext/rtree/rtree6.test 0cfbdf27ee086bf16a3da2c6f2d5b3d6473cb27e
|
||||
F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
|
||||
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
|
||||
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
|
||||
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34
|
||||
@@ -138,15 +140,19 @@ F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
|
||||
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
|
||||
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
|
||||
F ext/rtree/rtreeE.test 388c1c8602c3ce55c15f03b509e9cf545fb7c41f
|
||||
F ext/rtree/rtreeF.test 66deb9fd1611c7ca2e374adba63debdc2dbb12b4
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
|
||||
F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
|
||||
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 036a65c9042b2f5013baf85c82629d700fe031c4
|
||||
F main.mk e392561ffe17fc4dad945eef852400d5bf2911a0
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
@@ -154,119 +160,121 @@ F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test cce8e306d8596d5a2e497e27112dae1f6e5e3538
|
||||
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
|
||||
F mptest/mptest.c 499a74af4be293b7c1c7c3d40f332b67227dd739
|
||||
F mptest/mptest.c 24c5f72415df2eab7088ef8c9f99f163aed590c8
|
||||
F mptest/multiwrite01.test 499ad0310da8dff8e8f98d2e272fc2a8aa741b2e
|
||||
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
|
||||
F src/analyze.c f98a351908da29f7b44741cfeb9eb20dda648ba0
|
||||
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
||||
F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
|
||||
F src/analyze.c 91540f835163d5369ccbae78e2e6c74d0dd53c1d
|
||||
F src/attach.c 7f6b3fafa2290b407e4a94dcf1afda7ec0fe394b
|
||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c fa057e30794bfd867963b44a3a42710a45c335a1
|
||||
F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a
|
||||
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
|
||||
F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b
|
||||
F src/callback.c fcff28cf0df2403dd2f313bb8d1b8f31f6f3cd64
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
|
||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
|
||||
F src/expr.c f749009cf4a8534efb5e0d5cd7c9fb1fb0f2836c
|
||||
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
|
||||
F src/btree.c 4c098bb6e8678e4596983862abf78f7a0fcb807e
|
||||
F src/btree.h 94277c1d30c0b75705974bcc8b0c05e79c03d474
|
||||
F src/btreeInt.h a3d0ae1d511365e1a2b76ad10960dbe55c286f34
|
||||
F src/build.c f5cfd7b32216f695b995bbc7c1a395f6d451d11f
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463
|
||||
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
|
||||
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
|
||||
F src/delete.c bd1a91ddd247ce13004075251e0b7fe2bf9925ef
|
||||
F src/expr.c 7be80f7dc337329a24df45c2f3bdb2ea3b64c90e
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 8545f3b36da47473e10800ea4fb0810fd4062514
|
||||
F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7
|
||||
F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4
|
||||
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
|
||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||
F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12
|
||||
F src/func.c 6d3c4ebd72aa7923ce9b110a7dc15f9b8c548430
|
||||
F src/global.c 12561d70a1b25f67b21154622bb1723426724f75
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 991e4964e9295da3993e2c0f81c7faf642371848
|
||||
F src/insert.c 5b9243a33726008cc4132897d2be371db12a13be
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c febc2a9e7ad6c1a6191c7b5b9170b325d263f343
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
|
||||
F src/main.c 1cf92c5c6468f2b6ed99b638706781ccc9c60b42
|
||||
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
|
||||
F src/main.c 341fcc5601a8ca84389fa32bcf5a857f65af8dd0
|
||||
F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
|
||||
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c 74670012946c4adc8a6ad84d03acc80959c3e529
|
||||
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
|
||||
F src/mutex.c 84a073c9a23a8d7bdd2ea832522d1730df18812c
|
||||
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
|
||||
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
|
||||
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
|
||||
F src/msvc.h e78002098966e39b2fd9915bd70b7bc3ec8398b7
|
||||
F src/mutex.c 19bf9acba69ca2f367c3761080f8a9f0cf4670a8
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c f3f09fd7a2eb4287cfc799753ffc30380e7b71a1
|
||||
F src/mutex_unix.c 1b10d5413dfc794364a8adf3eb3a192926b43fa3
|
||||
F src/mutex_w32.c c50939b72368f1cfbddb58520372081a50558548
|
||||
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
|
||||
F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e
|
||||
F src/mutex_unix.c 551e2f25f0fa0ee8fd7a43f50fc3d8be00e95dde
|
||||
F src/mutex_w32.c df48fe07562a45c5c927c45b8d5873a27f98bbb0
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
|
||||
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542
|
||||
F src/os_win.c 1c936c7b0659d0eb12b868e2cd710a570e78873e
|
||||
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
|
||||
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
|
||||
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
|
||||
F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e
|
||||
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
|
||||
F src/printf.c af06f66927919730f03479fed6ae9854f73419f4
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697
|
||||
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
||||
F src/select.c ea48e891406ccdf748f3eb02893e056d134a0fea
|
||||
F src/shell.c 75bb7bd2c80bb44861598f322a417c4bafe98fd7
|
||||
F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553
|
||||
F src/os_unix.c aefeaf915aaef9f81aa2645e0d5d06fa1bd83beb
|
||||
F src/os_win.c 91d3d08e33ec0258d180d4c8255492f47d15e007
|
||||
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
|
||||
F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c
|
||||
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
|
||||
F src/parse.y c5d0d964f9ac023e8154cad512e54b0b6058e086
|
||||
F src/pcache.c d210cf90d04365a74f85d21374dded65af67b0cb
|
||||
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
|
||||
F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf
|
||||
F src/pragma.c ba149bbbc90783f84815636c509ced8eac11bbcf
|
||||
F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9
|
||||
F src/printf.c ea82bcb1b83273b4c67177c233c1f78c81fc42f9
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c a4e8fda24c8eab2682a058bdda0d5d68cfe3919c
|
||||
F src/shell.c ee1a80bf2b0e9e0c2b93db8f0f82b841289b2641
|
||||
F src/sqlite.h.in 9dfc99d6533d36d6a549c4f3f01cacc8be956ada
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 641f8fbb65ca2084c8df95b525f6f82c7a1e91ae
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
F src/sqliteInt.h eaf210295b551d4e40e622aec1b2261c0b28f844
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd
|
||||
F src/test1.c 14409a611e9c27c6c522c610bbff5561f05c1558
|
||||
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
|
||||
F src/status.c 81712116e826b0089bb221b018929536b2b5406f
|
||||
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
|
||||
F src/tclsqlite.c 0bbb44543175ef2033d39780a233f98bf354eff9
|
||||
F src/test1.c 093d8b5b54b829dcfebae3181d4406edcc935d90
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
|
||||
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
|
||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
|
||||
F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2
|
||||
F src/test8.c 54ccd7b1df5062f0ecbf50a8f7b618f8b1f13b20
|
||||
F src/test8.c df8dd4c99c1dd2225cb2a6f334299cddc5dcf1f1
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
|
||||
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
|
||||
F src/test_blob.c 1f2e3e25255b731c4fcf15ee7990d06347cb6c09
|
||||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c 42fb068a038c8684741522f551325228b1389e63
|
||||
F src/test_config.c e7b2e1634324d746aa5e1c7e0929470e8be27953
|
||||
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
F src/test_func.c d3013ce36f19ac72a99c73864930fd1fa41832f8
|
||||
F src/test_func.c 14e543ae4d905ee31dc322b2f8d31bfac1769d45
|
||||
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
|
||||
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
|
||||
F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61
|
||||
F src/test_intarray.h 2ece66438cfd177b78d1bfda7a4180cd3a10844d
|
||||
F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64
|
||||
F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
|
||||
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c 1ff5b1243d96124c9a180f3b89424820a1f337f3
|
||||
F src/test_multiplex.c ca90057438b63bf0840ebb84d0ef050624519a76
|
||||
F src/test_malloc.c b9495384e74923aefde8311de974bf9b0f5ba570
|
||||
F src/test_multiplex.c 72c0ad1e97af3d6d19975bbd81813072b40c7290
|
||||
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
|
||||
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
|
||||
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
|
||||
F src/test_osinst.c 3d0340bc31a9f3d8a3547e0272373e80f78dde25
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c 65f6348fec0f2b3020c907247fb47556b214abb9
|
||||
F src/test_quota.c 180813f43683be5725458fc1ff13ac455d8e722d
|
||||
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
|
||||
F src/test_rtree.c fdd8d29ca5165c7857987a2ba263fac5c69e231f
|
||||
F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6
|
||||
F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
|
||||
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
|
||||
F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e
|
||||
F src/test_stat.c 9898687a6c2beca733b0dd6fe19163d987826d31
|
||||
@@ -274,39 +282,40 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
|
||||
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
|
||||
F src/test_vfs.c 8ee7be45fe773a150b4015ef957da960179ee43a
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec
|
||||
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
|
||||
F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059
|
||||
F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05
|
||||
F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6
|
||||
F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
|
||||
F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df
|
||||
F src/vdbeapi.c 24e40422382beb774daab11fe9fe9d37e8a04949
|
||||
F src/vdbeaux.c 25d62ef82cf1be2a1255eacac636fa0d943d8b3d
|
||||
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
|
||||
F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394
|
||||
F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3
|
||||
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
|
||||
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a
|
||||
F src/threads.c 2fb3ea4d70d5acf68b539c2489b4adace61cc01b
|
||||
F src/tokenize.c e00458c9938072b0ea711c850b8dcf4ddcb5fe18
|
||||
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
|
||||
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
|
||||
F src/vacuum.c 9b30ec729337dd012ed88d4c292922c8ef9cf00c
|
||||
F src/vdbe.c ddfc977981cd6324668aa6b114045eb1c677421a
|
||||
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
|
||||
F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78
|
||||
F src/vdbeapi.c 4bc511a46b9839392ae0e90844a71dc96d9dbd71
|
||||
F src/vdbeaux.c f06d38c71d7f533348c09869d69fd1b647042a5b
|
||||
F src/vdbeblob.c 4af4bfb71f6df7778397b4a0ebc1879793276778
|
||||
F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f
|
||||
F src/vdbesort.c 6d64c5448b64851b99931ede980addc3af70d5e2
|
||||
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
|
||||
F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9
|
||||
F src/wal.c 39303f2c9db02a4e422cd8eb2c8760420c6a51fe
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c ab20f9c24a422ee8900831b343c3d1e5e7aca87b
|
||||
F src/whereInt.h 923820bee9726033a501a08d2fc69b9c1ee4feb3
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c 88509f19a64a36e1c22a1dbdac74ee1a62d99dc3
|
||||
F src/whereInt.h d3633e9b592103241b74b0ec76185f3e5b8b62e0
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
|
||||
F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2
|
||||
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
|
||||
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
|
||||
F test/alter4.test d6c011fa0d6227abba762498cafbb607c9609e93
|
||||
F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
@@ -315,11 +324,13 @@ F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
||||
F test/analyze9.test 3ef1b471247308e710a794b6e50a6ab536c5604b
|
||||
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
||||
F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82
|
||||
F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a
|
||||
F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a
|
||||
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
||||
F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
|
||||
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
|
||||
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
@@ -331,20 +342,22 @@ F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
|
||||
F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27
|
||||
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
|
||||
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
|
||||
F test/auth.test 5bdf154eb28c0e4bbc0473f335858c0d96171768
|
||||
F test/auth2.test c3b415b76c033bedb81292118fb7c01f5f10cbcd
|
||||
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
|
||||
F test/auth.test 855233ef26eb3601b6886567ea4e326c72959360
|
||||
F test/auth2.test 264c6af53cad9aba5218c68bbe18036e39007bfa
|
||||
F test/auth3.test 5cfa94ed90c6617c42b7ba4b133fd79678b251c7
|
||||
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
|
||||
F test/autoindex1.test 762ff3f8e25d852aae55c6462ca166a80c0cde61
|
||||
F test/autoindex2.test 60d2fc6f38364308ce73a9beb01b47ded38697de
|
||||
F test/autoindex3.test 8254f689c3241081fad52b7bea18ba53e07e14a2
|
||||
F test/autoindex1.test 6ff78b94f43a59616c06c11c55b12935173506d7
|
||||
F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8
|
||||
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
F test/backcompat.test 19a1f337c68419b020a7481dd272a472c4ad8ef4
|
||||
F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
|
||||
F test/backup.test b79299a536a4c6d919094786595b95be56d02014
|
||||
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
|
||||
F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4
|
||||
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
|
||||
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
|
||||
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
|
||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
@@ -354,6 +367,7 @@ F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
||||
F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
|
||||
F test/bind.test 3c7b320969000c441a70952b0b15938fbb66237c
|
||||
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
|
||||
F test/bitvec.test 75894a880520164d73b1305c1c3f96882615e142
|
||||
@@ -366,14 +380,15 @@ F test/boundary3.tcl 23361e108a125dca9c4080c2feb884fe54d69243
|
||||
F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45
|
||||
F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
|
||||
F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
|
||||
F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
|
||||
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
|
||||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
|
||||
F test/capi3.test 71bcf2fbd36a9732f617766dfd752552c8e491b5
|
||||
F test/capi3.test f0718f4f90d0efdc980119bfbdf1d7f1541ee5ef
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test a21869e4d50d5dbb7e566e328fc0bc7c2efa6a32
|
||||
F test/capi3d.test c84af0c49267f9c3fbf4c1c46aa647646023811e
|
||||
F test/capi3c.test fdc0d67a2cb8e8fc400d5b7735e330161ea057a2
|
||||
F test/capi3d.test a82b6321c50a1cfc848e386fa2c851893606f68c
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
|
||||
@@ -390,7 +405,7 @@ F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868
|
||||
F test/collate8.test df26649cfcbddf109c04122b340301616d3a88f6
|
||||
F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
|
||||
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
|
||||
F test/colmeta.test 087c42997754b8c648819832241daf724f813322
|
||||
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
|
||||
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
|
||||
F test/conflict.test 841bcf7cabbfca39c577eb8411ea8601843b46a8
|
||||
F test/conflict2.test 0d3af4fb534fa1bd020c79960bb56e4d52655f09
|
||||
@@ -412,8 +427,8 @@ F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
|
||||
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
|
||||
F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb
|
||||
F test/corruptI.test 0afbba50bfae006094cc548b4605f521c1179502
|
||||
F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
|
||||
F test/corruptI.test 221ad8b7f0a9ac6b80fc577e73b5ad8cdea31243
|
||||
F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318
|
||||
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
|
||||
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
|
||||
@@ -432,7 +447,7 @@ F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
|
||||
F test/date.test 42973251b9429f2c41b77eb98a7b0b0ba2d3b2c0
|
||||
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
|
||||
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
|
||||
F test/default.test 792c3c70836f1901e2a8cb34fa0880ed71e2c1a9
|
||||
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
|
||||
F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
|
||||
@@ -440,9 +455,14 @@ F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
|
||||
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
|
||||
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
||||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77
|
||||
F test/distinct.test 175d49ee783febaf368192dfe7f5afbc68910230
|
||||
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
||||
F test/e_createtable.test 181653f6f45e3adde73f8686600ce5ad7515466b
|
||||
F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f
|
||||
F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716
|
||||
F test/e_blobopen.test 234f960d90235a9b51ec3ca1e062e8541dd558d8
|
||||
F test/e_blobwrite.test 615b405f29feb2cfb5a1f03dab7933258294fa26
|
||||
F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
|
||||
F test/e_createtable.test c7e67b49e6cf92473c8fb30ab26143e9e2128cf7
|
||||
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
|
||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
|
||||
@@ -454,32 +474,38 @@ F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
|
||||
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
||||
F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
|
||||
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
|
||||
F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
|
||||
F test/e_uri.test a2c92d80093a7efdcfbb11093651cbea87097b6b
|
||||
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
|
||||
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
|
||||
F test/e_wal.test 0967f0b8f1dfda871dc7b9b5574198f1f4f7d69a
|
||||
F test/e_walauto.test ca70cf75c07a6cb1874ced101dd426da76625649
|
||||
F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608
|
||||
F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
|
||||
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
|
||||
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
|
||||
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
|
||||
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
|
||||
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
|
||||
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
|
||||
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
|
||||
F test/expr.test c4b9bf0cc60b26862475e19999fbd2609ca8259c
|
||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
|
||||
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
|
||||
F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b
|
||||
F test/fkey2.test 32ca728bcb854feed72d1406ea375fe423eebff2
|
||||
F test/fkey2.test 1db212cda86b0d3ce72714001f7b6381c321341c
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
F test/fkey5.test 8a1fde4e7721ae00b05b3178888833726ca2df8d
|
||||
F test/fkey5.test 488601fbda8350619b3029487e56830447056fd2
|
||||
F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48
|
||||
F test/fkey7.test e31d0e71a41c1d29349a16448d6c420e2c53a8fc
|
||||
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
|
||||
F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0
|
||||
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
|
||||
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
|
||||
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
|
||||
@@ -554,13 +580,13 @@ F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
||||
F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
|
||||
F test/fts3expr4.test 0713d94ab951ed88a8c3629a4889a48c55c4067c
|
||||
F test/fts3expr4.test e1be1248566f43c252d4404d52914f1fc4bfa065
|
||||
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
|
||||
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
|
||||
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
||||
F test/fts3matchinfo.test ff423e73faab8fc6d7adeefedf74dd8e2b0b14e0
|
||||
F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e
|
||||
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
||||
F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
|
||||
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
|
||||
@@ -572,7 +598,7 @@ F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
|
||||
F test/fts3tok1.test c551043de056b0b1582a54e878991f57bad074bc
|
||||
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
|
||||
F test/fts4aa.test 0c3152322c7f0b548cc942ad763eaba0da87ccca
|
||||
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
|
||||
F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a
|
||||
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
|
||||
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
||||
@@ -594,7 +620,7 @@ F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
|
||||
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
|
||||
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
|
||||
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
|
||||
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
|
||||
F test/fuzz2.test b34fe575aa10292135421ff4bf315de4cde7824a
|
||||
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
@@ -608,7 +634,7 @@ F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
|
||||
F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3
|
||||
F test/in5.test 1de657472fa9ac2924be25c2c959ac5ca1aae554
|
||||
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
|
||||
F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
@@ -623,9 +649,9 @@ F test/index.test 4d990005a67a36984e4f1a5f1bdccea8d08da4ee
|
||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||
F test/index3.test 55a90cff99834305e8141df7afaef39674b57062
|
||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||
F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33
|
||||
F test/index6.test fb370966ac3cd0989053dd5385757b5c3e24ab6a
|
||||
F test/index7.test a3baf9a625bda7fd49471e99aeae04095fbfeecf
|
||||
F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e
|
||||
F test/index6.test c56852451b574ad5b2a1789e566e62e6ab244f42
|
||||
F test/index7.test 917cf1e1c7439bb155abbeabec511b28945e157b
|
||||
F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
@@ -640,7 +666,7 @@ F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
|
||||
F test/intpkey.test 7506090fc08e028712a8bf47e5f54111947e3844
|
||||
F test/io.test 3a7abcef18727cc0f2399e04b0e8903eccae50f8
|
||||
F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d
|
||||
F test/ioerr2.test 9d71166f8466eda510f1af6137bdabaa82b5408d
|
||||
F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26
|
||||
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
|
||||
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
||||
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||
@@ -649,7 +675,7 @@ F test/join.test 52d4d49f86d0cf46926672878c4eaf0da399104a
|
||||
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe
|
||||
F test/join5.test 5df23eba184f159ed9705a954957e765a10c141d
|
||||
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
|
||||
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
|
||||
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
|
||||
@@ -669,14 +695,14 @@ F test/lock.test 87af515b0c4cf928576d0f89946d67d7c265dfb4
|
||||
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
|
||||
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
|
||||
F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
|
||||
F test/lock5.test 5ad6a1f536036ff1be915cfdd41481aeafda3273
|
||||
F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
|
||||
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
|
||||
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
|
||||
F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
|
||||
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
|
||||
F test/main.test 39c4bb8a157f57298ed1659d6df89d9f35aaf2c8
|
||||
F test/main.test 16131264ea0c2b93b95201f0c92958e85f2ba11a
|
||||
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test 4eb83876dfe4915766c179b687b8640437f14abf
|
||||
F test/malloc.test 96939d2d1a6f39667bbebe5bc27c6525f2ab614e
|
||||
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
|
||||
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
|
||||
F test/malloc5.test fafce0aa9157060445cd1a56ad50fc79d82f28c3
|
||||
@@ -684,7 +710,7 @@ F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
|
||||
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
|
||||
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
|
||||
F test/malloc9.test 2307c6ee3703b0a21391f3ea92388b4b73f9105e
|
||||
F test/mallocA.test 1ba0367fb5434e7bc2fa4afcb30b14174d91b160
|
||||
F test/mallocA.test 672cd7dedb63771bade3a6f557f851a4ad161d4a
|
||||
F test/mallocAll.test 98f1be74bc9f49a858bc4f361fc58e26486798be
|
||||
F test/mallocB.test bc475ab850cda896142ab935bbfbc74c24e51ed6
|
||||
F test/mallocC.test 3dffe16532f109293ce1ccecd0c31dca55ef08c4
|
||||
@@ -702,12 +728,12 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test fcb5297b321b562084fc79d64d5a12a1cd2b639b
|
||||
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
|
||||
F test/memsubsys1.test f97cfd0b30e85c2f1ed16d642e7ac58006be84b2
|
||||
F test/memsubsys1.test 690d142525a7d31efb638b0d232e25fac3afeb1a
|
||||
F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9
|
||||
F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
|
||||
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 536a3360470633a177e42fbc19660d146b51daef
|
||||
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
|
||||
F test/misc1.test 1201a037c24f982cc0e956cdaa34fcaf6439c417
|
||||
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
@@ -715,33 +741,37 @@ F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
|
||||
F test/misc8.test fc2754d38892f7dac30c22db3616c2764f117d66
|
||||
F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912
|
||||
F test/mmap1.test 93d167b328255cbe6679fe1e1a23be1b1197d07b
|
||||
F test/mmap1.test 1bfd611b9841eafb44f7d83c0788e146d84a33c9
|
||||
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
|
||||
F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e
|
||||
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
|
||||
F test/multiplex.test efd015ca0b5b4a57dc9535b8feb1273eebeadb60
|
||||
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
|
||||
F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
|
||||
F test/multiplex4.test d3e8a5a522c51cbf3ed1c5b0bd496be02c29d7b1
|
||||
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
|
||||
F test/nolock.test 0540dd96f39b8876e3ffdd8814fad0ea425efeee
|
||||
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
F test/notify2.test ce23eb522c9e1fff6443f96376fe67872202061c
|
||||
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
|
||||
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
|
||||
F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/orderby1.test 12426f99518cde45f34215ca6a0ebc0e9bc5c77a
|
||||
F test/orderby1.test eb246e377612b21a418fbea57047ba8ea88aaa6b
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
||||
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
||||
F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
|
||||
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
|
||||
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
|
||||
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
|
||||
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
|
||||
F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7
|
||||
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
|
||||
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
|
||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
@@ -753,12 +783,13 @@ F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
|
||||
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
|
||||
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
|
||||
F test/permutations.test bc474bafb022cc5014ef3a9c3d5ab61d6d6f587c
|
||||
F test/pragma.test 19d0241a007bcdd77fc2606ec60fc60357e7fc8b
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test f9cc1dd987986c9d4949211c7a4ed55ec9aecba1
|
||||
F test/pragma.test aa16dedfe01c02c8895169012f7dfde9c163f0d5
|
||||
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
|
||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/printf2.test bed79b4c3e5da08ba88ad637c0bf62586843cfb1
|
||||
F test/printf2.test b4acd4bf8734243257f01ddefa17c4fb090acc8a
|
||||
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
@@ -772,21 +803,23 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
|
||||
F test/releasetest.tcl a0df0dfc5e3ee83ade87b9cc96db41b52d590b9e
|
||||
F test/releasetest.tcl 13f401c10dd4fe1a2fb811ae6ed27fd7d1300d3c
|
||||
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
|
||||
F test/rollback.test e9504a009a202c3ed711da2e6879ff60c5a4669c
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
|
||||
F test/rollbackfault.test 6a004f71087cc399296cffbb5429ea6da655ae65
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test b78b30afb9537a73788ca1233a23a32190a3bb1f
|
||||
F test/rowid.test 742b5741584a8a44fd83e856cc2896688401d645
|
||||
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
|
||||
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
|
||||
F test/savepoint.test 6c53f76dffe5df0dd87646efe3e7aa159c36e07b
|
||||
F test/savepoint.test c671fdbd34cd3bfe1518a777526ada595180cf8d
|
||||
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
|
||||
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
|
||||
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
|
||||
F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
|
||||
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
|
||||
F test/savepoint7.test fbf319a7b2dda089ec5be30a424a0e95f121d423
|
||||
F test/savepoint7.test db3db281486c925095f305aad09fe806e5188ff3
|
||||
F test/scanstatus.test 5253c219e331318a437f436268e0e82345700285
|
||||
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
|
||||
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
|
||||
@@ -809,6 +842,7 @@ F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
|
||||
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
|
||||
F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7
|
||||
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
|
||||
F test/selectG.test e8600e379589e85e9fefd2fe4d44a4cdd63f6982
|
||||
F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
|
||||
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
@@ -819,23 +853,31 @@ F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
|
||||
F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
|
||||
F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
|
||||
F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
||||
F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa
|
||||
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
|
||||
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test d60946b5fde4d85fe06db7331dfe89011f564350
|
||||
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
|
||||
F test/shell1.test cdeb849acc2c37aada70d084564b0cc0a2c7df08
|
||||
F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
|
||||
F test/shell5.test 15a419cc1df21c892ed64f5596ae7a501f2816f2
|
||||
F test/shell5.test 81aba4793fa7441b1300daae1aec4f7e4b5741c1
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test 28c7faa41a0d7265040ecb0a0abd90c0904270b2
|
||||
F test/skipscan1.test 2ddfe5d168462170c4487f534e2a99fb006b2076
|
||||
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
|
||||
F test/skipscan5.test d8b9692b702745a0e41c23f9da6beac81df01196
|
||||
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
|
||||
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
|
||||
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
|
||||
F test/sort.test 3f492e5b7be1d3f756728d2ff6edf4f6091e84cb
|
||||
F test/sort2.test 37afbc03f5559f2eb0f18940b55d38dfbb5172ac
|
||||
F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2
|
||||
F test/sort4.test d5e8903194ae551551349ce25dc8d0b40ca2b9c3
|
||||
F test/sort5.test a448240a42b49239edc00f85d6d7ac7a1b261e1f
|
||||
F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66
|
||||
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
|
||||
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
|
||||
F test/speed1p.test b180e98609c7677382cf618c0ec9b69f789033a8
|
||||
@@ -844,27 +886,27 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c d29c8048beb7ea9254191f3fde9414709166a920
|
||||
F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe
|
||||
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
|
||||
F test/speedtest1.c e4e2aa37ff66bad9f414a50a8cb9edfaac65c9e5
|
||||
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
|
||||
F test/sqllimits1.test 9014524e7ab16e2a4976b13397db4c29cc29c6d9
|
||||
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9
|
||||
F test/subquery2.test 91e1e364072aeff431d1f9689b15147e421d88c7
|
||||
F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f
|
||||
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/table.test 2a1d2fa52c531de5915f28023747d9a8c27b6f31
|
||||
F test/table.test 06271d61eb13871490d38168433c1ef3dd82bb2a
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
F test/tester.tcl b4ff83a8b069633f4aca788236d10a7086112a49
|
||||
F test/tester.tcl ed77454e6c7b40eb501db7e79d1c6fbfd3eebbff
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -875,7 +917,8 @@ F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
|
||||
F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
|
||||
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
|
||||
F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9
|
||||
F test/threadtest3.c 0ed13e09690f6204d7455fac3b0e8ece490f6eef
|
||||
F test/threadtest3.c 9ab4b168681c3a6f70f6c833ba08e0d48dd4af9b
|
||||
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
|
||||
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
|
||||
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
|
||||
F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2
|
||||
@@ -917,6 +960,7 @@ F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
|
||||
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
|
||||
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
|
||||
F test/tkt-b75a9ca6b0.test 97cc2d5eeaf82799eb42138c0a1ff64370238ce4
|
||||
F test/tkt-ba7cbfaedc.test e76d88e572e489ee0d64fe4caf4af18b3d1dc688
|
||||
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
|
||||
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
|
||||
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
|
||||
@@ -926,7 +970,7 @@ F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
|
||||
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
|
||||
F test/tkt-f3e5abed55.test d5a0126118142d13e27f6ce9f4c47096e9321c00
|
||||
F test/tkt-f67b41381a.test a23bc124c981662db712167bacd0ed8ad11abac9
|
||||
F test/tkt-f777251dc7a.test af6531446c64bfd268416f07b4df7be7f9c749d2
|
||||
F test/tkt-f777251dc7a.test d1a8fc3eefb7a9e64d19ff24d5c8c94c34a632fb
|
||||
F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
|
||||
F test/tkt-f973c7ac31.test 28ef85c7f015477916795246d8286aeda39d4ead
|
||||
F test/tkt-fa7bf5ec.test 9102dfea58aa371d78969da735f9392c57e2e035
|
||||
@@ -1017,11 +1061,11 @@ F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
|
||||
F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
|
||||
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4
|
||||
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
|
||||
F test/trace.test 73a5508100f7fccfbc3f8018d5f6963ed478eea0
|
||||
F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382
|
||||
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 373ac5183cc56be69f48ae44090e7f672939f732
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
F test/transitive1.test 03f532954f46cdf5608f7766bff0b0c52bf2a7cd
|
||||
F test/trigger1.test dc47573ac79ffe0ee3eecaa517d70d8dacbccd03
|
||||
F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
|
||||
@@ -1031,13 +1075,17 @@ F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
|
||||
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
|
||||
F test/trigger7.test b39e6dee1debe0ff9c2ef66326668f149f07c9c4
|
||||
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
||||
F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
|
||||
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
|
||||
F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
|
||||
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
|
||||
F test/triggerC.test a68980c5955d62ee24be6f97129d824f199f9a4c
|
||||
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
|
||||
F test/triggerE.test 355e9c5cbaed5cd039a60baad1fb2197caeb8e52
|
||||
F test/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af
|
||||
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
|
||||
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
|
||||
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
|
||||
F test/tt3_stress.c c57d804716165811d979d4a719e05baccd79277f
|
||||
F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
|
||||
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
|
||||
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
|
||||
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
|
||||
@@ -1045,8 +1093,9 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
|
||||
F test/unique2.test 41e7f83c6827605991160a31380148a9fc5f1339
|
||||
F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
|
||||
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
|
||||
F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb
|
||||
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
|
||||
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
|
||||
@@ -1055,9 +1104,9 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
|
||||
F test/vtab1.test b631d147b198cfd7903ab5fed028eb2a3d321dc6
|
||||
F test/vtab1.test 1cef14310144718812351a61c5cfb4ba8494a171
|
||||
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
|
||||
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
|
||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
||||
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
|
||||
F test/vtab6.test 5f5380c425e52993560ab4763db4f826d2ba7b09
|
||||
@@ -1077,7 +1126,7 @@ F test/wal.test 885f32b2b390b30b4aa3dbb0e568f8f78d40f5cc
|
||||
F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada
|
||||
F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b
|
||||
F test/wal5.test dba8f5f5de95178bc40521d6edf153b2e2829917
|
||||
F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e
|
||||
F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
|
||||
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
|
||||
@@ -1118,7 +1167,7 @@ F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
||||
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
||||
F test/whereJ.test 35a40a50d0e13aa6b0de7cc5d4b204e5f9f9669f
|
||||
F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
@@ -1129,9 +1178,10 @@ F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
|
||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||
F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
|
||||
F test/without_rowid3.test 1081aabf60a1e1123b7f9a8f6ae19954351843b0
|
||||
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
||||
F test/without_rowid5.test b4a639a367f04d382d20e8f44fc1be4f2d57d107
|
||||
F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862
|
||||
F test/without_rowid6.test deddb78ef539c355bddec00cdfaea6c56efd8b3f
|
||||
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
|
||||
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
|
||||
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
@@ -1145,18 +1195,18 @@ F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c 3ff0fec22f92dfb54e62eeb48772eddffdbeb0d6
|
||||
F tool/lemon.c 1864c4fe4a72b1bb28f1792b60504804fe82c5d2
|
||||
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
|
||||
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
|
||||
F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
|
||||
F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460
|
||||
F tool/mkpragmatab.tcl 07a5124cf2dbafa1b375eefcf8ac4227028b0f8b
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 1712d3d71256ca1f297046619c89e77a4d7c8f6d
|
||||
F tool/mksqlite3c.tcl ba274df71f5e6534b0a913c7c48eabfcbd0934b6
|
||||
F tool/mksqlite3c-noext.tcl 9ef48e1748dce7b844f67e2450ff9dfeb0fb4ab5
|
||||
F tool/mksqlite3c.tcl cfde806851c413db7689b9cb74a4eeb92539c601
|
||||
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
|
||||
F tool/mksqlite3internalh.tcl b6514145a7d5321b47e64e19b8116cc44f973eb1
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
|
||||
@@ -1164,10 +1214,10 @@ F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/showdb.c b9ee6b6c81a094bf33badbf7e9da34cdbc0cce25
|
||||
F tool/showdb.c bd073a78bce714a0e42d92ea474b3eb8cb53be5d
|
||||
F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5
|
||||
F tool/showstat4.c c39279d6bd37cb999b634f0064f6f86ad7af008f
|
||||
F tool/showwal.c 3209120269cdf9380f091459e47b776b4f81dfd3
|
||||
F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
|
||||
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
|
||||
F tool/spaceanal.tcl 8e50b217c56a6a086a1b47eac9d09c5cd65b996f
|
||||
@@ -1181,15 +1231,17 @@ F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
|
||||
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
|
||||
F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
|
||||
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
|
||||
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 3f45b8192dad7fb1f027cbaa694046e3c1b3e278
|
||||
R be8bb3bca247e348b90f7388fee24972
|
||||
P ec27ab0eb3a1ee08a73dda23d2a0f9fb70962745
|
||||
R 7a9d6545656b7d4fe08d198e32a78d62
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.8.6 *
|
||||
T +sym-version-3.8.8.3 *
|
||||
U drh
|
||||
Z 74d8dd4d4aac0ae87245b4bcefd8b172
|
||||
Z 9dbdbd01efd2c5089344e2a1709c163b
|
||||
# Remove this line to create a well-formed manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
9491ba7d738528f168657adb43a198238abde19e
|
||||
9d6c1880fb75660bbabd693175579529785f8a6b
|
||||
|
||||
+1
-1
@@ -1395,7 +1395,7 @@ int main(int argc, char **argv){
|
||||
maybeClose(g.pLog);
|
||||
maybeClose(g.pErrLog);
|
||||
if( iClient==0 ){
|
||||
printf("Summary: %d errors in %d tests\n", g.nError, g.nTest);
|
||||
printf("Summary: %d errors out of %d tests\n", g.nError, g.nTest);
|
||||
}
|
||||
return g.nError>0;
|
||||
}
|
||||
|
||||
+45
-38
@@ -2,7 +2,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH SQLCIPHER 1 "Mon Jan 31 11:14:00 2014"
|
||||
.TH SQLCIPHER 1 "Fri Oct 31 10:41:31 EDT 2014"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
@@ -49,7 +49,7 @@ a table named "memos" and insert a couple of records into that table:
|
||||
$
|
||||
.B sqlcipher mydata.db
|
||||
.br
|
||||
SQLite version 3.8.3
|
||||
SQLite version 3.8.8
|
||||
.br
|
||||
Enter ".help" for instructions
|
||||
.br
|
||||
@@ -107,26 +107,29 @@ the '.help' command. For example:
|
||||
sqlite>
|
||||
.B .help
|
||||
.nf
|
||||
.cc |
|
||||
.backup ?DB? FILE Backup DB (default "main") to FILE
|
||||
.bail ON|OFF Stop after hitting an error. Default OFF
|
||||
.databases List names and files of attached databases
|
||||
.dump ?TABLE? ... Dump the database in an SQL text format
|
||||
.tr %.
|
||||
%backup ?DB? FILE Backup DB (default "main") to FILE
|
||||
%bail on|off Stop after hitting an error. Default OFF
|
||||
%clone NEWDB Clone data into NEWDB from the existing database
|
||||
%databases List names and files of attached databases
|
||||
%dump ?TABLE? ... Dump the database in an SQL text format
|
||||
If TABLE specified, only dump tables matching
|
||||
LIKE pattern TABLE.
|
||||
.echo ON|OFF Turn command echo on or off
|
||||
.exit Exit this program
|
||||
.explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.
|
||||
%echo on|off Turn command echo on or off
|
||||
%eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN
|
||||
%exit Exit this program
|
||||
%explain ?on|off? Turn output mode suitable for EXPLAIN on or off.
|
||||
With no args, it turns EXPLAIN on.
|
||||
.header(s) ON|OFF Turn display of headers on or off
|
||||
.help Show this message
|
||||
.import FILE TABLE Import data from FILE into TABLE
|
||||
.indices ?TABLE? Show names of all indices
|
||||
%fullschema Show schema and the content of sqlite_stat tables
|
||||
%headers on|off Turn display of headers on or off
|
||||
%help Show this message
|
||||
%import FILE TABLE Import data from FILE into TABLE
|
||||
%indices ?TABLE? Show names of all indices
|
||||
If TABLE specified, only show indices for tables
|
||||
matching LIKE pattern TABLE.
|
||||
.load FILE ?ENTRY? Load an extension library
|
||||
.log FILE|off Turn logging on or off. FILE can be stderr/stdout
|
||||
.mode MODE ?TABLE? Set output mode where MODE is one of:
|
||||
%load FILE ?ENTRY? Load an extension library
|
||||
%log FILE|off Turn logging on or off. FILE can be stderr/stdout
|
||||
%mode MODE ?TABLE? Set output mode where MODE is one of:
|
||||
csv Comma-separated values
|
||||
column Left-aligned columns. (See .width)
|
||||
html HTML <table> code
|
||||
@@ -135,31 +138,35 @@ sqlite>
|
||||
list Values delimited by .separator string
|
||||
tabs Tab-separated values
|
||||
tcl TCL list elements
|
||||
.nullvalue STRING Use STRING in place of NULL values
|
||||
.open ?FILENAME? Close existing database and reopen FILENAME
|
||||
.output FILENAME Send output to FILENAME
|
||||
.output stdout Send output to the screen
|
||||
.print STRING... Print literal STRING
|
||||
.prompt MAIN CONTINUE Replace the standard prompts
|
||||
.quit Exit this program
|
||||
.read FILENAME Execute SQL in FILENAME
|
||||
.restore ?DB? FILE Restore content of DB (default "main") from FILE
|
||||
.schema ?TABLE? Show the CREATE statements
|
||||
%nullvalue STRING Use STRING in place of NULL values
|
||||
%once FILENAME Output for the next SQL command only to FILENAME
|
||||
%open ?FILENAME? Close existing database and reopen FILENAME
|
||||
%output ?FILENAME? Send output to FILENAME or stdout
|
||||
%print STRING... Print literal STRING
|
||||
%prompt MAIN CONTINUE Replace the standard prompts
|
||||
%quit Exit this program
|
||||
%read FILENAME Execute SQL in FILENAME
|
||||
%restore ?DB? FILE Restore content of DB (default "main") from FILE
|
||||
%save FILE Write in-memory database into FILE
|
||||
%schema ?TABLE? Show the CREATE statements
|
||||
If TABLE specified, only show tables matching
|
||||
LIKE pattern TABLE.
|
||||
.separator STRING Change separator used by output mode and .import
|
||||
.show Show the current values for various settings
|
||||
.stats ON|OFF Turn stats on or off
|
||||
.tables ?TABLE? List names of tables
|
||||
%separator STRING ?NL? Change separator used by output mode and .import
|
||||
NL is the end-of-line mark for CSV
|
||||
%shell CMD ARGS... Run CMD ARGS... in a system shell
|
||||
%show Show the current values for various settings
|
||||
%stats on|off Turn stats on or off
|
||||
%system CMD ARGS... Run CMD ARGS... in a system shell
|
||||
%tables ?TABLE? List names of tables
|
||||
If TABLE specified, only list tables matching
|
||||
LIKE pattern TABLE.
|
||||
.timeout MS Try opening locked tables for MS milliseconds
|
||||
.trace FILE|off Output each SQL statement as it is run
|
||||
.vfsname ?AUX? Print the name of the VFS stack
|
||||
.width NUM1 NUM2 ... Set column widths for "column" mode
|
||||
.timer ON|OFF Turn the CPU timer measurement on or off
|
||||
%timeout MS Try opening locked tables for MS milliseconds
|
||||
%timer on|off Turn SQL timer on or off
|
||||
%trace FILE|off Output each SQL statement as it is run
|
||||
%vfsname ?AUX? Print the name of the VFS stack
|
||||
%width NUM1 NUM2 ... Set column widths for "column" mode
|
||||
Negative values right-justify
|
||||
sqlite>
|
||||
|cc .
|
||||
.sp
|
||||
.fi
|
||||
.SH OPTIONS
|
||||
@@ -269,7 +276,7 @@ o If the -init option is present, the specified file is processed.
|
||||
o All other command line options are processed.
|
||||
|
||||
.SH SEE ALSO
|
||||
http://www.sqlcipher.net/
|
||||
https://www.zetetic.net/sqlcipher
|
||||
.br
|
||||
The sqlite3-doc package.
|
||||
.SH AUTHOR
|
||||
|
||||
+2
-2
@@ -174,8 +174,8 @@ static void renameTriggerFunc(
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
|
||||
/* The principle used to locate the table name in the CREATE TRIGGER
|
||||
** statement is that the table name is the first token that is immediatedly
|
||||
** preceded by either TK_ON or TK_DOT and immediatedly followed by one
|
||||
** statement is that the table name is the first token that is immediately
|
||||
** preceded by either TK_ON or TK_DOT and immediately followed by one
|
||||
** of TK_WHEN, TK_BEGIN or TK_FOR.
|
||||
*/
|
||||
if( zSql ){
|
||||
|
||||
+79
-42
@@ -35,7 +35,7 @@
|
||||
** not possible to enable both STAT3 and STAT4 at the same time. If they
|
||||
** are both enabled, then STAT4 takes precedence.
|
||||
**
|
||||
** For most applications, sqlite_stat1 provides all the statisics required
|
||||
** For most applications, sqlite_stat1 provides all the statistics required
|
||||
** for the query planner to make good choices.
|
||||
**
|
||||
** Format of sqlite_stat1:
|
||||
@@ -387,8 +387,9 @@ static void stat4Destructor(void *pOld){
|
||||
** original WITHOUT ROWID table as N==K as a special case.
|
||||
**
|
||||
** This routine allocates the Stat4Accum object in heap memory. The return
|
||||
** value is a pointer to the the Stat4Accum object encoded as a blob (i.e.
|
||||
** the size of the blob is sizeof(void*) bytes).
|
||||
** value is a pointer to the Stat4Accum object. The datatype of the
|
||||
** return value is BLOB, but it is really just a pointer to the Stat4Accum
|
||||
** object.
|
||||
*/
|
||||
static void statInit(
|
||||
sqlite3_context *context,
|
||||
@@ -447,7 +448,7 @@ static void statInit(
|
||||
p->mxSample = mxSample;
|
||||
p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
|
||||
p->current.anLt = &p->current.anEq[nColUp];
|
||||
p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565;
|
||||
p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
|
||||
|
||||
/* Set up the Stat4Accum.a[] and aBest[] arrays */
|
||||
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
|
||||
@@ -466,8 +467,11 @@ static void statInit(
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return a pointer to the allocated object to the caller */
|
||||
sqlite3_result_blob(context, p, sizeof(p), stat4Destructor);
|
||||
/* Return a pointer to the allocated object to the caller. Note that
|
||||
** only the pointer (the 2nd parameter) matters. The size of the object
|
||||
** (given by the 3rd parameter) is never used and can be any positive
|
||||
** value. */
|
||||
sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor);
|
||||
}
|
||||
static const FuncDef statInitFuncdef = {
|
||||
2+IsStat34, /* nArg */
|
||||
@@ -793,7 +797,7 @@ static const FuncDef statPushFuncdef = {
|
||||
** Implementation of the stat_get(P,J) SQL function. This routine is
|
||||
** used to query statistical information that has been gathered into
|
||||
** the Stat4Accum object by prior calls to stat_push(). The P parameter
|
||||
** is a BLOB which is decoded into a pointer to the Stat4Accum objects.
|
||||
** has type BLOB but it is really just a pointer to the Stat4Accum object.
|
||||
** The content to returned is determined by the parameter J
|
||||
** which is one of the STAT_GET_xxxx values defined above.
|
||||
**
|
||||
@@ -1197,7 +1201,8 @@ static void analyzeOneTable(
|
||||
|
||||
/* Add the entry to the stat1 table. */
|
||||
callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
|
||||
assert( "BBB"[0]==SQLITE_AFF_TEXT );
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
@@ -1260,7 +1265,8 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1);
|
||||
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
|
||||
assert( "BBB"[0]==SQLITE_AFF_TEXT );
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
@@ -1431,7 +1437,7 @@ static void decodeIntArray(
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
if( z==0 ) z = "";
|
||||
#else
|
||||
if( NEVER(z==0) ) z = "";
|
||||
assert( z!=0 );
|
||||
#endif
|
||||
for(i=0; *z && i<nOut; i++){
|
||||
v = 0;
|
||||
@@ -1440,36 +1446,39 @@ static void decodeIntArray(
|
||||
z++;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
if( aOut ){
|
||||
aOut[i] = v;
|
||||
}else
|
||||
if( aOut ) aOut[i] = v;
|
||||
if( aLog ) aLog[i] = sqlite3LogEst(v);
|
||||
#else
|
||||
assert( aOut==0 );
|
||||
UNUSED_PARAMETER(aOut);
|
||||
assert( aLog!=0 );
|
||||
aLog[i] = sqlite3LogEst(v);
|
||||
#endif
|
||||
{
|
||||
aLog[i] = sqlite3LogEst(v);
|
||||
}
|
||||
if( *z==' ' ) z++;
|
||||
}
|
||||
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
assert( pIndex!=0 );
|
||||
assert( pIndex!=0 ); {
|
||||
#else
|
||||
if( pIndex )
|
||||
if( pIndex ){
|
||||
#endif
|
||||
while( z[0] ){
|
||||
if( sqlite3_strglob("unordered*", z)==0 ){
|
||||
pIndex->bUnordered = 1;
|
||||
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
|
||||
pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
|
||||
}
|
||||
pIndex->bUnordered = 0;
|
||||
pIndex->noSkipScan = 0;
|
||||
while( z[0] ){
|
||||
if( sqlite3_strglob("unordered*", z)==0 ){
|
||||
pIndex->bUnordered = 1;
|
||||
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
|
||||
pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
|
||||
}else if( sqlite3_strglob("noskipscan*", z)==0 ){
|
||||
pIndex->noSkipScan = 1;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_COSTMULT
|
||||
else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
|
||||
pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
|
||||
}
|
||||
else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
|
||||
pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
|
||||
}
|
||||
#endif
|
||||
while( z[0]!=0 && z[0]!=' ' ) z++;
|
||||
while( z[0]==' ' ) z++;
|
||||
while( z[0]!=0 && z[0]!=' ' ) z++;
|
||||
while( z[0]==' ' ) z++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1510,8 +1519,17 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
||||
z = argv[2];
|
||||
|
||||
if( pIndex ){
|
||||
int nCol = pIndex->nKeyCol+1;
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(
|
||||
sizeof(tRowcnt) * nCol
|
||||
);
|
||||
if( aiRowEst==0 ) pInfo->db->mallocFailed = 1;
|
||||
#else
|
||||
tRowcnt * const aiRowEst = 0;
|
||||
#endif
|
||||
pIndex->bUnordered = 0;
|
||||
decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
|
||||
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
|
||||
if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
|
||||
}else{
|
||||
Index fakeIdx;
|
||||
@@ -1570,25 +1588,39 @@ static void initAvgEq(Index *pIdx){
|
||||
pIdx->aAvgEq[nCol] = 1;
|
||||
}
|
||||
for(iCol=0; iCol<nCol; iCol++){
|
||||
int nSample = pIdx->nSample;
|
||||
int i; /* Used to iterate through samples */
|
||||
tRowcnt sumEq = 0; /* Sum of the nEq values */
|
||||
tRowcnt nSum = 0; /* Number of terms contributing to sumEq */
|
||||
tRowcnt avgEq = 0;
|
||||
tRowcnt nDLt = pFinal->anDLt[iCol];
|
||||
tRowcnt nRow; /* Number of rows in index */
|
||||
i64 nSum100 = 0; /* Number of terms contributing to sumEq */
|
||||
i64 nDist100; /* Number of distinct values in index */
|
||||
|
||||
if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){
|
||||
nRow = pFinal->anLt[iCol];
|
||||
nDist100 = (i64)100 * pFinal->anDLt[iCol];
|
||||
nSample--;
|
||||
}else{
|
||||
nRow = pIdx->aiRowEst[0];
|
||||
nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1];
|
||||
}
|
||||
pIdx->nRowEst0 = nRow;
|
||||
|
||||
/* Set nSum to the number of distinct (iCol+1) field prefixes that
|
||||
** occur in the stat4 table for this index before pFinal. Set
|
||||
** sumEq to the sum of the nEq values for column iCol for the same
|
||||
** set (adding the value only once where there exist dupicate
|
||||
** prefixes). */
|
||||
for(i=0; i<(pIdx->nSample-1); i++){
|
||||
if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){
|
||||
** occur in the stat4 table for this index. Set sumEq to the sum of
|
||||
** the nEq values for column iCol for the same set (adding the value
|
||||
** only once where there exist duplicate prefixes). */
|
||||
for(i=0; i<nSample; i++){
|
||||
if( i==(pIdx->nSample-1)
|
||||
|| aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol]
|
||||
){
|
||||
sumEq += aSample[i].anEq[iCol];
|
||||
nSum++;
|
||||
nSum100 += 100;
|
||||
}
|
||||
}
|
||||
if( nDLt>nSum ){
|
||||
avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum);
|
||||
|
||||
if( nDist100>nSum100 ){
|
||||
avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100);
|
||||
}
|
||||
if( avgEq==0 ) avgEq = 1;
|
||||
pIdx->aAvgEq[iCol] = avgEq;
|
||||
@@ -1834,12 +1866,17 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
||||
|
||||
/* Load the statistics from the sqlite_stat4 table. */
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){
|
||||
int lookasideEnabled = db->lookaside.bEnabled;
|
||||
db->lookaside.bEnabled = 0;
|
||||
rc = loadStat4(db, sInfo.zDatabase);
|
||||
db->lookaside.bEnabled = lookasideEnabled;
|
||||
}
|
||||
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
||||
Index *pIdx = sqliteHashData(i);
|
||||
sqlite3_free(pIdx->aiRowEst);
|
||||
pIdx->aiRowEst = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
|
||||
@@ -150,6 +150,7 @@ static void attachFunc(
|
||||
"attached databases must use the same text encoding as main database");
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sqlite3BtreeEnter(aNew->pBt);
|
||||
pPager = sqlite3BtreePager(aNew->pBt);
|
||||
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
|
||||
sqlite3BtreeSecureDelete(aNew->pBt,
|
||||
@@ -157,6 +158,7 @@ static void attachFunc(
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
|
||||
#endif
|
||||
sqlite3BtreeLeave(aNew->pBt);
|
||||
}
|
||||
aNew->safety_level = 3;
|
||||
aNew->zName = sqlite3DbStrDup(db, zName);
|
||||
@@ -207,6 +209,15 @@ static void attachFunc(
|
||||
rc = sqlite3Init(db, &zErrDyn);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
}
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
if( rc==SQLITE_OK ){
|
||||
u8 newAuth = 0;
|
||||
rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
|
||||
if( newAuth<db->auth.authLevel ){
|
||||
rc = SQLITE_AUTH_USER;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( rc ){
|
||||
int iDb = db->nDb - 1;
|
||||
assert( iDb>=2 );
|
||||
|
||||
+14
-3
@@ -72,8 +72,11 @@ int sqlite3_set_authorizer(
|
||||
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
|
||||
void *pArg
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->xAuth = xAuth;
|
||||
db->xAuth = (sqlite3_xauth)xAuth;
|
||||
db->pAuthArg = pArg;
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
@@ -108,7 +111,11 @@ int sqlite3AuthReadCol(
|
||||
char *zDb = db->aDb[iDb].zName; /* Name of attached database */
|
||||
int rc; /* Auth callback return code */
|
||||
|
||||
rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
|
||||
rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
,db->auth.zAuthUser
|
||||
#endif
|
||||
);
|
||||
if( rc==SQLITE_DENY ){
|
||||
if( db->nDb>2 || iDb!=0 ){
|
||||
sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
|
||||
@@ -208,7 +215,11 @@ int sqlite3AuthCheck(
|
||||
if( db->xAuth==0 ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
|
||||
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
,db->auth.zAuthUser
|
||||
#endif
|
||||
);
|
||||
if( rc==SQLITE_DENY ){
|
||||
sqlite3ErrorMsg(pParse, "not authorized");
|
||||
pParse->rc = SQLITE_AUTH;
|
||||
|
||||
+51
-12
@@ -87,12 +87,12 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
int rc = 0;
|
||||
pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse));
|
||||
if( pParse==0 ){
|
||||
sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory");
|
||||
sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory");
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
pParse->db = pDb;
|
||||
if( sqlite3OpenTempDatabase(pParse) ){
|
||||
sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
|
||||
sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
|
||||
@@ -105,7 +105,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
}
|
||||
|
||||
if( i<0 ){
|
||||
sqlite3Error(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb);
|
||||
sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,20 @@ static int setDestPgsz(sqlite3_backup *p){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check that there is no open read-transaction on the b-tree passed as the
|
||||
** second argument. If there is not, return SQLITE_OK. Otherwise, if there
|
||||
** is an open read-transaction, return SQLITE_ERROR and leave an error
|
||||
** message in database handle db.
|
||||
*/
|
||||
static int checkReadTransaction(sqlite3 *db, Btree *p){
|
||||
if( sqlite3BtreeIsInReadTrans(p) ){
|
||||
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create an sqlite3_backup process to copy the contents of zSrcDb from
|
||||
** connection handle pSrcDb to zDestDb in pDestDb. If successful, return
|
||||
@@ -138,6 +152,13 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
){
|
||||
sqlite3_backup *p; /* Value to return */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Lock the source database handle. The destination database
|
||||
** handle is not locked in this routine, but it is locked in
|
||||
** sqlite3_backup_step(). The user is required to ensure that no
|
||||
@@ -150,7 +171,7 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
sqlite3_mutex_enter(pDestDb->mutex);
|
||||
|
||||
if( pSrcDb==pDestDb ){
|
||||
sqlite3Error(
|
||||
sqlite3ErrorWithMsg(
|
||||
pDestDb, SQLITE_ERROR, "source and destination must be distinct"
|
||||
);
|
||||
p = 0;
|
||||
@@ -161,7 +182,7 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
** sqlite3_backup_finish(). */
|
||||
p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
|
||||
if( !p ){
|
||||
sqlite3Error(pDestDb, SQLITE_NOMEM, 0);
|
||||
sqlite3Error(pDestDb, SQLITE_NOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,12 +195,15 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
p->iNext = 1;
|
||||
p->isAttached = 0;
|
||||
|
||||
if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM ){
|
||||
if( 0==p->pSrc || 0==p->pDest
|
||||
|| setDestPgsz(p)==SQLITE_NOMEM
|
||||
|| checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
|
||||
){
|
||||
/* One (or both) of the named databases did not exist or an OOM
|
||||
** error was hit. The error has already been written into the
|
||||
** pDestDb handle. All that is left to do here is free the
|
||||
** sqlite3_backup structure.
|
||||
*/
|
||||
** error was hit. Or there is a transaction open on the destination
|
||||
** database. The error has already been written into the pDestDb
|
||||
** handle. All that is left to do here is free the sqlite3_backup
|
||||
** structure. */
|
||||
sqlite3_free(p);
|
||||
p = 0;
|
||||
}
|
||||
@@ -334,6 +358,9 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
int pgszSrc = 0; /* Source page size */
|
||||
int pgszDest = 0; /* Destination page size */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(p->pSrcDb->mutex);
|
||||
sqlite3BtreeEnter(p->pSrc);
|
||||
if( p->pDestDb ){
|
||||
@@ -597,12 +624,12 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
}
|
||||
|
||||
/* If a transaction is still open on the Btree, roll it back. */
|
||||
sqlite3BtreeRollback(p->pDest, SQLITE_OK);
|
||||
sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
|
||||
|
||||
/* Set the error code of the destination database handle. */
|
||||
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
|
||||
if( p->pDestDb ){
|
||||
sqlite3Error(p->pDestDb, rc, 0);
|
||||
sqlite3Error(p->pDestDb, rc);
|
||||
|
||||
/* Exit the mutexes and free the backup context structure. */
|
||||
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
|
||||
@@ -623,6 +650,12 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
** call to sqlite3_backup_step().
|
||||
*/
|
||||
int sqlite3_backup_remaining(sqlite3_backup *p){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return p->nRemaining;
|
||||
}
|
||||
|
||||
@@ -631,6 +664,12 @@ int sqlite3_backup_remaining(sqlite3_backup *p){
|
||||
** recent call to sqlite3_backup_step().
|
||||
*/
|
||||
int sqlite3_backup_pagecount(sqlite3_backup *p){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return p->nPagecount;
|
||||
}
|
||||
|
||||
|
||||
+17
-4
@@ -38,7 +38,7 @@ static void lockBtreeMutex(Btree *p){
|
||||
** Release the BtShared mutex associated with B-Tree handle p and
|
||||
** clear the p->locked boolean.
|
||||
*/
|
||||
static void unlockBtreeMutex(Btree *p){
|
||||
static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){
|
||||
BtShared *pBt = p->pBt;
|
||||
assert( p->locked==1 );
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
@@ -49,6 +49,9 @@ static void unlockBtreeMutex(Btree *p){
|
||||
p->locked = 0;
|
||||
}
|
||||
|
||||
/* Forward reference */
|
||||
static void SQLITE_NOINLINE btreeLockCarefully(Btree *p);
|
||||
|
||||
/*
|
||||
** Enter a mutex on the given BTree object.
|
||||
**
|
||||
@@ -66,8 +69,6 @@ static void unlockBtreeMutex(Btree *p){
|
||||
** subsequent Btrees that desire a lock.
|
||||
*/
|
||||
void sqlite3BtreeEnter(Btree *p){
|
||||
Btree *pLater;
|
||||
|
||||
/* Some basic sanity checking on the Btree. The list of Btrees
|
||||
** connected by pNext and pPrev should be in sorted order by
|
||||
** Btree.pBt value. All elements of the list should belong to
|
||||
@@ -92,9 +93,20 @@ void sqlite3BtreeEnter(Btree *p){
|
||||
if( !p->sharable ) return;
|
||||
p->wantToLock++;
|
||||
if( p->locked ) return;
|
||||
btreeLockCarefully(p);
|
||||
}
|
||||
|
||||
/* This is a helper function for sqlite3BtreeLock(). By moving
|
||||
** complex, but seldom used logic, out of sqlite3BtreeLock() and
|
||||
** into this routine, we avoid unnecessary stack pointer changes
|
||||
** and thus help the sqlite3BtreeLock() routine to run much faster
|
||||
** in the common case.
|
||||
*/
|
||||
static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){
|
||||
Btree *pLater;
|
||||
|
||||
/* In most cases, we should be able to acquire the lock we
|
||||
** want without having to go throught the ascending lock
|
||||
** want without having to go through the ascending lock
|
||||
** procedure that follows. Just be sure not to block.
|
||||
*/
|
||||
if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
|
||||
@@ -124,6 +136,7 @@ void sqlite3BtreeEnter(Btree *p){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Exit the recursive mutex on a Btree.
|
||||
*/
|
||||
|
||||
+1341
-722
File diff suppressed because it is too large
Load Diff
+12
-4
@@ -19,7 +19,7 @@
|
||||
/* TODO: This definition is just included so other modules compile. It
|
||||
** needs to be revisited.
|
||||
*/
|
||||
#define SQLITE_N_BTREE_META 10
|
||||
#define SQLITE_N_BTREE_META 16
|
||||
|
||||
/*
|
||||
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
|
||||
@@ -83,7 +83,7 @@ int sqlite3BtreeBeginTrans(Btree*,int);
|
||||
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
|
||||
int sqlite3BtreeCommitPhaseTwo(Btree*, int);
|
||||
int sqlite3BtreeCommit(Btree*);
|
||||
int sqlite3BtreeRollback(Btree*,int);
|
||||
int sqlite3BtreeRollback(Btree*,int,int);
|
||||
int sqlite3BtreeBeginStmt(Btree*,int);
|
||||
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
|
||||
int sqlite3BtreeIsInTrans(Btree*);
|
||||
@@ -116,7 +116,7 @@ int sqlite3BtreeIncrVacuum(Btree *);
|
||||
int sqlite3BtreeDropTable(Btree*, int, int*);
|
||||
int sqlite3BtreeClearTable(Btree*, int, int*);
|
||||
int sqlite3BtreeClearTableOfCursor(BtCursor*);
|
||||
void sqlite3BtreeTripAllCursors(Btree*, int);
|
||||
int sqlite3BtreeTripAllCursors(Btree*, int, int);
|
||||
|
||||
void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
|
||||
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
||||
@@ -134,6 +134,11 @@ int sqlite3BtreeNewDb(Btree *p);
|
||||
** For example, the free-page-count field is located at byte offset 36 of
|
||||
** the database file header. The incr-vacuum-flag field is located at
|
||||
** byte offset 64 (== 36+4*7).
|
||||
**
|
||||
** The BTREE_DATA_VERSION value is not really a value stored in the header.
|
||||
** It is a read-only number computed by the pager. But we merge it with
|
||||
** the header value access routines since its access pattern is the same.
|
||||
** Call it a "virtual meta value".
|
||||
*/
|
||||
#define BTREE_FREE_PAGE_COUNT 0
|
||||
#define BTREE_SCHEMA_VERSION 1
|
||||
@@ -144,6 +149,7 @@ int sqlite3BtreeNewDb(Btree *p);
|
||||
#define BTREE_USER_VERSION 6
|
||||
#define BTREE_INCR_VACUUM 7
|
||||
#define BTREE_APPLICATION_ID 8
|
||||
#define BTREE_DATA_VERSION 15 /* A virtual meta-value */
|
||||
|
||||
/*
|
||||
** Values that may be OR'd together to form the second argument of an
|
||||
@@ -169,7 +175,8 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
int bias,
|
||||
int *pRes
|
||||
);
|
||||
int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
|
||||
int sqlite3BtreeCursorHasMoved(BtCursor*);
|
||||
int sqlite3BtreeCursorRestore(BtCursor*, int*);
|
||||
int sqlite3BtreeDelete(BtCursor*);
|
||||
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
|
||||
const void *pData, int nData,
|
||||
@@ -195,6 +202,7 @@ void sqlite3BtreeClearCursor(BtCursor *);
|
||||
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
|
||||
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
|
||||
int sqlite3BtreeIsReadonly(Btree *pBt);
|
||||
int sqlite3HeaderSizeBtree(void);
|
||||
|
||||
#ifndef NDEBUG
|
||||
int sqlite3BtreeCursorIsValid(BtCursor*);
|
||||
|
||||
+23
-15
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** This file implements an external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
**
|
||||
** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
|
||||
@@ -135,7 +135,7 @@
|
||||
**
|
||||
** The flags define the format of this btree page. The leaf flag means that
|
||||
** this page has no children. The zerodata flag means that this page carries
|
||||
** only keys and no data. The intkey flag means that the key is a integer
|
||||
** only keys and no data. The intkey flag means that the key is an integer
|
||||
** which is stored in the key size entry of the cell header rather than in
|
||||
** the payload area.
|
||||
**
|
||||
@@ -273,9 +273,10 @@ typedef struct BtLock BtLock;
|
||||
struct MemPage {
|
||||
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
|
||||
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
|
||||
u8 intKey; /* True if intkey flag is set */
|
||||
u8 leaf; /* True if leaf flag is set */
|
||||
u8 hasData; /* True if this page stores data */
|
||||
u8 intKey; /* True if table b-trees. False for index b-trees */
|
||||
u8 intKeyLeaf; /* True if the leaf of an intKey table */
|
||||
u8 noPayload; /* True if internal intKey page (thus w/o data) */
|
||||
u8 leaf; /* True if a leaf page */
|
||||
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
|
||||
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
|
||||
u8 max1bytePayload; /* min(maxLocal,127) */
|
||||
@@ -350,6 +351,7 @@ struct Btree {
|
||||
u8 locked; /* True if db currently has pBt locked */
|
||||
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
|
||||
int nBackup; /* Number of backup operations reading this btree */
|
||||
u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
|
||||
Btree *pNext; /* List of other sharable Btrees from the same db */
|
||||
Btree *pPrev; /* Back pointer of the same list */
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
@@ -435,7 +437,7 @@ struct BtShared {
|
||||
BtLock *pLock; /* List of locks held on this shared-btree struct */
|
||||
Btree *pWriter; /* Btree with currently open write transaction */
|
||||
#endif
|
||||
u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */
|
||||
u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -456,12 +458,10 @@ struct BtShared {
|
||||
*/
|
||||
typedef struct CellInfo CellInfo;
|
||||
struct CellInfo {
|
||||
i64 nKey; /* The key for INTKEY tables, or number of bytes in key */
|
||||
u8 *pCell; /* Pointer to the start of cell content */
|
||||
u32 nData; /* Number of bytes of data */
|
||||
u32 nPayload; /* Total amount of payload */
|
||||
u16 nHeader; /* Size of the cell content header in bytes */
|
||||
u16 nLocal; /* Amount of payload held locally */
|
||||
i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
|
||||
u8 *pPayload; /* Pointer to the start of payload */
|
||||
u32 nPayload; /* Bytes of payload */
|
||||
u16 nLocal; /* Amount of payload held locally, not on overflow */
|
||||
u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */
|
||||
u16 nSize; /* Size of the cell content on the main b-tree page */
|
||||
};
|
||||
@@ -490,6 +490,11 @@ struct CellInfo {
|
||||
**
|
||||
** Fields in this structure are accessed under the BtShared.mutex
|
||||
** found at self->pBt->mutex.
|
||||
**
|
||||
** skipNext meaning:
|
||||
** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op.
|
||||
** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op.
|
||||
** eState==FAULT: Cursor fault with skipNext as error code.
|
||||
*/
|
||||
struct BtCursor {
|
||||
Btree *pBtree; /* The Btree to which this cursor belongs */
|
||||
@@ -502,7 +507,8 @@ struct BtCursor {
|
||||
void *pKey; /* Saved key that was cursor last known position */
|
||||
Pgno pgnoRoot; /* The root page of this tree */
|
||||
int nOvflAlloc; /* Allocated size of aOverflow[] array */
|
||||
int skipNext; /* Prev() is noop if negative. Next() is noop if positive */
|
||||
int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
|
||||
** Error code if eState==CURSOR_FAULT */
|
||||
u8 curFlags; /* zero or more BTCF_* flags defined below */
|
||||
u8 eState; /* One of the CURSOR_XXX constants (see below) */
|
||||
u8 hints; /* As configured by CursorSetHints() */
|
||||
@@ -544,11 +550,11 @@ struct BtCursor {
|
||||
** seek the cursor to the saved position.
|
||||
**
|
||||
** CURSOR_FAULT:
|
||||
** A unrecoverable error (an I/O error or a malloc failure) has occurred
|
||||
** An unrecoverable error (an I/O error or a malloc failure) has occurred
|
||||
** on a different connection that shares the BtShared cache with this
|
||||
** cursor. The error has left the cache in an inconsistent state.
|
||||
** Do nothing else with this cursor. Any attempt to use the cursor
|
||||
** should return the error code stored in BtCursor.skip
|
||||
** should return the error code stored in BtCursor.skipNext
|
||||
*/
|
||||
#define CURSOR_INVALID 0
|
||||
#define CURSOR_VALID 1
|
||||
@@ -658,6 +664,8 @@ struct IntegrityCk {
|
||||
int mxErr; /* Stop accumulating errors when this reaches zero */
|
||||
int nErr; /* Number of messages written to zErrMsg so far */
|
||||
int mallocFailed; /* A memory allocation error has occurred */
|
||||
const char *zPfx; /* Error message prefix */
|
||||
int v1, v2; /* Values for up to two %d fields in zPfx */
|
||||
StrAccum errMsg; /* Accumulate the error message text here */
|
||||
};
|
||||
|
||||
|
||||
+103
-63
@@ -156,6 +156,17 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
|
||||
sqlite3VdbeAddOp0(v, OP_Halt);
|
||||
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
if( pParse->nTableLock>0 && db->init.busy==0 ){
|
||||
sqlite3UserAuthInit(db);
|
||||
if( db->auth.authLevel<UAUTH_User ){
|
||||
pParse->rc = SQLITE_AUTH_USER;
|
||||
sqlite3ErrorMsg(pParse, "user not authenticated");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The cookie mask contains one bit for each database file open.
|
||||
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
|
||||
** set for each database that is used. Generate code to start a
|
||||
@@ -271,6 +282,16 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
pParse->nested--;
|
||||
}
|
||||
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
/*
|
||||
** Return TRUE if zTable is the name of the system table that stores the
|
||||
** list of users and their access credentials.
|
||||
*/
|
||||
int sqlite3UserAuthTable(const char *zTable){
|
||||
return sqlite3_stricmp(zTable, "sqlite_user")==0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Locate the in-memory structure that describes a particular database
|
||||
** table given the name of that table and (optionally) the name of the
|
||||
@@ -286,16 +307,25 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
|
||||
Table *p = 0;
|
||||
int i;
|
||||
int nName;
|
||||
assert( zName!=0 );
|
||||
nName = sqlite3Strlen30(zName);
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 ) return 0;
|
||||
#endif
|
||||
|
||||
/* All mutexes are required for schema access. Make sure we hold them. */
|
||||
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
/* Only the admin user is allowed to know that the sqlite_user table
|
||||
** exists */
|
||||
if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
|
||||
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName);
|
||||
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
|
||||
if( p ) break;
|
||||
}
|
||||
return p;
|
||||
@@ -335,6 +365,12 @@ Table *sqlite3LocateTable(
|
||||
}
|
||||
pParse->checkSchema = 1;
|
||||
}
|
||||
#if SQLITE_USER_AUTHENICATION
|
||||
else if( pParse->db->auth.authLevel<UAUTH_User ){
|
||||
sqlite3ErrorMsg(pParse, "user not authenticated");
|
||||
p = 0;
|
||||
}
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -378,7 +414,6 @@ Table *sqlite3LocateTableItem(
|
||||
Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
|
||||
Index *p = 0;
|
||||
int i;
|
||||
int nName = sqlite3Strlen30(zName);
|
||||
/* All mutexes are required for schema access. Make sure we hold them. */
|
||||
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
@@ -387,7 +422,7 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
|
||||
assert( pSchema );
|
||||
if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
|
||||
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||
p = sqlite3HashFind(&pSchema->idxHash, zName, nName);
|
||||
p = sqlite3HashFind(&pSchema->idxHash, zName);
|
||||
if( p ) break;
|
||||
}
|
||||
return p;
|
||||
@@ -400,10 +435,12 @@ static void freeIndex(sqlite3 *db, Index *p){
|
||||
#ifndef SQLITE_OMIT_ANALYZE
|
||||
sqlite3DeleteIndexSamples(db, p);
|
||||
#endif
|
||||
if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo);
|
||||
sqlite3ExprDelete(db, p->pPartIdxWhere);
|
||||
sqlite3DbFree(db, p->zColAff);
|
||||
if( p->isResized ) sqlite3DbFree(db, p->azColl);
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
sqlite3_free(p->aiRowEst);
|
||||
#endif
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
|
||||
@@ -415,13 +452,11 @@ static void freeIndex(sqlite3 *db, Index *p){
|
||||
*/
|
||||
void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
|
||||
Index *pIndex;
|
||||
int len;
|
||||
Hash *pHash;
|
||||
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
pHash = &db->aDb[iDb].pSchema->idxHash;
|
||||
len = sqlite3Strlen30(zIdxName);
|
||||
pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0);
|
||||
pIndex = sqlite3HashInsert(pHash, zIdxName, 0);
|
||||
if( ALWAYS(pIndex) ){
|
||||
if( pIndex->pTable->pIndex==pIndex ){
|
||||
pIndex->pTable->pIndex = pIndex->pNext;
|
||||
@@ -581,7 +616,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
|
||||
if( !db || db->pnBytesFreed==0 ){
|
||||
char *zName = pIndex->zName;
|
||||
TESTONLY ( Index *pOld = ) sqlite3HashInsert(
|
||||
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
|
||||
&pIndex->pSchema->idxHash, zName, 0
|
||||
);
|
||||
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
|
||||
assert( pOld==pIndex || pOld==0 );
|
||||
@@ -624,8 +659,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */
|
||||
pDb = &db->aDb[iDb];
|
||||
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
|
||||
sqlite3Strlen30(zTabName),0);
|
||||
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0);
|
||||
sqlite3DeleteTable(db, p);
|
||||
db->flags |= SQLITE_InternChanges;
|
||||
}
|
||||
@@ -1149,7 +1183,7 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){
|
||||
** estimate is scaled so that the size of an integer is 1. */
|
||||
if( pszEst ){
|
||||
*pszEst = 1; /* default size is approx 4 bytes */
|
||||
if( aff<=SQLITE_AFF_NONE ){
|
||||
if( aff<SQLITE_AFF_NUMERIC ){
|
||||
if( zChar ){
|
||||
while( zChar[0] ){
|
||||
if( sqlite3Isdigit(zChar[0]) ){
|
||||
@@ -1208,7 +1242,7 @@ void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
|
||||
p = pParse->pNewTable;
|
||||
if( p!=0 ){
|
||||
pCol = &(p->aCol[p->nCol-1]);
|
||||
if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr) ){
|
||||
if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){
|
||||
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
|
||||
pCol->zName);
|
||||
}else{
|
||||
@@ -1520,8 +1554,8 @@ static char *createTableStmt(sqlite3 *db, Table *p){
|
||||
zStmt[k++] = '(';
|
||||
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
|
||||
static const char * const azType[] = {
|
||||
/* SQLITE_AFF_TEXT */ " TEXT",
|
||||
/* SQLITE_AFF_NONE */ "",
|
||||
/* SQLITE_AFF_TEXT */ " TEXT",
|
||||
/* SQLITE_AFF_NUMERIC */ " NUM",
|
||||
/* SQLITE_AFF_INTEGER */ " INT",
|
||||
/* SQLITE_AFF_REAL */ " REAL"
|
||||
@@ -1533,15 +1567,15 @@ static char *createTableStmt(sqlite3 *db, Table *p){
|
||||
k += sqlite3Strlen30(&zStmt[k]);
|
||||
zSep = zSep2;
|
||||
identPut(zStmt, &k, pCol->zName);
|
||||
assert( pCol->affinity-SQLITE_AFF_TEXT >= 0 );
|
||||
assert( pCol->affinity-SQLITE_AFF_TEXT < ArraySize(azType) );
|
||||
testcase( pCol->affinity==SQLITE_AFF_TEXT );
|
||||
assert( pCol->affinity-SQLITE_AFF_NONE >= 0 );
|
||||
assert( pCol->affinity-SQLITE_AFF_NONE < ArraySize(azType) );
|
||||
testcase( pCol->affinity==SQLITE_AFF_NONE );
|
||||
testcase( pCol->affinity==SQLITE_AFF_TEXT );
|
||||
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
|
||||
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
|
||||
testcase( pCol->affinity==SQLITE_AFF_REAL );
|
||||
|
||||
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
|
||||
zType = azType[pCol->affinity - SQLITE_AFF_NONE];
|
||||
len = sqlite3Strlen30(zType);
|
||||
assert( pCol->affinity==SQLITE_AFF_NONE
|
||||
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
|
||||
@@ -1625,7 +1659,7 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){
|
||||
** no rowid btree for a WITHOUT ROWID. Instead, the canonical
|
||||
** data storage is a covering index btree.
|
||||
** (2) Bypass the creation of the sqlite_master table entry
|
||||
** for the PRIMARY KEY as the the primary key index is now
|
||||
** for the PRIMARY KEY as the primary key index is now
|
||||
** identified by the sqlite_master table entry of the table itself.
|
||||
** (3) Set the Index.tnum of the PRIMARY KEY Index object in the
|
||||
** schema to the rootpage from the main table.
|
||||
@@ -1646,7 +1680,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
|
||||
/* Convert the OP_CreateTable opcode that would normally create the
|
||||
** root-page for the table into a OP_CreateIndex opcode. The index
|
||||
** root-page for the table into an OP_CreateIndex opcode. The index
|
||||
** created will become the PRIMARY KEY index.
|
||||
*/
|
||||
if( pParse->addrCrTab ){
|
||||
@@ -1679,6 +1713,19 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
pTab->iPKey = -1;
|
||||
}else{
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
/*
|
||||
** Remove all redundant columns from the PRIMARY KEY. For example, change
|
||||
** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
|
||||
** code assumes the PRIMARY KEY contains no repeated columns.
|
||||
*/
|
||||
for(i=j=1; i<pPk->nKeyCol; i++){
|
||||
if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){
|
||||
pPk->nColumn--;
|
||||
}else{
|
||||
pPk->aiColumn[j++] = pPk->aiColumn[i];
|
||||
}
|
||||
}
|
||||
pPk->nKeyCol = j;
|
||||
}
|
||||
pPk->isCovering = 1;
|
||||
assert( pPk!=0 );
|
||||
@@ -1947,8 +1994,7 @@ void sqlite3EndTable(
|
||||
Table *pOld;
|
||||
Schema *pSchema = p->pSchema;
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName,
|
||||
sqlite3Strlen30(p->zName),p);
|
||||
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
|
||||
if( pOld ){
|
||||
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
|
||||
db->mallocFailed = 1;
|
||||
@@ -2059,7 +2105,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
int nErr = 0; /* Number of errors encountered */
|
||||
int n; /* Temporarily holds the number of cursors assigned */
|
||||
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
|
||||
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
|
||||
sqlite3_xauth xAuth; /* Saved xAuth pointer */
|
||||
|
||||
assert( pTable );
|
||||
|
||||
@@ -2598,7 +2644,7 @@ void sqlite3CreateForeignKey(
|
||||
|
||||
assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
|
||||
pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
|
||||
pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey
|
||||
pFKey->zTo, (void *)pFKey
|
||||
);
|
||||
if( pNextTo==pFKey ){
|
||||
db->mallocFailed = 1;
|
||||
@@ -2661,7 +2707,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
int iPartIdxLabel; /* Jump to this label to skip a row */
|
||||
Vdbe *v; /* Generate code into this virtual machine */
|
||||
KeyInfo *pKey; /* KeyInfo for index */
|
||||
int regRecord; /* Register holding assemblied index record */
|
||||
int regRecord; /* Register holding assembled index record */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
||||
|
||||
@@ -2686,7 +2732,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
|
||||
/* Open the sorter cursor if we are to use one. */
|
||||
iSorter = pParse->nTab++;
|
||||
sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)
|
||||
sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*)
|
||||
sqlite3KeyInfoRef(pKey), P4_KEYINFO);
|
||||
|
||||
/* Open the table. Loop through all rows of the table, inserting index
|
||||
@@ -2717,7 +2763,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
}else{
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
|
||||
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
sqlite3ReleaseTempReg(pParse, regRecord);
|
||||
@@ -2874,6 +2920,10 @@ Index *sqlite3CreateIndex(
|
||||
assert( pTab!=0 );
|
||||
assert( pParse->nErr==0 );
|
||||
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
|
||||
&& db->init.busy==0
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
&& sqlite3UserAuthTable(pTab->zName)==0
|
||||
#endif
|
||||
&& sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
|
||||
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
|
||||
goto exit_create_index;
|
||||
@@ -3035,7 +3085,7 @@ Index *sqlite3CreateIndex(
|
||||
pParse->checkSchema = 1;
|
||||
goto exit_create_index;
|
||||
}
|
||||
assert( pTab->nCol<=0x7fff && j<=0x7fff );
|
||||
assert( j<=0x7fff );
|
||||
pIndex->aiColumn[i] = (i16)j;
|
||||
if( pListItem->pExpr ){
|
||||
int nColl;
|
||||
@@ -3146,8 +3196,7 @@ Index *sqlite3CreateIndex(
|
||||
Index *p;
|
||||
assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
|
||||
p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
|
||||
pIndex->zName, sqlite3Strlen30(pIndex->zName),
|
||||
pIndex);
|
||||
pIndex->zName, pIndex);
|
||||
if( p ){
|
||||
assert( p==pIndex ); /* Malloc must have failed */
|
||||
db->mallocFailed = 1;
|
||||
@@ -3262,7 +3311,7 @@ exit_create_index:
|
||||
** Fill the Index.aiRowEst[] array with default information - information
|
||||
** to be used when we have not run the ANALYZE command.
|
||||
**
|
||||
** aiRowEst[0] is suppose to contain the number of elements in the index.
|
||||
** aiRowEst[0] is supposed to contain the number of elements in the index.
|
||||
** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
|
||||
** number of rows in the table that match any particular value of the
|
||||
** first column of the index. aiRowEst[2] is an estimate of the number
|
||||
@@ -3641,7 +3690,7 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
|
||||
** if this is the first term of the FROM clause. pTable and pDatabase
|
||||
** are the name of the table and database named in the FROM clause term.
|
||||
** pDatabase is NULL if the database name qualifier is missing - the
|
||||
** usual case. If the term has a alias, then pAlias points to the
|
||||
** usual case. If the term has an alias, then pAlias points to the
|
||||
** alias token. If the term is a subquery, then pSubquery is the
|
||||
** SELECT statement that the subquery encodes. The pTable and
|
||||
** pDatabase parameters are NULL for subqueries. The pOn and pUsing
|
||||
@@ -4153,40 +4202,31 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
|
||||
** when it has finished using it.
|
||||
*/
|
||||
KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
|
||||
int i;
|
||||
int nCol = pIdx->nColumn;
|
||||
int nKey = pIdx->nKeyCol;
|
||||
KeyInfo *pKey;
|
||||
if( pParse->nErr ) return 0;
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){
|
||||
sqlite3KeyInfoUnref(pIdx->pKeyInfo);
|
||||
pIdx->pKeyInfo = 0;
|
||||
if( pIdx->uniqNotNull ){
|
||||
pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
|
||||
}else{
|
||||
pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
|
||||
}
|
||||
#endif
|
||||
if( pIdx->pKeyInfo==0 ){
|
||||
int i;
|
||||
int nCol = pIdx->nColumn;
|
||||
int nKey = pIdx->nKeyCol;
|
||||
KeyInfo *pKey;
|
||||
if( pIdx->uniqNotNull ){
|
||||
pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
|
||||
}else{
|
||||
pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
|
||||
if( pKey ){
|
||||
assert( sqlite3KeyInfoIsWriteable(pKey) );
|
||||
for(i=0; i<nCol; i++){
|
||||
char *zColl = pIdx->azColl[i];
|
||||
assert( zColl!=0 );
|
||||
pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
|
||||
sqlite3LocateCollSeq(pParse, zColl);
|
||||
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
|
||||
}
|
||||
if( pKey ){
|
||||
assert( sqlite3KeyInfoIsWriteable(pKey) );
|
||||
for(i=0; i<nCol; i++){
|
||||
char *zColl = pIdx->azColl[i];
|
||||
assert( zColl!=0 );
|
||||
pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
|
||||
sqlite3LocateCollSeq(pParse, zColl);
|
||||
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
|
||||
}
|
||||
if( pParse->nErr ){
|
||||
sqlite3KeyInfoUnref(pKey);
|
||||
}else{
|
||||
pIdx->pKeyInfo = pKey;
|
||||
}
|
||||
if( pParse->nErr ){
|
||||
sqlite3KeyInfoUnref(pKey);
|
||||
pKey = 0;
|
||||
}
|
||||
}
|
||||
return sqlite3KeyInfoRef(pIdx->pKeyInfo);
|
||||
return pKey;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
|
||||
+5
-5
@@ -142,7 +142,7 @@ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
|
||||
**
|
||||
** Each pointer stored in the sqlite3.aCollSeq hash table contains an
|
||||
** array of three CollSeq structures. The first is the collation sequence
|
||||
** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be.
|
||||
** preferred for UTF-8, the second UTF-16le, and the third UTF-16be.
|
||||
**
|
||||
** Stored immediately after the three collation sequences is a copy of
|
||||
** the collation sequence name. A pointer to this string is stored in
|
||||
@@ -154,11 +154,11 @@ static CollSeq *findCollSeqEntry(
|
||||
int create /* Create a new entry if true */
|
||||
){
|
||||
CollSeq *pColl;
|
||||
int nName = sqlite3Strlen30(zName);
|
||||
pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
|
||||
pColl = sqlite3HashFind(&db->aCollSeq, zName);
|
||||
|
||||
if( 0==pColl && create ){
|
||||
pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 );
|
||||
int nName = sqlite3Strlen30(zName);
|
||||
pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1);
|
||||
if( pColl ){
|
||||
CollSeq *pDel = 0;
|
||||
pColl[0].zName = (char*)&pColl[3];
|
||||
@@ -169,7 +169,7 @@ static CollSeq *findCollSeqEntry(
|
||||
pColl[2].enc = SQLITE_UTF16BE;
|
||||
memcpy(pColl[0].zName, zName, nName);
|
||||
pColl[0].zName[nName] = 0;
|
||||
pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
|
||||
pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl);
|
||||
|
||||
/* If a malloc() failure occurred in sqlite3HashInsert(), it will
|
||||
** return the pColl pointer to be deleted (because it wasn't added
|
||||
|
||||
+10
-3
@@ -70,7 +70,7 @@ extern const char sqlite3IsEbcdicIdChar[];
|
||||
** a statement.
|
||||
**
|
||||
** (4) CREATE The keyword CREATE has been seen at the beginning of a
|
||||
** statement, possibly preceeded by EXPLAIN and/or followed by
|
||||
** statement, possibly preceded by EXPLAIN and/or followed by
|
||||
** TEMP or TEMPORARY
|
||||
**
|
||||
** (5) TRIGGER We are in the middle of a trigger definition that must be
|
||||
@@ -80,7 +80,7 @@ extern const char sqlite3IsEbcdicIdChar[];
|
||||
** the end of a trigger definition.
|
||||
**
|
||||
** (7) END We've seen the ";END" of the ";END;" that occurs at the end
|
||||
** of a trigger difinition.
|
||||
** of a trigger definition.
|
||||
**
|
||||
** Transitions between states above are determined by tokens extracted
|
||||
** from the input. The following tokens are significant:
|
||||
@@ -123,7 +123,7 @@ int sqlite3_complete(const char *zSql){
|
||||
};
|
||||
#else
|
||||
/* If triggers are not supported by this compile then the statement machine
|
||||
** used to detect the end of a statement is much simplier
|
||||
** used to detect the end of a statement is much simpler
|
||||
*/
|
||||
static const u8 trans[3][3] = {
|
||||
/* Token: */
|
||||
@@ -134,6 +134,13 @@ int sqlite3_complete(const char *zSql){
|
||||
};
|
||||
#endif /* SQLITE_OMIT_TRIGGER */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( zSql==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
while( *zSql ){
|
||||
switch( *zSql ){
|
||||
case ';': { /* A semicolon */
|
||||
|
||||
+120
-107
@@ -33,88 +33,91 @@ static const char * const azCompileOpt[] = {
|
||||
#define CTIMEOPT_VAL_(opt) #opt
|
||||
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
|
||||
|
||||
#ifdef SQLITE_32BIT_ROWID
|
||||
#if SQLITE_32BIT_ROWID
|
||||
"32BIT_ROWID",
|
||||
#endif
|
||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
#if SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
"4_BYTE_ALIGNED_MALLOC",
|
||||
#endif
|
||||
#ifdef SQLITE_CASE_SENSITIVE_LIKE
|
||||
#if SQLITE_CASE_SENSITIVE_LIKE
|
||||
"CASE_SENSITIVE_LIKE",
|
||||
#endif
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
#if SQLITE_CHECK_PAGES
|
||||
"CHECK_PAGES",
|
||||
#endif
|
||||
#ifdef SQLITE_COVERAGE_TEST
|
||||
#if SQLITE_COVERAGE_TEST
|
||||
"COVERAGE_TEST",
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
#if SQLITE_DEBUG
|
||||
"DEBUG",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_LOCKING_MODE
|
||||
#if SQLITE_DEFAULT_LOCKING_MODE
|
||||
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
|
||||
#endif
|
||||
#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
|
||||
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
|
||||
#endif
|
||||
#ifdef SQLITE_DISABLE_DIRSYNC
|
||||
#if SQLITE_DISABLE_DIRSYNC
|
||||
"DISABLE_DIRSYNC",
|
||||
#endif
|
||||
#ifdef SQLITE_DISABLE_LFS
|
||||
#if SQLITE_DISABLE_LFS
|
||||
"DISABLE_LFS",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
#if SQLITE_ENABLE_API_ARMOR
|
||||
"ENABLE_API_ARMOR",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_ATOMIC_WRITE
|
||||
"ENABLE_ATOMIC_WRITE",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_CEROD
|
||||
#if SQLITE_ENABLE_CEROD
|
||||
"ENABLE_CEROD",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
#if SQLITE_ENABLE_COLUMN_METADATA
|
||||
"ENABLE_COLUMN_METADATA",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
"ENABLE_EXPENSIVE_ASSERT",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS1
|
||||
#if SQLITE_ENABLE_FTS1
|
||||
"ENABLE_FTS1",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS2
|
||||
#if SQLITE_ENABLE_FTS2
|
||||
"ENABLE_FTS2",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS3
|
||||
#if SQLITE_ENABLE_FTS3
|
||||
"ENABLE_FTS3",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
#if SQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
"ENABLE_FTS3_PARENTHESIS",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS4
|
||||
#if SQLITE_ENABLE_FTS4
|
||||
"ENABLE_FTS4",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
#if SQLITE_ENABLE_ICU
|
||||
"ENABLE_ICU",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
#if SQLITE_ENABLE_IOTRACE
|
||||
"ENABLE_IOTRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
|
||||
#if SQLITE_ENABLE_LOAD_EXTENSION
|
||||
"ENABLE_LOAD_EXTENSION",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_LOCKING_STYLE
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
"ENABLE_MEMORY_MANAGEMENT",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
#if SQLITE_ENABLE_MEMSYS3
|
||||
"ENABLE_MEMSYS3",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MEMSYS5
|
||||
#if SQLITE_ENABLE_MEMSYS5
|
||||
"ENABLE_MEMSYS5",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
"ENABLE_OVERSIZE_CELL_CHECK",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
#if SQLITE_ENABLE_RTREE
|
||||
"ENABLE_RTREE",
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_STAT4)
|
||||
@@ -122,31 +125,31 @@ static const char * const azCompileOpt[] = {
|
||||
#elif defined(SQLITE_ENABLE_STAT3)
|
||||
"ENABLE_STAT3",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
#if SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
"ENABLE_UNLOCK_NOTIFY",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
"ENABLE_UPDATE_DELETE_LIMIT",
|
||||
#endif
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
#if SQLITE_HAS_CODEC
|
||||
"HAS_CODEC",
|
||||
#endif
|
||||
#ifdef SQLITE_HAVE_ISNAN
|
||||
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
|
||||
"HAVE_ISNAN",
|
||||
#endif
|
||||
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
||||
#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
||||
"HOMEGROWN_RECURSIVE_MUTEX",
|
||||
#endif
|
||||
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
|
||||
#if SQLITE_IGNORE_AFP_LOCK_ERRORS
|
||||
"IGNORE_AFP_LOCK_ERRORS",
|
||||
#endif
|
||||
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
"IGNORE_FLOCK_LOCK_ERRORS",
|
||||
#endif
|
||||
#ifdef SQLITE_INT64_TYPE
|
||||
"INT64_TYPE",
|
||||
#endif
|
||||
#ifdef SQLITE_LOCK_TRACE
|
||||
#if SQLITE_LOCK_TRACE
|
||||
"LOCK_TRACE",
|
||||
#endif
|
||||
#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
|
||||
@@ -155,223 +158,226 @@ static const char * const azCompileOpt[] = {
|
||||
#ifdef SQLITE_MAX_SCHEMA_RETRY
|
||||
"MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
|
||||
#endif
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
#if SQLITE_MEMDEBUG
|
||||
"MEMDEBUG",
|
||||
#endif
|
||||
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
||||
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
||||
"MIXED_ENDIAN_64BIT_FLOAT",
|
||||
#endif
|
||||
#ifdef SQLITE_NO_SYNC
|
||||
#if SQLITE_NO_SYNC
|
||||
"NO_SYNC",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_ALTERTABLE
|
||||
#if SQLITE_OMIT_ALTERTABLE
|
||||
"OMIT_ALTERTABLE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_ANALYZE
|
||||
#if SQLITE_OMIT_ANALYZE
|
||||
"OMIT_ANALYZE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_ATTACH
|
||||
#if SQLITE_OMIT_ATTACH
|
||||
"OMIT_ATTACH",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTHORIZATION
|
||||
#if SQLITE_OMIT_AUTHORIZATION
|
||||
"OMIT_AUTHORIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTOINCREMENT
|
||||
#if SQLITE_OMIT_AUTOINCREMENT
|
||||
"OMIT_AUTOINCREMENT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTOINIT
|
||||
#if SQLITE_OMIT_AUTOINIT
|
||||
"OMIT_AUTOINIT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
#if SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
"OMIT_AUTOMATIC_INDEX",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTORESET
|
||||
#if SQLITE_OMIT_AUTORESET
|
||||
"OMIT_AUTORESET",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTOVACUUM
|
||||
#if SQLITE_OMIT_AUTOVACUUM
|
||||
"OMIT_AUTOVACUUM",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
|
||||
#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
|
||||
"OMIT_BETWEEN_OPTIMIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_BLOB_LITERAL
|
||||
#if SQLITE_OMIT_BLOB_LITERAL
|
||||
"OMIT_BLOB_LITERAL",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_BTREECOUNT
|
||||
#if SQLITE_OMIT_BTREECOUNT
|
||||
"OMIT_BTREECOUNT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_BUILTIN_TEST
|
||||
#if SQLITE_OMIT_BUILTIN_TEST
|
||||
"OMIT_BUILTIN_TEST",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_CAST
|
||||
#if SQLITE_OMIT_CAST
|
||||
"OMIT_CAST",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_CHECK
|
||||
#if SQLITE_OMIT_CHECK
|
||||
"OMIT_CHECK",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_COMPLETE
|
||||
#if SQLITE_OMIT_COMPLETE
|
||||
"OMIT_COMPLETE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_COMPOUND_SELECT
|
||||
#if SQLITE_OMIT_COMPOUND_SELECT
|
||||
"OMIT_COMPOUND_SELECT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_CTE
|
||||
#if SQLITE_OMIT_CTE
|
||||
"OMIT_CTE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DATETIME_FUNCS
|
||||
#if SQLITE_OMIT_DATETIME_FUNCS
|
||||
"OMIT_DATETIME_FUNCS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DECLTYPE
|
||||
#if SQLITE_OMIT_DECLTYPE
|
||||
"OMIT_DECLTYPE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DEPRECATED
|
||||
#if SQLITE_OMIT_DEPRECATED
|
||||
"OMIT_DEPRECATED",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DISKIO
|
||||
#if SQLITE_OMIT_DISKIO
|
||||
"OMIT_DISKIO",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_EXPLAIN
|
||||
#if SQLITE_OMIT_EXPLAIN
|
||||
"OMIT_EXPLAIN",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_FLAG_PRAGMAS
|
||||
#if SQLITE_OMIT_FLAG_PRAGMAS
|
||||
"OMIT_FLAG_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
#if SQLITE_OMIT_FLOATING_POINT
|
||||
"OMIT_FLOATING_POINT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_FOREIGN_KEY
|
||||
#if SQLITE_OMIT_FOREIGN_KEY
|
||||
"OMIT_FOREIGN_KEY",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_GET_TABLE
|
||||
#if SQLITE_OMIT_GET_TABLE
|
||||
"OMIT_GET_TABLE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_INCRBLOB
|
||||
#if SQLITE_OMIT_INCRBLOB
|
||||
"OMIT_INCRBLOB",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
#if SQLITE_OMIT_INTEGRITY_CHECK
|
||||
"OMIT_INTEGRITY_CHECK",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
|
||||
#if SQLITE_OMIT_LIKE_OPTIMIZATION
|
||||
"OMIT_LIKE_OPTIMIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LOAD_EXTENSION
|
||||
#if SQLITE_OMIT_LOAD_EXTENSION
|
||||
"OMIT_LOAD_EXTENSION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LOCALTIME
|
||||
#if SQLITE_OMIT_LOCALTIME
|
||||
"OMIT_LOCALTIME",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LOOKASIDE
|
||||
#if SQLITE_OMIT_LOOKASIDE
|
||||
"OMIT_LOOKASIDE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_MEMORYDB
|
||||
#if SQLITE_OMIT_MEMORYDB
|
||||
"OMIT_MEMORYDB",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
|
||||
#if SQLITE_OMIT_OR_OPTIMIZATION
|
||||
"OMIT_OR_OPTIMIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
#if SQLITE_OMIT_PAGER_PRAGMAS
|
||||
"OMIT_PAGER_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_PRAGMA
|
||||
#if SQLITE_OMIT_PRAGMA
|
||||
"OMIT_PRAGMA",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
#if SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
"OMIT_PROGRESS_CALLBACK",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_QUICKBALANCE
|
||||
#if SQLITE_OMIT_QUICKBALANCE
|
||||
"OMIT_QUICKBALANCE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_REINDEX
|
||||
#if SQLITE_OMIT_REINDEX
|
||||
"OMIT_REINDEX",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
|
||||
#if SQLITE_OMIT_SCHEMA_PRAGMAS
|
||||
"OMIT_SCHEMA_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
||||
#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
||||
"OMIT_SCHEMA_VERSION_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
#if SQLITE_OMIT_SHARED_CACHE
|
||||
"OMIT_SHARED_CACHE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_SUBQUERY
|
||||
#if SQLITE_OMIT_SUBQUERY
|
||||
"OMIT_SUBQUERY",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TCL_VARIABLE
|
||||
#if SQLITE_OMIT_TCL_VARIABLE
|
||||
"OMIT_TCL_VARIABLE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TEMPDB
|
||||
#if SQLITE_OMIT_TEMPDB
|
||||
"OMIT_TEMPDB",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TRACE
|
||||
#if SQLITE_OMIT_TRACE
|
||||
"OMIT_TRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TRIGGER
|
||||
#if SQLITE_OMIT_TRIGGER
|
||||
"OMIT_TRIGGER",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
|
||||
#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
|
||||
"OMIT_TRUNCATE_OPTIMIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_UTF16
|
||||
#if SQLITE_OMIT_UTF16
|
||||
"OMIT_UTF16",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_VACUUM
|
||||
#if SQLITE_OMIT_VACUUM
|
||||
"OMIT_VACUUM",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_VIEW
|
||||
#if SQLITE_OMIT_VIEW
|
||||
"OMIT_VIEW",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
#if SQLITE_OMIT_VIRTUALTABLE
|
||||
"OMIT_VIRTUALTABLE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
#if SQLITE_OMIT_WAL
|
||||
"OMIT_WAL",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_WSD
|
||||
#if SQLITE_OMIT_WSD
|
||||
"OMIT_WSD",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_XFER_OPT
|
||||
#if SQLITE_OMIT_XFER_OPT
|
||||
"OMIT_XFER_OPT",
|
||||
#endif
|
||||
#ifdef SQLITE_PERFORMANCE_TRACE
|
||||
#if SQLITE_PERFORMANCE_TRACE
|
||||
"PERFORMANCE_TRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_PROXY_DEBUG
|
||||
#if SQLITE_PROXY_DEBUG
|
||||
"PROXY_DEBUG",
|
||||
#endif
|
||||
#ifdef SQLITE_RTREE_INT_ONLY
|
||||
#if SQLITE_RTREE_INT_ONLY
|
||||
"RTREE_INT_ONLY",
|
||||
#endif
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
#if SQLITE_SECURE_DELETE
|
||||
"SECURE_DELETE",
|
||||
#endif
|
||||
#ifdef SQLITE_SMALL_STACK
|
||||
#if SQLITE_SMALL_STACK
|
||||
"SMALL_STACK",
|
||||
#endif
|
||||
#ifdef SQLITE_SOUNDEX
|
||||
#if SQLITE_SOUNDEX
|
||||
"SOUNDEX",
|
||||
#endif
|
||||
#ifdef SQLITE_SYSTEM_MALLOC
|
||||
#if SQLITE_SYSTEM_MALLOC
|
||||
"SYSTEM_MALLOC",
|
||||
#endif
|
||||
#ifdef SQLITE_TCL
|
||||
#if SQLITE_TCL
|
||||
"TCL",
|
||||
#endif
|
||||
#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
|
||||
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
|
||||
#endif
|
||||
#ifdef SQLITE_TEST
|
||||
#if SQLITE_TEST
|
||||
"TEST",
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE)
|
||||
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
|
||||
#endif
|
||||
#ifdef SQLITE_USE_ALLOCA
|
||||
#if SQLITE_USE_ALLOCA
|
||||
"USE_ALLOCA",
|
||||
#endif
|
||||
#ifdef SQLITE_WIN32_MALLOC
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
"USER_AUTHENTICATION",
|
||||
#endif
|
||||
#if SQLITE_WIN32_MALLOC
|
||||
"WIN32_MALLOC",
|
||||
#endif
|
||||
#ifdef SQLITE_ZERO_MALLOC
|
||||
#if SQLITE_ZERO_MALLOC
|
||||
"ZERO_MALLOC"
|
||||
#endif
|
||||
};
|
||||
@@ -385,6 +391,13 @@ static const char * const azCompileOpt[] = {
|
||||
*/
|
||||
int sqlite3_compileoption_used(const char *zOptName){
|
||||
int i, n;
|
||||
|
||||
#if SQLITE_ENABLE_API_ARMOR
|
||||
if( zOptName==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
|
||||
n = sqlite3Strlen30(zOptName);
|
||||
|
||||
@@ -392,7 +405,7 @@ int sqlite3_compileoption_used(const char *zOptName){
|
||||
** linear search is adequate. No need for a binary search. */
|
||||
for(i=0; i<ArraySize(azCompileOpt); i++){
|
||||
if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
|
||||
&& sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0
|
||||
&& sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
|
||||
+14
-12
@@ -16,7 +16,7 @@
|
||||
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** SQLite processes all times and dates as Julian Day numbers. The
|
||||
** SQLite processes all times and dates as julian day numbers. The
|
||||
** dates and times are stored as the number of days since noon
|
||||
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
|
||||
** calendar system.
|
||||
@@ -24,14 +24,14 @@
|
||||
** 1970-01-01 00:00:00 is JD 2440587.5
|
||||
** 2000-01-01 00:00:00 is JD 2451544.5
|
||||
**
|
||||
** This implemention requires years to be expressed as a 4-digit number
|
||||
** This implementation requires years to be expressed as a 4-digit number
|
||||
** which means that only dates between 0000-01-01 and 9999-12-31 can
|
||||
** be represented, even though julian day numbers allow a much wider
|
||||
** range of dates.
|
||||
**
|
||||
** The Gregorian calendar system is used for all dates and times,
|
||||
** even those that predate the Gregorian calendar. Historians usually
|
||||
** use the Julian calendar for dates prior to 1582-10-15 and for some
|
||||
** use the julian calendar for dates prior to 1582-10-15 and for some
|
||||
** dates afterwards, depending on locale. Beware of this difference.
|
||||
**
|
||||
** The conversion algorithms are implemented based on descriptions
|
||||
@@ -304,7 +304,7 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to parse the given string into a Julian Day Number. Return
|
||||
** Attempt to parse the given string into a julian day number. Return
|
||||
** the number of errors.
|
||||
**
|
||||
** The following are acceptable forms for the input string:
|
||||
@@ -412,8 +412,9 @@ static void clearYMD_HMS_TZ(DateTime *p){
|
||||
** already, check for an MSVC build environment that provides
|
||||
** localtime_s().
|
||||
*/
|
||||
#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
|
||||
defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
|
||||
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \
|
||||
&& defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
|
||||
#undef HAVE_LOCALTIME_S
|
||||
#define HAVE_LOCALTIME_S 1
|
||||
#endif
|
||||
|
||||
@@ -433,8 +434,7 @@ static void clearYMD_HMS_TZ(DateTime *p){
|
||||
*/
|
||||
static int osLocaltime(time_t *t, struct tm *pTm){
|
||||
int rc;
|
||||
#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
|
||||
&& (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
|
||||
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S
|
||||
struct tm *pX;
|
||||
#if SQLITE_THREADSAFE>0
|
||||
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||
@@ -451,7 +451,7 @@ static int osLocaltime(time_t *t, struct tm *pTm){
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
|
||||
#endif
|
||||
#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
|
||||
#if HAVE_LOCALTIME_R
|
||||
rc = localtime_r(t, pTm)==0;
|
||||
#else
|
||||
rc = localtime_s(pTm, t);
|
||||
@@ -875,7 +875,7 @@ static void dateFunc(
|
||||
** %f ** fractional seconds SS.SSS
|
||||
** %H hour 00-24
|
||||
** %j day of year 000-366
|
||||
** %J ** Julian day number
|
||||
** %J ** julian day number
|
||||
** %m month 01-12
|
||||
** %M minute 00-59
|
||||
** %s seconds since 1970-01-01
|
||||
@@ -895,8 +895,10 @@ static void strftimeFunc(
|
||||
size_t i,j;
|
||||
char *z;
|
||||
sqlite3 *db;
|
||||
const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
|
||||
const char *zFmt;
|
||||
char zBuf[100];
|
||||
if( argc==0 ) return;
|
||||
zFmt = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
|
||||
db = sqlite3_context_db_handle(context);
|
||||
for(i=0, n=1; zFmt[i]; i++, n++){
|
||||
@@ -1090,7 +1092,7 @@ static void currentTimeFunc(
|
||||
iT = sqlite3StmtCurrentTime(context);
|
||||
if( iT<=0 ) return;
|
||||
t = iT/1000 - 10000*(sqlite3_int64)21086676;
|
||||
#ifdef HAVE_GMTIME_R
|
||||
#if HAVE_GMTIME_R
|
||||
pTm = gmtime_r(&t, &sNow);
|
||||
#else
|
||||
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
|
||||
|
||||
+13
-11
@@ -90,7 +90,7 @@ void sqlite3MaterializeView(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Table *pView, /* View definition */
|
||||
Expr *pWhere, /* Optional WHERE clause to be added */
|
||||
int iCur /* Cursor number for ephemerial table */
|
||||
int iCur /* Cursor number for ephemeral table */
|
||||
){
|
||||
SelectDest dest;
|
||||
Select *pSel;
|
||||
@@ -226,8 +226,8 @@ void sqlite3DeleteFrom(
|
||||
WhereInfo *pWInfo; /* Information about the WHERE clause */
|
||||
Index *pIdx; /* For looping over indices of the table */
|
||||
int iTabCur; /* Cursor number for the table */
|
||||
int iDataCur; /* VDBE cursor for the canonical data source */
|
||||
int iIdxCur; /* Cursor number of the first index */
|
||||
int iDataCur = 0; /* VDBE cursor for the canonical data source */
|
||||
int iIdxCur = 0; /* Cursor number of the first index */
|
||||
int nIdx; /* Number of indices */
|
||||
sqlite3 *db; /* Main database structure */
|
||||
AuthContext sContext; /* Authorization context */
|
||||
@@ -248,7 +248,7 @@ void sqlite3DeleteFrom(
|
||||
int addrBypass = 0; /* Address of jump over the delete logic */
|
||||
int addrLoop = 0; /* Top of the delete loop */
|
||||
int addrDelete = 0; /* Jump directly to the delete logic */
|
||||
int addrEphOpen = 0; /* Instruction to open the Ephermeral table */
|
||||
int addrEphOpen = 0; /* Instruction to open the Ephemeral table */
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
int isView; /* True if attempting to delete from a view */
|
||||
@@ -328,7 +328,7 @@ void sqlite3DeleteFrom(
|
||||
sqlite3BeginWriteOperation(pParse, 1, iDb);
|
||||
|
||||
/* If we are trying to delete from a view, realize that view into
|
||||
** a ephemeral table.
|
||||
** an ephemeral table.
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
if( isView ){
|
||||
@@ -382,7 +382,7 @@ void sqlite3DeleteFrom(
|
||||
iRowSet = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
|
||||
}else{
|
||||
/* For a WITHOUT ROWID table, create an ephermeral table used to
|
||||
/* For a WITHOUT ROWID table, create an ephemeral table used to
|
||||
** hold all primary keys for rows to be deleted. */
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
assert( pPk!=0 );
|
||||
@@ -466,10 +466,11 @@ void sqlite3DeleteFrom(
|
||||
** triggers.
|
||||
*/
|
||||
if( !isView ){
|
||||
testcase( IsVirtual(pTab) );
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
|
||||
&iDataCur, &iIdxCur);
|
||||
assert( pPk || iDataCur==iTabCur );
|
||||
assert( pPk || iIdxCur==iDataCur+1 );
|
||||
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
|
||||
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
|
||||
}
|
||||
|
||||
/* Set up a loop over the rowids/primary-keys that were found in the
|
||||
@@ -477,9 +478,10 @@ void sqlite3DeleteFrom(
|
||||
*/
|
||||
if( okOnePass ){
|
||||
/* Just one row. Hence the top-of-loop is a no-op */
|
||||
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
|
||||
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
|
||||
assert( !IsVirtual(pTab) );
|
||||
if( aToOpen[iDataCur-iTabCur] ){
|
||||
assert( pPk!=0 );
|
||||
assert( pPk!=0 || pTab->pSelect!=0 );
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
@@ -555,7 +557,7 @@ delete_from_cleanup:
|
||||
return;
|
||||
}
|
||||
/* Make sure "isView" and other macros defined above are undefined. Otherwise
|
||||
** thely may interfere with compilation of other functions in this file
|
||||
** they may interfere with compilation of other functions in this file
|
||||
** (or in another file, if this file becomes part of the amalgamation). */
|
||||
#ifdef isView
|
||||
#undef isView
|
||||
|
||||
+176
-157
@@ -22,7 +22,7 @@
|
||||
** affinity of that column is returned. Otherwise, 0x00 is returned,
|
||||
** indicating no affinity for the expression.
|
||||
**
|
||||
** i.e. the WHERE clause expresssions in the following statements all
|
||||
** i.e. the WHERE clause expressions in the following statements all
|
||||
** have an affinity:
|
||||
**
|
||||
** CREATE TABLE t1(a);
|
||||
@@ -501,7 +501,7 @@ void sqlite3ExprAttachSubtrees(
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate a Expr node which joins as many as two subtrees.
|
||||
** Allocate an Expr node which joins as many as two subtrees.
|
||||
**
|
||||
** One or both of the subtrees can be NULL. Return a pointer to the new
|
||||
** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed,
|
||||
@@ -515,7 +515,7 @@ Expr *sqlite3PExpr(
|
||||
const Token *pToken /* Argument token */
|
||||
){
|
||||
Expr *p;
|
||||
if( op==TK_AND && pLeft && pRight ){
|
||||
if( op==TK_AND && pLeft && pRight && pParse->nErr==0 ){
|
||||
/* Take advantage of short-circuit false optimization for AND */
|
||||
p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
|
||||
}else{
|
||||
@@ -611,7 +611,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
|
||||
**
|
||||
** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
|
||||
** as the previous instance of the same wildcard. Or if this is the first
|
||||
** instance of the wildcard, the next sequenial variable number is
|
||||
** instance of the wildcard, the next sequential variable number is
|
||||
** assigned.
|
||||
*/
|
||||
void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
@@ -746,7 +746,7 @@ static int exprStructSize(Expr *p){
|
||||
** During expression analysis, extra information is computed and moved into
|
||||
** later parts of teh Expr object and that extra information might get chopped
|
||||
** off if the expression is reduced. Note also that it does not work to
|
||||
** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal
|
||||
** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal
|
||||
** to reduce a pristine expression tree from the parser. The implementation
|
||||
** of dupedExprStructSize() contain multiple assert() statements that attempt
|
||||
** to enforce this constraint.
|
||||
@@ -815,7 +815,7 @@ static int dupedExprSize(Expr *p, int flags){
|
||||
** is not NULL then *pzBuffer is assumed to point to a buffer large enough
|
||||
** to store the copy of expression p, the copies of p->u.zToken
|
||||
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
|
||||
** if any. Before returning, *pzBuffer is set to the first byte passed the
|
||||
** if any. Before returning, *pzBuffer is set to the first byte past the
|
||||
** portion of the buffer copied into by this function.
|
||||
*/
|
||||
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||
@@ -1069,6 +1069,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
pNew->nSelectRow = p->nSelectRow;
|
||||
pNew->pWith = withDup(db, p->pWith);
|
||||
sqlite3SelectSetName(pNew, p->zSelName);
|
||||
return pNew;
|
||||
}
|
||||
#else
|
||||
@@ -1209,37 +1210,51 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
|
||||
}
|
||||
|
||||
/*
|
||||
** These routines are Walker callbacks. Walker.u.pi is a pointer
|
||||
** to an integer. These routines are checking an expression to see
|
||||
** if it is a constant. Set *Walker.u.pi to 0 if the expression is
|
||||
** not constant.
|
||||
** These routines are Walker callbacks used to check expressions to
|
||||
** see if they are "constant" for some definition of constant. The
|
||||
** Walker.eCode value determines the type of "constant" we are looking
|
||||
** for.
|
||||
**
|
||||
** These callback routines are used to implement the following:
|
||||
**
|
||||
** sqlite3ExprIsConstant()
|
||||
** sqlite3ExprIsConstantNotJoin()
|
||||
** sqlite3ExprIsConstantOrFunction()
|
||||
** sqlite3ExprIsConstant() pWalker->eCode==1
|
||||
** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
|
||||
** sqlite3ExprRefOneTableOnly() pWalker->eCode==3
|
||||
** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
|
||||
**
|
||||
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
|
||||
** is found to not be a constant.
|
||||
**
|
||||
** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
|
||||
** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing
|
||||
** an existing schema and 4 when processing a new statement. A bound
|
||||
** parameter raises an error for new statements, but is silently converted
|
||||
** to NULL for existing schemas. This allows sqlite_master tables that
|
||||
** contain a bound parameter because they were generated by older versions
|
||||
** of SQLite to be parsed by newer versions of SQLite without raising a
|
||||
** malformed schema error.
|
||||
*/
|
||||
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
|
||||
/* If pWalker->u.i is 3 then any term of the expression that comes from
|
||||
** the ON or USING clauses of a join disqualifies the expression
|
||||
/* If pWalker->eCode is 2 then any term of the expression that comes from
|
||||
** the ON or USING clauses of a left join disqualifies the expression
|
||||
** from being considered constant. */
|
||||
if( pWalker->u.i==3 && ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
pWalker->u.i = 0;
|
||||
if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
switch( pExpr->op ){
|
||||
/* Consider functions to be constant if all their arguments are constant
|
||||
** and either pWalker->u.i==2 or the function as the SQLITE_FUNC_CONST
|
||||
** flag. */
|
||||
** and either pWalker->eCode==4 or 5 or the function has the
|
||||
** SQLITE_FUNC_CONST flag. */
|
||||
case TK_FUNCTION:
|
||||
if( pWalker->u.i==2 || ExprHasProperty(pExpr,EP_Constant) ){
|
||||
if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_Constant) ){
|
||||
return WRC_Continue;
|
||||
}else{
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
/* Fall through */
|
||||
case TK_ID:
|
||||
case TK_COLUMN:
|
||||
case TK_AGG_FUNCTION:
|
||||
@@ -1248,8 +1263,25 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pExpr->op==TK_COLUMN );
|
||||
testcase( pExpr->op==TK_AGG_FUNCTION );
|
||||
testcase( pExpr->op==TK_AGG_COLUMN );
|
||||
pWalker->u.i = 0;
|
||||
return WRC_Abort;
|
||||
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
|
||||
return WRC_Continue;
|
||||
}else{
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
case TK_VARIABLE:
|
||||
if( pWalker->eCode==5 ){
|
||||
/* Silently convert bound parameters that appear inside of CREATE
|
||||
** statements into a NULL when parsing the CREATE statement text out
|
||||
** of the sqlite_master table */
|
||||
pExpr->op = TK_NULL;
|
||||
}else if( pWalker->eCode==4 ){
|
||||
/* A bound parameter in a CREATE statement that originates from
|
||||
** sqlite3_prepare() causes an error */
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
|
||||
testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
|
||||
@@ -1258,21 +1290,22 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
pWalker->u.i = 0;
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
static int exprIsConst(Expr *p, int initFlag){
|
||||
static int exprIsConst(Expr *p, int initFlag, int iCur){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.u.i = initFlag;
|
||||
w.eCode = initFlag;
|
||||
w.xExprCallback = exprNodeIsConstant;
|
||||
w.xSelectCallback = selectNodeIsConstant;
|
||||
w.u.iCur = iCur;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.u.i;
|
||||
return w.eCode;
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Return 1 if the expression is constant
|
||||
** Walk an expression tree. Return non-zero if the expression is constant
|
||||
** and 0 if it involves variables or function calls.
|
||||
**
|
||||
** For the purposes of this function, a double-quoted string (ex: "abc")
|
||||
@@ -1280,21 +1313,31 @@ static int exprIsConst(Expr *p, int initFlag){
|
||||
** a constant.
|
||||
*/
|
||||
int sqlite3ExprIsConstant(Expr *p){
|
||||
return exprIsConst(p, 1);
|
||||
return exprIsConst(p, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Return 1 if the expression is constant
|
||||
** Walk an expression tree. Return non-zero if the expression is constant
|
||||
** that does no originate from the ON or USING clauses of a join.
|
||||
** Return 0 if it involves variables or function calls or terms from
|
||||
** an ON or USING clause.
|
||||
*/
|
||||
int sqlite3ExprIsConstantNotJoin(Expr *p){
|
||||
return exprIsConst(p, 3);
|
||||
return exprIsConst(p, 2, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Return 1 if the expression is constant
|
||||
** Walk an expression tree. Return non-zero if the expression constant
|
||||
** for any single row of the table with cursor iCur. In other words, the
|
||||
** expression must not refer to any non-deterministic function nor any
|
||||
** table other than iCur.
|
||||
*/
|
||||
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
return exprIsConst(p, 3, iCur);
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Return non-zero if the expression is constant
|
||||
** or a function call with constant arguments. Return and 0 if there
|
||||
** are any variables.
|
||||
**
|
||||
@@ -1302,8 +1345,9 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){
|
||||
** is considered a variable but a single-quoted string (ex: 'abc') is
|
||||
** a constant.
|
||||
*/
|
||||
int sqlite3ExprIsConstantOrFunction(Expr *p){
|
||||
return exprIsConst(p, 2);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
||||
assert( isInit==0 || isInit==1 );
|
||||
return exprIsConst(p, 4+isInit, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1370,7 +1414,8 @@ int sqlite3ExprCanBeNull(const Expr *p){
|
||||
return 0;
|
||||
case TK_COLUMN:
|
||||
assert( p->pTab!=0 );
|
||||
return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0;
|
||||
return ExprHasProperty(p, EP_CanBeNull) ||
|
||||
(p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -1541,7 +1586,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){
|
||||
**
|
||||
** If the RHS of the IN operator is a list or a more complex subquery, then
|
||||
** an ephemeral table might need to be generated from the RHS and then
|
||||
** pX->iTable made to point to the ephermeral table instead of an
|
||||
** pX->iTable made to point to the ephemeral table instead of an
|
||||
** existing table.
|
||||
**
|
||||
** The inFlags parameter must contain exactly one of the bits
|
||||
@@ -1671,7 +1716,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
|
||||
** and IN_INDEX_NOOP is an allowed reply
|
||||
** and the RHS of the IN operator is a list, not a subquery
|
||||
** and the RHS is not contant or has two or fewer terms,
|
||||
** then it is not worth creating an ephermeral table to evaluate
|
||||
** then it is not worth creating an ephemeral table to evaluate
|
||||
** the IN operator so return IN_INDEX_NOOP.
|
||||
*/
|
||||
if( eType==0
|
||||
@@ -1813,7 +1858,6 @@ int sqlite3CodeSubselect(
|
||||
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
|
||||
pSelect->iLimit = 0;
|
||||
testcase( pSelect->selFlags & SF_Distinct );
|
||||
pSelect->selFlags &= ~SF_Distinct;
|
||||
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
|
||||
if( sqlite3Select(pParse, pSelect, &dest) ){
|
||||
sqlite3KeyInfoUnref(pKeyInfo);
|
||||
@@ -1912,6 +1956,7 @@ int sqlite3CodeSubselect(
|
||||
sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
|
||||
if( pExpr->op==TK_SELECT ){
|
||||
dest.eDest = SRT_Mem;
|
||||
dest.iSdst = dest.iSDParm;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm);
|
||||
VdbeComment((v, "Init subquery result"));
|
||||
}else{
|
||||
@@ -2431,16 +2476,9 @@ void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
|
||||
** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
|
||||
*/
|
||||
void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
|
||||
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
int x = p->iReg;
|
||||
if( x>=iFrom && x<iFrom+nReg ){
|
||||
p->iReg += iTo-iFrom;
|
||||
}
|
||||
}
|
||||
sqlite3ExprCacheRemove(pParse, iFrom, nReg);
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
||||
@@ -2595,26 +2633,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
case TK_CAST: {
|
||||
/* Expressions of the form: CAST(pLeft AS token) */
|
||||
int aff, to_op;
|
||||
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
aff = sqlite3AffinityType(pExpr->u.zToken, 0);
|
||||
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
|
||||
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
|
||||
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
|
||||
assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
|
||||
assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
|
||||
assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL );
|
||||
testcase( to_op==OP_ToText );
|
||||
testcase( to_op==OP_ToBlob );
|
||||
testcase( to_op==OP_ToNumeric );
|
||||
testcase( to_op==OP_ToInt );
|
||||
testcase( to_op==OP_ToReal );
|
||||
if( inReg!=target ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
|
||||
inReg = target;
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, to_op, inReg);
|
||||
sqlite3VdbeAddOp2(v, OP_Cast, target,
|
||||
sqlite3AffinityType(pExpr->u.zToken, 0));
|
||||
testcase( usedAsColumnCache(pParse, inReg, inReg) );
|
||||
sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
|
||||
break;
|
||||
@@ -2770,7 +2795,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
}
|
||||
|
||||
/* Attempt a direct implementation of the built-in COALESCE() and
|
||||
** IFNULL() functions. This avoids unnecessary evalation of
|
||||
** IFNULL() functions. This avoids unnecessary evaluation of
|
||||
** arguments past the first non-NULL argument.
|
||||
*/
|
||||
if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
|
||||
@@ -2979,7 +3004,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/* If the column has REAL affinity, it may currently be stored as an
|
||||
** integer. Use OP_RealAffinity to make sure it is really real. */
|
||||
** integer. Use OP_RealAffinity to make sure it is really real.
|
||||
**
|
||||
** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to
|
||||
** floating point when extracting it from the record. */
|
||||
if( pExpr->iColumn>=0
|
||||
&& pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
|
||||
){
|
||||
@@ -3209,7 +3237,7 @@ void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code that evalutes the given expression and puts the result
|
||||
** Generate code that evaluates the given expression and puts the result
|
||||
** in register target.
|
||||
**
|
||||
** Also make a copy of the expression results into another "cache" register
|
||||
@@ -3232,90 +3260,86 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
||||
exprToRegister(pExpr, iMem);
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Generate a human-readable explanation of an expression tree.
|
||||
*/
|
||||
void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
int op; /* The opcode being coded */
|
||||
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
const char *zBinOp = 0; /* Binary operator */
|
||||
const char *zUniOp = 0; /* Unary operator */
|
||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||
if( pExpr==0 ){
|
||||
op = TK_NULL;
|
||||
}else{
|
||||
op = pExpr->op;
|
||||
sqlite3TreeViewLine(pView, "nil");
|
||||
sqlite3TreeViewPop(pView);
|
||||
return;
|
||||
}
|
||||
switch( op ){
|
||||
switch( pExpr->op ){
|
||||
case TK_AGG_COLUMN: {
|
||||
sqlite3ExplainPrintf(pOut, "AGG{%d:%d}",
|
||||
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
|
||||
pExpr->iTable, pExpr->iColumn);
|
||||
break;
|
||||
}
|
||||
case TK_COLUMN: {
|
||||
if( pExpr->iTable<0 ){
|
||||
/* This only happens when coding check constraints */
|
||||
sqlite3ExplainPrintf(pOut, "COLUMN(%d)", pExpr->iColumn);
|
||||
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
|
||||
}else{
|
||||
sqlite3ExplainPrintf(pOut, "{%d:%d}",
|
||||
sqlite3TreeViewLine(pView, "{%d:%d}",
|
||||
pExpr->iTable, pExpr->iColumn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_INTEGER: {
|
||||
if( pExpr->flags & EP_IntValue ){
|
||||
sqlite3ExplainPrintf(pOut, "%d", pExpr->u.iValue);
|
||||
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
|
||||
}else{
|
||||
sqlite3ExplainPrintf(pOut, "%s", pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
case TK_FLOAT: {
|
||||
sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case TK_STRING: {
|
||||
sqlite3ExplainPrintf(pOut,"%Q", pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
|
||||
break;
|
||||
}
|
||||
case TK_NULL: {
|
||||
sqlite3ExplainPrintf(pOut,"NULL");
|
||||
sqlite3TreeViewLine(pView,"NULL");
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||
case TK_BLOB: {
|
||||
sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case TK_VARIABLE: {
|
||||
sqlite3ExplainPrintf(pOut,"VARIABLE(%s,%d)",
|
||||
pExpr->u.zToken, pExpr->iColumn);
|
||||
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
|
||||
pExpr->u.zToken, pExpr->iColumn);
|
||||
break;
|
||||
}
|
||||
case TK_REGISTER: {
|
||||
sqlite3ExplainPrintf(pOut,"REGISTER(%d)", pExpr->iTable);
|
||||
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
|
||||
break;
|
||||
}
|
||||
case TK_AS: {
|
||||
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||
break;
|
||||
}
|
||||
case TK_ID: {
|
||||
sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken);
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
case TK_CAST: {
|
||||
/* Expressions of the form: CAST(pLeft AS token) */
|
||||
const char *zAff = "unk";
|
||||
switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
|
||||
case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
|
||||
case SQLITE_AFF_NONE: zAff = "NONE"; break;
|
||||
case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
|
||||
case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
|
||||
case SQLITE_AFF_REAL: zAff = "REAL"; break;
|
||||
}
|
||||
sqlite3ExplainPrintf(pOut, "CAST-%s(", zAff);
|
||||
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||
sqlite3ExplainPrintf(pOut, ")");
|
||||
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_CAST */
|
||||
@@ -3339,6 +3363,7 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
|
||||
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
|
||||
case TK_CONCAT: zBinOp = "CONCAT"; break;
|
||||
case TK_DOT: zBinOp = "DOT"; break;
|
||||
|
||||
case TK_UMINUS: zUniOp = "UMINUS"; break;
|
||||
case TK_UPLUS: zUniOp = "UPLUS"; break;
|
||||
@@ -3348,8 +3373,8 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
|
||||
|
||||
case TK_COLLATE: {
|
||||
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||
sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3361,41 +3386,36 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
}else{
|
||||
pFarg = pExpr->x.pList;
|
||||
}
|
||||
if( op==TK_AGG_FUNCTION ){
|
||||
sqlite3ExplainPrintf(pOut, "AGG_FUNCTION%d:%s(",
|
||||
if( pExpr->op==TK_AGG_FUNCTION ){
|
||||
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
|
||||
pExpr->op2, pExpr->u.zToken);
|
||||
}else{
|
||||
sqlite3ExplainPrintf(pOut, "FUNCTION:%s(", pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
|
||||
}
|
||||
if( pFarg ){
|
||||
sqlite3ExplainExprList(pOut, pFarg);
|
||||
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
|
||||
}
|
||||
sqlite3ExplainPrintf(pOut, ")");
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
case TK_EXISTS: {
|
||||
sqlite3ExplainPrintf(pOut, "EXISTS(");
|
||||
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
|
||||
sqlite3ExplainPrintf(pOut,")");
|
||||
sqlite3TreeViewLine(pView, "EXISTS-expr");
|
||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||
break;
|
||||
}
|
||||
case TK_SELECT: {
|
||||
sqlite3ExplainPrintf(pOut, "(");
|
||||
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
|
||||
sqlite3ExplainPrintf(pOut, ")");
|
||||
sqlite3TreeViewLine(pView, "SELECT-expr");
|
||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||
break;
|
||||
}
|
||||
case TK_IN: {
|
||||
sqlite3ExplainPrintf(pOut, "IN(");
|
||||
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||
sqlite3ExplainPrintf(pOut, ",");
|
||||
sqlite3TreeViewLine(pView, "IN");
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
|
||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||
}else{
|
||||
sqlite3ExplainExprList(pOut, pExpr->x.pList);
|
||||
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
||||
}
|
||||
sqlite3ExplainPrintf(pOut, ")");
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||
@@ -3415,13 +3435,10 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
Expr *pX = pExpr->pLeft;
|
||||
Expr *pY = pExpr->x.pList->a[0].pExpr;
|
||||
Expr *pZ = pExpr->x.pList->a[1].pExpr;
|
||||
sqlite3ExplainPrintf(pOut, "BETWEEN(");
|
||||
sqlite3ExplainExpr(pOut, pX);
|
||||
sqlite3ExplainPrintf(pOut, ",");
|
||||
sqlite3ExplainExpr(pOut, pY);
|
||||
sqlite3ExplainPrintf(pOut, ",");
|
||||
sqlite3ExplainExpr(pOut, pZ);
|
||||
sqlite3ExplainPrintf(pOut, ")");
|
||||
sqlite3TreeViewLine(pView, "BETWEEN");
|
||||
sqlite3TreeViewExpr(pView, pX, 1);
|
||||
sqlite3TreeViewExpr(pView, pY, 1);
|
||||
sqlite3TreeViewExpr(pView, pZ, 0);
|
||||
break;
|
||||
}
|
||||
case TK_TRIGGER: {
|
||||
@@ -3432,15 +3449,14 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
** is set to the column of the pseudo-table to read, or to -1 to
|
||||
** read the rowid field.
|
||||
*/
|
||||
sqlite3ExplainPrintf(pOut, "%s(%d)",
|
||||
sqlite3TreeViewLine(pView, "%s(%d)",
|
||||
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
|
||||
break;
|
||||
}
|
||||
case TK_CASE: {
|
||||
sqlite3ExplainPrintf(pOut, "CASE(");
|
||||
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||
sqlite3ExplainPrintf(pOut, ",");
|
||||
sqlite3ExplainExprList(pOut, pExpr->x.pList);
|
||||
sqlite3TreeViewLine(pView, "CASE");
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
@@ -3452,55 +3468,57 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
case OE_Fail: zType = "fail"; break;
|
||||
case OE_Ignore: zType = "ignore"; break;
|
||||
}
|
||||
sqlite3ExplainPrintf(pOut, "RAISE-%s(%s)", zType, pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( zBinOp ){
|
||||
sqlite3ExplainPrintf(pOut,"%s(", zBinOp);
|
||||
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||
sqlite3ExplainPrintf(pOut,",");
|
||||
sqlite3ExplainExpr(pOut, pExpr->pRight);
|
||||
sqlite3ExplainPrintf(pOut,")");
|
||||
sqlite3TreeViewLine(pView, "%s", zBinOp);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
||||
}else if( zUniOp ){
|
||||
sqlite3ExplainPrintf(pOut,"%s(", zUniOp);
|
||||
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||
sqlite3ExplainPrintf(pOut,")");
|
||||
sqlite3TreeViewLine(pView, "%s", zUniOp);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Generate a human-readable explanation of an expression list.
|
||||
*/
|
||||
void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
|
||||
void sqlite3TreeViewExprList(
|
||||
TreeView *pView,
|
||||
const ExprList *pList,
|
||||
u8 moreToFollow,
|
||||
const char *zLabel
|
||||
){
|
||||
int i;
|
||||
if( pList==0 || pList->nExpr==0 ){
|
||||
sqlite3ExplainPrintf(pOut, "(empty-list)");
|
||||
return;
|
||||
}else if( pList->nExpr==1 ){
|
||||
sqlite3ExplainExpr(pOut, pList->a[0].pExpr);
|
||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
|
||||
if( pList==0 ){
|
||||
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
|
||||
}else{
|
||||
sqlite3ExplainPush(pOut);
|
||||
sqlite3TreeViewLine(pView, "%s", zLabel);
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
|
||||
sqlite3ExplainPush(pOut);
|
||||
sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
|
||||
sqlite3ExplainPop(pOut);
|
||||
if( pList->a[i].zName ){
|
||||
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
|
||||
#if 0
|
||||
if( pList->a[i].zName ){
|
||||
sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
|
||||
}
|
||||
if( pList->a[i].bSpanIsTab ){
|
||||
sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
|
||||
}
|
||||
if( i<pList->nExpr-1 ){
|
||||
sqlite3ExplainNL(pOut);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sqlite3ExplainPop(pOut);
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
@@ -3564,7 +3582,7 @@ int sqlite3ExprCodeExprList(
|
||||
** x>=y AND x<=z
|
||||
**
|
||||
** Code it as such, taking care to do the common subexpression
|
||||
** elementation of x.
|
||||
** elimination of x.
|
||||
*/
|
||||
static void exprCodeBetween(
|
||||
Parse *pParse, /* Parsing and code generating context */
|
||||
@@ -4051,10 +4069,11 @@ static int exprSrcCount(Walker *pWalker, Expr *pExpr){
|
||||
int i;
|
||||
struct SrcCount *p = pWalker->u.pSrcCount;
|
||||
SrcList *pSrc = p->pSrc;
|
||||
for(i=0; i<pSrc->nSrc; i++){
|
||||
int nSrc = pSrc ? pSrc->nSrc : 0;
|
||||
for(i=0; i<nSrc; i++){
|
||||
if( pExpr->iTable==pSrc->a[i].iCursor ) break;
|
||||
}
|
||||
if( i<pSrc->nSrc ){
|
||||
if( i<nSrc ){
|
||||
p->nThis++;
|
||||
}else{
|
||||
p->nOther++;
|
||||
@@ -4301,7 +4320,7 @@ int sqlite3GetTempReg(Parse *pParse){
|
||||
** purpose.
|
||||
**
|
||||
** If a register is currently being used by the column cache, then
|
||||
** the dallocation is deferred until the column cache line that uses
|
||||
** the deallocation is deferred until the column cache line that uses
|
||||
** the register becomes stale.
|
||||
*/
|
||||
void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
|
||||
|
||||
+63
-25
@@ -173,7 +173,7 @@
|
||||
**
|
||||
** 4) No parent key columns were provided explicitly as part of the
|
||||
** foreign key definition, and the PRIMARY KEY of the parent table
|
||||
** consists of a a different number of columns to the child key in
|
||||
** consists of a different number of columns to the child key in
|
||||
** the child table.
|
||||
**
|
||||
** then non-zero is returned, and a "foreign key mismatch" error loaded
|
||||
@@ -437,7 +437,7 @@ static void fkLookupParent(
|
||||
OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
|
||||
}else{
|
||||
if( nIncr>0 && pFKey->isDeferred==0 ){
|
||||
sqlite3ParseToplevel(pParse)->mayAbort = 1;
|
||||
sqlite3MayAbort(pParse);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
|
||||
}
|
||||
@@ -509,6 +509,10 @@ static Expr *exprTableColumn(
|
||||
** code for an SQL UPDATE operation, this function may be called twice -
|
||||
** once to "delete" the old row and once to "insert" the new row.
|
||||
**
|
||||
** Parameter nIncr is passed -1 when inserting a row (as this may decrease
|
||||
** the number of FK violations in the db) or +1 when deleting one (as this
|
||||
** may increase the number of FK constraint problems).
|
||||
**
|
||||
** The code generated by this function scans through the rows in the child
|
||||
** table that correspond to the parent table row being deleted or inserted.
|
||||
** For each child row found, one of the following actions is taken:
|
||||
@@ -625,13 +629,9 @@ static void fkScanChildren(
|
||||
sqlite3ResolveExprNames(&sNameContext, pWhere);
|
||||
|
||||
/* Create VDBE to loop through the entries in pSrc that match the WHERE
|
||||
** clause. If the constraint is not deferred, throw an exception for
|
||||
** each row found. Otherwise, for deferred constraints, increment the
|
||||
** deferred constraint counter by nIncr for each row selected. */
|
||||
** clause. For each row found, increment either the deferred or immediate
|
||||
** foreign key constraint counter. */
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
|
||||
if( nIncr>0 && pFKey->isDeferred==0 ){
|
||||
sqlite3ParseToplevel(pParse)->mayAbort = 1;
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
|
||||
if( pWInfo ){
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
@@ -659,8 +659,7 @@ static void fkScanChildren(
|
||||
** table).
|
||||
*/
|
||||
FKey *sqlite3FkReferences(Table *pTab){
|
||||
int nName = sqlite3Strlen30(pTab->zName);
|
||||
return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName);
|
||||
return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -811,6 +810,24 @@ static int fkParentIsModified(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the parser passed as the first argument is being
|
||||
** used to code a trigger that is really a "SET NULL" action belonging
|
||||
** to trigger pFKey.
|
||||
*/
|
||||
static int isSetNullAction(Parse *pParse, FKey *pFKey){
|
||||
Parse *pTop = sqlite3ParseToplevel(pParse);
|
||||
if( pTop->pTriggerPrg ){
|
||||
Trigger *p = pTop->pTriggerPrg->pTrigger;
|
||||
if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull)
|
||||
|| (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull)
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called when inserting, deleting or updating a row of
|
||||
** table pTab to generate VDBE code to perform foreign key constraint
|
||||
@@ -863,7 +880,7 @@ void sqlite3FkCheck(
|
||||
int *aiCol;
|
||||
int iCol;
|
||||
int i;
|
||||
int isIgnore = 0;
|
||||
int bIgnore = 0;
|
||||
|
||||
if( aChange
|
||||
&& sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
|
||||
@@ -922,7 +939,7 @@ void sqlite3FkCheck(
|
||||
int rcauth;
|
||||
char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
|
||||
rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
|
||||
isIgnore = (rcauth==SQLITE_IGNORE);
|
||||
bIgnore = (rcauth==SQLITE_IGNORE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -937,12 +954,18 @@ void sqlite3FkCheck(
|
||||
/* A row is being removed from the child table. Search for the parent.
|
||||
** If the parent does not exist, removing the child row resolves an
|
||||
** outstanding foreign key constraint violation. */
|
||||
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
|
||||
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore);
|
||||
}
|
||||
if( regNew!=0 ){
|
||||
if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){
|
||||
/* A row is being added to the child table. If a parent row cannot
|
||||
** be found, adding the child row has violated the FK constraint. */
|
||||
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
|
||||
** be found, adding the child row has violated the FK constraint.
|
||||
**
|
||||
** If this operation is being performed as part of a trigger program
|
||||
** that is actually a "SET NULL" action belonging to this very
|
||||
** foreign key, then omit this scan altogether. As all child key
|
||||
** values are guaranteed to be NULL, it is not possible for adding
|
||||
** this row to cause an FK violation. */
|
||||
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore);
|
||||
}
|
||||
|
||||
sqlite3DbFree(db, aiFree);
|
||||
@@ -963,8 +986,8 @@ void sqlite3FkCheck(
|
||||
&& !pParse->pToplevel && !pParse->isMultiWrite
|
||||
){
|
||||
assert( regOld==0 && regNew!=0 );
|
||||
/* Inserting a single row into a parent table cannot cause an immediate
|
||||
** foreign key violation. So do nothing in this case. */
|
||||
/* Inserting a single row into a parent table cannot cause (or fix)
|
||||
** an immediate foreign key violation. So do nothing in this case. */
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -988,13 +1011,28 @@ void sqlite3FkCheck(
|
||||
fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
|
||||
}
|
||||
if( regOld!=0 ){
|
||||
/* If there is a RESTRICT action configured for the current operation
|
||||
** on the parent table of this FK, then throw an exception
|
||||
** immediately if the FK constraint is violated, even if this is a
|
||||
** deferred trigger. That's what RESTRICT means. To defer checking
|
||||
** the constraint, the FK should specify NO ACTION (represented
|
||||
** using OE_None). NO ACTION is the default. */
|
||||
int eAction = pFKey->aAction[aChange!=0];
|
||||
fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);
|
||||
/* If this is a deferred FK constraint, or a CASCADE or SET NULL
|
||||
** action applies, then any foreign key violations caused by
|
||||
** removing the parent key will be rectified by the action trigger.
|
||||
** So do not set the "may-abort" flag in this case.
|
||||
**
|
||||
** Note 1: If the FK is declared "ON UPDATE CASCADE", then the
|
||||
** may-abort flag will eventually be set on this statement anyway
|
||||
** (when this function is called as part of processing the UPDATE
|
||||
** within the action trigger).
|
||||
**
|
||||
** Note 2: At first glance it may seem like SQLite could simply omit
|
||||
** all OP_FkCounter related scans when either CASCADE or SET NULL
|
||||
** applies. The trouble starts if the CASCADE or SET NULL action
|
||||
** trigger causes other triggers or action rules attached to the
|
||||
** child table to fire. In these cases the fk constraint counters
|
||||
** might be set incorrectly if any OP_FkCounter related scans are
|
||||
** omitted. */
|
||||
if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){
|
||||
sqlite3MayAbort(pParse);
|
||||
}
|
||||
}
|
||||
pItem->zName = 0;
|
||||
sqlite3SrcListDelete(db, pSrc);
|
||||
@@ -1338,7 +1376,7 @@ void sqlite3FkDelete(sqlite3 *db, Table *pTab){
|
||||
}else{
|
||||
void *p = (void *)pFKey->pNextTo;
|
||||
const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo);
|
||||
sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p);
|
||||
sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p);
|
||||
}
|
||||
if( pFKey->pNextTo ){
|
||||
pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
|
||||
|
||||
+143
-104
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains the C-language implementions for many of the SQL
|
||||
** This file contains the C-language implementations for many of the SQL
|
||||
** functions of SQLite. (Some function, and in particular the date and
|
||||
** time functions, are implemented separately.)
|
||||
*/
|
||||
@@ -22,7 +22,10 @@
|
||||
** Return the collating function associated with a function.
|
||||
*/
|
||||
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
|
||||
return context->pColl;
|
||||
VdbeOp *pOp = &context->pVdbe->aOp[context->iOp-1];
|
||||
assert( pOp->opcode==OP_CollSeq );
|
||||
assert( pOp->p4type==P4_COLLSEQ );
|
||||
return pOp->p4.pColl;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -154,8 +157,8 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
default: {
|
||||
/* Because sqlite3_value_double() returns 0.0 if the argument is not
|
||||
** something that can be converted into a number, we have:
|
||||
** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that
|
||||
** cannot be converted to a numeric value.
|
||||
** IMP: R-01992-00519 Abs(X) returns 0.0 if X is a string or blob
|
||||
** that cannot be converted to a numeric value.
|
||||
*/
|
||||
double rVal = sqlite3_value_double(argv[0]);
|
||||
if( rVal<0 ) rVal = -rVal;
|
||||
@@ -325,13 +328,14 @@ static void substrFunc(
|
||||
for(z2=z; *z2 && p2; p2--){
|
||||
SQLITE_SKIP_UTF8(z2);
|
||||
}
|
||||
sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT);
|
||||
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
|
||||
SQLITE_UTF8);
|
||||
}else{
|
||||
if( p1+p2>len ){
|
||||
p2 = len-p1;
|
||||
if( p2<0 ) p2 = 0;
|
||||
}
|
||||
sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT);
|
||||
sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,7 +394,7 @@ static void *contextMalloc(sqlite3_context *context, i64 nByte){
|
||||
sqlite3_result_error_toobig(context);
|
||||
z = 0;
|
||||
}else{
|
||||
z = sqlite3Malloc((int)nByte);
|
||||
z = sqlite3Malloc(nByte);
|
||||
if( !z ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}
|
||||
@@ -566,10 +570,12 @@ struct compareInfo {
|
||||
** whereas only characters less than 0x80 do in ASCII.
|
||||
*/
|
||||
#if defined(SQLITE_EBCDIC)
|
||||
# define sqlite3Utf8Read(A) (*((*A)++))
|
||||
# define GlobUpperToLower(A) A = sqlite3UpperToLower[A]
|
||||
# define sqlite3Utf8Read(A) (*((*A)++))
|
||||
# define GlobUpperToLower(A) A = sqlite3UpperToLower[A]
|
||||
# define GlobUpperToLowerAscii(A) A = sqlite3UpperToLower[A]
|
||||
#else
|
||||
# define GlobUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
|
||||
# define GlobUpperToLower(A) if( A<=0x7f ){ A = sqlite3UpperToLower[A]; }
|
||||
# define GlobUpperToLowerAscii(A) A = sqlite3UpperToLower[A]
|
||||
#endif
|
||||
|
||||
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
|
||||
@@ -582,7 +588,7 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
|
||||
|
||||
/*
|
||||
** Compare two UTF-8 strings for equality where the first string can
|
||||
** potentially be a "glob" expression. Return true (1) if they
|
||||
** potentially be a "glob" or "like" expression. Return true (1) if they
|
||||
** are the same and false (0) if they are different.
|
||||
**
|
||||
** Globbing rules:
|
||||
@@ -602,11 +608,18 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
|
||||
** "[a-z]" matches any single lower-case letter. To match a '-', make
|
||||
** it the last character in the list.
|
||||
**
|
||||
** Like matching rules:
|
||||
**
|
||||
** '%' Matches any sequence of zero or more characters
|
||||
**
|
||||
*** '_' Matches any one character
|
||||
**
|
||||
** Ec Where E is the "esc" character and c is any other
|
||||
** character, including '%', '_', and esc, match exactly c.
|
||||
**
|
||||
** The comments through this routine usually assume glob matching.
|
||||
**
|
||||
** This routine is usually quick, but can be N**2 in the worst case.
|
||||
**
|
||||
** Hints: to match '*' or '?', put them in "[]". Like this:
|
||||
**
|
||||
** abc[*]xyz Matches "abc*xyz" only
|
||||
*/
|
||||
static int patternCompare(
|
||||
const u8 *zPattern, /* The glob pattern */
|
||||
@@ -614,17 +627,25 @@ static int patternCompare(
|
||||
const struct compareInfo *pInfo, /* Information about how to do the compare */
|
||||
u32 esc /* The escape character */
|
||||
){
|
||||
u32 c, c2;
|
||||
int invert;
|
||||
int seen;
|
||||
u8 matchOne = pInfo->matchOne;
|
||||
u8 matchAll = pInfo->matchAll;
|
||||
u8 matchSet = pInfo->matchSet;
|
||||
u8 noCase = pInfo->noCase;
|
||||
int prevEscape = 0; /* True if the previous character was 'escape' */
|
||||
u32 c, c2; /* Next pattern and input string chars */
|
||||
u32 matchOne = pInfo->matchOne; /* "?" or "_" */
|
||||
u32 matchAll = pInfo->matchAll; /* "*" or "%" */
|
||||
u32 matchOther; /* "[" or the escape character */
|
||||
u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
|
||||
const u8 *zEscaped = 0; /* One past the last escaped input char */
|
||||
|
||||
/* The GLOB operator does not have an ESCAPE clause. And LIKE does not
|
||||
** have the matchSet operator. So we either have to look for one or
|
||||
** the other, never both. Hence the single variable matchOther is used
|
||||
** to store the one we have to look for.
|
||||
*/
|
||||
matchOther = esc ? esc : pInfo->matchSet;
|
||||
|
||||
while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
|
||||
if( c==matchAll && !prevEscape ){
|
||||
if( c==matchAll ){ /* Match "*" */
|
||||
/* Skip over multiple "*" characters in the pattern. If there
|
||||
** are also "?" characters, skip those as well, but consume a
|
||||
** single character of the input string for each "?" skipped */
|
||||
while( (c=sqlite3Utf8Read(&zPattern)) == matchAll
|
||||
|| c == matchOne ){
|
||||
if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
|
||||
@@ -632,86 +653,98 @@ static int patternCompare(
|
||||
}
|
||||
}
|
||||
if( c==0 ){
|
||||
return 1;
|
||||
}else if( c==esc ){
|
||||
c = sqlite3Utf8Read(&zPattern);
|
||||
if( c==0 ){
|
||||
return 0;
|
||||
}
|
||||
}else if( c==matchSet ){
|
||||
assert( esc==0 ); /* This is GLOB, not LIKE */
|
||||
assert( matchSet<0x80 ); /* '[' is a single-byte character */
|
||||
while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
|
||||
SQLITE_SKIP_UTF8(zString);
|
||||
}
|
||||
return *zString!=0;
|
||||
}
|
||||
while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
|
||||
if( noCase ){
|
||||
GlobUpperToLower(c2);
|
||||
GlobUpperToLower(c);
|
||||
while( c2 != 0 && c2 != c ){
|
||||
c2 = sqlite3Utf8Read(&zString);
|
||||
GlobUpperToLower(c2);
|
||||
}
|
||||
return 1; /* "*" at the end of the pattern matches */
|
||||
}else if( c==matchOther ){
|
||||
if( esc ){
|
||||
c = sqlite3Utf8Read(&zPattern);
|
||||
if( c==0 ) return 0;
|
||||
}else{
|
||||
while( c2 != 0 && c2 != c ){
|
||||
c2 = sqlite3Utf8Read(&zString);
|
||||
/* "[...]" immediately follows the "*". We have to do a slow
|
||||
** recursive search in this case, but it is an unusual case. */
|
||||
assert( matchOther<0x80 ); /* '[' is a single-byte character */
|
||||
while( *zString
|
||||
&& patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
|
||||
SQLITE_SKIP_UTF8(zString);
|
||||
}
|
||||
return *zString!=0;
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point variable c contains the first character of the
|
||||
** pattern string past the "*". Search in the input string for the
|
||||
** first matching character and recursively contine the match from
|
||||
** that point.
|
||||
**
|
||||
** For a case-insensitive search, set variable cx to be the same as
|
||||
** c but in the other case and search the input string for either
|
||||
** c or cx.
|
||||
*/
|
||||
if( c<=0x80 ){
|
||||
u32 cx;
|
||||
if( noCase ){
|
||||
cx = sqlite3Toupper(c);
|
||||
c = sqlite3Tolower(c);
|
||||
}else{
|
||||
cx = c;
|
||||
}
|
||||
while( (c2 = *(zString++))!=0 ){
|
||||
if( c2!=c && c2!=cx ) continue;
|
||||
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
||||
}
|
||||
}else{
|
||||
while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
|
||||
if( c2!=c ) continue;
|
||||
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
||||
}
|
||||
if( c2==0 ) return 0;
|
||||
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}else if( c==matchOne && !prevEscape ){
|
||||
if( sqlite3Utf8Read(&zString)==0 ){
|
||||
return 0;
|
||||
}
|
||||
}else if( c==matchSet ){
|
||||
u32 prior_c = 0;
|
||||
assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
|
||||
seen = 0;
|
||||
invert = 0;
|
||||
c = sqlite3Utf8Read(&zString);
|
||||
if( c==0 ) return 0;
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
if( c2=='^' ){
|
||||
invert = 1;
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
}
|
||||
if( c2==']' ){
|
||||
if( c==']' ) seen = 1;
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
}
|
||||
while( c2 && c2!=']' ){
|
||||
if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
if( c>=prior_c && c<=c2 ) seen = 1;
|
||||
prior_c = 0;
|
||||
}else{
|
||||
if( c==c2 ){
|
||||
seen = 1;
|
||||
}
|
||||
prior_c = c2;
|
||||
}
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
}
|
||||
if( c2==0 || (seen ^ invert)==0 ){
|
||||
return 0;
|
||||
}
|
||||
}else if( esc==c && !prevEscape ){
|
||||
prevEscape = 1;
|
||||
}else{
|
||||
c2 = sqlite3Utf8Read(&zString);
|
||||
if( noCase ){
|
||||
GlobUpperToLower(c);
|
||||
GlobUpperToLower(c2);
|
||||
}
|
||||
if( c!=c2 ){
|
||||
return 0;
|
||||
}
|
||||
prevEscape = 0;
|
||||
}
|
||||
if( c==matchOther ){
|
||||
if( esc ){
|
||||
c = sqlite3Utf8Read(&zPattern);
|
||||
if( c==0 ) return 0;
|
||||
zEscaped = zPattern;
|
||||
}else{
|
||||
u32 prior_c = 0;
|
||||
int seen = 0;
|
||||
int invert = 0;
|
||||
c = sqlite3Utf8Read(&zString);
|
||||
if( c==0 ) return 0;
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
if( c2=='^' ){
|
||||
invert = 1;
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
}
|
||||
if( c2==']' ){
|
||||
if( c==']' ) seen = 1;
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
}
|
||||
while( c2 && c2!=']' ){
|
||||
if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
if( c>=prior_c && c<=c2 ) seen = 1;
|
||||
prior_c = 0;
|
||||
}else{
|
||||
if( c==c2 ){
|
||||
seen = 1;
|
||||
}
|
||||
prior_c = c2;
|
||||
}
|
||||
c2 = sqlite3Utf8Read(&zPattern);
|
||||
}
|
||||
if( c2==0 || (seen ^ invert)==0 ){
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c2 = sqlite3Utf8Read(&zString);
|
||||
if( c==c2 ) continue;
|
||||
if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
|
||||
continue;
|
||||
}
|
||||
if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
|
||||
return 0;
|
||||
}
|
||||
return *zString==0;
|
||||
}
|
||||
@@ -1041,7 +1074,7 @@ static void charFunc(
|
||||
*zOut++ = 0x80 + (u8)(c & 0x3F);
|
||||
} \
|
||||
}
|
||||
sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free);
|
||||
sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1491,6 +1524,7 @@ static void minmaxStep(
|
||||
sqlite3SkipAccumulatorLoad(context);
|
||||
}
|
||||
}else{
|
||||
pBest->db = sqlite3_context_db_handle(context);
|
||||
sqlite3VdbeMemCopy(pBest, pArg);
|
||||
}
|
||||
}
|
||||
@@ -1652,7 +1686,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
||||
}
|
||||
|
||||
/*
|
||||
** All all of the FuncDef structures in the aBuiltinFunc[] array above
|
||||
** All of the FuncDef structures in the aBuiltinFunc[] array above
|
||||
** to the global function hash table. This occurs at start-time (as
|
||||
** a consequence of calling sqlite3_initialize()).
|
||||
**
|
||||
@@ -1676,10 +1710,12 @@ void sqlite3RegisterGlobalFunctions(void){
|
||||
FUNCTION(trim, 2, 3, 0, trimFunc ),
|
||||
FUNCTION(min, -1, 0, 1, minmaxFunc ),
|
||||
FUNCTION(min, 0, 0, 1, 0 ),
|
||||
AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
|
||||
AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize,
|
||||
SQLITE_FUNC_MINMAX ),
|
||||
FUNCTION(max, -1, 1, 1, minmaxFunc ),
|
||||
FUNCTION(max, 0, 1, 1, 0 ),
|
||||
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
|
||||
AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize,
|
||||
SQLITE_FUNC_MINMAX ),
|
||||
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
|
||||
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
|
||||
FUNCTION(instr, 2, 0, 0, instrFunc ),
|
||||
@@ -1709,6 +1745,9 @@ void sqlite3RegisterGlobalFunctions(void){
|
||||
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
|
||||
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
|
||||
FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
|
||||
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
|
||||
@@ -1729,8 +1768,8 @@ void sqlite3RegisterGlobalFunctions(void){
|
||||
AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
|
||||
AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
|
||||
AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
|
||||
/* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */
|
||||
{0,SQLITE_UTF8|SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
|
||||
AGGREGATE2(count, 0, 0, 0, countStep, countFinalize,
|
||||
SQLITE_FUNC_COUNT ),
|
||||
AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
|
||||
AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
|
||||
AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
|
||||
|
||||
+26
-3
@@ -10,7 +10,7 @@
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file contains definitions of global variables and contants.
|
||||
** This file contains definitions of global variables and constants.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -129,14 +129,36 @@ const unsigned char sqlite3CtypeMap[256] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards
|
||||
** compatibility for legacy applications, the URI filename capability is
|
||||
** disabled by default.
|
||||
**
|
||||
** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled
|
||||
** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options.
|
||||
**
|
||||
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
|
||||
** disabled. The default value may be changed by compiling with the
|
||||
** SQLITE_USE_URI symbol defined.
|
||||
*/
|
||||
#ifndef SQLITE_USE_URI
|
||||
# define SQLITE_USE_URI 0
|
||||
#endif
|
||||
|
||||
/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
|
||||
** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
|
||||
** that compile-time option is omitted.
|
||||
*/
|
||||
#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
|
||||
# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
|
||||
#endif
|
||||
|
||||
/* The minimum PMA size is set to this value multiplied by the database
|
||||
** page size in bytes.
|
||||
*/
|
||||
#ifndef SQLITE_SORTER_PMASZ
|
||||
# define SQLITE_SORTER_PMASZ 250
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following singleton contains the global configuration for
|
||||
** the SQLite library.
|
||||
@@ -167,6 +189,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
0, /* nPage */
|
||||
0, /* mxParserStack */
|
||||
0, /* sharedCacheEnabled */
|
||||
SQLITE_SORTER_PMASZ, /* szPma */
|
||||
/* All the rest should always be initialized to zero */
|
||||
0, /* isInit */
|
||||
0, /* inProgress */
|
||||
@@ -222,8 +245,8 @@ const Token sqlite3IntTokens[] = {
|
||||
**
|
||||
** IMPORTANT: Changing the pending byte to any value other than
|
||||
** 0x40000000 results in an incompatible database file format!
|
||||
** Changing the pending byte during operating results in undefined
|
||||
** and dileterious behavior.
|
||||
** Changing the pending byte during operation will result in undefined
|
||||
** and incorrect behavior.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_WSD
|
||||
int sqlite3PendingByte = 0x40000000;
|
||||
|
||||
+26
-40
@@ -52,12 +52,11 @@ void sqlite3HashClear(Hash *pH){
|
||||
/*
|
||||
** The hashing function.
|
||||
*/
|
||||
static unsigned int strHash(const char *z, int nKey){
|
||||
static unsigned int strHash(const char *z){
|
||||
unsigned int h = 0;
|
||||
assert( nKey>=0 );
|
||||
while( nKey > 0 ){
|
||||
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
|
||||
nKey--;
|
||||
unsigned char c;
|
||||
while( (c = (unsigned char)*z++)!=0 ){
|
||||
h = (h<<3) ^ h ^ sqlite3UpperToLower[c];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
@@ -129,7 +128,7 @@ static int rehash(Hash *pH, unsigned int new_size){
|
||||
pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
|
||||
memset(new_ht, 0, new_size*sizeof(struct _ht));
|
||||
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
|
||||
unsigned int h = strHash(elem->pKey, elem->nKey) % new_size;
|
||||
unsigned int h = strHash(elem->pKey) % new_size;
|
||||
next_elem = elem->next;
|
||||
insertElement(pH, &new_ht[h], elem);
|
||||
}
|
||||
@@ -137,28 +136,33 @@ static int rehash(Hash *pH, unsigned int new_size){
|
||||
}
|
||||
|
||||
/* This function (for internal use only) locates an element in an
|
||||
** hash table that matches the given key. The hash for this key has
|
||||
** already been computed and is passed as the 4th parameter.
|
||||
** hash table that matches the given key. The hash for this key is
|
||||
** also computed and returned in the *pH parameter.
|
||||
*/
|
||||
static HashElem *findElementGivenHash(
|
||||
static HashElem *findElementWithHash(
|
||||
const Hash *pH, /* The pH to be searched */
|
||||
const char *pKey, /* The key we are searching for */
|
||||
int nKey, /* Bytes in key (not counting zero terminator) */
|
||||
unsigned int h /* The hash for this key. */
|
||||
unsigned int *pHash /* Write the hash value here */
|
||||
){
|
||||
HashElem *elem; /* Used to loop thru the element list */
|
||||
int count; /* Number of elements left to test */
|
||||
unsigned int h; /* The computed hash */
|
||||
|
||||
if( pH->ht ){
|
||||
struct _ht *pEntry = &pH->ht[h];
|
||||
struct _ht *pEntry;
|
||||
h = strHash(pKey) % pH->htsize;
|
||||
pEntry = &pH->ht[h];
|
||||
elem = pEntry->chain;
|
||||
count = pEntry->count;
|
||||
}else{
|
||||
h = 0;
|
||||
elem = pH->first;
|
||||
count = pH->count;
|
||||
}
|
||||
while( count-- && ALWAYS(elem) ){
|
||||
if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
|
||||
*pHash = h;
|
||||
while( count-- ){
|
||||
assert( elem!=0 );
|
||||
if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
|
||||
return elem;
|
||||
}
|
||||
elem = elem->next;
|
||||
@@ -201,26 +205,20 @@ static void removeElementGivenHash(
|
||||
}
|
||||
|
||||
/* Attempt to locate an element of the hash table pH with a key
|
||||
** that matches pKey,nKey. Return the data for this element if it is
|
||||
** that matches pKey. Return the data for this element if it is
|
||||
** found, or NULL if there is no match.
|
||||
*/
|
||||
void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
|
||||
void *sqlite3HashFind(const Hash *pH, const char *pKey){
|
||||
HashElem *elem; /* The element that matches key */
|
||||
unsigned int h; /* A hash on key */
|
||||
|
||||
assert( pH!=0 );
|
||||
assert( pKey!=0 );
|
||||
assert( nKey>=0 );
|
||||
if( pH->ht ){
|
||||
h = strHash(pKey, nKey) % pH->htsize;
|
||||
}else{
|
||||
h = 0;
|
||||
}
|
||||
elem = findElementGivenHash(pH, pKey, nKey, h);
|
||||
elem = findElementWithHash(pH, pKey, &h);
|
||||
return elem ? elem->data : 0;
|
||||
}
|
||||
|
||||
/* Insert an element into the hash table pH. The key is pKey,nKey
|
||||
/* Insert an element into the hash table pH. The key is pKey
|
||||
** and the data is "data".
|
||||
**
|
||||
** If no element exists with a matching key, then a new
|
||||
@@ -234,20 +232,14 @@ void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
|
||||
** If the "data" parameter to this function is NULL, then the
|
||||
** element corresponding to "key" is removed from the hash table.
|
||||
*/
|
||||
void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
|
||||
void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
|
||||
unsigned int h; /* the hash of the key modulo hash table size */
|
||||
HashElem *elem; /* Used to loop thru the element list */
|
||||
HashElem *new_elem; /* New element added to the pH */
|
||||
|
||||
assert( pH!=0 );
|
||||
assert( pKey!=0 );
|
||||
assert( nKey>=0 );
|
||||
if( pH->htsize ){
|
||||
h = strHash(pKey, nKey) % pH->htsize;
|
||||
}else{
|
||||
h = 0;
|
||||
}
|
||||
elem = findElementGivenHash(pH,pKey,nKey,h);
|
||||
elem = findElementWithHash(pH,pKey,&h);
|
||||
if( elem ){
|
||||
void *old_data = elem->data;
|
||||
if( data==0 ){
|
||||
@@ -255,7 +247,6 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
|
||||
}else{
|
||||
elem->data = data;
|
||||
elem->pKey = pKey;
|
||||
assert(nKey==elem->nKey);
|
||||
}
|
||||
return old_data;
|
||||
}
|
||||
@@ -263,19 +254,14 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
|
||||
new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
|
||||
if( new_elem==0 ) return data;
|
||||
new_elem->pKey = pKey;
|
||||
new_elem->nKey = nKey;
|
||||
new_elem->data = data;
|
||||
pH->count++;
|
||||
if( pH->count>=10 && pH->count > 2*pH->htsize ){
|
||||
if( rehash(pH, pH->count*2) ){
|
||||
assert( pH->htsize>0 );
|
||||
h = strHash(pKey, nKey) % pH->htsize;
|
||||
h = strHash(pKey) % pH->htsize;
|
||||
}
|
||||
}
|
||||
if( pH->ht ){
|
||||
insertElement(pH, &pH->ht[h], new_elem);
|
||||
}else{
|
||||
insertElement(pH, 0, new_elem);
|
||||
}
|
||||
insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+3
-3
@@ -59,15 +59,15 @@ struct Hash {
|
||||
struct HashElem {
|
||||
HashElem *next, *prev; /* Next and previous elements in the table */
|
||||
void *data; /* Data associated with this element */
|
||||
const char *pKey; int nKey; /* Key associated with this element */
|
||||
const char *pKey; /* Key associated with this element */
|
||||
};
|
||||
|
||||
/*
|
||||
** Access routines. To delete, insert a NULL pointer.
|
||||
*/
|
||||
void sqlite3HashInit(Hash*);
|
||||
void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData);
|
||||
void *sqlite3HashFind(const Hash*, const char *pKey, int nKey);
|
||||
void *sqlite3HashInsert(Hash*, const char *pKey, void *pData);
|
||||
void *sqlite3HashFind(const Hash*, const char *pKey);
|
||||
void sqlite3HashClear(Hash*);
|
||||
|
||||
/*
|
||||
|
||||
+24
-21
@@ -56,13 +56,13 @@ void sqlite3OpenTable(
|
||||
**
|
||||
** Character Column affinity
|
||||
** ------------------------------
|
||||
** 'a' TEXT
|
||||
** 'b' NONE
|
||||
** 'c' NUMERIC
|
||||
** 'd' INTEGER
|
||||
** 'e' REAL
|
||||
** 'A' NONE
|
||||
** 'B' TEXT
|
||||
** 'C' NUMERIC
|
||||
** 'D' INTEGER
|
||||
** 'F' REAL
|
||||
**
|
||||
** An extra 'd' is appended to the end of the string to cover the
|
||||
** An extra 'D' is appended to the end of the string to cover the
|
||||
** rowid that appears as the last column in every index.
|
||||
**
|
||||
** Memory for the buffer containing the column index affinity string
|
||||
@@ -111,11 +111,11 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
||||
**
|
||||
** Character Column affinity
|
||||
** ------------------------------
|
||||
** 'a' TEXT
|
||||
** 'b' NONE
|
||||
** 'c' NUMERIC
|
||||
** 'd' INTEGER
|
||||
** 'e' REAL
|
||||
** 'A' NONE
|
||||
** 'B' TEXT
|
||||
** 'C' NUMERIC
|
||||
** 'D' INTEGER
|
||||
** 'E' REAL
|
||||
*/
|
||||
void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
||||
int i;
|
||||
@@ -410,7 +410,7 @@ static int xferOptimization(
|
||||
** The 4th template is used if the insert statement takes its
|
||||
** values from a SELECT but the data is being inserted into a table
|
||||
** that is also read as part of the SELECT. In the third form,
|
||||
** we have to use a intermediate table to store the results of
|
||||
** we have to use an intermediate table to store the results of
|
||||
** the select. The template is like this:
|
||||
**
|
||||
** X <- A
|
||||
@@ -575,7 +575,7 @@ void sqlite3Insert(
|
||||
regAutoinc = autoIncBegin(pParse, iDb, pTab);
|
||||
|
||||
/* Allocate registers for holding the rowid of the new row,
|
||||
** the content of the new row, and the assemblied row record.
|
||||
** the content of the new row, and the assembled row record.
|
||||
*/
|
||||
regRowid = regIns = pParse->nMem+1;
|
||||
pParse->nMem += pTab->nCol + 1;
|
||||
@@ -1027,7 +1027,7 @@ insert_cleanup:
|
||||
}
|
||||
|
||||
/* Make sure "isView" and other macros defined above are undefined. Otherwise
|
||||
** thely may interfere with compilation of other functions in this file
|
||||
** they may interfere with compilation of other functions in this file
|
||||
** (or in another file, if this file becomes part of the amalgamation). */
|
||||
#ifdef isView
|
||||
#undef isView
|
||||
@@ -1143,7 +1143,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
int ix; /* Index loop counter */
|
||||
int nCol; /* Number of columns */
|
||||
int onError; /* Conflict resolution strategy */
|
||||
int j1; /* Addresss of jump instruction */
|
||||
int j1; /* Address of jump instruction */
|
||||
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
|
||||
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
|
||||
int ipkTop = 0; /* Top of the rowid change constraint check */
|
||||
@@ -1547,7 +1547,7 @@ void sqlite3CompleteInsertion(
|
||||
Index *pIdx; /* An index being inserted or updated */
|
||||
u8 pik_flags; /* flag values passed to the btree insert */
|
||||
int regData; /* Content registers (after the rowid) */
|
||||
int regRec; /* Register holding assemblied record for the table */
|
||||
int regRec; /* Register holding assembled record for the table */
|
||||
int i; /* Loop counter */
|
||||
u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */
|
||||
|
||||
@@ -1612,6 +1612,9 @@ void sqlite3CompleteInsertion(
|
||||
** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range
|
||||
** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the
|
||||
** pTab->pIndex list.
|
||||
**
|
||||
** If pTab is a virtual table, then this routine is a no-op and the
|
||||
** *piDataCur and *piIdxCur values are left uninitialized.
|
||||
*/
|
||||
int sqlite3OpenTableAndIndices(
|
||||
Parse *pParse, /* Parsing context */
|
||||
@@ -1630,9 +1633,9 @@ int sqlite3OpenTableAndIndices(
|
||||
|
||||
assert( op==OP_OpenRead || op==OP_OpenWrite );
|
||||
if( IsVirtual(pTab) ){
|
||||
assert( aToOpen==0 );
|
||||
*piDataCur = 0;
|
||||
*piIdxCur = 1;
|
||||
/* This routine is a no-op for virtual tables. Leave the output
|
||||
** variables *piDataCur and *piIdxCur uninitialized so that valgrind
|
||||
** can detect if they are used by mistake in the caller. */
|
||||
return 0;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
@@ -1669,7 +1672,7 @@ int sqlite3OpenTableAndIndices(
|
||||
** The following global variable is incremented whenever the
|
||||
** transfer optimization is used. This is used for testing
|
||||
** purposes only - to make sure the transfer optimization really
|
||||
** is happening when it is suppose to.
|
||||
** is happening when it is supposed to.
|
||||
*/
|
||||
int sqlite3_xferopt_count;
|
||||
#endif /* SQLITE_TEST */
|
||||
@@ -1736,7 +1739,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
|
||||
** INSERT INTO tab1 SELECT * FROM tab2;
|
||||
**
|
||||
** The xfer optimization transfers raw records from tab2 over to tab1.
|
||||
** Columns are not decoded and reassemblied, which greatly improves
|
||||
** Columns are not decoded and reassembled, which greatly improves
|
||||
** performance. Raw index records are transferred in the same way.
|
||||
**
|
||||
** The xfer optimization is only attempted if tab1 and tab2 are compatible.
|
||||
|
||||
+4
-4
@@ -44,7 +44,7 @@ int sqlite3_exec(
|
||||
if( zSql==0 ) zSql = "";
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3Error(db, SQLITE_OK, 0);
|
||||
sqlite3Error(db, SQLITE_OK);
|
||||
while( rc==SQLITE_OK && zSql[0] ){
|
||||
int nCol;
|
||||
char **azVals = 0;
|
||||
@@ -102,7 +102,7 @@ int sqlite3_exec(
|
||||
rc = SQLITE_ABORT;
|
||||
sqlite3VdbeFinalize((Vdbe *)pStmt);
|
||||
pStmt = 0;
|
||||
sqlite3Error(db, SQLITE_ABORT, 0);
|
||||
sqlite3Error(db, SQLITE_ABORT);
|
||||
goto exec_out;
|
||||
}
|
||||
}
|
||||
@@ -125,14 +125,14 @@ exec_out:
|
||||
sqlite3DbFree(db, azCols);
|
||||
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){
|
||||
if( rc!=SQLITE_OK && pzErrMsg ){
|
||||
int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
|
||||
*pzErrMsg = sqlite3Malloc(nErrMsg);
|
||||
if( *pzErrMsg ){
|
||||
memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
sqlite3Error(db, SQLITE_NOMEM, 0);
|
||||
sqlite3Error(db, SQLITE_NOMEM);
|
||||
}
|
||||
}else if( pzErrMsg ){
|
||||
*pzErrMsg = 0;
|
||||
|
||||
+2
-2
@@ -271,9 +271,9 @@ static void yyGrowStack(yyParser *p){
|
||||
** A pointer to a parser. This pointer is used in subsequent calls
|
||||
** to Parse and ParseFree.
|
||||
*/
|
||||
void *ParseAlloc(void *(*mallocProc)(size_t)){
|
||||
void *ParseAlloc(void *(*mallocProc)(u64)){
|
||||
yyParser *pParser;
|
||||
pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
|
||||
pParser = (yyParser*)(*mallocProc)( (u64)sizeof(yyParser) );
|
||||
if( pParser ){
|
||||
pParser->yyidx = -1;
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
|
||||
+15
-3
@@ -34,7 +34,6 @@
|
||||
# define sqlite3_column_table_name16 0
|
||||
# define sqlite3_column_origin_name 0
|
||||
# define sqlite3_column_origin_name16 0
|
||||
# define sqlite3_table_column_metadata 0
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_AUTHORIZATION
|
||||
@@ -390,7 +389,20 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_uri_int64,
|
||||
sqlite3_uri_parameter,
|
||||
sqlite3_vsnprintf,
|
||||
sqlite3_wal_checkpoint_v2
|
||||
sqlite3_wal_checkpoint_v2,
|
||||
/* Version 3.8.7 and later */
|
||||
sqlite3_auto_extension,
|
||||
sqlite3_bind_blob64,
|
||||
sqlite3_bind_text64,
|
||||
sqlite3_cancel_auto_extension,
|
||||
sqlite3_load_extension,
|
||||
sqlite3_malloc64,
|
||||
sqlite3_msize,
|
||||
sqlite3_realloc64,
|
||||
sqlite3_reset_auto_extension,
|
||||
sqlite3_result_blob64,
|
||||
sqlite3_result_text64,
|
||||
sqlite3_strglob
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -749,7 +761,7 @@ void sqlite3AutoLoadExtensions(sqlite3 *db){
|
||||
sqlite3_mutex_leave(mutex);
|
||||
zErrmsg = 0;
|
||||
if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){
|
||||
sqlite3Error(db, rc,
|
||||
sqlite3ErrorWithMsg(db, rc,
|
||||
"automatic extension loading failed: %s", zErrmsg);
|
||||
go = 0;
|
||||
}
|
||||
|
||||
+367
-127
File diff suppressed because it is too large
Load Diff
+96
-64
@@ -294,11 +294,9 @@ static int mallocWithAlarm(int n, void **pp){
|
||||
** Allocate memory. This routine is like sqlite3_malloc() except that it
|
||||
** assumes the memory subsystem has already been initialized.
|
||||
*/
|
||||
void *sqlite3Malloc(int n){
|
||||
void *sqlite3Malloc(u64 n){
|
||||
void *p;
|
||||
if( n<=0 /* IMP: R-65312-04917 */
|
||||
|| n>=0x7fffff00
|
||||
){
|
||||
if( n==0 || n>=0x7fffff00 ){
|
||||
/* A memory allocation of a number of bytes which is near the maximum
|
||||
** signed integer value might cause an integer overflow inside of the
|
||||
** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving
|
||||
@@ -307,12 +305,12 @@ void *sqlite3Malloc(int n){
|
||||
p = 0;
|
||||
}else if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
mallocWithAlarm(n, &p);
|
||||
mallocWithAlarm((int)n, &p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
p = sqlite3GlobalConfig.m.xMalloc(n);
|
||||
p = sqlite3GlobalConfig.m.xMalloc((int)n);
|
||||
}
|
||||
assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */
|
||||
assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-11148-40995 */
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -322,6 +320,12 @@ void *sqlite3Malloc(int n){
|
||||
** allocation.
|
||||
*/
|
||||
void *sqlite3_malloc(int n){
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
#endif
|
||||
return n<=0 ? 0 : sqlite3Malloc(n);
|
||||
}
|
||||
void *sqlite3_malloc64(sqlite3_uint64 n){
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
#endif
|
||||
@@ -352,22 +356,20 @@ void *sqlite3ScratchMalloc(int n){
|
||||
assert( n>0 );
|
||||
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
|
||||
if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
|
||||
p = mem0.pScratchFree;
|
||||
mem0.pScratchFree = mem0.pScratchFree->pNext;
|
||||
mem0.nScratchFree--;
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
|
||||
n = mallocWithAlarm(n, &p);
|
||||
if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
p = sqlite3Malloc(n);
|
||||
if( sqlite3GlobalConfig.bMemstat && p ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
p = sqlite3GlobalConfig.m.xMalloc(n);
|
||||
}
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
|
||||
}
|
||||
@@ -375,11 +377,12 @@ void *sqlite3ScratchMalloc(int n){
|
||||
|
||||
|
||||
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
|
||||
/* Verify that no more than two scratch allocations per thread
|
||||
** are outstanding at one time. (This is only checked in the
|
||||
** single-threaded case since checking in the multi-threaded case
|
||||
** would be much more complicated.) */
|
||||
assert( scratchAllocOut<=1 );
|
||||
/* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch
|
||||
** buffers per thread.
|
||||
**
|
||||
** This can only be checked in single-threaded mode.
|
||||
*/
|
||||
assert( scratchAllocOut==0 );
|
||||
if( p ) scratchAllocOut++;
|
||||
#endif
|
||||
|
||||
@@ -445,29 +448,37 @@ static int isLookaside(sqlite3 *db, void *p){
|
||||
*/
|
||||
int sqlite3MallocSize(void *p){
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
assert( db!=0 );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( isLookaside(db, p) ){
|
||||
return db->lookaside.sz;
|
||||
if( db==0 ){
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
return sqlite3MallocSize(p);
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
|
||||
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( isLookaside(db, p) ){
|
||||
return db->lookaside.sz;
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_uint64 sqlite3_msize(void *p){
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Free memory previously obtained from sqlite3Malloc().
|
||||
*/
|
||||
void sqlite3_free(void *p){
|
||||
if( p==0 ) return; /* IMP: R-49053-54554 */
|
||||
assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
|
||||
@@ -479,6 +490,14 @@ void sqlite3_free(void *p){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Add the size of memory allocation "p" to the count in
|
||||
** *db->pnBytesFreed.
|
||||
*/
|
||||
static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
|
||||
*db->pnBytesFreed += sqlite3DbMallocSize(db,p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Free memory that might be associated with a particular database
|
||||
** connection.
|
||||
@@ -488,7 +507,7 @@ void sqlite3DbFree(sqlite3 *db, void *p){
|
||||
if( p==0 ) return;
|
||||
if( db ){
|
||||
if( db->pnBytesFreed ){
|
||||
*db->pnBytesFreed += sqlite3DbMallocSize(db, p);
|
||||
measureAllocationSize(db, p);
|
||||
return;
|
||||
}
|
||||
if( isLookaside(db, p) ){
|
||||
@@ -503,8 +522,8 @@ void sqlite3DbFree(sqlite3 *db, void *p){
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
sqlite3_free(p);
|
||||
@@ -513,14 +532,16 @@ void sqlite3DbFree(sqlite3 *db, void *p){
|
||||
/*
|
||||
** Change the size of an existing memory allocation
|
||||
*/
|
||||
void *sqlite3Realloc(void *pOld, int nBytes){
|
||||
void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
int nOld, nNew, nDiff;
|
||||
void *pNew;
|
||||
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
|
||||
if( pOld==0 ){
|
||||
return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
|
||||
return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */
|
||||
}
|
||||
if( nBytes<=0 ){
|
||||
sqlite3_free(pOld); /* IMP: R-31593-10574 */
|
||||
if( nBytes==0 ){
|
||||
sqlite3_free(pOld); /* IMP: R-26507-47431 */
|
||||
return 0;
|
||||
}
|
||||
if( nBytes>=0x7fffff00 ){
|
||||
@@ -531,22 +552,20 @@ void *sqlite3Realloc(void *pOld, int nBytes){
|
||||
/* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
|
||||
** argument to xRealloc is always a value returned by a prior call to
|
||||
** xRoundup. */
|
||||
nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
|
||||
nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes);
|
||||
if( nOld==nNew ){
|
||||
pNew = pOld;
|
||||
}else if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
|
||||
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
|
||||
nDiff = nNew - nOld;
|
||||
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
|
||||
mem0.alarmThreshold-nDiff ){
|
||||
sqlite3MallocAlarm(nDiff);
|
||||
}
|
||||
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
|
||||
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
||||
if( pNew==0 && mem0.alarmCallback ){
|
||||
sqlite3MallocAlarm(nBytes);
|
||||
sqlite3MallocAlarm((int)nBytes);
|
||||
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
||||
}
|
||||
if( pNew ){
|
||||
@@ -557,7 +576,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
|
||||
}else{
|
||||
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
||||
}
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */
|
||||
return pNew;
|
||||
}
|
||||
|
||||
@@ -566,6 +585,13 @@ void *sqlite3Realloc(void *pOld, int nBytes){
|
||||
** subsystem is initialized prior to invoking sqliteRealloc.
|
||||
*/
|
||||
void *sqlite3_realloc(void *pOld, int n){
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
#endif
|
||||
if( n<0 ) n = 0; /* IMP: R-26507-47431 */
|
||||
return sqlite3Realloc(pOld, n);
|
||||
}
|
||||
void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
#endif
|
||||
@@ -576,10 +602,10 @@ void *sqlite3_realloc(void *pOld, int n){
|
||||
/*
|
||||
** Allocate and zero memory.
|
||||
*/
|
||||
void *sqlite3MallocZero(int n){
|
||||
void *sqlite3MallocZero(u64 n){
|
||||
void *p = sqlite3Malloc(n);
|
||||
if( p ){
|
||||
memset(p, 0, n);
|
||||
memset(p, 0, (size_t)n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -588,10 +614,10 @@ void *sqlite3MallocZero(int n){
|
||||
** Allocate and zero memory. If the allocation fails, make
|
||||
** the mallocFailed flag in the connection pointer.
|
||||
*/
|
||||
void *sqlite3DbMallocZero(sqlite3 *db, int n){
|
||||
void *sqlite3DbMallocZero(sqlite3 *db, u64 n){
|
||||
void *p = sqlite3DbMallocRaw(db, n);
|
||||
if( p ){
|
||||
memset(p, 0, n);
|
||||
memset(p, 0, (size_t)n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -614,7 +640,7 @@ void *sqlite3DbMallocZero(sqlite3 *db, int n){
|
||||
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
|
||||
** that all prior mallocs (ex: "a") worked too.
|
||||
*/
|
||||
void *sqlite3DbMallocRaw(sqlite3 *db, int n){
|
||||
void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
|
||||
void *p;
|
||||
assert( db==0 || sqlite3_mutex_held(db->mutex) );
|
||||
assert( db==0 || db->pnBytesFreed==0 );
|
||||
@@ -649,8 +675,8 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){
|
||||
if( !p && db ){
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_DB |
|
||||
((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
|
||||
sqlite3MemdebugSetType(p,
|
||||
(db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -658,7 +684,7 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){
|
||||
** Resize the block of memory pointed to by p to n bytes. If the
|
||||
** resize fails, set the mallocFailed flag in the connection object.
|
||||
*/
|
||||
void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
|
||||
void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
|
||||
void *pNew = 0;
|
||||
assert( db!=0 );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
@@ -676,15 +702,14 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
pNew = sqlite3_realloc(p, n);
|
||||
pNew = sqlite3_realloc64(p, n);
|
||||
if( !pNew ){
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
|
||||
sqlite3MemdebugSetType(pNew,
|
||||
(db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
|
||||
}
|
||||
}
|
||||
@@ -695,7 +720,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
|
||||
** Attempt to reallocate p. If the reallocation fails, then free p
|
||||
** and set the mallocFailed flag in the database connection.
|
||||
*/
|
||||
void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
|
||||
void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){
|
||||
void *pNew;
|
||||
pNew = sqlite3DbRealloc(db, p, n);
|
||||
if( !pNew ){
|
||||
@@ -725,7 +750,7 @@ char *sqlite3DbStrDup(sqlite3 *db, const char *z){
|
||||
}
|
||||
return zNew;
|
||||
}
|
||||
char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
|
||||
char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
|
||||
char *zNew;
|
||||
if( z==0 ){
|
||||
return 0;
|
||||
@@ -733,7 +758,7 @@ char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
|
||||
assert( (n&0x7fffffff)==n );
|
||||
zNew = sqlite3DbMallocRaw(db, n+1);
|
||||
if( zNew ){
|
||||
memcpy(zNew, z, n);
|
||||
memcpy(zNew, z, (size_t)n);
|
||||
zNew[n] = 0;
|
||||
}
|
||||
return zNew;
|
||||
@@ -755,6 +780,14 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){
|
||||
*pz = z;
|
||||
}
|
||||
|
||||
/*
|
||||
** Take actions at the end of an API call to indicate an OOM error
|
||||
*/
|
||||
static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
|
||||
db->mallocFailed = 0;
|
||||
sqlite3Error(db, SQLITE_NOMEM);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function must be called before exiting any API function (i.e.
|
||||
@@ -775,10 +808,9 @@ int sqlite3ApiExit(sqlite3* db, int rc){
|
||||
** is unsafe, as is the call to sqlite3Error().
|
||||
*/
|
||||
assert( !db || sqlite3_mutex_held(db->mutex) );
|
||||
if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){
|
||||
sqlite3Error(db, SQLITE_NOMEM, 0);
|
||||
db->mallocFailed = 0;
|
||||
rc = SQLITE_NOMEM;
|
||||
if( db==0 ) return rc & 0xff;
|
||||
if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
|
||||
return apiOomError(db);
|
||||
}
|
||||
return rc & (db ? db->errMask : 0xff);
|
||||
return rc & db->errMask;
|
||||
}
|
||||
|
||||
+4
-4
@@ -79,9 +79,9 @@ static malloc_zone_t* _sqliteZone_;
|
||||
** The malloc.h header file is needed for malloc_usable_size() function
|
||||
** on some systems (e.g. Linux).
|
||||
*/
|
||||
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE)
|
||||
# define SQLITE_USE_MALLOC_H
|
||||
# define SQLITE_USE_MALLOC_USABLE_SIZE
|
||||
#if HAVE_MALLOC_H && HAVE_MALLOC_USABLE_SIZE
|
||||
# define SQLITE_USE_MALLOC_H 1
|
||||
# define SQLITE_USE_MALLOC_USABLE_SIZE 1
|
||||
/*
|
||||
** The MSVCRT has malloc_usable_size(), but it is called _msize(). The
|
||||
** use of _msize() is automatic, but can be disabled by compiling with
|
||||
@@ -188,7 +188,7 @@ static int sqlite3MemSize(void *pPrior){
|
||||
**
|
||||
** For this low-level interface, we know that pPrior!=0. Cases where
|
||||
** pPrior==0 while have been intercepted by higher-level routine and
|
||||
** redirected to xMalloc. Similarly, we know that nByte>0 becauses
|
||||
** redirected to xMalloc. Similarly, we know that nByte>0 because
|
||||
** cases where nByte<=0 will have been intercepted by higher-level
|
||||
** routines and redirected to xFree.
|
||||
*/
|
||||
|
||||
+2
-2
@@ -394,7 +394,7 @@ void sqlite3MemdebugSetType(void *p, u8 eType){
|
||||
** This routine is designed for use within an assert() statement, to
|
||||
** verify the type of an allocation. For example:
|
||||
**
|
||||
** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
|
||||
** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
*/
|
||||
int sqlite3MemdebugHasType(void *p, u8 eType){
|
||||
int rc = 1;
|
||||
@@ -416,7 +416,7 @@ int sqlite3MemdebugHasType(void *p, u8 eType){
|
||||
** This routine is designed for use within an assert() statement, to
|
||||
** verify the type of an allocation. For example:
|
||||
**
|
||||
** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
|
||||
** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
|
||||
*/
|
||||
int sqlite3MemdebugNoType(void *p, u8 eType){
|
||||
int rc = 1;
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@
|
||||
** 1. All memory allocations sizes are rounded up to a power of 2.
|
||||
**
|
||||
** 2. If two adjacent free blocks are the halves of a larger block,
|
||||
** then the two blocks are coalesed into the single larger block.
|
||||
** then the two blocks are coalesced into the single larger block.
|
||||
**
|
||||
** 3. New memory is allocated from the first available free block.
|
||||
**
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ typedef struct FileChunk FileChunk;
|
||||
**
|
||||
** The size chosen is a little less than a power of two. That way,
|
||||
** the FileChunk object will have a size that almost exactly fills
|
||||
** a power-of-two allocation. This mimimizes wasted space in power-of-two
|
||||
** a power-of-two allocation. This minimizes wasted space in power-of-two
|
||||
** memory allocators.
|
||||
*/
|
||||
#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
** 2015 January 12
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains code that is specific to MSVC.
|
||||
*/
|
||||
#ifndef _MSVC_H_
|
||||
#define _MSVC_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4054)
|
||||
#pragma warning(disable : 4055)
|
||||
#pragma warning(disable : 4100)
|
||||
#pragma warning(disable : 4127)
|
||||
#pragma warning(disable : 4152)
|
||||
#pragma warning(disable : 4189)
|
||||
#pragma warning(disable : 4206)
|
||||
#pragma warning(disable : 4210)
|
||||
#pragma warning(disable : 4232)
|
||||
#pragma warning(disable : 4244)
|
||||
#pragma warning(disable : 4305)
|
||||
#pragma warning(disable : 4306)
|
||||
#pragma warning(disable : 4702)
|
||||
#pragma warning(disable : 4706)
|
||||
#endif /* defined(_MSC_VER) */
|
||||
|
||||
#endif /* _MSVC_H_ */
|
||||
@@ -82,6 +82,7 @@ int sqlite3MutexEnd(void){
|
||||
sqlite3_mutex *sqlite3_mutex_alloc(int id){
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
|
||||
if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
|
||||
#endif
|
||||
return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
** Figure out what version of the code to use. The choices are
|
||||
**
|
||||
** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The
|
||||
** mutexes implemention cannot be overridden
|
||||
** mutexes implementation cannot be overridden
|
||||
** at start-time.
|
||||
**
|
||||
** SQLITE_MUTEX_NOOP For single-threaded applications. No
|
||||
|
||||
+6
-2
@@ -175,8 +175,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert( iType-2 >= 0 );
|
||||
assert( iType-2 < ArraySize(staticMutexes) );
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
p = &staticMutexes[iType-2];
|
||||
#if SQLITE_MUTEX_NREF
|
||||
p->id = iType;
|
||||
|
||||
+7
-1
@@ -99,7 +99,7 @@ static int winMutex_isNt = -1; /* <0 means "need to query" */
|
||||
** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
|
||||
** "interlocked" magic used here is probably not strictly necessary.
|
||||
*/
|
||||
static LONG volatile winMutex_lock = 0;
|
||||
static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
|
||||
|
||||
int sqlite3_win32_is_nt(void); /* os_win.c */
|
||||
void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
|
||||
@@ -209,6 +209,12 @@ static sqlite3_mutex *winMutexAlloc(int iType){
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
assert( iType-2 >= 0 );
|
||||
assert( iType-2 < ArraySize(winMutex_staticMutexes) );
|
||||
assert( winMutex_isInit==1 );
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ int sqlite3_unlock_notify(
|
||||
|
||||
leaveMutex();
|
||||
assert( !db->mallocFailed );
|
||||
sqlite3Error(db, rc, (rc?"database is deadlocked":0));
|
||||
sqlite3ErrorWithMsg(db, rc, (rc?"database is deadlocked":0));
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -361,6 +361,10 @@ int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
|
||||
int rc = sqlite3_initialize();
|
||||
if( rc ) return rc;
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
|
||||
MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
|
||||
sqlite3_mutex_enter(mutex);
|
||||
vfsUnlink(pVfs);
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
** shared locks begins at SHARED_FIRST.
|
||||
**
|
||||
** The same locking strategy and
|
||||
** byte ranges are used for Unix. This leaves open the possiblity of having
|
||||
** byte ranges are used for Unix. This leaves open the possibility of having
|
||||
** clients on win95, winNT, and unix all talking to the same shared file
|
||||
** and all locking correctly. To do so would require that samba (or whatever
|
||||
** tool is being used for file sharing) implements locks correctly between
|
||||
|
||||
+70
-37
@@ -299,6 +299,14 @@ static int randomnessPid = 0;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Explicitly call the 64-bit version of lseek() on Android. Otherwise, lseek()
|
||||
** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined.
|
||||
*/
|
||||
#ifdef __ANDROID__
|
||||
# define lseek lseek64
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Different Unix systems declare open() in different ways. Same use
|
||||
** open(const char*,int,mode_t). Others use open(const char*,int,...).
|
||||
@@ -631,7 +639,7 @@ static int unixMutexHeld(void) {
|
||||
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** Helper function for printing out trace information from debugging
|
||||
** binaries. This returns the string represetation of the supplied
|
||||
** binaries. This returns the string representation of the supplied
|
||||
** integer lock-type.
|
||||
*/
|
||||
static const char *azFileLock(int eFileLock){
|
||||
@@ -708,9 +716,22 @@ static int lockTrace(int fd, int op, struct flock *p){
|
||||
|
||||
/*
|
||||
** Retry ftruncate() calls that fail due to EINTR
|
||||
**
|
||||
** All calls to ftruncate() within this file should be made through this wrapper.
|
||||
** On the Android platform, bypassing the logic below could lead to a corrupt
|
||||
** database.
|
||||
*/
|
||||
static int robust_ftruncate(int h, sqlite3_int64 sz){
|
||||
int rc;
|
||||
#ifdef __ANDROID__
|
||||
/* On Android, ftruncate() always uses 32-bit offsets, even if
|
||||
** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to
|
||||
** truncate a file to any size larger than 2GiB. Silently ignore any
|
||||
** such attempts. */
|
||||
if( sz>(sqlite3_int64)0x7FFFFFFF ){
|
||||
rc = SQLITE_OK;
|
||||
}else
|
||||
#endif
|
||||
do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
|
||||
return rc;
|
||||
}
|
||||
@@ -3098,7 +3119,7 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){
|
||||
** NB: If you define USE_PREAD or USE_PREAD64, then it might also
|
||||
** be necessary to define _XOPEN_SOURCE to be 500. This varies from
|
||||
** one system to another. Since SQLite does not define USE_PREAD
|
||||
** any any form by default, we will not attempt to define _XOPEN_SOURCE.
|
||||
** in any form by default, we will not attempt to define _XOPEN_SOURCE.
|
||||
** See tickets #2741 and #2681.
|
||||
**
|
||||
** To avoid stomping the errno value on a failed read the lastErrno value
|
||||
@@ -3365,9 +3386,9 @@ int sqlite3_fullsync_count = 0;
|
||||
** We do not trust systems to provide a working fdatasync(). Some do.
|
||||
** Others do no. To be safe, we will stick with the (slightly slower)
|
||||
** fsync(). If you know that your system does support fdatasync() correctly,
|
||||
** then simply compile with -Dfdatasync=fdatasync
|
||||
** then simply compile with -Dfdatasync=fdatasync or -DHAVE_FDATASYNC
|
||||
*/
|
||||
#if !defined(fdatasync)
|
||||
#if !defined(fdatasync) && !HAVE_FDATASYNC
|
||||
# define fdatasync fsync
|
||||
#endif
|
||||
|
||||
@@ -3595,7 +3616,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
|
||||
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
|
||||
}
|
||||
|
||||
rc = robust_ftruncate(pFile->h, (off_t)nByte);
|
||||
rc = robust_ftruncate(pFile->h, nByte);
|
||||
if( rc ){
|
||||
pFile->lastErrno = errno;
|
||||
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
|
||||
@@ -3688,24 +3709,28 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
|
||||
}while( err==EINTR );
|
||||
if( err ) return SQLITE_IOERR_WRITE;
|
||||
#else
|
||||
/* If the OS does not have posix_fallocate(), fake it. First use
|
||||
** ftruncate() to set the file size, then write a single byte to
|
||||
** the last byte in each block within the extended region. This
|
||||
** is the same technique used by glibc to implement posix_fallocate()
|
||||
** on systems that do not have a real fallocate() system call.
|
||||
/* If the OS does not have posix_fallocate(), fake it. Write a
|
||||
** single byte to the last byte in each block that falls entirely
|
||||
** within the extended region. Then, if required, a single byte
|
||||
** at offset (nSize-1), to set the size of the file correctly.
|
||||
** This is a similar technique to that used by glibc on systems
|
||||
** that do not have a real fallocate() call.
|
||||
*/
|
||||
int nBlk = buf.st_blksize; /* File-system block size */
|
||||
int nWrite = 0; /* Number of bytes written by seekAndWrite */
|
||||
i64 iWrite; /* Next offset to write to */
|
||||
|
||||
if( robust_ftruncate(pFile->h, nSize) ){
|
||||
pFile->lastErrno = errno;
|
||||
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
|
||||
}
|
||||
iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
|
||||
while( iWrite<nSize ){
|
||||
int nWrite = seekAndWrite(pFile, iWrite, "", 1);
|
||||
assert( iWrite>=buf.st_size );
|
||||
assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) );
|
||||
assert( ((iWrite+1)%nBlk)==0 );
|
||||
for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){
|
||||
nWrite = seekAndWrite(pFile, iWrite, "", 1);
|
||||
if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
|
||||
}
|
||||
if( nWrite==0 || (nSize%nBlk) ){
|
||||
nWrite = seekAndWrite(pFile, nSize-1, "", 1);
|
||||
if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
|
||||
iWrite += nBlk;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -3730,7 +3755,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
|
||||
}
|
||||
|
||||
/*
|
||||
** If *pArg is inititially negative then this is a query. Set *pArg to
|
||||
** If *pArg is initially negative then this is a query. Set *pArg to
|
||||
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
|
||||
**
|
||||
** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
|
||||
@@ -3937,7 +3962,7 @@ static int unixSectorSize(sqlite3_file *id){
|
||||
** Return the device characteristics for the file.
|
||||
**
|
||||
** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
|
||||
** However, that choice is contraversial since technically the underlying
|
||||
** However, that choice is controversial since technically the underlying
|
||||
** file system does not always provide powersafe overwrites. (In other
|
||||
** words, after a power-loss event, parts of the file that were never
|
||||
** written might end up being altered.) However, non-PSOW behavior is very,
|
||||
@@ -4909,7 +4934,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
|
||||
** looks at the filesystem type and tries to guess the best locking
|
||||
** strategy from that.
|
||||
**
|
||||
** For finder-funtion F, two objects are created:
|
||||
** For finder-function F, two objects are created:
|
||||
**
|
||||
** (1) The real finder-function named "FImpt()".
|
||||
**
|
||||
@@ -4930,7 +4955,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
|
||||
** * An I/O method finder function called FINDER that returns a pointer
|
||||
** to the METHOD object in the previous bullet.
|
||||
*/
|
||||
#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \
|
||||
#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK, SHMMAP) \
|
||||
static const sqlite3_io_methods METHOD = { \
|
||||
VERSION, /* iVersion */ \
|
||||
CLOSE, /* xClose */ \
|
||||
@@ -4945,7 +4970,7 @@ static const sqlite3_io_methods METHOD = { \
|
||||
unixFileControl, /* xFileControl */ \
|
||||
unixSectorSize, /* xSectorSize */ \
|
||||
unixDeviceCharacteristics, /* xDeviceCapabilities */ \
|
||||
unixShmMap, /* xShmMap */ \
|
||||
SHMMAP, /* xShmMap */ \
|
||||
unixShmLock, /* xShmLock */ \
|
||||
unixShmBarrier, /* xShmBarrier */ \
|
||||
unixShmUnmap, /* xShmUnmap */ \
|
||||
@@ -4971,16 +4996,18 @@ IOMETHODS(
|
||||
unixClose, /* xClose method */
|
||||
unixLock, /* xLock method */
|
||||
unixUnlock, /* xUnlock method */
|
||||
unixCheckReservedLock /* xCheckReservedLock method */
|
||||
unixCheckReservedLock, /* xCheckReservedLock method */
|
||||
unixShmMap /* xShmMap method */
|
||||
)
|
||||
IOMETHODS(
|
||||
nolockIoFinder, /* Finder function name */
|
||||
nolockIoMethods, /* sqlite3_io_methods object name */
|
||||
1, /* shared memory is disabled */
|
||||
3, /* shared memory is disabled */
|
||||
nolockClose, /* xClose method */
|
||||
nolockLock, /* xLock method */
|
||||
nolockUnlock, /* xUnlock method */
|
||||
nolockCheckReservedLock /* xCheckReservedLock method */
|
||||
nolockCheckReservedLock, /* xCheckReservedLock method */
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
IOMETHODS(
|
||||
dotlockIoFinder, /* Finder function name */
|
||||
@@ -4989,7 +5016,8 @@ IOMETHODS(
|
||||
dotlockClose, /* xClose method */
|
||||
dotlockLock, /* xLock method */
|
||||
dotlockUnlock, /* xUnlock method */
|
||||
dotlockCheckReservedLock /* xCheckReservedLock method */
|
||||
dotlockCheckReservedLock, /* xCheckReservedLock method */
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
|
||||
@@ -5000,7 +5028,8 @@ IOMETHODS(
|
||||
flockClose, /* xClose method */
|
||||
flockLock, /* xLock method */
|
||||
flockUnlock, /* xUnlock method */
|
||||
flockCheckReservedLock /* xCheckReservedLock method */
|
||||
flockCheckReservedLock, /* xCheckReservedLock method */
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
#endif
|
||||
|
||||
@@ -5012,7 +5041,8 @@ IOMETHODS(
|
||||
semClose, /* xClose method */
|
||||
semLock, /* xLock method */
|
||||
semUnlock, /* xUnlock method */
|
||||
semCheckReservedLock /* xCheckReservedLock method */
|
||||
semCheckReservedLock, /* xCheckReservedLock method */
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
#endif
|
||||
|
||||
@@ -5024,7 +5054,8 @@ IOMETHODS(
|
||||
afpClose, /* xClose method */
|
||||
afpLock, /* xLock method */
|
||||
afpUnlock, /* xUnlock method */
|
||||
afpCheckReservedLock /* xCheckReservedLock method */
|
||||
afpCheckReservedLock, /* xCheckReservedLock method */
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
#endif
|
||||
|
||||
@@ -5049,7 +5080,8 @@ IOMETHODS(
|
||||
proxyClose, /* xClose method */
|
||||
proxyLock, /* xLock method */
|
||||
proxyUnlock, /* xUnlock method */
|
||||
proxyCheckReservedLock /* xCheckReservedLock method */
|
||||
proxyCheckReservedLock, /* xCheckReservedLock method */
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
#endif
|
||||
|
||||
@@ -5062,7 +5094,8 @@ IOMETHODS(
|
||||
unixClose, /* xClose method */
|
||||
unixLock, /* xLock method */
|
||||
nfsUnlock, /* xUnlock method */
|
||||
unixCheckReservedLock /* xCheckReservedLock method */
|
||||
unixCheckReservedLock, /* xCheckReservedLock method */
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
#endif
|
||||
|
||||
@@ -5171,7 +5204,7 @@ static const sqlite3_io_methods
|
||||
#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
|
||||
|
||||
/*
|
||||
** An abstract type for a pointer to a IO method finder function:
|
||||
** An abstract type for a pointer to an IO method finder function:
|
||||
*/
|
||||
typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
|
||||
|
||||
@@ -5485,7 +5518,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
|
||||
** descriptor on the same path, fail, and return an error to SQLite.
|
||||
**
|
||||
** Even if a subsequent open() call does succeed, the consequences of
|
||||
** not searching for a resusable file descriptor are not dire. */
|
||||
** not searching for a reusable file descriptor are not dire. */
|
||||
if( 0==osStat(zPath, &sStat) ){
|
||||
unixInodeInfo *pInode;
|
||||
|
||||
@@ -5516,7 +5549,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
|
||||
** written to *pMode. If an IO error occurs, an SQLite error code is
|
||||
** returned and the value of *pMode is not modified.
|
||||
**
|
||||
** In most cases cases, this routine sets *pMode to 0, which will become
|
||||
** In most cases, this routine sets *pMode to 0, which will become
|
||||
** an indication to robust_open() to create the file using
|
||||
** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
|
||||
** But if the file being opened is a WAL or regular journal file, then
|
||||
@@ -5885,7 +5918,7 @@ static int unixDelete(
|
||||
if( osUnlink(zPath)==(-1) ){
|
||||
if( errno==ENOENT
|
||||
#if OS_VXWORKS
|
||||
|| errno==0x380003
|
||||
|| osAccess(zPath,0)!=0
|
||||
#endif
|
||||
){
|
||||
rc = SQLITE_IOERR_DELETE_NOENT;
|
||||
@@ -6308,7 +6341,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
|
||||
** proxy path against the values stored in the conch. The conch file is
|
||||
** stored in the same directory as the database file and the file name
|
||||
** is patterned after the database file name as ".<databasename>-conch".
|
||||
** If the conch file does not exist, or it's contents do not match the
|
||||
** If the conch file does not exist, or its contents do not match the
|
||||
** host ID and/or proxy path, then the lock is escalated to an exclusive
|
||||
** lock and the conch file contents is updated with the host ID and proxy
|
||||
** path and the lock is downgraded to a shared lock again. If the conch
|
||||
@@ -6360,7 +6393,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
|
||||
** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
|
||||
** force proxy locking to be used for every database file opened, and 0
|
||||
** will force automatic proxy locking to be disabled for all database
|
||||
** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
|
||||
** files (explicitly calling the SQLITE_SET_LOCKPROXYFILE pragma or
|
||||
** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
|
||||
*/
|
||||
|
||||
|
||||
+61
-35
@@ -34,6 +34,11 @@
|
||||
with SQLITE_OMIT_WAL."
|
||||
#endif
|
||||
|
||||
#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0
|
||||
# error "Memory mapped files require support from the Windows NT kernel,\
|
||||
compile with SQLITE_MAX_MMAP_SIZE=0."
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
|
||||
** based on the sub-platform)?
|
||||
@@ -163,10 +168,11 @@
|
||||
|
||||
/*
|
||||
** Do we need to manually define the Win32 file mapping APIs for use with WAL
|
||||
** mode (e.g. these APIs are available in the Windows CE SDK; however, they
|
||||
** are not present in the header file)?
|
||||
** mode or memory mapped files (e.g. these APIs are available in the Windows
|
||||
** CE SDK; however, they are not present in the header file)?
|
||||
*/
|
||||
#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
|
||||
#if SQLITE_WIN32_FILEMAPPING_API && \
|
||||
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
||||
/*
|
||||
** Two of the file mapping APIs are different under WinRT. Figure out which
|
||||
** set we need.
|
||||
@@ -194,7 +200,7 @@ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
|
||||
** This file mapping API is common to both Win32 and WinRT.
|
||||
*/
|
||||
WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
|
||||
#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
|
||||
#endif /* SQLITE_WIN32_FILEMAPPING_API */
|
||||
|
||||
/*
|
||||
** Some Microsoft compilers lack this definition.
|
||||
@@ -410,9 +416,9 @@ const sqlite3_mem_methods *sqlite3MemGetWin32(void);
|
||||
** can manually set this value to 1 to emulate Win98 behavior.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
LONG volatile sqlite3_os_type = 0;
|
||||
LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
|
||||
#else
|
||||
static LONG volatile sqlite3_os_type = 0;
|
||||
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
|
||||
#endif
|
||||
|
||||
#ifndef SYSCALL
|
||||
@@ -487,7 +493,7 @@ static struct win_syscall {
|
||||
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
|
||||
|
||||
#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
|
||||
!defined(SQLITE_OMIT_WAL))
|
||||
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
|
||||
{ "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
|
||||
#else
|
||||
{ "CreateFileMappingA", (SYSCALL)0, 0 },
|
||||
@@ -497,7 +503,7 @@ static struct win_syscall {
|
||||
DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
||||
!defined(SQLITE_OMIT_WAL))
|
||||
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
|
||||
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
|
||||
#else
|
||||
{ "CreateFileMappingW", (SYSCALL)0, 0 },
|
||||
@@ -837,7 +843,8 @@ static struct win_syscall {
|
||||
LPOVERLAPPED))aSyscall[48].pCurrent)
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \
|
||||
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
|
||||
{ "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
|
||||
#else
|
||||
{ "MapViewOfFile", (SYSCALL)0, 0 },
|
||||
@@ -907,7 +914,7 @@ static struct win_syscall {
|
||||
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
||||
LPOVERLAPPED))aSyscall[58].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
|
||||
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
||||
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
|
||||
#else
|
||||
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
|
||||
@@ -943,7 +950,7 @@ static struct win_syscall {
|
||||
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
|
||||
DWORD))aSyscall[63].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
#if !SQLITE_OS_WINCE
|
||||
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
|
||||
#else
|
||||
{ "WaitForSingleObjectEx", (SYSCALL)0, 0 },
|
||||
@@ -970,7 +977,7 @@ static struct win_syscall {
|
||||
#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
|
||||
FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
|
||||
#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
||||
{ "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
|
||||
#else
|
||||
{ "MapViewOfFileFromApp", (SYSCALL)0, 0 },
|
||||
@@ -1034,7 +1041,7 @@ static struct win_syscall {
|
||||
|
||||
#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
|
||||
#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
||||
{ "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
|
||||
#else
|
||||
{ "CreateFileMappingFromApp", (SYSCALL)0, 0 },
|
||||
@@ -1055,8 +1062,8 @@ static struct win_syscall {
|
||||
#else
|
||||
{ "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
|
||||
|
||||
#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*, \
|
||||
LONG,LONG))aSyscall[76].pCurrent)
|
||||
#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
|
||||
SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
|
||||
#endif /* defined(InterlockedCompareExchange) */
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
@@ -1196,8 +1203,8 @@ int sqlite3_win32_reset_heap(){
|
||||
int rc;
|
||||
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
|
||||
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
|
||||
MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
|
||||
MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
|
||||
MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); )
|
||||
MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); )
|
||||
sqlite3_mutex_enter(pMaster);
|
||||
sqlite3_mutex_enter(pMem);
|
||||
winMemAssertMagic();
|
||||
@@ -1290,6 +1297,16 @@ void sqlite3_win32_sleep(DWORD milliseconds){
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
|
||||
SQLITE_THREADSAFE>0
|
||||
DWORD sqlite3Win32Wait(HANDLE hObject){
|
||||
DWORD rc;
|
||||
while( (rc = osWaitForSingleObjectEx(hObject, INFINITE,
|
||||
TRUE))==WAIT_IO_COMPLETION ){}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
|
||||
** or WinCE. Return false (zero) for Win95, Win98, or WinME.
|
||||
@@ -1317,27 +1334,36 @@ void sqlite3_win32_sleep(DWORD milliseconds){
|
||||
** based on the NT kernel.
|
||||
*/
|
||||
int sqlite3_win32_is_nt(void){
|
||||
#if defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
|
||||
#if SQLITE_OS_WINRT
|
||||
/*
|
||||
** NOTE: The WinRT sub-platform is always assumed to be based on the NT
|
||||
** kernel.
|
||||
*/
|
||||
return 1;
|
||||
#elif defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
|
||||
if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
|
||||
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
||||
defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
|
||||
OSVERSIONINFOW sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExW(&sInfo);
|
||||
osInterlockedCompareExchange(&sqlite3_os_type,
|
||||
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
||||
#elif defined(SQLITE_WIN32_HAS_ANSI)
|
||||
#if defined(SQLITE_WIN32_HAS_ANSI)
|
||||
OSVERSIONINFOA sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExA(&sInfo);
|
||||
osInterlockedCompareExchange(&sqlite3_os_type,
|
||||
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
||||
#elif defined(SQLITE_WIN32_HAS_WIDE)
|
||||
OSVERSIONINFOW sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExW(&sInfo);
|
||||
osInterlockedCompareExchange(&sqlite3_os_type,
|
||||
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
||||
#endif
|
||||
}
|
||||
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
|
||||
#elif SQLITE_TEST
|
||||
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
|
||||
#else
|
||||
/*
|
||||
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
|
||||
** deprecated are always assumed to be based on the NT kernel.
|
||||
*/
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
@@ -2453,7 +2479,7 @@ static int winRead(
|
||||
int amt, /* Number of bytes to read */
|
||||
sqlite3_int64 offset /* Begin reading at this offset */
|
||||
){
|
||||
#if !SQLITE_OS_WINCE
|
||||
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
OVERLAPPED overlapped; /* The offset for ReadFile. */
|
||||
#endif
|
||||
winFile *pFile = (winFile*)id; /* file handle */
|
||||
@@ -2485,7 +2511,7 @@ static int winRead(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_WINCE
|
||||
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
if( winSeekFile(pFile, offset) ){
|
||||
OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
|
||||
return SQLITE_FULL;
|
||||
@@ -2557,13 +2583,13 @@ static int winWrite(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_WINCE
|
||||
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
rc = winSeekFile(pFile, offset);
|
||||
if( rc==0 ){
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
#if !SQLITE_OS_WINCE
|
||||
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
OVERLAPPED overlapped; /* The offset for WriteFile. */
|
||||
#endif
|
||||
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
|
||||
@@ -2571,14 +2597,14 @@ static int winWrite(
|
||||
DWORD nWrite; /* Bytes written by each WriteFile() call */
|
||||
DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
|
||||
|
||||
#if !SQLITE_OS_WINCE
|
||||
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
||||
overlapped.Offset = (LONG)(offset & 0xffffffff);
|
||||
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
|
||||
#endif
|
||||
|
||||
while( nRem>0 ){
|
||||
#if SQLITE_OS_WINCE
|
||||
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
|
||||
#else
|
||||
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
|
||||
@@ -2591,7 +2617,7 @@ static int winWrite(
|
||||
lastErrno = osGetLastError();
|
||||
break;
|
||||
}
|
||||
#if !SQLITE_OS_WINCE
|
||||
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
||||
offset += nWrite;
|
||||
overlapped.Offset = (LONG)(offset & 0xffffffff);
|
||||
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
|
||||
@@ -3114,7 +3140,7 @@ static int winUnlock(sqlite3_file *id, int locktype){
|
||||
}
|
||||
|
||||
/*
|
||||
** If *pArg is inititially negative then this is a query. Set *pArg to
|
||||
** If *pArg is initially negative then this is a query. Set *pArg to
|
||||
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
|
||||
**
|
||||
** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
|
||||
@@ -4128,7 +4154,7 @@ static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
|
||||
}else{
|
||||
/* FIXME: If Windows truly always prevents truncating or deleting a
|
||||
** file while a mapping is held, then the following winUnmapfile() call
|
||||
** is unnecessary can can be omitted - potentially improving
|
||||
** is unnecessary can be omitted - potentially improving
|
||||
** performance. */
|
||||
winUnmapfile(pFd);
|
||||
}
|
||||
|
||||
@@ -64,4 +64,14 @@
|
||||
# define SQLITE_OS_WINRT 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For WinCE, some API function parameters do not appear to be declared as
|
||||
** volatile.
|
||||
*/
|
||||
#if SQLITE_OS_WINCE
|
||||
# define SQLITE_WIN32_VOLATILE
|
||||
#else
|
||||
# define SQLITE_WIN32_VOLATILE volatile
|
||||
#endif
|
||||
|
||||
#endif /* _OS_WIN_H_ */
|
||||
|
||||
+191
-151
@@ -76,12 +76,12 @@
|
||||
** Definition: Two databases (or the same database at two points it time)
|
||||
** are said to be "logically equivalent" if they give the same answer to
|
||||
** all queries. Note in particular the content of freelist leaf
|
||||
** pages can be changed arbitarily without effecting the logical equivalence
|
||||
** pages can be changed arbitrarily without affecting the logical equivalence
|
||||
** of the database.
|
||||
**
|
||||
** (7) At any time, if any subset, including the empty set and the total set,
|
||||
** of the unsynced changes to a rollback journal are removed and the
|
||||
** journal is rolled back, the resulting database file will be logical
|
||||
** journal is rolled back, the resulting database file will be logically
|
||||
** equivalent to the database file at the beginning of the transaction.
|
||||
**
|
||||
** (8) When a transaction is rolled back, the xTruncate method of the VFS
|
||||
@@ -378,7 +378,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
|
||||
**
|
||||
** The exception is when the database file is unlocked as the pager moves
|
||||
** from ERROR to OPEN state. At this point there may be a hot-journal file
|
||||
** in the file-system that needs to be rolled back (as part of a OPEN->SHARED
|
||||
** in the file-system that needs to be rolled back (as part of an OPEN->SHARED
|
||||
** transition, by the same pager or any other). If the call to xUnlock()
|
||||
** fails at this point and the pager is left holding an EXCLUSIVE lock, this
|
||||
** can confuse the call to xCheckReservedLock() call made later as part
|
||||
@@ -461,7 +461,7 @@ struct PagerSavepoint {
|
||||
#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */
|
||||
|
||||
/*
|
||||
** A open page cache is an instance of struct Pager. A description of
|
||||
** An open page cache is an instance of struct Pager. A description of
|
||||
** some of the more important member variables follows:
|
||||
**
|
||||
** eState
|
||||
@@ -633,7 +633,7 @@ struct Pager {
|
||||
|
||||
/**************************************************************************
|
||||
** The following block contains those class members that change during
|
||||
** routine opertion. Class members not in this block are either fixed
|
||||
** routine operation. Class members not in this block are either fixed
|
||||
** when the pager is first created or else only change when there is a
|
||||
** significant mode change (such as changing the page_size, locking_mode,
|
||||
** or the journal_mode). From another view, these class members describe
|
||||
@@ -646,6 +646,8 @@ struct Pager {
|
||||
u8 setMaster; /* True if a m-j name has been written to jrnl */
|
||||
u8 doNotSpill; /* Do not spill the cache when non-zero */
|
||||
u8 subjInMemory; /* True to use in-memory sub-journals */
|
||||
u8 bUseFetch; /* True to use xFetch() */
|
||||
u8 hasBeenUsed; /* True if any content previously read from this pager*/
|
||||
Pgno dbSize; /* Number of pages in the database */
|
||||
Pgno dbOrigSize; /* dbSize before the current transaction */
|
||||
Pgno dbFileSize; /* Number of pages in the database file */
|
||||
@@ -663,9 +665,9 @@ struct Pager {
|
||||
sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
|
||||
PagerSavepoint *aSavepoint; /* Array of active savepoints */
|
||||
int nSavepoint; /* Number of elements in aSavepoint[] */
|
||||
u32 iDataVersion; /* Changes whenever database content changes */
|
||||
char dbFileVers[16]; /* Changes whenever database file changes */
|
||||
|
||||
u8 bUseFetch; /* True to use xFetch() */
|
||||
int nMmapOut; /* Number of mmap pages currently outstanding */
|
||||
sqlite3_int64 szMmap; /* Desired maximum mmap size */
|
||||
PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */
|
||||
@@ -1677,29 +1679,23 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Find a page in the hash table given its page number. Return
|
||||
** a pointer to the page or NULL if the requested page is not
|
||||
** already in memory.
|
||||
*/
|
||||
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
|
||||
PgHdr *p = 0; /* Return value */
|
||||
|
||||
/* It is not possible for a call to PcacheFetch() with createFlag==0 to
|
||||
** fail, since no attempt to allocate dynamic memory will be made.
|
||||
*/
|
||||
(void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Discard the entire contents of the in-memory page-cache.
|
||||
*/
|
||||
static void pager_reset(Pager *pPager){
|
||||
pPager->iDataVersion++;
|
||||
sqlite3BackupRestart(pPager->pBackup);
|
||||
sqlite3PcacheClear(pPager->pPCache);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the pPager->iDataVersion value
|
||||
*/
|
||||
u32 sqlite3PagerDataVersion(Pager *pPager){
|
||||
assert( pPager->eState>PAGER_OPEN );
|
||||
return pPager->iDataVersion;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free all structures in the Pager.aSavepoint[] array and set both
|
||||
** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
|
||||
@@ -1956,6 +1952,14 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = sqlite3OsTruncate(pPager->jfd, 0);
|
||||
if( rc==SQLITE_OK && pPager->fullSync ){
|
||||
/* Make sure the new file size is written into the inode right away.
|
||||
** Otherwise the journal might resurrect following a power loss and
|
||||
** cause the last transaction to roll back. See
|
||||
** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773
|
||||
*/
|
||||
rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
|
||||
}
|
||||
}
|
||||
pPager->journalOff = 0;
|
||||
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
|
||||
@@ -1984,7 +1988,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
|
||||
if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
|
||||
PgHdr *p = pager_lookup(pPager, 1);
|
||||
PgHdr *p = sqlite3PagerLookup(pPager, 1);
|
||||
if( p ){
|
||||
p->pageHash = 0;
|
||||
sqlite3PagerUnrefNotNull(p);
|
||||
@@ -2263,7 +2267,7 @@ static int pager_playback_one_page(
|
||||
if( pagerUseWal(pPager) ){
|
||||
pPg = 0;
|
||||
}else{
|
||||
pPg = pager_lookup(pPager, pgno);
|
||||
pPg = sqlite3PagerLookup(pPager, pgno);
|
||||
}
|
||||
assert( pPg || !MEMDB );
|
||||
assert( pPager->eState!=PAGER_OPEN || pPg==0 );
|
||||
@@ -2443,7 +2447,7 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
|
||||
rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
|
||||
if( rc!=SQLITE_OK ) goto delmaster_out;
|
||||
nMasterPtr = pVfs->mxPathname+1;
|
||||
zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
|
||||
zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1);
|
||||
if( !zMasterJournal ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto delmaster_out;
|
||||
@@ -2512,7 +2516,7 @@ delmaster_out:
|
||||
** If the file on disk is currently larger than nPage pages, then use the VFS
|
||||
** xTruncate() method to truncate it.
|
||||
**
|
||||
** Or, it might might be the case that the file on disk is smaller than
|
||||
** Or, it might be the case that the file on disk is smaller than
|
||||
** nPage pages. Some operating system implementations can get confused if
|
||||
** you try to truncate a file to some size that is larger than it
|
||||
** currently is, so detect this case and write a single zero byte to
|
||||
@@ -2571,7 +2575,7 @@ int sqlite3SectorSize(sqlite3_file *pFile){
|
||||
/*
|
||||
** Set the value of the Pager.sectorSize variable for the given
|
||||
** pager based on the value returned by the xSectorSize method
|
||||
** of the open database file. The sector size will be used used
|
||||
** of the open database file. The sector size will be used
|
||||
** to determine the size and alignment of journal header and
|
||||
** master journal pointers within created journal files.
|
||||
**
|
||||
@@ -2906,7 +2910,7 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){
|
||||
**
|
||||
** For an encrypted database, the situation is more complex: bytes
|
||||
** 24..39 of the database are white noise. But the probability of
|
||||
** white noising equaling 16 bytes of 0xff is vanishingly small so
|
||||
** white noise equaling 16 bytes of 0xff is vanishingly small so
|
||||
** we should still be ok.
|
||||
*/
|
||||
memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
|
||||
@@ -3633,11 +3637,15 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
pager_reset(pPager);
|
||||
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
|
||||
pPager->pageSize = pageSize;
|
||||
rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3PageFree(pPager->pTmpSpace);
|
||||
pPager->pTmpSpace = pNew;
|
||||
sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
|
||||
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
|
||||
pPager->pageSize = pageSize;
|
||||
}else{
|
||||
sqlite3PageFree(pNew);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3771,7 +3779,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
||||
int rc; /* Return code */
|
||||
|
||||
/* Check that this is either a no-op (because the requested lock is
|
||||
** already held, or one of the transistions that the busy-handler
|
||||
** already held), or one of the transitions that the busy-handler
|
||||
** may be invoked during, according to the comment above
|
||||
** sqlite3PagerSetBusyhandler().
|
||||
*/
|
||||
@@ -3890,7 +3898,7 @@ static int pagerAcquireMapPage(
|
||||
PgHdr **ppPage /* OUT: Acquired page object */
|
||||
){
|
||||
PgHdr *p; /* Memory mapped page to return */
|
||||
|
||||
|
||||
if( pPager->pMmapFreelist ){
|
||||
*ppPage = p = pPager->pMmapFreelist;
|
||||
pPager->pMmapFreelist = p->pDirty;
|
||||
@@ -4399,8 +4407,8 @@ static int pagerStress(void *p, PgHdr *pPg){
|
||||
** a rollback or by user request, respectively.
|
||||
**
|
||||
** Spilling is also prohibited when in an error state since that could
|
||||
** lead to database corruption. In the current implementaton it
|
||||
** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
|
||||
** lead to database corruption. In the current implementation it
|
||||
** is impossible for sqlite3PcacheFetch() to be called with createFlag==3
|
||||
** while in the error state, hence it is impossible for this routine to
|
||||
** be called in the error state. Nevertheless, we include a NEVER()
|
||||
** test for the error state as a safeguard against future changes.
|
||||
@@ -4736,22 +4744,23 @@ act_like_temp_file:
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
|
||||
/* If an error occurred in either of the blocks above, free the
|
||||
** Pager structure and close the file.
|
||||
/* Initialize the PCache object. */
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( nExtra<1000 );
|
||||
nExtra = ROUND8(nExtra);
|
||||
rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
|
||||
!memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
|
||||
}
|
||||
|
||||
/* If an error occurred above, free the Pager structure and close the file.
|
||||
*/
|
||||
if( rc!=SQLITE_OK ){
|
||||
assert( !pPager->pTmpSpace );
|
||||
sqlite3OsClose(pPager->fd);
|
||||
sqlite3PageFree(pPager->pTmpSpace);
|
||||
sqlite3_free(pPager);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Initialize the PCache object. */
|
||||
assert( nExtra<1000 );
|
||||
nExtra = ROUND8(nExtra);
|
||||
sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
|
||||
!memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
|
||||
|
||||
PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
|
||||
IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
|
||||
|
||||
@@ -4938,7 +4947,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
|
||||
*pExists = (first!=0);
|
||||
}else if( rc==SQLITE_CANTOPEN ){
|
||||
/* If we cannot open the rollback journal file in order to see if
|
||||
** its has a zero header, that might be due to an I/O error, or
|
||||
** it has a zero header, that might be due to an I/O error, or
|
||||
** it might be due to the race condition described above and in
|
||||
** ticket #3883. Either way, assume that the journal is hot.
|
||||
** This might be a false positive. But if it is, then the
|
||||
@@ -5120,16 +5129,12 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
);
|
||||
}
|
||||
|
||||
if( !pPager->tempFile && (
|
||||
pPager->pBackup
|
||||
|| sqlite3PcachePagecount(pPager->pPCache)>0
|
||||
|| USEFETCH(pPager)
|
||||
)){
|
||||
/* The shared-lock has just been acquired on the database file
|
||||
** and there are already pages in the cache (from a previous
|
||||
** read or write transaction). Check to see if the database
|
||||
** has been modified. If the database has changed, flush the
|
||||
** cache.
|
||||
if( !pPager->tempFile && pPager->hasBeenUsed ){
|
||||
/* The shared-lock has just been acquired then check to
|
||||
** see if the database has been modified. If the database has changed,
|
||||
** flush the cache. The pPager->hasBeenUsed flag prevents this from
|
||||
** occurring on the very first access to a file, in order to save a
|
||||
** single unnecessary sqlite3OsRead() call at the start-up.
|
||||
**
|
||||
** Database changes is detected by looking at 15 bytes beginning
|
||||
** at offset 24 into the file. The first 4 of these 16 bytes are
|
||||
@@ -5294,13 +5299,13 @@ int sqlite3PagerAcquire(
|
||||
if( pgno==0 ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
pPager->hasBeenUsed = 1;
|
||||
|
||||
/* If the pager is in the error state, return an error immediately.
|
||||
** Otherwise, request the page from the PCache layer. */
|
||||
if( pPager->errCode!=SQLITE_OK ){
|
||||
rc = pPager->errCode;
|
||||
}else{
|
||||
|
||||
if( bMmapOk && pagerUseWal(pPager) ){
|
||||
rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
|
||||
if( rc!=SQLITE_OK ) goto pager_acquire_err;
|
||||
@@ -5315,7 +5320,7 @@ int sqlite3PagerAcquire(
|
||||
|
||||
if( rc==SQLITE_OK && pData ){
|
||||
if( pPager->eState>PAGER_READER ){
|
||||
(void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
|
||||
pPg = sqlite3PagerLookup(pPager, pgno);
|
||||
}
|
||||
if( pPg==0 ){
|
||||
rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
|
||||
@@ -5333,7 +5338,16 @@ int sqlite3PagerAcquire(
|
||||
}
|
||||
}
|
||||
|
||||
rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
|
||||
{
|
||||
sqlite3_pcache_page *pBase;
|
||||
pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
|
||||
if( pBase==0 ){
|
||||
rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
|
||||
if( rc!=SQLITE_OK ) goto pager_acquire_err;
|
||||
}
|
||||
pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);
|
||||
if( pPg==0 ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -5430,13 +5444,13 @@ pager_acquire_err:
|
||||
** has ever happened.
|
||||
*/
|
||||
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
|
||||
PgHdr *pPg = 0;
|
||||
sqlite3_pcache_page *pPage;
|
||||
assert( pPager!=0 );
|
||||
assert( pgno!=0 );
|
||||
assert( pPager->pPCache!=0 );
|
||||
assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR );
|
||||
sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
|
||||
return pPg;
|
||||
pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);
|
||||
assert( pPage==0 || pPager->hasBeenUsed );
|
||||
return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5772,6 +5786,97 @@ static int pager_write(PgHdr *pPg){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a variant of sqlite3PagerWrite() that runs when the sector size
|
||||
** is larger than the page size. SQLite makes the (reasonable) assumption that
|
||||
** all bytes of a sector are written together by hardware. Hence, all bytes of
|
||||
** a sector need to be journalled in case of a power loss in the middle of
|
||||
** a write.
|
||||
**
|
||||
** Usually, the sector size is less than or equal to the page size, in which
|
||||
** case pages can be individually written. This routine only runs in the exceptional
|
||||
** case where the page size is smaller than the sector size.
|
||||
*/
|
||||
static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Pgno nPageCount; /* Total number of pages in database file */
|
||||
Pgno pg1; /* First page of the sector pPg is located on. */
|
||||
int nPage = 0; /* Number of pages starting at pg1 to journal */
|
||||
int ii; /* Loop counter */
|
||||
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
|
||||
Pager *pPager = pPg->pPager; /* The pager that owns pPg */
|
||||
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
|
||||
|
||||
/* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
|
||||
** a journal header to be written between the pages journaled by
|
||||
** this function.
|
||||
*/
|
||||
assert( !MEMDB );
|
||||
assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
|
||||
pPager->doNotSpill |= SPILLFLAG_NOSYNC;
|
||||
|
||||
/* This trick assumes that both the page-size and sector-size are
|
||||
** an integer power of 2. It sets variable pg1 to the identifier
|
||||
** of the first page of the sector pPg is located on.
|
||||
*/
|
||||
pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
|
||||
|
||||
nPageCount = pPager->dbSize;
|
||||
if( pPg->pgno>nPageCount ){
|
||||
nPage = (pPg->pgno - pg1)+1;
|
||||
}else if( (pg1+nPagePerSector-1)>nPageCount ){
|
||||
nPage = nPageCount+1-pg1;
|
||||
}else{
|
||||
nPage = nPagePerSector;
|
||||
}
|
||||
assert(nPage>0);
|
||||
assert(pg1<=pPg->pgno);
|
||||
assert((pg1+nPage)>pPg->pgno);
|
||||
|
||||
for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
|
||||
Pgno pg = pg1+ii;
|
||||
PgHdr *pPage;
|
||||
if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
|
||||
if( pg!=PAGER_MJ_PGNO(pPager) ){
|
||||
rc = sqlite3PagerGet(pPager, pg, &pPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_write(pPage);
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}else if( (pPage = sqlite3PagerLookup(pPager, pg))!=0 ){
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
|
||||
** starting at pg1, then it needs to be set for all of them. Because
|
||||
** writing to any of these nPage pages may damage the others, the
|
||||
** journal file must contain sync()ed copies of all of them
|
||||
** before any of them can be written out to the database file.
|
||||
*/
|
||||
if( rc==SQLITE_OK && needSync ){
|
||||
assert( !MEMDB );
|
||||
for(ii=0; ii<nPage; ii++){
|
||||
PgHdr *pPage = sqlite3PagerLookup(pPager, pg1+ii);
|
||||
if( pPage ){
|
||||
pPage->flags |= PGHDR_NEED_SYNC;
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
|
||||
pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Mark a data page as writeable. This routine must be called before
|
||||
** making changes to a page. The caller must check the return value
|
||||
@@ -5786,96 +5891,16 @@ static int pager_write(PgHdr *pPg){
|
||||
** If an error occurs, SQLITE_NOMEM or an IO error code is returned
|
||||
** as appropriate. Otherwise, SQLITE_OK.
|
||||
*/
|
||||
int sqlite3PagerWrite(DbPage *pDbPage){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
PgHdr *pPg = pDbPage;
|
||||
Pager *pPager = pPg->pPager;
|
||||
|
||||
int sqlite3PagerWrite(PgHdr *pPg){
|
||||
assert( (pPg->flags & PGHDR_MMAP)==0 );
|
||||
assert( pPager->eState>=PAGER_WRITER_LOCKED );
|
||||
assert( pPager->eState!=PAGER_ERROR );
|
||||
assert( assert_pager_state(pPager) );
|
||||
|
||||
if( pPager->sectorSize > (u32)pPager->pageSize ){
|
||||
Pgno nPageCount; /* Total number of pages in database file */
|
||||
Pgno pg1; /* First page of the sector pPg is located on. */
|
||||
int nPage = 0; /* Number of pages starting at pg1 to journal */
|
||||
int ii; /* Loop counter */
|
||||
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
|
||||
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
|
||||
|
||||
/* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
|
||||
** a journal header to be written between the pages journaled by
|
||||
** this function.
|
||||
*/
|
||||
assert( !MEMDB );
|
||||
assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
|
||||
pPager->doNotSpill |= SPILLFLAG_NOSYNC;
|
||||
|
||||
/* This trick assumes that both the page-size and sector-size are
|
||||
** an integer power of 2. It sets variable pg1 to the identifier
|
||||
** of the first page of the sector pPg is located on.
|
||||
*/
|
||||
pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
|
||||
|
||||
nPageCount = pPager->dbSize;
|
||||
if( pPg->pgno>nPageCount ){
|
||||
nPage = (pPg->pgno - pg1)+1;
|
||||
}else if( (pg1+nPagePerSector-1)>nPageCount ){
|
||||
nPage = nPageCount+1-pg1;
|
||||
}else{
|
||||
nPage = nPagePerSector;
|
||||
}
|
||||
assert(nPage>0);
|
||||
assert(pg1<=pPg->pgno);
|
||||
assert((pg1+nPage)>pPg->pgno);
|
||||
|
||||
for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
|
||||
Pgno pg = pg1+ii;
|
||||
PgHdr *pPage;
|
||||
if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
|
||||
if( pg!=PAGER_MJ_PGNO(pPager) ){
|
||||
rc = sqlite3PagerGet(pPager, pg, &pPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_write(pPage);
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}else if( (pPage = pager_lookup(pPager, pg))!=0 ){
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
|
||||
** starting at pg1, then it needs to be set for all of them. Because
|
||||
** writing to any of these nPage pages may damage the others, the
|
||||
** journal file must contain sync()ed copies of all of them
|
||||
** before any of them can be written out to the database file.
|
||||
*/
|
||||
if( rc==SQLITE_OK && needSync ){
|
||||
assert( !MEMDB );
|
||||
for(ii=0; ii<nPage; ii++){
|
||||
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
|
||||
if( pPage ){
|
||||
pPage->flags |= PGHDR_NEED_SYNC;
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
|
||||
pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
|
||||
assert( pPg->pPager->eState>=PAGER_WRITER_LOCKED );
|
||||
assert( pPg->pPager->eState!=PAGER_ERROR );
|
||||
assert( assert_pager_state(pPg->pPager) );
|
||||
if( pPg->pPager->sectorSize > (u32)pPg->pPager->pageSize ){
|
||||
return pagerWriteLargeSector(pPg);
|
||||
}else{
|
||||
rc = pager_write(pDbPage);
|
||||
return pager_write(pPg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6291,6 +6316,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
|
||||
}
|
||||
|
||||
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
|
||||
pPager->iDataVersion++;
|
||||
rc = pager_end_transaction(pPager, pPager->setMaster, 1);
|
||||
return pager_error(pPager, rc);
|
||||
}
|
||||
@@ -6771,7 +6797,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
** for the page moved there.
|
||||
*/
|
||||
pPg->flags &= ~PGHDR_NEED_SYNC;
|
||||
pPgOld = pager_lookup(pPager, pgno);
|
||||
pPgOld = sqlite3PagerLookup(pPager, pgno);
|
||||
assert( !pPgOld || pPgOld->nRef==1 );
|
||||
if( pPgOld ){
|
||||
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
|
||||
@@ -6831,6 +6857,18 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The page handle passed as the first argument refers to a dirty page
|
||||
** with a page number other than iNew. This function changes the page's
|
||||
** page number to iNew and sets the value of the PgHdr.flags field to
|
||||
** the value passed as the third parameter.
|
||||
*/
|
||||
void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){
|
||||
assert( pPg->pgno!=iNew );
|
||||
pPg->flags = flags;
|
||||
sqlite3PcacheMove(pPg, iNew);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to the data for the specified page.
|
||||
*/
|
||||
@@ -7047,7 +7085,8 @@ int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
|
||||
int rc = SQLITE_OK;
|
||||
if( pPager->pWal ){
|
||||
rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
|
||||
pPager->xBusyHandler, pPager->pBusyHandlerArg,
|
||||
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
|
||||
pPager->pBusyHandlerArg,
|
||||
pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
|
||||
pnLog, pnCkpt
|
||||
);
|
||||
@@ -7224,11 +7263,12 @@ int sqlite3PagerCloseWal(Pager *pPager){
|
||||
** is empty, return 0.
|
||||
*/
|
||||
int sqlite3PagerWalFramesize(Pager *pPager){
|
||||
assert( pPager->eState==PAGER_READER );
|
||||
assert( pPager->eState>=PAGER_READER );
|
||||
return sqlite3WalFramesize(pPager->pWal);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SQLITE_OMIT_DISKIO */
|
||||
|
||||
/* BEGIN SQLCIPHER */
|
||||
|
||||
@@ -172,6 +172,7 @@ int sqlite3PagerSharedLock(Pager *pPager);
|
||||
|
||||
/* Functions used to query pager state and configuration. */
|
||||
u8 sqlite3PagerIsreadonly(Pager*);
|
||||
u32 sqlite3PagerDataVersion(Pager*);
|
||||
int sqlite3PagerRefcount(Pager*);
|
||||
int sqlite3PagerMemUsed(Pager*);
|
||||
const char *sqlite3PagerFilename(Pager*, int);
|
||||
@@ -188,6 +189,8 @@ int sqlite3SectorSize(sqlite3_file *);
|
||||
/* Functions used to truncate the database file. */
|
||||
void sqlite3PagerTruncateImage(Pager*,Pgno);
|
||||
|
||||
void sqlite3PagerRekey(DbPage*, Pgno, u16);
|
||||
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
|
||||
void *sqlite3PagerCodec(DbPage *);
|
||||
#endif
|
||||
|
||||
+34
-7
@@ -399,9 +399,6 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
|
||||
cmd ::= select(X). {
|
||||
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
|
||||
sqlite3Select(pParse, X, &dest);
|
||||
sqlite3ExplainBegin(pParse->pVdbe);
|
||||
sqlite3ExplainSelect(pParse->pVdbe, X);
|
||||
sqlite3ExplainFinish(pParse->pVdbe);
|
||||
sqlite3SelectDelete(pParse->db, X);
|
||||
}
|
||||
|
||||
@@ -418,13 +415,19 @@ select(A) ::= with(W) selectnowith(X). {
|
||||
int cnt = 0, mxSelect;
|
||||
p->pWith = W;
|
||||
if( p->pPrior ){
|
||||
u16 allValues = SF_Values;
|
||||
pNext = 0;
|
||||
for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
|
||||
pLoop->pNext = pNext;
|
||||
pLoop->selFlags |= SF_Compound;
|
||||
allValues &= pLoop->selFlags;
|
||||
}
|
||||
mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
|
||||
if( mxSelect && cnt>mxSelect ){
|
||||
if( allValues ){
|
||||
p->selFlags |= SF_AllValues;
|
||||
}else if(
|
||||
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0
|
||||
&& cnt>mxSelect
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
|
||||
}
|
||||
}
|
||||
@@ -459,9 +462,33 @@ multiselect_op(A) ::= UNION(OP). {A = @OP;}
|
||||
multiselect_op(A) ::= UNION ALL. {A = TK_ALL;}
|
||||
multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;}
|
||||
%endif SQLITE_OMIT_COMPOUND_SELECT
|
||||
oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
|
||||
oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
|
||||
groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
|
||||
A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset);
|
||||
#if SELECTTRACE_ENABLED
|
||||
/* Populate the Select.zSelName[] string that is used to help with
|
||||
** query planner debugging, to differentiate between multiple Select
|
||||
** objects in a complex query.
|
||||
**
|
||||
** If the SELECT keyword is immediately followed by a C-style comment
|
||||
** then extract the first few alphanumeric characters from within that
|
||||
** comment to be the zSelName value. Otherwise, the label is #N where
|
||||
** is an integer that is incremented with each SELECT statement seen.
|
||||
*/
|
||||
if( A!=0 ){
|
||||
const char *z = S.z+6;
|
||||
int i;
|
||||
sqlite3_snprintf(sizeof(A->zSelName), A->zSelName, "#%d",
|
||||
++pParse->nSelect);
|
||||
while( z[0]==' ' ) z++;
|
||||
if( z[0]=='/' && z[1]=='*' ){
|
||||
z += 2;
|
||||
while( z[0]==' ' ) z++;
|
||||
for(i=0; sqlite3Isalnum(z[i]); i++){}
|
||||
sqlite3_snprintf(sizeof(A->zSelName), A->zSelName, "%.*s", i, z);
|
||||
}
|
||||
}
|
||||
#endif /* SELECTRACE_ENABLED */
|
||||
}
|
||||
oneselect(A) ::= values(X). {A = X;}
|
||||
|
||||
@@ -940,7 +967,7 @@ expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
|
||||
** unary TK_ISNULL or TK_NOTNULL expression. */
|
||||
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
|
||||
sqlite3 *db = pParse->db;
|
||||
if( db->mallocFailed==0 && pY->op==TK_NULL ){
|
||||
if( pY && pA && pY->op==TK_NULL ){
|
||||
pA->op = (u8)op;
|
||||
sqlite3ExprDelete(db, pA->pRight);
|
||||
pA->pRight = 0;
|
||||
|
||||
+249
-224
@@ -31,102 +31,73 @@ struct PCache {
|
||||
PgHdr *pPage1; /* Reference to page 1 */
|
||||
};
|
||||
|
||||
/*
|
||||
** Some of the assert() macros in this code are too expensive to run
|
||||
** even during normal debugging. Use them only rarely on long-running
|
||||
** tests. Enable the expensive asserts using the
|
||||
** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
# define expensive_assert(X) assert(X)
|
||||
#else
|
||||
# define expensive_assert(X)
|
||||
#endif
|
||||
|
||||
/********************************** Linked List Management ********************/
|
||||
|
||||
#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
|
||||
/*
|
||||
** Check that the pCache->pSynced variable is set correctly. If it
|
||||
** is not, either fail an assert or return zero. Otherwise, return
|
||||
** non-zero. This is only used in debugging builds, as follows:
|
||||
**
|
||||
** expensive_assert( pcacheCheckSynced(pCache) );
|
||||
*/
|
||||
static int pcacheCheckSynced(PCache *pCache){
|
||||
PgHdr *p;
|
||||
for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
|
||||
assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
|
||||
}
|
||||
return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
|
||||
}
|
||||
#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
|
||||
/* Allowed values for second argument to pcacheManageDirtyList() */
|
||||
#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */
|
||||
#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */
|
||||
#define PCACHE_DIRTYLIST_FRONT 3 /* Move pPage to the front of the list */
|
||||
|
||||
/*
|
||||
** Remove page pPage from the list of dirty pages.
|
||||
** Manage pPage's participation on the dirty list. Bits of the addRemove
|
||||
** argument determines what operation to do. The 0x01 bit means first
|
||||
** remove pPage from the dirty list. The 0x02 means add pPage back to
|
||||
** the dirty list. Doing both moves pPage to the front of the dirty list.
|
||||
*/
|
||||
static void pcacheRemoveFromDirtyList(PgHdr *pPage){
|
||||
static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
|
||||
PCache *p = pPage->pCache;
|
||||
|
||||
assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
|
||||
assert( pPage->pDirtyPrev || pPage==p->pDirty );
|
||||
|
||||
/* Update the PCache1.pSynced variable if necessary. */
|
||||
if( p->pSynced==pPage ){
|
||||
PgHdr *pSynced = pPage->pDirtyPrev;
|
||||
while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
|
||||
pSynced = pSynced->pDirtyPrev;
|
||||
if( addRemove & PCACHE_DIRTYLIST_REMOVE ){
|
||||
assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
|
||||
assert( pPage->pDirtyPrev || pPage==p->pDirty );
|
||||
|
||||
/* Update the PCache1.pSynced variable if necessary. */
|
||||
if( p->pSynced==pPage ){
|
||||
PgHdr *pSynced = pPage->pDirtyPrev;
|
||||
while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
|
||||
pSynced = pSynced->pDirtyPrev;
|
||||
}
|
||||
p->pSynced = pSynced;
|
||||
}
|
||||
p->pSynced = pSynced;
|
||||
|
||||
if( pPage->pDirtyNext ){
|
||||
pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
|
||||
}else{
|
||||
assert( pPage==p->pDirtyTail );
|
||||
p->pDirtyTail = pPage->pDirtyPrev;
|
||||
}
|
||||
if( pPage->pDirtyPrev ){
|
||||
pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
|
||||
}else{
|
||||
assert( pPage==p->pDirty );
|
||||
p->pDirty = pPage->pDirtyNext;
|
||||
if( p->pDirty==0 && p->bPurgeable ){
|
||||
assert( p->eCreate==1 );
|
||||
p->eCreate = 2;
|
||||
}
|
||||
}
|
||||
pPage->pDirtyNext = 0;
|
||||
pPage->pDirtyPrev = 0;
|
||||
}
|
||||
|
||||
if( pPage->pDirtyNext ){
|
||||
pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
|
||||
}else{
|
||||
assert( pPage==p->pDirtyTail );
|
||||
p->pDirtyTail = pPage->pDirtyPrev;
|
||||
}
|
||||
if( pPage->pDirtyPrev ){
|
||||
pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
|
||||
}else{
|
||||
assert( pPage==p->pDirty );
|
||||
p->pDirty = pPage->pDirtyNext;
|
||||
if( p->pDirty==0 && p->bPurgeable ){
|
||||
assert( p->eCreate==1 );
|
||||
p->eCreate = 2;
|
||||
if( addRemove & PCACHE_DIRTYLIST_ADD ){
|
||||
assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
|
||||
|
||||
pPage->pDirtyNext = p->pDirty;
|
||||
if( pPage->pDirtyNext ){
|
||||
assert( pPage->pDirtyNext->pDirtyPrev==0 );
|
||||
pPage->pDirtyNext->pDirtyPrev = pPage;
|
||||
}else{
|
||||
p->pDirtyTail = pPage;
|
||||
if( p->bPurgeable ){
|
||||
assert( p->eCreate==2 );
|
||||
p->eCreate = 1;
|
||||
}
|
||||
}
|
||||
p->pDirty = pPage;
|
||||
if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
|
||||
p->pSynced = pPage;
|
||||
}
|
||||
}
|
||||
pPage->pDirtyNext = 0;
|
||||
pPage->pDirtyPrev = 0;
|
||||
|
||||
expensive_assert( pcacheCheckSynced(p) );
|
||||
}
|
||||
|
||||
/*
|
||||
** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
|
||||
** pPage).
|
||||
*/
|
||||
static void pcacheAddToDirtyList(PgHdr *pPage){
|
||||
PCache *p = pPage->pCache;
|
||||
|
||||
assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
|
||||
|
||||
pPage->pDirtyNext = p->pDirty;
|
||||
if( pPage->pDirtyNext ){
|
||||
assert( pPage->pDirtyNext->pDirtyPrev==0 );
|
||||
pPage->pDirtyNext->pDirtyPrev = pPage;
|
||||
}else if( p->bPurgeable ){
|
||||
assert( p->eCreate==2 );
|
||||
p->eCreate = 1;
|
||||
}
|
||||
p->pDirty = pPage;
|
||||
if( !p->pDirtyTail ){
|
||||
p->pDirtyTail = pPage;
|
||||
}
|
||||
if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
|
||||
p->pSynced = pPage;
|
||||
}
|
||||
expensive_assert( pcacheCheckSynced(p) );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -134,12 +105,22 @@ static void pcacheAddToDirtyList(PgHdr *pPage){
|
||||
** being used for an in-memory database, this function is a no-op.
|
||||
*/
|
||||
static void pcacheUnpin(PgHdr *p){
|
||||
PCache *pCache = p->pCache;
|
||||
if( pCache->bPurgeable ){
|
||||
if( p->pCache->bPurgeable ){
|
||||
if( p->pgno==1 ){
|
||||
pCache->pPage1 = 0;
|
||||
p->pCache->pPage1 = 0;
|
||||
}
|
||||
sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
|
||||
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute the number of pages of cache requested.
|
||||
*/
|
||||
static int numberOfCachePages(PCache *p){
|
||||
if( p->szCache>=0 ){
|
||||
return p->szCache;
|
||||
}else{
|
||||
return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +156,7 @@ int sqlite3PcacheSize(void){ return sizeof(PCache); }
|
||||
** The caller discovers how much space needs to be allocated by
|
||||
** calling sqlite3PcacheSize().
|
||||
*/
|
||||
void sqlite3PcacheOpen(
|
||||
int sqlite3PcacheOpen(
|
||||
int szPage, /* Size of every page */
|
||||
int szExtra, /* Extra space associated with each page */
|
||||
int bPurgeable, /* True if pages are on backing store */
|
||||
@@ -184,76 +165,76 @@ void sqlite3PcacheOpen(
|
||||
PCache *p /* Preallocated space for the PCache */
|
||||
){
|
||||
memset(p, 0, sizeof(PCache));
|
||||
p->szPage = szPage;
|
||||
p->szPage = 1;
|
||||
p->szExtra = szExtra;
|
||||
p->bPurgeable = bPurgeable;
|
||||
p->eCreate = 2;
|
||||
p->xStress = xStress;
|
||||
p->pStress = pStress;
|
||||
p->szCache = 100;
|
||||
return sqlite3PcacheSetPageSize(p, szPage);
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the page size for PCache object. The caller must ensure that there
|
||||
** are no outstanding page references when this function is called.
|
||||
*/
|
||||
void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
|
||||
int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
|
||||
assert( pCache->nRef==0 && pCache->pDirty==0 );
|
||||
if( pCache->pCache ){
|
||||
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
|
||||
pCache->pCache = 0;
|
||||
if( pCache->szPage ){
|
||||
sqlite3_pcache *pNew;
|
||||
pNew = sqlite3GlobalConfig.pcache2.xCreate(
|
||||
szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)),
|
||||
pCache->bPurgeable
|
||||
);
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
|
||||
if( pCache->pCache ){
|
||||
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
|
||||
}
|
||||
pCache->pCache = pNew;
|
||||
pCache->pPage1 = 0;
|
||||
pCache->szPage = szPage;
|
||||
}
|
||||
pCache->szPage = szPage;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute the number of pages of cache requested.
|
||||
*/
|
||||
static int numberOfCachePages(PCache *p){
|
||||
if( p->szCache>=0 ){
|
||||
return p->szCache;
|
||||
}else{
|
||||
return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to obtain a page from the cache.
|
||||
**
|
||||
** This routine returns a pointer to an sqlite3_pcache_page object if
|
||||
** such an object is already in cache, or if a new one is created.
|
||||
** This routine returns a NULL pointer if the object was not in cache
|
||||
** and could not be created.
|
||||
**
|
||||
** The createFlags should be 0 to check for existing pages and should
|
||||
** be 3 (not 1, but 3) to try to create a new page.
|
||||
**
|
||||
** If the createFlag is 0, then NULL is always returned if the page
|
||||
** is not already in the cache. If createFlag is 1, then a new page
|
||||
** is created only if that can be done without spilling dirty pages
|
||||
** and without exceeding the cache size limit.
|
||||
**
|
||||
** The caller needs to invoke sqlite3PcacheFetchFinish() to properly
|
||||
** initialize the sqlite3_pcache_page object and convert it into a
|
||||
** PgHdr object. The sqlite3PcacheFetch() and sqlite3PcacheFetchFinish()
|
||||
** routines are split this way for performance reasons. When separated
|
||||
** they can both (usually) operate without having to push values to
|
||||
** the stack on entry and pop them back off on exit, which saves a
|
||||
** lot of pushing and popping.
|
||||
*/
|
||||
int sqlite3PcacheFetch(
|
||||
sqlite3_pcache_page *sqlite3PcacheFetch(
|
||||
PCache *pCache, /* Obtain the page from this cache */
|
||||
Pgno pgno, /* Page number to obtain */
|
||||
int createFlag, /* If true, create page if it does not exist already */
|
||||
PgHdr **ppPage /* Write the page here */
|
||||
int createFlag /* If true, create page if it does not exist already */
|
||||
){
|
||||
sqlite3_pcache_page *pPage;
|
||||
PgHdr *pPgHdr = 0;
|
||||
int eCreate;
|
||||
|
||||
assert( pCache!=0 );
|
||||
assert( createFlag==1 || createFlag==0 );
|
||||
assert( pCache->pCache!=0 );
|
||||
assert( createFlag==3 || createFlag==0 );
|
||||
assert( pgno>0 );
|
||||
|
||||
/* If the pluggable cache (sqlite3_pcache*) has not been allocated,
|
||||
** allocate it now.
|
||||
*/
|
||||
if( !pCache->pCache ){
|
||||
sqlite3_pcache *p;
|
||||
if( !createFlag ){
|
||||
*ppPage = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
p = sqlite3GlobalConfig.pcache2.xCreate(
|
||||
pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
|
||||
);
|
||||
if( !p ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
|
||||
pCache->pCache = p;
|
||||
}
|
||||
|
||||
/* eCreate defines what to do if the page does not exist.
|
||||
** 0 Do not allocate a new page. (createFlag==0)
|
||||
** 1 Allocate a new page if doing so is inexpensive.
|
||||
@@ -261,89 +242,135 @@ int sqlite3PcacheFetch(
|
||||
** 2 Allocate a new page even it doing so is difficult.
|
||||
** (createFlag==1 AND !(bPurgeable AND pDirty)
|
||||
*/
|
||||
eCreate = createFlag==0 ? 0 : pCache->eCreate;
|
||||
assert( (createFlag*(1+(!pCache->bPurgeable||!pCache->pDirty)))==eCreate );
|
||||
pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
|
||||
if( !pPage && eCreate==1 ){
|
||||
PgHdr *pPg;
|
||||
eCreate = createFlag & pCache->eCreate;
|
||||
assert( eCreate==0 || eCreate==1 || eCreate==2 );
|
||||
assert( createFlag==0 || pCache->eCreate==eCreate );
|
||||
assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
|
||||
return sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
|
||||
}
|
||||
|
||||
/* Find a dirty page to write-out and recycle. First try to find a
|
||||
** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
|
||||
** cleared), but if that is not possible settle for any other
|
||||
** unreferenced dirty page.
|
||||
*/
|
||||
expensive_assert( pcacheCheckSynced(pCache) );
|
||||
for(pPg=pCache->pSynced;
|
||||
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
|
||||
pPg=pPg->pDirtyPrev
|
||||
);
|
||||
pCache->pSynced = pPg;
|
||||
if( !pPg ){
|
||||
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
|
||||
}
|
||||
if( pPg ){
|
||||
int rc;
|
||||
/*
|
||||
** If the sqlite3PcacheFetch() routine is unable to allocate a new
|
||||
** page because new clean pages are available for reuse and the cache
|
||||
** size limit has been reached, then this routine can be invoked to
|
||||
** try harder to allocate a page. This routine might invoke the stress
|
||||
** callback to spill dirty pages to the journal. It will then try to
|
||||
** allocate the new page and will only fail to allocate a new page on
|
||||
** an OOM error.
|
||||
**
|
||||
** This routine should be invoked only after sqlite3PcacheFetch() fails.
|
||||
*/
|
||||
int sqlite3PcacheFetchStress(
|
||||
PCache *pCache, /* Obtain the page from this cache */
|
||||
Pgno pgno, /* Page number to obtain */
|
||||
sqlite3_pcache_page **ppPage /* Write result here */
|
||||
){
|
||||
PgHdr *pPg;
|
||||
if( pCache->eCreate==2 ) return 0;
|
||||
|
||||
|
||||
/* Find a dirty page to write-out and recycle. First try to find a
|
||||
** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
|
||||
** cleared), but if that is not possible settle for any other
|
||||
** unreferenced dirty page.
|
||||
*/
|
||||
for(pPg=pCache->pSynced;
|
||||
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
|
||||
pPg=pPg->pDirtyPrev
|
||||
);
|
||||
pCache->pSynced = pPg;
|
||||
if( !pPg ){
|
||||
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
|
||||
}
|
||||
if( pPg ){
|
||||
int rc;
|
||||
#ifdef SQLITE_LOG_CACHE_SPILL
|
||||
sqlite3_log(SQLITE_FULL,
|
||||
"spill page %d making room for %d - cache used: %d/%d",
|
||||
pPg->pgno, pgno,
|
||||
sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
|
||||
numberOfCachePages(pCache));
|
||||
sqlite3_log(SQLITE_FULL,
|
||||
"spill page %d making room for %d - cache used: %d/%d",
|
||||
pPg->pgno, pgno,
|
||||
sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
|
||||
numberOfCachePages(pCache));
|
||||
#endif
|
||||
rc = pCache->xStress(pCache->pStress, pPg);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
|
||||
}
|
||||
|
||||
if( pPage ){
|
||||
pPgHdr = (PgHdr *)pPage->pExtra;
|
||||
|
||||
if( !pPgHdr->pPage ){
|
||||
memset(pPgHdr, 0, sizeof(PgHdr));
|
||||
pPgHdr->pPage = pPage;
|
||||
pPgHdr->pData = pPage->pBuf;
|
||||
pPgHdr->pExtra = (void *)&pPgHdr[1];
|
||||
memset(pPgHdr->pExtra, 0, pCache->szExtra);
|
||||
pPgHdr->pCache = pCache;
|
||||
pPgHdr->pgno = pgno;
|
||||
}
|
||||
assert( pPgHdr->pCache==pCache );
|
||||
assert( pPgHdr->pgno==pgno );
|
||||
assert( pPgHdr->pData==pPage->pBuf );
|
||||
assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
|
||||
|
||||
if( 0==pPgHdr->nRef ){
|
||||
pCache->nRef++;
|
||||
}
|
||||
pPgHdr->nRef++;
|
||||
if( pgno==1 ){
|
||||
pCache->pPage1 = pPgHdr;
|
||||
rc = pCache->xStress(pCache->pStress, pPg);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
*ppPage = pPgHdr;
|
||||
return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
|
||||
*ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
|
||||
return *ppPage==0 ? SQLITE_NOMEM : SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a helper routine for sqlite3PcacheFetchFinish()
|
||||
**
|
||||
** In the uncommon case where the page being fetched has not been
|
||||
** initialized, this routine is invoked to do the initialization.
|
||||
** This routine is broken out into a separate function since it
|
||||
** requires extra stack manipulation that can be avoided in the common
|
||||
** case.
|
||||
*/
|
||||
static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
|
||||
PCache *pCache, /* Obtain the page from this cache */
|
||||
Pgno pgno, /* Page number obtained */
|
||||
sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */
|
||||
){
|
||||
PgHdr *pPgHdr;
|
||||
assert( pPage!=0 );
|
||||
pPgHdr = (PgHdr*)pPage->pExtra;
|
||||
assert( pPgHdr->pPage==0 );
|
||||
memset(pPgHdr, 0, sizeof(PgHdr));
|
||||
pPgHdr->pPage = pPage;
|
||||
pPgHdr->pData = pPage->pBuf;
|
||||
pPgHdr->pExtra = (void *)&pPgHdr[1];
|
||||
memset(pPgHdr->pExtra, 0, pCache->szExtra);
|
||||
pPgHdr->pCache = pCache;
|
||||
pPgHdr->pgno = pgno;
|
||||
return sqlite3PcacheFetchFinish(pCache,pgno,pPage);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine converts the sqlite3_pcache_page object returned by
|
||||
** sqlite3PcacheFetch() into an initialized PgHdr object. This routine
|
||||
** must be called after sqlite3PcacheFetch() in order to get a usable
|
||||
** result.
|
||||
*/
|
||||
PgHdr *sqlite3PcacheFetchFinish(
|
||||
PCache *pCache, /* Obtain the page from this cache */
|
||||
Pgno pgno, /* Page number obtained */
|
||||
sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */
|
||||
){
|
||||
PgHdr *pPgHdr;
|
||||
|
||||
if( pPage==0 ) return 0;
|
||||
pPgHdr = (PgHdr *)pPage->pExtra;
|
||||
|
||||
if( !pPgHdr->pPage ){
|
||||
return pcacheFetchFinishWithInit(pCache, pgno, pPage);
|
||||
}
|
||||
if( 0==pPgHdr->nRef ){
|
||||
pCache->nRef++;
|
||||
}
|
||||
pPgHdr->nRef++;
|
||||
if( pgno==1 ){
|
||||
pCache->pPage1 = pPgHdr;
|
||||
}
|
||||
return pPgHdr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Decrement the reference count on a page. If the page is clean and the
|
||||
** reference count drops to 0, then it is made elible for recycling.
|
||||
** reference count drops to 0, then it is made eligible for recycling.
|
||||
*/
|
||||
void sqlite3PcacheRelease(PgHdr *p){
|
||||
void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
|
||||
assert( p->nRef>0 );
|
||||
p->nRef--;
|
||||
if( p->nRef==0 ){
|
||||
PCache *pCache = p->pCache;
|
||||
pCache->nRef--;
|
||||
p->pCache->nRef--;
|
||||
if( (p->flags&PGHDR_DIRTY)==0 ){
|
||||
pcacheUnpin(p);
|
||||
}else{
|
||||
}else if( p->pDirtyPrev!=0 ){
|
||||
/* Move the page to the head of the dirty list. */
|
||||
pcacheRemoveFromDirtyList(p);
|
||||
pcacheAddToDirtyList(p);
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,17 +389,15 @@ void sqlite3PcacheRef(PgHdr *p){
|
||||
** page pointed to by p is invalid.
|
||||
*/
|
||||
void sqlite3PcacheDrop(PgHdr *p){
|
||||
PCache *pCache;
|
||||
assert( p->nRef==1 );
|
||||
if( p->flags&PGHDR_DIRTY ){
|
||||
pcacheRemoveFromDirtyList(p);
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
|
||||
}
|
||||
pCache = p->pCache;
|
||||
pCache->nRef--;
|
||||
p->pCache->nRef--;
|
||||
if( p->pgno==1 ){
|
||||
pCache->pPage1 = 0;
|
||||
p->pCache->pPage1 = 0;
|
||||
}
|
||||
sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
|
||||
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -384,7 +409,7 @@ void sqlite3PcacheMakeDirty(PgHdr *p){
|
||||
assert( p->nRef>0 );
|
||||
if( 0==(p->flags & PGHDR_DIRTY) ){
|
||||
p->flags |= PGHDR_DIRTY;
|
||||
pcacheAddToDirtyList( p);
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +419,7 @@ void sqlite3PcacheMakeDirty(PgHdr *p){
|
||||
*/
|
||||
void sqlite3PcacheMakeClean(PgHdr *p){
|
||||
if( (p->flags & PGHDR_DIRTY) ){
|
||||
pcacheRemoveFromDirtyList(p);
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
|
||||
p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
|
||||
if( p->nRef==0 ){
|
||||
pcacheUnpin(p);
|
||||
@@ -433,8 +458,7 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
|
||||
sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
|
||||
p->pgno = newPgno;
|
||||
if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
|
||||
pcacheRemoveFromDirtyList(p);
|
||||
pcacheAddToDirtyList(p);
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,9 +499,8 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
|
||||
** Close a cache.
|
||||
*/
|
||||
void sqlite3PcacheClose(PCache *pCache){
|
||||
if( pCache->pCache ){
|
||||
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
|
||||
}
|
||||
assert( pCache->pCache!=0 );
|
||||
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -586,11 +609,8 @@ int sqlite3PcachePageRefcount(PgHdr *p){
|
||||
** Return the total number of pages in the cache.
|
||||
*/
|
||||
int sqlite3PcachePagecount(PCache *pCache){
|
||||
int nPage = 0;
|
||||
if( pCache->pCache ){
|
||||
nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
|
||||
}
|
||||
return nPage;
|
||||
assert( pCache->pCache!=0 );
|
||||
return sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
@@ -606,22 +626,27 @@ int sqlite3PcacheGetCachesize(PCache *pCache){
|
||||
** Set the suggested cache-size value.
|
||||
*/
|
||||
void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
|
||||
assert( pCache->pCache!=0 );
|
||||
pCache->szCache = mxPage;
|
||||
if( pCache->pCache ){
|
||||
sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
|
||||
numberOfCachePages(pCache));
|
||||
}
|
||||
sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
|
||||
numberOfCachePages(pCache));
|
||||
}
|
||||
|
||||
/*
|
||||
** Free up as much memory as possible from the page cache.
|
||||
*/
|
||||
void sqlite3PcacheShrink(PCache *pCache){
|
||||
if( pCache->pCache ){
|
||||
sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
|
||||
}
|
||||
assert( pCache->pCache!=0 );
|
||||
sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the size of the header added by this middleware layer
|
||||
** in the page-cache hierarchy.
|
||||
*/
|
||||
int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
|
||||
|
||||
|
||||
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** For all dirty pages currently in the cache, invoke the specified
|
||||
|
||||
+9
-3
@@ -68,7 +68,7 @@ void sqlite3PCacheBufferSetup(void *, int sz, int n);
|
||||
** Under memory stress, invoke xStress to try to make pages clean.
|
||||
** Only clean and unpinned pages can be reclaimed.
|
||||
*/
|
||||
void sqlite3PcacheOpen(
|
||||
int sqlite3PcacheOpen(
|
||||
int szPage, /* Size of every page */
|
||||
int szExtra, /* Extra space associated with each page */
|
||||
int bPurgeable, /* True if pages are on backing store */
|
||||
@@ -78,7 +78,7 @@ void sqlite3PcacheOpen(
|
||||
);
|
||||
|
||||
/* Modify the page-size after the cache has been created. */
|
||||
void sqlite3PcacheSetPageSize(PCache *, int);
|
||||
int sqlite3PcacheSetPageSize(PCache *, int);
|
||||
|
||||
/* Return the size in bytes of a PCache object. Used to preallocate
|
||||
** storage space.
|
||||
@@ -88,7 +88,9 @@ int sqlite3PcacheSize(void);
|
||||
/* One release per successful fetch. Page is pinned until released.
|
||||
** Reference counted.
|
||||
*/
|
||||
int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**);
|
||||
sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag);
|
||||
int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**);
|
||||
PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage);
|
||||
void sqlite3PcacheRelease(PgHdr*);
|
||||
|
||||
void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
|
||||
@@ -158,4 +160,8 @@ void sqlite3PcacheStats(int*,int*,int*,int*);
|
||||
|
||||
void sqlite3PCacheSetDefault(void);
|
||||
|
||||
/* Return the header size */
|
||||
int sqlite3HeaderSizePcache(void);
|
||||
int sqlite3HeaderSizePcache1(void);
|
||||
|
||||
#endif /* _PCACHE_H_ */
|
||||
|
||||
+117
-104
@@ -13,7 +13,7 @@
|
||||
** This file implements the default page cache implementation (the
|
||||
** sqlite3_pcache interface). It also contains part of the implementation
|
||||
** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
|
||||
** If the default page cache implementation is overriden, then neither of
|
||||
** If the default page cache implementation is overridden, then neither of
|
||||
** these two features are available.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef struct PgFreeslot PgFreeslot;
|
||||
typedef struct PGroup PGroup;
|
||||
|
||||
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
|
||||
** of one or more PCaches that are able to recycle each others unpinned
|
||||
** of one or more PCaches that are able to recycle each other's unpinned
|
||||
** pages when they are under memory pressure. A PGroup is an instance of
|
||||
** the following object.
|
||||
**
|
||||
@@ -296,7 +296,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
|
||||
pPg = 0;
|
||||
}
|
||||
#else
|
||||
pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
|
||||
pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra);
|
||||
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
|
||||
#endif
|
||||
pcache1EnterMutex(pCache->pGroup);
|
||||
@@ -383,7 +383,7 @@ static int pcache1UnderMemoryPressure(PCache1 *pCache){
|
||||
**
|
||||
** The PCache mutex must be held when this function is called.
|
||||
*/
|
||||
static int pcache1ResizeHash(PCache1 *p){
|
||||
static void pcache1ResizeHash(PCache1 *p){
|
||||
PgHdr1 **apNew;
|
||||
unsigned int nNew;
|
||||
unsigned int i;
|
||||
@@ -415,8 +415,6 @@ static int pcache1ResizeHash(PCache1 *p){
|
||||
p->apHash = apNew;
|
||||
p->nHash = nNew;
|
||||
}
|
||||
|
||||
return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -551,6 +549,9 @@ static void pcache1Shutdown(void *NotUsed){
|
||||
memset(&pcache1, 0, sizeof(pcache1));
|
||||
}
|
||||
|
||||
/* forward declaration */
|
||||
static void pcache1Destroy(sqlite3_pcache *p);
|
||||
|
||||
/*
|
||||
** Implementation of the sqlite3_pcache.xCreate method.
|
||||
**
|
||||
@@ -595,12 +596,17 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
|
||||
pCache->szPage = szPage;
|
||||
pCache->szExtra = szExtra;
|
||||
pCache->bPurgeable = (bPurgeable ? 1 : 0);
|
||||
pcache1EnterMutex(pGroup);
|
||||
pcache1ResizeHash(pCache);
|
||||
if( bPurgeable ){
|
||||
pCache->nMin = 10;
|
||||
pcache1EnterMutex(pGroup);
|
||||
pGroup->nMinPage += pCache->nMin;
|
||||
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
|
||||
pcache1LeaveMutex(pGroup);
|
||||
}
|
||||
pcache1LeaveMutex(pGroup);
|
||||
if( pCache->nHash==0 ){
|
||||
pcache1Destroy((sqlite3_pcache*)pCache);
|
||||
pCache = 0;
|
||||
}
|
||||
}
|
||||
return (sqlite3_pcache *)pCache;
|
||||
@@ -656,6 +662,95 @@ static int pcache1Pagecount(sqlite3_pcache *p){
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described
|
||||
** in the header of the pcache1Fetch() procedure.
|
||||
**
|
||||
** This steps are broken out into a separate procedure because they are
|
||||
** usually not needed, and by avoiding the stack initialization required
|
||||
** for these steps, the main pcache1Fetch() procedure can run faster.
|
||||
*/
|
||||
static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||
PCache1 *pCache,
|
||||
unsigned int iKey,
|
||||
int createFlag
|
||||
){
|
||||
unsigned int nPinned;
|
||||
PGroup *pGroup = pCache->pGroup;
|
||||
PgHdr1 *pPage = 0;
|
||||
|
||||
/* Step 3: Abort if createFlag is 1 but the cache is nearly full */
|
||||
assert( pCache->nPage >= pCache->nRecyclable );
|
||||
nPinned = pCache->nPage - pCache->nRecyclable;
|
||||
assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
|
||||
assert( pCache->n90pct == pCache->nMax*9/10 );
|
||||
if( createFlag==1 && (
|
||||
nPinned>=pGroup->mxPinned
|
||||
|| nPinned>=pCache->n90pct
|
||||
|| (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable<nPinned)
|
||||
)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache);
|
||||
assert( pCache->nHash>0 && pCache->apHash );
|
||||
|
||||
/* Step 4. Try to recycle a page. */
|
||||
if( pCache->bPurgeable && pGroup->pLruTail && (
|
||||
(pCache->nPage+1>=pCache->nMax)
|
||||
|| pGroup->nCurrentPage>=pGroup->nMaxPage
|
||||
|| pcache1UnderMemoryPressure(pCache)
|
||||
)){
|
||||
PCache1 *pOther;
|
||||
pPage = pGroup->pLruTail;
|
||||
assert( pPage->isPinned==0 );
|
||||
pcache1RemoveFromHash(pPage);
|
||||
pcache1PinPage(pPage);
|
||||
pOther = pPage->pCache;
|
||||
|
||||
/* We want to verify that szPage and szExtra are the same for pOther
|
||||
** and pCache. Assert that we can verify this by comparing sums. */
|
||||
assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
|
||||
assert( pCache->szExtra<512 );
|
||||
assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
|
||||
assert( pOther->szExtra<512 );
|
||||
|
||||
if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
|
||||
pcache1FreePage(pPage);
|
||||
pPage = 0;
|
||||
}else{
|
||||
pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 5. If a usable page buffer has still not been found,
|
||||
** attempt to allocate a new one.
|
||||
*/
|
||||
if( !pPage ){
|
||||
if( createFlag==1 ) sqlite3BeginBenignMalloc();
|
||||
pPage = pcache1AllocPage(pCache);
|
||||
if( createFlag==1 ) sqlite3EndBenignMalloc();
|
||||
}
|
||||
|
||||
if( pPage ){
|
||||
unsigned int h = iKey % pCache->nHash;
|
||||
pCache->nPage++;
|
||||
pPage->iKey = iKey;
|
||||
pPage->pNext = pCache->apHash[h];
|
||||
pPage->pCache = pCache;
|
||||
pPage->pLruPrev = 0;
|
||||
pPage->pLruNext = 0;
|
||||
pPage->isPinned = 1;
|
||||
*(void **)pPage->page.pExtra = 0;
|
||||
pCache->apHash[h] = pPage;
|
||||
if( iKey>pCache->iMaxKey ){
|
||||
pCache->iMaxKey = iKey;
|
||||
}
|
||||
}
|
||||
return pPage;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the sqlite3_pcache.xFetch method.
|
||||
**
|
||||
@@ -715,9 +810,7 @@ static sqlite3_pcache_page *pcache1Fetch(
|
||||
unsigned int iKey,
|
||||
int createFlag
|
||||
){
|
||||
unsigned int nPinned;
|
||||
PCache1 *pCache = (PCache1 *)p;
|
||||
PGroup *pGroup;
|
||||
PgHdr1 *pPage = 0;
|
||||
|
||||
assert( offsetof(PgHdr1,page)==0 );
|
||||
@@ -725,107 +818,22 @@ static sqlite3_pcache_page *pcache1Fetch(
|
||||
assert( pCache->bPurgeable || pCache->nMin==0 );
|
||||
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
|
||||
assert( pCache->nMin==0 || pCache->bPurgeable );
|
||||
pcache1EnterMutex(pGroup = pCache->pGroup);
|
||||
assert( pCache->nHash>0 );
|
||||
pcache1EnterMutex(pCache->pGroup);
|
||||
|
||||
/* Step 1: Search the hash table for an existing entry. */
|
||||
if( pCache->nHash>0 ){
|
||||
unsigned int h = iKey % pCache->nHash;
|
||||
for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);
|
||||
}
|
||||
pPage = pCache->apHash[iKey % pCache->nHash];
|
||||
while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; }
|
||||
|
||||
/* Step 2: Abort if no existing page is found and createFlag is 0 */
|
||||
if( pPage ){
|
||||
if( !pPage->isPinned ) pcache1PinPage(pPage);
|
||||
goto fetch_out;
|
||||
}else if( createFlag ){
|
||||
/* Steps 3, 4, and 5 implemented by this subroutine */
|
||||
pPage = pcache1FetchStage2(pCache, iKey, createFlag);
|
||||
}
|
||||
if( createFlag==0 ){
|
||||
goto fetch_out;
|
||||
}
|
||||
|
||||
/* The pGroup local variable will normally be initialized by the
|
||||
** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined,
|
||||
** then pcache1EnterMutex() is a no-op, so we have to initialize the
|
||||
** local variable here. Delaying the initialization of pGroup is an
|
||||
** optimization: The common case is to exit the module before reaching
|
||||
** this point.
|
||||
*/
|
||||
#ifdef SQLITE_MUTEX_OMIT
|
||||
pGroup = pCache->pGroup;
|
||||
#endif
|
||||
|
||||
/* Step 3: Abort if createFlag is 1 but the cache is nearly full */
|
||||
assert( pCache->nPage >= pCache->nRecyclable );
|
||||
nPinned = pCache->nPage - pCache->nRecyclable;
|
||||
assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
|
||||
assert( pCache->n90pct == pCache->nMax*9/10 );
|
||||
if( createFlag==1 && (
|
||||
nPinned>=pGroup->mxPinned
|
||||
|| nPinned>=pCache->n90pct
|
||||
|| pcache1UnderMemoryPressure(pCache)
|
||||
)){
|
||||
goto fetch_out;
|
||||
}
|
||||
|
||||
if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
|
||||
goto fetch_out;
|
||||
}
|
||||
assert( pCache->nHash>0 && pCache->apHash );
|
||||
|
||||
/* Step 4. Try to recycle a page. */
|
||||
if( pCache->bPurgeable && pGroup->pLruTail && (
|
||||
(pCache->nPage+1>=pCache->nMax)
|
||||
|| pGroup->nCurrentPage>=pGroup->nMaxPage
|
||||
|| pcache1UnderMemoryPressure(pCache)
|
||||
)){
|
||||
PCache1 *pOther;
|
||||
pPage = pGroup->pLruTail;
|
||||
assert( pPage->isPinned==0 );
|
||||
pcache1RemoveFromHash(pPage);
|
||||
pcache1PinPage(pPage);
|
||||
pOther = pPage->pCache;
|
||||
|
||||
/* We want to verify that szPage and szExtra are the same for pOther
|
||||
** and pCache. Assert that we can verify this by comparing sums. */
|
||||
assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
|
||||
assert( pCache->szExtra<512 );
|
||||
assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
|
||||
assert( pOther->szExtra<512 );
|
||||
|
||||
if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
|
||||
pcache1FreePage(pPage);
|
||||
pPage = 0;
|
||||
}else{
|
||||
pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 5. If a usable page buffer has still not been found,
|
||||
** attempt to allocate a new one.
|
||||
*/
|
||||
if( !pPage ){
|
||||
if( createFlag==1 ) sqlite3BeginBenignMalloc();
|
||||
pPage = pcache1AllocPage(pCache);
|
||||
if( createFlag==1 ) sqlite3EndBenignMalloc();
|
||||
}
|
||||
|
||||
if( pPage ){
|
||||
unsigned int h = iKey % pCache->nHash;
|
||||
pCache->nPage++;
|
||||
pPage->iKey = iKey;
|
||||
pPage->pNext = pCache->apHash[h];
|
||||
pPage->pCache = pCache;
|
||||
pPage->pLruPrev = 0;
|
||||
pPage->pLruNext = 0;
|
||||
pPage->isPinned = 1;
|
||||
*(void **)pPage->page.pExtra = 0;
|
||||
pCache->apHash[h] = pPage;
|
||||
}
|
||||
|
||||
fetch_out:
|
||||
if( pPage && iKey>pCache->iMaxKey ){
|
||||
pCache->iMaxKey = iKey;
|
||||
}
|
||||
pcache1LeaveMutex(pGroup);
|
||||
assert( pPage==0 || pCache->iMaxKey>=iKey );
|
||||
pcache1LeaveMutex(pCache->pGroup);
|
||||
return (sqlite3_pcache_page*)pPage;
|
||||
}
|
||||
|
||||
@@ -973,6 +981,11 @@ void sqlite3PCacheSetDefault(void){
|
||||
sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the size of the header on each page of this PCACHE implementation.
|
||||
*/
|
||||
int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
/*
|
||||
** This function is called to free superfluous dynamically allocated memory
|
||||
|
||||
+60
-34
@@ -61,15 +61,17 @@
|
||||
#define PragTyp_TABLE_INFO 30
|
||||
#define PragTyp_TEMP_STORE 31
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 32
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 33
|
||||
#define PragTyp_WAL_CHECKPOINT 34
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 35
|
||||
#define PragTyp_HEXKEY 36
|
||||
#define PragTyp_KEY 37
|
||||
#define PragTyp_REKEY 38
|
||||
#define PragTyp_LOCK_STATUS 39
|
||||
#define PragTyp_PARSER_TRACE 40
|
||||
#define PragTyp_THREADS 33
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 34
|
||||
#define PragTyp_WAL_CHECKPOINT 35
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 36
|
||||
#define PragTyp_HEXKEY 37
|
||||
#define PragTyp_KEY 38
|
||||
#define PragTyp_REKEY 39
|
||||
#define PragTyp_LOCK_STATUS 40
|
||||
#define PragTyp_PARSER_TRACE 41
|
||||
#define PragFlag_NeedSchema 0x01
|
||||
#define PragFlag_ReadOnly 0x02
|
||||
static const struct sPragmaNames {
|
||||
const char *const zName; /* Name of pragma */
|
||||
u8 ePragTyp; /* PragTyp_XXX value */
|
||||
@@ -86,7 +88,7 @@ static const struct sPragmaNames {
|
||||
{ /* zName: */ "application_id",
|
||||
/* ePragTyp: */ PragTyp_HEADER_VALUE,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
/* iArg: */ BTREE_APPLICATION_ID },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_AUTOVACUUM)
|
||||
{ /* zName: */ "auto_vacuum",
|
||||
@@ -152,6 +154,12 @@ static const struct sPragmaNames {
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
{ /* zName: */ "data_version",
|
||||
/* ePragTyp: */ PragTyp_HEADER_VALUE,
|
||||
/* ePragFlag: */ PragFlag_ReadOnly,
|
||||
/* iArg: */ BTREE_DATA_VERSION },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
{ /* zName: */ "database_list",
|
||||
/* ePragTyp: */ PragTyp_DATABASE_LIST,
|
||||
@@ -207,8 +215,8 @@ static const struct sPragmaNames {
|
||||
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
{ /* zName: */ "freelist_count",
|
||||
/* ePragTyp: */ PragTyp_HEADER_VALUE,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
/* ePragFlag: */ PragFlag_ReadOnly,
|
||||
/* iArg: */ BTREE_FREE_PAGE_COUNT },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
{ /* zName: */ "full_column_names",
|
||||
@@ -360,7 +368,7 @@ static const struct sPragmaNames {
|
||||
{ /* zName: */ "schema_version",
|
||||
/* ePragTyp: */ PragTyp_HEADER_VALUE,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
/* iArg: */ BTREE_SCHEMA_VERSION },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
{ /* zName: */ "secure_delete",
|
||||
@@ -418,11 +426,15 @@ static const struct sPragmaNames {
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
{ /* zName: */ "threads",
|
||||
/* ePragTyp: */ PragTyp_THREADS,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
{ /* zName: */ "user_version",
|
||||
/* ePragTyp: */ PragTyp_HEADER_VALUE,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
/* iArg: */ BTREE_USER_VERSION },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
#if defined(SQLITE_DEBUG)
|
||||
@@ -465,7 +477,7 @@ static const struct sPragmaNames {
|
||||
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
|
||||
#endif
|
||||
};
|
||||
/* Number of pragmas: 56 on by default, 69 total. */
|
||||
/* Number of pragmas: 58 on by default, 71 total. */
|
||||
/* End of the automatically generated pragma table.
|
||||
***************************************************************************/
|
||||
|
||||
@@ -715,7 +727,7 @@ void sqlite3Pragma(
|
||||
Token *pId; /* Pointer to <id> token */
|
||||
char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
|
||||
int iDb; /* Database index for <database> */
|
||||
int lwr, upr, mid; /* Binary search bounds */
|
||||
int lwr, upr, mid = 0; /* Binary search bounds */
|
||||
int rc; /* return value form SQLITE_FCNTL_PRAGMA */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
Db *pDb; /* The specific database being pragmaed */
|
||||
@@ -1408,6 +1420,12 @@ void sqlite3Pragma(
|
||||
** in auto-commit mode. */
|
||||
mask &= ~(SQLITE_ForeignKeys);
|
||||
}
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
if( db->auth.authLevel==UAUTH_User ){
|
||||
/* Do not allow non-admin users to modify the schema arbitrarily */
|
||||
mask &= ~(SQLITE_WriteSchema);
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3GetBoolean(zRight, 0) ){
|
||||
db->flags |= mask;
|
||||
@@ -2085,7 +2103,8 @@ void sqlite3Pragma(
|
||||
){
|
||||
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
|
||||
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
|
||||
ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
|
||||
SCHEMA_ENC(db) = ENC(db) =
|
||||
pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2130,24 +2149,9 @@ void sqlite3Pragma(
|
||||
** applications for any purpose.
|
||||
*/
|
||||
case PragTyp_HEADER_VALUE: {
|
||||
int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
|
||||
int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
switch( zLeft[0] ){
|
||||
case 'a': case 'A':
|
||||
iCookie = BTREE_APPLICATION_ID;
|
||||
break;
|
||||
case 'f': case 'F':
|
||||
iCookie = BTREE_FREE_PAGE_COUNT;
|
||||
break;
|
||||
case 's': case 'S':
|
||||
iCookie = BTREE_SCHEMA_VERSION;
|
||||
break;
|
||||
default:
|
||||
iCookie = BTREE_USER_VERSION;
|
||||
break;
|
||||
}
|
||||
|
||||
if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){
|
||||
if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){
|
||||
/* Write the specified cookie value */
|
||||
static const VdbeOpList setCookie[] = {
|
||||
{ OP_Transaction, 0, 1, 0}, /* 0 */
|
||||
@@ -2200,7 +2204,7 @@ void sqlite3Pragma(
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/*
|
||||
** PRAGMA [database.]wal_checkpoint = passive|full|restart
|
||||
** PRAGMA [database.]wal_checkpoint = passive|full|restart|truncate
|
||||
**
|
||||
** Checkpoint the database.
|
||||
*/
|
||||
@@ -2212,6 +2216,8 @@ void sqlite3Pragma(
|
||||
eMode = SQLITE_CHECKPOINT_FULL;
|
||||
}else if( sqlite3StrICmp(zRight, "restart")==0 ){
|
||||
eMode = SQLITE_CHECKPOINT_RESTART;
|
||||
}else if( sqlite3StrICmp(zRight, "truncate")==0 ){
|
||||
eMode = SQLITE_CHECKPOINT_TRUNCATE;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeSetNumCols(v, 3);
|
||||
@@ -2289,6 +2295,26 @@ void sqlite3Pragma(
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA threads
|
||||
** PRAGMA threads = N
|
||||
**
|
||||
** Configure the maximum number of worker threads. Return the new
|
||||
** maximum, which might be less than requested.
|
||||
*/
|
||||
case PragTyp_THREADS: {
|
||||
sqlite3_int64 N;
|
||||
if( zRight
|
||||
&& sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
|
||||
&& N>=0
|
||||
){
|
||||
sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff));
|
||||
}
|
||||
returnSingleInt(pParse, "threads",
|
||||
sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
/*
|
||||
** Report the current state of file logs for all databases
|
||||
|
||||
+19
-11
@@ -328,7 +328,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
db->aDb[iDb].zName, zMasterName);
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
|
||||
sqlite3_xauth xAuth;
|
||||
xAuth = db->xAuth;
|
||||
db->xAuth = 0;
|
||||
#endif
|
||||
@@ -394,8 +394,11 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
||||
int commit_internal = !(db->flags&SQLITE_InternChanges);
|
||||
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
|
||||
assert( db->init.busy==0 );
|
||||
rc = SQLITE_OK;
|
||||
db->init.busy = 1;
|
||||
ENC(db) = SCHEMA_ENC(db);
|
||||
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
||||
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
|
||||
rc = sqlite3InitOne(db, i, pzErrMsg);
|
||||
@@ -409,8 +412,8 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
||||
** schema may contain references to objects in other databases.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_TEMPDB
|
||||
if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
|
||||
&& !DbHasProperty(db, 1, DB_SchemaLoaded) ){
|
||||
assert( db->nDb>1 );
|
||||
if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, 1, pzErrMsg);
|
||||
if( rc ){
|
||||
sqlite3ResetOneSchema(db, 1);
|
||||
@@ -593,7 +596,7 @@ static int sqlite3Prepare(
|
||||
rc = sqlite3BtreeSchemaLocked(pBt);
|
||||
if( rc ){
|
||||
const char *zDb = db->aDb[i].zName;
|
||||
sqlite3Error(db, rc, "database schema is locked: %s", zDb);
|
||||
sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
|
||||
testcase( db->flags & SQLITE_ReadUncommitted );
|
||||
goto end_prepare;
|
||||
}
|
||||
@@ -610,7 +613,7 @@ static int sqlite3Prepare(
|
||||
testcase( nBytes==mxLen );
|
||||
testcase( nBytes==mxLen+1 );
|
||||
if( nBytes>mxLen ){
|
||||
sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
|
||||
sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long");
|
||||
rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
|
||||
goto end_prepare;
|
||||
}
|
||||
@@ -677,10 +680,10 @@ static int sqlite3Prepare(
|
||||
}
|
||||
|
||||
if( zErrMsg ){
|
||||
sqlite3Error(db, rc, "%s", zErrMsg);
|
||||
sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
|
||||
sqlite3DbFree(db, zErrMsg);
|
||||
}else{
|
||||
sqlite3Error(db, rc, 0);
|
||||
sqlite3Error(db, rc);
|
||||
}
|
||||
|
||||
/* Delete any TriggerPrg structures allocated while parsing this statement. */
|
||||
@@ -708,9 +711,12 @@ static int sqlite3LockAndPrepare(
|
||||
const char **pzTail /* OUT: End of parsed string */
|
||||
){
|
||||
int rc;
|
||||
assert( ppStmt!=0 );
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
*ppStmt = 0;
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
@@ -817,9 +823,11 @@ static int sqlite3Prepare16(
|
||||
const char *zTail8 = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( ppStmt );
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
*ppStmt = 0;
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
if( nBytes>=0 ){
|
||||
|
||||
+121
-22
@@ -201,7 +201,7 @@ void sqlite3VXPrintf(
|
||||
const et_info *infop; /* Pointer to the appropriate info structure */
|
||||
char *zOut; /* Rendering buffer */
|
||||
int nOut; /* Size of the rendering buffer */
|
||||
char *zExtra; /* Malloced memory used by some conversion */
|
||||
char *zExtra = 0; /* Malloced memory used by some conversion */
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int exp, e2; /* exponent of real numbers */
|
||||
int nsd; /* Number of significant digits returned */
|
||||
@@ -212,6 +212,13 @@ void sqlite3VXPrintf(
|
||||
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
|
||||
char buf[etBUFSIZE]; /* Conversion buffer */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ap==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
sqlite3StrAccumReset(pAccum);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bufpt = 0;
|
||||
if( bFlags ){
|
||||
if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
|
||||
@@ -224,9 +231,13 @@ void sqlite3VXPrintf(
|
||||
for(; (c=(*fmt))!=0; ++fmt){
|
||||
if( c!='%' ){
|
||||
bufpt = (char *)fmt;
|
||||
while( (c=(*++fmt))!='%' && c!=0 ){};
|
||||
#if HAVE_STRCHRNUL
|
||||
fmt = strchrnul(fmt, '%');
|
||||
#else
|
||||
do{ fmt++; }while( *fmt && *fmt != '%' );
|
||||
#endif
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt));
|
||||
if( c==0 ) break;
|
||||
if( *fmt==0 ) break;
|
||||
}
|
||||
if( (c=(*++fmt))==0 ){
|
||||
sqlite3StrAccumAppend(pAccum, "%", 1);
|
||||
@@ -314,7 +325,6 @@ void sqlite3VXPrintf(
|
||||
break;
|
||||
}
|
||||
}
|
||||
zExtra = 0;
|
||||
|
||||
/*
|
||||
** At this point, variables are initialized as follows:
|
||||
@@ -605,13 +615,16 @@ void sqlite3VXPrintf(
|
||||
}else{
|
||||
c = va_arg(ap,int);
|
||||
}
|
||||
buf[0] = (char)c;
|
||||
if( precision>=0 ){
|
||||
for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
|
||||
length = precision;
|
||||
}else{
|
||||
length =1;
|
||||
if( precision>1 ){
|
||||
width -= precision-1;
|
||||
if( width>1 && !flag_leftjustify ){
|
||||
sqlite3AppendChar(pAccum, width-1, ' ');
|
||||
width = 0;
|
||||
}
|
||||
sqlite3AppendChar(pAccum, precision-1, c);
|
||||
}
|
||||
length = 1;
|
||||
buf[0] = c;
|
||||
bufpt = buf;
|
||||
break;
|
||||
case etSTRING:
|
||||
@@ -712,11 +725,14 @@ void sqlite3VXPrintf(
|
||||
** the output.
|
||||
*/
|
||||
width -= length;
|
||||
if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
|
||||
if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, length);
|
||||
if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
|
||||
if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
|
||||
|
||||
if( zExtra ) sqlite3_free(zExtra);
|
||||
if( zExtra ){
|
||||
sqlite3_free(zExtra);
|
||||
zExtra = 0;
|
||||
}
|
||||
}/* End for loop over the format string */
|
||||
} /* End of function */
|
||||
|
||||
@@ -743,6 +759,11 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
|
||||
i64 szNew = p->nChar;
|
||||
szNew += N + 1;
|
||||
if( szNew+p->nChar<=p->mxAlloc ){
|
||||
/* Force exponential buffer size growth as long as it does not overflow,
|
||||
** to avoid having to call this routine too often */
|
||||
szNew += p->nChar;
|
||||
}
|
||||
if( szNew > p->mxAlloc ){
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
@@ -759,6 +780,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
assert( p->zText!=0 || p->nChar==0 );
|
||||
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
||||
p->zText = zNew;
|
||||
p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
|
||||
}else{
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
@@ -769,11 +791,11 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
}
|
||||
|
||||
/*
|
||||
** Append N space characters to the given string buffer.
|
||||
** Append N copies of character c to the given string buffer.
|
||||
*/
|
||||
void sqlite3AppendSpace(StrAccum *p, int N){
|
||||
void sqlite3AppendChar(StrAccum *p, int N, char c){
|
||||
if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
|
||||
while( (N--)>0 ) p->zText[p->nChar++] = ' ';
|
||||
while( (N--)>0 ) p->zText[p->nChar++] = c;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -784,7 +806,7 @@ void sqlite3AppendSpace(StrAccum *p, int N){
|
||||
** work (enlarging the buffer) using tail recursion, so that the
|
||||
** sqlite3StrAccumAppend() routine can use fast calling semantics.
|
||||
*/
|
||||
static void enlargeAndAppend(StrAccum *p, const char *z, int N){
|
||||
static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
|
||||
N = sqlite3StrAccumEnlarge(p, N);
|
||||
if( N>0 ){
|
||||
memcpy(&p->zText[p->nChar], z, N);
|
||||
@@ -803,11 +825,11 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
assert( p->accError==0 || p->nAlloc==0 );
|
||||
if( p->nChar+N >= p->nAlloc ){
|
||||
enlargeAndAppend(p,z,N);
|
||||
return;
|
||||
}else{
|
||||
assert( p->zText );
|
||||
p->nChar += N;
|
||||
memcpy(&p->zText[p->nChar-N], z, N);
|
||||
}
|
||||
assert( p->zText );
|
||||
memcpy(&p->zText[p->nChar], z, N);
|
||||
p->nChar += N;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -904,7 +926,7 @@ char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
|
||||
|
||||
/*
|
||||
** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
|
||||
** the string and before returnning. This routine is intended to be used
|
||||
** the string and before returning. This routine is intended to be used
|
||||
** to modify an existing string. For example:
|
||||
**
|
||||
** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
|
||||
@@ -928,6 +950,13 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){
|
||||
char *z;
|
||||
char zBase[SQLITE_PRINT_BUF_SIZE];
|
||||
StrAccum acc;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( zFormat==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
#endif
|
||||
@@ -970,6 +999,13 @@ char *sqlite3_mprintf(const char *zFormat, ...){
|
||||
char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
|
||||
StrAccum acc;
|
||||
if( n<=0 ) return zBuf;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( zBuf==0 || zFormat==0 ) {
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
if( zBuf && n>0 ) zBuf[0] = 0;
|
||||
return zBuf;
|
||||
}
|
||||
#endif
|
||||
sqlite3StrAccumInit(&acc, zBuf, n, 0);
|
||||
acc.useMalloc = 0;
|
||||
sqlite3VXPrintf(&acc, 0, zFormat, ap);
|
||||
@@ -1037,6 +1073,69 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*************************************************************************
|
||||
** Routines for implementing the "TreeView" display of hierarchical
|
||||
** data structures for debugging.
|
||||
**
|
||||
** The main entry points (coded elsewhere) are:
|
||||
** sqlite3TreeViewExpr(0, pExpr, 0);
|
||||
** sqlite3TreeViewExprList(0, pList, 0, 0);
|
||||
** sqlite3TreeViewSelect(0, pSelect, 0);
|
||||
** Insert calls to those routines while debugging in order to display
|
||||
** a diagram of Expr, ExprList, and Select objects.
|
||||
**
|
||||
*/
|
||||
/* Add a new subitem to the tree. The moreToFollow flag indicates that this
|
||||
** is not the last item in the tree. */
|
||||
TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
|
||||
if( p==0 ){
|
||||
p = sqlite3_malloc( sizeof(*p) );
|
||||
if( p==0 ) return 0;
|
||||
memset(p, 0, sizeof(*p));
|
||||
}else{
|
||||
p->iLevel++;
|
||||
}
|
||||
assert( moreToFollow==0 || moreToFollow==1 );
|
||||
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
|
||||
return p;
|
||||
}
|
||||
/* Finished with one layer of the tree */
|
||||
void sqlite3TreeViewPop(TreeView *p){
|
||||
if( p==0 ) return;
|
||||
p->iLevel--;
|
||||
if( p->iLevel<0 ) sqlite3_free(p);
|
||||
}
|
||||
/* Generate a single line of output for the tree, with a prefix that contains
|
||||
** all the appropriate tree lines */
|
||||
void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int i;
|
||||
StrAccum acc;
|
||||
char zBuf[500];
|
||||
sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
|
||||
acc.useMalloc = 0;
|
||||
if( p ){
|
||||
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
|
||||
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
|
||||
}
|
||||
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
|
||||
}
|
||||
va_start(ap, zFormat);
|
||||
sqlite3VXPrintf(&acc, 0, zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
|
||||
sqlite3StrAccumFinish(&acc);
|
||||
fprintf(stdout,"%s", zBuf);
|
||||
fflush(stdout);
|
||||
}
|
||||
/* Shorthand for starting a new tree item that consists of a single label */
|
||||
void sqlite3TreeViewItem(TreeView *p, const char *zLabel, u8 moreToFollow){
|
||||
p = sqlite3TreeViewPush(p, moreToFollow);
|
||||
sqlite3TreeViewLine(p, "%s", zLabel);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** variable-argument wrapper around sqlite3VXPrintf().
|
||||
*/
|
||||
|
||||
+11
-3
@@ -48,11 +48,19 @@ void sqlite3_randomness(int N, void *pBuf){
|
||||
#endif
|
||||
|
||||
#if SQLITE_THREADSAFE
|
||||
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
|
||||
sqlite3_mutex_enter(mutex);
|
||||
sqlite3_mutex *mutex;
|
||||
#endif
|
||||
|
||||
if( N<=0 ){
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return;
|
||||
#endif
|
||||
|
||||
#if SQLITE_THREADSAFE
|
||||
mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
|
||||
#endif
|
||||
|
||||
sqlite3_mutex_enter(mutex);
|
||||
if( N<=0 || pBuf==0 ){
|
||||
wsdPrng.isInit = 0;
|
||||
sqlite3_mutex_leave(mutex);
|
||||
return;
|
||||
|
||||
+23
-15
@@ -28,7 +28,7 @@
|
||||
** is a helper function - a callback for the tree walker.
|
||||
*/
|
||||
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
|
||||
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.i;
|
||||
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
|
||||
return WRC_Continue;
|
||||
}
|
||||
static void incrAggFunctionDepth(Expr *pExpr, int N){
|
||||
@@ -36,7 +36,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = incrAggDepth;
|
||||
w.u.i = N;
|
||||
w.u.n = N;
|
||||
sqlite3WalkExpr(&w, pExpr);
|
||||
}
|
||||
}
|
||||
@@ -320,6 +320,10 @@ static int lookupName(
|
||||
if( pMatch ){
|
||||
pExpr->iTable = pMatch->iCursor;
|
||||
pExpr->pTab = pMatch->pTab;
|
||||
assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */
|
||||
if( (pMatch->jointype & JT_LEFT)!=0 ){
|
||||
ExprSetProperty(pExpr, EP_CanBeNull);
|
||||
}
|
||||
pSchema = pExpr->pTab->pSchema;
|
||||
}
|
||||
} /* if( pSrcList ) */
|
||||
@@ -584,7 +588,7 @@ static int exprProbability(Expr *p){
|
||||
sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
|
||||
assert( r>=0.0 );
|
||||
if( r>1.0 ) return -1;
|
||||
return (int)(r*1000.0);
|
||||
return (int)(r*134217728.0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -716,12 +720,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
|
||||
** likelihood(X,0.9375). */
|
||||
/* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
|
||||
pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
|
||||
pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( pDef ){
|
||||
auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
|
||||
if( auth!=SQLITE_OK ){
|
||||
if( auth==SQLITE_DENY ){
|
||||
@@ -732,9 +734,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
pExpr->op = TK_NULL;
|
||||
return WRC_Prune;
|
||||
}
|
||||
#endif
|
||||
if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant);
|
||||
}
|
||||
#endif
|
||||
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
|
||||
pNC->nErr++;
|
||||
@@ -757,7 +759,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
pExpr->op2++;
|
||||
pNC2 = pNC2->pNext;
|
||||
}
|
||||
if( pNC2 ) pNC2->ncFlags |= NC_HasAgg;
|
||||
assert( pDef!=0 );
|
||||
if( pNC2 ){
|
||||
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
|
||||
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
|
||||
pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
|
||||
|
||||
}
|
||||
pNC->ncFlags |= NC_AllowAgg;
|
||||
}
|
||||
/* FIX ME: Compute pExpr->affinity based on the expected return
|
||||
@@ -1118,7 +1126,7 @@ static int resolveOrderGroupBy(
|
||||
}
|
||||
|
||||
/*
|
||||
** Resolve names in the SELECT statement p and all of its descendents.
|
||||
** Resolve names in the SELECT statement p and all of its descendants.
|
||||
*/
|
||||
static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
NameContext *pOuterNC; /* Context that contains this SELECT */
|
||||
@@ -1222,7 +1230,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
assert( (p->selFlags & SF_Aggregate)==0 );
|
||||
pGroupBy = p->pGroupBy;
|
||||
if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
|
||||
p->selFlags |= SF_Aggregate;
|
||||
assert( NC_MinMaxAgg==SF_MinMaxAgg );
|
||||
p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
|
||||
}else{
|
||||
sNC.ncFlags &= ~NC_AllowAgg;
|
||||
}
|
||||
@@ -1350,7 +1359,7 @@ int sqlite3ResolveExprNames(
|
||||
NameContext *pNC, /* Namespace to resolve expressions in. */
|
||||
Expr *pExpr /* The expression to be analyzed. */
|
||||
){
|
||||
u8 savedHasAgg;
|
||||
u16 savedHasAgg;
|
||||
Walker w;
|
||||
|
||||
if( pExpr==0 ) return 0;
|
||||
@@ -1363,8 +1372,8 @@ int sqlite3ResolveExprNames(
|
||||
pParse->nHeight += pExpr->nHeight;
|
||||
}
|
||||
#endif
|
||||
savedHasAgg = pNC->ncFlags & NC_HasAgg;
|
||||
pNC->ncFlags &= ~NC_HasAgg;
|
||||
savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
|
||||
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = resolveExprStep;
|
||||
w.xSelectCallback = resolveSelectStep;
|
||||
@@ -1379,9 +1388,8 @@ int sqlite3ResolveExprNames(
|
||||
}
|
||||
if( pNC->ncFlags & NC_HasAgg ){
|
||||
ExprSetProperty(pExpr, EP_Agg);
|
||||
}else if( savedHasAgg ){
|
||||
pNC->ncFlags |= NC_HasAgg;
|
||||
}
|
||||
pNC->ncFlags |= savedHasAgg;
|
||||
return ExprHasProperty(pExpr, EP_Error);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -50,7 +50,7 @@
|
||||
** No INSERTs may occurs after a SMALLEST. An assertion will fail if
|
||||
** that is attempted.
|
||||
**
|
||||
** The cost of an INSERT is roughly constant. (Sometime new memory
|
||||
** The cost of an INSERT is roughly constant. (Sometimes new memory
|
||||
** has to be allocated on an INSERT.) The cost of a TEST with a new
|
||||
** batch number is O(NlogN) where N is the number of elements in the RowSet.
|
||||
** The cost of a TEST using the same batch number is O(logN). The cost
|
||||
@@ -443,8 +443,8 @@ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
|
||||
** Check to see if element iRowid was inserted into the rowset as
|
||||
** part of any insert batch prior to iBatch. Return 1 or 0.
|
||||
**
|
||||
** If this is the first test of a new batch and if there exist entires
|
||||
** on pRowSet->pEntry, then sort those entires into the forest at
|
||||
** If this is the first test of a new batch and if there exist entries
|
||||
** on pRowSet->pEntry, then sort those entries into the forest at
|
||||
** pRowSet->pForest so that they can be tested.
|
||||
*/
|
||||
int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
|
||||
|
||||
+351
-174
@@ -14,6 +14,20 @@
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Trace output macros
|
||||
*/
|
||||
#if SELECTTRACE_ENABLED
|
||||
/***/ int sqlite3SelectTrace = 0;
|
||||
# define SELECTTRACE(K,P,S,X) \
|
||||
if(sqlite3SelectTrace&(K)) \
|
||||
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",(S)->zSelName,(S)),\
|
||||
sqlite3DebugPrintf X
|
||||
#else
|
||||
# define SELECTTRACE(K,P,S,X)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** An instance of the following object is used to record information about
|
||||
** how to process the DISTINCT keyword, to simplify passing that information
|
||||
@@ -44,20 +58,25 @@ struct SortCtx {
|
||||
#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
|
||||
|
||||
/*
|
||||
** Delete all the content of a Select structure but do not deallocate
|
||||
** the select structure itself.
|
||||
** Delete all the content of a Select structure. Deallocate the structure
|
||||
** itself only if bFree is true.
|
||||
*/
|
||||
static void clearSelect(sqlite3 *db, Select *p){
|
||||
sqlite3ExprListDelete(db, p->pEList);
|
||||
sqlite3SrcListDelete(db, p->pSrc);
|
||||
sqlite3ExprDelete(db, p->pWhere);
|
||||
sqlite3ExprListDelete(db, p->pGroupBy);
|
||||
sqlite3ExprDelete(db, p->pHaving);
|
||||
sqlite3ExprListDelete(db, p->pOrderBy);
|
||||
sqlite3SelectDelete(db, p->pPrior);
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
sqlite3ExprDelete(db, p->pOffset);
|
||||
sqlite3WithDelete(db, p->pWith);
|
||||
static void clearSelect(sqlite3 *db, Select *p, int bFree){
|
||||
while( p ){
|
||||
Select *pPrior = p->pPrior;
|
||||
sqlite3ExprListDelete(db, p->pEList);
|
||||
sqlite3SrcListDelete(db, p->pSrc);
|
||||
sqlite3ExprDelete(db, p->pWhere);
|
||||
sqlite3ExprListDelete(db, p->pGroupBy);
|
||||
sqlite3ExprDelete(db, p->pHaving);
|
||||
sqlite3ExprListDelete(db, p->pOrderBy);
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
sqlite3ExprDelete(db, p->pOffset);
|
||||
sqlite3WithDelete(db, p->pWith);
|
||||
if( bFree ) sqlite3DbFree(db, p);
|
||||
p = pPrior;
|
||||
bFree = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -116,8 +135,7 @@ Select *sqlite3SelectNew(
|
||||
pNew->addrOpenEphm[0] = -1;
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
if( db->mallocFailed ) {
|
||||
clearSelect(db, pNew);
|
||||
if( pNew!=&standin ) sqlite3DbFree(db, pNew);
|
||||
clearSelect(db, pNew, pNew!=&standin);
|
||||
pNew = 0;
|
||||
}else{
|
||||
assert( pNew->pSrc!=0 || pParse->nErr>0 );
|
||||
@@ -126,14 +144,23 @@ Select *sqlite3SelectNew(
|
||||
return pNew;
|
||||
}
|
||||
|
||||
#if SELECTTRACE_ENABLED
|
||||
/*
|
||||
** Set the name of a Select object
|
||||
*/
|
||||
void sqlite3SelectSetName(Select *p, const char *zName){
|
||||
if( p && zName ){
|
||||
sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Delete the given Select structure and all of its substructures.
|
||||
*/
|
||||
void sqlite3SelectDelete(sqlite3 *db, Select *p){
|
||||
if( p ){
|
||||
clearSelect(db, p);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
clearSelect(db, p, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -455,28 +482,43 @@ static KeyInfo *keyInfoFromExprList(
|
||||
);
|
||||
|
||||
/*
|
||||
** Insert code into "v" that will push the record in register regData
|
||||
** into the sorter.
|
||||
** Generate code that will push the record in registers regData
|
||||
** through regData+nData-1 onto the sorter.
|
||||
*/
|
||||
static void pushOntoSorter(
|
||||
Parse *pParse, /* Parser context */
|
||||
SortCtx *pSort, /* Information about the ORDER BY clause */
|
||||
Select *pSelect, /* The whole SELECT statement */
|
||||
int regData /* Register holding data to be sorted */
|
||||
int regData, /* First register holding data to be sorted */
|
||||
int nData, /* Number of elements in the data array */
|
||||
int nPrefixReg /* No. of reg prior to regData available for use */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int nExpr = pSort->pOrderBy->nExpr;
|
||||
int regRecord = ++pParse->nMem;
|
||||
int regBase = pParse->nMem+1;
|
||||
int nOBSat = pSort->nOBSat;
|
||||
int op;
|
||||
Vdbe *v = pParse->pVdbe; /* Stmt under construction */
|
||||
int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0);
|
||||
int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */
|
||||
int nBase = nExpr + bSeq + nData; /* Fields in sorter record */
|
||||
int regBase; /* Regs for sorter record */
|
||||
int regRecord = ++pParse->nMem; /* Assembled sorter record */
|
||||
int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */
|
||||
int op; /* Opcode to add sorter record to sorter */
|
||||
|
||||
pParse->nMem += nExpr+2; /* nExpr+2 registers allocated at regBase */
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
|
||||
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat,regRecord);
|
||||
assert( bSeq==0 || bSeq==1 );
|
||||
if( nPrefixReg ){
|
||||
assert( nPrefixReg==nExpr+bSeq );
|
||||
regBase = regData - nExpr - bSeq;
|
||||
}else{
|
||||
regBase = pParse->nMem + 1;
|
||||
pParse->nMem += nBase;
|
||||
}
|
||||
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, SQLITE_ECEL_DUP);
|
||||
if( bSeq ){
|
||||
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
|
||||
}
|
||||
if( nPrefixReg==0 ){
|
||||
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
|
||||
}
|
||||
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
|
||||
if( nOBSat>0 ){
|
||||
int regPrevKey; /* The first nOBSat columns of the previous row */
|
||||
int addrFirst; /* Address of the OP_IfNot opcode */
|
||||
@@ -487,16 +529,23 @@ static void pushOntoSorter(
|
||||
|
||||
regPrevKey = pParse->nMem+1;
|
||||
pParse->nMem += pSort->nOBSat;
|
||||
nKey = nExpr - pSort->nOBSat + 1;
|
||||
addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); VdbeCoverage(v);
|
||||
nKey = nExpr - pSort->nOBSat + bSeq;
|
||||
if( bSeq ){
|
||||
addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr);
|
||||
}else{
|
||||
addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor);
|
||||
}
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
|
||||
pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
|
||||
if( pParse->db->mallocFailed ) return;
|
||||
pOp->p2 = nKey + 1;
|
||||
pOp->p2 = nKey + nData;
|
||||
pKI = pOp->p4.pKeyInfo;
|
||||
memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
|
||||
pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1);
|
||||
testcase( pKI->nXField>2 );
|
||||
pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat,
|
||||
pKI->nXField-1);
|
||||
addrJmp = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
|
||||
pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
|
||||
@@ -504,7 +553,7 @@ static void pushOntoSorter(
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
|
||||
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
|
||||
sqlite3VdbeJumpHere(v, addrFirst);
|
||||
sqlite3VdbeAddOp3(v, OP_Move, regBase, regPrevKey, pSort->nOBSat);
|
||||
sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat);
|
||||
sqlite3VdbeJumpHere(v, addrJmp);
|
||||
}
|
||||
if( pSort->sortFlags & SORTFLAG_UseSorter ){
|
||||
@@ -626,6 +675,7 @@ static void selectInnerLoop(
|
||||
int eDest = pDest->eDest; /* How to dispose of results */
|
||||
int iParm = pDest->iSDParm; /* First argument to disposal method */
|
||||
int nResultCol; /* Number of result columns */
|
||||
int nPrefixReg = 0; /* Number of extra registers before regResult */
|
||||
|
||||
assert( v );
|
||||
assert( pEList!=0 );
|
||||
@@ -641,6 +691,11 @@ static void selectInnerLoop(
|
||||
nResultCol = pEList->nExpr;
|
||||
|
||||
if( pDest->iSdst==0 ){
|
||||
if( pSort ){
|
||||
nPrefixReg = pSort->pOrderBy->nExpr;
|
||||
if( !(pSort->sortFlags & SORTFLAG_UseSorter) ) nPrefixReg++;
|
||||
pParse->nMem += nPrefixReg;
|
||||
}
|
||||
pDest->iSdst = pParse->nMem+1;
|
||||
pParse->nMem += nResultCol;
|
||||
}else if( pDest->iSdst+nResultCol > pParse->nMem ){
|
||||
@@ -757,10 +812,10 @@ static void selectInnerLoop(
|
||||
case SRT_DistFifo:
|
||||
case SRT_Table:
|
||||
case SRT_EphemTab: {
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1);
|
||||
testcase( eDest==SRT_Table );
|
||||
testcase( eDest==SRT_EphemTab );
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
if( eDest==SRT_DistFifo ){
|
||||
/* If the destination is DistFifo, then cursor (iParm+1) is open
|
||||
@@ -775,7 +830,7 @@ static void selectInnerLoop(
|
||||
}
|
||||
#endif
|
||||
if( pSort ){
|
||||
pushOntoSorter(pParse, pSort, p, r1);
|
||||
pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, 1, nPrefixReg);
|
||||
}else{
|
||||
int r2 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
|
||||
@@ -783,7 +838,7 @@ static void selectInnerLoop(
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
sqlite3ReleaseTempReg(pParse, r2);
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -801,7 +856,7 @@ static void selectInnerLoop(
|
||||
** ORDER BY in this case since the order of entries in the set
|
||||
** does not matter. But there might be a LIMIT clause, in which
|
||||
** case the order does matter */
|
||||
pushOntoSorter(pParse, pSort, p, regResult);
|
||||
pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg);
|
||||
}else{
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
|
||||
@@ -827,9 +882,9 @@ static void selectInnerLoop(
|
||||
case SRT_Mem: {
|
||||
assert( nResultCol==1 );
|
||||
if( pSort ){
|
||||
pushOntoSorter(pParse, pSort, p, regResult);
|
||||
pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg);
|
||||
}else{
|
||||
sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
|
||||
assert( regResult==iParm );
|
||||
/* The LIMIT clause will jump out of the loop for us */
|
||||
}
|
||||
break;
|
||||
@@ -841,10 +896,7 @@ static void selectInnerLoop(
|
||||
testcase( eDest==SRT_Coroutine );
|
||||
testcase( eDest==SRT_Output );
|
||||
if( pSort ){
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
|
||||
pushOntoSorter(pParse, pSort, p, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
pushOntoSorter(pParse, pSort, p, regResult, nResultCol, nPrefixReg);
|
||||
}else if( eDest==SRT_Coroutine ){
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
|
||||
}else{
|
||||
@@ -987,7 +1039,7 @@ int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; }
|
||||
** then the KeyInfo structure is appropriate for initializing a virtual
|
||||
** index to implement a DISTINCT test.
|
||||
**
|
||||
** Space to hold the KeyInfo structure is obtain from malloc. The calling
|
||||
** Space to hold the KeyInfo structure is obtained from malloc. The calling
|
||||
** function is responsible for seeing that this structure is eventually
|
||||
** freed.
|
||||
*/
|
||||
@@ -1004,7 +1056,7 @@ static KeyInfo *keyInfoFromExprList(
|
||||
int i;
|
||||
|
||||
nExpr = pList->nExpr;
|
||||
pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1);
|
||||
pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
|
||||
if( pInfo ){
|
||||
assert( sqlite3KeyInfoIsWriteable(pInfo) );
|
||||
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
|
||||
@@ -1124,46 +1176,58 @@ static void generateSortTail(
|
||||
int addr;
|
||||
int addrOnce = 0;
|
||||
int iTab;
|
||||
int pseudoTab = 0;
|
||||
ExprList *pOrderBy = pSort->pOrderBy;
|
||||
int eDest = pDest->eDest;
|
||||
int iParm = pDest->iSDParm;
|
||||
int regRow;
|
||||
int regRowid;
|
||||
int nKey;
|
||||
int iSortTab; /* Sorter cursor to read from */
|
||||
int nSortData; /* Trailing values to read from sorter */
|
||||
int i;
|
||||
int bSeq; /* True if sorter record includes seq. no. */
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
struct ExprList_item *aOutEx = p->pEList->a;
|
||||
#endif
|
||||
|
||||
if( pSort->labelBkOut ){
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak);
|
||||
sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
|
||||
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
}
|
||||
iTab = pSort->iECursor;
|
||||
regRow = sqlite3GetTempReg(pParse);
|
||||
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
|
||||
pseudoTab = pParse->nTab++;
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
|
||||
regRowid = 0;
|
||||
regRow = pDest->iSdst;
|
||||
nSortData = nColumn;
|
||||
}else{
|
||||
regRowid = sqlite3GetTempReg(pParse);
|
||||
regRow = sqlite3GetTempReg(pParse);
|
||||
nSortData = 1;
|
||||
}
|
||||
nKey = pOrderBy->nExpr - pSort->nOBSat;
|
||||
if( pSort->sortFlags & SORTFLAG_UseSorter ){
|
||||
int regSortOut = ++pParse->nMem;
|
||||
int ptab2 = pParse->nTab++;
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, nKey+2);
|
||||
iSortTab = pParse->nTab++;
|
||||
if( pSort->labelBkOut ){
|
||||
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData);
|
||||
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
|
||||
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
|
||||
VdbeCoverage(v);
|
||||
codeOffset(v, p->iOffset, addrContinue);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, ptab2, nKey+1, regRow);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
|
||||
sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab);
|
||||
bSeq = 0;
|
||||
}else{
|
||||
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
|
||||
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
|
||||
codeOffset(v, p->iOffset, addrContinue);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iTab, nKey+1, regRow);
|
||||
iSortTab = iTab;
|
||||
bSeq = 1;
|
||||
}
|
||||
for(i=0; i<nSortData; i++){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
|
||||
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
|
||||
}
|
||||
switch( eDest ){
|
||||
case SRT_Table:
|
||||
@@ -1192,17 +1256,9 @@ static void generateSortTail(
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
int i;
|
||||
assert( eDest==SRT_Output || eDest==SRT_Coroutine );
|
||||
testcase( eDest==SRT_Output );
|
||||
testcase( eDest==SRT_Coroutine );
|
||||
for(i=0; i<nColumn; i++){
|
||||
assert( regRow!=pDest->iSdst+i );
|
||||
sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iSdst+i);
|
||||
if( i==0 ){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
|
||||
}
|
||||
}
|
||||
if( eDest==SRT_Output ){
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
|
||||
sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
|
||||
@@ -1212,9 +1268,10 @@ static void generateSortTail(
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, regRow);
|
||||
sqlite3ReleaseTempReg(pParse, regRowid);
|
||||
|
||||
if( regRowid ){
|
||||
sqlite3ReleaseTempReg(pParse, regRow);
|
||||
sqlite3ReleaseTempReg(pParse, regRowid);
|
||||
}
|
||||
/* The bottom of the loop
|
||||
*/
|
||||
sqlite3VdbeResolveLabel(v, addrContinue);
|
||||
@@ -1509,7 +1566,7 @@ static void generateColumnNames(
|
||||
}
|
||||
|
||||
/*
|
||||
** Given a an expression list (which is really the list of expressions
|
||||
** Given an expression list (which is really the list of expressions
|
||||
** that form the result set of a SELECT statement) compute appropriate
|
||||
** column names for a table that would hold the expression list.
|
||||
**
|
||||
@@ -1582,7 +1639,7 @@ static int selectColumnsFromExprList(
|
||||
}
|
||||
|
||||
/* Make sure the column name is unique. If the name is not unique,
|
||||
** append a integer to the name so that it becomes unique.
|
||||
** append an integer to the name so that it becomes unique.
|
||||
*/
|
||||
nName = sqlite3Strlen30(zName);
|
||||
for(j=cnt=0; j<i; j++){
|
||||
@@ -2021,6 +2078,66 @@ static int multiSelectOrderBy(
|
||||
SelectDest *pDest /* What to do with query results */
|
||||
);
|
||||
|
||||
/*
|
||||
** Error message for when two or more terms of a compound select have different
|
||||
** size result sets.
|
||||
*/
|
||||
static void selectWrongNumTermsError(Parse *pParse, Select *p){
|
||||
if( p->selFlags & SF_Values ){
|
||||
sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
|
||||
}else{
|
||||
sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
|
||||
" do not have the same number of result columns", selectOpName(p->op));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Handle the special case of a compound-select that originates from a
|
||||
** VALUES clause. By handling this as a special case, we avoid deep
|
||||
** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT
|
||||
** on a VALUES clause.
|
||||
**
|
||||
** Because the Select object originates from a VALUES clause:
|
||||
** (1) It has no LIMIT or OFFSET
|
||||
** (2) All terms are UNION ALL
|
||||
** (3) There is no ORDER BY clause
|
||||
*/
|
||||
static int multiSelectValues(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Select *p, /* The right-most of SELECTs to be coded */
|
||||
SelectDest *pDest /* What to do with query results */
|
||||
){
|
||||
Select *pPrior;
|
||||
int nExpr = p->pEList->nExpr;
|
||||
int nRow = 1;
|
||||
int rc = 0;
|
||||
assert( p->pNext==0 );
|
||||
assert( p->selFlags & SF_AllValues );
|
||||
do{
|
||||
assert( p->selFlags & SF_Values );
|
||||
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
|
||||
assert( p->pLimit==0 );
|
||||
assert( p->pOffset==0 );
|
||||
if( p->pEList->nExpr!=nExpr ){
|
||||
selectWrongNumTermsError(pParse, p);
|
||||
return 1;
|
||||
}
|
||||
if( p->pPrior==0 ) break;
|
||||
assert( p->pPrior->pNext==p );
|
||||
p = p->pPrior;
|
||||
nRow++;
|
||||
}while(1);
|
||||
while( p ){
|
||||
pPrior = p->pPrior;
|
||||
p->pPrior = 0;
|
||||
rc = sqlite3Select(pParse, p, pDest);
|
||||
p->pPrior = pPrior;
|
||||
if( rc ) break;
|
||||
p->nSelectRow = nRow;
|
||||
p = p->pNext;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called to process a compound query form from
|
||||
@@ -2102,17 +2219,19 @@ static int multiSelect(
|
||||
dest.eDest = SRT_Table;
|
||||
}
|
||||
|
||||
/* Special handling for a compound-select that originates as a VALUES clause.
|
||||
*/
|
||||
if( p->selFlags & SF_AllValues ){
|
||||
rc = multiSelectValues(pParse, p, &dest);
|
||||
goto multi_select_end;
|
||||
}
|
||||
|
||||
/* Make sure all SELECTs in the statement have the same number of elements
|
||||
** in their result sets.
|
||||
*/
|
||||
assert( p->pEList && pPrior->pEList );
|
||||
if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
|
||||
if( p->selFlags & SF_Values ){
|
||||
sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
|
||||
}else{
|
||||
sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
|
||||
" do not have the same number of result columns", selectOpName(p->op));
|
||||
}
|
||||
selectWrongNumTermsError(pParse, p);
|
||||
rc = 1;
|
||||
goto multi_select_end;
|
||||
}
|
||||
@@ -3066,7 +3185,7 @@ static void substSelect(
|
||||
**
|
||||
** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
|
||||
**
|
||||
** The code generated for this simpification gives the same result
|
||||
** The code generated for this simplification gives the same result
|
||||
** but only has to scan the data once. And because indices might
|
||||
** exist on the table t1, a complete scan of the data might be
|
||||
** avoided.
|
||||
@@ -3099,8 +3218,10 @@ static void substSelect(
|
||||
** (9) The subquery does not use LIMIT or the outer query does not use
|
||||
** aggregates.
|
||||
**
|
||||
** (10) The subquery does not use aggregates or the outer query does not
|
||||
** use LIMIT.
|
||||
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
|
||||
** accidently carried the comment forward until 2014-09-15. Original
|
||||
** text: "The subquery does not use aggregates or the outer query does not
|
||||
** use LIMIT."
|
||||
**
|
||||
** (11) The subquery and the outer query do not both have ORDER BY clauses.
|
||||
**
|
||||
@@ -3163,6 +3284,11 @@ static void substSelect(
|
||||
** parent to a compound query confuses the code that handles
|
||||
** recursive queries in multiSelect().
|
||||
**
|
||||
** (24) The subquery is not an aggregate that uses the built-in min() or
|
||||
** or max() functions. (Without this restriction, a query like:
|
||||
** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
|
||||
** return the value X for which Y was maximal.)
|
||||
**
|
||||
**
|
||||
** In this routine, the "p" parameter is a pointer to the outer query.
|
||||
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
|
||||
@@ -3210,7 +3336,7 @@ static int flattenSubquery(
|
||||
pSubSrc = pSub->pSrc;
|
||||
assert( pSubSrc );
|
||||
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
|
||||
** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
|
||||
** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
|
||||
** because they could be computed at compile-time. But when LIMIT and OFFSET
|
||||
** became arbitrary expressions, we were forced to add restrictions (13)
|
||||
** and (14). */
|
||||
@@ -3235,8 +3361,14 @@ static int flattenSubquery(
|
||||
if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
|
||||
return 0; /* Restriction (21) */
|
||||
}
|
||||
if( pSub->selFlags & SF_Recursive ) return 0; /* Restriction (22) */
|
||||
if( (p->selFlags & SF_Recursive) && pSub->pPrior ) return 0; /* (23) */
|
||||
testcase( pSub->selFlags & SF_Recursive );
|
||||
testcase( pSub->selFlags & SF_MinMaxAgg );
|
||||
if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){
|
||||
return 0; /* Restrictions (22) and (24) */
|
||||
}
|
||||
if( (p->selFlags & SF_Recursive) && pSub->pPrior ){
|
||||
return 0; /* Restriction (23) */
|
||||
}
|
||||
|
||||
/* OBSOLETE COMMENT 1:
|
||||
** Restriction 3: If the subquery is a join, make sure the subquery is
|
||||
@@ -3310,6 +3442,8 @@ static int flattenSubquery(
|
||||
}
|
||||
|
||||
/***** If we reach this point, flattening is permitted. *****/
|
||||
SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n",
|
||||
pSub->zSelName, pSub, iFrom));
|
||||
|
||||
/* Authorize the subquery */
|
||||
pParse->zAuthContext = pSubitem->zName;
|
||||
@@ -3362,6 +3496,7 @@ static int flattenSubquery(
|
||||
p->pLimit = 0;
|
||||
p->pOffset = 0;
|
||||
pNew = sqlite3SelectDup(db, p, 0);
|
||||
sqlite3SelectSetName(pNew, pSub->zSelName);
|
||||
p->pOffset = pOffset;
|
||||
p->pLimit = pLimit;
|
||||
p->pOrderBy = pOrderBy;
|
||||
@@ -3374,6 +3509,9 @@ static int flattenSubquery(
|
||||
if( pPrior ) pPrior->pNext = pNew;
|
||||
pNew->pNext = p;
|
||||
p->pPrior = pNew;
|
||||
SELECTTRACE(2,pParse,p,
|
||||
("compound-subquery flattener creates %s.%p as peer\n",
|
||||
pNew->zSelName, pNew));
|
||||
}
|
||||
if( db->mallocFailed ) return 1;
|
||||
}
|
||||
@@ -3503,8 +3641,23 @@ static int flattenSubquery(
|
||||
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
|
||||
}
|
||||
if( pSub->pOrderBy ){
|
||||
/* At this point, any non-zero iOrderByCol values indicate that the
|
||||
** ORDER BY column expression is identical to the iOrderByCol'th
|
||||
** expression returned by SELECT statement pSub. Since these values
|
||||
** do not necessarily correspond to columns in SELECT statement pParent,
|
||||
** zero them before transfering the ORDER BY clause.
|
||||
**
|
||||
** Not doing this may cause an error if a subsequent call to this
|
||||
** function attempts to flatten a compound sub-query into pParent
|
||||
** (the only way this can happen is if the compound sub-query is
|
||||
** currently part of pSub->pSrc). See ticket [d11a6e908f]. */
|
||||
ExprList *pOrderBy = pSub->pOrderBy;
|
||||
for(i=0; i<pOrderBy->nExpr; i++){
|
||||
pOrderBy->a[i].u.x.iOrderByCol = 0;
|
||||
}
|
||||
assert( pParent->pOrderBy==0 );
|
||||
pParent->pOrderBy = pSub->pOrderBy;
|
||||
assert( pSub->pPrior==0 );
|
||||
pParent->pOrderBy = pOrderBy;
|
||||
pSub->pOrderBy = 0;
|
||||
}else if( pParent->pOrderBy ){
|
||||
substExprList(db, pParent->pOrderBy, iParent, pSub->pEList);
|
||||
@@ -3550,6 +3703,13 @@ static int flattenSubquery(
|
||||
*/
|
||||
sqlite3SelectDelete(db, pSub1);
|
||||
|
||||
#if SELECTTRACE_ENABLED
|
||||
if( sqlite3SelectTrace & 0x100 ){
|
||||
sqlite3DebugPrintf("After flattening:\n");
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||
@@ -3596,7 +3756,7 @@ static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
|
||||
|
||||
/*
|
||||
** The select statement passed as the first argument is an aggregate query.
|
||||
** The second argment is the associated aggregate-info object. This
|
||||
** The second argument is the associated aggregate-info object. This
|
||||
** function tests if the SELECT is of the form:
|
||||
**
|
||||
** SELECT count(*) FROM <tbl>
|
||||
@@ -3926,10 +4086,10 @@ static void selectPopWith(Walker *pWalker, Select *p){
|
||||
** fill pTabList->a[].pSelect with a copy of the SELECT statement
|
||||
** that implements the view. A copy is made of the view's SELECT
|
||||
** statement so that we can freely modify or delete that statement
|
||||
** without worrying about messing up the presistent representation
|
||||
** without worrying about messing up the persistent representation
|
||||
** of the view.
|
||||
**
|
||||
** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
|
||||
** (3) Add terms to the WHERE clause to accommodate the NATURAL keyword
|
||||
** on joins and the ON and USING clause of joins.
|
||||
**
|
||||
** (4) Scan the list of columns in the result set (pEList) looking
|
||||
@@ -3957,7 +4117,9 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
}
|
||||
pTabList = p->pSrc;
|
||||
pEList = p->pEList;
|
||||
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
|
||||
if( pWalker->xSelectCallback2==selectPopWith ){
|
||||
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
|
||||
}
|
||||
|
||||
/* Make sure cursor numbers have been assigned to all entries in
|
||||
** the FROM clause of the SELECT statement.
|
||||
@@ -4020,6 +4182,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
|
||||
assert( pFrom->pSelect==0 );
|
||||
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
|
||||
sqlite3SelectSetName(pFrom->pSelect, pTab->zName);
|
||||
sqlite3WalkSelect(pWalker, pFrom->pSelect);
|
||||
}
|
||||
#endif
|
||||
@@ -4247,7 +4410,9 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
}
|
||||
w.xSelectCallback = selectExpander;
|
||||
w.xSelectCallback2 = selectPopWith;
|
||||
if( (pSelect->selFlags & SF_AllValues)==0 ){
|
||||
w.xSelectCallback2 = selectPopWith;
|
||||
}
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
}
|
||||
|
||||
@@ -4554,6 +4719,13 @@ int sqlite3Select(
|
||||
}
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
|
||||
memset(&sAggInfo, 0, sizeof(sAggInfo));
|
||||
#if SELECTTRACE_ENABLED
|
||||
pParse->nSelectIndent++;
|
||||
SELECTTRACE(1,pParse,p, ("begin processing:\n"));
|
||||
if( sqlite3SelectTrace & 0x100 ){
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
|
||||
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
|
||||
@@ -4710,6 +4882,10 @@ int sqlite3Select(
|
||||
if( p->pPrior ){
|
||||
rc = multiSelect(pParse, p, pDest);
|
||||
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
|
||||
#if SELECTTRACE_ENABLED
|
||||
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
|
||||
pParse->nSelectIndent--;
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
@@ -4722,7 +4898,7 @@ int sqlite3Select(
|
||||
**
|
||||
** is transformed to:
|
||||
**
|
||||
** SELECT xyz FROM ... GROUP BY xyz
|
||||
** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz
|
||||
**
|
||||
** The second form is preferred as a single index (or temp-table) may be
|
||||
** used for both the ORDER BY and DISTINCT processing. As originally
|
||||
@@ -4735,7 +4911,6 @@ int sqlite3Select(
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
|
||||
pGroupBy = p->pGroupBy;
|
||||
sSort.pOrderBy = 0;
|
||||
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
|
||||
** the sDistinct.isTnct is still set. Hence, isTnct represents the
|
||||
** original setting of the SF_Distinct flag, not the current setting */
|
||||
@@ -4751,12 +4926,13 @@ int sqlite3Select(
|
||||
*/
|
||||
if( sSort.pOrderBy ){
|
||||
KeyInfo *pKeyInfo;
|
||||
pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0);
|
||||
pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr);
|
||||
sSort.iECursor = pParse->nTab++;
|
||||
sSort.addrSortIndex =
|
||||
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
|
||||
sSort.iECursor, sSort.pOrderBy->nExpr+2, 0,
|
||||
(char*)pKeyInfo, P4_KEYINFO);
|
||||
sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0,
|
||||
(char*)pKeyInfo, P4_KEYINFO
|
||||
);
|
||||
}else{
|
||||
sSort.addrSortIndex = -1;
|
||||
}
|
||||
@@ -4887,7 +5063,7 @@ int sqlite3Select(
|
||||
sNC.pSrcList = pTabList;
|
||||
sNC.pAggInfo = &sAggInfo;
|
||||
sAggInfo.mnReg = pParse->nMem+1;
|
||||
sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
|
||||
sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
|
||||
sAggInfo.pGroupBy = pGroupBy;
|
||||
sqlite3ExprAnalyzeAggList(&sNC, pEList);
|
||||
sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
|
||||
@@ -4924,7 +5100,7 @@ int sqlite3Select(
|
||||
** will be converted into a Noop.
|
||||
*/
|
||||
sAggInfo.sortingIdx = pParse->nTab++;
|
||||
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0);
|
||||
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn);
|
||||
addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
|
||||
sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
|
||||
0, (char*)pKeyInfo, P4_KEYINFO);
|
||||
@@ -4980,8 +5156,8 @@ int sqlite3Select(
|
||||
|
||||
groupBySort = 1;
|
||||
nGroupBy = pGroupBy->nExpr;
|
||||
nCol = nGroupBy + 1;
|
||||
j = nGroupBy+1;
|
||||
nCol = nGroupBy;
|
||||
j = nGroupBy;
|
||||
for(i=0; i<sAggInfo.nColumn; i++){
|
||||
if( sAggInfo.aCol[i].iSorterColumn>=j ){
|
||||
nCol++;
|
||||
@@ -4991,8 +5167,7 @@ int sqlite3Select(
|
||||
regBase = sqlite3GetTempRange(pParse, nCol);
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
|
||||
j = nGroupBy+1;
|
||||
j = nGroupBy;
|
||||
for(i=0; i<sAggInfo.nColumn; i++){
|
||||
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
|
||||
if( pCol->iSorterColumn>=j ){
|
||||
@@ -5045,12 +5220,11 @@ int sqlite3Select(
|
||||
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
if( groupBySort ){
|
||||
sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut);
|
||||
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut,sortPTab);
|
||||
}
|
||||
for(j=0; j<pGroupBy->nExpr; j++){
|
||||
if( groupBySort ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
|
||||
if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
|
||||
}else{
|
||||
sAggInfo.directMode = 1;
|
||||
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
|
||||
@@ -5309,100 +5483,103 @@ select_end:
|
||||
|
||||
sqlite3DbFree(db, sAggInfo.aCol);
|
||||
sqlite3DbFree(db, sAggInfo.aFunc);
|
||||
#if SELECTTRACE_ENABLED
|
||||
SELECTTRACE(1,pParse,p,("end processing\n"));
|
||||
pParse->nSelectIndent--;
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Generate a human-readable description of a the Select object.
|
||||
*/
|
||||
static void explainOneSelect(Vdbe *pVdbe, Select *p){
|
||||
sqlite3ExplainPrintf(pVdbe, "SELECT ");
|
||||
if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
|
||||
if( p->selFlags & SF_Distinct ){
|
||||
sqlite3ExplainPrintf(pVdbe, "DISTINCT ");
|
||||
}
|
||||
if( p->selFlags & SF_Aggregate ){
|
||||
sqlite3ExplainPrintf(pVdbe, "agg_flag ");
|
||||
}
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3ExplainPrintf(pVdbe, " ");
|
||||
}
|
||||
sqlite3ExplainExprList(pVdbe, p->pEList);
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
int n = 0;
|
||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||
sqlite3TreeViewLine(pView, "SELECT%s%s",
|
||||
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
|
||||
((p->selFlags & SF_Aggregate) ? " agg_flag" : "")
|
||||
);
|
||||
if( p->pSrc && p->pSrc->nSrc ) n++;
|
||||
if( p->pWhere ) n++;
|
||||
if( p->pGroupBy ) n++;
|
||||
if( p->pHaving ) n++;
|
||||
if( p->pOrderBy ) n++;
|
||||
if( p->pLimit ) n++;
|
||||
if( p->pOffset ) n++;
|
||||
if( p->pPrior ) n++;
|
||||
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
|
||||
if( p->pSrc && p->pSrc->nSrc ){
|
||||
int i;
|
||||
sqlite3ExplainPrintf(pVdbe, "FROM ");
|
||||
sqlite3ExplainPush(pVdbe);
|
||||
pView = sqlite3TreeViewPush(pView, (n--)>0);
|
||||
sqlite3TreeViewLine(pView, "FROM");
|
||||
for(i=0; i<p->pSrc->nSrc; i++){
|
||||
struct SrcList_item *pItem = &p->pSrc->a[i];
|
||||
sqlite3ExplainPrintf(pVdbe, "{%d,*} = ", pItem->iCursor);
|
||||
if( pItem->pSelect ){
|
||||
sqlite3ExplainSelect(pVdbe, pItem->pSelect);
|
||||
if( pItem->pTab ){
|
||||
sqlite3ExplainPrintf(pVdbe, " (tabname=%s)", pItem->pTab->zName);
|
||||
}
|
||||
StrAccum x;
|
||||
char zLine[100];
|
||||
sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0);
|
||||
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
|
||||
if( pItem->zDatabase ){
|
||||
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
|
||||
}else if( pItem->zName ){
|
||||
sqlite3ExplainPrintf(pVdbe, "%s", pItem->zName);
|
||||
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
|
||||
}
|
||||
if( pItem->pTab ){
|
||||
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
|
||||
}
|
||||
if( pItem->zAlias ){
|
||||
sqlite3ExplainPrintf(pVdbe, " (AS %s)", pItem->zAlias);
|
||||
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
|
||||
}
|
||||
if( pItem->jointype & JT_LEFT ){
|
||||
sqlite3ExplainPrintf(pVdbe, " LEFT-JOIN");
|
||||
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
|
||||
}
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3StrAccumFinish(&x);
|
||||
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
|
||||
if( pItem->pSelect ){
|
||||
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
sqlite3ExplainPop(pVdbe);
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
if( p->pWhere ){
|
||||
sqlite3ExplainPrintf(pVdbe, "WHERE ");
|
||||
sqlite3ExplainExpr(pVdbe, p->pWhere);
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
|
||||
sqlite3TreeViewExpr(pView, p->pWhere, 0);
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
if( p->pGroupBy ){
|
||||
sqlite3ExplainPrintf(pVdbe, "GROUPBY ");
|
||||
sqlite3ExplainExprList(pVdbe, p->pGroupBy);
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
|
||||
}
|
||||
if( p->pHaving ){
|
||||
sqlite3ExplainPrintf(pVdbe, "HAVING ");
|
||||
sqlite3ExplainExpr(pVdbe, p->pHaving);
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
|
||||
sqlite3TreeViewExpr(pView, p->pHaving, 0);
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
if( p->pOrderBy ){
|
||||
sqlite3ExplainPrintf(pVdbe, "ORDERBY ");
|
||||
sqlite3ExplainExprList(pVdbe, p->pOrderBy);
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
|
||||
}
|
||||
if( p->pLimit ){
|
||||
sqlite3ExplainPrintf(pVdbe, "LIMIT ");
|
||||
sqlite3ExplainExpr(pVdbe, p->pLimit);
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
|
||||
sqlite3TreeViewExpr(pView, p->pLimit, 0);
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
if( p->pOffset ){
|
||||
sqlite3ExplainPrintf(pVdbe, "OFFSET ");
|
||||
sqlite3ExplainExpr(pVdbe, p->pOffset);
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
|
||||
sqlite3TreeViewExpr(pView, p->pOffset, 0);
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
if( p->pPrior ){
|
||||
const char *zOp = "UNION";
|
||||
switch( p->op ){
|
||||
case TK_ALL: zOp = "UNION ALL"; break;
|
||||
case TK_INTERSECT: zOp = "INTERSECT"; break;
|
||||
case TK_EXCEPT: zOp = "EXCEPT"; break;
|
||||
}
|
||||
sqlite3TreeViewItem(pView, zOp, (n--)>0);
|
||||
sqlite3TreeViewSelect(pView, p->pPrior, 0);
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
|
||||
if( p==0 ){
|
||||
sqlite3ExplainPrintf(pVdbe, "(null-select)");
|
||||
return;
|
||||
}
|
||||
sqlite3ExplainPush(pVdbe);
|
||||
while( p ){
|
||||
explainOneSelect(pVdbe, p);
|
||||
p = p->pNext;
|
||||
if( p==0 ) break;
|
||||
sqlite3ExplainNL(pVdbe);
|
||||
sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op));
|
||||
}
|
||||
sqlite3ExplainPrintf(pVdbe, "END");
|
||||
sqlite3ExplainPop(pVdbe);
|
||||
}
|
||||
|
||||
/* End of the structure debug printing code
|
||||
*****************************************************************************/
|
||||
#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
+676
-286
File diff suppressed because it is too large
Load Diff
+569
-348
File diff suppressed because it is too large
Load Diff
+32
-2
@@ -28,7 +28,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
|
||||
** WARNING: In order to maintain backwards compatibility, add new
|
||||
** interfaces to the end of this structure only. If you insert new
|
||||
** interfaces in the middle of this structure, then older different
|
||||
** versions of SQLite will not be able to load each others' shared
|
||||
** versions of SQLite will not be able to load each other's shared
|
||||
** libraries!
|
||||
*/
|
||||
struct sqlite3_api_routines {
|
||||
@@ -250,11 +250,28 @@ struct sqlite3_api_routines {
|
||||
const char *(*uri_parameter)(const char*,const char*);
|
||||
char *(*vsnprintf)(int,char*,const char*,va_list);
|
||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
||||
/* Version 3.8.7 and later */
|
||||
int (*auto_extension)(void(*)(void));
|
||||
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
|
||||
void(*)(void*));
|
||||
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
|
||||
void(*)(void*),unsigned char);
|
||||
int (*cancel_auto_extension)(void(*)(void));
|
||||
int (*load_extension)(sqlite3*,const char*,const char*,char**);
|
||||
void *(*malloc64)(sqlite3_uint64);
|
||||
sqlite3_uint64 (*msize)(void*);
|
||||
void *(*realloc64)(void*,sqlite3_uint64);
|
||||
void (*reset_auto_extension)(void);
|
||||
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
|
||||
void(*)(void*));
|
||||
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
|
||||
void(*)(void*), unsigned char);
|
||||
int (*strglob)(const char*,const char*);
|
||||
};
|
||||
|
||||
/*
|
||||
** The following macros redefine the API routines so that they are
|
||||
** redirected throught the global sqlite3_api structure.
|
||||
** redirected through the global sqlite3_api structure.
|
||||
**
|
||||
** This header file is also used by the loadext.c source file
|
||||
** (part of the main SQLite library - not an extension) so that
|
||||
@@ -467,6 +484,19 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
||||
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
|
||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
||||
/* Version 3.8.7 and later */
|
||||
#define sqlite3_auto_extension sqlite3_api->auto_extension
|
||||
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
|
||||
#define sqlite3_bind_text64 sqlite3_api->bind_text64
|
||||
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
|
||||
#define sqlite3_load_extension sqlite3_api->load_extension
|
||||
#define sqlite3_malloc64 sqlite3_api->malloc64
|
||||
#define sqlite3_msize sqlite3_api->msize
|
||||
#define sqlite3_realloc64 sqlite3_api->realloc64
|
||||
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
|
||||
#define sqlite3_result_blob64 sqlite3_api->result_blob64
|
||||
#define sqlite3_result_text64 sqlite3_api->result_text64
|
||||
#define sqlite3_strglob sqlite3_api->strglob
|
||||
#endif /* SQLITE_CORE */
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
|
||||
+227
-106
@@ -15,6 +15,14 @@
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
|
||||
/*
|
||||
** Include the header file used to customize the compiler options for MSVC.
|
||||
** This should be done first so that it can successfully prevent spurious
|
||||
** compiler warnings due to subsequent content in this file and other files
|
||||
** that are included by this file.
|
||||
*/
|
||||
#include "msvc.h"
|
||||
|
||||
/*
|
||||
** These #defines should enable >2GB file support on POSIX if the
|
||||
** underlying operating system supports it. If the OS lacks
|
||||
@@ -47,6 +55,15 @@
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
#endif
|
||||
|
||||
/* Needed for various definitions... */
|
||||
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
|
||||
# define _BSD_SOURCE
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For MinGW, check to see if we can include the header file containing its
|
||||
** version information, among other things. Normally, this internal MinGW
|
||||
@@ -104,15 +121,6 @@
|
||||
#pragma warn -spa /* Suspicious pointer arithmetic */
|
||||
#endif
|
||||
|
||||
/* Needed for various definitions... */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
|
||||
# define _BSD_SOURCE
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Include standard header files as necessary
|
||||
*/
|
||||
@@ -153,6 +161,18 @@
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(X))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** A macro to hint to the compiler that a function should not be
|
||||
** inlined.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
# define SQLITE_NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER) && _MSC_VER>=1310
|
||||
# define SQLITE_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
# define SQLITE_NOINLINE
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
|
||||
** 0 means mutexes are permanently disable and the library is never
|
||||
@@ -181,10 +201,9 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
|
||||
** It determines whether or not the features related to
|
||||
** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
|
||||
** be overridden at runtime using the sqlite3_config() API.
|
||||
** EVIDENCE-OF: R-25715-37072 Memory allocation statistics are enabled by
|
||||
** default unless SQLite is compiled with SQLITE_DEFAULT_MEMSTATUS=0 in
|
||||
** which case memory allocation statistics are disabled by default.
|
||||
*/
|
||||
#if !defined(SQLITE_DEFAULT_MEMSTATUS)
|
||||
# define SQLITE_DEFAULT_MEMSTATUS 1
|
||||
@@ -339,7 +358,7 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return true (non-zero) if the input is a integer that is too large
|
||||
** Return true (non-zero) if the input is an integer that is too large
|
||||
** to fit in 32-bits. This macro is used inside of various testcase()
|
||||
** macros to verify that we have tested SQLite for large-file support.
|
||||
*/
|
||||
@@ -422,6 +441,27 @@
|
||||
# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if
|
||||
** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it
|
||||
** to zero.
|
||||
*/
|
||||
#if SQLITE_TEMP_STORE==3 || SQLITE_THREADSAFE==0
|
||||
# undef SQLITE_MAX_WORKER_THREADS
|
||||
# define SQLITE_MAX_WORKER_THREADS 0
|
||||
#endif
|
||||
#ifndef SQLITE_MAX_WORKER_THREADS
|
||||
# define SQLITE_MAX_WORKER_THREADS 8
|
||||
#endif
|
||||
#ifndef SQLITE_DEFAULT_WORKER_THREADS
|
||||
# define SQLITE_DEFAULT_WORKER_THREADS 0
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_WORKER_THREADS>SQLITE_MAX_WORKER_THREADS
|
||||
# undef SQLITE_MAX_WORKER_THREADS
|
||||
# define SQLITE_MAX_WORKER_THREADS SQLITE_DEFAULT_WORKER_THREADS
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** GCC does not define the offsetof() macro so we'll have to do it
|
||||
** ourselves.
|
||||
@@ -436,6 +476,11 @@
|
||||
#define MIN(A,B) ((A)<(B)?(A):(B))
|
||||
#define MAX(A,B) ((A)>(B)?(A):(B))
|
||||
|
||||
/*
|
||||
** Swap two objects of type TYPE.
|
||||
*/
|
||||
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
|
||||
|
||||
/*
|
||||
** Check to see if this machine uses EBCDIC. (Yes, believe it or
|
||||
** not, there are still machines out there that use EBCDIC.)
|
||||
@@ -525,7 +570,7 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
|
||||
** gives a possible range of values of approximately 1.0e986 to 1e-986.
|
||||
** But the allowed values are "grainy". Not every value is representable.
|
||||
** For example, quantities 16 and 17 are both represented by a LogEst
|
||||
** of 40. However, since LogEst quantaties are suppose to be estimates,
|
||||
** of 40. However, since LogEst quantities are suppose to be estimates,
|
||||
** not exact values, this imprecision is not a problem.
|
||||
**
|
||||
** "LogEst" is short for "Logarithmic Estimate".
|
||||
@@ -606,7 +651,7 @@ extern const int sqlite3one;
|
||||
** all alignment restrictions correct.
|
||||
**
|
||||
** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
|
||||
** underlying malloc() implemention might return us 4-byte aligned
|
||||
** underlying malloc() implementation might return us 4-byte aligned
|
||||
** pointers. In that case, only verify 4-byte alignment.
|
||||
*/
|
||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
@@ -673,6 +718,16 @@ extern const int sqlite3one;
|
||||
# undef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
#endif
|
||||
|
||||
/*
|
||||
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
|
||||
** the Select query generator tracing logic is turned on.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
# define SELECTTRACE_ENABLED 1
|
||||
#else
|
||||
# define SELECTTRACE_ENABLED 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** An instance of the following structure is used to store the busy-handler
|
||||
** callback for a given sqlite handle.
|
||||
@@ -805,12 +860,14 @@ typedef struct PrintfArguments PrintfArguments;
|
||||
typedef struct RowSet RowSet;
|
||||
typedef struct Savepoint Savepoint;
|
||||
typedef struct Select Select;
|
||||
typedef struct SQLiteThread SQLiteThread;
|
||||
typedef struct SelectDest SelectDest;
|
||||
typedef struct SrcList SrcList;
|
||||
typedef struct StrAccum StrAccum;
|
||||
typedef struct Table Table;
|
||||
typedef struct TableLock TableLock;
|
||||
typedef struct Token Token;
|
||||
typedef struct TreeView TreeView;
|
||||
typedef struct Trigger Trigger;
|
||||
typedef struct TriggerPrg TriggerPrg;
|
||||
typedef struct TriggerStep TriggerStep;
|
||||
@@ -907,7 +964,7 @@ struct Schema {
|
||||
** The number of different kinds of things that can be limited
|
||||
** using the sqlite3_limit() interface.
|
||||
*/
|
||||
#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_DEPTH+1)
|
||||
#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1)
|
||||
|
||||
/*
|
||||
** Lookaside malloc is a set of fixed-size buffers that can be used
|
||||
@@ -954,6 +1011,45 @@ struct FuncDefHash {
|
||||
FuncDef *a[23]; /* Hash table for functions */
|
||||
};
|
||||
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
/*
|
||||
** Information held in the "sqlite3" database connection object and used
|
||||
** to manage user authentication.
|
||||
*/
|
||||
typedef struct sqlite3_userauth sqlite3_userauth;
|
||||
struct sqlite3_userauth {
|
||||
u8 authLevel; /* Current authentication level */
|
||||
int nAuthPW; /* Size of the zAuthPW in bytes */
|
||||
char *zAuthPW; /* Password used to authenticate */
|
||||
char *zAuthUser; /* User name used to authenticate */
|
||||
};
|
||||
|
||||
/* Allowed values for sqlite3_userauth.authLevel */
|
||||
#define UAUTH_Unknown 0 /* Authentication not yet checked */
|
||||
#define UAUTH_Fail 1 /* User authentication failed */
|
||||
#define UAUTH_User 2 /* Authenticated as a normal user */
|
||||
#define UAUTH_Admin 3 /* Authenticated as an administrator */
|
||||
|
||||
/* Functions used only by user authorization logic */
|
||||
int sqlite3UserAuthTable(const char*);
|
||||
int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
|
||||
void sqlite3UserAuthInit(sqlite3*);
|
||||
void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
|
||||
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
|
||||
/*
|
||||
** typedef for the authorization callback function.
|
||||
*/
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
|
||||
const char*, const char*);
|
||||
#else
|
||||
typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
|
||||
const char*);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Each database connection is an instance of the following structure.
|
||||
*/
|
||||
@@ -971,6 +1067,7 @@ struct sqlite3 {
|
||||
int errCode; /* Most recent error code (SQLITE_*) */
|
||||
int errMask; /* & result codes with this before returning */
|
||||
u16 dbOptFlags; /* Flags to enable/disable optimizations */
|
||||
u8 enc; /* Text encoding */
|
||||
u8 autoCommit; /* The auto-commit flag. */
|
||||
u8 temp_store; /* 1: file 2: memory 0: default */
|
||||
u8 mallocFailed; /* True if we have seen a malloc failure */
|
||||
@@ -984,6 +1081,7 @@ struct sqlite3 {
|
||||
int nChange; /* Value returned by sqlite3_changes() */
|
||||
int nTotalChange; /* Value returned by sqlite3_total_changes() */
|
||||
int aLimit[SQLITE_N_LIMIT]; /* Limits */
|
||||
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
|
||||
struct sqlite3InitInfo { /* Information used during initialization */
|
||||
int newTnum; /* Rootpage of table being initialized */
|
||||
u8 iDb; /* Which db file is being initialized */
|
||||
@@ -1020,8 +1118,7 @@ struct sqlite3 {
|
||||
} u1;
|
||||
Lookaside lookaside; /* Lookaside malloc configuration */
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
|
||||
/* Access authorization function */
|
||||
sqlite3_xauth xAuth; /* Access authorization function */
|
||||
void *pAuthArg; /* 1st argument to the access auth function */
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
@@ -1047,7 +1144,6 @@ struct sqlite3 {
|
||||
i64 nDeferredCons; /* Net deferred constraints this transaction. */
|
||||
i64 nDeferredImmCons; /* Net deferred immediate constraints */
|
||||
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
|
||||
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
/* The following variables are all protected by the STATIC_MASTER
|
||||
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
|
||||
@@ -1065,12 +1161,16 @@ struct sqlite3 {
|
||||
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
|
||||
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
|
||||
#endif
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
sqlite3_userauth auth; /* User authentication information */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** A macro to discover the encoding of a database.
|
||||
*/
|
||||
#define ENC(db) ((db)->aDb[0].pSchema->enc)
|
||||
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
|
||||
#define ENC(db) ((db)->enc)
|
||||
|
||||
/*
|
||||
** Possible values for the sqlite3.flags.
|
||||
@@ -1123,8 +1223,7 @@ struct sqlite3 {
|
||||
#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
|
||||
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
|
||||
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
|
||||
#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */
|
||||
#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */
|
||||
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
|
||||
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
||||
|
||||
/*
|
||||
@@ -1211,6 +1310,7 @@ struct FuncDestructor {
|
||||
#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */
|
||||
#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */
|
||||
#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */
|
||||
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
|
||||
|
||||
/*
|
||||
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
|
||||
@@ -1258,6 +1358,9 @@ struct FuncDestructor {
|
||||
#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
|
||||
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
|
||||
SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}
|
||||
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
|
||||
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
|
||||
SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}
|
||||
|
||||
/*
|
||||
** All current savepoints are stored in a linked list starting at
|
||||
@@ -1344,18 +1447,18 @@ struct CollSeq {
|
||||
** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
|
||||
** the speed a little by numbering the values consecutively.
|
||||
**
|
||||
** But rather than start with 0 or 1, we begin with 'a'. That way,
|
||||
** But rather than start with 0 or 1, we begin with 'A'. That way,
|
||||
** when multiple affinity types are concatenated into a string and
|
||||
** used as the P4 operand, they will be more readable.
|
||||
**
|
||||
** Note also that the numeric types are grouped together so that testing
|
||||
** for a numeric type is a single comparison.
|
||||
** for a numeric type is a single comparison. And the NONE type is first.
|
||||
*/
|
||||
#define SQLITE_AFF_TEXT 'a'
|
||||
#define SQLITE_AFF_NONE 'b'
|
||||
#define SQLITE_AFF_NUMERIC 'c'
|
||||
#define SQLITE_AFF_INTEGER 'd'
|
||||
#define SQLITE_AFF_REAL 'e'
|
||||
#define SQLITE_AFF_NONE 'A'
|
||||
#define SQLITE_AFF_TEXT 'B'
|
||||
#define SQLITE_AFF_NUMERIC 'C'
|
||||
#define SQLITE_AFF_INTEGER 'D'
|
||||
#define SQLITE_AFF_REAL 'E'
|
||||
|
||||
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
|
||||
|
||||
@@ -1363,7 +1466,7 @@ struct CollSeq {
|
||||
** The SQLITE_AFF_MASK values masks off the significant bits of an
|
||||
** affinity value.
|
||||
*/
|
||||
#define SQLITE_AFF_MASK 0x67
|
||||
#define SQLITE_AFF_MASK 0x47
|
||||
|
||||
/*
|
||||
** Additional bit values that can be ORed with an affinity without
|
||||
@@ -1374,10 +1477,10 @@ struct CollSeq {
|
||||
** operator is NULL. It is added to certain comparison operators to
|
||||
** prove that the operands are always NOT NULL.
|
||||
*/
|
||||
#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */
|
||||
#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */
|
||||
#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */
|
||||
#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */
|
||||
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
|
||||
#define SQLITE_NOTNULL 0x88 /* Assert that operands are never NULL */
|
||||
#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
|
||||
|
||||
/*
|
||||
** An object of this type is created for each virtual table present in
|
||||
@@ -1647,7 +1750,7 @@ struct UnpackedRecord {
|
||||
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
||||
u16 nField; /* Number of entries in apMem[] */
|
||||
i8 default_rc; /* Comparison result if keys are equal */
|
||||
u8 isCorrupt; /* Corruption detected by xRecordCompare() */
|
||||
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
|
||||
Mem *aMem; /* Values */
|
||||
int r1; /* Value to return if (lhs > rhs) */
|
||||
int r2; /* Value to return if (rhs < lhs) */
|
||||
@@ -1691,7 +1794,6 @@ struct Index {
|
||||
u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
|
||||
char **azColl; /* Array of collation sequence names for index */
|
||||
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
|
||||
KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */
|
||||
int tnum; /* DB Page containing root of this index */
|
||||
LogEst szIdxRow; /* Estimated average row size in bytes */
|
||||
u16 nKeyCol; /* Number of columns forming the key */
|
||||
@@ -1702,11 +1804,14 @@ struct Index {
|
||||
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
|
||||
unsigned isResized:1; /* True if resizeIndexObject() has been called */
|
||||
unsigned isCovering:1; /* True if this is a covering index */
|
||||
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
int nSample; /* Number of elements in aSample[] */
|
||||
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
|
||||
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
|
||||
IndexSample *aSample; /* Samples of the left-most key */
|
||||
tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */
|
||||
tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1904,7 +2009,7 @@ struct Expr {
|
||||
int iTable; /* TK_COLUMN: cursor number of table holding column
|
||||
** TK_REGISTER: register number
|
||||
** TK_TRIGGER: 1 -> new, 0 -> old
|
||||
** EP_Unlikely: 1000 times likelihood */
|
||||
** EP_Unlikely: 134217728 times likelihood */
|
||||
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
|
||||
** TK_VARIABLE: variable number (always >= 1). */
|
||||
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
||||
@@ -1919,7 +2024,7 @@ struct Expr {
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags field.
|
||||
*/
|
||||
#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */
|
||||
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
|
||||
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x000008 /* Expression contains one or more errors */
|
||||
@@ -1939,6 +2044,7 @@ struct Expr {
|
||||
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
|
||||
#define EP_Constant 0x080000 /* Node is a constant */
|
||||
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
|
||||
|
||||
/*
|
||||
** These macros can be used to test, set, or clear bits in the
|
||||
@@ -2137,7 +2243,7 @@ struct SrcList {
|
||||
#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
|
||||
#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
|
||||
#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
|
||||
#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
|
||||
/* 0x0080 // not currently used */
|
||||
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
|
||||
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
|
||||
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
||||
@@ -2180,17 +2286,22 @@ struct NameContext {
|
||||
NameContext *pNext; /* Next outer name context. NULL for outermost */
|
||||
int nRef; /* Number of names resolved by this context */
|
||||
int nErr; /* Number of errors encountered while resolving names */
|
||||
u8 ncFlags; /* Zero or more NC_* flags defined below */
|
||||
u16 ncFlags; /* Zero or more NC_* flags defined below */
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values for the NameContext, ncFlags field.
|
||||
**
|
||||
** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and
|
||||
** SQLITE_FUNC_MINMAX.
|
||||
**
|
||||
*/
|
||||
#define NC_AllowAgg 0x01 /* Aggregate functions are allowed here */
|
||||
#define NC_HasAgg 0x02 /* One or more aggregate functions seen */
|
||||
#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
|
||||
#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
|
||||
#define NC_PartIdx 0x10 /* True if resolving a partial index WHERE */
|
||||
#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
|
||||
#define NC_HasAgg 0x0002 /* One or more aggregate functions seen */
|
||||
#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
|
||||
#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
|
||||
#define NC_PartIdx 0x0010 /* True if resolving a partial index WHERE */
|
||||
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
|
||||
|
||||
/*
|
||||
** An instance of the following structure contains all information
|
||||
@@ -2217,6 +2328,9 @@ struct Select {
|
||||
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
|
||||
u16 selFlags; /* Various SF_* values */
|
||||
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
|
||||
#if SELECTTRACE_ENABLED
|
||||
char zSelName[12]; /* Symbolic name of this SELECT use for debugging */
|
||||
#endif
|
||||
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
|
||||
u64 nSelectRow; /* Estimated number of result rows */
|
||||
SrcList *pSrc; /* The FROM clause */
|
||||
@@ -2241,13 +2355,13 @@ struct Select {
|
||||
#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
|
||||
#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
|
||||
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
|
||||
/* 0x0040 NOT USED */
|
||||
#define SF_Compound 0x0040 /* Part of a compound query */
|
||||
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
|
||||
/* 0x0100 NOT USED */
|
||||
#define SF_AllValues 0x0100 /* All terms of compound are VALUES */
|
||||
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
|
||||
#define SF_Compound 0x1000 /* Part of a compound query */
|
||||
#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */
|
||||
|
||||
|
||||
/*
|
||||
@@ -2475,6 +2589,10 @@ struct Parse {
|
||||
int regRowid; /* Register holding rowid of CREATE TABLE entry */
|
||||
int regRoot; /* Register holding root page number for new objects */
|
||||
int nMaxArg; /* Max args passed to user function by sub-program */
|
||||
#if SELECTTRACE_ENABLED
|
||||
int nSelect; /* Number of SELECT statements seen */
|
||||
int nSelectIndent; /* How far to indent SELECTTRACE() output */
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
int nTableLock; /* Number of locks in aTableLock */
|
||||
TableLock *aTableLock; /* Required table locks for shared-cache mode */
|
||||
@@ -2554,11 +2672,11 @@ struct AuthContext {
|
||||
** Bitfield flags for P5 value in various opcodes.
|
||||
*/
|
||||
#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */
|
||||
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
|
||||
#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
|
||||
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
|
||||
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
|
||||
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
|
||||
#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
|
||||
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
|
||||
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
|
||||
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
|
||||
@@ -2729,6 +2847,7 @@ struct Sqlite3Config {
|
||||
int nPage; /* Number of pages in pPage[] */
|
||||
int mxParserStack; /* maximum depth of the parser stack */
|
||||
int sharedCacheEnabled; /* true if shared-cache mode enabled */
|
||||
u32 szPma; /* Maximum Sorter PMA size */
|
||||
/* The above might be initialized to non-zero. The following need to always
|
||||
** initially be zero, however. */
|
||||
int isInit; /* True after initialization has finished */
|
||||
@@ -2784,9 +2903,11 @@ struct Walker {
|
||||
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
|
||||
Parse *pParse; /* Parser context. */
|
||||
int walkerDepth; /* Number of subqueries */
|
||||
u8 eCode; /* A small processing code */
|
||||
union { /* Extra data for callback */
|
||||
NameContext *pNC; /* Naming context */
|
||||
int i; /* Integer value */
|
||||
int n; /* A counter */
|
||||
int iCur; /* A cursor number */
|
||||
SrcList *pSrcList; /* FROM clause */
|
||||
struct SrcCount *pSrcCount; /* Counting column references */
|
||||
} u;
|
||||
@@ -2822,6 +2943,17 @@ struct With {
|
||||
} a[1];
|
||||
};
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** An instance of the TreeView object is used for printing the content of
|
||||
** data structures on sqlite3DebugPrintf() using a tree-like view.
|
||||
*/
|
||||
struct TreeView {
|
||||
int iLevel; /* Which level of the tree we are on */
|
||||
u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */
|
||||
};
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** Assuming zIn points to the first byte of a UTF-8 character,
|
||||
** advance zIn to point to the first byte of the next UTF-8 character.
|
||||
@@ -2849,11 +2981,11 @@ int sqlite3CantopenError(int);
|
||||
|
||||
/*
|
||||
** FTS4 is really an extension for FTS3. It is enabled using the
|
||||
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
|
||||
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
|
||||
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also call
|
||||
** the SQLITE_ENABLE_FTS4 macro to serve as an alias for SQLITE_ENABLE_FTS3.
|
||||
*/
|
||||
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
|
||||
# define SQLITE_ENABLE_FTS3
|
||||
# define SQLITE_ENABLE_FTS3 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -2887,6 +3019,7 @@ int sqlite3CantopenError(int);
|
||||
# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
|
||||
# define sqlite3Tolower(x) tolower((unsigned char)(x))
|
||||
#endif
|
||||
int sqlite3IsIdChar(u8);
|
||||
|
||||
/*
|
||||
** Internal function prototypes
|
||||
@@ -2897,15 +3030,15 @@ int sqlite3Strlen30(const char*);
|
||||
|
||||
int sqlite3MallocInit(void);
|
||||
void sqlite3MallocEnd(void);
|
||||
void *sqlite3Malloc(int);
|
||||
void *sqlite3MallocZero(int);
|
||||
void *sqlite3DbMallocZero(sqlite3*, int);
|
||||
void *sqlite3DbMallocRaw(sqlite3*, int);
|
||||
void *sqlite3Malloc(u64);
|
||||
void *sqlite3MallocZero(u64);
|
||||
void *sqlite3DbMallocZero(sqlite3*, u64);
|
||||
void *sqlite3DbMallocRaw(sqlite3*, u64);
|
||||
char *sqlite3DbStrDup(sqlite3*,const char*);
|
||||
char *sqlite3DbStrNDup(sqlite3*,const char*, int);
|
||||
void *sqlite3Realloc(void*, int);
|
||||
void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
|
||||
void *sqlite3DbRealloc(sqlite3 *, void *, int);
|
||||
char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
|
||||
void *sqlite3Realloc(void*, u64);
|
||||
void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
|
||||
void *sqlite3DbRealloc(sqlite3 *, void *, u64);
|
||||
void sqlite3DbFree(sqlite3*, void*);
|
||||
int sqlite3MallocSize(void*);
|
||||
int sqlite3DbMallocSize(sqlite3*, void*);
|
||||
@@ -2985,25 +3118,14 @@ char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
|
||||
void *sqlite3TestTextToPtr(const char*);
|
||||
#endif
|
||||
|
||||
/* Output formatting for SQLITE_TESTCTRL_EXPLAIN */
|
||||
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
|
||||
void sqlite3ExplainBegin(Vdbe*);
|
||||
void sqlite3ExplainPrintf(Vdbe*, const char*, ...);
|
||||
void sqlite3ExplainNL(Vdbe*);
|
||||
void sqlite3ExplainPush(Vdbe*);
|
||||
void sqlite3ExplainPop(Vdbe*);
|
||||
void sqlite3ExplainFinish(Vdbe*);
|
||||
void sqlite3ExplainSelect(Vdbe*, Select*);
|
||||
void sqlite3ExplainExpr(Vdbe*, Expr*);
|
||||
void sqlite3ExplainExprList(Vdbe*, ExprList*);
|
||||
const char *sqlite3VdbeExplanation(Vdbe*);
|
||||
#else
|
||||
# define sqlite3ExplainBegin(X)
|
||||
# define sqlite3ExplainSelect(A,B)
|
||||
# define sqlite3ExplainExpr(A,B)
|
||||
# define sqlite3ExplainExprList(A,B)
|
||||
# define sqlite3ExplainFinish(X)
|
||||
# define sqlite3VdbeExplanation(X) 0
|
||||
#if defined(SQLITE_DEBUG)
|
||||
TreeView *sqlite3TreeViewPush(TreeView*,u8);
|
||||
void sqlite3TreeViewPop(TreeView*);
|
||||
void sqlite3TreeViewLine(TreeView*, const char*, ...);
|
||||
void sqlite3TreeViewItem(TreeView*, const char*, u8);
|
||||
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
|
||||
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
|
||||
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3185,7 +3307,8 @@ void sqlite3CloseSavepoints(sqlite3 *);
|
||||
void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
||||
int sqlite3ExprIsConstant(Expr*);
|
||||
int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
||||
int sqlite3ExprIsTableConstant(Expr*,int);
|
||||
int sqlite3ExprIsInteger(Expr*, int*);
|
||||
int sqlite3ExprCanBeNull(const Expr*);
|
||||
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||
@@ -3209,6 +3332,11 @@ ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
|
||||
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
|
||||
IdList *sqlite3IdListDup(sqlite3*,IdList*);
|
||||
Select *sqlite3SelectDup(sqlite3*,Select*,int);
|
||||
#if SELECTTRACE_ENABLED
|
||||
void sqlite3SelectSetName(Select*,const char*);
|
||||
#else
|
||||
# define sqlite3SelectSetName(A,B)
|
||||
#endif
|
||||
void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
|
||||
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8);
|
||||
void sqlite3RegisterBuiltinFunctions(sqlite3*);
|
||||
@@ -3295,38 +3423,23 @@ u64 sqlite3LogEstToInt(LogEst);
|
||||
/*
|
||||
** Routines to read and write variable-length integers. These used to
|
||||
** be defined locally, but now we use the varint routines in the util.c
|
||||
** file. Code should use the MACRO forms below, as the Varint32 versions
|
||||
** are coded to assume the single byte case is already handled (which
|
||||
** the MACRO form does).
|
||||
** file.
|
||||
*/
|
||||
int sqlite3PutVarint(unsigned char*, u64);
|
||||
int sqlite3PutVarint32(unsigned char*, u32);
|
||||
u8 sqlite3GetVarint(const unsigned char *, u64 *);
|
||||
u8 sqlite3GetVarint32(const unsigned char *, u32 *);
|
||||
int sqlite3VarintLen(u64 v);
|
||||
|
||||
/*
|
||||
** The header of a record consists of a sequence variable-length integers.
|
||||
** These integers are almost always small and are encoded as a single byte.
|
||||
** The following macros take advantage this fact to provide a fast encode
|
||||
** and decode of the integers in a record header. It is faster for the common
|
||||
** case where the integer is a single byte. It is a little slower when the
|
||||
** integer is two or more bytes. But overall it is faster.
|
||||
**
|
||||
** The following expressions are equivalent:
|
||||
**
|
||||
** x = sqlite3GetVarint32( A, &B );
|
||||
** x = sqlite3PutVarint32( A, B );
|
||||
**
|
||||
** x = getVarint32( A, B );
|
||||
** x = putVarint32( A, B );
|
||||
**
|
||||
** The common case is for a varint to be a single byte. They following
|
||||
** macros handle the common case without a procedure call, but then call
|
||||
** the procedure for larger varints.
|
||||
*/
|
||||
#define getVarint32(A,B) \
|
||||
(u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
|
||||
#define putVarint32(A,B) \
|
||||
(u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
|
||||
sqlite3PutVarint32((A),(B)))
|
||||
sqlite3PutVarint((A),(B)))
|
||||
#define getVarint sqlite3GetVarint
|
||||
#define putVarint sqlite3PutVarint
|
||||
|
||||
@@ -3338,7 +3451,8 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
||||
char sqlite3ExprAffinity(Expr *pExpr);
|
||||
int sqlite3Atoi64(const char*, i64*, int, u8);
|
||||
int sqlite3DecOrHexToI64(const char*, i64*);
|
||||
void sqlite3Error(sqlite3*, int, const char*,...);
|
||||
void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
|
||||
void sqlite3Error(sqlite3*,int);
|
||||
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
|
||||
u8 sqlite3HexToInt(int h);
|
||||
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
||||
@@ -3440,7 +3554,7 @@ int sqlite3OpenTempDatabase(Parse *);
|
||||
void sqlite3StrAccumInit(StrAccum*, char*, int, int);
|
||||
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
|
||||
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
|
||||
void sqlite3AppendSpace(StrAccum*,int);
|
||||
void sqlite3AppendChar(StrAccum*,int,char);
|
||||
char *sqlite3StrAccumFinish(StrAccum*);
|
||||
void sqlite3StrAccumReset(StrAccum*);
|
||||
void sqlite3SelectDestInit(SelectDest*,int,int);
|
||||
@@ -3460,7 +3574,7 @@ int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**);
|
||||
/*
|
||||
** The interface to the LEMON-generated parser
|
||||
*/
|
||||
void *sqlite3ParserAlloc(void*(*)(size_t));
|
||||
void *sqlite3ParserAlloc(void*(*)(u64));
|
||||
void sqlite3ParserFree(void*, void(*)(void*));
|
||||
void sqlite3Parser(void*, int, Token, Parse*);
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
@@ -3700,9 +3814,16 @@ SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
|
||||
# define sqlite3MemdebugNoType(X,Y) 1
|
||||
#endif
|
||||
#define MEMTYPE_HEAP 0x01 /* General heap allocations */
|
||||
#define MEMTYPE_LOOKASIDE 0x02 /* Might have been lookaside memory */
|
||||
#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */
|
||||
#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
|
||||
#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
|
||||
#define MEMTYPE_DB 0x10 /* Uses sqlite3DbMalloc, not sqlite_malloc */
|
||||
|
||||
/*
|
||||
** Threading interface
|
||||
*/
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
|
||||
int sqlite3ThreadJoin(SQLiteThread*, void**);
|
||||
#endif
|
||||
|
||||
#endif /* _SQLITEINT_H_ */
|
||||
|
||||
+13
-3
@@ -86,6 +86,9 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
*pCurrent = wsdStat.nowValue[op];
|
||||
*pHighwater = wsdStat.mxValue[op];
|
||||
if( resetFlag ){
|
||||
@@ -105,6 +108,11 @@ int sqlite3_db_status(
|
||||
int resetFlag /* Reset high-water mark if true */
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
switch( op ){
|
||||
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
|
||||
@@ -213,7 +221,7 @@ int sqlite3_db_status(
|
||||
}
|
||||
db->pnBytesFreed = 0;
|
||||
|
||||
*pHighwater = 0;
|
||||
*pHighwater = 0; /* IMP: R-64479-57858 */
|
||||
*pCurrent = nByte;
|
||||
|
||||
break;
|
||||
@@ -238,7 +246,9 @@ int sqlite3_db_status(
|
||||
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
|
||||
}
|
||||
}
|
||||
*pHighwater = 0;
|
||||
*pHighwater = 0; /* IMP: R-42420-56072 */
|
||||
/* IMP: R-54100-20147 */
|
||||
/* IMP: R-29431-39229 */
|
||||
*pCurrent = nRet;
|
||||
break;
|
||||
}
|
||||
@@ -248,7 +258,7 @@ int sqlite3_db_status(
|
||||
** have been satisfied. The *pHighwater is always set to zero.
|
||||
*/
|
||||
case SQLITE_DBSTATUS_DEFERRED_FKS: {
|
||||
*pHighwater = 0;
|
||||
*pHighwater = 0; /* IMP: R-11967-56545 */
|
||||
*pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
|
||||
break;
|
||||
}
|
||||
|
||||
+10
-7
@@ -29,10 +29,10 @@
|
||||
typedef struct TabResult {
|
||||
char **azResult; /* Accumulated output */
|
||||
char *zErrMsg; /* Error message text, if an error occurs */
|
||||
int nAlloc; /* Slots allocated for azResult[] */
|
||||
int nRow; /* Number of rows in the result */
|
||||
int nColumn; /* Number of columns in the result */
|
||||
int nData; /* Slots used in azResult[]. (nRow+1)*nColumn */
|
||||
u32 nAlloc; /* Slots allocated for azResult[] */
|
||||
u32 nRow; /* Number of rows in the result */
|
||||
u32 nColumn; /* Number of columns in the result */
|
||||
u32 nData; /* Slots used in azResult[]. (nRow+1)*nColumn */
|
||||
int rc; /* Return code from sqlite3_exec() */
|
||||
} TabResult;
|
||||
|
||||
@@ -58,7 +58,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
|
||||
if( p->nData + need > p->nAlloc ){
|
||||
char **azNew;
|
||||
p->nAlloc = p->nAlloc*2 + need;
|
||||
azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc );
|
||||
azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
|
||||
if( azNew==0 ) goto malloc_failed;
|
||||
p->azResult = azNew;
|
||||
}
|
||||
@@ -73,7 +73,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
|
||||
if( z==0 ) goto malloc_failed;
|
||||
p->azResult[p->nData++] = z;
|
||||
}
|
||||
}else if( p->nColumn!=nCol ){
|
||||
}else if( (int)p->nColumn!=nCol ){
|
||||
sqlite3_free(p->zErrMsg);
|
||||
p->zErrMsg = sqlite3_mprintf(
|
||||
"sqlite3_get_table() called with two or more incompatible queries"
|
||||
@@ -126,6 +126,9 @@ int sqlite3_get_table(
|
||||
int rc;
|
||||
TabResult res;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
*pazResult = 0;
|
||||
if( pnColumn ) *pnColumn = 0;
|
||||
if( pnRow ) *pnRow = 0;
|
||||
@@ -182,7 +185,7 @@ int sqlite3_get_table(
|
||||
** This routine frees the space the sqlite3_get_table() malloced.
|
||||
*/
|
||||
void sqlite3_free_table(
|
||||
char **azResult /* Result returned from from sqlite3_get_table() */
|
||||
char **azResult /* Result returned from sqlite3_get_table() */
|
||||
){
|
||||
if( azResult ){
|
||||
int i, n;
|
||||
|
||||
+84
-6
@@ -25,6 +25,14 @@
|
||||
** hundreds of new commands used for testing
|
||||
** SQLite. This option implies -DSQLITE_TCLMD5.
|
||||
*/
|
||||
|
||||
/*
|
||||
** If requested, include the SQLite compiler options file for MSVC.
|
||||
*/
|
||||
#if defined(INCLUDE_MSVC_H)
|
||||
#include "msvc.h"
|
||||
#endif
|
||||
|
||||
#include "tcl.h"
|
||||
#include <errno.h>
|
||||
|
||||
@@ -635,6 +643,7 @@ static int DbWalHandler(
|
||||
Tcl_Interp *interp = pDb->interp;
|
||||
assert(pDb->pWalHook);
|
||||
|
||||
assert( db==pDb->db );
|
||||
p = Tcl_DuplicateObj(pDb->pWalHook);
|
||||
Tcl_IncrRefCount(p);
|
||||
Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1));
|
||||
@@ -760,7 +769,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
||||
/* If there are arguments to the function, make a shallow copy of the
|
||||
** script object, lappend the arguments, then evaluate the copy.
|
||||
**
|
||||
** By "shallow" copy, we mean a only the outer list Tcl_Obj is duplicated.
|
||||
** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated.
|
||||
** The new Tcl_Obj contains pointers to the original list elements.
|
||||
** That way, when Tcl_EvalObjv() is run and shimmers the first element
|
||||
** of the list to tclCmdNameType, that alternate representation will
|
||||
@@ -872,6 +881,9 @@ static int auth_callback(
|
||||
const char *zArg2,
|
||||
const char *zArg3,
|
||||
const char *zArg4
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
,const char *zArg5
|
||||
#endif
|
||||
){
|
||||
const char *zCode;
|
||||
Tcl_DString str;
|
||||
@@ -924,6 +936,9 @@ static int auth_callback(
|
||||
Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
|
||||
Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
|
||||
Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
Tcl_DStringAppendElement(&str, zArg5 ? zArg5 : "");
|
||||
#endif
|
||||
rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
|
||||
Tcl_DStringFree(&str);
|
||||
zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
|
||||
@@ -1078,10 +1093,10 @@ static int dbPrepareAndBind(
|
||||
SqlPreparedStmt **ppPreStmt /* OUT: Object used to cache statement */
|
||||
){
|
||||
const char *zSql = zIn; /* Pointer to first SQL statement in zIn */
|
||||
sqlite3_stmt *pStmt; /* Prepared statement object */
|
||||
sqlite3_stmt *pStmt = 0; /* Prepared statement object */
|
||||
SqlPreparedStmt *pPreStmt; /* Pointer to cached statement */
|
||||
int nSql; /* Length of zSql in bytes */
|
||||
int nVar; /* Number of variables in statement */
|
||||
int nVar = 0; /* Number of variables in statement */
|
||||
int iParm = 0; /* Next free entry in apParm */
|
||||
char c;
|
||||
int i;
|
||||
@@ -1700,8 +1715,11 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
pDb->zAuth = 0;
|
||||
}
|
||||
if( pDb->zAuth ){
|
||||
typedef int (*sqlite3_auth_cb)(
|
||||
void*,int,const char*,const char*,
|
||||
const char*,const char*);
|
||||
pDb->interp = interp;
|
||||
sqlite3_set_authorizer(pDb->db, auth_callback, pDb);
|
||||
sqlite3_set_authorizer(pDb->db,(sqlite3_auth_cb)auth_callback,pDb);
|
||||
}else{
|
||||
sqlite3_set_authorizer(pDb->db, 0, 0);
|
||||
}
|
||||
@@ -2381,7 +2399,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
|
||||
if( rc==TCL_OK ){
|
||||
rc = createIncrblobChannel(
|
||||
interp, pDb, zDb, zTable, zColumn, iRow, isReadonly
|
||||
interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly
|
||||
);
|
||||
}
|
||||
#endif
|
||||
@@ -3092,7 +3110,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
** The EXTERN macros are required by TCL in order to work on windows.
|
||||
*/
|
||||
EXTERN int Sqlite3_Init(Tcl_Interp *interp){
|
||||
int rc = Tcl_InitStubs(interp, "8.4", 0)==0 ? TCL_ERROR : TCL_OK;
|
||||
int rc = Tcl_InitStubs(interp, "8.4", 0) ? TCL_OK : TCL_ERROR;
|
||||
if( rc==TCL_OK ){
|
||||
Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
|
||||
#ifndef SQLITE_3_SUFFIX_ONLY
|
||||
@@ -3632,6 +3650,45 @@ static int db_use_legacy_prepare_cmd(
|
||||
Tcl_ResetResult(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Tclcmd: db_last_stmt_ptr DB
|
||||
**
|
||||
** If the statement cache associated with database DB is not empty,
|
||||
** return the text representation of the most recently used statement
|
||||
** handle.
|
||||
*/
|
||||
static int db_last_stmt_ptr(
|
||||
ClientData cd,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
|
||||
Tcl_CmdInfo cmdInfo;
|
||||
SqliteDb *pDb;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
char zBuf[100];
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
|
||||
Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pDb = (SqliteDb*)cmdInfo.objClientData;
|
||||
|
||||
if( pDb->stmtList ) pStmt = pDb->stmtList->pStmt;
|
||||
if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -3677,6 +3734,7 @@ static void init_all(Tcl_Interp *interp){
|
||||
extern int Sqlitetest9_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestasync_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_autoext_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_blob_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_demovfs_Init(Tcl_Interp *);
|
||||
extern int Sqlitetest_func_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_hexio_Init(Tcl_Interp*);
|
||||
@@ -3720,6 +3778,7 @@ static void init_all(Tcl_Interp *interp){
|
||||
Sqlitetest9_Init(interp);
|
||||
Sqlitetestasync_Init(interp);
|
||||
Sqlitetest_autoext_Init(interp);
|
||||
Sqlitetest_blob_Init(interp);
|
||||
Sqlitetest_demovfs_Init(interp);
|
||||
Sqlitetest_func_Init(interp);
|
||||
Sqlitetest_hexio_Init(interp);
|
||||
@@ -3751,6 +3810,9 @@ static void init_all(Tcl_Interp *interp){
|
||||
Tcl_CreateObjCommand(
|
||||
interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0
|
||||
);
|
||||
Tcl_CreateObjCommand(
|
||||
interp, "db_last_stmt_ptr", db_last_stmt_ptr, 0, 0
|
||||
);
|
||||
|
||||
#ifdef SQLITE_SSE
|
||||
Sqlitetestsse_Init(interp);
|
||||
@@ -3759,6 +3821,11 @@ static void init_all(Tcl_Interp *interp){
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Needed for the setrlimit() system call on unix */
|
||||
#if defined(unix)
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#define TCLSH_MAIN main /* Needed to fake out mktclapp */
|
||||
int TCLSH_MAIN(int argc, char **argv){
|
||||
Tcl_Interp *interp;
|
||||
@@ -3772,6 +3839,17 @@ int TCLSH_MAIN(int argc, char **argv){
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Since the primary use case for this binary is testing of SQLite,
|
||||
** be sure to generate core files if we crash */
|
||||
#if defined(SQLITE_TEST) && defined(unix)
|
||||
{ struct rlimit x;
|
||||
getrlimit(RLIMIT_CORE, &x);
|
||||
x.rlim_cur = x.rlim_max;
|
||||
setrlimit(RLIMIT_CORE, &x);
|
||||
}
|
||||
#endif /* SQLITE_TEST && unix */
|
||||
|
||||
|
||||
/* Call sqlite3_shutdown() once before doing anything else. This is to
|
||||
** test that sqlite3_shutdown() can be safely called by a process before
|
||||
** sqlite3_initialize() is. */
|
||||
|
||||
+514
-173
@@ -261,6 +261,8 @@ static int test_io_trace(
|
||||
**
|
||||
** Returns true if the program was compiled using clang with the
|
||||
** -fsanitize=address switch on the command line. False otherwise.
|
||||
**
|
||||
** Also return true if the OMIT_MISUSE environment variable exists.
|
||||
*/
|
||||
static int clang_sanitize_address(
|
||||
void *NotUsed,
|
||||
@@ -274,6 +276,7 @@ static int clang_sanitize_address(
|
||||
res = 1;
|
||||
# endif
|
||||
#endif
|
||||
if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1;
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -564,7 +567,7 @@ static int test_get_table_printf(
|
||||
Tcl_DString str;
|
||||
int rc;
|
||||
char *zErr = 0;
|
||||
int nRow, nCol;
|
||||
int nRow = 0, nCol = 0;
|
||||
char **aResult;
|
||||
int i;
|
||||
char zBuf[30];
|
||||
@@ -1569,7 +1572,6 @@ static int test_libversion_number(
|
||||
** Usage: sqlite3_table_column_metadata DB dbname tblname colname
|
||||
**
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
static int test_table_column_metadata(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
@@ -1589,14 +1591,14 @@ static int test_table_column_metadata(
|
||||
int primarykey;
|
||||
int autoincrement;
|
||||
|
||||
if( objc!=5 ){
|
||||
if( objc!=5 && objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
zDb = Tcl_GetString(objv[2]);
|
||||
zTbl = Tcl_GetString(objv[3]);
|
||||
zCol = Tcl_GetString(objv[4]);
|
||||
zCol = objc==5 ? Tcl_GetString(objv[4]) : 0;
|
||||
|
||||
if( strlen(zDb)==0 ) zDb = 0;
|
||||
|
||||
@@ -1618,7 +1620,6 @@ static int test_table_column_metadata(
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
|
||||
@@ -1651,154 +1652,6 @@ static int blobHandleFromObj(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_bytes CHANNEL
|
||||
*/
|
||||
static int test_blob_bytes(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int nByte;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
nByte = sqlite3_blob_bytes(pBlob);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte));
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_close CHANNEL
|
||||
*/
|
||||
static int test_blob_close(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
sqlite3_blob_close(pBlob);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_read CHANNEL OFFSET N
|
||||
**
|
||||
** This command is used to test the sqlite3_blob_read() in ways that
|
||||
** the Tcl channel interface does not. The first argument should
|
||||
** be the name of a valid channel created by the [incrblob] method
|
||||
** of a database handle. This function calls sqlite3_blob_read()
|
||||
** to read N bytes from offset OFFSET from the underlying SQLite
|
||||
** blob handle.
|
||||
**
|
||||
** On success, a byte-array object containing the read data is
|
||||
** returned. On failure, the interpreter result is set to the
|
||||
** text representation of the returned error code (i.e. "SQLITE_NOMEM")
|
||||
** and a Tcl exception is thrown.
|
||||
*/
|
||||
static int test_blob_read(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int nByte;
|
||||
int iOffset;
|
||||
unsigned char *zBuf = 0;
|
||||
int rc;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset)
|
||||
|| TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte)
|
||||
){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( nByte>0 ){
|
||||
zBuf = (unsigned char *)Tcl_Alloc(nByte);
|
||||
}
|
||||
rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset);
|
||||
if( rc==SQLITE_OK ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte));
|
||||
}else{
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
}
|
||||
Tcl_Free((char *)zBuf);
|
||||
|
||||
return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_write CHANNEL OFFSET DATA ?NDATA?
|
||||
**
|
||||
** This command is used to test the sqlite3_blob_write() in ways that
|
||||
** the Tcl channel interface does not. The first argument should
|
||||
** be the name of a valid channel created by the [incrblob] method
|
||||
** of a database handle. This function calls sqlite3_blob_write()
|
||||
** to write the DATA byte-array to the underlying SQLite blob handle.
|
||||
** at offset OFFSET.
|
||||
**
|
||||
** On success, an empty string is returned. On failure, the interpreter
|
||||
** result is set to the text representation of the returned error code
|
||||
** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown.
|
||||
*/
|
||||
static int test_blob_write(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int iOffset;
|
||||
int rc;
|
||||
|
||||
unsigned char *zBuf;
|
||||
int nBuf;
|
||||
|
||||
if( objc!=4 && objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
|
||||
if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
}
|
||||
|
||||
return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
||||
}
|
||||
|
||||
static int test_blob_reopen(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
@@ -2267,7 +2120,7 @@ static int test_stmt_status(
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int iValue;
|
||||
int i, op, resetFlag;
|
||||
int i, op = 0, resetFlag;
|
||||
const char *zOpName;
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
@@ -2301,6 +2154,77 @@ static int test_stmt_status(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
/*
|
||||
** Usage: sqlite3_stmt_scanstatus STMT IDX
|
||||
*/
|
||||
static int test_stmt_scanstatus(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_stmt *pStmt; /* First argument */
|
||||
int idx; /* Second argument */
|
||||
|
||||
const char *zName;
|
||||
const char *zExplain;
|
||||
sqlite3_int64 nLoop;
|
||||
sqlite3_int64 nVisit;
|
||||
double rEst;
|
||||
int res;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
|
||||
|
||||
res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
|
||||
if( res==0 ){
|
||||
Tcl_Obj *pRet = Tcl_NewObj();
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
|
||||
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
|
||||
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
|
||||
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
|
||||
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
|
||||
Tcl_SetObjResult(interp, pRet);
|
||||
}else{
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_stmt_scanstatus_reset STMT
|
||||
*/
|
||||
static int test_stmt_scanstatus_reset(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_stmt *pStmt; /* First argument */
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "STMT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
sqlite3_stmt_scanstatus_reset(pStmt);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_next_stmt DB STMT
|
||||
**
|
||||
@@ -2605,7 +2529,7 @@ static int test_bind(
|
||||
** SQLite selected to call. The TCL test script implements the
|
||||
** "test_collate" proc.
|
||||
**
|
||||
** Note that this will only work with one intepreter at a time, as the
|
||||
** Note that this will only work with one interpreter at a time, as the
|
||||
** interp pointer to use when evaluating the TCL script is stored in
|
||||
** pTestCollateInterp.
|
||||
*/
|
||||
@@ -2717,6 +2641,46 @@ bad_args:
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: add_test_utf16bin_collate <db ptr>
|
||||
**
|
||||
** Add a utf-16 collation sequence named "utf16bin" to the database
|
||||
** handle. This collation sequence compares arguments in the same way as the
|
||||
** built-in collation "binary".
|
||||
*/
|
||||
static int test_utf16bin_collate_func(
|
||||
void *pCtx,
|
||||
int nA, const void *zA,
|
||||
int nB, const void *zB
|
||||
){
|
||||
int nCmp = (nA>nB ? nB : nA);
|
||||
int res = memcmp(zA, zB, nCmp);
|
||||
if( res==0 ) res = nA - nB;
|
||||
return res;
|
||||
}
|
||||
static int test_utf16bin_collate(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
if( objc!=2 ) goto bad_args;
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
|
||||
test_utf16bin_collate_func
|
||||
);
|
||||
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
||||
return TCL_OK;
|
||||
|
||||
bad_args:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** When the collation needed callback is invoked, record the name of
|
||||
** the requested collating function here. The recorded name is linked
|
||||
@@ -3134,7 +3098,7 @@ static int test_bind_double(
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int idx;
|
||||
double value;
|
||||
double value = 0;
|
||||
int rc;
|
||||
const char *zVal;
|
||||
int i;
|
||||
@@ -3675,6 +3639,7 @@ static int test_prepare_v2(
|
||||
){
|
||||
sqlite3 *db;
|
||||
const char *zSql;
|
||||
char *zCopy = 0; /* malloc() copy of zSql */
|
||||
int bytes;
|
||||
const char *zTail = 0;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
@@ -3690,11 +3655,25 @@ static int test_prepare_v2(
|
||||
zSql = Tcl_GetString(objv[2]);
|
||||
if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
|
||||
/* Instead of using zSql directly, make a copy into a buffer obtained
|
||||
** directly from malloc(). The idea is to make it easier for valgrind
|
||||
** to spot buffer overreads. */
|
||||
if( bytes>=0 ){
|
||||
zCopy = malloc(bytes);
|
||||
memcpy(zCopy, zSql, bytes);
|
||||
}else{
|
||||
int n = (int)strlen(zSql) + 1;
|
||||
zCopy = malloc(n);
|
||||
memcpy(zCopy, zSql, n);
|
||||
}
|
||||
rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
|
||||
free(zCopy);
|
||||
zTail = &zSql[(zTail - zCopy)];
|
||||
|
||||
assert(rc==SQLITE_OK || pStmt==0);
|
||||
Tcl_ResetResult(interp);
|
||||
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
||||
if( zTail && objc>=5 ){
|
||||
if( rc==SQLITE_OK && zTail && objc>=5 ){
|
||||
if( bytes>=0 ){
|
||||
bytes = bytes - (int)(zTail-zSql);
|
||||
}
|
||||
@@ -3718,7 +3697,7 @@ static int test_prepare_v2(
|
||||
** Usage: sqlite3_prepare_tkt3134 DB
|
||||
**
|
||||
** Generate a prepared statement for a zero-byte string as a test
|
||||
** for ticket #3134. The string should be preceeded by a zero byte.
|
||||
** for ticket #3134. The string should be preceded by a zero byte.
|
||||
*/
|
||||
static int test_prepare_tkt3134(
|
||||
void * clientData,
|
||||
@@ -5473,12 +5452,13 @@ static int test_limit(
|
||||
{ "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
|
||||
{ "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
|
||||
{ "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
|
||||
{ "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
|
||||
|
||||
/* Out of range test cases */
|
||||
{ "SQLITE_LIMIT_TOOSMALL", -1, },
|
||||
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_TRIGGER_DEPTH+1 },
|
||||
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
|
||||
};
|
||||
int i, id;
|
||||
int i, id = 0;
|
||||
int val;
|
||||
const char *zId;
|
||||
|
||||
@@ -5711,10 +5691,11 @@ static int test_wal_checkpoint_v2(
|
||||
int nCkpt = -555;
|
||||
Tcl_Obj *pRet;
|
||||
|
||||
const char * aMode[] = { "passive", "full", "restart", 0 };
|
||||
const char * aMode[] = { "passive", "full", "restart", "truncate", 0 };
|
||||
assert( SQLITE_CHECKPOINT_PASSIVE==0 );
|
||||
assert( SQLITE_CHECKPOINT_FULL==1 );
|
||||
assert( SQLITE_CHECKPOINT_RESTART==2 );
|
||||
assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
|
||||
|
||||
if( objc!=3 && objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
|
||||
@@ -5724,15 +5705,18 @@ static int test_wal_checkpoint_v2(
|
||||
if( objc==4 ){
|
||||
zDb = Tcl_GetString(objv[3]);
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
|
||||
|| Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
|
||||
){
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || (
|
||||
TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode)
|
||||
&& TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
|
||||
)){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
|
||||
Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
|
||||
const char *zErrCode = sqlite3ErrName(rc);
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -5745,6 +5729,43 @@ static int test_wal_checkpoint_v2(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: sqlite3_wal_autocheckpoint db VALUE
|
||||
*/
|
||||
static int test_wal_autocheckpoint(
|
||||
ClientData clientData, /* Unused */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
int iVal;
|
||||
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
|
||||
|| Tcl_GetIntFromObj(0, objv[2], &iVal)
|
||||
){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = sqlite3_wal_autocheckpoint(db, iVal);
|
||||
Tcl_ResetResult(interp);
|
||||
if( rc!=SQLITE_OK ){
|
||||
const char *zErrCode = sqlite3ErrName(rc);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** tclcmd: test_sqlite3_log ?SCRIPT?
|
||||
*/
|
||||
@@ -5895,6 +5916,7 @@ static int test_test_control(
|
||||
int i;
|
||||
} aVerb[] = {
|
||||
{ "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
|
||||
{ "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
|
||||
};
|
||||
int iVerb;
|
||||
int iFlag;
|
||||
@@ -5922,6 +5944,19 @@ static int test_test_control(
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
|
||||
break;
|
||||
}
|
||||
|
||||
case SQLITE_TESTCTRL_SORTER_MMAP: {
|
||||
int val;
|
||||
sqlite3 *db;
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
@@ -6238,7 +6273,8 @@ static int optimization_control(
|
||||
{ "transitive", SQLITE_Transitive },
|
||||
{ "subquery-coroutine", SQLITE_SubqCoroutine },
|
||||
{ "omit-noop-join", SQLITE_OmitNoopJoin },
|
||||
{ "stat3", SQLITE_Stat3 },
|
||||
{ "stat3", SQLITE_Stat34 },
|
||||
{ "stat4", SQLITE_Stat34 },
|
||||
};
|
||||
|
||||
if( objc!=4 ){
|
||||
@@ -6281,6 +6317,7 @@ static int tclLoadStaticExtensionCmd(
|
||||
){
|
||||
extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
@@ -6296,6 +6333,7 @@ static int tclLoadStaticExtensionCmd(
|
||||
} aExtension[] = {
|
||||
{ "amatch", sqlite3_amatch_init },
|
||||
{ "closure", sqlite3_closure_init },
|
||||
{ "eval", sqlite3_eval_init },
|
||||
{ "fileio", sqlite3_fileio_init },
|
||||
{ "fuzzer", sqlite3_fuzzer_init },
|
||||
{ "ieee754", sqlite3_ieee_init },
|
||||
@@ -6335,6 +6373,298 @@ static int tclLoadStaticExtensionCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sorter_test_fakeheap BOOL
|
||||
**
|
||||
*/
|
||||
static int sorter_test_fakeheap(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int bArg;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( bArg ){
|
||||
if( sqlite3GlobalConfig.pHeap==0 ){
|
||||
sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
|
||||
}
|
||||
}else{
|
||||
if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
|
||||
sqlite3GlobalConfig.pHeap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sorter_test_sort4_helper DB SQL1 NSTEP SQL2
|
||||
**
|
||||
** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
|
||||
** check that the leftmost and rightmost columns returned are both integers,
|
||||
** and that both contain the same value.
|
||||
**
|
||||
** Then execute statement $SQL2. Check that the statement returns the same
|
||||
** set of integers in the same order as in the previous step (using $SQL1).
|
||||
*/
|
||||
static int sorter_test_sort4_helper(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
const char *zSql1;
|
||||
const char *zSql2;
|
||||
int nStep;
|
||||
int iStep;
|
||||
int iCksum1 = 0;
|
||||
int iCksum2 = 0;
|
||||
int rc;
|
||||
int iB;
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
if( objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
zSql1 = Tcl_GetString(objv[2]);
|
||||
if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
|
||||
zSql2 = Tcl_GetString(objv[4]);
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
|
||||
iB = sqlite3_column_count(pStmt)-1;
|
||||
for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
|
||||
int a = sqlite3_column_int(pStmt, 0);
|
||||
if( a!=sqlite3_column_int(pStmt, iB) ){
|
||||
Tcl_AppendResult(interp, "data error: (a!=b)", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
iCksum1 += (iCksum1 << 3) + a;
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
|
||||
int a = sqlite3_column_int(pStmt, 0);
|
||||
iCksum2 += (iCksum2 << 3) + a;
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ) goto sql_error;
|
||||
|
||||
if( iCksum1!=iCksum2 ){
|
||||
Tcl_AppendResult(interp, "checksum mismatch", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
sql_error:
|
||||
Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
#include "sqlite3userauth.h"
|
||||
/*
|
||||
** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD
|
||||
*/
|
||||
static int test_user_authenticate(
|
||||
ClientData clientData, /* Unused */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
char *zUser = 0;
|
||||
char *zPasswd = 0;
|
||||
int nPasswd = 0;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zUser = Tcl_GetString(objv[2]);
|
||||
zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
|
||||
rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
|
||||
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
/*
|
||||
** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN
|
||||
*/
|
||||
static int test_user_add(
|
||||
ClientData clientData, /* Unused */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
char *zUser = 0;
|
||||
char *zPasswd = 0;
|
||||
int nPasswd = 0;
|
||||
int isAdmin = 0;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
if( objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zUser = Tcl_GetString(objv[2]);
|
||||
zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
|
||||
Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
|
||||
rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
|
||||
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
/*
|
||||
** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN
|
||||
*/
|
||||
static int test_user_change(
|
||||
ClientData clientData, /* Unused */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
char *zUser = 0;
|
||||
char *zPasswd = 0;
|
||||
int nPasswd = 0;
|
||||
int isAdmin = 0;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
if( objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zUser = Tcl_GetString(objv[2]);
|
||||
zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
|
||||
Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
|
||||
rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
|
||||
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
/*
|
||||
** tclcmd: sqlite3_user_delete DB USERNAME
|
||||
*/
|
||||
static int test_user_delete(
|
||||
ClientData clientData, /* Unused */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
char *zUser = 0;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zUser = Tcl_GetString(objv[2]);
|
||||
rc = sqlite3_user_delete(db, zUser);
|
||||
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
|
||||
/*
|
||||
** tclcmd: bad_behavior TYPE
|
||||
**
|
||||
** Do some things that should trigger a valgrind or -fsanitize=undefined
|
||||
** warning. This is used to verify that errors and warnings output by those
|
||||
** tools are detected by the test scripts.
|
||||
**
|
||||
** TYPE BEHAVIOR
|
||||
** 1 Overflow a signed integer
|
||||
** 2 Jump based on an uninitialized variable
|
||||
** 3 Read after free
|
||||
** 4 Panic
|
||||
*/
|
||||
static int test_bad_behavior(
|
||||
ClientData clientData, /* Pointer to an integer containing zero */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
int iType;
|
||||
int xyz;
|
||||
int i = *(int*)clientData;
|
||||
int j;
|
||||
int w[10];
|
||||
int *a;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "TYPE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR;
|
||||
switch( iType ){
|
||||
case 1: {
|
||||
xyz = 0x7fffff00 - i;
|
||||
xyz += 0x100;
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz));
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
w[1] = 5;
|
||||
if( w[i]>0 ) w[1]++;
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1]));
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
a = malloc( sizeof(int)*10 );
|
||||
for(j=0; j<10; j++) a[j] = j;
|
||||
free(a);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i]));
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
Tcl_Panic("Deliberate panic");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register commands with the TCL interpreter.
|
||||
@@ -6352,6 +6682,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
extern int sqlite3_max_blobsize;
|
||||
extern int sqlite3BtreeSharedCacheReport(void*,
|
||||
Tcl_Interp*,int,Tcl_Obj*CONST*);
|
||||
static int iZero = 0;
|
||||
static struct {
|
||||
char *zName;
|
||||
Tcl_CmdProc *xProc;
|
||||
@@ -6404,6 +6735,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
Tcl_ObjCmdProc *xProc;
|
||||
void *clientData;
|
||||
} aObjCmd[] = {
|
||||
{ "bad_behavior", test_bad_behavior, (void*)&iZero },
|
||||
{ "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
|
||||
{ "sqlite3_bind_int", test_bind_int, 0 },
|
||||
{ "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
|
||||
@@ -6537,6 +6869,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "add_test_collate", test_collate, 0 },
|
||||
{ "add_test_collate_needed", test_collate_needed, 0 },
|
||||
{ "add_test_function", test_function, 0 },
|
||||
{ "add_test_utf16bin_collate", test_utf16bin_collate, 0 },
|
||||
#endif
|
||||
{ "sqlite3_test_errstr", test_errstr, 0 },
|
||||
{ "tcl_variable_type", tcl_variable_type, 0 },
|
||||
@@ -6545,15 +6878,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
|
||||
#endif
|
||||
{ "sqlite3_libversion_number", test_libversion_number, 0 },
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
{ "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
{ "sqlite3_blob_read", test_blob_read, 0 },
|
||||
{ "sqlite3_blob_write", test_blob_write, 0 },
|
||||
{ "sqlite3_blob_reopen", test_blob_reopen, 0 },
|
||||
{ "sqlite3_blob_bytes", test_blob_bytes, 0 },
|
||||
{ "sqlite3_blob_close", test_blob_close, 0 },
|
||||
#endif
|
||||
{ "pcache_stats", test_pcache_stats, 0 },
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
@@ -6561,6 +6888,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
#endif
|
||||
{ "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
|
||||
{ "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
|
||||
{ "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 },
|
||||
{ "test_sqlite3_log", test_sqlite3_log, 0 },
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
{ "print_explain_query_plan", test_print_eqp, 0 },
|
||||
@@ -6570,6 +6898,19 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "getrusage", test_getrusage },
|
||||
#endif
|
||||
{ "load_static_extension", tclLoadStaticExtensionCmd },
|
||||
{ "sorter_test_fakeheap", sorter_test_fakeheap },
|
||||
{ "sorter_test_sort4_helper", sorter_test_sort4_helper },
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
{ "sqlite3_user_authenticate", test_user_authenticate, 0 },
|
||||
{ "sqlite3_user_add", test_user_add, 0 },
|
||||
{ "sqlite3_user_change", test_user_change, 0 },
|
||||
{ "sqlite3_user_delete", test_user_delete, 0 },
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
{ "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 },
|
||||
{ "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 },
|
||||
#endif
|
||||
|
||||
};
|
||||
static int bitmask_size = sizeof(Bitmask)*8;
|
||||
int i;
|
||||
|
||||
+1
-1
@@ -310,7 +310,7 @@ static int page_get(
|
||||
){
|
||||
Pager *pPager;
|
||||
char zBuf[100];
|
||||
DbPage *pPage;
|
||||
DbPage *pPage = 0;
|
||||
int pgno;
|
||||
int rc;
|
||||
if( argc!=3 ){
|
||||
|
||||
+5
-5
@@ -648,12 +648,12 @@ static int echoRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
** indeed the hash of the supplied idxStr.
|
||||
*/
|
||||
static int hashString(const char *zString){
|
||||
int val = 0;
|
||||
u32 val = 0;
|
||||
int ii;
|
||||
for(ii=0; zString[ii]; ii++){
|
||||
val = (val << 3) + (int)zString[ii];
|
||||
}
|
||||
return val;
|
||||
return (int)(val&0x7fffffff);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -777,11 +777,11 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
Tcl_Interp *interp = pVtab->interp;
|
||||
|
||||
int nRow;
|
||||
int nRow = 0;
|
||||
int useIdx = 0;
|
||||
int rc = SQLITE_OK;
|
||||
int useCost = 0;
|
||||
double cost;
|
||||
double cost = 0;
|
||||
int isIgnoreUsable = 0;
|
||||
if( Tcl_GetVar(interp, "echo_module_ignore_usable", TCL_GLOBAL_ONLY) ){
|
||||
isIgnoreUsable = 1;
|
||||
@@ -927,7 +927,7 @@ int echoUpdate(
|
||||
sqlite3 *db = pVtab->db;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
sqlite3_stmt *pStmt;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
char *z = 0; /* SQL statement to execute */
|
||||
int bindArgZero = 0; /* True to bind apData[0] to sql var no. nData */
|
||||
int bindArgOne = 0; /* True to bind apData[1] to sql var no. 1 */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user