Compare commits

..

1 Commits

Author SHA1 Message Date
drh 464a2dd1f5 Add code to check the validity of CollSeq objects during runtime. This code
was not able to detect anomalies such as came up as a result of
ticket [e4a18565a36884b00edf66541f38c693827968ab] so it is put into a branch
for historical reference, with the intent of leaving it out of trunk.

FossilOrigin-Name: 68b23c3d41ce9303f42251d0c199181312e148f9
2014-12-05 14:36:15 +00:00
110 changed files with 1262 additions and 4880 deletions
+5 -62
View File
@@ -22,15 +22,11 @@ TOP = @srcdir@
#
BCC = @BUILD_CC@ @BUILD_CFLAGS@
# TCC is the C Compile and options for use in building executables that
# 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.) 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"
# same unless your are cross-compiling.)
#
CC = @CC@
CFLAGS = @CPPFLAGS@ @CFLAGS@
TCC = $(CC) $(CFLAGS) -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/fts3
TCC = @CC@ @CPPFLAGS@ @CFLAGS@ -I. -I${TOP}/src -I${TOP}/ext/rtree
# Define this for the autoconf-based build, so that the code knows it can
# include the generated config.h
@@ -41,7 +37,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@
TCC += @TARGET_DEBUG@ @XTHREADCONNECT@
# Compiler options needed for programs that use the TCL library.
#
@@ -234,7 +230,6 @@ 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 \
@@ -464,7 +459,6 @@ 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 \
@@ -536,11 +530,6 @@ 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
@@ -932,37 +921,19 @@ 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) sqlite3$(TEXE)
./testfixture$(TEXE) $(TOP)/test/all.test
# Really really long testing
soaktest: testfixture$(TEXE) sqlite3$(TEXE)
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1
# Do extra testing but not aeverything.
fulltestonly: testfixture$(TEXE) sqlite3$(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) sqlite3$(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 >> $@
@@ -998,34 +969,6 @@ 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'
# 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: libsqlite3.la
+22 -59
View File
@@ -16,23 +16,6 @@ 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.
#
@@ -125,12 +108,11 @@ WIN32HEAP = 0
# levels. Currently, the recognized values for DEBUG are:
#
# 0 == NDEBUG: Disables assert() and other runtime diagnostics.
# 1 == SQLITE_ENABLE_API_ARMOR: extra attempts to detect misuse of the API.
# 2 == Disables NDEBUG and all optimizations and then enables PDBs.
# 3 == SQLITE_DEBUG: Enables various diagnostics messages and code.
# 4 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
# 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.
#
!IFNDEF DEBUG
DEBUG = 0
@@ -249,11 +231,7 @@ 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.
@@ -274,13 +252,7 @@ NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
# will run on the target platform. (BCC and TCC are usually the
# same unless your are cross-compiling.)
#
!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
TCC = $(CC) -W3 -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
@@ -308,7 +280,7 @@ RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP
# MSVC runtime library.
#
!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0
!IF $(DEBUG)>1
!IF $(DEBUG)>0
TCC = $(TCC) -MDd
BCC = $(BCC) -MDd
!ELSE
@@ -316,7 +288,7 @@ TCC = $(TCC) -MD
BCC = $(BCC) -MD
!ENDIF
!ELSE
!IF $(DEBUG)>1
!IF $(DEBUG)>0
TCC = $(TCC) -MTd
BCC = $(BCC) -MTd
!ELSE
@@ -341,7 +313,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)>1
!IF $(DEBUG)>0
MKSQLITE3C_ARGS = --linemacros
!ELSE
MKSQLITE3C_ARGS =
@@ -357,22 +329,17 @@ BCC = $(BCC) -DNDEBUG
RCC = $(RCC) -DNDEBUG
!ENDIF
!IF $(DEBUG)>0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR
!ENDIF
!IF $(DEBUG)>2
!IF $(DEBUG)>1
TCC = $(TCC) -DSQLITE_DEBUG
RCC = $(RCC) -DSQLITE_DEBUG
!ENDIF
!IF $(DEBUG)>4
!IF $(DEBUG)>3
TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1
!ENDIF
!IF $(DEBUG)>5
!IF $(DEBUG)>4
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
!ENDIF
@@ -404,7 +371,7 @@ RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
# Validate the heap on every call into the native Win32 heap subsystem?
#
!IF $(DEBUG)>3
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
!ENDIF
@@ -515,7 +482,7 @@ RCC = $(RCC) $(OPTS)
# If compiling for debugging, add some defines.
#
!IF $(DEBUG)>1
!IF $(DEBUG)>0
TCC = $(TCC) -D_DEBUG
BCC = $(BCC) -D_DEBUG
RCC = $(RCC) -D_DEBUG
@@ -524,7 +491,7 @@ RCC = $(RCC) -D_DEBUG
# If optimizations are enabled or disabled (either implicitly or
# explicitly), add the necessary flags.
#
!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0
!IF $(DEBUG)>0 || $(OPTIMIZATIONS)==0
TCC = $(TCC) -Od
BCC = $(BCC) -Od
!ELSEIF $(OPTIMIZATIONS)>=3
@@ -540,7 +507,7 @@ BCC = $(BCC) -O1
# If symbols are enabled (or compiling for debugging), enable PDBs.
#
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
TCC = $(TCC) -Zi
BCC = $(BCC) -Zi
!ENDIF
@@ -625,7 +592,7 @@ LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
# If either debugging or symbols are enabled, enable PDBs.
#
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
LDFLAGS = /DEBUG
!ENDIF
@@ -733,7 +700,6 @@ 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 \
@@ -966,7 +932,6 @@ 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 \
@@ -1018,7 +983,8 @@ 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
@@ -1068,8 +1034,7 @@ lempar.c: $(TOP)\src\lempar.c
copy $(TOP)\src\lempar.c .
lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) $(NO_WARN) -Daccess=_access \
-Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
# Rules to build individual *.lo files from generated *.c files. This
# applies to:
@@ -1340,8 +1305,7 @@ sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) \
$(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
$(BCC) -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
@@ -1422,8 +1386,7 @@ 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=""
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) libsqlite3.lib
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
-2
View File
@@ -253,7 +253,6 @@ 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 \
@@ -415,7 +414,6 @@ 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 \
+12 -12
View File
@@ -53,10 +53,10 @@ 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.
SQLite does not require Tcl 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
@@ -95,14 +95,14 @@ 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.
Tcl script 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
-6
View File
@@ -27,9 +27,6 @@
/* 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
@@ -51,9 +48,6 @@
/* 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
Vendored
+91 -21
View File
@@ -868,6 +868,7 @@ RELEASE
VERSION_NUMBER
BUILD_CC
SQLITE_THREADSAFE
XTHREADCONNECT
ALLOWRELEASE
TEMP_STORE
BUILD_EXEEXT
@@ -905,7 +906,9 @@ enable_fast_install
with_gnu_ld
enable_libtool_lock
enable_largefile
with_hints
enable_threadsafe
enable_cross_thread_connections
enable_releasemode
enable_tempstore
enable_tcl
@@ -1559,7 +1562,9 @@ Optional Features:
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
--disable-largefile omit support for large files
--disable-threadsafe Disable mutexing
--enable-threadsafe Support threadsafe operation
--enable-cross-thread-connections
Allow connection sharing across threads
--enable-releasemode Support libtool link to release mode
--enable-tempstore Use an in-ram database for temporary tables
(never,no,yes,always)
@@ -1568,8 +1573,7 @@ Optional Features:
--enable-debug enable debugging & verbose explain
--disable-amalgamation Disable the amalgamation and instead build all files
separately
--disable-load-extension
Disable loading of external extensions
--enable-load-extension Enable loading of external extensions
--enable-gcov Enable coverage testing using gcov
Optional Packages:
@@ -1578,6 +1582,7 @@ Optional Packages:
--with-pic try to use only PIC/non-PIC objects [default=use
both]
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-hints=FILE Read configuration options from FILE
--with-tcl=DIR directory containing tcl configuration
(tclConfig.sh)
--with-readline-lib specify readline library
@@ -2053,6 +2058,9 @@ please regen with autoconf" >&2;}
{ (exit 1); exit 1; }; }
fi
# The following RCS revision string applies to configure.in
# $Revision: 1.56 $
#########
# Programs needed
#
@@ -3724,13 +3732,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3727: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3735: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3730: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3738: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3733: output\"" >&5)
(eval echo "\"\$as_me:3741: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -4952,7 +4960,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 4955 "configure"' > conftest.$ac_ext
echo '#line 4963 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6821,11 +6829,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:6824: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6832: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6828: \$? = $ac_status" >&5
echo "$as_me:6836: \$? = $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.
@@ -7160,11 +7168,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:7163: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7171: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7167: \$? = $ac_status" >&5
echo "$as_me:7175: \$? = $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.
@@ -7265,11 +7273,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:7268: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7276: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7272: \$? = $ac_status" >&5
echo "$as_me:7280: \$? = $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
@@ -7320,11 +7328,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:7323: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7331: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7327: \$? = $ac_status" >&5
echo "$as_me:7335: \$? = $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
@@ -10133,7 +10141,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 10136 "configure"
#line 10144 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10229,7 +10237,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 10232 "configure"
#line 10240 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12138,9 +12146,7 @@ done
for ac_func in fdatasync gmtime_r isnan localtime_r localtime_s malloc_usabel_size strchrnul usleep utime
for ac_func in usleep fdatasync localtime_r gmtime_r localtime_s utime malloc_usable_size
do
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -12336,6 +12342,45 @@ VERSION_NUMBER=`cat $srcdir/VERSION \
$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:$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.
@@ -12507,6 +12552,31 @@ fi
fi
##########
# Do we want to allow a connection created in one thread to be used
# in another thread. This does not work on many Linux systems (ex: RedHat 9)
# due to bugs in the threading implementations. This is thus off by default.
#
# Check whether --enable-cross-thread-connections was given.
if test "${enable_cross_thread_connections+set}" = set; then
enableval=$enable_cross_thread_connections;
else
enable_xthreadconnect=no
fi
{ $as_echo "$as_me:$LINENO: checking whether to allow connections to be shared across threads" >&5
$as_echo_n "checking whether to allow connections to be shared across threads... " >&6; }
if test "$enable_xthreadconnect" = "no"; then
XTHREADCONNECT=''
{ $as_echo "$as_me:$LINENO: result: no" >&5
$as_echo "no" >&6; }
else
XTHREADCONNECT='-DSQLITE_ALLOW_XTHREAD_CONNECT=1'
{ $as_echo "$as_me:$LINENO: result: yes" >&5
$as_echo "yes" >&6; }
fi
##########
# Do we want to support release
#
@@ -13357,7 +13427,7 @@ fi
if test "${enable_load_extension+set}" = set; then
enableval=$enable_load_extension; use_loadextension=$enableval
else
use_loadextension=yes
use_loadextension=no
fi
if test "${use_loadextension}" = "yes" ; then
+75 -5
View File
@@ -69,6 +69,19 @@
# 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
@@ -85,6 +98,11 @@ 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
#
@@ -109,7 +127,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([fdatasync gmtime_r isnan localtime_r localtime_s malloc_usabel_size strchrnul usleep utime])
AC_CHECK_FUNCS([usleep fdatasync localtime_r gmtime_r localtime_s utime malloc_usable_size])
#########
# By default, we use the amalgamation (this may be changed below...)
@@ -162,6 +180,41 @@ 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.
@@ -183,7 +236,7 @@ AC_SUBST(BUILD_CC)
# Do we want to support multithreaded use of sqlite
#
AC_ARG_ENABLE(threadsafe,
AC_HELP_STRING([--disable-threadsafe],[Disable mutexing]),,enable_threadsafe=yes)
AC_HELP_STRING([--enable-threadsafe],[Support threadsafe operation]),,enable_threadsafe=yes)
AC_MSG_CHECKING([whether to support threadsafe operation])
if test "$enable_threadsafe" = "no"; then
SQLITE_THREADSAFE=0
@@ -198,6 +251,23 @@ if test "$SQLITE_THREADSAFE" = "1"; then
AC_SEARCH_LIBS(pthread_create, pthread)
fi
##########
# Do we want to allow a connection created in one thread to be used
# in another thread. This does not work on many Linux systems (ex: RedHat 9)
# due to bugs in the threading implementations. This is thus off by default.
#
AC_ARG_ENABLE(cross-thread-connections,
AC_HELP_STRING([--enable-cross-thread-connections],[Allow connection sharing across threads]),,enable_xthreadconnect=no)
AC_MSG_CHECKING([whether to allow connections to be shared across threads])
if test "$enable_xthreadconnect" = "no"; then
XTHREADCONNECT=''
AC_MSG_RESULT([no])
else
XTHREADCONNECT='-DSQLITE_ALLOW_XTHREAD_CONNECT=1'
AC_MSG_RESULT([yes])
fi
AC_SUBST(XTHREADCONNECT)
##########
# Do we want to support release
#
@@ -535,9 +605,9 @@ AC_SUBST(USE_AMALGAMATION)
#########
# See whether we should allow loadable extensions
AC_ARG_ENABLE(load-extension, AC_HELP_STRING([--disable-load-extension],
[Disable loading of external extensions]),
[use_loadextension=$enableval],[use_loadextension=yes])
AC_ARG_ENABLE(load-extension, AC_HELP_STRING([--enable-load-extension],
[Enable loading of external extensions]),
[use_loadextension=$enableval],[use_loadextension=no])
if test "${use_loadextension}" = "yes" ; then
OPT_FEATURE_FLAGS=""
AC_SEARCH_LIBS(dlopen, dl)
+3 -3
View File
@@ -1853,7 +1853,7 @@ static int fts3SelectLeaf(
sqlite3_int64 *piLeaf, /* Selected leaf node */
sqlite3_int64 *piLeaf2 /* Selected leaf node */
){
int rc = SQLITE_OK; /* Return code */
int rc; /* 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 = 0; /* Size of zBlob in bytes */
int nBlob; /* 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 = SQLITE_OK;
int rc;
char *zSql; /* SQL statement used to access %_content */
int eSearch;
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
+1 -1
View File
@@ -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 = 0;
Fts3tokTable *pTab;
const sqlite3_tokenizer_module *pMod = 0;
sqlite3_tokenizer *pTok = 0;
int rc;
+2 -2
View File
@@ -3082,8 +3082,8 @@ static int fts3PromoteSegments(
if( bOk ){
int iIdx = 0;
sqlite3_stmt *pUpdate1 = 0;
sqlite3_stmt *pUpdate2 = 0;
sqlite3_stmt *pUpdate1;
sqlite3_stmt *pUpdate2;
if( rc==SQLITE_OK ){
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0);
+1 -1
View File
@@ -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 = 0;
amatch_avl *pBalance;
/* assert( amatchAvlSearch(*ppHead, pOld->zKey)==pOld ); */
ppParent = amatchAvlFromPtr(pOld, ppHead);
if( pOld->pBefore==0 && pOld->pAfter==0 ){
+1 -2
View File
@@ -342,8 +342,7 @@ static int fuzzerLoadOneRule(
rc = SQLITE_NOMEM;
}else{
memset(pRule, 0, sizeof(*pRule));
pRule->zFrom = pRule->zTo;
pRule->zFrom += nTo + 1;
pRule->zFrom = &pRule->zTo[nTo+1];
pRule->nFrom = nFrom;
memcpy(pRule->zFrom, zFrom, nFrom+1);
memcpy(pRule->zTo, zTo, nTo+1);
+1 -1
View File
@@ -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 = 0, cB; /* Current character of zA and zB */
char cA, 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 */
+1 -3
View File
@@ -1182,7 +1182,7 @@ static RtreeSearchPoint *rtreeEnqueue(
pNew = pCur->aPoint + i;
pNew->rScore = rScore;
pNew->iLevel = iLevel;
assert( iLevel<=RTREE_MAX_DEPTH );
assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH );
while( i>0 ){
RtreeSearchPoint *pParent;
j = (i-1)/2;
@@ -2806,8 +2806,6 @@ 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:
**
+3 -11
View File
@@ -112,7 +112,6 @@ 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 \
@@ -346,7 +345,6 @@ 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 \
@@ -627,15 +625,9 @@ 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_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)
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)
threadtest: threadtest3$(EXE)
./threadtest3$(EXE)
+104 -113
View File
@@ -1,11 +1,11 @@
C Fix\sharmless\scompiler\swarning\sin\san\sassert()\sstatement.
D 2015-01-12T20:25:33.360
C Add\scode\sto\scheck\sthe\svalidity\sof\sCollSeq\sobjects\sduring\sruntime.\s\sThis\scode\nwas\snot\sable\sto\sdetect\sanomalies\ssuch\sas\scame\sup\sas\sa\sresult\sof\nticket\s[e4a18565a36884b00edf66541f38c693827968ab]\sso\sit\sis\sput\sinto\sa\sbranch\nfor\shistorical\sreference,\swith\sthe\sintent\sof\sleaving\sit\sout\sof\strunk.
D 2014-12-05T14:36:15.903
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 9efcdb5c6025caea362cdfc38817451170fc6344
F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 4c057774e6138b9023fc16ec05639ddd3329b152
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
F Makefile.msc 10720782f88648bf2b5dcedf4c1524b067d43e47
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
F VERSION d846487aff892625eb8e75960234e7285f0462fe
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
@@ -36,10 +36,10 @@ 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 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure f0438487966ab02dd0357c4ad27f1082e70a4b34 x
F configure.ac 0c94d28b0a839fd0f35ccebded2ea4aed4424d65
F configure 4343c810cc772571210af75d1a8f7c2eb711d75a x
F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
@@ -78,7 +78,7 @@ 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 5c464816508e40feb3c61f1f5566551764698fc8
F ext/fts3/fts3.c 8b6cceb3e0be22da26d83a3cec0e0e337e6b8ec6
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 53d4eca1fb23eab00681fb028fb82eb5705c1e21
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
@@ -90,13 +90,13 @@ F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
F ext/fts3/fts3_snippet.c 51beb5c1498176fd9caccaf1c75b55cb803a985a
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
F ext/fts3/fts3_tokenize_vtab.c becc661223db7898b213f9e8a23d75bac02408c9
F ext/fts3/fts3_tokenize_vtab.c 011170fe9eba5ff062f1a31d3188e00267716706
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 9b3a32cbecf40a1f41cb08c00df8c066c23c7a25
F ext/fts3/fts3_write.c 8260388626516a7005d06a9dce94f9e55c6c2a41
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 3986531f2fc0ceca0c89c31ec7d0589b6adb19d6
@@ -106,25 +106,25 @@ 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 17ba78dc9b33601a40d2a7bc54c748b6f3eb7176
F ext/misc/amatch.c 678056a4bfcd83c4e82dea81d37543cd1d6dbee1
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 e3e18f47252c151b5553d7e806f38e757d37c4cc
F ext/misc/fuzzer.c 136533c53cfce0957f0b48fa11dba27e21c5c01d
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/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 25810dda37fc904b0772a13efd8ca072fb09e355
F ext/misc/spellfix.c 56739fab8c2ed6a9e2dac5592a88d281a999c43b
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 b61e9eab7229a443d0d2029da7624299e19301a2
F ext/rtree/rtree.c 57bec53e1a677ab74217fe1f20a58c3a47261d6b
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 541bbcab74613907fea08b2ecdcdd5b7aa724cc9
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -152,7 +152,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 1d0cf88b6e89249608677215ad36e4f8a231accc
F main.mk 084976077a4aa3bd985154b5423e7aed88e4a2e9
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -160,33 +160,33 @@ F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test cce8e306d8596d5a2e497e27112dae1f6e5e3538
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
F mptest/mptest.c 24c5f72415df2eab7088ef8c9f99f163aed590c8
F mptest/mptest.c 499a74af4be293b7c1c7c3d40f332b67227dd739
F mptest/multiwrite01.test 499ad0310da8dff8e8f98d2e272fc2a8aa741b2e
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
F src/analyze.c 91540f835163d5369ccbae78e2e6c74d0dd53c1d
F src/attach.c 7f6b3fafa2290b407e4a94dcf1afda7ec0fe394b
F src/analyze.c f7d774356ba5a14e7ad4fb637681af16875ad88f
F src/attach.c f4e94df2d1826feda65eb0939f7f6f5f923a0ad9
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
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/btree.c 44b58cd798a32579816ce274e415de262df9843d
F src/btree.h e31a3a3ebdedb1caf9bda3ad5dbab3db9b780f6e
F src/btreeInt.h 3363e18fd76f69a27a870b25221b2345b3fd4d21
F src/build.c 67bb05b1077e0cdaccb2e36bfcbe7a5df9ed31e8
F src/callback.c 759c9aff944f72fd7fb810594d95af1092a8433a
F src/complete.c c4ba6e0626bb94bc77a0861735f3382fcf7cc818
F src/ctime.c df19848891c8a553c80e6f5a035e768280952d1a
F src/date.c 93594514aae68de117ca4a2a0d6cc63eddf26744
F src/delete.c 0750b1eb4d96cd3fb2c798599a3a7c85e92f1417
F src/expr.c 00da3072f362b06f39ce4052baa1d4ce2bb36d1c
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12
F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7
F src/func.c 6d3c4ebd72aa7923ce9b110a7dc15f9b8c548430
F src/global.c 12561d70a1b25f67b21154622bb1723426724f75
F src/global.c 6ded36dda9466fc1c9a3c5492ded81d79bf3977d
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@@ -194,66 +194,65 @@ F src/insert.c 5b9243a33726008cc4132897d2be371db12a13be
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
F src/main.c 05bf368c934cc73d02906030846eb4d1818c10f7
F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994
F src/main.c fa9f0e511a64caf66b8e7bb835c55172e7d61527
F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
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 551e2f25f0fa0ee8fd7a43f50fc3d8be00e95dde
F src/mutex_w32.c df48fe07562a45c5c927c45b8d5873a27f98bbb0
F src/mutex_w32.c 06bfff9a3a83b53389a51a967643db3967032e1e
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 aefeaf915aaef9f81aa2645e0d5d06fa1bd83beb
F src/os_win.c 91d3d08e33ec0258d180d4c8255492f47d15e007
F src/os_unix.c fb587121840f690101336879adfa6d0b2cd0e8c7
F src/os_win.c a9e500dd963fb1f67d7860e58b5772abe6123862
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/pager.c 7a5c5bc0e29b9b16834f5558a9d5d22bbae59a08
F src/pager.h d1eee3c3f741be247ce6d82752a178515fc8578b
F src/parse.y 5dfead8aed90cb0c7c1115898ee2266804daff45
F src/pcache.c ace1b67632deeaa84859b4c16c27711dfb7db3d4
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/pcache1.c facbdd3ecc09c8f750089d941305694301328e98
F src/pragma.c d54cdd40b63d608f2d95b7482c710690e3593a73
F src/prepare.c b7b7bf020bd4c962f7c8aed5a3c542c7dfe9f9c7
F src/printf.c 9e75a6a0b55bf61cfff7d7e19d89834a1b938236
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c e4c38c75e36f28aed80a69a725d888751bfd53df
F src/shell.c 5b8e786a7c8eec87fa3f2ea615b337d2d99e284c
F src/sqlite.h.in 9dfc99d6533d36d6a549c4f3f01cacc8be956ada
F src/select.c f377fb8a5c73c10678ea74f3400f7913943e3d75
F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf
F src/sqlite.h.in 6ec654324cb490ea3d8a7be28b8c7d37fe4ad282
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h eaf210295b551d4e40e622aec1b2261c0b28f844
F src/sqliteInt.h ef42a0515a846ab2a670bda705be494d7acc2535
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
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/table.c f142bba7903e93ca8d113a5b8877a108ad1a27dc
F src/tclsqlite.c 0a874655dd39a9875e39c5d3c464db662171d228
F src/test1.c c24d7f67252348d756773a6dbe23a61b4552f709
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
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 df8dd4c99c1dd2225cb2a6f334299cddc5dcf1f1
F src/test8.c 54ccd7b1df5062f0ecbf50a8f7b618f8b1f13b20
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 e7b2e1634324d746aa5e1c7e0929470e8be27953
F src/test_config.c 035c17a173937d019b8dfc1d524f9d3fc8123504
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
@@ -262,16 +261,16 @@ F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
F src/test_malloc.c b9495384e74923aefde8311de974bf9b0f5ba570
F src/test_multiplex.c 72c0ad1e97af3d6d19975bbd81813072b40c7290
F src/test_malloc.c ba34143f941a9d74b30bbffc8818389bb73a1ca2
F src/test_multiplex.c caadb62cc777268b4f8fb94d5b27b80156c8f7c0
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 180813f43683be5725458fc1ff13ac455d8e722d
F src/test_quota.c 65f6348fec0f2b3020c907247fb47556b214abb9
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c fdd8d29ca5165c7857987a2ba263fac5c69e231f
F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
@@ -282,30 +281,30 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
F src/test_vfs.c 8ee7be45fe773a150b4015ef957da960179ee43a
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 2fb3ea4d70d5acf68b539c2489b4adace61cc01b
F src/tokenize.c e00458c9938072b0ea711c850b8dcf4ddcb5fe18
F src/threads.c 6de09362b657f19ba83e5fa521ee715787ce9fee
F src/tokenize.c cc9016e5007fc5e76789079616d2f26741bcc689
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
F src/util.c 3b627daa45c7308c1e36e3dbaa3f9ce7e5c7fa73
F src/vacuum.c 9b30ec729337dd012ed88d4c292922c8ef9cf00c
F src/vdbe.c ddfc977981cd6324668aa6b114045eb1c677421a
F src/vdbe.c 1a9e671c9cfc259e4d2affc71f7df4a4c00a842c
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78
F src/vdbeapi.c 4bc511a46b9839392ae0e90844a71dc96d9dbd71
F src/vdbeaux.c 07ef87c6d4b5abdf13ff33babb10205702fdab0a
F src/vdbeapi.c 07acb615d1e4170e71fc1b0d087f3c53a1ad8e83
F src/vdbeaux.c 7e0a097ac7cf716300128f18147ef9af7c9d1130
F src/vdbeblob.c 4af4bfb71f6df7778397b4a0ebc1879793276778
F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f
F src/vdbesort.c 6d64c5448b64851b99931ede980addc3af70d5e2
F src/vdbesort.c 42c166f7ca78cb643c7f4e4bdfa83c59d363d1a6
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9
F src/wal.c 85353539f2d9d0c91ebd057c32525b1e1aa3335e
F src/wal.c 847692349eb6e1fb8543dbc97e69ddbfa4cc7ea7
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c d46de821bc604a4fd36fa3928c086950e91aafb1
F src/where.c d67fe69dd1bb32ad3d488a8c5bc803a29814f357
F src/whereInt.h d3633e9b592103241b74b0ec76185f3e5b8b62e0
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -367,7 +366,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/bigsort.test 835478d0ce83bd1e5b05c90571dedd9871a09196
F test/bind.test 3c7b320969000c441a70952b0b15938fbb66237c
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
F test/bitvec.test 75894a880520164d73b1305c1c3f96882615e142
@@ -405,7 +404,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 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
F test/colmeta.test 087c42997754b8c648819832241daf724f813322
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
F test/conflict.test 841bcf7cabbfca39c577eb8411ea8601843b46a8
F test/conflict2.test 0d3af4fb534fa1bd020c79960bb56e4d52655f09
@@ -479,9 +478,6 @@ F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
F test/e_wal.test 0967f0b8f1dfda871dc7b9b5574198f1f4f7d69a
F test/e_walauto.test d2dfc6681aade1f1306a8a336f5a258d8b62becd
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
@@ -502,10 +498,9 @@ F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b
F test/fkey2.test 1db212cda86b0d3ce72714001f7b6381c321341c
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 488601fbda8350619b3029487e56830447056fd2
F test/fkey5.test 8a1fde4e7721ae00b05b3178888833726ca2df8d
F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48
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
@@ -620,7 +615,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 b34fe575aa10292135421ff4bf315de4cde7824a
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
@@ -700,7 +695,7 @@ 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 16131264ea0c2b93b95201f0c92958e85f2ba11a
F test/main.test 39c4bb8a157f57298ed1659d6df89d9f35aaf2c8
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 96939d2d1a6f39667bbebe5bc27c6525f2ab614e
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
@@ -728,7 +723,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test fcb5297b321b562084fc79d64d5a12a1cd2b639b
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 690d142525a7d31efb638b0d232e25fac3afeb1a
F test/memsubsys1.test bf270964ab83bc2da5927960f78304a866fb9a9d
F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9
F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
@@ -756,7 +751,7 @@ F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
F test/nolock.test 0540dd96f39b8876e3ffdd8814fad0ea425efeee
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify2.test ce23eb522c9e1fff6443f96376fe67872202061c
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
F test/null.test a8b09b8ed87852742343b33441a9240022108993
@@ -769,7 +764,7 @@ F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@@ -782,11 +777,10 @@ F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test f9cc1dd987986c9d4949211c7a4ed55ec9aecba1
F test/pragma.test aa16dedfe01c02c8895169012f7dfde9c163f0d5
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
F test/permutations.test 4e12d43f4639ea8a0e366d9c64e0009afe2eb544
F test/pragma.test 49ac8a73c0daa574824538fed28727d1259fe735
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/printf2.test b4acd4bf8734243257f01ddefa17c4fb090acc8a
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
@@ -802,7 +796,8 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl 13f401c10dd4fe1a2fb811ae6ed27fd7d1300d3c
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
F test/releasetest.tcl a4279c890698584feb2ffc86735857a4e4474180
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
@@ -841,7 +836,6 @@ 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
@@ -855,11 +849,11 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test cdeb849acc2c37aada70d084564b0cc0a2c7df08
F test/shell1.test ab6025d941f9c84c5b83412c6b4d8b57f78dfa3a
F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
F test/shell5.test 81aba4793fa7441b1300daae1aec4f7e4b5741c1
F test/shell5.test 15a419cc1df21c892ed64f5596ae7a501f2816f2
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
@@ -871,12 +865,12 @@ F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
F test/sort.test 3f492e5b7be1d3f756728d2ff6edf4f6091e84cb
F test/sort2.test 37afbc03f5559f2eb0f18940b55d38dfbb5172ac
F test/sort.test c4400e7533748f6bd7413851ff148645e82b9e2d
F test/sort2.test 84a92eebf697feee9c6697746918c7d67373eea1
F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2
F test/sort4.test d5e8903194ae551551349ce25dc8d0b40ca2b9c3
F test/sort4.test 6c37d85f7cd28d50cce222fcab84ccd771e105cb
F test/sort5.test a448240a42b49239edc00f85d6d7ac7a1b261e1f
F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66
F test/sortfault.test b8e35177f97438b930ee87c9419ca2599e8073e1
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
F test/speed1p.test b180e98609c7677382cf618c0ec9b69f789033a8
@@ -916,8 +910,7 @@ 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 9ab4b168681c3a6f70f6c833ba08e0d48dd4af9b
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
F test/threadtest3.c 0ed13e09690f6204d7455fac3b0e8ece490f6eef
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2
@@ -1080,11 +1073,7 @@ 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 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/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
@@ -1125,7 +1114,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 11b8658dd4d5448f4604124bebd9b68be5bc3e66
F test/wal5.test 174cc1512e304a7dfa28ac30527e28ea02fc37df
F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e
F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
@@ -1180,7 +1169,6 @@ F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test 1081aabf60a1e1123b7f9a8f6ae19954351843b0
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
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
@@ -1194,18 +1182,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 1864c4fe4a72b1bb28f1792b60504804fe82c5d2
F tool/lemon.c 3ff0fec22f92dfb54e62eeb48772eddffdbeb0d6
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh 5dc5010e2e748a9e1bba67baca5956a2c2deda7b
F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 07a5124cf2dbafa1b375eefcf8ac4227028b0f8b
F tool/mkpragmatab.tcl cce51d8f60c7f145d8fccabe6b5dfdedf31c5f5c
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 9ef48e1748dce7b844f67e2450ff9dfeb0fb4ab5
F tool/mksqlite3c.tcl cfde806851c413db7689b9cb74a4eeb92539c601
F tool/mksqlite3c-noext.tcl 88a1e3b0c769773fb7a9ebb363ffc603a4ac21d8
F tool/mksqlite3c.tcl e72c0c97fe1a105fa9616483e652949be2199fe6
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mksqlite3internalh.tcl b6514145a7d5321b47e64e19b8116cc44f973eb1
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
@@ -1236,7 +1224,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P de30d5b053b8e004418c81945d626cfad315d6ba
R 79278f99b3f4d9aaeb5b2b5be8f618ce
U mistachkin
Z 02f72f6c4a80a1aa451e44b57450d7f3
P 71f589e3f82a07513425e212072f32748c0732d4
R 02b8ea23886487ef9860b5ee40d238ab
T *branch * collseq-checking
T *sym-collseq-checking *
T -sym-fix-stale-keyinfo-cache *
U drh
Z 74adfe1c6f95aa3cd0aa6e2d3a771e07
+1 -1
View File
@@ -1 +1 @@
bdbeed01ddc60a4ab322621fc118cc4767660fd3
68b23c3d41ce9303f42251d0c199181312e148f9
+1 -1
View File
@@ -1395,7 +1395,7 @@ int main(int argc, char **argv){
maybeClose(g.pLog);
maybeClose(g.pErrLog);
if( iClient==0 ){
printf("Summary: %d errors out of %d tests\n", g.nError, g.nTest);
printf("Summary: %d errors in %d tests\n", g.nError, g.nTest);
}
return g.nError>0;
}
+2 -2
View File
@@ -448,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 = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565;
/* Set up the Stat4Accum.a[] and aBest[] arrays */
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
@@ -1596,7 +1596,7 @@ static void initAvgEq(Index *pIdx){
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 ){
if( pIdx->aiRowEst==0 || pIdx->aiRowEst[iCol+1]==0 ){
nRow = pFinal->anLt[iCol];
nDist100 = (i64)100 * pFinal->anDLt[iCol];
nSample--;
-2
View File
@@ -150,7 +150,6 @@ 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,
@@ -158,7 +157,6 @@ 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);
+9 -31
View File
@@ -3550,7 +3550,6 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
sqlite3BtreeLeave(p);
return rc;
}
p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
pBt->inTransaction = TRANS_READ;
btreeClearHasContent(pBt);
}
@@ -3914,7 +3913,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
releasePage(pCur->apPage[i]);
}
unlockBtreeIfUnused(pBt);
sqlite3_free(pCur->aOverflow);
sqlite3DbFree(pBtree->db, pCur->aOverflow);
/* sqlite3_free(pCur); */
sqlite3BtreeLeave(pBtree);
}
@@ -4209,7 +4208,6 @@ static int accessPayload(
offset -= pCur->info.nLocal;
}
if( rc==SQLITE_OK && amt>0 ){
const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
Pgno nextPage;
@@ -4227,8 +4225,8 @@ static int accessPayload(
if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
if( nOvfl>pCur->nOvflAlloc ){
Pgno *aNew = (Pgno*)sqlite3Realloc(
pCur->aOverflow, nOvfl*2*sizeof(Pgno)
Pgno *aNew = (Pgno*)sqlite3DbRealloc(
pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno)
);
if( aNew==0 ){
rc = SQLITE_NOMEM;
@@ -4275,7 +4273,6 @@ static int accessPayload(
*/
assert( eOp!=2 );
assert( pCur->curFlags & BTCF_ValidOvfl );
assert( pCur->pBtree->db==pBt->db );
if( pCur->aOverflow[iIdx+1] ){
nextPage = pCur->aOverflow[iIdx+1];
}else{
@@ -6788,7 +6785,7 @@ static int balance_nonroot(
/* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer
** that is more than 6 times the database page size. */
assert( szScratch<=6*(int)pBt->pageSize );
assert( szScratch<=6*pBt->pageSize );
apCell = sqlite3ScratchMalloc( szScratch );
if( apCell==0 ){
rc = SQLITE_NOMEM;
@@ -6862,11 +6859,7 @@ static int balance_nonroot(
}else{
assert( leafCorrection==4 );
if( szCell[nCell]<4 ){
/* Do not allow any cells smaller than 4 bytes. If a smaller cell
** does exist, pad it with 0x00 bytes. */
assert( szCell[nCell]==3 );
assert( apCell[nCell]==&aSpace1[iSpace1-3] );
aSpace1[iSpace1++] = 0x00;
/* Do not allow any cells smaller than 4 bytes. */
szCell[nCell] = 4;
}
}
@@ -7101,11 +7094,7 @@ static int balance_nonroot(
** if sibling page iOld had the same page number as pNew, and if
** pCell really was a part of sibling page iOld (not a divider or
** overflow cell), we can skip updating the pointer map entries. */
if( iOld>=nNew
|| pNew->pgno!=aPgno[iOld]
|| pCell<aOld
|| pCell>=&aOld[usableSize]
){
if( pNew->pgno!=aPgno[iOld] || pCell<aOld || pCell>=&aOld[usableSize] ){
if( !leafCorrection ){
ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
}
@@ -8178,13 +8167,6 @@ int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
** The schema layer numbers meta values differently. At the schema
** layer (and the SetCookie and ReadCookie opcodes) the number of
** free pages is not visible. So Cookie[0] is the same as Meta[1].
**
** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead
** of reading the value out of the header, it instead loads the "DataVersion"
** from the pager. The BTREE_DATA_VERSION value is not actually stored in the
** database file. It is a number computed by the pager. But its access
** pattern is the same as header meta values, and so it is convenient to
** read it from this routine.
*/
void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
BtShared *pBt = p->pBt;
@@ -8195,11 +8177,7 @@ void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
assert( pBt->pPage1 );
assert( idx>=0 && idx<=15 );
if( idx==BTREE_DATA_VERSION ){
*pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
}else{
*pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
}
*pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
/* If auto-vacuum is disabled in this build and this is an auto-vacuum
** database, mark the database as read-only. */
@@ -8290,7 +8268,7 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
if( pCur->iPage==0 ){
/* All pages of the b-tree have been visited. Return successfully. */
*pnEntry = nEntry;
return moveToRoot(pCur);
return SQLITE_OK;
}
moveToParent(pCur);
}while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
@@ -9146,4 +9124,4 @@ int sqlite3BtreeIsReadonly(Btree *p){
/*
** Return the size of the header added to each page by this module.
*/
int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); }
+1 -7
View File
@@ -19,7 +19,7 @@
/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/
#define SQLITE_N_BTREE_META 16
#define SQLITE_N_BTREE_META 10
/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
@@ -134,11 +134,6 @@ 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
@@ -149,7 +144,6 @@ 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
-1
View File
@@ -351,7 +351,6 @@ 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
+30 -33
View File
@@ -435,6 +435,7 @@ 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);
@@ -1713,19 +1714,6 @@ 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 );
@@ -4202,31 +4190,40 @@ 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;
if( pIdx->uniqNotNull ){
pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
}else{
pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
#ifndef SQLITE_OMIT_SHARED_CACHE
if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){
sqlite3KeyInfoUnref(pIdx->pKeyInfo);
pIdx->pKeyInfo = 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];
#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( pParse->nErr ){
sqlite3KeyInfoUnref(pKey);
pKey = 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( pParse->nErr ){
sqlite3KeyInfoUnref(pKey);
}else{
pIdx->pKeyInfo = pKey;
}
}
}
return pKey;
return sqlite3KeyInfoRef(pIdx->pKeyInfo);
}
#ifndef SQLITE_OMIT_CTE
+30 -2
View File
@@ -102,7 +102,7 @@ CollSeq *sqlite3GetCollSeq(
if( p && !p->xCmp && synthCollSeq(db, p) ){
p = 0;
}
assert( !p || p->xCmp );
assert( p==0 || (sqlite3ValidCollSeq(p) && p->xCmp!=0) );
if( p==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
}
@@ -186,6 +186,31 @@ static CollSeq *findCollSeqEntry(
return pColl;
}
#ifdef SQLITE_DEBUG
/*
** The following routine does sanity checking on a CollSeq object and
** returns 1 if everything looks ok and 0 if the CollSeq object appears
** to be corrupt. This routine is used only inside of assert() statements.
*/
int sqlite3ValidCollSeq(const CollSeq *p){
/* The CollSeq must be one of a triple and the zName field must
** point to the first byte after that triple
*/
int n = (int)(p->zName - (char*)p)/sizeof(CollSeq);
if( n<=0 || n>3 ) return 0;
/* Check for valid enc values */
if( p->enc==SQLITE_UTF8 ) return 1;
if( p->enc==SQLITE_UTF16LE ) return 1;
if( p->enc==SQLITE_UTF16BE ) return 1;
if( p->enc==(SQLITE_UTF16LE|SQLITE_UTF16_ALIGNED) ) return 1;
if( p->enc==(SQLITE_UTF16BE|SQLITE_UTF16_ALIGNED) ) return 1;
/* Otherwise, malformed */
return 0;
}
#endif /* SQLITE_DEBUG */
/*
** Parameter zName points to a UTF-8 encoded string nName bytes long.
** Return the CollSeq* pointer for the collation sequence named zName
@@ -215,7 +240,10 @@ CollSeq *sqlite3FindCollSeq(
}
assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
if( pColl ) pColl += enc-1;
if( pColl ){
pColl += enc-1;
assert( sqlite3ValidCollSeq(pColl) );
}
return pColl;
}
+7 -7
View File
@@ -105,6 +105,13 @@ int sqlite3_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
#ifdef SQLITE_ENABLE_API_ARMOR
if( zSql==0 ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
#ifndef SQLITE_OMIT_TRIGGER
/* A complex statement machine used to detect the end of a CREATE TRIGGER
** statement. This is the normal case.
@@ -134,13 +141,6 @@ 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 */
+109 -109
View File
@@ -33,91 +33,91 @@ static const char * const azCompileOpt[] = {
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
#if SQLITE_32BIT_ROWID
#ifdef SQLITE_32BIT_ROWID
"32BIT_ROWID",
#endif
#if SQLITE_4_BYTE_ALIGNED_MALLOC
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
"4_BYTE_ALIGNED_MALLOC",
#endif
#if SQLITE_CASE_SENSITIVE_LIKE
#ifdef SQLITE_CASE_SENSITIVE_LIKE
"CASE_SENSITIVE_LIKE",
#endif
#if SQLITE_CHECK_PAGES
#ifdef SQLITE_CHECK_PAGES
"CHECK_PAGES",
#endif
#if SQLITE_COVERAGE_TEST
#ifdef SQLITE_COVERAGE_TEST
"COVERAGE_TEST",
#endif
#if SQLITE_DEBUG
#ifdef SQLITE_DEBUG
"DEBUG",
#endif
#if SQLITE_DEFAULT_LOCKING_MODE
#ifdef 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
#if SQLITE_DISABLE_DIRSYNC
#ifdef SQLITE_DISABLE_DIRSYNC
"DISABLE_DIRSYNC",
#endif
#if SQLITE_DISABLE_LFS
#ifdef SQLITE_DISABLE_LFS
"DISABLE_LFS",
#endif
#if SQLITE_ENABLE_API_ARMOR
#ifdef SQLITE_ENABLE_API_ARMOR
"ENABLE_API_ARMOR",
#endif
#if SQLITE_ENABLE_ATOMIC_WRITE
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
"ENABLE_ATOMIC_WRITE",
#endif
#if SQLITE_ENABLE_CEROD
#ifdef SQLITE_ENABLE_CEROD
"ENABLE_CEROD",
#endif
#if SQLITE_ENABLE_COLUMN_METADATA
#ifdef SQLITE_ENABLE_COLUMN_METADATA
"ENABLE_COLUMN_METADATA",
#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
"ENABLE_EXPENSIVE_ASSERT",
#endif
#if SQLITE_ENABLE_FTS1
#ifdef SQLITE_ENABLE_FTS1
"ENABLE_FTS1",
#endif
#if SQLITE_ENABLE_FTS2
#ifdef SQLITE_ENABLE_FTS2
"ENABLE_FTS2",
#endif
#if SQLITE_ENABLE_FTS3
#ifdef SQLITE_ENABLE_FTS3
"ENABLE_FTS3",
#endif
#if SQLITE_ENABLE_FTS3_PARENTHESIS
#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
"ENABLE_FTS3_PARENTHESIS",
#endif
#if SQLITE_ENABLE_FTS4
#ifdef SQLITE_ENABLE_FTS4
"ENABLE_FTS4",
#endif
#if SQLITE_ENABLE_ICU
#ifdef SQLITE_ENABLE_ICU
"ENABLE_ICU",
#endif
#if SQLITE_ENABLE_IOTRACE
#ifdef SQLITE_ENABLE_IOTRACE
"ENABLE_IOTRACE",
#endif
#if SQLITE_ENABLE_LOAD_EXTENSION
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
"ENABLE_LOAD_EXTENSION",
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
#ifdef SQLITE_ENABLE_LOCKING_STYLE
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
#endif
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
"ENABLE_MEMORY_MANAGEMENT",
#endif
#if SQLITE_ENABLE_MEMSYS3
#ifdef SQLITE_ENABLE_MEMSYS3
"ENABLE_MEMSYS3",
#endif
#if SQLITE_ENABLE_MEMSYS5
#ifdef SQLITE_ENABLE_MEMSYS5
"ENABLE_MEMSYS5",
#endif
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
#if SQLITE_ENABLE_RTREE
#ifdef SQLITE_ENABLE_RTREE
"ENABLE_RTREE",
#endif
#if defined(SQLITE_ENABLE_STAT4)
@@ -125,31 +125,31 @@ static const char * const azCompileOpt[] = {
#elif defined(SQLITE_ENABLE_STAT3)
"ENABLE_STAT3",
#endif
#if SQLITE_ENABLE_UNLOCK_NOTIFY
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
"ENABLE_UNLOCK_NOTIFY",
#endif
#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
"ENABLE_UPDATE_DELETE_LIMIT",
#endif
#if SQLITE_HAS_CODEC
#ifdef SQLITE_HAS_CODEC
"HAS_CODEC",
#endif
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
#ifdef SQLITE_HAVE_ISNAN
"HAVE_ISNAN",
#endif
#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
"HOMEGROWN_RECURSIVE_MUTEX",
#endif
#if SQLITE_IGNORE_AFP_LOCK_ERRORS
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
"IGNORE_AFP_LOCK_ERRORS",
#endif
#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
"IGNORE_FLOCK_LOCK_ERRORS",
#endif
#ifdef SQLITE_INT64_TYPE
"INT64_TYPE",
#endif
#if SQLITE_LOCK_TRACE
#ifdef SQLITE_LOCK_TRACE
"LOCK_TRACE",
#endif
#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
@@ -158,226 +158,226 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_MAX_SCHEMA_RETRY
"MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
#endif
#if SQLITE_MEMDEBUG
#ifdef SQLITE_MEMDEBUG
"MEMDEBUG",
#endif
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
"MIXED_ENDIAN_64BIT_FLOAT",
#endif
#if SQLITE_NO_SYNC
#ifdef SQLITE_NO_SYNC
"NO_SYNC",
#endif
#if SQLITE_OMIT_ALTERTABLE
#ifdef SQLITE_OMIT_ALTERTABLE
"OMIT_ALTERTABLE",
#endif
#if SQLITE_OMIT_ANALYZE
#ifdef SQLITE_OMIT_ANALYZE
"OMIT_ANALYZE",
#endif
#if SQLITE_OMIT_ATTACH
#ifdef SQLITE_OMIT_ATTACH
"OMIT_ATTACH",
#endif
#if SQLITE_OMIT_AUTHORIZATION
#ifdef SQLITE_OMIT_AUTHORIZATION
"OMIT_AUTHORIZATION",
#endif
#if SQLITE_OMIT_AUTOINCREMENT
#ifdef SQLITE_OMIT_AUTOINCREMENT
"OMIT_AUTOINCREMENT",
#endif
#if SQLITE_OMIT_AUTOINIT
#ifdef SQLITE_OMIT_AUTOINIT
"OMIT_AUTOINIT",
#endif
#if SQLITE_OMIT_AUTOMATIC_INDEX
#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
"OMIT_AUTOMATIC_INDEX",
#endif
#if SQLITE_OMIT_AUTORESET
#ifdef SQLITE_OMIT_AUTORESET
"OMIT_AUTORESET",
#endif
#if SQLITE_OMIT_AUTOVACUUM
#ifdef SQLITE_OMIT_AUTOVACUUM
"OMIT_AUTOVACUUM",
#endif
#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
"OMIT_BETWEEN_OPTIMIZATION",
#endif
#if SQLITE_OMIT_BLOB_LITERAL
#ifdef SQLITE_OMIT_BLOB_LITERAL
"OMIT_BLOB_LITERAL",
#endif
#if SQLITE_OMIT_BTREECOUNT
#ifdef SQLITE_OMIT_BTREECOUNT
"OMIT_BTREECOUNT",
#endif
#if SQLITE_OMIT_BUILTIN_TEST
#ifdef SQLITE_OMIT_BUILTIN_TEST
"OMIT_BUILTIN_TEST",
#endif
#if SQLITE_OMIT_CAST
#ifdef SQLITE_OMIT_CAST
"OMIT_CAST",
#endif
#if SQLITE_OMIT_CHECK
#ifdef SQLITE_OMIT_CHECK
"OMIT_CHECK",
#endif
#if SQLITE_OMIT_COMPLETE
#ifdef SQLITE_OMIT_COMPLETE
"OMIT_COMPLETE",
#endif
#if SQLITE_OMIT_COMPOUND_SELECT
#ifdef SQLITE_OMIT_COMPOUND_SELECT
"OMIT_COMPOUND_SELECT",
#endif
#if SQLITE_OMIT_CTE
#ifdef SQLITE_OMIT_CTE
"OMIT_CTE",
#endif
#if SQLITE_OMIT_DATETIME_FUNCS
#ifdef SQLITE_OMIT_DATETIME_FUNCS
"OMIT_DATETIME_FUNCS",
#endif
#if SQLITE_OMIT_DECLTYPE
#ifdef SQLITE_OMIT_DECLTYPE
"OMIT_DECLTYPE",
#endif
#if SQLITE_OMIT_DEPRECATED
#ifdef SQLITE_OMIT_DEPRECATED
"OMIT_DEPRECATED",
#endif
#if SQLITE_OMIT_DISKIO
#ifdef SQLITE_OMIT_DISKIO
"OMIT_DISKIO",
#endif
#if SQLITE_OMIT_EXPLAIN
#ifdef SQLITE_OMIT_EXPLAIN
"OMIT_EXPLAIN",
#endif
#if SQLITE_OMIT_FLAG_PRAGMAS
#ifdef SQLITE_OMIT_FLAG_PRAGMAS
"OMIT_FLAG_PRAGMAS",
#endif
#if SQLITE_OMIT_FLOATING_POINT
#ifdef SQLITE_OMIT_FLOATING_POINT
"OMIT_FLOATING_POINT",
#endif
#if SQLITE_OMIT_FOREIGN_KEY
#ifdef SQLITE_OMIT_FOREIGN_KEY
"OMIT_FOREIGN_KEY",
#endif
#if SQLITE_OMIT_GET_TABLE
#ifdef SQLITE_OMIT_GET_TABLE
"OMIT_GET_TABLE",
#endif
#if SQLITE_OMIT_INCRBLOB
#ifdef SQLITE_OMIT_INCRBLOB
"OMIT_INCRBLOB",
#endif
#if SQLITE_OMIT_INTEGRITY_CHECK
#ifdef SQLITE_OMIT_INTEGRITY_CHECK
"OMIT_INTEGRITY_CHECK",
#endif
#if SQLITE_OMIT_LIKE_OPTIMIZATION
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
"OMIT_LIKE_OPTIMIZATION",
#endif
#if SQLITE_OMIT_LOAD_EXTENSION
#ifdef SQLITE_OMIT_LOAD_EXTENSION
"OMIT_LOAD_EXTENSION",
#endif
#if SQLITE_OMIT_LOCALTIME
#ifdef SQLITE_OMIT_LOCALTIME
"OMIT_LOCALTIME",
#endif
#if SQLITE_OMIT_LOOKASIDE
#ifdef SQLITE_OMIT_LOOKASIDE
"OMIT_LOOKASIDE",
#endif
#if SQLITE_OMIT_MEMORYDB
#ifdef SQLITE_OMIT_MEMORYDB
"OMIT_MEMORYDB",
#endif
#if SQLITE_OMIT_OR_OPTIMIZATION
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
"OMIT_OR_OPTIMIZATION",
#endif
#if SQLITE_OMIT_PAGER_PRAGMAS
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
"OMIT_PAGER_PRAGMAS",
#endif
#if SQLITE_OMIT_PRAGMA
#ifdef SQLITE_OMIT_PRAGMA
"OMIT_PRAGMA",
#endif
#if SQLITE_OMIT_PROGRESS_CALLBACK
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
"OMIT_PROGRESS_CALLBACK",
#endif
#if SQLITE_OMIT_QUICKBALANCE
#ifdef SQLITE_OMIT_QUICKBALANCE
"OMIT_QUICKBALANCE",
#endif
#if SQLITE_OMIT_REINDEX
#ifdef SQLITE_OMIT_REINDEX
"OMIT_REINDEX",
#endif
#if SQLITE_OMIT_SCHEMA_PRAGMAS
#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
"OMIT_SCHEMA_PRAGMAS",
#endif
#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
"OMIT_SCHEMA_VERSION_PRAGMAS",
#endif
#if SQLITE_OMIT_SHARED_CACHE
#ifdef SQLITE_OMIT_SHARED_CACHE
"OMIT_SHARED_CACHE",
#endif
#if SQLITE_OMIT_SUBQUERY
#ifdef SQLITE_OMIT_SUBQUERY
"OMIT_SUBQUERY",
#endif
#if SQLITE_OMIT_TCL_VARIABLE
#ifdef SQLITE_OMIT_TCL_VARIABLE
"OMIT_TCL_VARIABLE",
#endif
#if SQLITE_OMIT_TEMPDB
#ifdef SQLITE_OMIT_TEMPDB
"OMIT_TEMPDB",
#endif
#if SQLITE_OMIT_TRACE
#ifdef SQLITE_OMIT_TRACE
"OMIT_TRACE",
#endif
#if SQLITE_OMIT_TRIGGER
#ifdef SQLITE_OMIT_TRIGGER
"OMIT_TRIGGER",
#endif
#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
"OMIT_TRUNCATE_OPTIMIZATION",
#endif
#if SQLITE_OMIT_UTF16
#ifdef SQLITE_OMIT_UTF16
"OMIT_UTF16",
#endif
#if SQLITE_OMIT_VACUUM
#ifdef SQLITE_OMIT_VACUUM
"OMIT_VACUUM",
#endif
#if SQLITE_OMIT_VIEW
#ifdef SQLITE_OMIT_VIEW
"OMIT_VIEW",
#endif
#if SQLITE_OMIT_VIRTUALTABLE
#ifdef SQLITE_OMIT_VIRTUALTABLE
"OMIT_VIRTUALTABLE",
#endif
#if SQLITE_OMIT_WAL
#ifdef SQLITE_OMIT_WAL
"OMIT_WAL",
#endif
#if SQLITE_OMIT_WSD
#ifdef SQLITE_OMIT_WSD
"OMIT_WSD",
#endif
#if SQLITE_OMIT_XFER_OPT
#ifdef SQLITE_OMIT_XFER_OPT
"OMIT_XFER_OPT",
#endif
#if SQLITE_PERFORMANCE_TRACE
#ifdef SQLITE_PERFORMANCE_TRACE
"PERFORMANCE_TRACE",
#endif
#if SQLITE_PROXY_DEBUG
#ifdef SQLITE_PROXY_DEBUG
"PROXY_DEBUG",
#endif
#if SQLITE_RTREE_INT_ONLY
#ifdef SQLITE_RTREE_INT_ONLY
"RTREE_INT_ONLY",
#endif
#if SQLITE_SECURE_DELETE
#ifdef SQLITE_SECURE_DELETE
"SECURE_DELETE",
#endif
#if SQLITE_SMALL_STACK
#ifdef SQLITE_SMALL_STACK
"SMALL_STACK",
#endif
#if SQLITE_SOUNDEX
#ifdef SQLITE_SOUNDEX
"SOUNDEX",
#endif
#if SQLITE_SYSTEM_MALLOC
#ifdef SQLITE_SYSTEM_MALLOC
"SYSTEM_MALLOC",
#endif
#if SQLITE_TCL
#ifdef SQLITE_TCL
"TCL",
#endif
#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
#endif
#if SQLITE_TEST
#ifdef SQLITE_TEST
"TEST",
#endif
#if defined(SQLITE_THREADSAFE)
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#endif
#if SQLITE_USE_ALLOCA
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
#if SQLITE_USER_AUTHENTICATION
#ifdef SQLITE_USER_AUTHENTICATION
"USER_AUTHENTICATION",
#endif
#if SQLITE_WIN32_MALLOC
#ifdef SQLITE_WIN32_MALLOC
"WIN32_MALLOC",
#endif
#if SQLITE_ZERO_MALLOC
#ifdef SQLITE_ZERO_MALLOC
"ZERO_MALLOC"
#endif
};
@@ -392,7 +392,7 @@ static const char * const azCompileOpt[] = {
int sqlite3_compileoption_used(const char *zOptName){
int i, n;
#if SQLITE_ENABLE_API_ARMOR
#ifdef SQLITE_ENABLE_API_ARMOR
if( zOptName==0 ){
(void)SQLITE_MISUSE_BKPT;
return 0;
+7 -9
View File
@@ -412,9 +412,8 @@ static void clearYMD_HMS_TZ(DateTime *p){
** already, check for an MSVC build environment that provides
** localtime_s().
*/
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \
&& defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
#undef HAVE_LOCALTIME_S
#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
#define HAVE_LOCALTIME_S 1
#endif
@@ -434,7 +433,8 @@ static void clearYMD_HMS_TZ(DateTime *p){
*/
static int osLocaltime(time_t *t, struct tm *pTm){
int rc;
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S
#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
&& (!defined(HAVE_LOCALTIME_S) || !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 HAVE_LOCALTIME_R
#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
rc = localtime_r(t, pTm)==0;
#else
rc = localtime_s(pTm, t);
@@ -895,10 +895,8 @@ static void strftimeFunc(
size_t i,j;
char *z;
sqlite3 *db;
const char *zFmt;
const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
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++){
@@ -1092,7 +1090,7 @@ static void currentTimeFunc(
iT = sqlite3StmtCurrentTime(context);
if( iT<=0 ) return;
t = iT/1000 - 10000*(sqlite3_int64)21086676;
#if HAVE_GMTIME_R
#ifdef HAVE_GMTIME_R
pTm = gmtime_r(&t, &sNow);
#else
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+2 -2
View File
@@ -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 = 0; /* VDBE cursor for the canonical data source */
int iIdxCur = 0; /* Cursor number of the first index */
int iDataCur; /* VDBE cursor for the canonical data source */
int iIdxCur; /* Cursor number of the first index */
int nIdx; /* Number of indices */
sqlite3 *db; /* Main database structure */
AuthContext sContext; /* Authorization context */
+3 -4
View File
@@ -515,7 +515,7 @@ Expr *sqlite3PExpr(
const Token *pToken /* Argument token */
){
Expr *p;
if( op==TK_AND && pLeft && pRight && pParse->nErr==0 ){
if( op==TK_AND && pLeft && pRight ){
/* Take advantage of short-circuit false optimization for AND */
p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
}else{
@@ -4069,11 +4069,10 @@ static int exprSrcCount(Walker *pWalker, Expr *pExpr){
int i;
struct SrcCount *p = pWalker->u.pSrcCount;
SrcList *pSrc = p->pSrc;
int nSrc = pSrc ? pSrc->nSrc : 0;
for(i=0; i<nSrc; i++){
for(i=0; i<pSrc->nSrc; i++){
if( pExpr->iTable==pSrc->a[i].iCursor ) break;
}
if( i<nSrc ){
if( i<pSrc->nSrc ){
p->nThis++;
}else{
p->nOther++;
+21 -60
View File
@@ -437,7 +437,7 @@ static void fkLookupParent(
OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
}else{
if( nIncr>0 && pFKey->isDeferred==0 ){
sqlite3MayAbort(pParse);
sqlite3ParseToplevel(pParse)->mayAbort = 1;
}
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
}
@@ -509,10 +509,6 @@ 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:
@@ -629,9 +625,13 @@ static void fkScanChildren(
sqlite3ResolveExprNames(&sNameContext, pWhere);
/* Create VDBE to loop through the entries in pSrc that match the WHERE
** clause. For each row found, increment either the deferred or immediate
** foreign key constraint counter. */
** clause. If the constraint is not deferred, throw an exception for
** each row found. Otherwise, for deferred constraints, increment the
** deferred constraint counter by nIncr for each row selected. */
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
if( nIncr>0 && pFKey->isDeferred==0 ){
sqlite3ParseToplevel(pParse)->mayAbort = 1;
}
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
if( pWInfo ){
sqlite3WhereEnd(pWInfo);
@@ -810,24 +810,6 @@ 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
@@ -880,7 +862,7 @@ void sqlite3FkCheck(
int *aiCol;
int iCol;
int i;
int bIgnore = 0;
int isIgnore = 0;
if( aChange
&& sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
@@ -939,7 +921,7 @@ void sqlite3FkCheck(
int rcauth;
char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
bIgnore = (rcauth==SQLITE_IGNORE);
isIgnore = (rcauth==SQLITE_IGNORE);
}
#endif
}
@@ -954,18 +936,12 @@ 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, bIgnore);
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
}
if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){
if( regNew!=0 ){
/* 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.
**
** 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);
** be found, adding the child row has violated the FK constraint. */
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
}
sqlite3DbFree(db, aiFree);
@@ -986,8 +962,8 @@ void sqlite3FkCheck(
&& !pParse->pToplevel && !pParse->isMultiWrite
){
assert( regOld==0 && regNew!=0 );
/* Inserting a single row into a parent table cannot cause (or fix)
** an immediate foreign key violation. So do nothing in this case. */
/* Inserting a single row into a parent table cannot cause an immediate
** foreign key violation. So do nothing in this case. */
continue;
}
@@ -1011,28 +987,13 @@ void sqlite3FkCheck(
fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
}
if( regOld!=0 ){
int eAction = pFKey->aAction[aChange!=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. */
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);
-8
View File
@@ -152,13 +152,6 @@ const unsigned char sqlite3CtypeMap[256] = {
# 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.
@@ -189,7 +182,6 @@ 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 */
+1
View File
@@ -34,6 +34,7 @@
# 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
+49 -36
View File
@@ -62,7 +62,7 @@ int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
** I/O active are written using this function. These messages
** are intended for debugging activity only.
*/
/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0;
void (*sqlite3IoTrace)(const char*, ...) = 0;
#endif
/*
@@ -271,13 +271,6 @@ int sqlite3_initialize(void){
** when this routine is invoked, then this routine is a harmless no-op.
*/
int sqlite3_shutdown(void){
#ifdef SQLITE_OMIT_WSD
int rc = sqlite3_wsd_init(4096, 24);
if( rc!=SQLITE_OK ){
return rc;
}
#endif
if( sqlite3GlobalConfig.isInit ){
#ifdef SQLITE_EXTRA_SHUTDOWN
void SQLITE_EXTRA_SHUTDOWN(void);
@@ -594,11 +587,6 @@ int sqlite3_config(int op, ...){
}
#endif
case SQLITE_CONFIG_PMASZ: {
sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int);
break;
}
default: {
rc = SQLITE_ERROR;
break;
@@ -1046,7 +1034,13 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
if( pDb->pBt ){
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
if( j!=1 ){
if( j!=1 && pDb->pSchema ){
/* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */
for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3KeyInfoUnref(pIdx->pKeyInfo);
pIdx->pKeyInfo = 0;
}
pDb->pSchema = 0;
}
}
@@ -1350,7 +1344,7 @@ static int sqliteDefaultBusyCallback(
void *ptr, /* Database connection */
int count /* Number of times table has been busy */
){
#if SQLITE_OS_WIN || HAVE_USLEEP
#if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP)
static const u8 delays[] =
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
static const u8 totals[] =
@@ -2171,6 +2165,32 @@ const char *sqlite3_errstr(int rc){
return sqlite3ErrStr(rc);
}
/*
** Invalidate all cached KeyInfo objects for database connection "db"
*/
static void invalidateCachedKeyInfo(sqlite3 *db){
Db *pDb; /* A single database */
int iDb; /* The database index number */
HashElem *k; /* For looping over tables in pDb */
Table *pTab; /* A table in the database */
Index *pIdx; /* Each index */
for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
if( pDb->pBt==0 ) continue;
sqlite3BtreeEnter(pDb->pBt);
for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
pTab = (Table*)sqliteHashData(k);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){
sqlite3KeyInfoUnref(pIdx->pKeyInfo);
pIdx->pKeyInfo = 0;
}
}
}
sqlite3BtreeLeave(pDb->pBt);
}
}
/*
** Create a new collating function for database "db". The name is zName
** and the encoding is enc.
@@ -2214,6 +2234,7 @@ static int createCollation(
return SQLITE_BUSY;
}
sqlite3ExpirePreparedStatements(db);
invalidateCachedKeyInfo(db);
/* If collation sequence pColl was created directly by a call to
** sqlite3_create_collation, and not generated by synthCollSeq(),
@@ -2717,9 +2738,6 @@ static int openDatabase(
#endif
#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS
| SQLITE_ForeignKeys
#endif
#if defined(SQLITE_REVERSE_UNORDERED_SELECTS)
| SQLITE_ReverseOrder
#endif
;
sqlite3HashInit(&db->aCollSeq);
@@ -2768,10 +2786,7 @@ static int openDatabase(
sqlite3Error(db, rc);
goto opendb_out;
}
sqlite3BtreeEnter(db->aDb[0].pBt);
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db);
sqlite3BtreeLeave(db->aDb[0].pBt);
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
/* The default safety_level for the main database is 'full'; for the temp
@@ -2929,7 +2944,7 @@ int sqlite3_open16(
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
assert( *ppDb || rc==SQLITE_NOMEM );
if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE;
ENC(*ppDb) = SQLITE_UTF16NATIVE;
}
}else{
rc = SQLITE_NOMEM;
@@ -3125,6 +3140,7 @@ void sqlite3_thread_cleanup(void){
** Return meta information about a specific column of a database table.
** See comment in sqlite3.h (sqlite.h.in) for details.
*/
#ifdef SQLITE_ENABLE_COLUMN_METADATA
int sqlite3_table_column_metadata(
sqlite3 *db, /* Connection handle */
const char *zDbName, /* Database name or NULL */
@@ -3140,7 +3156,7 @@ int sqlite3_table_column_metadata(
char *zErrMsg = 0;
Table *pTab = 0;
Column *pCol = 0;
int iCol = 0;
int iCol;
char const *zDataType = 0;
char const *zCollSeq = 0;
@@ -3164,8 +3180,11 @@ int sqlite3_table_column_metadata(
}
/* Find the column for which info is requested */
if( zColumnName==0 ){
/* Query for existance of table only */
if( sqlite3IsRowid(zColumnName) ){
iCol = pTab->iPKey;
if( iCol>=0 ){
pCol = &pTab->aCol[iCol];
}
}else{
for(iCol=0; iCol<pTab->nCol; iCol++){
pCol = &pTab->aCol[iCol];
@@ -3174,13 +3193,8 @@ int sqlite3_table_column_metadata(
}
}
if( iCol==pTab->nCol ){
if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
iCol = pTab->iPKey;
pCol = iCol>=0 ? &pTab->aCol[iCol] : 0;
}else{
pTab = 0;
goto error_out;
}
pTab = 0;
goto error_out;
}
}
@@ -3233,6 +3247,7 @@ error_out:
sqlite3_mutex_leave(db->mutex);
return rc;
}
#endif
/*
** Sleep for a little while. Return the amount of time slept.
@@ -3671,14 +3686,13 @@ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
** connection.
*/
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
Btree *pBt;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
pBt = sqlite3DbNameToBtree(db, zDbName);
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
}
@@ -3687,13 +3701,12 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
** no such database exists.
*/
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
Btree *pBt;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return -1;
}
#endif
pBt = sqlite3DbNameToBtree(db, zDbName);
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
}
+3 -3
View File
@@ -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 HAVE_MALLOC_H && HAVE_MALLOC_USABLE_SIZE
# define SQLITE_USE_MALLOC_H 1
# define SQLITE_USE_MALLOC_USABLE_SIZE 1
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE)
# define SQLITE_USE_MALLOC_H
# define SQLITE_USE_MALLOC_USABLE_SIZE
/*
** The MSVCRT has malloc_usable_size(), but it is called _msize(). The
** use of _msize() is automatic, but can be disabled by compiling with
-35
View File
@@ -1,35 +0,0 @@
/*
** 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_ */
-6
View File
@@ -209,12 +209,6 @@ 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 );
+14 -18
View File
@@ -3386,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 or -DHAVE_FDATASYNC
** then simply compile with -Dfdatasync=fdatasync
*/
#if !defined(fdatasync) && !HAVE_FDATASYNC
#if !defined(fdatasync)
# define fdatasync fsync
#endif
@@ -3709,28 +3709,24 @@ 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. 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.
/* 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.
*/
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 */
iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-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( robust_ftruncate(pFile->h, nSize) ){
pFile->lastErrno = errno;
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
}
if( nWrite==0 || (nSize%nBlk) ){
nWrite = seekAndWrite(pFile, nSize-1, "", 1);
iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
while( iWrite<nSize ){
int nWrite = seekAndWrite(pFile, iWrite, "", 1);
if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
iWrite += nBlk;
}
#endif
}
+9 -9
View File
@@ -1203,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 = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); )
MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); )
MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
sqlite3_mutex_enter(pMaster);
sqlite3_mutex_enter(pMem);
winMemAssertMagic();
@@ -2479,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 && !defined(SQLITE_WIN32_NO_OVERLAPPED)
#if !SQLITE_OS_WINCE
OVERLAPPED overlapped; /* The offset for ReadFile. */
#endif
winFile *pFile = (winFile*)id; /* file handle */
@@ -2511,7 +2511,7 @@ static int winRead(
}
#endif
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
#if SQLITE_OS_WINCE
if( winSeekFile(pFile, offset) ){
OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
return SQLITE_FULL;
@@ -2583,13 +2583,13 @@ static int winWrite(
}
#endif
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
#if SQLITE_OS_WINCE
rc = winSeekFile(pFile, offset);
if( rc==0 ){
#else
{
#endif
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
#if !SQLITE_OS_WINCE
OVERLAPPED overlapped; /* The offset for WriteFile. */
#endif
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
@@ -2597,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 && !defined(SQLITE_WIN32_NO_OVERLAPPED)
#if !SQLITE_OS_WINCE
memset(&overlapped, 0, sizeof(OVERLAPPED));
overlapped.Offset = (LONG)(offset & 0xffffffff);
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
#endif
while( nRem>0 ){
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
#if SQLITE_OS_WINCE
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
#else
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
@@ -2617,7 +2617,7 @@ static int winWrite(
lastErrno = osGetLastError();
break;
}
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
#if !SQLITE_OS_WINCE
offset += nWrite;
overlapped.Offset = (LONG)(offset & 0xffffffff);
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
+12 -22
View File
@@ -646,8 +646,6 @@ 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 */
@@ -665,9 +663,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) */
@@ -1683,19 +1681,10 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
** 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
@@ -3898,7 +3887,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;
@@ -5129,12 +5118,16 @@ int sqlite3PagerSharedLock(Pager *pPager){
);
}
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.
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.
**
** Database changes is detected by looking at 15 bytes beginning
** at offset 24 into the file. The first 4 of these 16 bytes are
@@ -5299,7 +5292,6 @@ 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. */
@@ -5449,7 +5441,6 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
assert( pgno!=0 );
assert( pPager->pPCache!=0 );
pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);
assert( pPage==0 || pPager->hasBeenUsed );
return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
}
@@ -6316,7 +6307,6 @@ 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);
}
-1
View File
@@ -172,7 +172,6 @@ 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);
+2 -8
View File
@@ -415,19 +415,13 @@ 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;
}
if( allValues ){
p->selFlags |= SF_AllValues;
}else if(
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0
&& cnt>mxSelect
){
mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
if( mxSelect && cnt>mxSelect ){
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
}
}
+14 -3
View File
@@ -31,6 +31,18 @@ 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 ********************/
/* Allowed values for second argument to pcacheManageDirtyList() */
@@ -184,8 +196,7 @@ int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
if( pCache->szPage ){
sqlite3_pcache *pNew;
pNew = sqlite3GlobalConfig.pcache2.xCreate(
szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)),
pCache->bPurgeable
szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
);
if( pNew==0 ) return SQLITE_NOMEM;
sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
@@ -644,7 +655,7 @@ void sqlite3PcacheShrink(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)); }
int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); }
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
+2 -2
View File
@@ -296,7 +296,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
pPg = 0;
}
#else
pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra);
pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
pcache1EnterMutex(pCache->pGroup);
@@ -984,7 +984,7 @@ void sqlite3PCacheSetDefault(void){
/*
** Return the size of the header on each page of this PCACHE implementation.
*/
int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); }
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
+25 -18
View File
@@ -71,7 +71,6 @@
#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 */
@@ -88,7 +87,7 @@ static const struct sPragmaNames {
{ /* zName: */ "application_id",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlag: */ 0,
/* iArg: */ BTREE_APPLICATION_ID },
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
{ /* zName: */ "auto_vacuum",
@@ -154,12 +153,6 @@ 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,
@@ -215,8 +208,8 @@ static const struct sPragmaNames {
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{ /* zName: */ "freelist_count",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlag: */ PragFlag_ReadOnly,
/* iArg: */ BTREE_FREE_PAGE_COUNT },
/* ePragFlag: */ 0,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{ /* zName: */ "full_column_names",
@@ -368,7 +361,7 @@ static const struct sPragmaNames {
{ /* zName: */ "schema_version",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlag: */ 0,
/* iArg: */ BTREE_SCHEMA_VERSION },
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{ /* zName: */ "secure_delete",
@@ -434,7 +427,7 @@ static const struct sPragmaNames {
{ /* zName: */ "user_version",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlag: */ 0,
/* iArg: */ BTREE_USER_VERSION },
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if defined(SQLITE_DEBUG)
@@ -477,7 +470,7 @@ static const struct sPragmaNames {
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 58 on by default, 71 total. */
/* Number of pragmas: 57 on by default, 70 total. */
/* End of the automatically generated pragma table.
***************************************************************************/
@@ -727,7 +720,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 = 0; /* Binary search bounds */
int lwr, upr, mid; /* 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 */
@@ -2087,8 +2080,7 @@ void sqlite3Pragma(
){
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
SCHEMA_ENC(db) = ENC(db) =
pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
break;
}
}
@@ -2133,9 +2125,24 @@ void sqlite3Pragma(
** applications for any purpose.
*/
case PragTyp_HEADER_VALUE: {
int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */
int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){
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 ){
/* Write the specified cookie value */
static const VdbeOpList setCookie[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */
-2
View File
@@ -394,11 +394,9 @@ 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);
+11
View File
@@ -14,6 +14,17 @@
*/
#include "sqliteInt.h"
/*
** If the strchrnul() library function is available, then set
** HAVE_STRCHRNUL. If that routine is not available, this module
** will supply its own. The built-in version is slower than
** the glibc version so the glibc version is definitely preferred.
*/
#if !defined(HAVE_STRCHRNUL)
# define HAVE_STRCHRNUL 0
#endif
/*
** Conversion types fall into various categories as defined by the
** following enumeration.
+27 -94
View File
@@ -58,25 +58,20 @@ struct SortCtx {
#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
/*
** Delete all the content of a Select structure. Deallocate the structure
** itself only if bFree is true.
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
*/
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;
}
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);
}
/*
@@ -135,7 +130,8 @@ Select *sqlite3SelectNew(
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
if( db->mallocFailed ) {
clearSelect(db, pNew, pNew!=&standin);
clearSelect(db, pNew);
if( pNew!=&standin ) sqlite3DbFree(db, pNew);
pNew = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -160,7 +156,10 @@ void sqlite3SelectSetName(Select *p, const char *zName){
** Delete the given Select structure and all of its substructures.
*/
void sqlite3SelectDelete(sqlite3 *db, Select *p){
clearSelect(db, p, 1);
if( p ){
clearSelect(db, p);
sqlite3DbFree(db, p);
}
}
/*
@@ -2076,66 +2075,6 @@ 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
@@ -2217,19 +2156,17 @@ 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 ){
selectWrongNumTermsError(pParse, 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));
}
rc = 1;
goto multi_select_end;
}
@@ -4115,9 +4052,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
if( pWalker->xSelectCallback2==selectPopWith ){
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
}
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
** the FROM clause of the SELECT statement.
@@ -4408,9 +4343,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
if( (pSelect->selFlags & SF_AllValues)==0 ){
w.xSelectCallback2 = selectPopWith;
}
w.xSelectCallback2 = selectPopWith;
sqlite3WalkSelect(&w, pSelect);
}
+129 -259
View File
@@ -17,13 +17,6 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
/*
** If requested, include the SQLite compiler options file for MSVC.
*/
#if defined(INCLUDE_MSVC_H)
#include "msvc.h"
#endif
/*
** Enable large-file support for fopen() and friends on unix.
*/
@@ -55,16 +48,17 @@
# include <sys/types.h>
#endif
#if HAVE_READLINE
#if defined(HAVE_READLINE) && HAVE_READLINE!=0
# include <readline/readline.h>
# include <readline/history.h>
#endif
#if HAVE_EDITLINE
#else
# undef HAVE_READLINE
#endif
#if defined(HAVE_EDITLINE) && !defined(HAVE_READLINE)
# define HAVE_READLINE 1
# include <editline/readline.h>
#endif
#if !HAVE_READLINE
#if !defined(HAVE_READLINE)
# define add_history(X)
# define read_history(X)
# define write_history(X)
@@ -431,7 +425,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
zResult = local_getline(zPrior, in);
}else{
zPrompt = isContinuation ? continuePrompt : mainPrompt;
#if HAVE_READLINE
#if defined(HAVE_READLINE)
free(zPrior);
zResult = readline(zPrompt);
if( zResult && *zResult ) add_history(zResult);
@@ -477,11 +471,11 @@ struct ShellState {
int showHeader; /* True to show column names in List or Column mode */
unsigned shellFlgs; /* Various flags */
char *zDestTable; /* Name of destination table when MODE_Insert */
char colSeparator[20]; /* Column separator character for several modes */
char rowSeparator[20]; /* Row separator character for MODE_Ascii */
char separator[20]; /* Separator character for MODE_List */
char newline[20]; /* Record separator in MODE_Csv */
int colWidth[100]; /* Requested width of each column when in column mode*/
int actualWidth[100]; /* Actual width of each column */
char nullValue[20]; /* The text to print when a NULL comes back from
char nullvalue[20]; /* The text to print when a NULL comes back from
** the database */
SavedModeInfo normalMode;/* Holds the mode just before .explain ON */
char outfile[FILENAME_MAX]; /* Filename for *out */
@@ -514,7 +508,6 @@ struct ShellState {
#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
#define MODE_Csv 7 /* Quote strings, numbers are plain */
#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */
#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */
static const char *modeDescr[] = {
"line",
@@ -526,22 +519,8 @@ static const char *modeDescr[] = {
"tcl",
"csv",
"explain",
"ascii",
};
/*
** These are the column/row/line separators used by the various
** import/export modes.
*/
#define SEP_Column "|"
#define SEP_Row "\n"
#define SEP_Tab "\t"
#define SEP_Space " "
#define SEP_Comma ","
#define SEP_CrLf "\r\n"
#define SEP_Unit "\x1F"
#define SEP_Record "\x1E"
/*
** Number of elements in an array
*/
@@ -698,22 +677,22 @@ static const char needCsvQuote[] = {
};
/*
** Output a single term of CSV. Actually, p->colSeparator is used for
** the separator, which may or may not be a comma. p->nullValue is
** Output a single term of CSV. Actually, p->separator is used for
** the separator, which may or may not be a comma. p->nullvalue is
** the null value. Strings are quoted if necessary. The separator
** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){
FILE *out = p->out;
if( z==0 ){
fprintf(out,"%s",p->nullValue);
fprintf(out,"%s",p->nullvalue);
}else{
int i;
int nSep = strlen30(p->colSeparator);
int nSep = strlen30(p->separator);
for(i=0; z[i]; i++){
if( needCsvQuote[((unsigned char*)z)[i]]
|| (z[i]==p->colSeparator[0] &&
(nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
|| (z[i]==p->separator[0] &&
(nSep==1 || memcmp(z, p->separator, nSep)==0)) ){
i = 0;
break;
}
@@ -730,7 +709,7 @@ static void output_csv(ShellState *p, const char *z, int bSep){
}
}
if( bSep ){
fprintf(p->out, "%s", p->colSeparator);
fprintf(p->out, "%s", p->separator);
}
}
@@ -768,10 +747,10 @@ static int shell_callback(
int len = strlen30(azCol[i] ? azCol[i] : "");
if( len>w ) w = len;
}
if( p->cnt++>0 ) fprintf(p->out, "%s", p->rowSeparator);
if( p->cnt++>0 ) fprintf(p->out,"\n");
for(i=0; i<nArg; i++){
fprintf(p->out,"%*s = %s%s", w, azCol[i],
azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
fprintf(p->out,"%*s = %s\n", w, azCol[i],
azArg[i] ? azArg[i] : p->nullvalue);
}
break;
}
@@ -788,7 +767,7 @@ static int shell_callback(
if( w==0 ){
w = strlen30(azCol[i] ? azCol[i] : "");
if( w<10 ) w = 10;
n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue);
n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullvalue);
if( w<n ) w = n;
}
if( i<ArraySize(p->actualWidth) ){
@@ -796,11 +775,9 @@ static int shell_callback(
}
if( p->showHeader ){
if( w<0 ){
fprintf(p->out,"%*.*s%s",-w,-w,azCol[i],
i==nArg-1 ? p->rowSeparator : " ");
fprintf(p->out,"%*.*s%s",-w,-w,azCol[i], i==nArg-1 ? "\n": " ");
}else{
fprintf(p->out,"%-*.*s%s",w,w,azCol[i],
i==nArg-1 ? p->rowSeparator : " ");
fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
}
}
}
@@ -815,7 +792,7 @@ static int shell_callback(
}
fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
"----------------------------------------------------------",
i==nArg-1 ? p->rowSeparator : " ");
i==nArg-1 ? "\n": " ");
}
}
}
@@ -838,12 +815,10 @@ static int shell_callback(
}
if( w<0 ){
fprintf(p->out,"%*.*s%s",-w,-w,
azArg[i] ? azArg[i] : p->nullValue,
i==nArg-1 ? p->rowSeparator : " ");
azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
}else{
fprintf(p->out,"%-*.*s%s",w,w,
azArg[i] ? azArg[i] : p->nullValue,
i==nArg-1 ? p->rowSeparator : " ");
azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
}
}
break;
@@ -852,21 +827,20 @@ static int shell_callback(
case MODE_List: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
fprintf(p->out,"%s%s",azCol[i],
i==nArg-1 ? p->rowSeparator : p->colSeparator);
fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
}
}
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
char *z = azArg[i];
if( z==0 ) z = p->nullValue;
if( z==0 ) z = p->nullvalue;
fprintf(p->out, "%s", z);
if( i<nArg-1 ){
fprintf(p->out, "%s", p->colSeparator);
fprintf(p->out, "%s", p->separator);
}else if( p->mode==MODE_Semi ){
fprintf(p->out, ";%s", p->rowSeparator);
fprintf(p->out, ";\n");
}else{
fprintf(p->out, "%s", p->rowSeparator);
fprintf(p->out, "\n");
}
}
break;
@@ -885,7 +859,7 @@ static int shell_callback(
fprintf(p->out,"<TR>");
for(i=0; i<nArg; i++){
fprintf(p->out,"<TD>");
output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
fprintf(p->out,"</TD>\n");
}
fprintf(p->out,"</TR>\n");
@@ -895,16 +869,16 @@ static int shell_callback(
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_c_string(p->out,azCol[i] ? azCol[i] : "");
if(i<nArg-1) fprintf(p->out, "%s", p->colSeparator);
if(i<nArg-1) fprintf(p->out, "%s", p->separator);
}
fprintf(p->out, "%s", p->rowSeparator);
fprintf(p->out,"\n");
}
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
if(i<nArg-1) fprintf(p->out, "%s", p->colSeparator);
output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
if(i<nArg-1) fprintf(p->out, "%s", p->separator);
}
fprintf(p->out, "%s", p->rowSeparator);
fprintf(p->out,"\n");
break;
}
case MODE_Csv: {
@@ -916,13 +890,13 @@ static int shell_callback(
for(i=0; i<nArg; i++){
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
}
fprintf(p->out, "%s", p->rowSeparator);
fprintf(p->out,"%s",p->newline);
}
if( nArg>0 ){
for(i=0; i<nArg; i++){
output_csv(p, azArg[i], i<nArg-1);
}
fprintf(p->out, "%s", p->rowSeparator);
fprintf(p->out,"%s",p->newline);
}
#if defined(WIN32) || defined(_WIN32)
fflush(p->out);
@@ -959,22 +933,6 @@ static int shell_callback(
fprintf(p->out,");\n");
break;
}
case MODE_Ascii: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
if( i>0 ) fprintf(p->out, "%s", p->colSeparator);
fprintf(p->out,"%s",azCol[i] ? azCol[i] : "");
}
fprintf(p->out, "%s", p->rowSeparator);
}
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
if( i>0 ) fprintf(p->out, "%s", p->colSeparator);
fprintf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
}
fprintf(p->out, "%s", p->rowSeparator);
break;
}
}
return 0;
}
@@ -1740,13 +1698,12 @@ static char zHelp[] =
#endif
".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
" ascii Columns/rows delimited by 0x1F and 0x1E\n"
" csv Comma-separated values\n"
" column Left-aligned columns. (See .width)\n"
" html HTML <table> code\n"
" insert SQL insert statements for TABLE\n"
" line One value per line\n"
" list Values delimited by .separator strings\n"
" list Values delimited by .separator string\n"
" tabs Tab-separated values\n"
" tcl TCL list elements\n"
".nullvalue STRING Use STRING in place of NULL values\n"
@@ -1763,8 +1720,8 @@ static char zHelp[] =
".schema ?TABLE? Show the CREATE statements\n"
" If TABLE specified, only show tables matching\n"
" LIKE pattern TABLE.\n"
".separator COL ?ROW? Change the column separator and optionally the row\n"
" separator for both the output mode and .import\n"
".separator STRING ?NL? Change separator used by output mode and .import\n"
" NL is the end-of-line mark for CSV\n"
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
".show Show the current values for various settings\n"
".stats on|off Turn stats on or off\n"
@@ -2045,10 +2002,10 @@ static void test_breakpoint(void){
}
/*
** An object used to read a CSV and other files for import.
** An object used to read a CSV file
*/
typedef struct ImportCtx ImportCtx;
struct ImportCtx {
typedef struct CSVReader CSVReader;
struct CSVReader {
const char *zFile; /* Name of the input file */
FILE *in; /* Read the CSV text from this input stream */
char *z; /* Accumulated text for a field */
@@ -2056,12 +2013,11 @@ struct ImportCtx {
int nAlloc; /* Space allocated for z[] */
int nLine; /* Current line number */
int cTerm; /* Character that terminated the most recent field */
int cColSep; /* The column separator character. (Usually ",") */
int cRowSep; /* The row separator character. (Usually "\n") */
int cSeparator; /* The separator character. (Usually ",") */
};
/* Append a single byte to z[] */
static void import_append_char(ImportCtx *p, int c){
static void csv_append_char(CSVReader *p, int c){
if( p->n+1>=p->nAlloc ){
p->nAlloc += p->nAlloc + 100;
p->z = sqlite3_realloc(p->z, p->nAlloc);
@@ -2079,17 +2035,15 @@ static void import_append_char(ImportCtx *p, int c){
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc().
** + Use p->cSep as the column separator. The default is ",".
** + Use p->rSep as the row separator. The default is "\n".
** + Use p->cSep as the separator. The default is ",".
** + Keep track of the line number in p->nLine.
** + Store the character that terminates the field in p->cTerm. Store
** EOF on end-of-file.
** + Report syntax errors on stderr
*/
static char *csv_read_one_field(ImportCtx *p){
int c;
int cSep = p->cColSep;
int rSep = p->cRowSep;
static char *csv_read_one_field(CSVReader *p){
int c, pc, ppc;
int cSep = p->cSeparator;
p->n = 0;
c = fgetc(p->in);
if( c==EOF || seenInterrupt ){
@@ -2097,13 +2051,12 @@ static char *csv_read_one_field(ImportCtx *p){
return 0;
}
if( c=='"' ){
int pc, ppc;
int startLine = p->nLine;
int cQuote = c;
pc = ppc = 0;
while( 1 ){
c = fgetc(p->in);
if( c==rSep ) p->nLine++;
if( c=='\n' ) p->nLine++;
if( c==cQuote ){
if( pc==cQuote ){
pc = 0;
@@ -2111,8 +2064,8 @@ static char *csv_read_one_field(ImportCtx *p){
}
}
if( (c==cSep && pc==cQuote)
|| (c==rSep && pc==cQuote)
|| (c==rSep && pc=='\r' && ppc==cQuote)
|| (c=='\n' && pc==cQuote)
|| (c=='\n' && pc=='\r' && ppc==cQuote)
|| (c==EOF && pc==cQuote)
){
do{ p->n--; }while( p->z[p->n]!=cQuote );
@@ -2126,19 +2079,19 @@ static char *csv_read_one_field(ImportCtx *p){
if( c==EOF ){
fprintf(stderr, "%s:%d: unterminated %c-quoted field\n",
p->zFile, startLine, cQuote);
p->cTerm = c;
p->cTerm = EOF;
break;
}
import_append_char(p, c);
csv_append_char(p, c);
ppc = pc;
pc = c;
}
}else{
while( c!=EOF && c!=cSep && c!=rSep ){
import_append_char(p, c);
while( c!=EOF && c!=cSep && c!='\n' ){
csv_append_char(p, c);
c = fgetc(p->in);
}
if( c==rSep ){
if( c=='\n' ){
p->nLine++;
if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
}
@@ -2148,40 +2101,6 @@ static char *csv_read_one_field(ImportCtx *p){
return p->z;
}
/* Read a single field of ASCII delimited text.
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc().
** + Use p->cSep as the column separator. The default is "\x1F".
** + Use p->rSep as the row separator. The default is "\x1E".
** + Keep track of the row number in p->nLine.
** + Store the character that terminates the field in p->cTerm. Store
** EOF on end-of-file.
** + Report syntax errors on stderr
*/
static char *ascii_read_one_field(ImportCtx *p){
int c;
int cSep = p->cColSep;
int rSep = p->cRowSep;
p->n = 0;
c = fgetc(p->in);
if( c==EOF || seenInterrupt ){
p->cTerm = EOF;
return 0;
}
while( c!=EOF && c!=cSep && c!=rSep ){
import_append_char(p, c);
c = fgetc(p->in);
}
if( c==rSep ){
p->nLine++;
}
p->cTerm = c;
if( p->z ) p->z[p->n] = 0;
return p->z;
}
/*
** Try to transfer data for table zTable. If an error is seen while
** moving forward, try to go backwards. The backwards movement won't
@@ -2736,10 +2655,9 @@ static int do_meta_command(char *zLine, ShellState *p){
int nByte; /* Number of bytes in an SQL string */
int i, j; /* Loop counters */
int needCommit; /* True to COMMIT or ROLLBACK at end */
int nSep; /* Number of bytes in p->colSeparator[] */
int nSep; /* Number of bytes in p->separator[] */
char *zSql; /* An SQL statement */
ImportCtx sCtx; /* Reader context */
char *(*xRead)(ImportCtx*); /* Procedure to read one value */
CSVReader sCsv; /* Reader context */
int (*xCloser)(FILE*); /* Procedure to close th3 connection */
if( nArg!=3 ){
@@ -2749,79 +2667,55 @@ static int do_meta_command(char *zLine, ShellState *p){
zFile = azArg[1];
zTable = azArg[2];
seenInterrupt = 0;
memset(&sCtx, 0, sizeof(sCtx));
memset(&sCsv, 0, sizeof(sCsv));
open_db(p, 0);
nSep = strlen30(p->colSeparator);
nSep = strlen30(p->separator);
if( nSep==0 ){
fprintf(stderr, "Error: non-null column separator required for import\n");
fprintf(stderr, "Error: non-null separator required for import\n");
return 1;
}
if( nSep>1 ){
fprintf(stderr, "Error: multi-character column separators not allowed"
fprintf(stderr, "Error: multi-character separators not allowed"
" for import\n");
return 1;
}
nSep = strlen30(p->rowSeparator);
if( nSep==0 ){
fprintf(stderr, "Error: non-null row separator required for import\n");
return 1;
}
if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
/* When importing CSV (only), if the row separator is set to the
** default output row separator, change it to the default input
** row separator. This avoids having to maintain different input
** and output row separators. */
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
nSep = strlen30(p->rowSeparator);
}
if( nSep>1 ){
fprintf(stderr, "Error: multi-character row separators not allowed"
" for import\n");
return 1;
}
sCtx.zFile = zFile;
sCtx.nLine = 1;
if( sCtx.zFile[0]=='|' ){
sCtx.in = popen(sCtx.zFile+1, "r");
sCtx.zFile = "<pipe>";
sCsv.zFile = zFile;
sCsv.nLine = 1;
if( sCsv.zFile[0]=='|' ){
sCsv.in = popen(sCsv.zFile+1, "r");
sCsv.zFile = "<pipe>";
xCloser = pclose;
}else{
sCtx.in = fopen(sCtx.zFile, "rb");
sCsv.in = fopen(sCsv.zFile, "rb");
xCloser = fclose;
}
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
}else{
xRead = csv_read_one_field;
}
if( sCtx.in==0 ){
if( sCsv.in==0 ){
fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
return 1;
}
sCtx.cColSep = p->colSeparator[0];
sCtx.cRowSep = p->rowSeparator[0];
sCsv.cSeparator = p->separator[0];
zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
if( zSql==0 ){
fprintf(stderr, "Error: out of memory\n");
xCloser(sCtx.in);
xCloser(sCsv.in);
return 1;
}
nByte = strlen30(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
csv_append_char(&sCsv, 0); /* To ensure sCsv.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
char cSep = '(';
while( xRead(&sCtx) ){
zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCtx.z);
while( csv_read_one_field(&sCsv) ){
zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCsv.z);
cSep = ',';
if( sCtx.cTerm!=sCtx.cColSep ) break;
if( sCsv.cTerm!=sCsv.cSeparator ) break;
}
if( cSep=='(' ){
sqlite3_free(zCreate);
sqlite3_free(sCtx.z);
xCloser(sCtx.in);
fprintf(stderr,"%s: empty file\n", sCtx.zFile);
sqlite3_free(sCsv.z);
xCloser(sCsv.in);
fprintf(stderr,"%s: empty file\n", sCsv.zFile);
return 1;
}
zCreate = sqlite3_mprintf("%z\n)", zCreate);
@@ -2830,8 +2724,8 @@ static int do_meta_command(char *zLine, ShellState *p){
if( rc ){
fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
sqlite3_errmsg(db));
sqlite3_free(sCtx.z);
xCloser(sCtx.in);
sqlite3_free(sCsv.z);
xCloser(sCsv.in);
return 1;
}
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
@@ -2840,7 +2734,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( rc ){
if (pStmt) sqlite3_finalize(pStmt);
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
xCloser(sCtx.in);
xCloser(sCsv.in);
return 1;
}
nCol = sqlite3_column_count(pStmt);
@@ -2850,7 +2744,7 @@ static int do_meta_command(char *zLine, ShellState *p){
zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 );
if( zSql==0 ){
fprintf(stderr, "Error: out of memory\n");
xCloser(sCtx.in);
xCloser(sCsv.in);
return 1;
}
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
@@ -2866,56 +2760,46 @@ static int do_meta_command(char *zLine, ShellState *p){
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
if (pStmt) sqlite3_finalize(pStmt);
xCloser(sCtx.in);
xCloser(sCsv.in);
return 1;
}
needCommit = sqlite3_get_autocommit(db);
if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
do{
int startLine = sCtx.nLine;
int startLine = sCsv.nLine;
for(i=0; i<nCol; i++){
char *z = xRead(&sCtx);
/*
** Did we reach end-of-file before finding any columns?
** If so, stop instead of NULL filling the remaining columns.
*/
char *z = csv_read_one_field(&sCsv);
if( z==0 && i==0 ) break;
/*
** Did we reach end-of-file OR end-of-line before finding any
** columns in ASCII mode? If so, stop instead of NULL filling
** the remaining columns.
*/
if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){
fprintf(stderr, "%s:%d: expected %d columns but found %d - "
"filling the rest with NULL\n",
sCtx.zFile, startLine, nCol, i+1);
sCsv.zFile, startLine, nCol, i+1);
i++;
while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
}
}
if( sCtx.cTerm==sCtx.cColSep ){
if( sCsv.cTerm==sCsv.cSeparator ){
do{
xRead(&sCtx);
csv_read_one_field(&sCsv);
i++;
}while( sCtx.cTerm==sCtx.cColSep );
}while( sCsv.cTerm==sCsv.cSeparator );
fprintf(stderr, "%s:%d: expected %d columns but found %d - "
"extras ignored\n",
sCtx.zFile, startLine, nCol, i);
sCsv.zFile, startLine, nCol, i);
}
if( i>=nCol ){
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
if( rc!=SQLITE_OK ){
fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine,
fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCsv.zFile, startLine,
sqlite3_errmsg(db));
}
}
}while( sCtx.cTerm!=EOF );
}while( sCsv.cTerm!=EOF );
xCloser(sCtx.in);
sqlite3_free(sCtx.z);
xCloser(sCsv.in);
sqlite3_free(sCsv.z);
sqlite3_finalize(pStmt);
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
}else
@@ -3033,32 +2917,28 @@ static int do_meta_command(char *zLine, ShellState *p){
p->mode = MODE_Html;
}else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
p->mode = MODE_Tcl;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
p->mode = MODE_Csv;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
sqlite3_snprintf(sizeof(p->newline), p->newline, "\r\n");
}else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
p->mode = MODE_List;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
}else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
p->mode = MODE_Insert;
set_table_name(p, nArg>=3 ? azArg[2] : "table");
}else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
p->mode = MODE_Ascii;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
}else {
fprintf(stderr,"Error: mode should be one of: "
"ascii column csv html insert line list tabs tcl\n");
"column csv html insert line list tabs tcl\n");
rc = 1;
}
}else
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
if( nArg==2 ){
sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
"%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
"%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
}else{
fprintf(stderr, "Usage: .nullvalue STRING\n");
rc = 1;
@@ -3343,16 +3223,14 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
if( nArg<2 || nArg>3 ){
fprintf(stderr, "Usage: .separator COL ?ROW?\n");
fprintf(stderr, "Usage: .separator SEPARATOR ?NEWLINE?\n");
rc = 1;
}
if( nArg>=2 ){
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
"%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
sqlite3_snprintf(sizeof(p->separator), p->separator, azArg[1]);
}
if( nArg>=3 ){
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
"%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
sqlite3_snprintf(sizeof(p->newline), p->newline, azArg[2]);
}
}else
@@ -3383,24 +3261,23 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
goto meta_command_exit;
}
fprintf(p->out,"%12.12s: %s\n","echo", p->echoOn ? "on" : "off");
fprintf(p->out,"%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off");
fprintf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off");
fprintf(p->out,"%12.12s: %s\n","mode", modeDescr[p->mode]);
fprintf(p->out,"%12.12s: ", "nullvalue");
output_c_string(p->out, p->nullValue);
fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
fprintf(p->out,"%9.9s: ", "nullvalue");
output_c_string(p->out, p->nullvalue);
fprintf(p->out, "\n");
fprintf(p->out,"%12.12s: %s\n","output",
fprintf(p->out,"%9.9s: %s\n","output",
strlen30(p->outfile) ? p->outfile : "stdout");
fprintf(p->out,"%12.12s: ", "colseparator");
output_c_string(p->out, p->colSeparator);
fprintf(p->out,"%9.9s: ", "separator");
output_c_string(p->out, p->separator);
fprintf(p->out," ");
output_c_string(p->out, p->newline);
fprintf(p->out, "\n");
fprintf(p->out,"%12.12s: ", "rowseparator");
output_c_string(p->out, p->rowSeparator);
fprintf(p->out, "\n");
fprintf(p->out,"%12.12s: %s\n","stats", p->statsOn ? "on" : "off");
fprintf(p->out,"%12.12s: ","width");
fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
fprintf(p->out,"%9.9s: ","width");
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
fprintf(p->out,"%d ",p->colWidth[i]);
}
@@ -4061,7 +3938,6 @@ static int process_sqliterc(
** Show available command line options
*/
static const char zOptions[] =
" -ascii set output mode to 'ascii'\n"
" -bail stop after hitting an error\n"
" -batch force batch I/O\n"
" -column set output mode to 'column'\n"
@@ -4083,11 +3959,11 @@ static const char zOptions[] =
#ifdef SQLITE_ENABLE_MULTIPLEX
" -multiplex enable the multiplexor VFS\n"
#endif
" -newline SEP set output row separator. Default: '\\n'\n"
" -newline SEP set newline character(s) for CSV\n"
" -nullvalue TEXT set text string for NULL values. Default ''\n"
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
" -scratch SIZE N use N slots of SZ bytes each for scratch memory\n"
" -separator SEP set output column separator. Default: '|'\n"
" -separator SEP set output field separator. Default: '|'\n"
" -stats print memory stats before each finalize\n"
" -version show SQLite version\n"
" -vfs NAME use NAME as the default VFS\n"
@@ -4114,8 +3990,8 @@ static void usage(int showDetail){
static void main_init(ShellState *data) {
memset(data, 0, sizeof(*data));
data->mode = MODE_List;
memcpy(data->colSeparator,SEP_Column, 2);
memcpy(data->rowSeparator,SEP_Row, 2);
memcpy(data->separator,"|", 2);
memcpy(data->newline,"\r\n", 3);
data->showHeader = 0;
data->shellFlgs = SHFLG_Lookaside;
sqlite3_config(SQLITE_CONFIG_URI, 1);
@@ -4354,21 +4230,15 @@ int main(int argc, char **argv){
data.mode = MODE_Column;
}else if( strcmp(z,"-csv")==0 ){
data.mode = MODE_Csv;
memcpy(data.colSeparator,",",2);
}else if( strcmp(z,"-ascii")==0 ){
data.mode = MODE_Ascii;
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
SEP_Unit);
sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
SEP_Record);
memcpy(data.separator,",",2);
}else if( strcmp(z,"-separator")==0 ){
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
sqlite3_snprintf(sizeof(data.separator), data.separator,
"%s",cmdline_option_value(argc,argv,++i));
}else if( strcmp(z,"-newline")==0 ){
sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
sqlite3_snprintf(sizeof(data.newline), data.newline,
"%s",cmdline_option_value(argc,argv,++i));
}else if( strcmp(z,"-nullvalue")==0 ){
sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
"%s",cmdline_option_value(argc,argv,++i));
}else if( strcmp(z,"-header")==0 ){
data.showHeader = 1;
@@ -4488,7 +4358,7 @@ int main(int argc, char **argv){
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
}
}
#if HAVE_READLINE
#if defined(HAVE_READLINE)
if( zHistory ) read_history(zHistory);
#endif
rc = process_input(&data, 0);
+29 -51
View File
@@ -196,7 +196,7 @@ const char *sqlite3_compileoption_get(int N);
** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
** can be fully or partially disabled using a call to [sqlite3_config()]
** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the
** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the
** sqlite3_threadsafe() function shows only the compile-time setting of
** thread safety, not any run-time changes to that setting made by
** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
@@ -1565,7 +1565,7 @@ struct sqlite3_mem_methods {
** 8-byte aligned
** memory, the size of each page buffer (sz), and the number of pages (N).
** The sz argument should be the size of the largest database page
** (a power of two between 512 and 65536) plus some extra bytes for each
** (a power of two between 512 and 32768) plus some extra bytes for each
** page header. ^The number of extra bytes needed by the page header
** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
** to [sqlite3_config()].
@@ -1745,17 +1745,6 @@ struct sqlite3_mem_methods {
** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
** The amount of extra space required can change depending on the compiler,
** target platform, and SQLite version.
**
** [[SQLITE_CONFIG_PMASZ]]
** <dt>SQLITE_CONFIG_PMASZ
** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which
** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded
** sorter to that integer. The default minimum PMA Size is set by the
** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched
** to help with sort operations when multithreaded sorting
** is enabled (using the [PRAGMA threads] command) and the amount of content
** to be sorted exceeds the page size times the minimum of the
** [PRAGMA cache_size] setting and this value.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -1782,7 +1771,6 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -5164,27 +5152,20 @@ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
/*
** CAPI3REF: Extract Metadata About A Column Of A Table
**
** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
** information about column C of table T in database D
** on [database connection] X.)^ ^The sqlite3_table_column_metadata()
** interface returns SQLITE_OK and fills in the non-NULL pointers in
** the final five arguments with appropriate values if the specified
** column exists. ^The sqlite3_table_column_metadata() interface returns
** SQLITE_ERROR and if the specified column does not exist.
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
** NULL pointer, then this routine simply checks for the existance of the
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
** does not.
** ^This routine returns metadata about a specific column of a specific
** database table accessible using the [database connection] handle
** passed as the first function argument.
**
** ^The column is identified by the second, third and fourth parameters to
** this function. ^(The second parameter is either the name of the database
** this function. ^The second parameter is either the name of the database
** (i.e. "main", "temp", or an attached database) containing the specified
** table or NULL.)^ ^If it is NULL, then all attached databases are searched
** table or NULL. ^If it is NULL, then all attached databases are searched
** for the table using the same algorithm used by the database engine to
** resolve unqualified table references.
**
** ^The third and fourth parameters to this function are the table and column
** name of the desired column, respectively.
** name of the desired column, respectively. Neither of these parameters
** may be NULL.
**
** ^Metadata is returned by writing to the memory locations passed as the 5th
** and subsequent parameters to this function. ^Any of these arguments may be
@@ -5203,17 +5184,16 @@ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** </blockquote>)^
**
** ^The memory pointed to by the character pointers returned for the
** declaration type and collation sequence is valid until the next
** declaration type and collation sequence is valid only until the next
** call to any SQLite API function.
**
** ^If the specified table is actually a view, an [error code] is returned.
**
** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
** is not a [WITHOUT ROWID] table and an
** ^If the specified column is "rowid", "oid" or "_rowid_" and an
** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
** parameters are set for the explicitly declared column. ^(If there is no
** [INTEGER PRIMARY KEY] column, then the outputs
** for the [rowid] are set as follows:
** explicitly declared [INTEGER PRIMARY KEY] column, then the output
** parameters are set as follows:
**
** <pre>
** data type: "INTEGER"
@@ -5223,9 +5203,13 @@ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** auto increment: 0
** </pre>)^
**
** ^This function causes all database schemas to be read from disk and
** parsed, if that has not already been done, and returns an error if
** any errors are encountered while loading the schema.
** ^(This function may load one or more schemas from database files. If an
** error occurs during this process, or if the requested table or column
** cannot be found, an [error code] is returned and an error message left
** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^
**
** ^This API is only available if the library was compiled with the
** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
*/
int sqlite3_table_column_metadata(
sqlite3 *db, /* Connection handle */
@@ -7192,10 +7176,12 @@ void sqlite3_log(int iErrCode, const char *zFormat, ...);
** CAPI3REF: Write-Ahead Log Commit Hook
**
** ^The [sqlite3_wal_hook()] function is used to register a callback that
** is invoked each time data is committed to a database in wal mode.
** will be invoked each time a database connection commits data to a
** [write-ahead log] (i.e. whenever a transaction is committed in
** [journal_mode | journal_mode=WAL mode]).
**
** ^(The callback is invoked by SQLite after the commit has taken place and
** the associated write-lock on the database released)^, so the implementation
** ^The callback is invoked by SQLite after the commit has taken place and
** the associated write-lock on the database released, so the implementation
** may read, write or [checkpoint] the database as required.
**
** ^The first parameter passed to the callback function when it is invoked
@@ -7486,10 +7472,6 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a
** different metric for sqlite3_stmt_scanstatus() to return.
**
** When the value returned to V is a string, space to hold that string is
** managed by the prepared statement S and will be automatically freed when
** S is finalized.
**
** <dl>
** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be
@@ -7535,14 +7517,7 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Prepared Statement Scan Status
**
** This interface returns information about the predicted and measured
** performance for pStmt. Advanced applications can use this
** interface to compare the predicted and the measured performance and
** issue warnings and/or rerun [ANALYZE] if discrepancies are found.
**
** Since this interface is expected to be rarely used, it is only
** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS]
** compile-time option.
** Return status data for a single loop within query pStmt.
**
** The "iScanStatusOp" parameter determines which status information to return.
** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior
@@ -7560,6 +7535,9 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
** as if the loop did not exist - it returns non-zero and leave the variable
** that pOut points to unchanged.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
**
** See also: [sqlite3_stmt_scanstatus_reset()]
*/
SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
+7 -14
View File
@@ -15,14 +15,6 @@
#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
@@ -1067,7 +1059,6 @@ 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 */
@@ -1169,8 +1160,7 @@ struct sqlite3 {
/*
** A macro to discover the encoding of a database.
*/
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
#define ENC(db) ((db)->enc)
#define ENC(db) ((db)->aDb[0].pSchema->enc)
/*
** Possible values for the sqlite3.flags.
@@ -1794,6 +1784,7 @@ 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 */
@@ -2357,7 +2348,7 @@ struct Select {
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
#define SF_Compound 0x0040 /* Part of a compound query */
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
#define SF_AllValues 0x0100 /* All terms of compound are VALUES */
/* 0x0100 NOT USED */
#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 */
@@ -2847,7 +2838,6 @@ 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 */
@@ -2985,7 +2975,7 @@ int sqlite3CantopenError(int);
** 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 1
# define SQLITE_ENABLE_FTS3
#endif
/*
@@ -3463,6 +3453,9 @@ const char *sqlite3ErrName(int);
const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
#if defined(SQLITE_DEBUG)
int sqlite3ValidCollSeq(const CollSeq*);
#endif
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
+1 -1
View File
@@ -127,7 +127,7 @@ int sqlite3_get_table(
TabResult res;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT;
if( pazResult==0 ) return SQLITE_MISUSE_BKPT;
#endif
*pazResult = 0;
if( pnColumn ) *pnColumn = 0;
+3 -28
View File
@@ -25,14 +25,6 @@
** 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>
@@ -643,7 +635,6 @@ 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));
@@ -1093,10 +1084,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 = 0; /* Prepared statement object */
sqlite3_stmt *pStmt; /* Prepared statement object */
SqlPreparedStmt *pPreStmt; /* Pointer to cached statement */
int nSql; /* Length of zSql in bytes */
int nVar = 0; /* Number of variables in statement */
int nVar; /* Number of variables in statement */
int iParm = 0; /* Next free entry in apParm */
char c;
int i;
@@ -3110,7 +3101,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) ? TCL_OK : TCL_ERROR;
int rc = Tcl_InitStubs(interp, "8.4", 0)==0 ? TCL_ERROR : TCL_OK;
if( rc==TCL_OK ){
Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
#ifndef SQLITE_3_SUFFIX_ONLY
@@ -3821,11 +3812,6 @@ 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;
@@ -3839,17 +3825,6 @@ 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. */
+15 -116
View File
@@ -261,8 +261,6 @@ 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,
@@ -276,7 +274,6 @@ 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;
}
@@ -567,7 +564,7 @@ static int test_get_table_printf(
Tcl_DString str;
int rc;
char *zErr = 0;
int nRow = 0, nCol = 0;
int nRow, nCol;
char **aResult;
int i;
char zBuf[30];
@@ -1572,6 +1569,7 @@ 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 */
@@ -1591,14 +1589,14 @@ static int test_table_column_metadata(
int primarykey;
int autoincrement;
if( objc!=5 && objc!=4 ){
if( objc!=5 ){
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 = objc==5 ? Tcl_GetString(objv[4]) : 0;
zCol = Tcl_GetString(objv[4]);
if( strlen(zDb)==0 ) zDb = 0;
@@ -1620,6 +1618,7 @@ static int test_table_column_metadata(
return TCL_OK;
}
#endif
#ifndef SQLITE_OMIT_INCRBLOB
@@ -2120,7 +2119,7 @@ static int test_stmt_status(
Tcl_Obj *CONST objv[]
){
int iValue;
int i, op = 0, resetFlag;
int i, op, resetFlag;
const char *zOpName;
sqlite3_stmt *pStmt;
@@ -3098,7 +3097,7 @@ static int test_bind_double(
){
sqlite3_stmt *pStmt;
int idx;
double value = 0;
double value;
int rc;
const char *zVal;
int i;
@@ -3673,7 +3672,7 @@ static int test_prepare_v2(
assert(rc==SQLITE_OK || pStmt==0);
Tcl_ResetResult(interp);
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
if( rc==SQLITE_OK && zTail && objc>=5 ){
if( zTail && objc>=5 ){
if( bytes>=0 ){
bytes = bytes - (int)(zTail-zSql);
}
@@ -5458,7 +5457,7 @@ static int test_limit(
{ "SQLITE_LIMIT_TOOSMALL", -1, },
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
};
int i, id = 0;
int i, id;
int val;
const char *zId;
@@ -5705,18 +5704,15 @@ static int test_wal_checkpoint_v2(
if( objc==4 ){
zDb = Tcl_GetString(objv[3]);
}
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)
)){
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
|| 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 ){
const char *zErrCode = sqlite3ErrName(rc);
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
return TCL_ERROR;
}
@@ -5729,43 +5725,6 @@ 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?
*/
@@ -6607,65 +6566,6 @@ static int test_user_delete(
}
#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.
*/
@@ -6682,7 +6582,6 @@ 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;
@@ -6735,7 +6634,6 @@ 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 },
@@ -6878,7 +6776,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_reopen", test_blob_reopen, 0 },
#endif
@@ -6888,7 +6788,6 @@ 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 },
+1 -1
View File
@@ -310,7 +310,7 @@ static int page_get(
){
Pager *pPager;
char zBuf[100];
DbPage *pPage = 0;
DbPage *pPage;
int pgno;
int rc;
if( argc!=3 ){
+5 -5
View File
@@ -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){
u32 val = 0;
int val = 0;
int ii;
for(ii=0; zString[ii]; ii++){
val = (val << 3) + (int)zString[ii];
}
return (int)(val&0x7fffffff);
return val;
}
/*
@@ -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 = 0;
int nRow;
int useIdx = 0;
int rc = SQLITE_OK;
int useCost = 0;
double cost = 0;
double cost;
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 = 0;
sqlite3_stmt *pStmt;
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 */
+1 -1
View File
@@ -41,7 +41,7 @@
** procedures use this to determine when tests should be omitted.
*/
static void set_options(Tcl_Interp *interp){
#if HAVE_MALLOC_USABLE_SIZE
#ifdef HAVE_MALLOC_USABLE_SIZE
Tcl_SetVar2(interp, "sqlite_options", "malloc_usable_size", "1",
TCL_GLOBAL_ONLY);
#else
+2 -5
View File
@@ -409,9 +409,7 @@ static int openTransaction(jt_file *pMain, jt_file *pJournal){
if( iOff==PENDING_BYTE ) continue;
rc = sqlite3OsRead(pMain->pReal, aData, pMain->nPagesize, iOff);
pMain->aCksum[ii] = genCksum(aData, pMain->nPagesize);
if( ii+1==(int)pMain->nPage && rc==SQLITE_IOERR_SHORT_READ ){
rc = SQLITE_OK;
}
if( ii+1==pMain->nPage && rc==SQLITE_IOERR_SHORT_READ ) rc = SQLITE_OK;
}
}
@@ -552,8 +550,7 @@ static int jtWrite(
*/
}else{
u32 pgno = (u32)(iOfst/p->nPagesize + 1);
assert( (iAmt==1||iAmt==(int)p->nPagesize) &&
((iOfst+iAmt)%p->nPagesize)==0 );
assert( (iAmt==1||iAmt==p->nPagesize) && ((iOfst+iAmt)%p->nPagesize)==0 );
assert( pgno<=p->nPage || p->nSync>0 );
assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) );
}
+2 -31
View File
@@ -1260,34 +1260,6 @@ static int test_config_cis(
return TCL_OK;
}
/*
** Usage: sqlite3_config_pmasz INTEGER
**
** Set the minimum PMA size.
*/
static int test_config_pmasz(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
int rc;
int iPmaSz;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, objv[1], &iPmaSz) ){
return TCL_ERROR;
}
rc = sqlite3_config(SQLITE_CONFIG_PMASZ, iPmaSz);
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
return TCL_OK;
}
/*
** Usage: sqlite3_dump_memsys3 FILENAME
@@ -1338,7 +1310,7 @@ static int test_status(
Tcl_Obj *CONST objv[]
){
int rc, iValue, mxValue;
int i, op = 0, resetFlag;
int i, op, resetFlag;
const char *zOpName;
static const struct {
const char *zName;
@@ -1395,7 +1367,7 @@ static int test_db_status(
Tcl_Obj *CONST objv[]
){
int rc, iValue, mxValue;
int i, op = 0, resetFlag;
int i, op, resetFlag;
const char *zOpName;
sqlite3 *db;
extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
@@ -1542,7 +1514,6 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
{ "sqlite3_config_error", test_config_error ,0 },
{ "sqlite3_config_uri", test_config_uri ,0 },
{ "sqlite3_config_cis", test_config_cis ,0 },
{ "sqlite3_config_pmasz", test_config_pmasz ,0 },
{ "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
{ "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
{ "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
+2 -2
View File
@@ -406,7 +406,7 @@ static void multiplexControlFunc(
){
int rc = SQLITE_OK;
sqlite3 *db = sqlite3_context_db_handle(context);
int op = 0;
int op;
int iVal;
if( !db || argc!=2 ){
@@ -535,7 +535,7 @@ static int multiplexOpen(
/* assign pointers to extra space allocated */
memset(pGroup, 0, sz);
pMultiplexOpen->pGroup = pGroup;
pGroup->bEnabled = (unsigned char)-1;
pGroup->bEnabled = -1;
pGroup->bTruncate = sqlite3_uri_boolean(zUri, "truncate",
(flags & SQLITE_OPEN_MAIN_DB)==0);
pGroup->szChunk = (int)sqlite3_uri_int64(zUri, "chunksize",
+1 -1
View File
@@ -889,7 +889,7 @@ int sqlite3_quota_set(
** management, update its size.
*/
int sqlite3_quota_file(const char *zFilename){
char *zFull = 0;
char *zFull;
sqlite3_file *fd;
int rc;
int outFlags = 0;
+2 -2
View File
@@ -421,7 +421,7 @@ static int tvfsSync(sqlite3_file *pFile, int flags){
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
if( p->pScript && p->mask&TESTVFS_SYNC_MASK ){
char *zFlags = 0;
char *zFlags;
switch( flags ){
case SQLITE_SYNC_NORMAL:
@@ -1225,7 +1225,7 @@ static int testvfs_obj_cmd(
case CMD_CANTOPENERR:
case CMD_IOERR:
case CMD_FULLERR: {
TestFaultInject *pTest = 0;
TestFaultInject *pTest;
int iRet;
switch( aSubcmd[i].eCmd ){
-3
View File
@@ -26,9 +26,6 @@
** single-threaded if desired.
*/
#include "sqliteInt.h"
#if SQLITE_OS_WIN
# include "os_win.h"
#endif
#if SQLITE_MAX_WORKER_THREADS>0
-3
View File
@@ -391,9 +391,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
int mxSqlLen; /* Max length of an SQL string */
#ifdef SQLITE_ENABLE_API_ARMOR
if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT;
#endif
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
if( db->nVdbeActive==0 ){
db->u1.isInterrupted = 0;
+4 -4
View File
@@ -17,7 +17,7 @@
*/
#include "sqliteInt.h"
#include <stdarg.h>
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif
@@ -58,7 +58,7 @@ int sqlite3FaultSim(int iTest){
*/
int sqlite3IsNaN(double x){
int rc; /* The value return */
#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN
#if !defined(SQLITE_HAVE_ISNAN)
/*
** Systems that support the isnan() library function should probably
** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have
@@ -88,9 +88,9 @@ int sqlite3IsNaN(double x){
volatile double y = x;
volatile double z = y;
rc = (y!=z);
#else /* if HAVE_ISNAN */
#else /* if defined(SQLITE_HAVE_ISNAN) */
rc = isnan(x);
#endif /* HAVE_ISNAN */
#endif /* SQLITE_HAVE_ISNAN */
testcase( rc );
return rc;
}
+2 -2
View File
@@ -3823,8 +3823,8 @@ case OP_Found: { /* jump, in3 */
/* For the OP_NoConflict opcode, take the jump if any of the
** input fields are NULL, since any key with a NULL will not
** conflict */
for(ii=0; ii<pIdxKey->nField; ii++){
if( pIdxKey->aMem[ii].flags & MEM_Null ){
for(ii=0; ii<r.nField; ii++){
if( r.aMem[ii].flags & MEM_Null ){
pc = pOp->p2 - 1; VdbeBranchTaken(1,2);
break;
}
+2 -4
View File
@@ -400,10 +400,7 @@ static int doWalCallbacks(sqlite3 *db){
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
int nEntry;
sqlite3BtreeEnter(pBt);
nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
sqlite3BtreeLeave(pBt);
int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
}
@@ -583,6 +580,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
assert( zErr!=0 || db->mallocFailed );
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
+7 -7
View File
@@ -396,7 +396,6 @@ static Op *opIterNext(VdbeOpIter *p){
*/
int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
int hasAbort = 0;
int hasFkCounter = 0;
Op *pOp;
VdbeOpIter sIter;
memset(&sIter, 0, sizeof(sIter));
@@ -405,17 +404,15 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
#ifndef SQLITE_OMIT_FOREIGN_KEY
|| (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
#endif
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
){
hasAbort = 1;
break;
}
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
hasFkCounter = 1;
}
#endif
}
sqlite3DbFree(v->db, sIter.apSub);
@@ -424,7 +421,7 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
** through all opcodes and hasAbort may be set incorrectly. Return
** true for this case to prevent the assert() in the callers frame
** from failing. */
return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter );
return ( v->db->mallocFailed || hasAbort==mayAbort );
}
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
@@ -1057,6 +1054,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
CollSeq *pColl = pKeyInfo->aColl[j];
const char *zColl = pColl ? pColl->zName : "nil";
int n = sqlite3Strlen30(zColl);
assert( pColl==0 || sqlite3ValidCollSeq(pColl) );
if( n==6 && memcmp(zColl,"BINARY",6)==0 ){
zColl = "B";
n = 1;
@@ -3361,6 +3359,7 @@ static int vdbeCompareMemString(
const CollSeq *pColl,
u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */
){
assert( sqlite3ValidCollSeq(pColl) );
if( pMem1->enc==pColl->enc ){
/* The strings are already in the correct encoding. Call the
** comparison function directly */
@@ -3476,6 +3475,7 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
assert( !pColl || pColl->xCmp );
if( pColl ){
assert( sqlite3ValidCollSeq(pColl) );
return vdbeCompareMemString(pMem1, pMem2, pColl, 0);
}
/* If a NULL pointer was passed as the collate function, fall through
+13 -12
View File
@@ -152,7 +152,7 @@
** to a level 0 PMA. The purpose of this limit is to prevent various integer
** overflows. 512MiB.
*/
#define SQLITE_MAX_PMASZ (1<<29)
#define SQLITE_MAX_MXPMASIZE (1<<29)
/*
** Private objects used by the sorter
@@ -448,6 +448,9 @@ struct SorterRecord {
*/
#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1))
/* The minimum PMA size is set to this value multiplied by the database
** page size in bytes. */
#define SORTER_MIN_WORKING 10
/* Maximum number of PMAs that a single MergeEngine can merge */
#define SORTER_MAX_MERGE_COUNT 16
@@ -846,11 +849,10 @@ int sqlite3VdbeSorterInit(
}
if( !sqlite3TempInMemory(db) ){
u32 szPma = sqlite3GlobalConfig.szPma;
pSorter->mnPmaSize = szPma * pgsz;
pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
mxCache = db->aDb[0].pSchema->cache_size;
if( mxCache<(int)szPma ) mxCache = (int)szPma;
pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);
if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_MXPMASIZE);
/* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
@@ -1128,12 +1130,12 @@ void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
*/
static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
void *p = 0;
int chunksize = 4*1024;
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
sqlite3OsFetch(pFd, 0, (int)nByte, &p);
sqlite3OsUnfetch(pFd, 0, p);
int rc = sqlite3OsTruncate(pFd, nByte);
if( rc==SQLITE_OK ){
void *p = 0;
sqlite3OsFetch(pFd, 0, (int)nByte, &p);
sqlite3OsUnfetch(pFd, 0, p);
}
}
}
#else
@@ -2414,7 +2416,6 @@ int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
}else
#endif
/*if( !pSorter->bUseThreads )*/ {
assert( pSorter->pMerger!=0 );
assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) );
rc = vdbeMergeEngineStep(pSorter->pMerger, pbEof);
}
+1 -1
View File
@@ -2412,7 +2412,7 @@ int sqlite3WalFindFrame(
for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
u32 iFrame = aHash[iKey] + iZero;
if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){
assert( iFrame>iRead || CORRUPT_DB );
/* assert( iFrame>iRead ); -- not true if there is corruption */
iRead = iFrame;
}
if( (nCollide--)==0 ){
+2 -2
View File
@@ -222,7 +222,6 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
sqlite3DbFree(db, pOld);
}
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm));
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( p && ExprHasProperty(p, EP_Unlikely) ){
@@ -2948,7 +2947,7 @@ static void addScanStatus(
){
const char *zObj = 0;
WhereLoop *pLoop = pLvl->pWLoop;
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){
if( (pLoop->wsFlags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
zObj = pLoop->u.btree.pIndex->zName;
}else{
zObj = pSrclist->a[pLvl->iFrom].zName;
@@ -3941,6 +3940,7 @@ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
p->u.vtab.idxStr = 0;
}else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo);
sqlite3DbFree(db, p->u.btree.pIndex);
p->u.btree.pIndex = 0;
}
+2 -9
View File
@@ -20,15 +20,6 @@ set testprefix bigsort
# loop if the product was also an integer multiple of 2^32, or
# inefficiency otherwise.
#
# This test causes thrashing on machines with smaller amounts of
# memory. Make sure the host has at least 8GB available before running
# this test.
#
if {[catch {exec free | grep Mem:} out] || [lindex $out 1]<8000000} {
finish_test
return
}
do_execsql_test 1.0 {
PRAGMA page_size = 1024;
CREATE TABLE t1(a, b);
@@ -48,3 +39,5 @@ do_execsql_test 1.1 {
finish_test
+12 -28
View File
@@ -17,14 +17,17 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !columnmetadata {
finish_test
return
}
# Set up a schema in the main and temp test databases.
do_test colmeta-0 {
execsql {
CREATE TABLE abc(a, b, c);
CREATE TABLE abc2(a PRIMARY KEY COLLATE NOCASE, b VARCHAR(32), c);
CREATE TABLE abc3(a NOT NULL, b INTEGER PRIMARY KEY, c);
CREATE TABLE abc5(w,x,y,z,PRIMARY KEY(x,z)) WITHOUT ROWID;
CREATE TABLE abc6(rowid TEXT COLLATE rtrim, oid REAL, _rowid_ BLOB);
}
ifcapable autoinc {
execsql {
@@ -54,27 +57,19 @@ set tests {
13 {main abc rowid} {0 {INTEGER BINARY 0 1 0}}
14 {main abc3 rowid} {0 {INTEGER BINARY 0 1 0}}
16 {main abc d} {1 {no such table column: abc.d}}
20 {main abc5 w} {0 {{} BINARY 0 0 0}}
21 {main abc5 x} {0 {{} BINARY 1 1 0}}
22 {main abc5 y} {0 {{} BINARY 0 0 0}}
23 {main abc5 z} {0 {{} BINARY 1 1 0}}
24 {main abc5 rowid} {1 {no such table column: abc5.rowid}}
30 {main abc6 rowid} {0 {TEXT rtrim 0 0 0}}
31 {main abc6 oid} {0 {REAL BINARY 0 0 0}}
32 {main abc6 _rowid_} {0 {BLOB BINARY 0 0 0}}
}
ifcapable autoinc {
ifcapable view {
set tests [concat $tests {
100 {{} abc4 b} {0 {INTEGER BINARY 0 1 1}}
101 {main abc4 rowid} {0 {INTEGER BINARY 0 1 1}}
8 {{} abc4 b} {0 {INTEGER BINARY 0 1 1}}
15 {main abc4 rowid} {0 {INTEGER BINARY 0 1 1}}
}]
}
ifcapable view {
set tests [concat $tests {
200 {{} v1 a} {1 {no such table column: v1.a}}
201 {main v1 b} {1 {no such table column: v1.b}}
202 {main v1 badname} {1 {no such table column: v1.badname}}
203 {main v1 rowid} {1 {no such table column: v1.rowid}}
9 {{} v1 a} {1 {no such table column: v1.a}}
10 {main v1 b} {1 {no such table column: v1.b}}
11 {main v1 badname} {1 {no such table column: v1.badname}}
12 {main v1 rowid} {1 {no such table column: v1.rowid}}
}]
}
@@ -96,15 +91,4 @@ foreach {tn params results} $tests {
} $results
}
# Calling sqlite3_table_column_metadata with a NULL column name merely
# checks for the existance of the table.
#
do_test colmeta-300 {
catch {sqlite3_table_column_metadata $::DB main xyzzy} res
} {1}
do_test colmeta-301 {
catch {sqlite3_table_column_metadata $::DB main abc} res
} {0}
finish_test
-202
View File
@@ -1,202 +0,0 @@
# 2014 December 04
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/wal_common.tcl
set testprefix e_walauto
proc read_nbackfill {} {
seek $::shmfd 96
binary scan [read $::shmfd 4] i nBackfill
set nBackfill
}
proc read_mxframe {} {
seek $::shmfd 16
binary scan [read $::shmfd 4] i mxFrame
set mxFrame
}
# Assuming that the main db for database handle
#
proc do_autocommit_threshold_test {tn value} {
set nBackfillSaved [read_nbackfill]
while {1} {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
if {[read_mxframe] >= $value} break
}
set nBackfillNew [read_nbackfill]
uplevel [list do_test $tn "expr $nBackfillNew > $nBackfillSaved" 1]
}
# EVIDENCE-OF: R-30135-06439 The wal_autocheckpoint pragma can be used
# to invoke this interface from SQL.
#
# All tests in this file are run twice - once using the
# sqlite3_wal_autocheckpoint() API, and once using "PRAGMA
# wal_autocheckpoint".
#
foreach {tn code} {
1 {
proc autocheckpoint {db value} {
uplevel [list $db eval "PRAGMA wal_autocheckpoint = $value"]
}
}
2 {
proc autocheckpoint {db value} {
uplevel [list sqlite3_wal_autocheckpoint $db $value]
return $value
}
}
} {
eval $code
reset_db
execsql { PRAGMA auto_vacuum = 0 }
do_execsql_test 1.$tn.0 { PRAGMA journal_mode = WAL } {wal}
do_execsql_test 1.$tn.1 { CREATE TABLE t1(a, b) }
set shmfd [open "test.db-shm" rb]
# EVIDENCE-OF: R-41531-51083 Every new database connection defaults to
# having the auto-checkpoint enabled with a threshold of 1000 or
# SQLITE_DEFAULT_WAL_AUTOCHECKPOINT pages.
#
do_autocommit_threshold_test 1.$tn.2 1000
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
do_autocommit_threshold_test 1.$tn.3 1000
# EVIDENCE-OF: R-38128-34102 The sqlite3_wal_autocheckpoint(D,N) is a
# wrapper around sqlite3_wal_hook() that causes any database on database
# connection D to automatically checkpoint after committing a
# transaction if there are N or more frames in the write-ahead log file.
#
do_test 1.$tn.4 {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
autocheckpoint db 100
} {100}
do_autocommit_threshold_test 1.$tn.5 100
do_test 1.$tn.6 {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
autocheckpoint db 500
} {500}
do_autocommit_threshold_test 1.$tn.7 500
# EVIDENCE-OF: R-26993-43540 Passing zero or a negative value as the
# nFrame parameter disables automatic checkpoints entirely.
#
do_test 1.$tn.7 {
autocheckpoint db 0 ;# Set to zero
for {set i 0} {$i < 10000} {incr i} {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
}
expr {[file size test.db-wal] > (5 * 1024 * 1024)}
} 1
do_test 1.$tn.8 {
sqlite3_wal_checkpoint_v2 db truncate
file size test.db-wal
} 0
do_test 1.$tn.9 {
autocheckpoint db -4 ;# Set to a negative value
for {set i 0} {$i < 10000} {incr i} {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
}
expr {[file size test.db-wal] > (5 * 1024 * 1024)}
} 1
# EVIDENCE-OF: R-10203-42688 The callback registered by this function
# replaces any existing callback registered using sqlite3_wal_hook().
#
set ::wal_hook_callback 0
proc wal_hook_callback {args} { incr ::wal_hook_callback ; return 0 }
do_test 1.$tn.10.1 {
db wal_hook wal_hook_callback
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
set ::wal_hook_callback
} 2
do_test 1.$tn.10.2 {
autocheckpoint db 100
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
set ::wal_hook_callback
} 2
# EVIDENCE-OF: R-17497-43474 Likewise, registering a callback using
# sqlite3_wal_hook() disables the automatic checkpoint mechanism
# configured by this function.
do_test 1.$tn.11.1 {
sqlite3_wal_checkpoint_v2 db truncate
file size test.db-wal
} 0
do_test 1.$tn.11.2 {
autocheckpoint db 100
for {set i 0} {$i < 1000} {incr i} {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
}
expr {[file size test.db-wal] < (1 * 1024 * 1024)}
} 1
do_test 1.$tn.11.3 {
db wal_hook wal_hook_callback
for {set i 0} {$i < 1000} {incr i} {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
}
expr {[file size test.db-wal] < (1 * 1024 * 1024)}
} 0
# EVIDENCE-OF: R-33080-59193 Checkpoints initiated by this mechanism
# are PASSIVE.
#
set ::busy_callback_count 0
proc busy_callback {args} {
puts Hello
incr ::busy_callback_count
return 0
}
do_test 1.$tn.12.1 {
sqlite3_wal_checkpoint_v2 db truncate
autocheckpoint db 100
db busy busy_callback
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
} {}
do_test 1.$tn.12.2 {
sqlite3 db2 test.db
db2 eval { BEGIN; SELECT * FROM t1 LIMIT 10; }
read_nbackfill
} {0}
do_test 1.$tn.12.3 {
for {set i 0} {$i < 1000} {incr i} {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
}
read_nbackfill
} {2}
do_test 1.$tn.12.4 {
set ::busy_callback_count
} {0}
db2 close
do_test 1.$tn.12.5 {
db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
read_nbackfill
} {1559}
db close
close $shmfd
}
finish_test
-754
View File
@@ -1,754 +0,0 @@
# 2014 December 04
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
set testprefix e_walckpt
# The following two commands are used to determine if any of the files
# "test.db", "test.db2" and "test.db3" are modified by a test case.
#
# The [save_db_hashes] command saves a hash of the current contents of
# all three files in global variables. The [compare_db_hashes] compares
# the current contents with the saved hashes and returns a list of the
# files that have changed.
#
proc save_db_hashes {} {
global H
foreach f {test.db test.db2 test.db3} {
set H($f) 0
catch { set H($f) [md5file $f] }
}
}
proc compare_db_hashes {} {
global H
set ret [list]
foreach f {test.db test.db2 test.db3} {
set expect 0
catch { set expect [md5file $f] }
if {$H($f) != $expect} { lappend ret $f }
}
set ret
}
#-------------------------------------------------------------------------
# All calls to the [sqlite3_wal_checkpoint_v2] command made within this
# file use this wrapper. It's sole purpose is to throw an error if the
# following requirement is violated:
#
# EVIDENCE-OF: R-60567-47780 Unless it returns SQLITE_MISUSE, the
# sqlite3_wal_checkpoint_v2() interface sets the error information that
# is queried by sqlite3_errcode() and sqlite3_errmsg().
#
proc wal_checkpoint_v2 {db args} {
set rc [catch {
uplevel sqlite3_wal_checkpoint_v2 $db $args
} msg]
set errcode "SQLITE_OK"
if {$rc} {
set errcode [lindex [split $msg " "] 0]
} elseif { [lindex $msg 0] } {
set errcode "SQLITE_BUSY"
}
if {$errcode != "SQLITE_MISUSE" && [sqlite3_errcode $db] != $errcode} {
error "sqlite3_errcode mismatch! (1) $errcode!=[sqlite3_errcode $db]"
}
if {$rc==0} {
return $msg
} else {
error $msg
}
}
# The following tests are run 3 times, each using a different method of
# invoking a checkpoint:
#
# 1) Using sqlite3_wal_checkpoint_v2()
# 2) Using "PRAGMA wal_checkpoint"
# 3) Using sqlite3_wal_checkpoint() in place of checkpoint_v2(PASSIVE)
#
# Cases (2) and (3) are to show that the following statements are
# correct, respectively:
#
# EVIDENCE-OF: R-36706-10507 The PRAGMA wal_checkpoint command can be
# used to invoke this interface from SQL.
#
# EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is
# equivalent to
# sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0).
#
foreach {tn script} {
1 {
proc checkpoint {db mode args} {
eval wal_checkpoint_v2 [list $db] [list $mode] $args
}
}
2 {
proc checkpoint {db mode args} {
set sql "PRAGMA wal_checkpoint = $mode"
if {[llength $args] && [lindex $args 0]!=""} {
set sql "PRAGMA [lindex $args 0].wal_checkpoint = $mode"
}
set rc [catch { $db eval $sql } msg]
if {$rc} {
regsub {database} $msg {database:} msg
error "[sqlite3_errcode $db] - $msg"
}
set msg
}
}
3 {
proc checkpoint {db mode args} {
if {$mode == "passive"} {
set rc [eval sqlite3_wal_checkpoint [list $db] $args]
if {$rc != "SQLITE_OK"} {
error "$rc - [sqlite3_errmsg $db]"
}
} else {
eval wal_checkpoint_v2 [list $db] [list $mode] $args
}
}
}
} {
eval $script
reset_db
forcedelete test.db2 test.db3 test.db4
execsql {
ATTACH 'test.db2' AS aux;
ATTACH 'test.db3' AS aux2;
ATTACH 'test.db4' AS aux3;
CREATE TABLE t1(x);
CREATE TABLE aux.t2(x);
CREATE TABLE aux2.t3(x);
CREATE TABLE aux3.t4(x);
PRAGMA main.journal_mode = WAL;
PRAGMA aux.journal_mode = WAL;
PRAGMA aux2.journal_mode = WAL;
/* Leave aux4 in rollback mode */
}
# EVIDENCE-OF: R-49787-09095 The sqlite3_wal_checkpoint_v2(D,X,M,L,C)
# interface runs a checkpoint operation on database X of database
# connection D in mode M. Status information is written back into
# integers pointed to by L and C.
#
# Tests 1, 2 and 3 below verify the "on database X" part of the
# above. Other parts of this requirement are tested below.
#
# EVIDENCE-OF: R-00653-06026 If parameter zDb is NULL or points to a
# zero length string, then the specified operation is attempted on all
# WAL databases attached to database connection db.
#
# Tests 4 and 5 below test this.
#
foreach {tn2 zDb dblist} {
1 main test.db
2 aux test.db2
3 aux2 test.db3
4 "" {test.db test.db2 test.db3}
5 - {test.db test.db2 test.db3}
6 temp {}
} {
do_test $tn.1.$tn2 {
execsql {
INSERT INTO t1 VALUES(1);
INSERT INTO t2 VALUES(2);
INSERT INTO t3 VALUES(3);
}
save_db_hashes
if {$zDb == "-"} {
checkpoint db passive
} else {
checkpoint db passive $zDb
}
compare_db_hashes
} $dblist
}
# EVIDENCE-OF: R-38207-48996 If zDb is not NULL (or a zero length
# string) and is not the name of any attached database, SQLITE_ERROR is
# returned to the caller.
do_test $tn.2.1 {
list [catch { checkpoint db passive notadb } msg] $msg
} {1 {SQLITE_ERROR - unknown database: notadb}}
# EVIDENCE-OF: R-14303-42483 If database zDb is the name of an attached
# database that is not in WAL mode, SQLITE_OK is returned and both
# *pnLog and *pnCkpt set to -1.
#
if {$tn==3} {
# With sqlite3_wal_checkpoint() the two output variables cannot be
# tested. So just test that no error is returned when attempting to
# checkpoint a db in rollback mode.
do_test $tn.2.2.a { checkpoint db passive aux3 } {}
} else {
do_test $tn.2.2.b { checkpoint db passive aux3 } {0 -1 -1}
}
# EVIDENCE-OF: R-62028-47212 All calls obtain an exclusive "checkpoint"
# lock on the database file.
db close
testvfs tvfs
tvfs filter xShmLock
tvfs script filelock
proc filelock {method file handle details} {
# Test for an exclusive checkpoint lock. A checkpoint lock locks a
# single byte starting at offset 1.
if {$details == "1 1 lock exclusive"} { set ::seen_checkpoint_lock 1 }
}
sqlite3 db test.db -vfs tvfs
do_test $tn.3.1 {
execsql { INSERT INTO t1 VALUES('xyz') }
unset -nocomplain ::seen_checkpoint_lock
checkpoint db passive
set ::seen_checkpoint_lock
} {1}
db close
tvfs delete
reset_db
#-----------------------------------------------------------------------
# EVIDENCE-OF: R-10421-19736 If any other process is running a
# checkpoint operation at the same time, the lock cannot be obtained and
# SQLITE_BUSY is returned.
#
# EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
# it will not be invoked in this case.
#
testvfs tvfs
tvfs filter xWrite
sqlite3 db test.db -vfs tvfs
sqlite3 db2 test.db -vfs tvfs
do_test $tn.3.2.1 {
db2 eval {
PRAGMA auto_vacuum = 0;
PRAGMA journal_mode = WAL;
CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES(1,2);
INSERT INTO t1 VALUES(3,4);
INSERT INTO t1 VALUES(5,6);
}
file size test.db-wal
} [wal_file_size 5 1024]
# Connection [db] runs a checkpoint. During this checkpoint, each
# time it calls xWrite() to write a page into the database file, we
# attempt to start a checkpoint using [db2]. According to the
# first requirement being tested, this should return SQLITE_BUSY. According
# to the second, the busy-handler belonging to [db2] should not be
# invoked.
#
set ::write_count 0
set ::write_errors [list]
proc busy_callback {args} {
lappend ::write_errors "busy handler called!"
}
proc write_callback {args} {
set rc [catch {checkpoint db2 passive} msg]
if {0==[regexp "database is locked" $msg] && $msg!="1 -1 -1"} {
lappend ::write_errors "$rc $msg"
}
incr ::write_count
}
db2 busy busy_callback
tvfs script write_callback
do_test $tn.3.2.2 {
db eval {SELECT * FROM sqlite_master}
checkpoint db full
set ::write_count
} {2}
do_test $tn.3.2.3 {
set ::write_errors
} {}
db close
db2 close
tvfs delete
proc busy_handler {mode busy_handler_mode n} {
incr ::busy_handler_counter
switch -- $busy_handler_mode {
1 {
# Do nothing. Do not block.
return 1
}
2 {
# Close first the reader, then later the writer. Give up before
# closing the [db6] reader.
if {$n==5} { catch {db2 eval commit} }
if {$n==10} { catch {db3 eval commit} }
if {$n==15} { return 1 }
return 0
}
3 {
# Close first the writer, then later the reader. And finally the
# [db6] reader.
if {$n==5} { catch {db2 eval commit} }
if {$n==10} { catch {db3 eval commit} }
if {$n==15} { catch {db6 eval commit} }
return 0
}
}
}
foreach {mode busy_handler_mode} {
passive 1
full 1 full 2 full 3
restart 1 restart 2 restart 3
truncate 1 truncate 2 truncate 3
} {
set tp "$tn.$mode.$busy_handler_mode"
set ::sync_counter 0
# Set up a callback function for xSync and xWrite calls made during
# the checkpoint.
#
set ::checkpoint_ongoing 0
proc tvfs_callback {method args} {
if {$::checkpoint_ongoing==0} return
set tail [file tail [lindex $args 0]]
if {$method == "xSync" && $tail == "test.db"} {
incr ::sync_counter
}
if {$method == "xWrite" && $tail=="test.db"} {
if {$::write_ok < 0} {
set ::write_ok [expr ![catch {db5 eval { BEGIN IMMEDIATE }}]]
catch { db5 eval ROLLBACK }
}
if {$::read_ok < 0} {
set ::read_ok [expr ![catch {db5 eval { SELECT * FROM t1 }}]]
}
# If one has not already been opened, open a read-transaction using
# connection [db6]
catch { db6 eval { BEGIN ; SELECT * FROM sqlite_master } } msg
}
if {$method == "xShmLock" } {
set details [lindex $args 2]
if {$details == "0 1 lock exclusive"} { set ::seen_writer_lock 1 }
}
}
catch { db close }
forcedelete test.db
testvfs tvfs
sqlite3 db test.db -vfs tvfs
#tvfs filter xSync
tvfs script tvfs_callback
do_execsql_test $tp.0 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(a, b);
PRAGMA journal_mode = wal;
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
} {wal}
# Open a reader on the current database snapshot.
do_test $tp.1 {
sqlite3 db2 test.db -vfs tvfs
execsql {
BEGIN;
SELECT * FROM t1 UNION ALL SELECT * FROM t2;
} db2
} {1 2 3 4 5 6}
# Open a writer. Write a transaction. Then begin, but do not commit,
# a second transaction.
do_test $tp.2 {
sqlite3 db3 test.db -vfs tvfs
execsql {
INSERT INTO t2 VALUES(7, 8);
BEGIN;
INSERT INTO t2 VALUES(9, 10);
SELECT * FROM t1 UNION ALL SELECT * FROM t2;
} db3
} {1 2 3 4 5 6 7 8 9 10}
sqlite3 db5 test.db -vfs tvfs
sqlite3 db6 test.db -vfs tvfs
# Register a busy-handler with connection [db].
#
db busy [list busy_handler $mode $busy_handler_mode]
set ::sync_counter 0
set ::busy_handler_counter 0
set ::read_ok -1
set ::write_ok -1
set ::seen_writer_lock 0
set ::checkpoint_ongoing 1
do_test $tp.3 {
checkpoint db $mode main
set {} {}
} {}
set ::checkpoint_ongoing 0
set ::did_restart_blocking [expr {[catch {db6 eval commit}]}]
if { $mode=="passive" } {
# EVIDENCE-OF: R-16333-64433 Checkpoint as many frames as possible
# without waiting for any database readers or writers to finish, then
# sync the database file if all frames in the log were checkpointed.
#
# "As many frames as possible" means all but the last two transactions
# (the two that write to table t2, of which the scond is unfinished).
# So copying the db file only we see the t1 change, but not the t2
# modifications.
#
# The busy handler is not invoked (see below) and the db reader and
# writer are still active - so the checkpointer did not wait for either
# readers or writers. As a result the checkpoint was not finished and
# so the db file is not synced.
#
# EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
# in the SQLITE_CHECKPOINT_PASSIVE mode.
#
# It's not. Test case "$tp.6".
#
do_test $tp.4 {
forcecopy test.db abc.db
sqlite3 db4 abc.db
db4 eval { SELECT * FROM t1 UNION ALL SELECT * FROM t2 }
} {1 2 3 4 5 6}
do_test $tp.5 { set ::sync_counter } 0
do_test $tp.6 { set ::busy_handler_counter } 0
db4 close
db2 eval COMMIT
db3 eval COMMIT
# EVIDENCE-OF: R-65499-53765 On the other hand, passive mode might leave
# the checkpoint unfinished if there are concurrent readers or writers.
#
# The reader and writer have now dropped their locks. And so a
# checkpoint now is able to checkpoint more frames. Showing that the
# attempt above was left "unfinished".
#
# Also, because the checkpoint finishes this time, the db is synced.
# Which is part of R-16333-64433 above.
#
set ::checkpoint_ongoing 1
do_test $tp.7 {
checkpoint db $mode main
forcecopy test.db abc.db
sqlite3 db4 abc.db
db4 eval { SELECT * FROM t1 UNION ALL SELECT * FROM t2 }
} {1 2 3 4 5 6 7 8 9 10}
set ::checkpoint_ongoing 0
do_test $tp.7 { set ::sync_counter } 1
do_test $tp.8 { set ::busy_handler_counter } 0
db4 close
}
if { $mode=="full" || $mode=="restart" || $mode=="truncate" } {
# EVIDENCE-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
# TRUNCATE modes also obtain the exclusive "writer" lock on the
# database file.
#
# Or at least attempts to obtain.
#
do_test $tp.9 {
set ::seen_writer_lock
} {1}
if {$busy_handler_mode==2 || $busy_handler_mode==3} {
# EVIDENCE-OF: R-59171-47567 This mode blocks (it invokes the
# busy-handler callback) until there is no database writer and all
# readers are reading from the most recent database snapshot.
#
# The test below shows that both the reader and writer have
# finished:
#
# Also restated by the following two. That both busy_handler_mode
# values 2 and 3 work show that both of the following are true - as
# they release the reader and writer transactions in different
# orders.
#
# EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
# immediately, and a busy-handler is configured, it is invoked and the
# writer lock retried until either the busy-handler returns 0 or the
# lock is successfully obtained.
#
# EVIDENCE-OF: R-48107-00250 The busy-handler is also invoked while
# waiting for database readers as described above.
#
do_test $tp.7 {
list [catchsql COMMIT db2] [catchsql COMMIT db3]
} [list \
{1 {cannot commit - no transaction is active}} \
{1 {cannot commit - no transaction is active}} \
]
# EVIDENCE-OF: R-29177-48281 It then checkpoints all frames in the log
# file and syncs the database file.
#
do_test $tp.8 {
forcecopy test.db abc.db
sqlite3 db4 abc.db
db4 eval { SELECT * FROM t1 UNION ALL SELECT * FROM t2 }
} {1 2 3 4 5 6 7 8 9 10}
do_test $tp.9 { set ::sync_counter } 1
db4 close
# EVIDENCE-OF: R-51867-44713 This mode blocks new database writers
# while it is pending, but new database readers are allowed to continue
# unimpeded.
#
# EVIDENCE-OF: R-47276-58266 Like SQLITE_CHECKPOINT_FULL, this mode
# blocks new database writer attempts while it is pending, but does not
# impede readers.
#
# The first of the above two refers to "full" mode. The second
# to "restart".
#
do_test $tp.10.1 {
list $::write_ok $::read_ok
} {0 1}
# EVIDENCE-OF: R-12410-31217 This mode works the same way as
# SQLITE_CHECKPOINT_FULL with the addition that after checkpointing the
# log file it blocks (calls the busy-handler callback) until all
# readers are reading from the database file only.
#
# The stuff above passed, so the first part of this requirement
# is met. The second part is tested below. If the checkpoint mode
# was "restart" or "truncate", then the busy-handler will have
# been called to block on wal-file readers.
#
do_test $tp.11 {
set ::did_restart_blocking
} [expr {($mode=="restart"||$mode=="truncate")&&$busy_handler_mode==3}]
# EVIDENCE-OF: R-44699-57140 This mode works the same way as
# SQLITE_CHECKPOINT_RESTART with the addition that it also truncates
# the log file to zero bytes just prior to a successful return.
if {$mode=="truncate" && $busy_handler_mode==3} {
do_test $tp.12 {
file size test.db-wal
} 0
}
} elseif {$busy_handler_mode==1} {
# EVIDENCE-OF: R-34519-06271 SQLITE_BUSY is returned in this case.
if {$tn!=2} {
# ($tn==2) is the loop that uses "PRAGMA wal_checkpoint"
do_test $tp.13 { sqlite3_errcode db } {SQLITE_BUSY}
}
# EVIDENCE-OF: R-49155-63541 If the busy-handler returns 0 before the
# writer lock is obtained or while waiting for database readers, the
# checkpoint operation proceeds from that point in the same way as
# SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
# without blocking any further.
do_test $tp.14 {
forcecopy test.db abc.db
sqlite3 db4 abc.db
db4 eval { SELECT * FROM t1 UNION ALL SELECT * FROM t2 }
} {1 2 3 4 5 6}
do_test $tp.15 { set ::sync_counter } 0
do_test $tp.16 { set ::busy_handler_counter } 1
db4 close
}
}
db2 close
db3 close
db5 close
db6 close
}
db close
tvfs delete
}
#-----------------------------------------------------------------------
# EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint
# mode:
#
# Valid checkpoint modes are 0, 1, 2 and 3.
#
sqlite3 db test.db
foreach {tn mode res} {
0 -1001 {1 {SQLITE_MISUSE - not an error}}
1 -1 {1 {SQLITE_MISUSE - not an error}}
2 0 {0 {0 -1 -1}}
3 1 {0 {0 -1 -1}}
4 2 {0 {0 -1 -1}}
5 3 {0 {0 -1 -1}}
6 4 {1 {SQLITE_MISUSE - not an error}}
7 114 {1 {SQLITE_MISUSE - not an error}}
8 1000000 {1 {SQLITE_MISUSE - not an error}}
} {
do_test 4.$tn {
list [catch "wal_checkpoint_v2 db $mode" msg] $msg
} $res
}
db close
foreach tn {1 2 3} {
forcedelete test.db test.db2 test.db3
testvfs tvfs
sqlite3 db test.db -vfs tvfs
execsql {
ATTACH 'test.db2' AS aux2;
ATTACH 'test.db3' AS aux3;
PRAGMA main.journal_mode = WAL;
PRAGMA aux2.journal_mode = WAL;
PRAGMA aux3.journal_mode = WAL;
CREATE TABLE main.t1(x,y);
CREATE TABLE aux2.t2(x,y);
CREATE TABLE aux3.t3(x,y);
INSERT INTO t1 VALUES('a', 'b');
INSERT INTO t2 VALUES('a', 'b');
INSERT INTO t3 VALUES('a', 'b');
}
sqlite3 db2 test.db2 -vfs tvfs
switch -- $tn {
1 {
# EVIDENCE-OF: R-41299-52117 If no error (SQLITE_BUSY or otherwise) is
# encountered while processing the attached databases, SQLITE_OK is
# returned.
do_test 5.$tn.1 {
lindex [wal_checkpoint_v2 db truncate] 0
} {0} ;# 0 -> SQLITE_OK
do_test 5.$tn.2 {
list [expr [file size test.db-wal]==0] \
[expr [file size test.db2-wal]==0] \
[expr [file size test.db3-wal]==0]
} {1 1 1}
}
2 {
# EVIDENCE-OF: R-38578-34175 If an SQLITE_BUSY error is encountered when
# processing one or more of the attached WAL databases, the operation is
# still attempted on any remaining attached databases and SQLITE_BUSY is
# returned at the end.
db2 eval { BEGIN; INSERT INTO t2 VALUES('d', 'e'); }
do_test 5.$tn.1 {
lindex [wal_checkpoint_v2 db truncate] 0
} {1} ;# 1 -> SQLITE_BUSY
do_test 5.$tn.2 {
list [expr [file size test.db-wal]==0] \
[expr [file size test.db2-wal]==0] \
[expr [file size test.db3-wal]==0]
} {1 0 1}
db2 eval ROLLBACK
}
3 {
# EVIDENCE-OF: R-38049-07913 If any other error occurs while processing
# an attached database, processing is abandoned and the error code is
# returned to the caller immediately.
tvfs filter xWrite
tvfs script inject_ioerr
proc inject_ioerr {method file args} {
if {[file tail $file]=="test.db2"} {
return "SQLITE_IOERR"
}
return 0
}
do_test 5.$tn.1 {
list [catch { wal_checkpoint_v2 db truncate } msg] $msg
} {1 {SQLITE_IOERR - disk I/O error}}
do_test 5.$tn.2 {
list [expr [file size test.db-wal]==0] \
[expr [file size test.db2-wal]==0] \
[expr [file size test.db3-wal]==0]
} {1 0 0}
tvfs script ""
}
}
db close
db2 close
}
reset_db
sqlite3 db2 test.db
do_test 6.1 {
execsql {
PRAGMA auto_vacuum = 0;
PRAGMA journal_mode = WAL;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
}
file size test.db-wal
} [wal_file_size 3 1024]
do_test 6.2 {
db2 eval { BEGIN; SELECT * FROM t1; }
db eval { INSERT INTO t1 VALUES(3, 4) }
file size test.db-wal
} [wal_file_size 4 1024]
# At this point the log file contains 4 frames. 3 of which it should
# be possible to checkpoint.
#
# EVIDENCE-OF: R-16642-42503 If pnLog is not NULL, then *pnLog is set to
# the total number of frames in the log file or to -1 if the checkpoint
# could not run because of an error or because the database is not in
# WAL mode.
#
# EVIDENCE-OF: R-10514-25250 If pnCkpt is not NULL,then *pnCkpt is set
# to the total number of checkpointed frames in the log file (including
# any that were already checkpointed before the function was called) or
# to -1 if the checkpoint could not run due to an error or because the
# database is not in WAL mode.
#
do_test 6.4 {
lrange [wal_checkpoint_v2 db passive] 1 2
} {4 3}
# EVIDENCE-OF: R-37257-17813 Note that upon successful completion of an
# SQLITE_CHECKPOINT_TRUNCATE, the log file will have been truncated to
# zero bytes and so both *pnLog and *pnCkpt will be set to zero.
#
do_test 6.5 {
db2 eval COMMIT
wal_checkpoint_v2 db truncate
} {0 0 0}
finish_test
-200
View File
@@ -1,200 +0,0 @@
# 2014 December 04
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/wal_common.tcl
set testprefix e_walhook
# EVIDENCE-OF: R-00752-43975 The sqlite3_wal_hook() function is used to
# register a callback that is invoked each time data is committed to a
# database in wal mode.
#
# 1.1: shows that the wal-hook is not invoked in rollback mode.
# 1.2: but is invoked in wal mode.
#
set ::wal_hook_count 0
proc my_wal_hook {args} {
incr ::wal_hook_count
return 0
}
do_test 1.1.1 {
db wal_hook my_wal_hook
execsql {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1);
}
set ::wal_hook_count
} 0
do_test 1.1.2 {
execsql { PRAGMA journal_mode = wal }
set ::wal_hook_count
} 0
do_test 1.3 {
execsql { INSERT INTO t1 VALUES(2) }
set wal_hook_count
} 1
do_test 1.4 {
execsql {
BEGIN;
INSERT INTO t1 VALUES(3);
INSERT INTO t1 VALUES(4);
COMMIT;
}
set wal_hook_count
} 2
# EVIDENCE-OF: R-65366-15139 The callback is invoked by SQLite after the
# commit has taken place and the associated write-lock on the database
# released
#
set ::read_ok 0
proc my_wal_hook {args} {
sqlite3 db2 test.db
if {[db2 eval { SELECT * FROM t1 }] == "1 2 3 4 5"} {
set ::read_ok 1
}
db2 close
}
do_test 2.1 {
execsql { INSERT INTO t1 VALUES(5) }
set ::read_ok
} 1
# EVIDENCE-OF: R-44294-52863 The third parameter is the name of the
# database that was written to - either "main" or the name of an
# ATTACH-ed database.
#
# EVIDENCE-OF: R-18913-19355 The fourth parameter is the number of pages
# currently in the write-ahead log file, including those that were just
# committed.
#
set ::wal_hook_args [list]
proc my_wal_hook {dbname nEntry} {
set ::wal_hook_args [list $dbname $nEntry]
}
forcedelete test.db2
do_test 3.0 {
execsql {
ATTACH 'test.db2' AS aux;
CREATE TABLE aux.t2(x);
PRAGMA aux.journal_mode = wal;
}
} {wal}
# Database "aux"
do_test 3.1.1 {
set wal_hook_args [list]
execsql { INSERT INTO t2 VALUES('a') }
} {}
do_test 3.1.2 {
set wal_hook_args
} [list aux [wal_frame_count test.db2-wal 1024]]
# Database "main"
do_test 3.2.1 {
set wal_hook_args [list]
execsql { INSERT INTO t1 VALUES(6) }
} {}
do_test 3.1.2 {
set wal_hook_args
} [list main [wal_frame_count test.db-wal 1024]]
# EVIDENCE-OF: R-14034-00929 If an error code is returned, that error
# will propagate back up through the SQLite code base to cause the
# statement that provoked the callback to report an error, though the
# commit will have still occurred.
#
proc my_wal_hook {args} { return 1 ;# SQLITE_ERROR }
do_catchsql_test 4.1 {
INSERT INTO t1 VALUES(7)
} {1 {SQL logic error or missing database}}
proc my_wal_hook {args} { return 5 ;# SQLITE_BUSY }
do_catchsql_test 4.2 {
INSERT INTO t1 VALUES(8)
} {1 {database is locked}}
proc my_wal_hook {args} { return 14 ;# SQLITE_CANTOPEN }
do_catchsql_test 4.3 {
INSERT INTO t1 VALUES(9)
} {1 {unable to open database file}}
do_execsql_test 4.4 {
SELECT * FROM t1
} {1 2 3 4 5 6 7 8 9}
# EVIDENCE-OF: R-10466-53920 Calling sqlite3_wal_hook() replaces any
# previously registered write-ahead log callback.
set ::old_wal_hook 0
proc my_old_wal_hook {args} {
incr ::old_wal_hook
return 0
}
db wal_hook my_old_wal_hook
do_test 5.1 {
execsql { INSERT INTO t1 VALUES(10) }
set ::old_wal_hook
} {1}
# Replace old_wal_hook. Observe that it is not invoked after it has
# been replaced.
proc my_new_wal_hook {args} { return 0 }
db wal_hook my_new_wal_hook
do_test 5.2 {
execsql { INSERT INTO t1 VALUES(11) }
set ::old_wal_hook
} {1}
# EVIDENCE-OF: R-42842-27162 Note that the sqlite3_wal_autocheckpoint()
# interface and the wal_autocheckpoint pragma both invoke
# sqlite3_wal_hook() and will those overwrite any prior
# sqlite3_wal_hook() settings.
#
set ::old_wal_hook 0
proc my_old_wal_hook {args} { incr ::old_wal_hook ; return 0 }
db wal_hook my_old_wal_hook
do_test 6.1.1 {
execsql { INSERT INTO t1 VALUES(12) }
set ::old_wal_hook
} {1}
do_test 6.1.2 {
execsql { PRAGMA wal_autocheckpoint = 1000 }
execsql { INSERT INTO t1 VALUES(12) }
set ::old_wal_hook
} {1}
# EVIDENCE-OF: R-52629-38967 The first parameter passed to the callback
# function when it is invoked is a copy of the third parameter passed to
# sqlite3_wal_hook() when registering the callback.
#
# This is tricky to test using the tcl interface. However, the
# mechanism used to invoke the tcl script registered as a wal-hook
# depends on the context pointer being correctly passed through. And
# since multiple different wal-hook scripts have been successfully
# invoked by this test script, consider this tested.
#
# EVIDENCE-OF: R-23378-42536 The second is a copy of the database
# handle.
#
# There is an assert() in the C wal-hook used by tclsqlite.c to
# prove this. And that hook has been invoked multiple times when
# running this script. So consider this requirement tested as well.
#
finish_test
+1 -5
View File
@@ -252,17 +252,13 @@ do_test fkey5-6.5 {
} {c12 1 p4 0 c12 3 p4 0 c12 6 p4 0}
do_test fkey5-7.1 {
set res {}
db eval {
INSERT OR IGNORE INTO c13 SELECT * FROM c12;
INSERT OR IGNORE INTO C14 SELECT * FROM c12;
DELETE FROM c12;
PRAGMA foreign_key_check;
} {
lappend res [list $table $rowid $fkid $parent]
}
lsort $res
} {{c13 1 0 p3} {c13 2 0 p3} {c13 3 0 p3} {c13 4 0 p3} {c13 5 0 p3} {c13 6 0 p3} {c14 1 0 p4} {c14 3 0 p4} {c14 6 0 p4}}
} {c14 1 p4 0 c14 3 p4 0 c14 6 p4 0 c13 1 p3 0 c13 2 p3 0 c13 3 p3 0 c13 4 p3 0 c13 5 p3 0 c13 6 p3 0}
do_test fkey5-7.2 {
db eval {
PRAGMA foreign_key_check(c14);
-106
View File
@@ -1,106 +0,0 @@
# 2001 September 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for foreign keys.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fkey8
ifcapable {!foreignkey} {
finish_test
return
}
do_execsql_test 1.0 { PRAGMA foreign_keys = 1; }
foreach {tn use_stmt sql schema} {
1 1 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1);
}
2.1 0 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE);
}
2.2 0 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON DELETE SET NULL);
}
2.3 1 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON DELETE SET DEFAULT);
}
3 1 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE);
CREATE TRIGGER ct1 AFTER DELETE ON c1 BEGIN
INSERT INTO p1 VALUES('x');
END;
}
4 1 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
CREATE TABLE cc1(d REFERENCES c1);
}
5.1 0 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
CREATE TABLE cc1(d REFERENCES c1 ON DELETE CASCADE);
}
5.2 0 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET NULL);
}
5.3 1 "DELETE FROM p1" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET DEFAULT);
}
6.1 1 "UPDATE p1 SET a = ?" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c);
}
6.2 0 "UPDATE OR IGNORE p1 SET a = ?" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c);
}
6.3 1 "UPDATE OR IGNORE p1 SET a = ?" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b REFERENCES p1 ON UPDATE CASCADE, c);
}
6.4 1 "UPDATE OR IGNORE p1 SET a = ?" {
CREATE TABLE p1(a PRIMARY KEY);
CREATE TABLE c1(b NOT NULL REFERENCES p1 ON UPDATE SET NULL, c);
}
} {
drop_all_tables
do_test 1.$tn {
execsql $schema
set stmt [sqlite3_prepare_v2 db $sql -1 dummy]
set ret [uses_stmt_journal $stmt]
sqlite3_finalize $stmt
set ret
} $use_stmt
}
finish_test
+1 -22
View File
@@ -12,6 +12,7 @@
#
# This file checks error recovery from malformed SQL strings.
#
# $Id: fuzz2.test,v 1.3 2007/05/15 16:51:37 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -104,26 +105,4 @@ do_test fuzz2-5.5 {
fuzzcatch {SELECT ALL * GROUP BY EXISTS ( SELECT "AAAAAA" . * , AAAAAA ( * ) AS AAAAAA FROM "AAAAAA" . "AAAAAA" AS "AAAAAA" USING ( AAAAAA , "AAAAAA" , "AAAAAA" ) WHERE AAAAAA ( DISTINCT ) - RAISE ( FAIL , "AAAAAA" ) HAVING "AAAAAA" . "AAAAAA" . AAAAAA ORDER BY #182 , #55 ) BETWEEN EXISTS ( SELECT ALL * FROM ( ( }
} {1}
# Test cases discovered by Michal Zalewski on 2015-01-03 and reported on the
# sqlite-users mailing list. All of these cases cause segfaults in
# SQLite 3.8.7.4 and earlier.
#
do_test fuzz2-6.1 {
catchsql {SELECT n()AND+#0;}
} {1 {near "#0": syntax error}}
do_test fuzz2-6.2 {
catchsql {SELECT strftime()}
} {0 {{}}}
do_test fuzz2-6.3 {
catchsql {DETACH(SELECT group_concat(q));}
} {1 {no such column: q}}
do_test fuzz2-6.4a {
db eval {DROP TABLE IF EXISTS t0; CREATE TABLE t0(t);}
catchsql {INSERT INTO t0 SELECT strftime();}
} {0 {}}
do_test fuzz2-6.4b {
db eval {SELECT quote(t) FROM t0}
} {NULL}
finish_test
-20
View File
@@ -514,25 +514,5 @@ if {$::tcl_platform(platform)=="unix"
} {1 {no such vfs: async}}
}
}
# Print the version number so that it can be picked up by releasetest.tcl.
#
puts [db one {SELECT 'VERSION: ' ||
sqlite_version() || ' ' ||
sqlite_source_id();}]
# Do deliberate failures if the TEST_FAILURE environment variable is set.
# This is done to verify that failure notifications are detected by the
# releasetest.tcl script, or possibly by other scripts involved in automatic
# testing.
#
if {[info exists ::env(TEST_FAILURE)]} {
set res 123
if {$::env(TEST_FAILURE)==0} {set res 234}
do_test main-99.1 {
bad_behavior $::env(TEST_FAILURE)
set x 123
} $res
}
finish_test
+4 -4
View File
@@ -176,20 +176,20 @@ do_test memsubsys1-4.6 {
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1
# Test 5: Activate both PAGECACHE and SCRATCH. But make the page size is
# Test 5: Activate both PAGECACHE and SCRATCH. But make the page size
# such that the SCRATCH allocations are too small.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache [expr 4096+$xtra_size] 24
sqlite3_config_scratch 4000 2
sqlite3_config_scratch 6000 2
sqlite3_initialize
reset_highwater_marks
build_test_db memsubsys1-5 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-5.3 {
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} {/^2[34]$/}
} 24
do_test memsubsys1-5.4 {
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
expr {$maxreq>4096}
@@ -215,7 +215,7 @@ build_test_db memsubsys1-6 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-6.3 {
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} {/^2[34]$/}
} 24
#do_test memsubsys1-6.4 {
# set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
# expr {$maxreq>4096 && $maxreq<=(4096+$xtra_size)}
+8 -33
View File
@@ -101,8 +101,6 @@ set sql $zSql
# This loop runs for ~20 seconds.
#
set iStart [clock_seconds]
set nOp 0
set nAttempt 0
while { ([clock_seconds]-$iStart) < $nSecond } {
# Each transaction does 3 operations. Each operation is either a read
@@ -130,7 +128,6 @@ set sql $zSql
# Execute the SQL transaction.
#
incr nAttempt
set rc [catch { execsql_blocking $::DB "
BEGIN;
$SQL(1);
@@ -157,14 +154,13 @@ set sql $zSql
# returned "1". Otherwise, the invariant was false, indicating that
# some malfunction has occurred.
foreach r $msg { if {$r != 1} { puts "Invariant check failed: $msg" } }
incr nOp
}
}
# Close the database connection and return 0.
#
sqlite3_close $::DB
list $nOp $nAttempt
expr 0
}
foreach {iTest xStep xPrepare} {
@@ -208,9 +204,7 @@ foreach {iTest xStep xPrepare} {
for {set ii 0} {$ii < $nThread} {incr ii} {
do_test notify2-$iTest.2.$ii {
if {![info exists finished($ii)]} { vwait finished($ii) }
incr anSuccess($xStep) [lindex $finished($ii) 0]
incr anAttempt($xStep) [lindex $finished($ii) 1]
expr 0
set finished($ii)
} {0}
}
@@ -231,36 +225,17 @@ foreach {iTest xStep xPrepare} {
}
# The following tests checks to make sure sqlite3_blocking_step() is
# faster than sqlite3_step(). "Faster" in this case means uses fewer
# CPU cycles. This is not always the same as faster in wall-clock time
# for this type of test. The number of CPU cycles per transaction is
# roughly proportional to the number of attempts made (i.e. one plus the
# number of SQLITE_BUSY or SQLITE_LOCKED errors that require the transaction
# to be retried). So this test just measures that a greater percentage of
# transactions attempted using blocking_step() succeed.
#
# The blocking_step() function is almost always faster on multi-core and is
# usually faster on single-core. But sometimes, by chance, step() will be
# faster on a single core, in which case the
# faster than sqlite3_step(). blocking_step() is always faster on
# multi-core and is usually faster on single-core. But sometimes, by
# chance, step() will be faster on a single core, in which case the
# following test will fail.
#
puts "The following test seeks to demonstrate that the sqlite3_unlock_notify()"
puts "interface helps multi-core systems to run more efficiently. This test"
puts "sometimes fails on single-core machines."
puts "interface helps multi-core systems to run faster. This test sometimes"
puts "fails on single-core machines."
puts [array get anWrite]
do_test notify2-3 {
set blocking [expr {
double($anSuccess(sqlite3_blocking_step)) /
double($anAttempt(sqlite3_blocking_step))
}]
set non [expr {
double($anSuccess(sqlite3_step)) /
double($anAttempt(sqlite3_step))
}]
puts -nonewline [format " blocking: %.1f%% non-blocking %.1f%% ..." \
[expr $blocking*100.0] [expr $non*100.0]]
expr {$blocking > $non}
expr {$anWrite(sqlite3_blocking_step) > $anWrite(sqlite3_step)}
} {1}
sqlite3_enable_shared_cache $::enable_shared_cache
+13 -14
View File
@@ -51,20 +51,19 @@ proc do_re_test {tn script expression} {
# a call to getcwd() may fail if there are no free file descriptors. So
# an error may be reported for either open() or getcwd() here.
#
if {![clang_sanitize_address]} {
do_test 1.1.1 {
set ::log [list]
list [catch {
for {set i 0} {$i < 2000} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
} msg] $msg
} {1 {unable to open database file}}
do_test 1.1.2 {
catch { for {set i 0} {$i < 2000} {incr i} { dbh_$i close } }
} {1}
do_re_test 1.1.3 {
lindex $::log 0
} {^os_unix.c:\d+: \(\d+\) (open|getcwd)\(.*test.db\) - }
}
puts "Possible valgrind error about invalid file descriptor follows:"
do_test 1.1.1 {
set ::log [list]
list [catch {
for {set i 0} {$i < 2000} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
} msg] $msg
} {1 {unable to open database file}}
do_test 1.1.2 {
catch { for {set i 0} {$i < 2000} {incr i} { dbh_$i close } }
} {1}
do_re_test 1.1.3 {
lindex $::log 0
} {^os_unix.c:\d+: \(\d+\) (open|getcwd)\(.*test.db\) - }
# Test a failure in open() due to the path being a directory.
+1 -1
View File
@@ -200,7 +200,7 @@ ifcapable vtab {
} {
do_test percentile-2.1.$in {
execsql {
SELECT round(percentile(x, $in),1) from t3;
SELECT percentile(x, $in) from t3;
}
} $out
}
+3 -18
View File
@@ -118,19 +118,6 @@ set allquicktests [test_set $alltests -exclude {
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
}
if {[info exists ::env(QUICKTEST_OMIT)]} {
foreach x [split $::env(QUICKTEST_OMIT) ,] {
regsub -all \\y$x\\y $allquicktests {} allquicktests
}
}
# If the TEST_FAILURE environment variable is set, it means that we what to
# deliberately provoke test failures in order to test the test infrastructure.
# Only the main.test module is needed for this.
#
if {[info exists ::env(TEST_FAILURE)]} {
set allquicktests main.test
}
#############################################################################
# Start of tests
@@ -154,7 +141,7 @@ test_suite "veryquick" -prefix "" -description {
]
test_suite "mmap" -prefix "mm-" -description {
Similar to veryquick. Except with memory mapping enabled.
Similar to veryquick. Except with memory mapping disabled.
} -presql {
pragma mmap_size = 268435456;
} -files [
@@ -165,9 +152,7 @@ test_suite "valgrind" -prefix "" -description {
Run the "veryquick" test suite with a couple of multi-process tests (that
fail under valgrind) omitted.
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test \
shell*.test crash8.test atof1.test selectG.test \
tkt-fc62af4523.test
test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test
] -initialize {
set ::G(valgrind) 1
} -shutdown {
@@ -705,7 +690,7 @@ test_suite "inmemory_journal" -description {
zerodamage.test
# WAL mode is different.
wal* tkt-2d1a5c67d.test backcompat.test e_wal*
wal* tkt-2d1a5c67d.test backcompat.test
}]
ifcapable mem3 {
+1 -25
View File
@@ -454,34 +454,10 @@ do_execsql_test pragma-3.21 {
do_execsql_test pragma-3.22 {
PRAGMA integrity_check(2);
} {{non-unique entry in index t1a} {NULL value in t1x.a}}
do_execsql_test pragma-3.23 {
do_execsql_test pragma-3.21 {
PRAGMA integrity_check(1);
} {{non-unique entry in index t1a}}
# PRAGMA integrity check (or more specifically the sqlite3BtreeCount()
# interface) used to leave index cursors in an inconsistent state
# which could result in an assertion fault in sqlite3BtreeKey()
# called from saveCursorPosition() if content is removed from the
# index while the integrity_check is still running. This test verifies
# that problem has been fixed.
#
do_test pragma-3.30 {
db close
delete_file test.db
sqlite3 db test.db
db eval {
CREATE TABLE t1(a,b,c);
WITH RECURSIVE
c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<100)
INSERT INTO t1(a,b,c) SELECT i, printf('xyz%08x',i), 2000-i FROM c;
CREATE INDEX t1a ON t1(a);
CREATE INDEX t1bc ON t1(b,c);
}
db eval {PRAGMA integrity_check} {
db eval {DELETE FROM t1}
}
} {}
# Test modifying the cache_size of an attached database.
ifcapable pager_pragmas&&attach {
do_test pragma-4.1 {
-253
View File
@@ -1,253 +0,0 @@
# 2014-12-19
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for PRAGMA data_version command.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test pragma3-100 {
PRAGMA data_version;
} {1}
do_execsql_test pragma3-101 {
PRAGMA temp.data_version;
} {1}
# Writing to the pragma is a no-op
do_execsql_test pragma3-102 {
PRAGMA main.data_version=1234;
PRAGMA main.data_version;
} {1 1}
# EVIDENCE-OF: R-27726-60934 The "PRAGMA data_version" command provides
# an indication that the database file has been modified.
#
# EVIDENCE-OF: R-47505-58569 The "PRAGMA data_version" value is
# unchanged for commits made on the same database connection.
#
do_execsql_test pragma3-110 {
PRAGMA data_version;
BEGIN IMMEDIATE;
PRAGMA data_version;
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(100),(200),(300);
PRAGMA data_version;
COMMIT;
SELECT * FROM t1;
PRAGMA data_version;
} {1 1 1 100 200 300 1}
sqlite3 db2 test.db
do_test pragma3-120 {
db2 eval {
SELECT * FROM t1;
PRAGMA data_version;
}
} {100 200 300 1}
do_execsql_test pragma3-130 {
PRAGMA data_version;
BEGIN IMMEDIATE;
PRAGMA data_version;
INSERT INTO t1 VALUES(400),(500);
PRAGMA data_version;
COMMIT;
SELECT * FROM t1;
PRAGMA data_version;
PRAGMA shrink_memory;
} {1 1 1 100 200 300 400 500 1}
# EVIDENCE-OF: R-63005-41812 The integer values returned by two
# invocations of "PRAGMA data_version" from the same connection will be
# different if changes were committed to the database by any other
# connection in the interim.
#
# Value went from 1 in pragma3-120 to 2 here.
#
do_test pragma3-140 {
db2 eval {
SELECT * FROM t1;
PRAGMA data_version;
BEGIN IMMEDIATE;
PRAGMA data_version;
UPDATE t1 SET a=a+1;
COMMIT;
SELECT * FROM t1;
PRAGMA data_version;
}
} {100 200 300 400 500 2 2 101 201 301 401 501 2}
do_execsql_test pragma3-150 {
SELECT * FROM t1;
PRAGMA data_version;
} {101 201 301 401 501 2}
#
do_test pragma3-160 {
db eval {
BEGIN;
PRAGMA data_version;
UPDATE t1 SET a=555 WHERE a=501;
PRAGMA data_version;
SELECT * FROM t1 ORDER BY a;
PRAGMA data_version;
}
} {2 2 101 201 301 401 555 2}
do_test pragma3-170 {
db2 eval {
PRAGMA data_version;
}
} {2}
do_test pragma3-180 {
db eval {
COMMIT;
PRAGMA data_version;
}
} {2}
do_test pragma3-190 {
db2 eval {
PRAGMA data_version;
}
} {3}
# EVIDENCE-OF: R-19326-44825 The "PRAGMA data_version" value is a local
# property of each database connection and so values returned by two
# concurrent invocations of "PRAGMA data_version" on separate database
# connections are often different even though the underlying database is
# identical.
#
do_test pragma3-195 {
expr {[db eval {PRAGMA data_version}]!=[db2 eval {PRAGMA data_version}]}
} {1}
# EVIDENCE-OF: R-54562-06892 The behavior of "PRAGMA data_version" is
# the same for all database connections, including database connections
# in separate processes and shared cache database connections.
#
# The next block checks the behavior for separate processes.
#
do_test pragma3-200 {
db eval {PRAGMA data_version; SELECT * FROM t1;}
} {2 101 201 301 401 555}
do_test pragma3-201 {
set fd [open pragma3.txt wb]
puts $fd {
sqlite3 db test.db;
db eval {DELETE FROM t1 WHERE a>300};
db close;
exit;
}
close $fd
exec [info nameofexec] pragma3.txt
forcedelete pragma3.txt
db eval {
PRAGMA data_version;
SELECT * FROM t1;
}
} {3 101 201}
db2 close
db close
# EVIDENCE-OF: R-54562-06892 The behavior of "PRAGMA data_version" is
# the same for all database connections, including database connections
# in separate processes and shared cache database connections.
#
# The next block checks that behavior is the same for shared-cache.
#
ifcapable shared_cache {
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
sqlite3 db test.db
sqlite3 db2 test.db
do_test pragma3-300 {
db eval {
PRAGMA data_version;
BEGIN;
CREATE TABLE t3(a,b,c);
CREATE TABLE t4(x,y,z);
INSERT INTO t4 VALUES(123,456,789);
PRAGMA data_version;
COMMIT;
PRAGMA data_version;
}
} {1 1 1}
do_test pragma3-310 {
db2 eval {
PRAGMA data_version;
BEGIN;
INSERT INTO t3(a,b,c) VALUES('abc','def','ghi');
SELECT * FROM t3;
PRAGMA data_version;
}
} {2 abc def ghi 2}
# The transaction in db2 has not yet committed, so the data_version in
# db is unchanged.
do_test pragma3-320 {
db eval {
PRAGMA data_version;
SELECT * FROM t4;
}
} {1 123 456 789}
do_test pragma3-330 {
db2 eval {
COMMIT;
PRAGMA data_version;
SELECT * FROM t4;
}
} {2 123 456 789}
do_test pragma3-340 {
db eval {
PRAGMA data_version;
SELECT * FROM t3;
SELECT * FROM t4;
}
} {2 abc def ghi 123 456 789}
db2 close
db close
sqlite3_enable_shared_cache $::enable_shared_cache
}
# Make sure this also works in WAL mode
#
# This will not work with the in-memory journal permutation, as opening
# [db2] switches the journal mode back to "memory"
#
ifcapable wal {
if {[permutation]!="inmemory_journal"} {
sqlite3 db test.db
db eval {PRAGMA journal_mode=WAL}
sqlite3 db2 test.db
do_test pragma3-400 {
db eval {
PRAGMA data_version;
PRAGMA journal_mode;
SELECT * FROM t1;
}
} {2 wal 101 201}
do_test pragma3-410 {
db2 eval {
PRAGMA data_version;
PRAGMA journal_mode;
SELECT * FROM t1;
}
} {2 wal 101 201}
do_test pragma3-420 {
db eval {UPDATE t1 SET a=111*(a/100); PRAGMA data_version; SELECT * FROM t1}
} {2 111 222}
do_test pragma3-430 {
db2 eval {PRAGMA data_version; SELECT * FROM t1;}
} {3 111 222}
db2 close
}
}
finish_test
+14
View File
@@ -0,0 +1,14 @@
########################################################
TOP=/home/drh/sqlite/sqlite
TCL_FLAGS=-I/home/drh/tcltk/86linux
LIBTCL=/home/drh/tcltk/86linux/libtcl8.6.a -lm -ldl -lpthread
BCC = gcc
TCC = gcc -ansi -g $(CFLAGS)
NAWK = awk
AR = ar cr
RANLIB = ranlib
THREADLIB = -lpthread -ldl -lz
include $(TOP)/main.mk
########################################################
+104 -336
View File
@@ -1,63 +1,70 @@
#!/usr/bin/tclsh
#
set rcsid {$Id: $}
# Documentation for this script. This may be output to stderr
# if the script is invoked incorrectly. See the [process_options]
# proc below.
#
set ::USAGE_MESSAGE {
This Tcl script is used to test the various configurations required
before releasing a new version. Supported command line options (all
before releasing a new version. Supported command line options (all
optional) are:
--srcdir TOP-OF-SQLITE-TREE (see below)
--platform PLATFORM (see below)
--config CONFIGNAME (Run only CONFIGNAME)
--quick (Run "veryquick.test" only)
--veryquick (Run "make smoketest" only)
--buildonly (Just build testfixture - do not run)
--dryrun (Print what would have happened)
--info (Show diagnostic info)
-makefile PATH-TO-MAKEFILE (default "releasetest.mk")
-platform PLATFORM (see below)
-quick BOOLEAN (default "0")
-config CONFIGNAME (Run only CONFIGNAME)
The default value for --srcdir is the parent of the directory holding
this script.
The default value for -makefile is "./releasetest.mk".
The script determines the default value for --platform using the
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
The script determines the default value for -platform using the
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
platforms are "Linux-x86", "Linux-x86_64" and "Darwin-i386".
Every test begins with a fresh run of the configure script at the top
of the SQLite source tree.
If the -quick option is set to true, then the "veryquick.test" script
is run for all compilation configurations. Otherwise, sometimes "all.test"
is run, sometimes "veryquick.test".
Almost any SQLite makefile (except those generated by configure - see below)
should work. The following properties are required:
* The makefile should support the "fulltest" target.
* The makefile should support the variable "OPTS" as a way to pass
options from the make command line to lemon and the C compiler.
More precisely, the following invocation must be supported:
make -f $::MAKEFILE fulltest OPTS="-DSQLITE_SECURE_DELETE=1 -DSQLITE_DEBUG=1"
Makefiles generated by the sqlite configure program cannot be used as
they do not respect the OPTS variable.
Example Makefile contents:
########################################################
TOP=/home/dan/work/sqlite/sqlite
TCL_FLAGS=-I/home/dan/tcl/include
LIBTCL=-L/home/dan/tcl/lib -ltcl
BCC = gcc
TCC = gcc -ansi -g $(CFLAGS)
NAWK = awk
AR = ar cr
RANLIB = ranlib
THREADLIB = -lpthread -ldl
include $(TOP)/main.mk
########################################################
}
# Omit comments (text between # and \n) in a long multi-line string.
#
proc strip_comments {in} {
regsub -all {#[^\n]*\n} $in {} out
return $out
}
array set ::Configs [strip_comments {
array set ::Configs {
"Default" {
-O2
--disable-amalgamation --disable-shared
}
"Sanitize" {
CC=clang -fsanitize=undefined
-DSQLITE_ENABLE_STAT4
}
"Have-Not" {
# The "Have-Not" configuration sets all possible -UHAVE_feature options
# in order to verify that the code works even on platforms that lack
# these support services.
-DHAVE_FDATASYNC=0
-DHAVE_GMTIME_R=0
-DHAVE_ISNAN=0
-DHAVE_LOCALTIME_R=0
-DHAVE_LOCALTIME_S=0
-DHAVE_MALLOC_USABLE_SIZE=0
-DHAVE_STRCHRNUL=0
-DHAVE_USLEEP=0
-DHAVE_UTIME=0
"Ftrapv" {
-O2 -ftrapv
-DSQLITE_MAX_ATTACHED=55
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
}
"Unlock-Notify" {
-O2
@@ -74,7 +81,6 @@ array set ::Configs [strip_comments {
-O2
-DSQLITE_DEFAULT_FILE_FORMAT=4
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
-DSQLITE_ENABLE_STMT_SCANSTATUS
}
"Check-Symbols" {
-DSQLITE_MEMDEBUG=1
@@ -88,13 +94,11 @@ array set ::Configs [strip_comments {
-DSQLITE_SECURE_DELETE=1
-DSQLITE_SOUNDEX=1
-DSQLITE_ENABLE_ATOMIC_WRITE=1
-DSQLITE_ENABLE_IOTRACE=1
-DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
-DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_STMT_SCANSTATUS
}
"Debug-One" {
--disable-shared
-O2
-DSQLITE_DEBUG=1
-DSQLITE_MEMDEBUG=1
@@ -105,8 +109,6 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_MEMSYS5=1
-DSQLITE_ENABLE_MEMSYS3=1
-DSQLITE_ENABLE_COLUMN_METADATA=1
-DSQLITE_ENABLE_STAT4
-DSQLITE_MAX_ATTACHED=125
}
"Device-One" {
-O2
@@ -147,7 +149,6 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_LOCKING_STYLE=1
}
"OS-X" {
-O1 # Avoid a compiler bug in gcc 4.2.1 build 5658
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DSQLITE_DEFAULT_MEMSTATUS=0
-DSQLITE_THREADSAFE=2
@@ -160,9 +161,8 @@ array set ::Configs [strip_comments {
-DSQLITE_DEFAULT_CACHE_SIZE=1000
-DSQLITE_MAX_LENGTH=2147483645
-DSQLITE_MAX_VARIABLE_NUMBER=500000
-DSQLITE_DEBUG=1
-DSQLITE_DEBUG=1
-DSQLITE_PREFER_PROXY_LOCKING=1
-DSQLITE_ENABLE_API_ARMOR=1
}
"Extra-Robustness" {
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
@@ -177,80 +177,41 @@ array set ::Configs [strip_comments {
-DSQLITE_DISABLE_FTS4_DEFERRED
-DSQLITE_ENABLE_RTREE
}
"No-lookaside" {
-DSQLITE_TEST_REALLOC_STRESS=1
-DSQLITE_OMIT_LOOKASIDE=1
-DHAVE_USLEEP=1
}
"Valgrind" {
-DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_RTREE
}
}
# The next group of configurations are used only by the
# Failure-Detection platform. They are all the same, but we need
# different names for them all so that they results appear in separate
# subdirectories.
#
Fail0 {-O0}
Fail2 {-O0}
Fail3 {-O0}
Fail4 {-O0}
}]
array set ::Platforms [strip_comments {
array set ::Platforms {
Linux-x86_64 {
"Check-Symbols" checksymbols
"Debug-One" "mptest test"
"Have-Not" test
"Debug-One" test
"Secure-Delete" test
"Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
"Update-Delete-Limit" test
"Extra-Robustness" test
"Device-Two" test
"Ftrapv" test
"No-lookaside" test
"Devkit" test
"Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test}
"Valgrind" valgrindtest
"Default" "threadtest fulltest"
"Device-One" fulltest
}
Linux-i686 {
"Devkit" test
"Have-Not" test
"Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
"Device-One" test
"Device-Two" test
"Default" "threadtest fulltest"
}
Darwin-i386 {
"Locking-Style" "mptest test"
"Have-Not" test
"Locking-Style" test
"OS-X" "threadtest fulltest"
}
Darwin-x86_64 {
"Locking-Style" "mptest test"
"Have-Not" test
"OS-X" "threadtest fulltest"
}
"Windows NT-intel" {
"Default" "mptest fulltestonly"
"Have-Not" test
}
# The Failure-Detection platform runs various tests that deliberately
# fail. This is used as a test of this script to verify that this script
# correctly identifies failures.
#
Failure-Detection {
Fail0 "TEST_FAILURE=0 test"
Sanitize "TEST_FAILURE=1 test"
Fail2 "TEST_FAILURE=2 valgrindtest"
Fail3 "TEST_FAILURE=3 valgrindtest"
Fail4 "TEST_FAILURE=4 test"
}
}]
}
# End of configuration section.
@@ -266,82 +227,18 @@ foreach {key value} [array get ::Platforms] {
}
}
# Open the file $logfile and look for a report on the number of errors
# and the number of test cases run. Add these values to the global
# $::NERRCASE and $::NTESTCASE variables.
#
# If any errors occur, then write into $errmsgVar the text of an appropriate
# one-line error message to show on the output.
#
proc count_tests_and_errors {logfile rcVar errmsgVar} {
if {$::DRYRUN} return
upvar 1 $rcVar rc $errmsgVar errmsg
set fd [open $logfile rb]
set seen 0
while {![eof $fd]} {
set line [gets $fd]
if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} {
incr ::NERRCASE $nerr
incr ::NTESTCASE $ntest
set seen 1
if {$nerr>0} {
set rc 1
set errmsg $line
}
}
if {[regexp {runtime error: +(.*)} $line all msg]} {
incr ::NERRCASE
if {$rc==0} {
set rc 1
set errmsg $msg
}
}
if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
incr ::NERRCASE
if {$rc==0} {
set rc 1
set errmsg $all
}
}
if {[regexp {^VERSION: 3\.\d+.\d+} $line]} {
set v [string range $line 9 end]
if {$::SQLITE_VERSION eq ""} {
set ::SQLITE_VERSION $v
} elseif {$::SQLITE_VERSION ne $v} {
set rc 1
set errmsg "version conflict: {$::SQLITE_VERSION} vs. {$v}"
}
}
}
close $fd
if {!$seen} {
set rc 1
set errmsg "Test did not complete"
if {[file readable core]} {
append errmsg " - core file exists"
}
}
}
proc run_test_suite {name testtarget config} {
# Tcl variable $opts is used to build up the value used to set the
# Tcl variable $opts is used to build up the value used to set the
# OPTS Makefile variable. Variable $cflags holds the value for
# CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
# CFLAGS is only passed to gcc.
#
set cflags "-g"
set cflags ""
set opts ""
set title ${name}($testtarget)
set configOpts ""
regsub -all {#[^\n]*\n} $config \n config
foreach arg $config {
if {[regexp {^-[UD]} $arg]} {
if {[string match -D* $arg]} {
lappend opts $arg
} elseif {[regexp {^[A-Z]+=} $arg]} {
lappend testtarget $arg
} elseif {[regexp {^--(enable|disable)-} $arg]} {
lappend configOpts $arg
} else {
lappend cflags $arg
}
@@ -361,76 +258,30 @@ proc run_test_suite {name testtarget config} {
append opts " -DSQLITE_OS_UNIX=1"
}
if {!$::TRACE} {
set n [string length $title]
puts -nonewline "${title}[string repeat . [expr {63-$n}]]"
flush stdout
}
# Run the test.
#
set makefile [file normalize $::MAKEFILE]
file mkdir $dir
puts -nonewline "Testing configuration \"$name\" (logfile=$dir/test.log)..."
flush stdout
set rc 0
set tm1 [clock seconds]
set origdir [pwd]
trace_cmd file mkdir $dir
trace_cmd cd $dir
set errmsg {}
catch {file delete core}
set rc [catch [configureCommand $configOpts]]
if {!$rc} {
set rc [catch [makeCommand $testtarget $cflags $opts]]
count_tests_and_errors test.log rc errmsg
}
trace_cmd cd $origdir
set makecmd [concat \
[list exec make -C $dir -f $makefile clean] \
$testtarget \
[list CFLAGS=$cflags OPTS=$opts >& $dir/test.log] \
]
set tm1 [clock seconds]
set rc [catch $makecmd]
set tm2 [clock seconds]
if {!$::TRACE} {
set hours [expr {($tm2-$tm1)/3600}]
set minutes [expr {(($tm2-$tm1)/60)%60}]
set seconds [expr {($tm2-$tm1)%60}]
set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]
if {$rc} {
puts " FAIL $tm"
incr ::NERR
if {$errmsg!=""} {puts " $errmsg"}
} else {
puts " Ok $tm"
}
}
}
# The following procedure returns the "configure" command to be exectued for
# the current platform, which may be Windows (via MinGW, etc).
#
proc configureCommand {opts} {
set result [list trace_cmd exec]
if {$::tcl_platform(platform)=="windows"} {
lappend result sh
}
lappend result $::SRCDIR/configure --enable-load-extension
foreach x $opts {lappend result $x}
lappend result >& test.log
}
# The following procedure returns the "make" command to be executed for the
# specified targets, compiler flags, and options.
#
proc makeCommand { targets cflags opts } {
set result [list trace_cmd exec make clean]
foreach target $targets {
lappend result $target
}
lappend result CFLAGS=$cflags OPTS=$opts >>& test.log
}
# The following procedure prints its arguments if ::TRACE is true.
# And it executes the command of its arguments in the calling context
# if ::DRYRUN is false.
#
proc trace_cmd {args} {
if {$::TRACE} {
puts $args
}
if {!$::DRYRUN} {
uplevel 1 $args
set minutes [expr {($tm2-$tm1)/60}]
set seconds [expr {($tm2-$tm1)%60}]
puts -nonewline [format " (%d:%.2d) " $minutes $seconds]
if {$rc} {
puts "FAILED."
} else {
puts "Ok."
}
}
@@ -441,22 +292,16 @@ proc trace_cmd {args} {
# option.
#
proc process_options {argv} {
set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]]
set ::QUICK 0
set ::BUILDONLY 0
set ::DRYRUN 0
set ::EXEC exec
set ::TRACE 0
set ::MAKEFILE releasetest.mk ;# Default value
set ::QUICK 0 ;# Default value
set config {}
set platform $::tcl_platform(os)-$::tcl_platform(machine)
for {set i 0} {$i < [llength $argv]} {incr i} {
set x [lindex $argv $i]
if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]}
switch -glob -- $x {
-srcdir {
switch -- [lindex $argv $i] {
-makefile {
incr i
set ::SRCDIR [file normalize [lindex $argv $i]]
set ::MAKEFILE [lindex $argv $i]
}
-platform {
@@ -465,57 +310,15 @@ proc process_options {argv} {
}
-quick {
set ::QUICK 1
}
-veryquick {
set ::QUICK 2
incr i
set ::QUICK [lindex $argv $i]
}
-config {
incr i
set config [lindex $argv $i]
}
-buildonly {
set ::BUILDONLY 1
}
-dryrun {
set ::DRYRUN 1
}
-trace {
set ::TRACE 1
}
-info {
puts "Command-line Options:"
puts " --srcdir $::SRCDIR"
puts " --platform [list $platform]"
puts " --config [list $config]"
if {$::QUICK} {puts " --quick"}
if {$::BUILDONLY} {puts " --buildonly"}
if {$::DRYRUN} {puts " --dryrun"}
if {$::TRACE} {puts " --trace"}
puts "\nAvailable --platform options:"
foreach y [lsort [array names ::Platforms]] {
puts " [list $y]"
}
puts "\nAvailable --config options:"
foreach y [lsort [array names ::Configs]] {
puts " [list $y]"
}
exit
}
-g -
-D* -
-O* -
-enable-* -
-disable-* -
*=* {
lappend ::EXTRACONFIG [lindex $argv $i]
}
default {
puts stderr ""
puts stderr [string trim $::USAGE_MESSAGE]
@@ -524,6 +327,8 @@ proc process_options {argv} {
}
}
set ::MAKEFILE [file normalize $::MAKEFILE]
if {0==[info exists ::Platforms($platform)]} {
puts "Unknown platform: $platform"
puts -nonewline "Set the -platform option to "
@@ -542,16 +347,8 @@ proc process_options {argv} {
} else {
set ::CONFIGLIST $::Platforms($platform)
}
puts "Running the following test configurations for $platform:"
puts "Running the following configurations for $platform:"
puts " [string trim $::CONFIGLIST]"
puts -nonewline "Flags:"
if {$::DRYRUN} {puts -nonewline " --dryrun"}
if {$::BUILDONLY} {puts -nonewline " --buildonly"}
switch -- $::QUICK {
1 {puts -nonewline " --quick"}
2 {puts -nonewline " --veryquick"}
}
puts ""
}
# Main routine.
@@ -559,59 +356,30 @@ proc process_options {argv} {
proc main {argv} {
# Process any command line options.
set ::EXTRACONFIG {}
process_options $argv
puts [string repeat * 79]
set ::NERR 0
set ::NTEST 0
set ::NTESTCASE 0
set ::NERRCASE 0
set ::SQLITE_VERSION {}
set STARTTIME [clock seconds]
foreach {zConfig target} $::CONFIGLIST {
if {$target ne "checksymbols"} {
switch -- $::QUICK {
1 {set target test}
2 {set target smoketest}
}
if {$::BUILDONLY} {set target testfixture}
}
set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]
if {$::QUICK} {set target test}
set config_options $::Configs($zConfig)
incr NTEST
run_test_suite $zConfig $target $config_options
# If the configuration included the SQLITE_DEBUG option, then remove
# it and run veryquick.test. If it did not include the SQLITE_DEBUG option
# add it and run veryquick.test.
if {$target!="checksymbols" && $target!="valgrindtest"
&& !$::BUILDONLY && $::QUICK<2} {
if {$target!="checksymbols"} {
set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
set xtarget $target
regsub -all {fulltest[a-z]*} $xtarget test xtarget
if {$debug_idx < 0} {
incr NTEST
append config_options " -DSQLITE_DEBUG=1"
run_test_suite "${zConfig}_debug" $xtarget $config_options
run_test_suite "${zConfig}_debug" test [
concat $config_options -DSQLITE_DEBUG=1
]
} else {
incr NTEST
regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options
regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options
run_test_suite "${zConfig}_ndebug" $xtarget $config_options
run_test_suite "${zConfig}_ndebug" test [
lreplace $config_options $debug_idx $debug_idx
]
}
}
}
set elapsetime [expr {[clock seconds]-$STARTTIME}]
set hr [expr {$elapsetime/3600}]
set min [expr {($elapsetime/60)%60}]
set sec [expr {$elapsetime%60}]
set etime [format (%02d:%02d:%02d) $hr $min $sec]
puts [string repeat * 79]
puts "$::NERRCASE failures out of $::NTESTCASE tests in $etime"
if {$::SQLITE_VERSION ne ""} {
puts "SQLite $::SQLITE_VERSION"
}
}
-39
View File
@@ -1,39 +0,0 @@
# 2015-01-05
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file verifies that INSERT operations with a very large number of
# VALUE terms works and does not hit the SQLITE_LIMIT_COMPOUND_SELECT limit.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix selectG
# Do an INSERT with a VALUES clause that contains 100,000 entries. Verify
# that this insert happens quickly (in less than 10 seconds). Actually, the
# insert will normally happen in less than 0.5 seconds on a workstation, but
# we allow plenty of overhead for slower machines. The speed test checks
# for an O(N*N) inefficiency that was once in the code and that would make
# the insert run for over a minute.
#
do_test 100 {
set sql "CREATE TABLE t1(x);\nINSERT INTO t1(x) VALUES"
for {set i 1} {$i<100000} {incr i} {
append sql "($i),"
}
append sql "($i);"
set microsec [lindex [time {db eval $sql}] 0]
db eval {
SELECT count(x), sum(x), avg(x), $microsec<10000000 FROM t1;
}
} {100000 5000050000 50000.5 1}
finish_test
+13 -15
View File
@@ -207,10 +207,10 @@ do_test shell1-2.2.4 {
} {0 {}}
do_test shell1-2.2.5 {
catchcmd "test.db" ".mode \"insert FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}}
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
do_test shell1-2.2.6 {
catchcmd "test.db" ".mode \'insert FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}}
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
# check multiple tokens, and quoted tokens
do_test shell1-2.3.1 {
@@ -238,7 +238,7 @@ do_test shell1-2.3.7 {
# check quoted args are unquoted
do_test shell1-2.4.1 {
catchcmd "test.db" ".mode FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}}
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
do_test shell1-2.4.2 {
catchcmd "test.db" ".mode csv"
} {0 {}}
@@ -421,21 +421,20 @@ do_test shell1-3.12.3 {
} {1 {Usage: .indices ?LIKE-PATTERN?}}
# .mode MODE ?TABLE? Set output mode where MODE is one of:
# ascii Columns/rows delimited by 0x1F and 0x1E
# csv Comma-separated values
# column Left-aligned columns. (See .width)
# html HTML <table> code
# insert SQL insert statements for TABLE
# line One value per line
# list Values delimited by .separator strings
# list Values delimited by .separator string
# tabs Tab-separated values
# tcl TCL list elements
do_test shell1-3.13.1 {
catchcmd "test.db" ".mode"
} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}}
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
do_test shell1-3.13.2 {
catchcmd "test.db" ".mode FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}}
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
do_test shell1-3.13.3 {
catchcmd "test.db" ".mode csv"
} {0 {}}
@@ -468,10 +467,10 @@ do_test shell1-3.13.11 {
# don't allow partial mode type matches
do_test shell1-3.13.12 {
catchcmd "test.db" ".mode l"
} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}}
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
do_test shell1-3.13.13 {
catchcmd "test.db" ".mode li"
} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}}
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
do_test shell1-3.13.14 {
catchcmd "test.db" ".mode lin"
} {0 {}}
@@ -587,10 +586,10 @@ CREATE VIEW v2 AS SELECT x+1 AS y FROM t1;
CREATE VIEW v1 AS SELECT y+1 FROM v2;}}
db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}
# .separator STRING Change column separator used by output and .import
# .separator STRING Change separator used by output mode and .import
do_test shell1-3.22.1 {
catchcmd "test.db" ".separator"
} {1 {Usage: .separator COL ?ROW?}}
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
do_test shell1-3.22.2 {
catchcmd "test.db" ".separator FOO"
} {0 {}}
@@ -600,7 +599,7 @@ do_test shell1-3.22.3 {
do_test shell1-3.22.4 {
# too many arguments
catchcmd "test.db" ".separator FOO BAD BAD2"
} {1 {Usage: .separator COL ?ROW?}}
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
# .show Show the current values for various settings
do_test shell1-3.23.1 {
@@ -611,11 +610,10 @@ do_test shell1-3.23.1 {
[regexp {mode:} $res] \
[regexp {nullvalue:} $res] \
[regexp {output:} $res] \
[regexp {colseparator:} $res] \
[regexp {rowseparator:} $res] \
[regexp {separator:} $res] \
[regexp {stats:} $res] \
[regexp {width:} $res]
} {1 1 1 1 1 1 1 1 1 1}
} {1 1 1 1 1 1 1 1 1}
do_test shell1-3.23.2 {
# too many arguments
catchcmd "test.db" ".show BAD"
+5 -37
View File
@@ -55,7 +55,7 @@ do_test shell5-1.1.3 {
# .separator STRING Change separator used by output mode and .import
do_test shell5-1.2.1 {
catchcmd "test.db" ".separator"
} {1 {Usage: .separator COL ?ROW?}}
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
do_test shell5-1.2.2 {
catchcmd "test.db" ".separator ONE"
} {0 {}}
@@ -65,18 +65,12 @@ do_test shell5-1.2.3 {
do_test shell5-1.2.4 {
# too many arguments
catchcmd "test.db" ".separator ONE TWO THREE"
} {1 {Usage: .separator COL ?ROW?}}
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
# column separator should default to "|"
do_test shell5-1.3.1.1 {
# separator should default to "|"
do_test shell5-1.3.1 {
set res [catchcmd "test.db" ".show"]
list [regexp {colseparator: \"\|\"} $res]
} {1}
# row separator should default to "\n"
do_test shell5-1.3.1.2 {
set res [catchcmd "test.db" ".show"]
list [regexp {rowseparator: \"\\n\"} $res]
list [regexp {separator: \"\|\"} $res]
} {1}
# set separator to different value.
@@ -378,31 +372,5 @@ CREATE TABLE t4(a, b);
db eval { SELECT * FROM t4 }
} {xy\" hello one 2 {} {}}
#----------------------------------------------------------------------------
# Tests for the shell "ascii" import/export mode.
#
do_test shell5-3.1 {
set fd [open shell5.csv w]
fconfigure $fd -encoding binary -translation binary
puts -nonewline $fd "\"test 1\"\x1F,test 2\r\n\x1E"
puts -nonewline $fd "test 3\x1Ftest 4\n"
close $fd
catchcmd test.db {
.mode ascii
CREATE TABLE t5(a, b);
.import shell5.csv t5
}
db eval { SELECT * FROM t5 }
} "\{\"test 1\"} \{,test 2\r\n\} \{test 3\} \{test 4\n\}"
do_test shell5-3.2 {
set x [catchcmd test.db {
.mode ascii
SELECT * FROM t5;
}]
# Handle platform end-of-line differences
regsub -all {[\n\r]?\n} $x <EOL> x
set x
} "0 \{\"test 1\"\x1F,test 2<EOL>\x1Etest 3\x1Ftest 4<EOL>\x1E\}"
finish_test
-5
View File
@@ -16,11 +16,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort
db close
sqlite3_shutdown
sqlite3_config_pmasz 10
sqlite3_initialize
sqlite3 db test.db
# Create a bunch of data to sort against
#
-5
View File
@@ -17,11 +17,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort2
db close
sqlite3_shutdown
sqlite3_config_pmasz 10
sqlite3_initialize
sqlite3 db test.db
foreach {tn script} {
1 { }
-6
View File
@@ -17,12 +17,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort4
db close
sqlite3_shutdown
sqlite3_config_pmasz 10
sqlite3_initialize
sqlite3 db test.db
# Configure the sorter to use 3 background threads.
db eval {PRAGMA threads=3}
-6
View File
@@ -17,12 +17,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sortfault
db close
sqlite3_shutdown
sqlite3_config_pmasz 10
sqlite3_initialize
sqlite3 db test.db
do_execsql_test 1.0 {
PRAGMA cache_size = 5;
+117 -149
View File
@@ -1,41 +1,41 @@
/*
** 2010-07-22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** The code in this file runs a few multi-threaded test cases using the
** SQLite library. It can be compiled to an executable on unix using the
** following command:
**
** gcc -O2 threadtest3.c sqlite3.c -ldl -lpthread -lm
**
** Even though threadtest3.c is the only C source code file mentioned on
** the compiler command-line, #include macros are used to pull in additional
** C code files named "tt3_*.c".
** Then run the compiled program. The exit status is non-zero if any tests
** failed (hopefully there is also some output to stdout to clarify what went
** wrong).
**
** After compiling, run this program with an optional argument telling
** which test to run. All tests are run if no argument is given. The
** argument can be a glob pattern to match multiple tests. Examples:
** There are three parts to the code in this file, in the following order:
**
** ./a.out -- Run all tests
** ./a.out walthread3 -- Run the "walthread3" test
** ./a.out 'wal*' -- Run all of the wal* tests
** ./a.out --help -- List all available tests
** 1. Code for the SQL aggregate function md5sum() copied from
** tclsqlite.c in the SQLite distribution. The names of all the
** types and functions in this section begin with "MD5" or "md5".
**
** The exit status is non-zero if any test fails.
** 2. A set of utility functions that may be used to implement
** multi-threaded test cases. These are all called by test code
** via macros that help with error reporting. The macros are defined
** immediately below this comment.
**
** 3. The test code itself. And a main() routine to drive the test
** code.
*/
/*
** The "Set Error Line" macro.
/*************************************************************************
** Start of test code/infrastructure interface macros.
**
** The following macros constitute the interface between the test
** programs and the test infrastructure. Test infrastructure code
** does not itself use any of these macros. Test code should not
** call any of the macroname_x() functions directly.
**
** See the header comments above the corresponding macroname_x()
** function for a description of each interface.
*/
#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))
/* Database functions */
#define opendb(w,x,y,z) (SEL(w), opendb_x(w,x,y,z))
@@ -47,13 +47,10 @@
#define execsql_i64(x,y,...) (SEL(x), execsql_i64_x(x,y,__VA_ARGS__))
#define execsql_text(x,y,z,...) (SEL(x), execsql_text_x(x,y,z,__VA_ARGS__))
#define execsql(x,y,...) (SEL(x), (void)execsql_i64_x(x,y,__VA_ARGS__))
#define sql_script_printf(x,y,z,...) ( \
SEL(x), sql_script_printf_x(x,y,z,__VA_ARGS__) \
)
/* Thread functions */
#define launch_thread(w,x,y,z) (SEL(w), launch_thread_x(w,x,y,z))
#define join_all_threads(y,z) (SEL(y), join_all_threads_x(y,z))
#define launch_thread(w,x,y,z) (SEL(w), launch_thread_x(w,x,y,z))
#define join_all_threads(y,z) (SEL(y), join_all_threads_x(y,z))
/* Timer functions */
#define setstoptime(y,z) (SEL(y), setstoptime_x(y,z))
@@ -67,9 +64,6 @@
#define filesize(y,z) (SEL(y), filesize_x(y,z))
#define filecopy(x,y,z) (SEL(x), filecopy_x(x,y,z))
#define PTR2INT(x) ((int)((intptr_t)x))
#define INT2PTR(x) ((void*)((intptr_t)x))
/*
** End of test code/infrastructure interface macros.
*************************************************************************/
@@ -121,10 +115,7 @@ struct MD5Context {
int isInit;
uint32 buf[4];
uint32 bits[2];
union {
unsigned char in[64];
uint32 in32[16];
} u;
unsigned char in[64];
};
typedef struct MD5Context MD5Context;
@@ -273,7 +264,7 @@ void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
/* Handle any leading odd-sized chunks */
if ( t ) {
unsigned char *p = (unsigned char *)ctx->u.in + t;
unsigned char *p = (unsigned char *)ctx->in + t;
t = 64-t;
if (len < t) {
@@ -281,8 +272,8 @@ void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
return;
}
memcpy(p, buf, t);
byteReverse(ctx->u.in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->in);
buf += t;
len -= t;
}
@@ -290,16 +281,16 @@ void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->u.in, buf, 64);
byteReverse(ctx->u.in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->u.in, buf, len);
memcpy(ctx->in, buf, len);
}
/*
@@ -315,7 +306,7 @@ static void MD5Final(unsigned char digest[16], MD5Context *ctx){
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->u.in + count;
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
@@ -325,25 +316,25 @@ static void MD5Final(unsigned char digest[16], MD5Context *ctx){
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->u.in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32 *)ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->u.in, 0, 56);
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count-8);
}
byteReverse(ctx->u.in, 14);
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
ctx->u.in32[14] = ctx->bits[0];
ctx->u.in32[15] = ctx->bits[1];
((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
MD5Transform(ctx->buf, (uint32 *)ctx->in);
byteReverse((unsigned char *)ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(*ctx)); /* In case it is sensitive */
memset(ctx, 0, sizeof(ctx)); /* In case it is sensitive */
}
/*
@@ -391,9 +382,9 @@ static void md5finalize(sqlite3_context *context){
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
/*
/*************************************************************************
** End of copied md5sum() code.
**************************************************************************/
*/
typedef sqlite3_int64 i64;
@@ -407,6 +398,9 @@ typedef struct Thread Thread;
/* Total number of errors in this process so far. */
static int nGlobalErr = 0;
/* Set to true to run in "process" instead of "thread" mode. */
static int bProcessMode = 0;
struct Error {
int rc;
int iLine;
@@ -427,10 +421,10 @@ struct Statement {
struct Thread {
int iTid; /* Thread number within test */
void* pArg; /* Pointer argument passed by caller */
int iArg; /* Integer argument passed by caller */
pthread_t tid; /* Thread id */
char *(*xProc)(int, void*); /* Thread main proc */
char *(*xProc)(int, int); /* Thread main proc */
Thread *pNext; /* Next in this list of threads */
};
@@ -447,13 +441,8 @@ static void free_err(Error *p){
static void print_err(Error *p){
if( p->rc!=SQLITE_OK ){
int isWarn = 0;
if( p->rc==SQLITE_SCHEMA ) isWarn = 1;
if( sqlite3_strglob("* - no such table: *",p->zErr)==0 ) isWarn = 1;
printf("%s: (%d) \"%s\" at line %d\n", isWarn ? "Warning" : "Error",
p->rc, p->zErr, p->iLine);
if( !isWarn ) nGlobalErr++;
fflush(stdout);
printf("Error: (%d) \"%s\" at line %d\n", p->rc, p->zErr, p->iLine);
nGlobalErr++;
}
}
@@ -517,9 +506,8 @@ static void opendb_x(
){
if( pErr->rc==SQLITE_OK ){
int rc;
int flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
if( bDelete ) unlink(zFile);
rc = sqlite3_open_v2(zFile, &pDb->db, flags, 0);
rc = sqlite3_open(zFile, &pDb->db);
if( rc ){
sqlite_error(pErr, pDb, "open");
sqlite3_close(pDb->db);
@@ -568,22 +556,6 @@ static void sql_script_x(
}
}
static void sql_script_printf_x(
Error *pErr, /* IN/OUT: Error code */
Sqlite *pDb, /* Database handle */
const char *zFormat, /* SQL printf format string */
... /* Printf args */
){
va_list ap; /* ... printf arguments */
va_start(ap, zFormat);
if( pErr->rc==SQLITE_OK ){
char *zSql = sqlite3_vmprintf(zFormat, ap);
pErr->rc = sqlite3_exec(pDb->db, zSql, 0, 0, &pErr->zErr);
sqlite3_free(zSql);
}
va_end(ap);
}
static Statement *getSqlStatement(
Error *pErr, /* IN/OUT: Error code */
Sqlite *pDb, /* Database handle */
@@ -652,9 +624,11 @@ static i64 execsql_i64_x(
if( pErr->rc==SQLITE_OK ){
sqlite3_stmt *pStmt; /* SQL statement to execute */
va_list ap; /* ... arguments */
int i; /* Used to iterate through parameters */
va_start(ap, pDb);
pStmt = getAndBindSqlStatement(pErr, pDb, ap);
if( pStmt ){
int rc;
int first = 1;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
if( first && sqlite3_column_count(pStmt)>0 ){
@@ -689,9 +663,11 @@ static char * execsql_text_x(
if( pErr->rc==SQLITE_OK ){
sqlite3_stmt *pStmt; /* SQL statement to execute */
va_list ap; /* ... arguments */
int i; /* Used to iterate through parameters */
va_start(ap, iSlot);
pStmt = getAndBindSqlStatement(pErr, pDb, ap);
if( pStmt ){
int rc;
int first = 1;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
if( first && sqlite3_column_count(pStmt)>0 ){
@@ -717,13 +693,14 @@ static void integrity_check_x(
){
if( pErr->rc==SQLITE_OK ){
Statement *pStatement; /* Statement to execute */
int rc; /* Return code */
char *zErr = 0; /* Integrity check error */
pStatement = getSqlStatement(pErr, pDb, "PRAGMA integrity_check");
if( pStatement ){
sqlite3_stmt *pStmt = pStatement->pStmt;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
const char *z = (const char*)sqlite3_column_text(pStmt, 0);
const char *z = sqlite3_column_text(pStmt, 0);
if( strcmp(z, "ok") ){
if( zErr==0 ){
zErr = sqlite3_mprintf("%s", z);
@@ -744,14 +721,14 @@ static void integrity_check_x(
static void *launch_thread_main(void *pArg){
Thread *p = (Thread *)pArg;
return (void *)p->xProc(p->iTid, p->pArg);
return (void *)p->xProc(p->iTid, p->iArg);
}
static void launch_thread_x(
Error *pErr, /* IN/OUT: Error code */
Threadset *pThreads, /* Thread set */
char *(*xProc)(int, void*), /* Proc to run */
void *pArg /* Argument passed to thread proc */
char *(*xProc)(int, int), /* Proc to run */
int iArg /* Argument passed to thread proc */
){
if( pErr->rc==SQLITE_OK ){
int iTid = ++pThreads->iMaxTid;
@@ -761,7 +738,7 @@ static void launch_thread_x(
p = (Thread *)sqlite3_malloc(sizeof(Thread));
memset(p, 0, sizeof(Thread));
p->iTid = iTid;
p->pArg = pArg;
p->iArg = iArg;
p->xProc = xProc;
rc = pthread_create(&p->tid, NULL, launch_thread_main, (void *)p);
@@ -790,7 +767,6 @@ static void join_all_threads_x(
if( pErr->rc==SQLITE_OK ) system_error(pErr, rc);
}else{
printf("Thread %d says: %s\n", p->iTid, (ret==0 ? "..." : (char *)ret));
fflush(stdout);
}
sqlite3_free(p);
}
@@ -904,6 +880,11 @@ static int timetostop_x(
return ret;
}
/*
** The "Set Error Line" macro.
*/
#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))
/*************************************************************************
**************************************************************************
@@ -914,7 +895,7 @@ static int timetostop_x(
#define WALTHREAD1_NTHREAD 10
#define WALTHREAD3_NTHREAD 6
static char *walthread1_thread(int iTid, void *pArg){
static char *walthread1_thread(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
int nIter = 0; /* Iterations so far */
@@ -953,7 +934,7 @@ static char *walthread1_thread(int iTid, void *pArg){
return sqlite3_mprintf("%d iterations", nIter);
}
static char *walthread1_ckpt_thread(int iTid, void *pArg){
static char *walthread1_ckpt_thread(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
int nCkpt = 0; /* Checkpoints so far */
@@ -985,7 +966,6 @@ static void walthread1(int nMs){
"INSERT INTO t1 VALUES(randomblob(100));"
"INSERT INTO t1 SELECT md5sum(x) FROM t1;"
);
closedb(&err, &db);
setstoptime(&err, nMs);
for(i=0; i<WALTHREAD1_NTHREAD; i++){
@@ -997,11 +977,10 @@ static void walthread1(int nMs){
print_and_free_err(&err);
}
static char *walthread2_thread(int iTid, void *pArg){
static char *walthread2_thread(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
int anTrans[2] = {0, 0}; /* Number of WAL and Rollback transactions */
int iArg = PTR2INT(pArg);
const char *zJournal = "PRAGMA journal_mode = WAL";
if( iArg ){ zJournal = "PRAGMA journal_mode = DELETE"; }
@@ -1047,18 +1026,17 @@ static void walthread2(int nMs){
setstoptime(&err, nMs);
launch_thread(&err, &threads, walthread2_thread, 0);
launch_thread(&err, &threads, walthread2_thread, 0);
launch_thread(&err, &threads, walthread2_thread, (void*)1);
launch_thread(&err, &threads, walthread2_thread, (void*)1);
launch_thread(&err, &threads, walthread2_thread, 1);
launch_thread(&err, &threads, walthread2_thread, 1);
join_all_threads(&err, &threads);
print_and_free_err(&err);
}
static char *walthread3_thread(int iTid, void *pArg){
static char *walthread3_thread(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
i64 iNextWrite; /* Next value this thread will write */
int iArg = PTR2INT(pArg);
opendb(&err, &db, "test.db", 0);
sql_script(&err, &db, "PRAGMA wal_autocheckpoint = 10");
@@ -1109,14 +1087,14 @@ static void walthread3(int nMs){
setstoptime(&err, nMs);
for(i=0; i<WALTHREAD3_NTHREAD; i++){
launch_thread(&err, &threads, walthread3_thread, INT2PTR(i));
launch_thread(&err, &threads, walthread3_thread, i);
}
join_all_threads(&err, &threads);
print_and_free_err(&err);
}
static char *walthread4_reader_thread(int iTid, void *pArg){
static char *walthread4_reader_thread(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
@@ -1130,7 +1108,7 @@ static char *walthread4_reader_thread(int iTid, void *pArg){
return 0;
}
static char *walthread4_writer_thread(int iTid, void *pArg){
static char *walthread4_writer_thread(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
i64 iRow = 1;
@@ -1170,7 +1148,7 @@ static void walthread4(int nMs){
print_and_free_err(&err);
}
static char *walthread5_thread(int iTid, void *pArg){
static char *walthread5_thread(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
i64 nRow;
@@ -1302,7 +1280,7 @@ static void cgt_pager_1(int nMs){
** is an attempt to find a bug reported to us.
*/
static char *dynamic_triggers_1(int iTid, void *pArg){
static char *dynamic_triggers_1(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
int nDrop = 0;
@@ -1348,13 +1326,12 @@ static char *dynamic_triggers_1(int iTid, void *pArg){
nDrop++;
}
}
closedb(&err, &db);
print_and_free_err(&err);
return sqlite3_mprintf("%d created, %d dropped", nCreate, nDrop);
}
static char *dynamic_triggers_2(int iTid, void *pArg){
static char *dynamic_triggers_2(int iTid, int iArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
i64 iVal = 0;
@@ -1375,7 +1352,6 @@ static char *dynamic_triggers_2(int iTid, void *pArg){
nDelete++;
} while( iVal );
}
closedb(&err, &db);
print_and_free_err(&err);
return sqlite3_mprintf("%d inserts, %d deletes", nInsert, nDelete);
@@ -1400,16 +1376,15 @@ static void dynamic_triggers(int nMs){
"CREATE TABLE t8(x, y);"
"CREATE TABLE t9(x, y);"
);
closedb(&err, &db);
setstoptime(&err, nMs);
sqlite3_enable_shared_cache(1);
launch_thread(&err, &threads, dynamic_triggers_2, 0);
launch_thread(&err, &threads, dynamic_triggers_2, 0);
sqlite3_enable_shared_cache(0);
sleep(2);
sqlite3_enable_shared_cache(0);
launch_thread(&err, &threads, dynamic_triggers_2, 0);
launch_thread(&err, &threads, dynamic_triggers_1, 0);
@@ -1419,71 +1394,62 @@ static void dynamic_triggers(int nMs){
print_and_free_err(&err);
}
#include "tt3_checkpoint.c"
#include "tt3_index.c"
#include "tt3_lookaside1.c"
#include "tt3_vacuum.c"
#include "tt3_stress.c"
int main(int argc, char **argv){
struct ThreadTest {
void (*xTest)(int); /* Routine for running this test */
const char *zTest; /* Name of this test */
int nMs; /* How long to run this test, in milliseconds */
void (*xTest)(int);
const char *zTest;
int nMs;
} aTest[] = {
{ walthread1, "walthread1", 20000 },
{ walthread2, "walthread2", 20000 },
{ walthread3, "walthread3", 20000 },
{ walthread4, "walthread4", 20000 },
{ walthread5, "walthread5", 1000 },
{ walthread5, "walthread5", 1000 },
{ cgt_pager_1, "cgt_pager_1", 0 },
{ dynamic_triggers, "dynamic_triggers", 20000 },
{ checkpoint_starvation_1, "checkpoint_starvation_1", 10000 },
{ checkpoint_starvation_2, "checkpoint_starvation_2", 10000 },
{ create_drop_index_1, "create_drop_index_1", 10000 },
{ lookaside1, "lookaside1", 10000 },
{ vacuum1, "vacuum1", 10000 },
{ stress1, "stress1", 10000 },
{ stress2, "stress2", 60000 },
};
static char *substArgv[] = { 0, "*", 0 };
int i, iArg;
int nTestfound = 0;
int i;
char *zTest = 0;
int nTest = 0;
int bTestfound = 0;
int bPrefix = 0;
if( argc>2 ) goto usage;
if( argc==2 ){
zTest = argv[1];
nTest = strlen(zTest);
if( zTest[nTest-1]=='*' ){
nTest--;
bPrefix = 1;
}
}
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
if( argc<2 ){
argc = 2;
argv = substArgv;
}
for(iArg=1; iArg<argc; iArg++){
for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
if( sqlite3_strglob(argv[iArg],aTest[i].zTest)==0 ) break;
}
if( i>=sizeof(aTest)/sizeof(aTest[0]) ) goto usage;
}
for(iArg=1; iArg<argc; iArg++){
for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
char const *z = aTest[i].zTest;
if( sqlite3_strglob(argv[iArg],z)==0 ){
printf("Running %s for %d seconds...\n", z, aTest[i].nMs/1000);
fflush(stdout);
aTest[i].xTest(aTest[i].nMs);
nTestfound++;
}
}
}
if( nTestfound==0 ) goto usage;
printf("%d errors out of %d tests\n", nGlobalErr, nTestfound);
for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
char const *z = aTest[i].zTest;
int n = strlen(z);
if( !zTest || ((bPrefix || n==nTest) && 0==strncmp(zTest, z, nTest)) ){
printf("Running %s for %d seconds...\n", z, aTest[i].nMs/1000);
aTest[i].xTest(aTest[i].nMs);
bTestfound++;
}
}
if( bTestfound==0 ) goto usage;
printf("Total of %d errors across all tests\n", nGlobalErr);
return (nGlobalErr>0 ? 255 : 0);
usage:
printf("Usage: %s [testname|testprefix*]...\n", argv[0]);
printf("Usage: %s [testname|testprefix*]\n", argv[0]);
printf("Available tests are:\n");
for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
printf(" %s\n", aTest[i].zTest);
@@ -1491,3 +1457,5 @@ int main(int argc, char **argv){
return 254;
}
-484
View File
@@ -1,484 +0,0 @@
/*
** 2014-12-11
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements a simple standalone program used to stress the
** SQLite library when accessing the same set of databases simultaneously
** from multiple threads in shared-cache mode.
**
** This test program runs on unix-like systems only. It uses pthreads.
** To compile:
**
** gcc -g -Wall -I. threadtest4.c sqlite3.c -ldl -lpthread
**
** To run:
**
** ./a.out 10
**
** The argument is the number of threads. There are also options, such
** as -wal and -multithread and -serialized.
**
** Consider also compiling with clang instead of gcc and adding the
** -fsanitize=thread option.
*/
#include "sqlite3.h"
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
/*
** An instance of the following structure is passed into each worker
** thread.
*/
typedef struct WorkerInfo WorkerInfo;
struct WorkerInfo {
int tid; /* Thread ID */
int nWorker; /* Total number of workers */
unsigned wkrFlags; /* Flags */
sqlite3 *mainDb; /* Database connection of the main thread */
sqlite3 *db; /* Database connection of this thread */
int nErr; /* Number of errors seen by this thread */
int nTest; /* Number of tests run by this thread */
char *zMsg; /* Message returned by this thread */
pthread_t id; /* Thread id */
pthread_mutex_t *pWrMutex; /* Hold this mutex while writing */
};
/*
** Allowed values for WorkerInfo.wkrFlags
*/
#define TT4_SERIALIZED 0x0000001 /* The --serialized option is used */
#define TT4_WAL 0x0000002 /* WAL mode in use */
#define TT4_TRACE 0x0000004 /* Trace activity */
/*
** Report an OOM error and die if the argument is NULL
*/
static void check_oom(void *x){
if( x==0 ){
fprintf(stderr, "out of memory\n");
exit(1);
}
}
/*
** Allocate memory. If the allocation fails, print an error message and
** kill the process.
*/
static void *safe_malloc(int sz){
void *x = sqlite3_malloc(sz>0?sz:1);
check_oom(x);
return x;
}
/*
** Print a trace message for a worker
*/
static void worker_trace(WorkerInfo *p, const char *zFormat, ...){
va_list ap;
char *zMsg;
if( (p->wkrFlags & TT4_TRACE)==0 ) return;
va_start(ap, zFormat);
zMsg = sqlite3_vmprintf(zFormat, ap);
check_oom(zMsg);
va_end(ap);
fprintf(stderr, "TRACE(%02d): %s\n", p->tid, zMsg);
sqlite3_free(zMsg);
}
/*
** Prepare a single SQL query
*/
static sqlite3_stmt *prep_sql(sqlite3 *db, const char *zFormat, ...){
va_list ap;
char *zSql;
int rc;
sqlite3_stmt *pStmt = 0;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
check_oom(zSql);
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error (%d,%d): %s\nWhile preparing: [%s]\n",
rc, sqlite3_extended_errcode(db), sqlite3_errmsg(db), zSql);
exit(1);
}
sqlite3_free(zSql);
return pStmt;
}
/*
** Run a SQL statements. Panic if unable.
*/
static void run_sql(WorkerInfo *p, const char *zFormat, ...){
va_list ap;
char *zSql;
int rc;
sqlite3_stmt *pStmt = 0;
int nRetry = 0;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
check_oom(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error (%d,%d): %s\nWhile preparing: [%s]\n",
rc, sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zSql);
exit(1);
}
worker_trace(p, "running [%s]", zSql);
while( (rc = sqlite3_step(pStmt))!=SQLITE_DONE ){
if( (rc&0xff)==SQLITE_BUSY || (rc&0xff)==SQLITE_LOCKED ){
sqlite3_reset(pStmt);
nRetry++;
if( nRetry<10 ){
worker_trace(p, "retry %d for [%s]", nRetry, zSql);
sched_yield();
continue;
}else{
fprintf(stderr, "Deadlock in thread %d while running [%s]\n",
p->tid, zSql);
exit(1);
}
}
if( rc!=SQLITE_ROW ){
fprintf(stderr, "SQL error (%d,%d): %s\nWhile running [%s]\n",
rc, sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zSql);
exit(1);
}
}
sqlite3_free(zSql);
sqlite3_finalize(pStmt);
}
/*
** Open the database connection for WorkerInfo. The order in which
** the files are opened is a function of the tid value.
*/
static void worker_open_connection(WorkerInfo *p, int iCnt){
char *zFile;
int x;
int rc;
static const unsigned char aOrder[6][3] = {
{ 1, 2, 3},
{ 1, 3, 2},
{ 2, 1, 3},
{ 2, 3, 1},
{ 3, 1, 2},
{ 3, 2, 1}
};
x = (p->tid + iCnt) % 6;
zFile = sqlite3_mprintf("tt4-test%d.db", aOrder[x][0]);
check_oom(zFile);
worker_trace(p, "open %s", zFile);
rc = sqlite3_open_v2(zFile, &p->db,
SQLITE_OPEN_READWRITE|SQLITE_OPEN_SHAREDCACHE, 0);
if( rc!=SQLITE_OK ){
fprintf(stderr, "sqlite_open_v2(%s) failed on thread %d\n",
zFile, p->tid);
exit(1);
}
sqlite3_free(zFile);
run_sql(p, "PRAGMA read_uncommitted=ON;");
sqlite3_busy_timeout(p->db, 10000);
run_sql(p, "PRAGMA synchronous=OFF;");
run_sql(p, "ATTACH 'tt4-test%d.db' AS aux1", aOrder[x][1]);
run_sql(p, "ATTACH 'tt4-test%d.db' AS aux2", aOrder[x][2]);
}
/*
** Close the worker database connection
*/
static void worker_close_connection(WorkerInfo *p){
if( p->db ){
worker_trace(p, "close");
sqlite3_close(p->db);
p->db = 0;
}
}
/*
** Delete all content in the three databases associated with a
** single thread. Make this happen all in a single transaction if
** inTrans is true, or separately for each database if inTrans is
** false.
*/
static void worker_delete_all_content(WorkerInfo *p, int inTrans){
if( inTrans ){
pthread_mutex_lock(p->pWrMutex);
run_sql(p, "BEGIN");
run_sql(p, "DELETE FROM t1 WHERE tid=%d", p->tid);
run_sql(p, "DELETE FROM t2 WHERE tid=%d", p->tid);
run_sql(p, "DELETE FROM t3 WHERE tid=%d", p->tid);
run_sql(p, "COMMIT");
pthread_mutex_unlock(p->pWrMutex);
p->nTest++;
}else{
pthread_mutex_lock(p->pWrMutex);
run_sql(p, "DELETE FROM t1 WHERE tid=%d", p->tid);
pthread_mutex_unlock(p->pWrMutex);
p->nTest++;
pthread_mutex_lock(p->pWrMutex);
run_sql(p, "DELETE FROM t2 WHERE tid=%d", p->tid);
pthread_mutex_unlock(p->pWrMutex);
p->nTest++;
pthread_mutex_lock(p->pWrMutex);
run_sql(p, "DELETE FROM t3 WHERE tid=%d", p->tid);
pthread_mutex_unlock(p->pWrMutex);
p->nTest++;
}
}
/*
** Create rows mn through mx in table iTab for the given worker
*/
static void worker_add_content(WorkerInfo *p, int mn, int mx, int iTab){
char *zTabDef;
switch( iTab ){
case 1: zTabDef = "t1(tid,sp,a,b,c)"; break;
case 2: zTabDef = "t2(tid,sp,d,e,f)"; break;
case 3: zTabDef = "t3(tid,sp,x,y,z)"; break;
}
pthread_mutex_lock(p->pWrMutex);
run_sql(p,
"WITH RECURSIVE\n"
" c(i) AS (VALUES(%d) UNION ALL SELECT i+1 FROM c WHERE i<%d)\n"
"INSERT INTO %s SELECT %d, zeroblob(3000), i, printf('%%d',i), i FROM c;",
mn, mx, zTabDef, p->tid
);
pthread_mutex_unlock(p->pWrMutex);
p->nTest++;
}
/*
** Set an error message on a worker
*/
static void worker_error(WorkerInfo *p, const char *zFormat, ...){
va_list ap;
p->nErr++;
sqlite3_free(p->zMsg);
va_start(ap, zFormat);
p->zMsg = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
}
/*
** Each thread runs the following function.
*/
static void *worker_thread(void *pArg){
WorkerInfo *p = (WorkerInfo*)pArg;
int iOuter;
int i;
int rc;
sqlite3_stmt *pStmt;
printf("worker %d startup\n", p->tid); fflush(stdout);
for(iOuter=1; iOuter<=p->nWorker; iOuter++){
worker_open_connection(p, iOuter);
for(i=0; i<4; i++){
worker_add_content(p, i*100+1, (i+1)*100, (p->tid+iOuter)%3 + 1);
worker_add_content(p, i*100+1, (i+1)*100, (p->tid+iOuter+1)%3 + 1);
worker_add_content(p, i*100+1, (i+1)*100, (p->tid+iOuter+2)%3 + 1);
}
pStmt = prep_sql(p->db, "SELECT count(a) FROM t1 WHERE tid=%d", p->tid);
worker_trace(p, "query [%s]", sqlite3_sql(pStmt));
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ){
worker_error(p, "Failed to step: %s", sqlite3_sql(pStmt));
}else if( sqlite3_column_int(pStmt, 0)!=400 ){
worker_error(p, "Wrong result: %d", sqlite3_column_int(pStmt,0));
}
sqlite3_finalize(pStmt);
if( p->nErr ) break;
if( ((iOuter+p->tid)%3)==0 ){
sqlite3_db_release_memory(p->db);
p->nTest++;
}
pthread_mutex_lock(p->pWrMutex);
run_sql(p, "BEGIN;");
run_sql(p, "UPDATE t1 SET c=NULL WHERE a=55");
run_sql(p, "UPDATE t2 SET f=NULL WHERE d=42");
run_sql(p, "UPDATE t3 SET z=NULL WHERE x=31");
run_sql(p, "ROLLBACK;");
p->nTest++;
pthread_mutex_unlock(p->pWrMutex);
if( iOuter==p->tid ){
pthread_mutex_lock(p->pWrMutex);
run_sql(p, "VACUUM");
pthread_mutex_unlock(p->pWrMutex);
}
pStmt = prep_sql(p->db,
"SELECT t1.rowid, t2.rowid, t3.rowid"
" FROM t1, t2, t3"
" WHERE t1.tid=%d AND t2.tid=%d AND t3.tid=%d"
" AND t1.a<>t2.d AND t2.d<>t3.x"
" ORDER BY 1, 2, 3"
,p->tid, p->tid, p->tid);
worker_trace(p, "query [%s]", sqlite3_sql(pStmt));
for(i=0; i<p->nWorker; i++){
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ){
worker_error(p, "Failed to step: %s", sqlite3_sql(pStmt));
break;
}
sched_yield();
}
sqlite3_finalize(pStmt);
if( p->nErr ) break;
worker_delete_all_content(p, (p->tid+iOuter)%2);
worker_close_connection(p);
p->db = 0;
}
worker_close_connection(p);
printf("worker %d finished\n", p->tid); fflush(stdout);
return 0;
}
int main(int argc, char **argv){
int nWorker = 0; /* Number of worker threads */
int i; /* Loop counter */
WorkerInfo *aInfo; /* Information for each worker */
unsigned wkrFlags = 0; /* Default worker flags */
int nErr = 0; /* Number of errors */
int nTest = 0; /* Number of tests */
int rc; /* Return code */
sqlite3 *db = 0; /* Main database connection */
pthread_mutex_t wrMutex; /* The write serialization mutex */
WorkerInfo infoTop; /* WorkerInfo for the main thread */
WorkerInfo *p; /* Pointer to infoTop */
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' ){
if( z[1]=='-' && z[2]!=0 ) z++;
if( strcmp(z,"-multithread")==0 ){
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
wkrFlags &= ~TT4_SERIALIZED;
}else if( strcmp(z,"-serialized")==0 ){
sqlite3_config(SQLITE_CONFIG_SERIALIZED);
wkrFlags |= TT4_SERIALIZED;
}else if( strcmp(z,"-wal")==0 ){
wkrFlags |= TT4_WAL;
}else if( strcmp(z,"-trace")==0 ){
wkrFlags |= TT4_TRACE;
}else{
fprintf(stderr, "unknown command-line option: %s\n", argv[i]);
exit(1);
}
}else if( z[0]>='1' && z[0]<='9' && nWorker==0 ){
nWorker = atoi(z);
if( nWorker<2 ){
fprintf(stderr, "minimum of 2 threads\n");
exit(1);
}
}else{
fprintf(stderr, "extra command-line argument: \"%s\"\n", argv[i]);
exit(1);
}
}
if( nWorker==0 ){
fprintf(stderr,
"usage: %s ?OPTIONS? N\n"
"N is the number of threads and must be at least 2.\n"
"Options:\n"
" --serialized\n"
" --multithread\n"
" --wal\n"
" --trace\n"
,argv[0]
);
exit(1);
}
if( !sqlite3_threadsafe() ){
fprintf(stderr, "requires a threadsafe build of SQLite\n");
exit(1);
}
sqlite3_initialize();
sqlite3_enable_shared_cache(1);
pthread_mutex_init(&wrMutex, 0);
/* Initialize the test database files */
(void)unlink("tt4-test1.db");
(void)unlink("tt4-test2.db");
(void)unlink("tt4-test3.db");
rc = sqlite3_open("tt4-test1.db", &db);
if( rc!=SQLITE_OK ){
fprintf(stderr, "Unable to open test database: tt4-test2.db\n");
exit(1);
}
memset(&infoTop, 0, sizeof(infoTop));
infoTop.db = db;
infoTop.wkrFlags = wkrFlags;
p = &infoTop;
if( wkrFlags & TT4_WAL ){
run_sql(p, "PRAGMA journal_mode=WAL");
}
run_sql(p, "PRAGMA synchronous=OFF");
run_sql(p, "CREATE TABLE IF NOT EXISTS t1(tid INTEGER, sp, a, b, c)");
run_sql(p, "CREATE INDEX t1tid ON t1(tid)");
run_sql(p, "CREATE INDEX t1ab ON t1(a,b)");
run_sql(p, "ATTACH 'tt4-test2.db' AS 'test2'");
run_sql(p, "CREATE TABLE IF NOT EXISTS test2.t2(tid INTEGER, sp, d, e, f)");
run_sql(p, "CREATE INDEX test2.t2tid ON t2(tid)");
run_sql(p, "CREATE INDEX test2.t2de ON t2(d,e)");
run_sql(p, "ATTACH 'tt4-test3.db' AS 'test3'");
run_sql(p, "CREATE TABLE IF NOT EXISTS test3.t3(tid INTEGER, sp, x, y, z)");
run_sql(p, "CREATE INDEX test3.t3tid ON t3(tid)");
run_sql(p, "CREATE INDEX test3.t3xy ON t3(x,y)");
aInfo = safe_malloc( sizeof(*aInfo)*nWorker );
memset(aInfo, 0, sizeof(*aInfo)*nWorker);
for(i=0; i<nWorker; i++){
aInfo[i].tid = i+1;
aInfo[i].nWorker = nWorker;
aInfo[i].wkrFlags = wkrFlags;
aInfo[i].mainDb = db;
aInfo[i].pWrMutex = &wrMutex;
rc = pthread_create(&aInfo[i].id, 0, worker_thread, &aInfo[i]);
if( rc!=0 ){
fprintf(stderr, "thread creation failed for thread %d\n", i+1);
exit(1);
}
sched_yield();
}
for(i=0; i<nWorker; i++){
pthread_join(aInfo[i].id, 0);
printf("Joined thread %d: %d errors in %d tests",
aInfo[i].tid, aInfo[i].nErr, aInfo[i].nTest);
if( aInfo[i].zMsg ){
printf(": %s\n", aInfo[i].zMsg);
}else{
printf("\n");
}
nErr += aInfo[i].nErr;
nTest += aInfo[i].nTest;
fflush(stdout);
}
sqlite3_close(db);
sqlite3_free(aInfo);
printf("Total %d errors in %d tests\n", nErr, nTest);
return nErr;
}
+4 -2
View File
@@ -1,5 +1,5 @@
/*
** 2011-02-02
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -66,7 +66,7 @@ static int checkpoint_starvation_walhook(
return SQLITE_OK;
}
static char *checkpoint_starvation_reader(int iTid, void *pArg){
static char *checkpoint_starvation_reader(int iTid, int iArg){
Error err = {0};
Sqlite db = {0};
@@ -146,3 +146,5 @@ static void checkpoint_starvation_2(int nMs){
}
print_and_free_err(&err);
}
-74
View File
@@ -1,74 +0,0 @@
/*
** 2014 December 9
**
** 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.
**
*************************************************************************
**
** create_drop_index_1
*/
static char *create_drop_index_thread(int iTid, void *pArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
while( !timetostop(&err) ){
opendb(&err, &db, "test.db", 0);
sql_script(&err, &db,
"DROP INDEX IF EXISTS i1;"
"DROP INDEX IF EXISTS i2;"
"DROP INDEX IF EXISTS i3;"
"DROP INDEX IF EXISTS i4;"
"CREATE INDEX IF NOT EXISTS i1 ON t11(a);"
"CREATE INDEX IF NOT EXISTS i2 ON t11(b);"
"CREATE INDEX IF NOT EXISTS i3 ON t11(c);"
"CREATE INDEX IF NOT EXISTS i4 ON t11(d);"
"SELECT * FROM t11 ORDER BY a;"
"SELECT * FROM t11 ORDER BY b;"
"SELECT * FROM t11 ORDER BY c;"
"SELECT * FROM t11 ORDER BY d;"
);
clear_error(&err, SQLITE_LOCKED);
closedb(&err, &db);
}
print_and_free_err(&err);
return sqlite3_mprintf("ok");
}
static void create_drop_index_1(int nMs){
Error err = {0};
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1);
sql_script(&err, &db,
"CREATE TABLE t11(a, b, c, d);"
"WITH data(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM data WHERE x<100) "
"INSERT INTO t11 SELECT x,x,x,x FROM data;"
);
closedb(&err, &db);
setstoptime(&err, nMs);
sqlite3_enable_shared_cache(1);
launch_thread(&err, &threads, create_drop_index_thread, 0);
launch_thread(&err, &threads, create_drop_index_thread, 0);
launch_thread(&err, &threads, create_drop_index_thread, 0);
launch_thread(&err, &threads, create_drop_index_thread, 0);
launch_thread(&err, &threads, create_drop_index_thread, 0);
join_all_threads(&err, &threads);
sqlite3_enable_shared_cache(0);
print_and_free_err(&err);
}

Some files were not shown because too many files have changed in this diff Show More