From ddb595fbc985c288cd0543ab9dadc473e9d9cd06 Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Mon, 26 Dec 2011 14:52:17 -0500
Subject: [PATCH] upstream 3.7.9
---
Makefile.in | 40 +-
Makefile.msc | 202 +-
Makefile.vxworks | 2 +-
VERSION | 2 +-
configure | 6435 ++++++++++++-----------------------
doc/lemon.html | 2 +-
ext/fts3/README.content | 178 +
ext/fts3/fts3.c | 1576 ++++++---
ext/fts3/fts3Int.h | 40 +-
ext/fts3/fts3_expr.c | 30 +-
ext/fts3/fts3_hash.c | 1 -
ext/fts3/fts3_snippet.c | 9 +-
ext/fts3/fts3_test.c | 3 +
ext/fts3/fts3_tokenizer.c | 5 -
ext/fts3/fts3_write.c | 199 +-
ext/rtree/rtree.c | 11 +-
main.mk | 58 +-
manifest | 640 ++--
manifest.uuid | 2 +-
mkopcodec.awk | 9 +-
src/analyze.c | 761 ++++-
src/backup.c | 195 +-
src/btree.c | 133 +-
src/build.c | 252 +-
src/ctime.c | 10 +-
src/date.c | 51 +-
src/delete.c | 4 +-
src/expr.c | 49 +-
src/fkey.c | 20 +-
src/func.c | 16 +-
src/global.c | 2 +-
src/insert.c | 3 +
src/lempar.c | 5 +-
src/loadext.c | 9 +-
src/main.c | 23 +-
src/mem3.c | 6 +-
src/mutex.h | 7 +-
src/os.c | 8 +-
src/os_common.h | 11 +-
src/os_unix.c | 356 +-
src/os_win.c | 477 ++-
src/pager.c | 43 +-
src/pager.h | 2 +
src/pcache1.c | 21 +-
src/pragma.c | 10 +-
src/printf.c | 151 +-
src/resolve.c | 61 +-
src/select.c | 208 +-
src/shell.c | 165 +-
src/sqlite.h.in | 97 +-
src/sqlite3ext.h | 53 +-
src/sqliteInt.h | 83 +-
src/status.c | 22 +
src/tclsqlite.c | 228 +-
src/test1.c | 189 +-
src/test6.c | 10 +
src/test8.c | 52 +-
src/test_config.c | 19 +-
src/test_malloc.c | 10 +-
src/test_multiplex.c | 486 +--
src/test_quota.c | 171 +-
src/test_rtree.c | 2 +
src/test_stat.c | 63 +-
src/test_syscall.c | 2 +-
src/test_thread.c | 19 +-
src/test_vfs.c | 21 +-
src/trigger.c | 19 +-
src/update.c | 6 +-
src/utf.c | 2 +-
src/util.c | 18 +-
src/vacuum.c | 14 +-
src/vdbe.c | 254 +-
src/vdbe.h | 14 +-
src/vdbeInt.h | 27 +
src/vdbeapi.c | 4 +-
src/vdbeaux.c | 233 +-
src/vdbeblob.c | 4 +-
src/vdbemem.c | 42 +-
src/vdbesort.c | 882 +++++
src/vtab.c | 4 +-
src/wal.c | 6 +-
src/where.c | 773 +++--
test/8_3_names.test | 8 +-
test/all.test | 1 +
test/alter.test | 10 +-
test/alter2.test | 5 +-
test/alter3.test | 6 +-
test/alter4.test | 6 +-
test/analyze.test | 58 +
test/analyze2.test | 554 ---
test/analyze3.test | 36 +-
test/analyze5.test | 146 +-
test/analyze6.test | 2 +-
test/analyze7.test | 22 +-
test/analyze8.test | 103 +
test/async.test | 2 +-
test/async2.test | 2 +-
test/async3.test | 4 +-
test/async5.test | 2 +-
test/attach.test | 22 +-
test/attach2.test | 8 +-
test/attach3.test | 4 +-
test/attach4.test | 6 +-
test/attachmalloc.test | 8 +-
test/auth.test | 8 +-
test/autoinc.test | 6 +-
test/autoindex1.test | 10 +
test/autovacuum.test | 8 +-
test/autovacuum_ioerr2.test | 8 +-
test/backcompat.test | 4 +-
test/backup.test | 52 +-
test/backup2.test | 18 +-
test/backup_ioerr.test | 6 +-
test/capi3.test | 8 +-
test/capi3c.test | 8 +-
test/collate5.test | 6 +-
test/collate7.test | 2 +-
test/corrupt.test | 32 +-
test/corrupt2.test | 42 +-
test/corrupt3.test | 2 +-
test/corrupt9.test | 6 +-
test/corruptA.test | 10 +-
test/corruptB.test | 16 +-
test/corruptC.test | 42 +-
test/corruptD.test | 4 +-
test/corruptE.test | 20 +-
test/crash.test | 6 +-
test/crash3.test | 6 +-
test/crash4.test | 2 +-
test/crash5.test | 2 +-
test/crash6.test | 6 +-
test/crash7.test | 2 +-
test/crash8.test | 14 +-
test/createtab.test | 2 +-
test/dbstatus.test | 18 +-
test/dbstatus2.test | 76 +
test/delete.test | 6 +-
test/descidx1.test | 6 +-
test/diskfull.test | 4 +-
test/distinct.test | 166 +
test/e_expr.test | 6 +-
test/e_fts3.test | 4 +-
test/e_select.test | 12 +-
test/enc2.test | 26 +-
test/enc3.test | 4 +-
test/enc4.test | 4 +-
test/errmsg.test | 116 +
test/exclusive.test | 16 +-
test/exclusive2.test | 4 +-
test/exists.test | 2 +-
test/fallocate.test | 2 +-
test/filectrl.test | 2 +-
test/filefmt.test | 10 +-
test/fkey_malloc.test | 2 +-
test/fts-9fd058691.test | 59 +
test/fts1j.test | 6 +-
test/fts1o.test | 2 +-
test/fts2j.test | 6 +-
test/fts2o.test | 4 +-
test/fts3aj.test | 6 +-
test/fts3ao.test | 7 +-
test/fts3auto.test | 52 +-
test/fts3d.test | 53 +
test/fts3defer.test | 40 +
test/fts3drop.test | 61 +
test/fts3fault.test | 10 +-
test/fts3fault2.test | 49 +
test/fts3first.test | 163 +
test/fts3malloc.test | 1 +
test/fts3matchinfo.test | 16 +
test/fts3prefix.test | 10 +
test/fts3snippet.test | 2 +-
test/fts3sort.test | 23 +
test/fts4aa.test | 2 +-
test/fts4content.test | 501 +++
test/func3.test | 38 +-
test/fuzz_malloc.test | 2 +-
test/fuzzer1.test | 2 +-
test/hook.test | 4 +-
test/incrblob.test | 6 +-
test/incrblob_err.test | 6 +-
test/incrvacuum.test | 12 +-
test/incrvacuum2.test | 2 +-
test/incrvacuum_ioerr.test | 2 +-
test/index4.test | 126 +
test/indexfault.test | 342 ++
test/insert4.test | 2 +-
test/insert5.test | 2 +-
test/io.test | 12 +-
test/ioerr.test | 8 +-
test/ioerr4.test | 10 +-
test/journal1.test | 8 +-
test/journal2.test | 2 +-
test/journal3.test | 2 +-
test/jrnlmode.test | 12 +-
test/jrnlmode2.test | 2 +-
test/jrnlmode3.test | 4 +-
test/like.test | 13 +-
test/loadext.test | 2 +-
test/lock4.test | 2 +-
test/lock5.test | 4 +-
test/main.test | 14 +-
test/malloc.test | 34 +-
test/malloc3.test | 4 +-
test/malloc5.test | 6 +-
test/mallocA.test | 6 +-
test/malloc_common.tcl | 4 +-
test/manydb.test | 4 +-
test/memsubsys1.test | 2 +-
test/memsubsys2.test | 2 +-
test/misc1.test | 2 +-
test/misc2.test | 6 +-
test/misc3.test | 6 +-
test/misc5.test | 6 +-
test/misc7.test | 30 +-
test/misuse.test | 4 +-
test/multiplex.test | 85 +-
test/nan.test | 46 +
test/notify1.test | 4 +-
test/notify2.test | 2 +-
test/notify3.test | 2 +-
test/openv2.test | 2 +-
test/oserror.test | 36 +-
test/pager1.test | 113 +-
test/pagerfault.test | 6 +-
test/pageropt.test | 2 +-
test/pagesize.test | 8 +-
test/pcache2.test | 5 +-
test/permutations.test | 24 +-
test/pragma.test | 34 +-
test/pragma2.test | 8 +-
test/printf.test | 2 +-
test/quota.test | 131 +-
test/releasetest.tcl | 3 +-
test/rollback.test | 4 +-
test/savepoint.test | 16 +-
test/savepoint6.test | 2 +-
test/securedel.test | 2 +-
test/selectB.test | 2 +-
test/server1.test | 2 +-
test/shared.test | 30 +-
test/shared2.test | 2 +-
test/shared3.test | 2 +-
test/shared4.test | 8 +-
test/shared6.test | 2 +-
test/shared7.test | 2 +-
test/speed3.test | 2 +-
test/sqllimits1.test | 22 +-
test/stat.test | 26 +-
test/subquery2.test | 86 +
test/superlock.test | 5 +
test/sync.test | 4 +-
test/syscall.test | 2 +-
test/table.test | 16 +-
test/tclsqlite.test | 11 +
test/temptable.test | 7 +-
test/temptrigger.test | 4 +-
test/tester.tcl | 197 +-
test/thread001.test | 4 +-
test/thread002.test | 4 +-
test/thread003.test | 8 +-
test/thread005.test | 2 +-
test/tkt-2d1a5c67d.test | 4 +-
test/tkt-31338dca7e.test | 101 +
test/tkt-54844eea3f.test | 67 +
test/tkt-5ee23731f.test | 2 +-
test/tkt-b1d3a2e531.test | 109 +
test/tkt-c48d99d690.test | 26 +
test/tkt-cbd054fa6b.test | 6 +-
test/tkt-d635236375.test | 38 +
test/tkt-f3e5abed55.test | 6 +-
test/tkt-fa7bf5ec.test | 39 +
test/tkt1667.test | 2 +-
test/tkt1873.test | 2 +-
test/tkt2686.test | 2 +-
test/tkt2817.test | 2 +-
test/tkt2820.test | 4 +-
test/tkt2854.test | 2 +-
test/tkt3457.test | 12 +-
test/tkt35xx.test | 2 +-
test/tkt3793.test | 18 +-
test/trigger1.test | 4 +-
test/trigger4.test | 6 +-
test/triggerA.test | 10 +-
test/triggerC.test | 2 +-
test/triggerD.test | 45 +
test/unordered.test | 6 +-
test/uri.test | 76 +-
test/vacuum.test | 30 +-
test/vacuum2.test | 2 +-
test/vacuum3.test | 2 +-
test/view.test | 2 +-
test/vtab1.test | 19 +-
test/vtab7.test | 4 +-
test/vtabC.test | 2 +-
test/vtabF.test | 45 +
test/wal.test | 62 +-
test/wal2.test | 25 +-
test/wal3.test | 21 +-
test/wal4.test | 2 +-
test/wal5.test | 9 +-
test/wal6.test | 13 +-
test/walbak.test | 84 +-
test/walbig.test | 5 +
test/walcksum.test | 30 +-
test/walcrash.test | 22 +-
test/walfault.test | 2 +-
test/walmode.test | 2 +-
test/walnoshm.test | 8 +-
test/walpersist.test | 73 +
test/walro.test | 13 +-
test/walslow.test | 8 +-
test/walthread.test | 10 +-
test/where3.test | 83 +
test/where7.test | 4 +-
test/where9.test | 84 +-
test/win32lock.test | 133 +
tool/extract.c | 46 +
tool/lemon.c | 2 +
tool/mksqlite3c-noext.tcl | 308 ++
tool/mksqlite3c.tcl | 16 +-
tool/offsets.c | 329 ++
tool/omittest.tcl | 44 +-
tool/spaceanal.tcl | 198 +-
tool/symbols-mingw.sh | 33 +
tool/symbols.sh | 10 +-
tool/tostr.awk | 1 -
tool/warnings-clang.sh | 13 +
tool/warnings.sh | 9 +-
329 files changed, 14623 insertions(+), 8786 deletions(-)
create mode 100644 ext/fts3/README.content
create mode 100644 src/vdbesort.c
delete mode 100644 test/analyze2.test
create mode 100644 test/analyze8.test
create mode 100644 test/dbstatus2.test
create mode 100644 test/distinct.test
create mode 100644 test/errmsg.test
create mode 100644 test/fts-9fd058691.test
create mode 100644 test/fts3drop.test
create mode 100644 test/fts3first.test
create mode 100644 test/fts4content.test
create mode 100644 test/index4.test
create mode 100644 test/indexfault.test
create mode 100644 test/subquery2.test
create mode 100644 test/tkt-54844eea3f.test
create mode 100644 test/tkt-b1d3a2e531.test
create mode 100644 test/tkt-c48d99d690.test
create mode 100644 test/tkt-d635236375.test
create mode 100644 test/tkt-fa7bf5ec.test
create mode 100644 test/vtabF.test
create mode 100644 test/walpersist.test
create mode 100644 test/win32lock.test
create mode 100644 tool/extract.c
create mode 100644 tool/mksqlite3c-noext.tcl
create mode 100644 tool/offsets.c
create mode 100644 tool/symbols-mingw.sh
create mode 100644 tool/warnings-clang.sh
diff --git a/Makefile.in b/Makefile.in
index 4a81e156..cbcf8eca 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -177,8 +177,8 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
table.lo tokenize.lo trigger.lo \
update.lo util.lo vacuum.lo \
- vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbetrace.lo \
- wal.lo walker.lo where.lo utf.lo vtab.lo
+ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
+ vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
# Object files for the amalgamation.
#
@@ -274,6 +274,7 @@ SRC = \
$(TOP)/src/vdbeaux.c \
$(TOP)/src/vdbeblob.c \
$(TOP)/src/vdbemem.c \
+ $(TOP)/src/vdbesort.c \
$(TOP)/src/vdbetrace.c \
$(TOP)/src/vdbeInt.h \
$(TOP)/src/vtab.c \
@@ -517,6 +518,9 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
+sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl
+ $(TCLSH_CMD) $(TOP)/tool/split-sqlite3c.tcl
+
# Rule to build the amalgamation
#
sqlite3.lo: sqlite3.c
@@ -737,6 +741,9 @@ vdbeblob.lo: $(TOP)/src/vdbeblob.c $(HDR)
vdbemem.lo: $(TOP)/src/vdbemem.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbemem.c
+vdbesort.lo: $(TOP)/src/vdbesort.c $(HDR)
+ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbesort.c
+
vdbetrace.lo: $(TOP)/src/vdbetrace.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbetrace.c
@@ -768,7 +775,7 @@ tclsqlite3$(TEXE): tclsqlite-shell.lo libsqlite3.la
# Rules to build opcodes.c and opcodes.h
#
opcodes.c: opcodes.h $(TOP)/mkopcodec.awk
- sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c
+ $(NAWK) -f $(TOP)/mkopcodec.awk opcodes.h >opcodes.c
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
cat parse.h $(TOP)/src/vdbe.c | $(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h
@@ -785,7 +792,7 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk
$(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
- tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
+ $(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
$(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
@@ -859,6 +866,7 @@ rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
#
TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
+TESTFIXTURE_FLAGS += -DBUILD_sqlite
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
@@ -878,18 +886,16 @@ soaktest: testfixture$(TEXE) sqlite3$(TEXE)
test: testfixture$(TEXE) sqlite3$(TEXE)
./testfixture$(TEXE) $(TOP)/test/veryquick.test
-sqlite3_analyzer$(TEXE): $(TESTFIXTURE_SRC) $(TOP)/tool/spaceanal.tcl
- sed \
- -e '/^#/d' \
- -e 's,\\,\\\\,g' \
- -e 's,",\\",g' \
- -e 's,^,",' \
- -e 's,$$,\\n",' \
- $(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h
- $(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \
- -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE \
- $(TEMP_STORE) -o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
+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 >> $@
+ echo "static const char *tclsh_main_loop(void){" >> $@
+ echo "static const char *zMainloop = " >> $@
+ $(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@
+ echo "; return zMainloop; }" >> $@
+sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
+ $(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
# Standard install and cleanup targets
#
@@ -923,9 +929,11 @@ clean:
rm -f $(PUBLISH)
rm -f *.da *.bb *.bbg gmon.out
rm -rf tsrc .target_source
+ rm -f tclsqlite3$(TEXE)
rm -f testfixture$(TEXE) test.db
- rm -f sqlite3.dll sqlite3.lib sqlite3.def
+ rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
rm -f sqlite3.c
+ rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
distclean: clean
rm -f config.log config.status libtool Makefile sqlite3.pc
diff --git a/Makefile.msc b/Makefile.msc
index a6d1bf4c..f40936d9 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -11,22 +11,43 @@ TOP = .
#
USE_AMALGAMATION = 1
+# Set this non-0 to use the International Components for Unicode (ICU).
+#
+USE_ICU = 0
+
+# Set this to non-0 to create and use PDBs.
+#
+SYMBOLS = 1
+
+# Set this to one of the following values to enable various debugging
+# features. Each level includes the debugging options from the previous
+# levels. Currently, the recognized values for DEBUG are:
+#
+# 0 == NDEBUG: Disables assert() and other runtime diagnostics.
+# 1 == 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.
+#
+DEBUG = 0
+
# Version numbers and release number for the SQLite being compiled.
#
VERSION = 3.7
-VERSION_NUMBER = 3007007
-RELEASE = 3.7.7
+VERSION_NUMBER = 3007009
+RELEASE = 3.7.9
# C Compiler and options for use in building executables that
# will run on the platform that is doing the build.
#
-BCC = cl.exe -O2
+BCC = cl.exe
# 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.)
#
-TCC = cl.exe -W3 -O2 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise
+TCC = cl.exe -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise
# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in
# any extension header files by default. For non-amalgamation
@@ -41,18 +62,82 @@ TCC = $(TCC) -I$(TOP)\ext\rtree
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#
+!IF $(DEBUG)==0
TCC = $(TCC) -DNDEBUG
+!ENDIF
+
+!IF $(DEBUG)>1
+TCC = $(TCC) -DSQLITE_DEBUG
+!ENDIF
+
+!IF $(DEBUG)>3
+TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
+!ENDIF
+
+!IF $(DEBUG)>4
+TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
+!ENDIF
-# The library that programs using TCL must link against.
#
-LIBTCL = tcl85.lib
+# Prevent warnings about "insecure" runtime library functions being used.
+#
+TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
+
+#
+# Use native Win32 heap instead of malloc/free?
+#
+# TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
+
+#
+# Validate the heap on every call into the native Win32 heap subsystem?
+#
+!IF $(DEBUG)>2
+TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
+!ENDIF
+
+# The locations of the Tcl header and library files. Also, the library that
+# non-stubs enabled programs using Tcl must link against. These variables
+# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
+# prior to running nmake in order to match the actual installed location and
+# version on this machine.
+#
+!if "$(TCLINCDIR)" == ""
TCLINCDIR = c:\tcl\include
+!endif
+
+!if "$(TCLLIBDIR)" == ""
TCLLIBDIR = c:\tcl\lib
+!endif
+
+!if "$(LIBTCL)" == ""
+LIBTCL = tcl85.lib
+!endif
+
+# The locations of the ICU header and library files. These variables
+# (ICUINCDIR, ICULIBDIR, and LIBICU) may be overridden via the environment
+# prior to running nmake in order to match the actual installed location on
+# this machine.
+#
+!if "$(ICUINCDIR)" == ""
+ICUINCDIR = c:\icu\include
+!endif
+
+!if "$(ICULIBDIR)" == ""
+ICULIBDIR = c:\icu\lib
+!endif
+
+!if "$(LIBICU)" == ""
+LIBICU = icuuc.lib icuin.lib
+!endif
# This is the command to use for tclsh - normally just "tclsh", but we may
-# know the specific version we want to use
+# know the specific version we want to use. This variable (TCLSH_CMD) may be
+# overridden via the environment prior to running nmake in order to select a
+# specific Tcl shell to use.
#
+!if "$(TCLSH_CMD)" == ""
TCLSH_CMD = tclsh85
+!endif
# Compiler options needed for programs that use the readline() library.
#
@@ -72,7 +157,9 @@ TCC = $(TCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
# Any target libraries which libsqlite must be linked against
#
+!if "$(TLIBS)" == ""
TLIBS =
+!endif
# Flags controlling use of the in memory btree implementation
#
@@ -103,6 +190,25 @@ TCC = $(TCC) $(OPT_FEATURE_FLAGS)
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
TCC = $(TCC) $(OPTS)
+# If symbols are enabled, enable PDBs.
+# If debugging is enabled, disable all optimizations and enable PDBs.
+!IF $(DEBUG)>0
+TCC = $(TCC) -Od -D_DEBUG
+!ELSE
+TCC = $(TCC) -O2
+!ENDIF
+
+!IF $(DEBUG)>0 || $(SYMBOLS)!=0
+TCC = $(TCC) -Zi
+!ENDIF
+
+# If ICU support is enabled, add the compiler options for it.
+!IF $(USE_ICU)!=0
+TCC = $(TCC) -DSQLITE_ENABLE_ICU=1
+TCC = $(TCC) -I$(TOP)\ext\icu
+TCC = $(TCC) -I$(ICUINCDIR)
+!ENDIF
+
# libtool compile/link
LTCOMPILE = $(TCC) -Fo$@
LTLIB = lib.exe
@@ -117,8 +223,23 @@ LTLINKOPTS = /MACHINE:$(PLATFORM)
LTLIBOPTS = /MACHINE:$(PLATFORM)
!ENDIF
+# If debugging is enabled, enable PDBs.
+!IF $(DEBUG)>0 || $(SYMBOLS)!=0
+LTLINKOPTS = $(LTLINKOPTS) /DEBUG
+!ENDIF
+
+# Start with the Tcl related linker options.
+LTLIBPATHS = /LIBPATH:$(TCLLIBDIR)
+LTLIBS = $(LIBTCL)
+
+# If ICU support is enabled, add the linker options for it.
+!IF $(USE_ICU)!=0
+LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR)
+LTLIBS = $(LTLIBS) $(LIBICU)
+!ENDIF
+
# nawk compatible awk.
-NAWK = .\gawk.exe
+NAWK = gawk.exe
# You should not have to change anything below this line
###############################################################################
@@ -141,8 +262,8 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
table.lo tokenize.lo trigger.lo \
update.lo util.lo vacuum.lo \
- vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbetrace.lo \
- wal.lo walker.lo where.lo utf.lo vtab.lo
+ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
+ vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
# Object files for the amalgamation.
#
@@ -241,6 +362,7 @@ SRC = \
$(TOP)\src\vdbeaux.c \
$(TOP)\src\vdbeblob.c \
$(TOP)\src\vdbemem.c \
+ $(TOP)\src\vdbesort.c \
$(TOP)\src\vdbetrace.c \
$(TOP)\src\vdbeInt.h \
$(TOP)\src\vtab.c \
@@ -382,6 +504,7 @@ TESTSRC2 = \
$(TOP)\src\vdbeaux.c \
$(TOP)\src\vdbe.c \
$(TOP)\src\vdbemem.c \
+ $(TOP)\src\vdbesort.c \
$(TOP)\src\vdbetrace.c \
$(TOP)\src\where.c \
parse.c \
@@ -439,18 +562,18 @@ EXTHDR = $(EXTHDR) \
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
-all: libsqlite3.lib sqlite3.exe libtclsqlite3.lib
+all: dll libsqlite3.lib sqlite3.exe libtclsqlite3.lib
libsqlite3.lib: $(LIBOBJ)
$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
- $(LTLIB) $(LTLIBOPTS) /LIBPATH:$(TCLLIBDIR) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
+ $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib sqlite3.h
$(LTLINK) $(READLINE_FLAGS) \
$(TOP)\src\shell.c \
- /link $(LTLINKOPTS) libsqlite3.lib $(LIBREADLINE) $(TLIBS)
+ /link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBREADLINE) $(LTLIBS) $(TLIBS)
# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
@@ -463,13 +586,16 @@ sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib sqlite3.h
-mkdir tsrc
for %i in ($(SRC)) do copy /Y %i tsrc
del /Q tsrc\sqlite.h.in tsrc\parse.y
- $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl vdbe.new
+ $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new
move vdbe.new tsrc\vdbe.c
echo > .target_source
sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl
+sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl
+ $(TCLSH_CMD) $(TOP)/tool/split-sqlite3c.tcl
+
# Rule to build the amalgamation
#
sqlite3.lo: sqlite3.c
@@ -692,6 +818,9 @@ vdbeblob.lo: $(TOP)\src\vdbeblob.c $(HDR)
vdbemem.lo: $(TOP)\src\vdbemem.c $(HDR)
$(LTCOMPILE) -c $(TOP)\src\vdbemem.c
+vdbesort.lo: $(TOP)\src\vdbesort.c $(HDR)
+ $(LTCOMPILE) -c $(TOP)\src\vdbesort.c
+
vdbetrace.lo: $(TOP)\src\vdbetrace.c $(HDR)
$(LTCOMPILE) -c $(TOP)\src\vdbetrace.c
@@ -715,15 +844,15 @@ tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR)
tclsqlite3.exe: tclsqlite-shell.lo libsqlite3.lib
$(LTLINK) tclsqlite-shell.lo \
- /link $(LTLINKOPTS) /LIBPATH:$(TCLLIBDIR) libsqlite3.lib $(LIBTCL)
+ /link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LTLIBS) $(TLIBS)
# Rules to build opcodes.c and opcodes.h
#
opcodes.c: opcodes.h $(TOP)\mkopcodec.awk
- $(NAWK) "/#define OP_/ { print }" opcodes.h | sort /+45 | $(NAWK) -f $(TOP)\mkopcodec.awk >opcodes.c
+ $(NAWK) -f $(TOP)\mkopcodec.awk opcodes.h > opcodes.c
opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\mkopcodeh.awk
- type parse.h $(TOP)\src\vdbe.c | $(NAWK) -f $(TOP)\mkopcodeh.awk >opcodes.h
+ type parse.h $(TOP)\src\vdbe.c | $(NAWK) -f $(TOP)\mkopcodeh.awk > opcodes.h
# Rules to build parse.c and parse.h - the outputs of lemon.
#
@@ -734,16 +863,16 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk
copy $(TOP)\src\parse.y .
.\lemon.exe $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
move parse.h parse.h.temp
- $(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp >parse.h
+ $(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h
sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
- $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP) >sqlite3.h
+ $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP) > sqlite3.h
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) -Femkkeywordhash.exe $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
- .\mkkeywordhash.exe >keywordhash.h
+ .\mkkeywordhash.exe > keywordhash.h
@@ -826,7 +955,7 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(HDR)
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
-DBUILD_sqlite -I$(TCLINCDIR) \
$(TESTFIXTURE_SRC) \
- /link $(LTLINKOPTS) /LIBPATH:$(TCLLIBDIR) $(LIBTCL) $(TLIBS)
+ /link $(LTLINKOPTS) $(LTLIBPATHS) $(LTLIBS) $(TLIBS)
fulltest: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\all.test
@@ -837,28 +966,29 @@ soaktest: testfixture.exe sqlite3.exe
test: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\veryquick.test
-spaceanal_tcl.h: $(TOP)\tool\spaceanal.tcl
- $(NAWK) -f $(TOP)/tool/tostr.awk \
- $(TOP)\tool\spaceanal.tcl >spaceanal_tcl.h
+sqlite3_analyzer.c: sqlite3.c $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
+ copy sqlite3.c + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@
+ echo static const char *tclsh_main_loop(void){ >> $@
+ echo static const char *zMainloop = >> $@
+ $(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@
+ echo ; return zMainloop; } >> $@
-sqlite3_analyzer.exe: $(TESTFIXTURE_SRC) spaceanal_tcl.h
- $(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \
- -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE \
- -DBUILD_sqlite -I$(TCLINCDIR) \
- $(TESTFIXTURE_SRC) \
- /link $(LTLINKOPTS) /LIBPATH:$(TCLLIBDIR) $(LIBTCL) $(TLIBS)
+sqlite3_analyzer.exe: sqlite3_analyzer.c
+ $(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
+ /link $(LTLINKOPTS) $(LTLIBPATHS) $(LTLIBS) $(TLIBS)
clean:
- del /Q *.lo *.lib *.obj sqlite3.exe libsqlite3.lib
+ del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
del /Q sqlite3.h opcodes.c opcodes.h
del /Q lemon.exe lempar.c parse.*
del /Q mkkeywordhash.exe keywordhash.h
-rmdir /Q/S tsrc
del /Q .target_source
+ del /Q tclsqlite3.exe
del /Q testfixture.exe testfixture.exp test.db
del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
del /Q sqlite3.c
- del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp spaceanal_tcl.h
+ del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c
#
# Windows section
@@ -866,10 +996,10 @@ clean:
dll: sqlite3.dll
sqlite3.def: libsqlite3.lib
- echo EXPORTS >sqlite3.def
+ echo EXPORTS > sqlite3.def
dumpbin /all libsqlite3.lib \
- | $(NAWK) "/ 1 _sqlite3_/ { sub(/^.* _/,\"\");print }" \
- | sort >>sqlite3.def
+ | $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \
+ | sort >> sqlite3.def
sqlite3.dll: $(LIBOBJ) sqlite3.def
- link $(LTLINKOPTS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ)
+ link $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LTLIBS) $(TLIBS)
diff --git a/Makefile.vxworks b/Makefile.vxworks
index 993e5579..8d57da72 100644
--- a/Makefile.vxworks
+++ b/Makefile.vxworks
@@ -517,7 +517,7 @@ tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
# Rules to build opcodes.c and opcodes.h
#
opcodes.c: opcodes.h $(TOP)/mkopcodec.awk
- sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c
+ $(NAWK) -f $(TOP)/mkopcodec.awk opcodes.h >opcodes.c
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
cat parse.h $(TOP)/src/vdbe.c | \
diff --git a/VERSION b/VERSION
index 9076adfe..c77a7de8 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.7.7.1
+3.7.9
diff --git a/configure b/configure
index b565366d..79cd72de 100755
--- a/configure
+++ b/configure
@@ -1,18 +1,22 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.62 for sqlite 3.7.7.1.
+# Generated by GNU Autoconf 2.67 for sqlite 3.7.9.
+#
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
@@ -20,23 +24,15 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
esac
-
fi
-
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
as_nl='
'
export as_nl
@@ -44,7 +40,13 @@ export as_nl
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
as_echo='printf %s\n'
as_echo_n='printf %s'
else
@@ -55,7 +57,7 @@ else
as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
as_echo_n_body='eval
arg=$1;
- case $arg in
+ case $arg in #(
*"$as_nl"*)
expr "X$arg" : "X\\(.*\\)$as_nl";
arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
@@ -78,13 +80,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
}
fi
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
# IFS
# We need space, tab and new line, in precisely that order. Quoting is
@@ -94,15 +89,15 @@ fi
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
-case $0 in
+case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
IFS=$as_save_IFS
;;
@@ -114,12 +109,16 @@ if test "x$as_myself" = x; then
fi
if test ! -f "$as_myself"; then
$as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- { (exit 1); exit 1; }
+ exit 1
fi
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
@@ -131,7 +130,248 @@ export LC_ALL
LANGUAGE=C
export LANGUAGE
-# Required to use basename.
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
@@ -145,8 +385,12 @@ else
as_basename=false
fi
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
-# Name of the executable.
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
@@ -166,295 +410,19 @@ $as_echo X/"$0" |
}
s/.*/./; q'`
-# CDPATH.
-$as_unset CDPATH
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
-if test "x$CONFIG_SHELL" = x; then
- if (eval ":") 2>/dev/null; then
- as_have_required=yes
-else
- as_have_required=no
-fi
-
- if test $as_have_required = yes && (eval ":
-(as_func_return () {
- (exit \$1)
-}
-as_func_success () {
- as_func_return 0
-}
-as_func_failure () {
- as_func_return 1
-}
-as_func_ret_success () {
- return 0
-}
-as_func_ret_failure () {
- return 1
-}
-
-exitcode=0
-if as_func_success; then
- :
-else
- exitcode=1
- echo as_func_success failed.
-fi
-
-if as_func_failure; then
- exitcode=1
- echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
- :
-else
- exitcode=1
- echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
- exitcode=1
- echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
- :
-else
- exitcode=1
- echo positional parameters were not saved.
-fi
-
-test \$exitcode = 0) || { (exit 1); exit 1; }
-
-(
- as_lineno_1=\$LINENO
- as_lineno_2=\$LINENO
- test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
- test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
-") 2> /dev/null; then
- :
-else
- as_candidate_shells=
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- case $as_dir in
- /*)
- for as_base in sh bash ksh sh5; do
- as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
- done;;
- esac
-done
-IFS=$as_save_IFS
-
-
- for as_shell in $as_candidate_shells $SHELL; do
- # Try only shells that exist, to save several forks.
- if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { ("$as_shell") 2> /dev/null <<\_ASEOF
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
-esac
-
-fi
-
-
-:
-_ASEOF
-}; then
- CONFIG_SHELL=$as_shell
- as_have_required=yes
- if { "$as_shell" 2> /dev/null <<\_ASEOF
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
-esac
-
-fi
-
-
-:
-(as_func_return () {
- (exit $1)
-}
-as_func_success () {
- as_func_return 0
-}
-as_func_failure () {
- as_func_return 1
-}
-as_func_ret_success () {
- return 0
-}
-as_func_ret_failure () {
- return 1
-}
-
-exitcode=0
-if as_func_success; then
- :
-else
- exitcode=1
- echo as_func_success failed.
-fi
-
-if as_func_failure; then
- exitcode=1
- echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
- :
-else
- exitcode=1
- echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
- exitcode=1
- echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = "$1" ); then
- :
-else
- exitcode=1
- echo positional parameters were not saved.
-fi
-
-test $exitcode = 0) || { (exit 1); exit 1; }
-
-(
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
-
-_ASEOF
-}; then
- break
-fi
-
-fi
-
- done
-
- if test "x$CONFIG_SHELL" != x; then
- for as_var in BASH_ENV ENV
- do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
- done
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
-fi
-
-
- if test $as_have_required = no; then
- echo This script requires a shell more modern than all the
- echo shells that I found on your system. Please install a
- echo modern shell, or manually run the script under such a
- echo shell if you do have one.
- { (exit 1); exit 1; }
-fi
-
-
-fi
-
-fi
-
-
-
-(eval "as_func_return () {
- (exit \$1)
-}
-as_func_success () {
- as_func_return 0
-}
-as_func_failure () {
- as_func_return 1
-}
-as_func_ret_success () {
- return 0
-}
-as_func_ret_failure () {
- return 1
-}
-
-exitcode=0
-if as_func_success; then
- :
-else
- exitcode=1
- echo as_func_success failed.
-fi
-
-if as_func_failure; then
- exitcode=1
- echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
- :
-else
- exitcode=1
- echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
- exitcode=1
- echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
- :
-else
- exitcode=1
- echo positional parameters were not saved.
-fi
-
-test \$exitcode = 0") || {
- echo No shell found that supports shell functions.
- echo Please tell bug-autoconf@gnu.org about your system,
- echo including any error possibly output before this message.
- echo This can help us improve future autoconf versions.
- echo Configuration will now proceed without shell functions.
-}
-
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line after each line using $LINENO; the second 'sed'
- # does the real work. The second script uses 'N' to pair each
- # line-number line with the line containing $LINENO, and appends
- # trailing '-' during substitution so that $LINENO is not a special
- # case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # scripts with optimization help from Paolo Bonzini. Blame Lee
- # E. McMahon (1931-1989) for sed's syntax. :-)
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
sed -n '
p
/[$]LINENO/=
@@ -471,8 +439,7 @@ test \$exitcode = 0") || {
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
- { (exit 1); exit 1; }; }
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
@@ -482,29 +449,18 @@ test \$exitcode = 0") || {
exit
}
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
-
ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
+case `echo -n x` in #(((((
-n*)
- case `echo 'x\c'` in
+ case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
- *) ECHO_C='\c';;
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
@@ -534,7 +490,7 @@ rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
+ as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
@@ -553,10 +509,10 @@ else
if test -d "$1"; then
test -d "$1/.";
else
- case $1 in
+ case $1 in #(
-*)set "./$1";;
esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
???[sx]*):;;*)false;;esac;fi
'\'' sh
'
@@ -571,7 +527,6 @@ as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
# Check that we are running under the correct shell.
SHELL=${CONFIG_SHELL-/bin/sh}
@@ -720,10 +675,11 @@ fi
-exec 7<&0 &1
+test -n "$DJDIR" || exec 7<&0 &1
# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
@@ -738,14 +694,14 @@ cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.7.7.1'
-PACKAGE_STRING='sqlite 3.7.7.1'
+PACKAGE_VERSION='3.7.9'
+PACKAGE_STRING='sqlite 3.7.9'
PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
# Factoring default headers for most tests.
ac_includes_default="\
@@ -783,121 +739,122 @@ ac_includes_default="\
# include
#endif"
-ac_subst_vars='SHELL
-PATH_SEPARATOR
-PACKAGE_NAME
-PACKAGE_TARNAME
-PACKAGE_VERSION
-PACKAGE_STRING
-PACKAGE_BUGREPORT
-exec_prefix
-prefix
-program_transform_name
-bindir
-sbindir
-libexecdir
-datarootdir
-datadir
-sysconfdir
-sharedstatedir
-localstatedir
-includedir
-oldincludedir
-docdir
-infodir
-htmldir
-dvidir
-pdfdir
-psdir
-libdir
-localedir
-mandir
-DEFS
-ECHO_C
-ECHO_N
-ECHO_T
-LIBS
-build_alias
-host_alias
-target_alias
-LIBTOOL
-build
-build_cpu
-build_vendor
-build_os
-host
-host_cpu
-host_vendor
-host_os
-CC
-CFLAGS
-LDFLAGS
-CPPFLAGS
-ac_ct_CC
-EXEEXT
-OBJEXT
-SED
-GREP
-EGREP
-FGREP
-LD
-DUMPBIN
-ac_ct_DUMPBIN
-NM
-LN_S
-OBJDUMP
-AR
-STRIP
-RANLIB
-lt_ECHO
-DSYMUTIL
-NMEDIT
-LIPO
-OTOOL
-OTOOL64
-CPP
-INSTALL_PROGRAM
-INSTALL_SCRIPT
-INSTALL_DATA
-AWK
-TCLSH_CMD
-TCLLIBDIR
-program_prefix
-VERSION
-RELEASE
-VERSION_NUMBER
-BUILD_CC
-SQLITE_THREADSAFE
-XTHREADCONNECT
-ALLOWRELEASE
-TEMP_STORE
-BUILD_EXEEXT
-SQLITE_OS_UNIX
-SQLITE_OS_WIN
-SQLITE_OS_OS2
-TARGET_EXEEXT
-TCL_VERSION
-TCL_BIN_DIR
-TCL_SRC_DIR
-TCL_LIBS
-TCL_INCLUDE_SPEC
-TCL_LIB_FILE
-TCL_LIB_FLAG
-TCL_LIB_SPEC
-TCL_STUB_LIB_FILE
-TCL_STUB_LIB_FLAG
-TCL_STUB_LIB_SPEC
-HAVE_TCL
-TARGET_READLINE_LIBS
-TARGET_READLINE_INC
-TARGET_HAVE_READLINE
-TARGET_DEBUG
-USE_AMALGAMATION
-OPT_FEATURE_FLAGS
-USE_GCOV
-BUILD_CFLAGS
+ac_subst_vars='LTLIBOBJS
LIBOBJS
-LTLIBOBJS'
+BUILD_CFLAGS
+USE_GCOV
+OPT_FEATURE_FLAGS
+USE_AMALGAMATION
+TARGET_DEBUG
+TARGET_HAVE_READLINE
+TARGET_READLINE_INC
+TARGET_READLINE_LIBS
+HAVE_TCL
+TCL_STUB_LIB_SPEC
+TCL_STUB_LIB_FLAG
+TCL_STUB_LIB_FILE
+TCL_LIB_SPEC
+TCL_LIB_FLAG
+TCL_LIB_FILE
+TCL_INCLUDE_SPEC
+TCL_LIBS
+TCL_SRC_DIR
+TCL_BIN_DIR
+TCL_VERSION
+TARGET_EXEEXT
+SQLITE_OS_OS2
+SQLITE_OS_WIN
+SQLITE_OS_UNIX
+BUILD_EXEEXT
+TEMP_STORE
+ALLOWRELEASE
+XTHREADCONNECT
+SQLITE_THREADSAFE
+BUILD_CC
+VERSION_NUMBER
+RELEASE
+VERSION
+program_prefix
+TCLLIBDIR
+TCLSH_CMD
+AWK
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+CPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+lt_ECHO
+RANLIB
+STRIP
+AR
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+LIBTOOL
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
@@ -995,8 +952,9 @@ do
fi
case $ac_option in
- *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
- *) ac_optarg=yes ;;
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
esac
# Accept the important Cygnus configure options, so we can diagnose typos.
@@ -1041,8 +999,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1068,8 +1025,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1273,8 +1229,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1290,8 +1245,7 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
@@ -1321,17 +1275,17 @@ do
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
- -*) { $as_echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; }
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
;;
*=*)
ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
# Reject names that are not valid shell variable names.
- expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
- { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2
- { (exit 1); exit 1; }; }
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
@@ -1348,16 +1302,14 @@ done
if test -n "$ac_prev"; then
ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- { $as_echo "$as_me: error: missing argument to $ac_option" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "missing argument to $ac_option"
fi
if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
- fatal) { $as_echo "$as_me: error: Unrecognized options: $ac_unrecognized_opts" >&2
- { (exit 1); exit 1; }; } ;;
- *) $as_echo "$as_me: WARNING: Unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1379,8 +1331,7 @@ do
[\\/$]* | ?:[\\/]* ) continue;;
NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
esac
- { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done
# There might be people who depend on the old broken behavior: `$host'
@@ -1394,8 +1345,8 @@ target=$target_alias
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
- $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used." >&2
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
@@ -1410,11 +1361,9 @@ test "$silent" = yes && exec 6>/dev/null
ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
- { $as_echo "$as_me: error: Working directory cannot be determined" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
- { $as_echo "$as_me: error: pwd does not report name of working directory" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "pwd does not report name of working directory"
# Find the source files, if location was not specified.
@@ -1453,13 +1402,11 @@ else
fi
if test ! -r "$srcdir/$ac_unique_file"; then
test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
- { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
- { (exit 1); exit 1; }; }
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
- cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2
- { (exit 1); exit 1; }; }
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
@@ -1485,7 +1432,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sqlite 3.7.7.1 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.7.9 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1499,7 +1446,7 @@ Configuration:
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking...' messages
+ -q, --quiet, --silent do not print \`checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for \`--cache-file=config.cache'
-n, --no-create do not create output files
@@ -1550,7 +1497,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.7.7.1:";;
+ short | recursive ) echo "Configuration of sqlite 3.7.9:";;
esac
cat <<\_ACEOF
@@ -1596,7 +1543,7 @@ Some influential environment variables:
LDFLAGS linker flags, e.g. -L if you have libraries in a
nonstandard directory
LIBS libraries to pass to the linker, e.g. -l
- CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if
you have headers in a nonstandard directory
CPP C preprocessor
TCLLIBDIR Where to install tcl plugin
@@ -1604,6 +1551,7 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
+Report bugs to the package provider.
_ACEOF
ac_status=$?
fi
@@ -1666,22 +1614,427 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.7.7.1
-generated by GNU Autoconf 2.62
+sqlite configure 3.7.9
+generated by GNU Autoconf 2.67
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
exit
fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case declares $2.
+ For example, HP-UX 11i declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer to if __STDC__ is defined, since
+ exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include
+#else
+# include
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval "test \"\${$3+set}\"" = set; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sqlite $as_me 3.7.7.1, which was
-generated by GNU Autoconf 2.62. Invocation command line was
+It was created by sqlite $as_me 3.7.9, which was
+generated by GNU Autoconf 2.67. Invocation command line was
$ $0 $@
@@ -1717,8 +2070,8 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
-done
+ $as_echo "PATH: $as_dir"
+ done
IFS=$as_save_IFS
} >&5
@@ -1755,9 +2108,9 @@ do
ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
- 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
2)
- ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ as_fn_append ac_configure_args1 " '$ac_arg'"
if test $ac_must_keep_next = true; then
ac_must_keep_next=false # Got value, back to normal.
else
@@ -1773,13 +2126,13 @@ do
-* ) ac_must_keep_next=true ;;
esac
fi
- ac_configure_args="$ac_configure_args '$ac_arg'"
+ as_fn_append ac_configure_args " '$ac_arg'"
;;
esac
done
done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
# When interrupted or exit'd, cleanup temporary files, and complete
# config.log. We remove comments because anyway the quotes in there
@@ -1791,11 +2144,9 @@ trap 'exit_status=$?
{
echo
- cat <<\_ASBOX
-## ---------------- ##
+ $as_echo "## ---------------- ##
## Cache variables. ##
-## ---------------- ##
-_ASBOX
+## ---------------- ##"
echo
# The following way of writing the cache mishandles newlines in values,
(
@@ -1804,13 +2155,13 @@ _ASBOX
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-$as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
- *) $as_unset $ac_var ;;
+ *) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
@@ -1829,11 +2180,9 @@ $as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
)
echo
- cat <<\_ASBOX
-## ----------------- ##
+ $as_echo "## ----------------- ##
## Output variables. ##
-## ----------------- ##
-_ASBOX
+## ----------------- ##"
echo
for ac_var in $ac_subst_vars
do
@@ -1846,11 +2195,9 @@ _ASBOX
echo
if test -n "$ac_subst_files"; then
- cat <<\_ASBOX
-## ------------------- ##
+ $as_echo "## ------------------- ##
## File substitutions. ##
-## ------------------- ##
-_ASBOX
+## ------------------- ##"
echo
for ac_var in $ac_subst_files
do
@@ -1864,11 +2211,9 @@ _ASBOX
fi
if test -s confdefs.h; then
- cat <<\_ASBOX
-## ----------- ##
+ $as_echo "## ----------- ##
## confdefs.h. ##
-## ----------- ##
-_ASBOX
+## ----------- ##"
echo
cat confdefs.h
echo
@@ -1882,46 +2227,53 @@ _ASBOX
exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
- trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
+$as_echo "/* confdefs.h */" > confdefs.h
+
# Predefined preprocessor variables.
cat >>confdefs.h <<_ACEOF
#define PACKAGE_NAME "$PACKAGE_NAME"
_ACEOF
-
cat >>confdefs.h <<_ACEOF
#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
_ACEOF
-
cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION "$PACKAGE_VERSION"
_ACEOF
-
cat >>confdefs.h <<_ACEOF
#define PACKAGE_STRING "$PACKAGE_STRING"
_ACEOF
-
cat >>confdefs.h <<_ACEOF
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
_ACEOF
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
ac_site_file1=NONE
ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- ac_site_file1=$CONFIG_SITE
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
elif test "x$prefix" != xNONE; then
ac_site_file1=$prefix/share/config.site
ac_site_file2=$prefix/etc/config.site
@@ -1932,19 +2284,23 @@ fi
for ac_site_file in "$ac_site_file1" "$ac_site_file2"
do
test "x$ac_site_file" = xNONE && continue
- if test -r "$ac_site_file"; then
- { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
- . "$ac_site_file"
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
done
if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special
- # files actually), so we avoid doing that.
- if test -f "$cache_file"; then
- { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
$as_echo "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
@@ -1952,7 +2308,7 @@ $as_echo "$as_me: loading cache $cache_file" >&6;}
esac
fi
else
- { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
$as_echo "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
@@ -1967,11 +2323,11 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
@@ -1981,17 +2337,17 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:$LINENO: former value: \`$ac_old_val'" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:$LINENO: current value: \`$ac_new_val'" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
@@ -2003,41 +2359,20 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
esac
case " $ac_configure_args " in
*" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
- *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
esac
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-$as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -2049,15 +2384,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
sqlite_version_sanity_check=`cat $srcdir/VERSION | tr -d '\n'`
if test "$PACKAGE_VERSION" != "$sqlite_version_sanity_check" ; then
-{ { $as_echo "$as_me:$LINENO: error: configure script is out of date:
+as_fn_error $? "configure script is out of date:
configure \$PACKAGE_VERSION = $PACKAGE_VERSION
top level VERSION file = $sqlite_version_sanity_check
-please regen with autoconf" >&5
-$as_echo "$as_me: error: configure script is out of date:
- configure \$PACKAGE_VERSION = $PACKAGE_VERSION
- top level VERSION file = $sqlite_version_sanity_check
-please regen with autoconf" >&2;}
- { (exit 1); exit 1; }; }
+please regen with autoconf" "$LINENO" 5
fi
# The following RCS revision string applies to configure.in
@@ -2068,7 +2398,7 @@ fi
#
case `pwd` in
*\ * | *\ *)
- { $as_echo "$as_me:$LINENO: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
esac
@@ -2108,9 +2438,7 @@ for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
fi
done
if test -z "$ac_aux_dir"; then
- { { $as_echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
-$as_echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
fi
# These three variables are undocumented and unsupported,
@@ -2124,35 +2452,27 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
# Make sure we can run config.sub.
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- { { $as_echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
-$as_echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:$LINENO: checking build system type" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
$as_echo_n "checking build system type... " >&6; }
-if test "${ac_cv_build+set}" = set; then
+if test "${ac_cv_build+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
test "x$ac_build_alias" = x &&
- { { $as_echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
-$as_echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
-$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
$as_echo "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
-*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
-$as_echo "$as_me: error: invalid value of canonical build" >&2;}
- { (exit 1); exit 1; }; };;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;;
esac
build=$ac_cv_build
ac_save_IFS=$IFS; IFS='-'
@@ -2168,28 +2488,24 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:$LINENO: checking host system type" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
$as_echo_n "checking host system type... " >&6; }
-if test "${ac_cv_host+set}" = set; then
+if test "${ac_cv_host+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
-$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
$as_echo "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
-*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
-$as_echo "$as_me: error: invalid value of canonical host" >&2;}
- { (exit 1); exit 1; }; };;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;;
esac
host=$ac_cv_host
ac_save_IFS=$IFS; IFS='-'
@@ -2213,9 +2529,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
+if test "${ac_cv_prog_CC+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
@@ -2226,24 +2542,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:$LINENO: result: $CC" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -2253,9 +2569,9 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CC"; then
@@ -2266,24 +2582,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -2292,12 +2608,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2310,9 +2622,9 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
+if test "${ac_cv_prog_CC+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
@@ -2323,24 +2635,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:$LINENO: result: $CC" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -2350,9 +2662,9 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
+if test "${ac_cv_prog_CC+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
@@ -2364,18 +2676,18 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
if test $ac_prog_rejected = yes; then
@@ -2394,10 +2706,10 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:$LINENO: result: $CC" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -2409,9 +2721,9 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
+if test "${ac_cv_prog_CC+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
@@ -2422,24 +2734,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:$LINENO: result: $CC" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -2453,9 +2765,9 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CC"; then
@@ -2466,24 +2778,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -2496,12 +2808,8 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2511,55 +2819,37 @@ fi
fi
-test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5 ; }
# Provide some information about the compiler.
-$as_echo "$as_me:$LINENO: checking for C compiler version" >&5
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-{ (ac_try="$ac_compiler --version >&5"
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compiler --version >&5") 2>&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compiler -v >&5") 2>&5
- ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compiler -V >&5") 2>&5
- ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2575,8 +2865,8 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
@@ -2592,17 +2882,17 @@ do
done
rm -f $ac_rmfiles
-if { (ac_try="$ac_link_default"
+if { { ac_try="$ac_link_default"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -2619,7 +2909,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -2638,80 +2928,41 @@ test "$ac_cv_exeext" = no && ac_cv_exeext=
else
ac_file=''
fi
-
-{ $as_echo "$as_me:$LINENO: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
-if test -z "$ac_file"; then
- $as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
- if { ac_try='./$ac_file'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
- fi
- fi
-fi
-{ $as_echo "$as_me:$LINENO: result: yes" >&5
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5 ; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
-{ $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
-
-{ $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
$as_echo_n "checking for suffix of executables... " >&6; }
-if { (ac_try="$ac_link"
+if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -2726,30 +2977,83 @@ for ac_file in conftest.exe conftest conftest.*; do
esac
done
else
- { { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
-
-rm -f conftest$ac_cv_exeext
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
$as_echo "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
-{ $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5 ; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
-if test "${ac_cv_objext+set}" = set; then
+if test "${ac_cv_objext+set}" = set; then :
$as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2761,17 +3065,17 @@ main ()
}
_ACEOF
rm -f conftest.o conftest.obj
-if { (ac_try="$ac_compile"
+if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -2784,29 +3088,23 @@ else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
-
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
$as_echo "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
$as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2820,37 +3118,16 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_compiler_gnu=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_compiler_gnu=no
+ ac_compiler_gnu=no
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
$as_echo "$ac_cv_c_compiler_gnu" >&6; }
if test $ac_compiler_gnu = yes; then
GCC=yes
@@ -2859,20 +3136,16 @@ else
fi
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then
+if test "${ac_cv_prog_cc_g+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
CFLAGS="-g"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2883,35 +3156,11 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_g=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- CFLAGS=""
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2922,36 +3171,12 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_compile "$LINENO"; then :
- ac_c_werror_flag=$ac_save_c_werror_flag
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -2962,42 +3187,17 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_g=yes
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
$as_echo "$ac_cv_prog_cc_g" >&6; }
if test "$ac_test_CFLAGS" = set; then
CFLAGS=$ac_save_CFLAGS
@@ -3014,18 +3214,14 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_cv_prog_cc_c89=no
ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#include
@@ -3082,32 +3278,9 @@ for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+ if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_c89=$ac_arg
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
rm -f core conftest.err conftest.$ac_objext
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
@@ -3118,17 +3291,19 @@ fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in
x)
- { $as_echo "$as_me:$LINENO: result: none needed" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
xno)
- { $as_echo "$as_me:$LINENO: result: unsupported" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
*)
CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -3136,9 +3311,9 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
$as_echo_n "checking for a sed that does not truncate output... " >&6; }
-if test "${ac_cv_path_SED+set}" = set; then
+if test "${ac_cv_path_SED+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
@@ -3146,7 +3321,7 @@ else
ac_script="$ac_script$as_nl$ac_script"
done
echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
- $as_unset ac_script || ac_script=
+ { ac_script=; unset ac_script;}
if test -z "$SED"; then
ac_path_SED_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
@@ -3155,7 +3330,7 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_prog in sed gsed; do
+ for ac_prog in sed gsed; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
{ test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
@@ -3175,7 +3350,7 @@ case `"$ac_path_SED" --version 2>&1` in
$as_echo '' >> "conftest.nl"
"$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- ac_count=`expr $ac_count + 1`
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_SED_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_SED="$ac_path_SED"
@@ -3190,19 +3365,17 @@ esac
$ac_path_SED_found && break 3
done
done
-done
+ done
IFS=$as_save_IFS
if test -z "$ac_cv_path_SED"; then
- { { $as_echo "$as_me:$LINENO: error: no acceptable sed could be found in \$PATH" >&5
-$as_echo "$as_me: error: no acceptable sed could be found in \$PATH" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
fi
else
ac_cv_path_SED=$SED
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_SED" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
$as_echo "$ac_cv_path_SED" >&6; }
SED="$ac_cv_path_SED"
rm -f conftest.sed
@@ -3220,9 +3393,9 @@ Xsed="$SED -e 1s/^X//"
-{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then
+if test "${ac_cv_path_GREP+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -z "$GREP"; then
@@ -3233,7 +3406,7 @@ for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
+ for ac_prog in grep ggrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
{ test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
@@ -3253,7 +3426,7 @@ case `"$ac_path_GREP" --version 2>&1` in
$as_echo 'GREP' >> "conftest.nl"
"$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- ac_count=`expr $ac_count + 1`
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_GREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_GREP="$ac_path_GREP"
@@ -3268,26 +3441,24 @@ esac
$ac_path_GREP_found && break 3
done
done
-done
+ done
IFS=$as_save_IFS
if test -z "$ac_cv_path_GREP"; then
- { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_GREP=$GREP
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
$as_echo "$ac_cv_path_GREP" >&6; }
GREP="$ac_cv_path_GREP"
-{ $as_echo "$as_me:$LINENO: checking for egrep" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
$as_echo_n "checking for egrep... " >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then
+if test "${ac_cv_path_EGREP+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
@@ -3301,7 +3472,7 @@ for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
+ for ac_prog in egrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
{ test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
@@ -3321,7 +3492,7 @@ case `"$ac_path_EGREP" --version 2>&1` in
$as_echo 'EGREP' >> "conftest.nl"
"$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- ac_count=`expr $ac_count + 1`
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_EGREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_EGREP="$ac_path_EGREP"
@@ -3336,12 +3507,10 @@ esac
$ac_path_EGREP_found && break 3
done
done
-done
+ done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP"; then
- { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_EGREP=$EGREP
@@ -3349,14 +3518,14 @@ fi
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
$as_echo "$ac_cv_path_EGREP" >&6; }
EGREP="$ac_cv_path_EGREP"
-{ $as_echo "$as_me:$LINENO: checking for fgrep" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
$as_echo_n "checking for fgrep... " >&6; }
-if test "${ac_cv_path_FGREP+set}" = set; then
+if test "${ac_cv_path_FGREP+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
@@ -3370,7 +3539,7 @@ for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_prog in fgrep; do
+ for ac_prog in fgrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
{ test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
@@ -3390,7 +3559,7 @@ case `"$ac_path_FGREP" --version 2>&1` in
$as_echo 'FGREP' >> "conftest.nl"
"$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- ac_count=`expr $ac_count + 1`
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_FGREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_FGREP="$ac_path_FGREP"
@@ -3405,12 +3574,10 @@ esac
$ac_path_FGREP_found && break 3
done
done
-done
+ done
IFS=$as_save_IFS
if test -z "$ac_cv_path_FGREP"; then
- { { $as_echo "$as_me:$LINENO: error: no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-$as_echo "$as_me: error: no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_FGREP=$FGREP
@@ -3418,7 +3585,7 @@ fi
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_FGREP" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
$as_echo "$ac_cv_path_FGREP" >&6; }
FGREP="$ac_cv_path_FGREP"
@@ -3444,7 +3611,7 @@ test -z "$GREP" && GREP=grep
# Check whether --with-gnu-ld was given.
-if test "${with_gnu_ld+set}" = set; then
+if test "${with_gnu_ld+set}" = set; then :
withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
else
with_gnu_ld=no
@@ -3453,7 +3620,7 @@ fi
ac_prog=ld
if test "$GCC" = yes; then
# Check if gcc -print-prog-name=ld gives a path.
- { $as_echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
$as_echo_n "checking for ld used by $CC... " >&6; }
case $host in
*-*-mingw*)
@@ -3483,13 +3650,13 @@ $as_echo_n "checking for ld used by $CC... " >&6; }
;;
esac
elif test "$with_gnu_ld" = yes; then
- { $as_echo "$as_me:$LINENO: checking for GNU ld" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
$as_echo_n "checking for GNU ld... " >&6; }
else
- { $as_echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
$as_echo_n "checking for non-GNU ld... " >&6; }
fi
-if test "${lt_cv_path_LD+set}" = set; then
+if test "${lt_cv_path_LD+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -z "$LD"; then
@@ -3520,18 +3687,16 @@ fi
LD="$lt_cv_path_LD"
if test -n "$LD"; then
- { $as_echo "$as_me:$LINENO: result: $LD" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
$as_echo "$LD" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
-test -z "$LD" && { { $as_echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
-$as_echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
- { (exit 1); exit 1; }; }
-{ $as_echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
-if test "${lt_cv_prog_gnu_ld+set}" = set; then
+if test "${lt_cv_prog_gnu_ld+set}" = set; then :
$as_echo_n "(cached) " >&6
else
# I'd rather use --version here, but apparently some GNU lds only accept -v.
@@ -3544,7 +3709,7 @@ case `$LD -v 2>&1 &5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
$as_echo "$lt_cv_prog_gnu_ld" >&6; }
with_gnu_ld=$lt_cv_prog_gnu_ld
@@ -3556,9 +3721,9 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
-{ $as_echo "$as_me:$LINENO: checking for BSD- or MS-compatible name lister (nm)" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
-if test "${lt_cv_path_NM+set}" = set; then
+if test "${lt_cv_path_NM+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$NM"; then
@@ -3605,7 +3770,7 @@ else
: ${lt_cv_path_NM=no}
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
$as_echo "$lt_cv_path_NM" >&6; }
if test "$lt_cv_path_NM" != "no"; then
NM="$lt_cv_path_NM"
@@ -3616,9 +3781,9 @@ else
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_DUMPBIN+set}" = set; then
+if test "${ac_cv_prog_DUMPBIN+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$DUMPBIN"; then
@@ -3629,24 +3794,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
DUMPBIN=$ac_cv_prog_DUMPBIN
if test -n "$DUMPBIN"; then
- { $as_echo "$as_me:$LINENO: result: $DUMPBIN" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
$as_echo "$DUMPBIN" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -3660,9 +3825,9 @@ if test -z "$DUMPBIN"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then
+if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_DUMPBIN"; then
@@ -3673,24 +3838,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
if test -n "$ac_ct_DUMPBIN"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_DUMPBIN" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
$as_echo "$ac_ct_DUMPBIN" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -3703,12 +3868,8 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DUMPBIN=$ac_ct_DUMPBIN
@@ -3727,44 +3888,44 @@ test -z "$NM" && NM=nm
-{ $as_echo "$as_me:$LINENO: checking the name lister ($NM) interface" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
$as_echo_n "checking the name lister ($NM) interface... " >&6; }
-if test "${lt_cv_nm_interface+set}" = set; then
+if test "${lt_cv_nm_interface+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:3737: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:3898: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:3740: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:3901: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:3743: output\"" >&5)
+ (eval echo "\"\$as_me:3904: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
fi
rm -f conftest*
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_nm_interface" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
$as_echo "$lt_cv_nm_interface" >&6; }
-{ $as_echo "$as_me:$LINENO: checking whether ln -s works" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
$as_echo_n "checking whether ln -s works... " >&6; }
LN_S=$as_ln_s
if test "$LN_S" = "ln -s"; then
- { $as_echo "$as_me:$LINENO: result: yes" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
$as_echo "no, using $LN_S" >&6; }
fi
# find the maximum length of command line arguments
-{ $as_echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
$as_echo_n "checking the maximum length of command line arguments... " >&6; }
-if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then :
$as_echo_n "(cached) " >&6
else
i=0
@@ -3882,10 +4043,10 @@ else
fi
if test -n $lt_cv_sys_max_cmd_len ; then
- { $as_echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: none" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
$as_echo "none" >&6; }
fi
max_cmd_len=$lt_cv_sys_max_cmd_len
@@ -3899,7 +4060,7 @@ max_cmd_len=$lt_cv_sys_max_cmd_len
: ${MV="mv -f"}
: ${RM="rm -f"}
-{ $as_echo "$as_me:$LINENO: checking whether the shell understands some XSI constructs" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
# Try some XSI features
xsi_shell=no
@@ -3909,17 +4070,17 @@ xsi_shell=no
&& eval 'test $(( 1 + 1 )) -eq 2 \
&& test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
&& xsi_shell=yes
-{ $as_echo "$as_me:$LINENO: result: $xsi_shell" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
$as_echo "$xsi_shell" >&6; }
-{ $as_echo "$as_me:$LINENO: checking whether the shell understands \"+=\"" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
lt_shell_append=no
( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
>/dev/null 2>&1 \
&& lt_shell_append=yes
-{ $as_echo "$as_me:$LINENO: result: $lt_shell_append" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
$as_echo "$lt_shell_append" >&6; }
@@ -3954,14 +4115,14 @@ esac
-{ $as_echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
$as_echo_n "checking for $LD option to reload object files... " >&6; }
-if test "${lt_cv_ld_reload_flag+set}" = set; then
+if test "${lt_cv_ld_reload_flag+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_ld_reload_flag='-r'
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
$as_echo "$lt_cv_ld_reload_flag" >&6; }
reload_flag=$lt_cv_ld_reload_flag
case $reload_flag in
@@ -3990,9 +4151,9 @@ esac
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
set dummy ${ac_tool_prefix}objdump; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OBJDUMP+set}" = set; then
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$OBJDUMP"; then
@@ -4003,24 +4164,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
OBJDUMP=$ac_cv_prog_OBJDUMP
if test -n "$OBJDUMP"; then
- { $as_echo "$as_me:$LINENO: result: $OBJDUMP" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
$as_echo "$OBJDUMP" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -4030,9 +4191,9 @@ if test -z "$ac_cv_prog_OBJDUMP"; then
ac_ct_OBJDUMP=$OBJDUMP
# Extract the first word of "objdump", so it can be a program name with args.
set dummy objdump; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_OBJDUMP"; then
@@ -4043,24 +4204,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_OBJDUMP="objdump"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
if test -n "$ac_ct_OBJDUMP"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
$as_echo "$ac_ct_OBJDUMP" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -4069,12 +4230,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
OBJDUMP=$ac_ct_OBJDUMP
@@ -4093,9 +4250,9 @@ test -z "$OBJDUMP" && OBJDUMP=objdump
-{ $as_echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
$as_echo_n "checking how to recognize dependent libraries... " >&6; }
-if test "${lt_cv_deplibs_check_method+set}" = set; then
+if test "${lt_cv_deplibs_check_method+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_file_magic_cmd='$MAGIC_CMD'
@@ -4289,7 +4446,7 @@ tpf*)
esac
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
$as_echo "$lt_cv_deplibs_check_method" >&6; }
file_magic_cmd=$lt_cv_file_magic_cmd
deplibs_check_method=$lt_cv_deplibs_check_method
@@ -4309,9 +4466,9 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_AR+set}" = set; then
+if test "${ac_cv_prog_AR+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$AR"; then
@@ -4322,24 +4479,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_AR="${ac_tool_prefix}ar"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
- { $as_echo "$as_me:$LINENO: result: $AR" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
$as_echo "$AR" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -4349,9 +4506,9 @@ if test -z "$ac_cv_prog_AR"; then
ac_ct_AR=$AR
# Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_AR"; then
@@ -4362,24 +4519,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_AR="ar"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
$as_echo "$ac_ct_AR" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -4388,12 +4545,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
AR=$ac_ct_AR
@@ -4418,9 +4571,9 @@ test -z "$AR_FLAGS" && AR_FLAGS=cru
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
set dummy ${ac_tool_prefix}strip; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_STRIP+set}" = set; then
+if test "${ac_cv_prog_STRIP+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$STRIP"; then
@@ -4431,24 +4584,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_STRIP="${ac_tool_prefix}strip"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
STRIP=$ac_cv_prog_STRIP
if test -n "$STRIP"; then
- { $as_echo "$as_me:$LINENO: result: $STRIP" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
$as_echo "$STRIP" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -4458,9 +4611,9 @@ if test -z "$ac_cv_prog_STRIP"; then
ac_ct_STRIP=$STRIP
# Extract the first word of "strip", so it can be a program name with args.
set dummy strip; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_STRIP"; then
@@ -4471,24 +4624,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_STRIP="strip"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
if test -n "$ac_ct_STRIP"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
$as_echo "$ac_ct_STRIP" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -4497,12 +4650,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
STRIP=$ac_ct_STRIP
@@ -4521,9 +4670,9 @@ test -z "$STRIP" && STRIP=:
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_RANLIB+set}" = set; then
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$RANLIB"; then
@@ -4534,24 +4683,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- { $as_echo "$as_me:$LINENO: result: $RANLIB" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
$as_echo "$RANLIB" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -4561,9 +4710,9 @@ if test -z "$ac_cv_prog_RANLIB"; then
ac_ct_RANLIB=$RANLIB
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_RANLIB"; then
@@ -4574,24 +4723,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
$as_echo "$ac_ct_RANLIB" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -4600,12 +4749,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
RANLIB=$ac_ct_RANLIB
@@ -4682,9 +4827,9 @@ compiler=$CC
# Check for command to grab the raw symbol name followed by C symbol from nm.
-{ $as_echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
-if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then :
$as_echo_n "(cached) " >&6
else
@@ -4800,18 +4945,18 @@ void nm_test_func(void){}
int main(){nm_test_var='a';nm_test_func();return(0);}
_LT_EOF
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
# Now try to grab the symbols.
nlist=conftest.nm
- if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5
(eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && test -s "$nlist"; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "$nlist"; then
# Try sorting and uniquifying the output.
if sort "$nlist" | uniq > "$nlist"T; then
mv -f "$nlist"T "$nlist"
@@ -4864,11 +5009,11 @@ _LT_EOF
lt_save_CFLAGS="$CFLAGS"
LIBS="conftstm.$ac_objext"
CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
- if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
(eval $ac_link) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && test -s conftest${ac_exeext}; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext}; then
pipe_works=yes
fi
LIBS="$lt_save_LIBS"
@@ -4902,10 +5047,10 @@ if test -z "$lt_cv_sys_global_symbol_pipe"; then
lt_cv_sys_global_symbol_to_cdecl=
fi
if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
- { $as_echo "$as_me:$LINENO: result: failed" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
$as_echo "failed" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: ok" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
$as_echo "ok" >&6; }
fi
@@ -4932,7 +5077,7 @@ fi
# Check whether --enable-libtool-lock was given.
-if test "${enable_libtool_lock+set}" = set; then
+if test "${enable_libtool_lock+set}" = set; then :
enableval=$enable_libtool_lock;
fi
@@ -4944,11 +5089,11 @@ case $host in
ia64-*-hpux*)
# Find out which ABI we are using.
echo 'int i;' > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
case `/usr/bin/file conftest.$ac_objext` in
*ELF-32*)
HPUX_IA64_MODE="32"
@@ -4962,12 +5107,12 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 4965 "configure"' > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ echo '#line 5110 "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
if test "$lt_cv_prog_gnu_ld" = yes; then
case `/usr/bin/file conftest.$ac_objext` in
*32-bit*)
@@ -5001,11 +5146,11 @@ x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# Find out which ABI we are using.
echo 'int i;' > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
case `/usr/bin/file conftest.o` in
*32-bit*)
case $host in
@@ -5054,9 +5199,9 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# On SCO OpenServer 5, we need -belf to get full-featured binaries.
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -belf"
- { $as_echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
-if test "${lt_cv_cc_needs_belf+set}" = set; then
+if test "${lt_cv_cc_needs_belf+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_ext=c
@@ -5065,11 +5210,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -5080,38 +5221,13 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
lt_cv_cc_needs_belf=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- lt_cv_cc_needs_belf=no
+ lt_cv_cc_needs_belf=no
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -5119,7 +5235,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
$as_echo "$lt_cv_cc_needs_belf" >&6; }
if test x"$lt_cv_cc_needs_belf" != x"yes"; then
# this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
@@ -5129,11 +5245,11 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; }
sparc*-*solaris*)
# Find out which ABI we are using.
echo 'int i;' > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
case `/usr/bin/file conftest.o` in
*64-bit*)
case $lt_cv_prog_gnu_ld in
@@ -5159,9 +5275,9 @@ need_locks="$enable_libtool_lock"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_DSYMUTIL+set}" = set; then
+if test "${ac_cv_prog_DSYMUTIL+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$DSYMUTIL"; then
@@ -5172,24 +5288,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
DSYMUTIL=$ac_cv_prog_DSYMUTIL
if test -n "$DSYMUTIL"; then
- { $as_echo "$as_me:$LINENO: result: $DSYMUTIL" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
$as_echo "$DSYMUTIL" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5199,9 +5315,9 @@ if test -z "$ac_cv_prog_DSYMUTIL"; then
ac_ct_DSYMUTIL=$DSYMUTIL
# Extract the first word of "dsymutil", so it can be a program name with args.
set dummy dsymutil; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then
+if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_DSYMUTIL"; then
@@ -5212,24 +5328,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
if test -n "$ac_ct_DSYMUTIL"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_DSYMUTIL" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
$as_echo "$ac_ct_DSYMUTIL" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5238,12 +5354,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DSYMUTIL=$ac_ct_DSYMUTIL
@@ -5255,9 +5367,9 @@ fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
set dummy ${ac_tool_prefix}nmedit; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_NMEDIT+set}" = set; then
+if test "${ac_cv_prog_NMEDIT+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$NMEDIT"; then
@@ -5268,24 +5380,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
NMEDIT=$ac_cv_prog_NMEDIT
if test -n "$NMEDIT"; then
- { $as_echo "$as_me:$LINENO: result: $NMEDIT" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
$as_echo "$NMEDIT" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5295,9 +5407,9 @@ if test -z "$ac_cv_prog_NMEDIT"; then
ac_ct_NMEDIT=$NMEDIT
# Extract the first word of "nmedit", so it can be a program name with args.
set dummy nmedit; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then
+if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_NMEDIT"; then
@@ -5308,24 +5420,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_NMEDIT="nmedit"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
if test -n "$ac_ct_NMEDIT"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_NMEDIT" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
$as_echo "$ac_ct_NMEDIT" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5334,12 +5446,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
NMEDIT=$ac_ct_NMEDIT
@@ -5351,9 +5459,9 @@ fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
set dummy ${ac_tool_prefix}lipo; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_LIPO+set}" = set; then
+if test "${ac_cv_prog_LIPO+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$LIPO"; then
@@ -5364,24 +5472,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
LIPO=$ac_cv_prog_LIPO
if test -n "$LIPO"; then
- { $as_echo "$as_me:$LINENO: result: $LIPO" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
$as_echo "$LIPO" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5391,9 +5499,9 @@ if test -z "$ac_cv_prog_LIPO"; then
ac_ct_LIPO=$LIPO
# Extract the first word of "lipo", so it can be a program name with args.
set dummy lipo; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then
+if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_LIPO"; then
@@ -5404,24 +5512,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_LIPO="lipo"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
if test -n "$ac_ct_LIPO"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_LIPO" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
$as_echo "$ac_ct_LIPO" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5430,12 +5538,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
LIPO=$ac_ct_LIPO
@@ -5447,9 +5551,9 @@ fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
set dummy ${ac_tool_prefix}otool; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OTOOL+set}" = set; then
+if test "${ac_cv_prog_OTOOL+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$OTOOL"; then
@@ -5460,24 +5564,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
OTOOL=$ac_cv_prog_OTOOL
if test -n "$OTOOL"; then
- { $as_echo "$as_me:$LINENO: result: $OTOOL" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
$as_echo "$OTOOL" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5487,9 +5591,9 @@ if test -z "$ac_cv_prog_OTOOL"; then
ac_ct_OTOOL=$OTOOL
# Extract the first word of "otool", so it can be a program name with args.
set dummy otool; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then
+if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_OTOOL"; then
@@ -5500,24 +5604,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_OTOOL="otool"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
if test -n "$ac_ct_OTOOL"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_OTOOL" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
$as_echo "$ac_ct_OTOOL" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5526,12 +5630,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
OTOOL=$ac_ct_OTOOL
@@ -5543,9 +5643,9 @@ fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
set dummy ${ac_tool_prefix}otool64; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OTOOL64+set}" = set; then
+if test "${ac_cv_prog_OTOOL64+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$OTOOL64"; then
@@ -5556,24 +5656,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
OTOOL64=$ac_cv_prog_OTOOL64
if test -n "$OTOOL64"; then
- { $as_echo "$as_me:$LINENO: result: $OTOOL64" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
$as_echo "$OTOOL64" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5583,9 +5683,9 @@ if test -z "$ac_cv_prog_OTOOL64"; then
ac_ct_OTOOL64=$OTOOL64
# Extract the first word of "otool64", so it can be a program name with args.
set dummy otool64; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then
+if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_OTOOL64"; then
@@ -5596,24 +5696,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_OTOOL64="otool64"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
if test -n "$ac_ct_OTOOL64"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_OTOOL64" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
$as_echo "$ac_ct_OTOOL64" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -5622,12 +5722,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
OTOOL64=$ac_ct_OTOOL64
@@ -5662,9 +5758,9 @@ fi
- { $as_echo "$as_me:$LINENO: checking for -single_module linker flag" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
$as_echo_n "checking for -single_module linker flag... " >&6; }
-if test "${lt_cv_apple_cc_single_mod+set}" = set; then
+if test "${lt_cv_apple_cc_single_mod+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_apple_cc_single_mod=no
@@ -5689,22 +5785,18 @@ else
rm -f conftest.*
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_apple_cc_single_mod" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
- { $as_echo "$as_me:$LINENO: checking for -exported_symbols_list linker flag" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
-if test "${lt_cv_ld_exported_symbols_list+set}" = set; then
+if test "${lt_cv_ld_exported_symbols_list+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_ld_exported_symbols_list=no
save_LDFLAGS=$LDFLAGS
echo "_main" > conftest.sym
LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -5715,42 +5807,17 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
lt_cv_ld_exported_symbols_list=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- lt_cv_ld_exported_symbols_list=no
+ lt_cv_ld_exported_symbols_list=no
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LDFLAGS="$save_LDFLAGS"
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_ld_exported_symbols_list" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
case $host_os in
rhapsody* | darwin1.[012])
@@ -5792,14 +5859,14 @@ ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
$as_echo_n "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
- if test "${ac_cv_prog_CPP+set}" = set; then
+ if test "${ac_cv_prog_CPP+set}" = set; then :
$as_echo_n "(cached) " >&6
else
# Double quotes because CPP needs to be expanded
@@ -5814,11 +5881,7 @@ do
# exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include
@@ -5827,78 +5890,34 @@ cat >>conftest.$ac_ext <<_ACEOF
#endif
Syntax error
_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_cpp "$LINENO"; then :
+else
# Broken: fails on valid input.
continue
fi
-
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
+if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
# Passes both tests.
ac_preproc_ok=:
break
fi
-
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
break
fi
@@ -5910,7 +5929,7 @@ fi
else
ac_cv_prog_CPP=$CPP
fi
-{ $as_echo "$as_me:$LINENO: result: $CPP" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
$as_echo "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
@@ -5921,11 +5940,7 @@ do
# exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include
@@ -5934,85 +5949,40 @@ cat >>conftest.$ac_ext <<_ACEOF
#endif
Syntax error
_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_cpp "$LINENO"; then :
+else
# Broken: fails on valid input.
continue
fi
-
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
+if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
# Passes both tests.
ac_preproc_ok=:
break
fi
-
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- :
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
else
- { { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
ac_ext=c
@@ -6022,16 +5992,12 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
$as_echo_n "checking for ANSI C header files... " >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
+if test "${ac_cv_header_stdc+set}" = set; then :
$as_echo_n "(cached) " >&6
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#include
@@ -6046,48 +6012,23 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_header_stdc=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_header_stdc=no
+ ac_cv_header_stdc=no
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then
- :
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
else
ac_cv_header_stdc=no
fi
@@ -6097,18 +6038,14 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then
- :
+ $EGREP "free" >/dev/null 2>&1; then :
+
else
ac_cv_header_stdc=no
fi
@@ -6118,14 +6055,10 @@ fi
if test $ac_cv_header_stdc = yes; then
# /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then
+ if test "$cross_compiling" = yes; then :
:
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#include
@@ -6152,117 +6085,33 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
+if ac_fn_c_try_run "$LINENO"; then :
+
else
- $as_echo "$as_me: program exited with status $ac_status" >&5
-$as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_header_stdc=no
+ ac_cv_header_stdc=no
fi
-rm -rf conftest.dSYM
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
$as_echo "$ac_cv_header_stdc" >&6; }
if test $ac_cv_header_stdc = yes; then
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
fi
# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-
-
-
-
-
-
-
-
-
for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
inttypes.h stdint.h unistd.h
-do
-as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
-$as_echo_n "checking for $ac_header... " >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- $as_echo_n "(cached) " >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval 'as_val=${'$as_ac_Header'}
- $as_echo "$as_val"'`
- { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-if test `eval 'as_val=${'$as_ac_Header'}
- $as_echo "$as_val"'` = yes; then
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
@@ -6272,61 +6121,13 @@ fi
done
-
for ac_header in dlfcn.h
-do
-as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
-$as_echo_n "checking for $ac_header... " >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- $as_echo_n "(cached) " >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- eval "$as_ac_Header=yes"
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval 'as_val=${'$as_ac_Header'}
- $as_echo "$as_val"'`
- { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-if test `eval 'as_val=${'$as_ac_Header'}
- $as_echo "$as_val"'` = yes; then
+do :
+ ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_DLFCN_H 1
_ACEOF
fi
@@ -6346,7 +6147,7 @@ done
# Check whether --enable-shared was given.
-if test "${enable_shared+set}" = set; then
+if test "${enable_shared+set}" = set; then :
enableval=$enable_shared; p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
@@ -6377,7 +6178,7 @@ fi
# Check whether --enable-static was given.
-if test "${enable_static+set}" = set; then
+if test "${enable_static+set}" = set; then :
enableval=$enable_static; p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
@@ -6409,7 +6210,7 @@ fi
# Check whether --with-pic was given.
-if test "${with_pic+set}" = set; then
+if test "${with_pic+set}" = set; then :
withval=$with_pic; pic_mode="$withval"
else
pic_mode=default
@@ -6425,7 +6226,7 @@ test -z "$pic_mode" && pic_mode=default
# Check whether --enable-fast-install was given.
-if test "${enable_fast_install+set}" = set; then
+if test "${enable_fast_install+set}" = set; then :
enableval=$enable_fast_install; p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
@@ -6506,9 +6307,9 @@ if test -n "${ZSH_VERSION+set}" ; then
setopt NO_GLOB_SUBST
fi
-{ $as_echo "$as_me:$LINENO: checking for objdir" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
$as_echo_n "checking for objdir... " >&6; }
-if test "${lt_cv_objdir+set}" = set; then
+if test "${lt_cv_objdir+set}" = set; then :
$as_echo_n "(cached) " >&6
else
rm -f .libs 2>/dev/null
@@ -6521,7 +6322,7 @@ else
fi
rmdir .libs 2>/dev/null
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
$as_echo "$lt_cv_objdir" >&6; }
objdir=$lt_cv_objdir
@@ -6614,9 +6415,9 @@ test -z "$MAGIC_CMD" && MAGIC_CMD=file
case $deplibs_check_method in
file_magic*)
if test "$file_magic_cmd" = '$MAGIC_CMD'; then
- { $as_echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
-if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
$as_echo_n "(cached) " >&6
else
case $MAGIC_CMD in
@@ -6667,10 +6468,10 @@ fi
MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
if test -n "$MAGIC_CMD"; then
- { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
$as_echo "$MAGIC_CMD" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -6680,9 +6481,9 @@ fi
if test -z "$lt_cv_path_MAGIC_CMD"; then
if test -n "$ac_tool_prefix"; then
- { $as_echo "$as_me:$LINENO: checking for file" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
$as_echo_n "checking for file... " >&6; }
-if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
$as_echo_n "(cached) " >&6
else
case $MAGIC_CMD in
@@ -6733,10 +6534,10 @@ fi
MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
if test -n "$MAGIC_CMD"; then
- { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
$as_echo "$MAGIC_CMD" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -6813,9 +6614,9 @@ lt_prog_compiler_no_builtin_flag=
if test "$GCC" = yes; then
lt_prog_compiler_no_builtin_flag=' -fno-builtin'
- { $as_echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
-if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_prog_compiler_rtti_exceptions=no
@@ -6831,11 +6632,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:6834: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6635: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6838: \$? = $ac_status" >&5
+ echo "$as_me:6639: \$? = $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.
@@ -6848,7 +6649,7 @@ else
$RM conftest*
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
@@ -6868,7 +6669,7 @@ fi
lt_prog_compiler_pic=
lt_prog_compiler_static=
-{ $as_echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
if test "$GCC" = yes; then
@@ -7140,7 +6941,7 @@ case $host_os in
lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
;;
esac
-{ $as_echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
$as_echo "$lt_prog_compiler_pic" >&6; }
@@ -7152,9 +6953,9 @@ $as_echo "$lt_prog_compiler_pic" >&6; }
# Check to make sure the PIC flag actually works.
#
if test -n "$lt_prog_compiler_pic"; then
- { $as_echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
-if test "${lt_cv_prog_compiler_pic_works+set}" = set; then
+if test "${lt_cv_prog_compiler_pic_works+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_prog_compiler_pic_works=no
@@ -7170,11 +6971,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:7173: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6974: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7177: \$? = $ac_status" >&5
+ echo "$as_me:6978: \$? = $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.
@@ -7187,7 +6988,7 @@ else
$RM conftest*
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
@@ -7211,9 +7012,9 @@ fi
# Check to make sure the static flag actually works.
#
wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
-{ $as_echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
-if test "${lt_cv_prog_compiler_static_works+set}" = set; then
+if test "${lt_cv_prog_compiler_static_works+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_prog_compiler_static_works=no
@@ -7239,7 +7040,7 @@ else
LDFLAGS="$save_LDFLAGS"
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
if test x"$lt_cv_prog_compiler_static_works" = xyes; then
@@ -7254,9 +7055,9 @@ fi
- { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_prog_compiler_c_o=no
@@ -7275,11 +7076,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:7278: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7079: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7282: \$? = $ac_status" >&5
+ echo "$as_me:7083: \$? = $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
@@ -7301,7 +7102,7 @@ else
$RM conftest*
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
@@ -7309,9 +7110,9 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; }
- { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
$as_echo_n "(cached) " >&6
else
lt_cv_prog_compiler_c_o=no
@@ -7330,11 +7131,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:7333: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7134: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7337: \$? = $ac_status" >&5
+ echo "$as_me:7138: \$? = $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
@@ -7356,7 +7157,7 @@ else
$RM conftest*
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
@@ -7365,7 +7166,7 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; }
hard_links="nottested"
if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
# do not overwrite the value of need_locks provided by the user
- { $as_echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
$as_echo_n "checking if we can lock with hard links... " >&6; }
hard_links=yes
$RM conftest*
@@ -7373,10 +7174,10 @@ $as_echo_n "checking if we can lock with hard links... " >&6; }
touch conftest.a
ln conftest.a conftest.b 2>&5 || hard_links=no
ln conftest.a conftest.b 2>/dev/null && hard_links=no
- { $as_echo "$as_me:$LINENO: result: $hard_links" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
$as_echo "$hard_links" >&6; }
if test "$hard_links" = no; then
- { $as_echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
need_locks=warn
fi
@@ -7389,7 +7190,7 @@ fi
- { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
runpath_var=
@@ -7831,11 +7632,7 @@ _LT_EOF
allow_undefined_flag='-berok'
# Determine the default libpath from the value encoded in an
# empty executable.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -7846,27 +7643,7 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
lt_aix_libpath_sed='
/Import File Strings/,/^$/ {
@@ -7880,16 +7657,9 @@ aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpat
if test -z "$aix_libpath"; then
aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
fi
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
@@ -7902,11 +7672,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
else
# Determine the default libpath from the value encoded in an
# empty executable.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -7917,27 +7683,7 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
lt_aix_libpath_sed='
/Import File Strings/,/^$/ {
@@ -7951,16 +7697,9 @@ aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpat
if test -z "$aix_libpath"; then
aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
fi
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
@@ -8172,42 +7911,16 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
# implicitly export all symbols.
save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
- cat >conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
int foo(void) {}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LDFLAGS="$save_LDFLAGS"
else
archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
@@ -8463,7 +8176,7 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
$as_echo "$ld_shlibs" >&6; }
test "$ld_shlibs" = no && can_build_shared=no
@@ -8500,16 +8213,16 @@ x|xyes)
# Test whether the compiler implicitly links with -lc since on some
# systems, -lgcc has to come before -lc. If gcc already passes -lc
# to ld, don't add -lc before -lgcc.
- { $as_echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
$RM conftest*
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } 2>conftest.err; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } 2>conftest.err; then
soname=conftest
lib=conftest
libobjs=conftest.$ac_objext
@@ -8523,11 +8236,11 @@ $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
libname=conftest
lt_save_allow_undefined_flag=$allow_undefined_flag
allow_undefined_flag=
- if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
(eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
then
archive_cmds_need_lc=no
else
@@ -8538,7 +8251,7 @@ $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
cat conftest.err 1>&5
fi
$RM conftest*
- { $as_echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5
$as_echo "$archive_cmds_need_lc" >&6; }
;;
esac
@@ -8702,7 +8415,7 @@ esac
- { $as_echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
$as_echo_n "checking dynamic linker characteristics... " >&6; }
if test "$GCC" = yes; then
@@ -9137,11 +8850,7 @@ linux* | k*bsd*-gnu)
save_libdir=$libdir
eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -9152,41 +8861,13 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
- if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then
+if ac_fn_c_try_link "$LINENO"; then :
+ if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
shlibpath_overrides_runpath=yes
fi
-
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LDFLAGS=$save_LDFLAGS
libdir=$save_libdir
@@ -9398,7 +9079,7 @@ uts4*)
dynamic_linker=no
;;
esac
-{ $as_echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
$as_echo "$dynamic_linker" >&6; }
test "$dynamic_linker" = no && can_build_shared=no
@@ -9500,7 +9181,7 @@ fi
- { $as_echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
hardcode_action=
if test -n "$hardcode_libdir_flag_spec" ||
@@ -9525,7 +9206,7 @@ else
# directories.
hardcode_action=unsupported
fi
-{ $as_echo "$as_me:$LINENO: result: $hardcode_action" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
$as_echo "$hardcode_action" >&6; }
if test "$hardcode_action" = relink ||
@@ -9570,18 +9251,14 @@ else
darwin*)
# if libdl is installed we need to link against it
- { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -9599,43 +9276,18 @@ return dlopen ();
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_dl_dlopen=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_dl_dlopen=no
+ ac_cv_lib_dl_dlopen=no
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test $ac_cv_lib_dl_dlopen = yes; then
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
else
@@ -9648,106 +9300,18 @@ fi
;;
*)
- { $as_echo "$as_me:$LINENO: checking for shl_load" >&5
-$as_echo_n "checking for shl_load... " >&6; }
-if test "${ac_cv_func_shl_load+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define shl_load to an innocuous variant, in case declares shl_load.
- For example, HP-UX 11i declares gettimeofday. */
-#define shl_load innocuous_shl_load
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char shl_load (); below.
- Prefer to if __STDC__ is defined, since
- exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include
-#else
-# include
-#endif
-
-#undef shl_load
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_shl_load || defined __stub___shl_load
-choke me
-#endif
-
-int
-main ()
-{
-return shl_load ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
- ac_cv_func_shl_load=yes
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_shl_load=no
-fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
-$as_echo "$ac_cv_func_shl_load" >&6; }
-if test $ac_cv_func_shl_load = yes; then
+ ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = x""yes; then :
lt_cv_dlopen="shl_load"
else
- { $as_echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
$as_echo_n "checking for shl_load in -ldld... " >&6; }
-if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldld $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -9765,145 +9329,32 @@ return shl_load ();
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_dld_shl_load=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_dld_shl_load=no
+ ac_cv_lib_dld_shl_load=no
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
-if test $ac_cv_lib_dld_shl_load = yes; then
+if test "x$ac_cv_lib_dld_shl_load" = x""yes; then :
lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
else
- { $as_echo "$as_me:$LINENO: checking for dlopen" >&5
-$as_echo_n "checking for dlopen... " >&6; }
-if test "${ac_cv_func_dlopen+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define dlopen to an innocuous variant, in case declares dlopen.
- For example, HP-UX 11i declares gettimeofday. */
-#define dlopen innocuous_dlopen
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char dlopen (); below.
- Prefer to if __STDC__ is defined, since
- exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include
-#else
-# include
-#endif
-
-#undef dlopen
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_dlopen || defined __stub___dlopen
-choke me
-#endif
-
-int
-main ()
-{
-return dlopen ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
- ac_cv_func_dlopen=yes
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_func_dlopen=no
-fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
-$as_echo "$ac_cv_func_dlopen" >&6; }
-if test $ac_cv_func_dlopen = yes; then
+ ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = x""yes; then :
lt_cv_dlopen="dlopen"
else
- { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -9921,57 +9372,28 @@ return dlopen ();
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_dl_dlopen=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_dl_dlopen=no
+ ac_cv_lib_dl_dlopen=no
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test $ac_cv_lib_dl_dlopen = yes; then
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
else
- { $as_echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
$as_echo_n "checking for dlopen in -lsvld... " >&6; }
-if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsvld $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -9989,57 +9411,28 @@ return dlopen ();
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_svld_dlopen=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_svld_dlopen=no
+ ac_cv_lib_svld_dlopen=no
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
-if test $ac_cv_lib_svld_dlopen = yes; then
+if test "x$ac_cv_lib_svld_dlopen" = x""yes; then :
lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
else
- { $as_echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
$as_echo_n "checking for dld_link in -ldld... " >&6; }
-if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldld $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -10057,43 +9450,18 @@ return dld_link ();
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_dld_dld_link=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_dld_dld_link=no
+ ac_cv_lib_dld_dld_link=no
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
-if test $ac_cv_lib_dld_dld_link = yes; then
+if test "x$ac_cv_lib_dld_dld_link" = x""yes; then :
lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
fi
@@ -10132,9 +9500,9 @@ fi
save_LIBS="$LIBS"
LIBS="$lt_cv_dlopen_libs $LIBS"
- { $as_echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
$as_echo_n "checking whether a program can dlopen itself... " >&6; }
-if test "${lt_cv_dlopen_self+set}" = set; then
+if test "${lt_cv_dlopen_self+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
@@ -10143,7 +9511,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10146 "configure"
+#line 9514 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10202,11 +9570,11 @@ int main ()
return status;
}
_LT_EOF
- if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
(eval $ac_link) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
(./conftest; exit; ) >&5 2>/dev/null
lt_status=$?
case x$lt_status in
@@ -10223,14 +9591,14 @@ rm -fr conftest*
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
$as_echo "$lt_cv_dlopen_self" >&6; }
if test "x$lt_cv_dlopen_self" = xyes; then
wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
- { $as_echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
-if test "${lt_cv_dlopen_self_static+set}" = set; then
+if test "${lt_cv_dlopen_self_static+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
@@ -10239,7 +9607,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10242 "configure"
+#line 9610 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10298,11 +9666,11 @@ int main ()
return status;
}
_LT_EOF
- if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
(eval $ac_link) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
(./conftest; exit; ) >&5 2>/dev/null
lt_status=$?
case x$lt_status in
@@ -10319,7 +9687,7 @@ rm -fr conftest*
fi
-{ $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
$as_echo "$lt_cv_dlopen_self_static" >&6; }
fi
@@ -10358,12 +9726,12 @@ fi
striplib=
old_striplib=
-{ $as_echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
$as_echo_n "checking whether stripping libraries is possible... " >&6; }
if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
test -z "$striplib" && striplib="$STRIP --strip-unneeded"
- { $as_echo "$as_me:$LINENO: result: yes" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
# FIXME - insert some real tests, host_os isn't really good enough
@@ -10372,15 +9740,15 @@ else
if test -n "$STRIP" ; then
striplib="$STRIP -x"
old_striplib="$STRIP -S"
- { $as_echo "$as_me:$LINENO: result: yes" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
;;
*)
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
;;
esac
@@ -10398,12 +9766,12 @@ fi
# Report which library types will actually be built
- { $as_echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
$as_echo_n "checking if libtool supports shared libraries... " >&6; }
- { $as_echo "$as_me:$LINENO: result: $can_build_shared" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
$as_echo "$can_build_shared" >&6; }
- { $as_echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
$as_echo_n "checking whether to build shared libraries... " >&6; }
test "$can_build_shared" = "no" && enable_shared=no
@@ -10424,14 +9792,14 @@ $as_echo_n "checking whether to build shared libraries... " >&6; }
fi
;;
esac
- { $as_echo "$as_me:$LINENO: result: $enable_shared" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
$as_echo "$enable_shared" >&6; }
- { $as_echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
$as_echo_n "checking whether to build static libraries... " >&6; }
# Make sure either enable_shared or enable_static is yes.
test "$enable_shared" = yes || enable_static=yes
- { $as_echo "$as_me:$LINENO: result: $enable_static" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
$as_echo "$enable_static" >&6; }
@@ -10480,10 +9848,10 @@ CC="$lt_save_CC"
# OS/2's system install, which has a completely different semantic
# ./install, which can be erroneously created by make from ./install.sh.
# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
$as_echo_n "checking for a BSD-compatible install... " >&6; }
if test -z "$INSTALL"; then
-if test "${ac_cv_path_install+set}" = set; then
+if test "${ac_cv_path_install+set}" = set; then :
$as_echo_n "(cached) " >&6
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -10491,11 +9859,11 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in
- ./ | .// | /cC/* | \
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
/usr/ucb/* ) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
@@ -10532,7 +9900,7 @@ case $as_dir/ in
;;
esac
-done
+ done
IFS=$as_save_IFS
rm -rf conftest.one conftest.two conftest.dir
@@ -10548,7 +9916,7 @@ fi
INSTALL=$ac_install_sh
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $INSTALL" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
$as_echo "$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
@@ -10563,9 +9931,9 @@ for ac_prog in gawk mawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_AWK+set}" = set; then
+if test "${ac_cv_prog_AWK+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$AWK"; then
@@ -10576,24 +9944,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_AWK="$ac_prog"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
AWK=$ac_cv_prog_AWK
if test -n "$AWK"; then
- { $as_echo "$as_me:$LINENO: result: $AWK" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
$as_echo "$AWK" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -10606,15 +9974,15 @@ done
# Enable large file support (if special flags are necessary)
#
# Check whether --enable-largefile was given.
-if test "${enable_largefile+set}" = set; then
+if test "${enable_largefile+set}" = set; then :
enableval=$enable_largefile;
fi
if test "$enable_largefile" != no; then
- { $as_echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
-if test "${ac_cv_sys_largefile_CC+set}" = set; then
+if test "${ac_cv_sys_largefile_CC+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_cv_sys_largefile_CC=no
@@ -10623,11 +9991,7 @@ else
while :; do
# IRIX 6.2 and later do not support large files by default,
# so use the C compiler's -n32 option if that helps.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
/* Check that off_t can represent 2**63 - 1 correctly.
@@ -10646,60 +10010,14 @@ main ()
return 0;
}
_ACEOF
- rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+ if ac_fn_c_try_compile "$LINENO"; then :
break
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
rm -f core conftest.err conftest.$ac_objext
CC="$CC -n32"
- rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+ if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_largefile_CC=' -n32'; break
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
rm -f core conftest.err conftest.$ac_objext
break
done
@@ -10707,23 +10025,19 @@ rm -f core conftest.err conftest.$ac_objext
rm -f conftest.$ac_ext
fi
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
$as_echo "$ac_cv_sys_largefile_CC" >&6; }
if test "$ac_cv_sys_largefile_CC" != no; then
CC=$CC$ac_cv_sys_largefile_CC
fi
- { $as_echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
-if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then :
$as_echo_n "(cached) " >&6
else
while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
/* Check that off_t can represent 2**63 - 1 correctly.
@@ -10742,38 +10056,11 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_file_offset_bits=no; break
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _FILE_OFFSET_BITS 64
#include
@@ -10793,38 +10080,15 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_file_offset_bits=64; break
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_sys_file_offset_bits=unknown
break
done
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
case $ac_cv_sys_file_offset_bits in #(
no | unknown) ;;
@@ -10836,17 +10100,13 @@ _ACEOF
esac
rm -rf conftest*
if test $ac_cv_sys_file_offset_bits = unknown; then
- { $as_echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
-if test "${ac_cv_sys_large_files+set}" = set; then
+if test "${ac_cv_sys_large_files+set}" = set; then :
$as_echo_n "(cached) " >&6
else
while :; do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
/* Check that off_t can represent 2**63 - 1 correctly.
@@ -10865,38 +10125,11 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_large_files=no; break
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGE_FILES 1
#include
@@ -10916,38 +10149,15 @@ main ()
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_large_files=1; break
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_sys_large_files=unknown
break
done
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
$as_echo "$ac_cv_sys_large_files" >&6; }
case $ac_cv_sys_large_files in #(
no | unknown) ;;
@@ -10964,101 +10174,8 @@ fi
#########
# Check for needed/wanted data types
-{ $as_echo "$as_me:$LINENO: checking for int8_t" >&5
-$as_echo_n "checking for int8_t... " >&6; }
-if test "${ac_cv_type_int8_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_int8_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (int8_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((int8_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_int8_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_int8_t" >&5
-$as_echo "$ac_cv_type_int8_t" >&6; }
-if test $ac_cv_type_int8_t = yes; then
+ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default"
+if test "x$ac_cv_type_int8_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_INT8_T 1
@@ -11066,101 +10183,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for int16_t" >&5
-$as_echo_n "checking for int16_t... " >&6; }
-if test "${ac_cv_type_int16_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_int16_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (int16_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((int16_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_int16_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_int16_t" >&5
-$as_echo "$ac_cv_type_int16_t" >&6; }
-if test $ac_cv_type_int16_t = yes; then
+ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default"
+if test "x$ac_cv_type_int16_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_INT16_T 1
@@ -11168,101 +10192,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for int32_t" >&5
-$as_echo_n "checking for int32_t... " >&6; }
-if test "${ac_cv_type_int32_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_int32_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (int32_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((int32_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_int32_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_int32_t" >&5
-$as_echo "$ac_cv_type_int32_t" >&6; }
-if test $ac_cv_type_int32_t = yes; then
+ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default"
+if test "x$ac_cv_type_int32_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_INT32_T 1
@@ -11270,101 +10201,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for int64_t" >&5
-$as_echo_n "checking for int64_t... " >&6; }
-if test "${ac_cv_type_int64_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_int64_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (int64_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((int64_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_int64_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_int64_t" >&5
-$as_echo "$ac_cv_type_int64_t" >&6; }
-if test $ac_cv_type_int64_t = yes; then
+ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default"
+if test "x$ac_cv_type_int64_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_INT64_T 1
@@ -11372,101 +10210,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for intptr_t" >&5
-$as_echo_n "checking for intptr_t... " >&6; }
-if test "${ac_cv_type_intptr_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_intptr_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (intptr_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((intptr_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_intptr_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_intptr_t" >&5
-$as_echo "$ac_cv_type_intptr_t" >&6; }
-if test $ac_cv_type_intptr_t = yes; then
+ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default"
+if test "x$ac_cv_type_intptr_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_INTPTR_T 1
@@ -11474,101 +10219,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for uint8_t" >&5
-$as_echo_n "checking for uint8_t... " >&6; }
-if test "${ac_cv_type_uint8_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_uint8_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (uint8_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((uint8_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_uint8_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uint8_t" >&5
-$as_echo "$ac_cv_type_uint8_t" >&6; }
-if test $ac_cv_type_uint8_t = yes; then
+ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default"
+if test "x$ac_cv_type_uint8_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UINT8_T 1
@@ -11576,101 +10228,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for uint16_t" >&5
-$as_echo_n "checking for uint16_t... " >&6; }
-if test "${ac_cv_type_uint16_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_uint16_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (uint16_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((uint16_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_uint16_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uint16_t" >&5
-$as_echo "$ac_cv_type_uint16_t" >&6; }
-if test $ac_cv_type_uint16_t = yes; then
+ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default"
+if test "x$ac_cv_type_uint16_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UINT16_T 1
@@ -11678,101 +10237,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for uint32_t" >&5
-$as_echo_n "checking for uint32_t... " >&6; }
-if test "${ac_cv_type_uint32_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_uint32_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (uint32_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((uint32_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_uint32_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uint32_t" >&5
-$as_echo "$ac_cv_type_uint32_t" >&6; }
-if test $ac_cv_type_uint32_t = yes; then
+ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default"
+if test "x$ac_cv_type_uint32_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UINT32_T 1
@@ -11780,101 +10246,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for uint64_t" >&5
-$as_echo_n "checking for uint64_t... " >&6; }
-if test "${ac_cv_type_uint64_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_uint64_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (uint64_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((uint64_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_uint64_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uint64_t" >&5
-$as_echo "$ac_cv_type_uint64_t" >&6; }
-if test $ac_cv_type_uint64_t = yes; then
+ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default"
+if test "x$ac_cv_type_uint64_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UINT64_T 1
@@ -11882,101 +10255,8 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for uintptr_t" >&5
-$as_echo_n "checking for uintptr_t... " >&6; }
-if test "${ac_cv_type_uintptr_t+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_type_uintptr_t=no
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof (uintptr_t))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-if (sizeof ((uintptr_t)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- :
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_type_uintptr_t=yes
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5
-$as_echo "$ac_cv_type_uintptr_t" >&6; }
-if test $ac_cv_type_uintptr_t = yes; then
+ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
+if test "x$ac_cv_type_uintptr_t" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UINTPTR_T 1
@@ -11988,146 +10268,11 @@ fi
#########
# Check for needed/wanted headers
-
-
-
-
for ac_header in sys/types.h stdlib.h stdint.h inttypes.h
-do
-as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
-$as_echo_n "checking for $ac_header... " >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- $as_echo_n "(cached) " >&6
-fi
-ac_res=`eval 'as_val=${'$as_ac_Header'}
- $as_echo "$as_val"'`
- { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5
-$as_echo_n "checking $ac_header usability... " >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5
-$as_echo_n "checking $ac_header presence... " >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-
- ;;
-esac
-{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
-$as_echo_n "checking for $ac_header... " >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
- $as_echo_n "(cached) " >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval 'as_val=${'$as_ac_Header'}
- $as_echo "$as_val"'`
- { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-
-fi
-if test `eval 'as_val=${'$as_ac_Header'}
- $as_echo "$as_val"'` = yes; then
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
@@ -12140,104 +10285,11 @@ done
#########
# Figure out whether or not we have these functions
#
-
-
-
-
-
-
for ac_func in usleep fdatasync localtime_r gmtime_r localtime_s utime
-do
-as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
-$as_echo_n "checking for $ac_func... " >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
- $as_echo_n "(cached) " >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define $ac_func to an innocuous variant, in case declares $ac_func.
- For example, HP-UX 11i declares gettimeofday. */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func (); below.
- Prefer to if __STDC__ is defined, since
- exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include
-#else
-# include
-#endif
-
-#undef $ac_func
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
-int
-main ()
-{
-return $ac_func ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
- eval "$as_ac_var=yes"
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_var=no"
-fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-fi
-ac_res=`eval 'as_val=${'$as_ac_var'}
- $as_echo "$as_val"'`
- { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-if test `eval 'as_val=${'$as_ac_var'}
- $as_echo "$as_val"'` = yes; then
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
@@ -12260,9 +10312,9 @@ for ac_prog in tclsh8.5 tclsh
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_TCLSH_CMD+set}" = set; then
+if test "${ac_cv_prog_TCLSH_CMD+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$TCLSH_CMD"; then
@@ -12273,24 +10325,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_TCLSH_CMD="$ac_prog"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
TCLSH_CMD=$ac_cv_prog_TCLSH_CMD
if test -n "$TCLSH_CMD"; then
- { $as_echo "$as_me:$LINENO: result: $TCLSH_CMD" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_CMD" >&5
$as_echo "$TCLSH_CMD" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -12328,17 +10380,17 @@ fi
VERSION=`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`
-{ $as_echo "$as_me:$LINENO: Version set to $VERSION" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: Version set to $VERSION" >&5
$as_echo "$as_me: Version set to $VERSION" >&6;}
RELEASE=`cat $srcdir/VERSION`
-{ $as_echo "$as_me:$LINENO: Release set to $RELEASE" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: Release set to $RELEASE" >&5
$as_echo "$as_me: Release set to $RELEASE" >&6;}
VERSION_NUMBER=`cat $srcdir/VERSION \
| sed 's/[^0-9]/ /g' \
| awk '{printf "%d%03d%03d",$1,$2,$3}'`
-{ $as_echo "$as_me:$LINENO: Version number set to $VERSION_NUMBER" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: Version number set to $VERSION_NUMBER" >&5
$as_echo "$as_me: Version number set to $VERSION_NUMBER" >&6;}
@@ -12351,7 +10403,7 @@ $as_echo "$as_me: Version number set to $VERSION_NUMBER" >&6;}
#
# Check whether --with-hints was given.
-if test "${with_hints+set}" = set; then
+if test "${with_hints+set}" = set; then :
withval=$with_hints; hints=$withval
fi
@@ -12376,7 +10428,7 @@ if test "$hints" = ""; then
fi
fi
if test "$hints" != ""; then
- { $as_echo "$as_me:$LINENO: result: reading hints from $hints" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: reading hints from $hints" >&5
$as_echo "reading hints from $hints" >&6; }
. $hints
fi
@@ -12394,9 +10446,9 @@ else
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_BUILD_CC+set}" = set; then
+if test "${ac_cv_prog_BUILD_CC+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$BUILD_CC"; then
@@ -12407,24 +10459,24 @@ for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_BUILD_CC="$ac_prog"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
-done
+ done
IFS=$as_save_IFS
fi
fi
BUILD_CC=$ac_cv_prog_BUILD_CC
if test -n "$BUILD_CC"; then
- { $as_echo "$as_me:$LINENO: result: $BUILD_CC" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5
$as_echo "$BUILD_CC" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -12443,37 +10495,33 @@ fi
# Do we want to support multithreaded use of sqlite
#
# Check whether --enable-threadsafe was given.
-if test "${enable_threadsafe+set}" = set; then
+if test "${enable_threadsafe+set}" = set; then :
enableval=$enable_threadsafe;
else
enable_threadsafe=yes
fi
-{ $as_echo "$as_me:$LINENO: checking whether to support threadsafe operation" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support threadsafe operation" >&5
$as_echo_n "checking whether to support threadsafe operation... " >&6; }
if test "$enable_threadsafe" = "no"; then
SQLITE_THREADSAFE=0
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
SQLITE_THREADSAFE=1
- { $as_echo "$as_me:$LINENO: result: yes" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
if test "$SQLITE_THREADSAFE" = "1"; then
- { $as_echo "$as_me:$LINENO: checking for library containing pthread_create" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
$as_echo_n "checking for library containing pthread_create... " >&6; }
-if test "${ac_cv_search_pthread_create+set}" = set; then
+if test "${ac_cv_search_pthread_create+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -12498,54 +10546,27 @@ for ac_lib in '' pthread; do
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+ if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_pthread_create=$ac_res
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_pthread_create+set}" = set; then
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_pthread_create+set}" = set; then :
break
fi
done
-if test "${ac_cv_search_pthread_create+set}" = set; then
- :
+if test "${ac_cv_search_pthread_create+set}" = set; then :
+
else
ac_cv_search_pthread_create=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_pthread_create" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5
$as_echo "$ac_cv_search_pthread_create" >&6; }
ac_res=$ac_cv_search_pthread_create
-if test "$ac_res" != no; then
+if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
@@ -12558,21 +10579,21 @@ fi
# 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
+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 "$as_me:${as_lineno-$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 "$as_me:${as_lineno-$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 "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
@@ -12581,21 +10602,21 @@ fi
# Do we want to support release
#
# Check whether --enable-releasemode was given.
-if test "${enable_releasemode+set}" = set; then
+if test "${enable_releasemode+set}" = set; then :
enableval=$enable_releasemode;
else
enable_releasemode=no
fi
-{ $as_echo "$as_me:$LINENO: checking whether to support shared library linked as release mode or not" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support shared library linked as release mode or not" >&5
$as_echo_n "checking whether to support shared library linked as release mode or not... " >&6; }
if test "$enable_releasemode" = "no"; then
ALLOWRELEASE=""
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
ALLOWRELEASE="-release `cat $srcdir/VERSION`"
- { $as_echo "$as_me:$LINENO: result: yes" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
@@ -12604,38 +10625,38 @@ fi
# Do we want temporary databases in memory
#
# Check whether --enable-tempstore was given.
-if test "${enable_tempstore+set}" = set; then
+if test "${enable_tempstore+set}" = set; then :
enableval=$enable_tempstore;
else
enable_tempstore=no
fi
-{ $as_echo "$as_me:$LINENO: checking whether to use an in-ram database for temporary tables" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use an in-ram database for temporary tables" >&5
$as_echo_n "checking whether to use an in-ram database for temporary tables... " >&6; }
case "$enable_tempstore" in
never )
TEMP_STORE=0
- { $as_echo "$as_me:$LINENO: result: never" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: never" >&5
$as_echo "never" >&6; }
;;
no )
TEMP_STORE=1
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
;;
yes )
TEMP_STORE=2
- { $as_echo "$as_me:$LINENO: result: yes" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
;;
always )
TEMP_STORE=3
- { $as_echo "$as_me:$LINENO: result: always" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: always" >&5
$as_echo "always" >&6; }
;;
* )
TEMP_STORE=1
- { $as_echo "$as_me:$LINENO: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
;;
esac
@@ -12647,53 +10668,17 @@ esac
# the CYGWIN environment. So check for that special case and handle
# things accordingly.
#
-{ $as_echo "$as_me:$LINENO: checking if executables have the .exe suffix" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if executables have the .exe suffix" >&5
$as_echo_n "checking if executables have the .exe suffix... " >&6; }
if test "$config_BUILD_EXEEXT" = ".exe"; then
CYGWIN=yes
- { $as_echo "$as_me:$LINENO: result: yes" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
- { $as_echo "$as_me:$LINENO: result: unknown" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5
$as_echo "unknown" >&6; }
fi
if test "$CYGWIN" != "yes"; then
- { $as_echo "$as_me:$LINENO: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if test "${ac_cv_host+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- if test "x$host_alias" = x; then
- ac_cv_host=$ac_cv_build
-else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
-$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
-$as_echo "$as_me: error: invalid value of canonical host" >&2;}
- { (exit 1); exit 1; }; };;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
case $host_os in
*cygwin* ) CYGWIN=yes;;
@@ -12745,7 +10730,7 @@ fi
# minor changes to accomodate systems that do not have TCL installed.
#
# Check whether --enable-tcl was given.
-if test "${enable_tcl+set}" = set; then
+if test "${enable_tcl+set}" = set; then :
enableval=$enable_tcl; use_tcl=$enableval
else
use_tcl=yes
@@ -12754,13 +10739,13 @@ fi
if test "${use_tcl}" = "yes" ; then
# Check whether --with-tcl was given.
-if test "${with_tcl+set}" = set; then
+if test "${with_tcl+set}" = set; then :
withval=$with_tcl; with_tclconfig=${withval}
fi
- { $as_echo "$as_me:$LINENO: checking for Tcl configuration" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5
$as_echo_n "checking for Tcl configuration... " >&6; }
- if test "${ac_cv_c_tclconfig+set}" = set; then
+ if test "${ac_cv_c_tclconfig+set}" = set; then :
$as_echo_n "(cached) " >&6
else
@@ -12769,9 +10754,7 @@ else
if test -f "${with_tclconfig}/tclConfig.sh" ; then
ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
else
- { { $as_echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5
-$as_echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5
fi
fi
@@ -12844,25 +10827,25 @@ fi
if test x"${ac_cv_c_tclconfig}" = x ; then
use_tcl=no
- { $as_echo "$as_me:$LINENO: WARNING: Can't find Tcl configuration definitions" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find Tcl configuration definitions" >&5
$as_echo "$as_me: WARNING: Can't find Tcl configuration definitions" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&5
$as_echo "$as_me: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&5
$as_echo "$as_me: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&2;}
else
TCL_BIN_DIR=${ac_cv_c_tclconfig}
- { $as_echo "$as_me:$LINENO: result: found $TCL_BIN_DIR/tclConfig.sh" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $TCL_BIN_DIR/tclConfig.sh" >&5
$as_echo "found $TCL_BIN_DIR/tclConfig.sh" >&6; }
- { $as_echo "$as_me:$LINENO: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5
$as_echo_n "checking for existence of $TCL_BIN_DIR/tclConfig.sh... " >&6; }
if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
- { $as_echo "$as_me:$LINENO: result: loading" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5
$as_echo "loading" >&6; }
. $TCL_BIN_DIR/tclConfig.sh
else
- { $as_echo "$as_me:$LINENO: result: file not found" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: file not found" >&5
$as_echo "file not found" >&6; }
fi
@@ -12923,7 +10906,7 @@ TARGET_READLINE_LIBS=""
TARGET_READLINE_INC=""
TARGET_HAVE_READLINE=0
# Check whether --enable-readline was given.
-if test "${enable_readline+set}" = set; then
+if test "${enable_readline+set}" = set; then :
enableval=$enable_readline; with_readline=$enableval
else
with_readline=auto
@@ -12935,7 +10918,7 @@ if test x"$with_readline" != xno; then
# Check whether --with-readline-lib was given.
-if test "${with_readline_lib+set}" = set; then
+if test "${with_readline_lib+set}" = set; then :
withval=$with_readline_lib; with_readline_lib=$withval
else
with_readline_lib="auto"
@@ -12944,17 +10927,13 @@ fi
if test "x$with_readline_lib" = xauto; then
save_LIBS="$LIBS"
LIBS=""
- { $as_echo "$as_me:$LINENO: checking for library containing tgetent" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tgetent" >&5
$as_echo_n "checking for library containing tgetent... " >&6; }
-if test "${ac_cv_search_tgetent+set}" = set; then
+if test "${ac_cv_search_tgetent+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -12979,72 +10958,41 @@ for ac_lib in '' readline ncurses curses termcap; do
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+ if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_tgetent=$ac_res
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_tgetent+set}" = set; then
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_tgetent+set}" = set; then :
break
fi
done
-if test "${ac_cv_search_tgetent+set}" = set; then
- :
+if test "${ac_cv_search_tgetent+set}" = set; then :
+
else
ac_cv_search_tgetent=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_tgetent" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_tgetent" >&5
$as_echo "$ac_cv_search_tgetent" >&6; }
ac_res=$ac_cv_search_tgetent
-if test "$ac_res" != no; then
+if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
term_LIBS="$LIBS"
else
term_LIBS=""
fi
- { $as_echo "$as_me:$LINENO: checking for readline in -lreadline" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5
$as_echo_n "checking for readline in -lreadline... " >&6; }
-if test "${ac_cv_lib_readline_readline+set}" = set; then
+if test "${ac_cv_lib_readline_readline+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lreadline $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -13062,43 +11010,18 @@ return readline ();
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_readline_readline=yes
else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_readline_readline=no
+ ac_cv_lib_readline_readline=no
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5
$as_echo "$ac_cv_lib_readline_readline" >&6; }
-if test $ac_cv_lib_readline_readline = yes; then
+if test "x$ac_cv_lib_readline_readline" = x""yes; then :
TARGET_READLINE_LIBS="-lreadline"
else
found="no"
@@ -13112,141 +11035,15 @@ fi
# Check whether --with-readline-inc was given.
-if test "${with_readline_inc+set}" = set; then
+if test "${with_readline_inc+set}" = set; then :
withval=$with_readline_inc; with_readline_inc=$withval
else
with_readline_inc="auto"
fi
if test "x$with_readline_inc" = xauto; then
- if test "${ac_cv_header_readline_h+set}" = set; then
- { $as_echo "$as_me:$LINENO: checking for readline.h" >&5
-$as_echo_n "checking for readline.h... " >&6; }
-if test "${ac_cv_header_readline_h+set}" = set; then
- $as_echo_n "(cached) " >&6
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_readline_h" >&5
-$as_echo "$ac_cv_header_readline_h" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:$LINENO: checking readline.h usability" >&5
-$as_echo_n "checking readline.h usability... " >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_header_compiler=yes
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:$LINENO: checking readline.h presence" >&5
-$as_echo_n "checking readline.h presence... " >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then
- ac_header_preproc=yes
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { $as_echo "$as_me:$LINENO: WARNING: readline.h: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: readline.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: readline.h: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: readline.h: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { $as_echo "$as_me:$LINENO: WARNING: readline.h: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: readline.h: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: readline.h: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: readline.h: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: readline.h: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: readline.h: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: readline.h: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: readline.h: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: readline.h: proceeding with the preprocessor's result" >&5
-$as_echo "$as_me: WARNING: readline.h: proceeding with the preprocessor's result" >&2;}
- { $as_echo "$as_me:$LINENO: WARNING: readline.h: in the future, the compiler will take precedence" >&5
-$as_echo "$as_me: WARNING: readline.h: in the future, the compiler will take precedence" >&2;}
-
- ;;
-esac
-{ $as_echo "$as_me:$LINENO: checking for readline.h" >&5
-$as_echo_n "checking for readline.h... " >&6; }
-if test "${ac_cv_header_readline_h+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- ac_cv_header_readline_h=$ac_header_preproc
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_readline_h" >&5
-$as_echo "$ac_cv_header_readline_h" >&6; }
-
-fi
-if test $ac_cv_header_readline_h = yes; then
+ ac_fn_c_check_header_mongrel "$LINENO" "readline.h" "ac_cv_header_readline_h" "$ac_includes_default"
+if test "x$ac_cv_header_readline_h" = x""yes; then :
found="yes"
else
@@ -13255,27 +11052,23 @@ else
for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do
for subdir in include include/readline; do
as_ac_File=`$as_echo "ac_cv_file_$dir/$subdir/readline.h" | $as_tr_sh`
-{ $as_echo "$as_me:$LINENO: checking for $dir/$subdir/readline.h" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $dir/$subdir/readline.h" >&5
$as_echo_n "checking for $dir/$subdir/readline.h... " >&6; }
-if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
+if eval "test \"\${$as_ac_File+set}\"" = set; then :
$as_echo_n "(cached) " >&6
else
test "$cross_compiling" = yes &&
- { { $as_echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-$as_echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
if test -r "$dir/$subdir/readline.h"; then
eval "$as_ac_File=yes"
else
eval "$as_ac_File=no"
fi
fi
-ac_res=`eval 'as_val=${'$as_ac_File'}
- $as_echo "$as_val"'`
- { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+eval ac_res=\$$as_ac_File
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
-if test `eval 'as_val=${'$as_ac_File'}
- $as_echo "$as_val"'` = yes; then
+if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
found=yes
fi
@@ -13312,17 +11105,13 @@ fi
# Figure out what C libraries are required to compile programs
# that use "fdatasync()" function.
#
-{ $as_echo "$as_me:$LINENO: checking for library containing fdatasync" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5
$as_echo_n "checking for library containing fdatasync... " >&6; }
-if test "${ac_cv_search_fdatasync+set}" = set; then
+if test "${ac_cv_search_fdatasync+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -13347,54 +11136,27 @@ for ac_lib in '' rt; do
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+ if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_fdatasync=$ac_res
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_fdatasync+set}" = set; then
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_fdatasync+set}" = set; then :
break
fi
done
-if test "${ac_cv_search_fdatasync+set}" = set; then
- :
+if test "${ac_cv_search_fdatasync+set}" = set; then :
+
else
ac_cv_search_fdatasync=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_fdatasync" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fdatasync" >&5
$as_echo "$ac_cv_search_fdatasync" >&6; }
ac_res=$ac_cv_search_fdatasync
-if test "$ac_res" != no; then
+if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
@@ -13403,7 +11165,7 @@ fi
#########
# check for debug enabled
# Check whether --enable-debug was given.
-if test "${enable_debug+set}" = set; then
+if test "${enable_debug+set}" = set; then :
enableval=$enable_debug; use_debug=$enableval
else
use_debug=no
@@ -13419,7 +11181,7 @@ fi
#########
# See whether we should use the amalgamation to build
# Check whether --enable-amalgamation was given.
-if test "${enable_amalgamation+set}" = set; then
+if test "${enable_amalgamation+set}" = set; then :
enableval=$enable_amalgamation; use_amalgamation=$enableval
else
use_amalgamation=yes
@@ -13433,7 +11195,7 @@ fi
#########
# See whether we should allow loadable extensions
# Check whether --enable-load-extension was given.
-if test "${enable_load_extension+set}" = set; then
+if test "${enable_load_extension+set}" = set; then :
enableval=$enable_load_extension; use_loadextension=$enableval
else
use_loadextension=no
@@ -13441,17 +11203,13 @@ fi
if test "${use_loadextension}" = "yes" ; then
OPT_FEATURE_FLAGS=""
- { $as_echo "$as_me:$LINENO: checking for library containing dlopen" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
$as_echo_n "checking for library containing dlopen... " >&6; }
-if test "${ac_cv_search_dlopen+set}" = set; then
+if test "${ac_cv_search_dlopen+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
@@ -13476,54 +11234,27 @@ for ac_lib in '' dl; do
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then
+ if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_dlopen=$ac_res
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
fi
-
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext
- if test "${ac_cv_search_dlopen+set}" = set; then
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_dlopen+set}" = set; then :
break
fi
done
-if test "${ac_cv_search_dlopen+set}" = set; then
- :
+if test "${ac_cv_search_dlopen+set}" = set; then :
+
else
ac_cv_search_dlopen=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_dlopen" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
$as_echo "$ac_cv_search_dlopen" >&6; }
ac_res=$ac_cv_search_dlopen
-if test "$ac_res" != no; then
+if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
@@ -13586,7 +11317,7 @@ BUILD_CFLAGS=$ac_temp_BUILD_CFLAGS
#########
# See whether we should use GCOV
# Check whether --enable-gcov was given.
-if test "${enable_gcov+set}" = set; then
+if test "${enable_gcov+set}" = set; then :
enableval=$enable_gcov; use_gcov=$enableval
else
use_gcov=no
@@ -13638,13 +11369,13 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-$as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
- *) $as_unset $ac_var ;;
+ *) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
@@ -13652,8 +11383,8 @@ $as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
(set) 2>&1 |
case $as_nl`(ac_space=' '; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote
- # substitution turns \\\\ into \\, and sed turns \\ into \).
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
sed -n \
"s/'/'\\\\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
@@ -13676,11 +11407,11 @@ $as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
test "x$cache_file" != "x/dev/null" &&
- { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
$as_echo "$as_me: updating cache $cache_file" >&6;}
cat confcache >$cache_file
else
- { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
@@ -13694,14 +11425,15 @@ DEFS=-DHAVE_CONFIG_H
ac_libobjs=
ac_ltlibobjs=
+U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
- ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
- ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs
@@ -13713,9 +11445,10 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
@@ -13725,17 +11458,18 @@ cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
debug=false
ac_cs_recheck=false
ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
@@ -13743,23 +11477,15 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
esac
-
fi
-
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
as_nl='
'
export as_nl
@@ -13767,7 +11493,13 @@ export as_nl
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
as_echo='printf %s\n'
as_echo_n='printf %s'
else
@@ -13778,7 +11510,7 @@ else
as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
as_echo_n_body='eval
arg=$1;
- case $arg in
+ case $arg in #(
*"$as_nl"*)
expr "X$arg" : "X\\(.*\\)$as_nl";
arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
@@ -13801,13 +11533,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
}
fi
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
# IFS
# We need space, tab and new line, in precisely that order. Quoting is
@@ -13817,15 +11542,15 @@ fi
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
-case $0 in
+case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
IFS=$as_save_IFS
;;
@@ -13837,12 +11562,16 @@ if test "x$as_myself" = x; then
fi
if test ! -f "$as_myself"; then
$as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- { (exit 1); exit 1; }
+ exit 1
fi
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
@@ -13854,7 +11583,89 @@ export LC_ALL
LANGUAGE=C
export LANGUAGE
-# Required to use basename.
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
@@ -13868,8 +11679,12 @@ else
as_basename=false
fi
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
-# Name of the executable.
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
@@ -13889,76 +11704,25 @@ $as_echo X/"$0" |
}
s/.*/./; q'`
-# CDPATH.
-$as_unset CDPATH
-
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line after each line using $LINENO; the second 'sed'
- # does the real work. The second script uses 'N' to pair each
- # line-number line with the line containing $LINENO, and appends
- # trailing '-' during substitution so that $LINENO is not a special
- # case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # scripts with optimization help from Paolo Bonzini. Blame Lee
- # E. McMahon (1931-1989) for sed's syntax. :-)
- sed -n '
- p
- /[$]LINENO/=
- ' <$as_myself |
- sed '
- s/[$]LINENO.*/&-/
- t lineno
- b
- :lineno
- N
- :loop
- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
- t loop
- s/-\n.*//
- ' >$as_me.lineno &&
- chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensitive to this).
- . "./$as_me.lineno"
- # Exit status is that of the last command.
- exit
-}
-
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
+case `echo -n x` in #(((((
-n*)
- case `echo 'x\c'` in
+ case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
- *) ECHO_C='\c';;
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
@@ -13987,8 +11751,56 @@ fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
+ as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
@@ -14007,10 +11819,10 @@ else
if test -d "$1"; then
test -d "$1/.";
else
- case $1 in
+ case $1 in #(
-*)set "./$1";;
esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
???[sx]*):;;*)false;;esac;fi
'\'' sh
'
@@ -14025,13 +11837,19 @@ as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
-# Save the log message, to keep $[0] and so on meaningful, and to
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sqlite $as_me 3.7.7.1, which was
-generated by GNU Autoconf 2.62. Invocation command line was
+This file was extended by sqlite $as_me 3.7.9, which was
+generated by GNU Autoconf 2.67. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -14044,6 +11862,15 @@ on `(hostname || uname -n) 2>/dev/null | sed 1q`
_ACEOF
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"
@@ -14054,19 +11881,22 @@ _ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
-Usage: $0 [OPTIONS] [FILE]...
+Usage: $0 [OPTION]... [TAG]...
-h, --help print this help, then exit
-V, --version print version number and configuration settings, then exit
- -q, --quiet do not print progress messages
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
-d, --debug don't remove temporary files
--recheck update $as_me by reconfiguring in the same conditions
- --file=FILE[:TEMPLATE]
+ --file=FILE[:TEMPLATE]
instantiate the configuration file FILE
- --header=FILE[:TEMPLATE]
+ --header=FILE[:TEMPLATE]
instantiate the configuration header FILE
Configuration files:
@@ -14078,16 +11908,17 @@ $config_headers
Configuration commands:
$config_commands
-Report bugs to ."
+Report bugs to the package provider."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sqlite config.status 3.7.7.1
-configured by $0, generated by GNU Autoconf 2.62,
- with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+sqlite config.status 3.7.9
+configured by $0, generated by GNU Autoconf 2.67,
+ with options \\"\$ac_cs_config\\"
-Copyright (C) 2008 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -14104,11 +11935,16 @@ ac_need_defaults=:
while test $# != 0
do
case $1 in
- --*=*)
+ --*=?*)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
ac_shift=:
;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
*)
ac_option=$1
ac_optarg=$2
@@ -14122,27 +11958,29 @@ do
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
$as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
esac
- CONFIG_FILES="$CONFIG_FILES '$ac_optarg'"
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
- CONFIG_HEADERS="$CONFIG_HEADERS '$ac_optarg'"
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h)
# Conflict between --help and --header
- { $as_echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; };;
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
--help | --hel | -h )
$as_echo "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
@@ -14150,11 +11988,10 @@ Try \`$0 --help' for more information." >&2
ac_cs_silent=: ;;
# This is an error.
- -*) { $as_echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; } ;;
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
- *) ac_config_targets="$ac_config_targets $1"
+ *) as_fn_append ac_config_targets " $1"
ac_need_defaults=false ;;
esac
@@ -14464,9 +12301,7 @@ do
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"sqlite3.pc") CONFIG_FILES="$CONFIG_FILES sqlite3.pc" ;;
- *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
- { (exit 1); exit 1; }; };;
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
esac
done
@@ -14493,7 +12328,7 @@ $debug ||
trap 'exit_status=$?
{ test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
' 0
- trap '{ (exit 1); exit 1; }' 1 2 13 15
+ trap 'as_fn_exit 1' 1 2 13 15
}
# Create a (secure) tmp directory for tmp files.
@@ -14504,11 +12339,7 @@ $debug ||
{
tmp=./conf$$-$RANDOM
(umask 077 && mkdir "$tmp")
-} ||
-{
- $as_echo "$as_me: cannot create a temporary directory in ." >&2
- { (exit 1); exit 1; }
-}
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
@@ -14516,7 +12347,13 @@ $debug ||
if test -n "$CONFIG_FILES"; then
-ac_cr='
'
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
ac_cs_awk_cr='\\r'
@@ -14533,23 +12370,18 @@ _ACEOF
echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
echo "_ACEOF"
} >conf$$subs.sh ||
- { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
- { (exit 1); exit 1; }; }
-ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
. ./conf$$subs.sh ||
- { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` = $ac_delim_num; then
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
break
elif $ac_last_try; then
- { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
@@ -14571,7 +12403,7 @@ s/'"$ac_delim"'$//
t delim
:nl
h
-s/\(.\{148\}\).*/\1/
+s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
@@ -14585,7 +12417,7 @@ s/.\{148\}//
t nl
:delim
h
-s/\(.\{148\}\).*/\1/
+s/\(.\{148\}\)..*/\1/
t more2
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
@@ -14638,22 +12470,28 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
else
cat
fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
- || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5
-$as_echo "$as_me: error: could not setup config files machinery" >&2;}
- { (exit 1); exit 1; }; }
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[ ]*\):*/\1/
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
s/^[^=]*=[ ]*$//
}'
fi
@@ -14681,9 +12519,7 @@ for ac_last_try in false false :; do
if test -z "$ac_t"; then
break
elif $ac_last_try; then
- { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_HEADERS" >&5
-$as_echo "$as_me: error: could not make $CONFIG_HEADERS" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
@@ -14749,9 +12585,9 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
}
split(mac1, mac2, "(") #)
macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
if (D_is_set[macro]) {
# Preserve the white space surrounding the "#".
- prefix = substr(line, 1, index(line, defundef) - 1)
print prefix "define", macro P[macro] D[macro]
next
} else {
@@ -14759,7 +12595,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# in the case of _POSIX_SOURCE, which is predefined and required
# on some systems where configure will not decide to define it.
if (defundef == "undef") {
- print "/*", line, "*/"
+ print "/*", prefix defundef, macro, "*/"
next
}
}
@@ -14768,9 +12604,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
- { { $as_echo "$as_me:$LINENO: error: could not setup config headers machinery" >&5
-$as_echo "$as_me: error: could not setup config headers machinery" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
fi # test -n "$CONFIG_HEADERS"
@@ -14783,9 +12617,7 @@ do
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
- :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
-$as_echo "$as_me: error: Invalid tag $ac_tag." >&2;}
- { (exit 1); exit 1; }; };;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
@@ -14813,12 +12645,10 @@ $as_echo "$as_me: error: Invalid tag $ac_tag." >&2;}
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
- { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
-$as_echo "$as_me: error: cannot find input file: $ac_f" >&2;}
- { (exit 1); exit 1; }; };;
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
esac
case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
- ac_file_inputs="$ac_file_inputs '$ac_f'"
+ as_fn_append ac_file_inputs " '$ac_f'"
done
# Let's still pretend it is `configure' which instantiates (i.e., don't
@@ -14829,7 +12659,7 @@ $as_echo "$as_me: error: cannot find input file: $ac_f" >&2;}
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:$LINENO: creating $ac_file" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
$as_echo "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
@@ -14842,9 +12672,7 @@ $as_echo "$as_me: creating $ac_file" >&6;}
case $ac_tag in
*:-:* | *:-) cat >"$tmp/stdin" \
- || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
-$as_echo "$as_me: error: could not create $ac_file" >&2;}
- { (exit 1); exit 1; }; } ;;
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
@@ -14872,47 +12700,7 @@ $as_echo X"$ac_file" |
q
}
s/.*/./; q'`
- { as_dir="$ac_dir"
- case $as_dir in #(
- -*) as_dir=./$as_dir;;
- esac
- test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
- as_dirs=
- while :; do
- case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
- *) as_qdir=$as_dir;;
- esac
- as_dirs="'$as_qdir' $as_dirs"
- as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- test -d "$as_dir" && break
- done
- test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
-$as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
- { (exit 1); exit 1; }; }; }
+ as_dir="$ac_dir"; as_fn_mkdir_p
ac_builddir=.
case "$ac_dir" in
@@ -14964,7 +12752,6 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# If the template does not know about datarootdir, expand it.
# FIXME: This hack should be removed a few years after 2.60.
ac_datarootdir_hack=; ac_datarootdir_seen=
-
ac_sed_dataroot='
/datarootdir/ {
p
@@ -14974,12 +12761,11 @@ ac_sed_dataroot='
/@docdir@/p
/@infodir@/p
/@localedir@/p
-/@mandir@/p
-'
+/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
@@ -14989,7 +12775,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
s&@infodir@&$infodir&g
s&@localedir@&$localedir&g
s&@mandir@&$mandir&g
- s&\\\${datarootdir}&$datarootdir&g' ;;
+ s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF
@@ -15017,26 +12803,22 @@ s&@INSTALL@&$ac_INSTALL&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
- || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
-$as_echo "$as_me: error: could not create $ac_file" >&2;}
- { (exit 1); exit 1; }; }
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&2;}
+which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$tmp/stdin"
case $ac_file in
-) cat "$tmp/out" && rm -f "$tmp/out";;
*) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
esac \
- || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
-$as_echo "$as_me: error: could not create $ac_file" >&2;}
- { (exit 1); exit 1; }; }
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;
:H)
#
@@ -15047,29 +12829,23 @@ $as_echo "$as_me: error: could not create $ac_file" >&2;}
$as_echo "/* $configure_input */" \
&& eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
} >"$tmp/config.h" \
- || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
-$as_echo "$as_me: error: could not create $ac_file" >&2;}
- { (exit 1); exit 1; }; }
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
- { $as_echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
$as_echo "$as_me: $ac_file is unchanged" >&6;}
else
rm -f "$ac_file"
mv "$tmp/config.h" "$ac_file" \
- || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
-$as_echo "$as_me: error: could not create $ac_file" >&2;}
- { (exit 1); exit 1; }; }
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
fi
else
$as_echo "/* $configure_input */" \
&& eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
- || { { $as_echo "$as_me:$LINENO: error: could not create -" >&5
-$as_echo "$as_me: error: could not create -" >&2;}
- { (exit 1); exit 1; }; }
+ || as_fn_error $? "could not create -" "$LINENO" 5
fi
;;
- :C) { $as_echo "$as_me:$LINENO: executing $ac_file commands" >&5
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
$as_echo "$as_me: executing $ac_file commands" >&6;}
;;
esac
@@ -15716,15 +13492,12 @@ _LT_EOF
done # for ac_tag
-{ (exit 0); exit 0; }
+as_fn_exit 0
_ACEOF
-chmod +x $CONFIG_STATUS
ac_clean_files=$ac_clean_files_save
test $ac_write_fail = 0 ||
- { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;}
- { (exit 1); exit 1; }; }
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
# configure is writing to config.log, and then calls config.status.
@@ -15745,10 +13518,10 @@ if test "$no_create" != yes; then
exec 5>>config.log
# Use ||, not &&, to avoid exiting from the if with $? = 1, which
# would make configure fail if this is the last instruction.
- $ac_cs_success || { (exit 1); exit 1; }
+ $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:$LINENO: WARNING: Unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: Unrecognized options: $ac_unrecognized_opts" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
diff --git a/doc/lemon.html b/doc/lemon.html
index 6a4d6dbd..2c655559 100644
--- a/doc/lemon.html
+++ b/doc/lemon.html
@@ -282,7 +282,7 @@ tokens) and it honors the same commenting conventions as C and C++.
A terminal symbol (token) is any string of alphanumeric
and underscore characters
that begins with an upper case letter.
-A terminal can contain lower class letters after the first character,
+A terminal can contain lowercase letters after the first character,
but the usual convention is to make terminals all upper case.
A nonterminal, on the other hand, is any string of alphanumeric
and underscore characters than begins with a lower case letter.
diff --git a/ext/fts3/README.content b/ext/fts3/README.content
new file mode 100644
index 00000000..ab986754
--- /dev/null
+++ b/ext/fts3/README.content
@@ -0,0 +1,178 @@
+
+FTS4 CONTENT OPTION
+
+ Normally, in order to create a full-text index on a dataset, the FTS4
+ module stores a copy of all indexed documents in a specially created
+ database table.
+
+ As of SQLite version 3.7.9, FTS4 supports a new option - "content" -
+ designed to extend FTS4 to support the creation of full-text indexes where:
+
+ * The indexed documents are not stored within the SQLite database
+ at all (a "contentless" FTS4 table), or
+
+ * The indexed documents are stored in a database table created and
+ managed by the user (an "external content" FTS4 table).
+
+ Because the indexed documents themselves are usually much larger than
+ the full-text index, the content option can sometimes be used to achieve
+ significant space savings.
+
+CONTENTLESS FTS4 TABLES
+
+ In order to create an FTS4 table that does not store a copy of the indexed
+ documents at all, the content option should be set to an empty string.
+ For example, the following SQL creates such an FTS4 table with three
+ columns - "a", "b", and "c":
+
+ CREATE VIRTUAL TABLE t1 USING fts4(content="", a, b, c);
+
+ Data can be inserted into such an FTS4 table using an INSERT statements.
+ However, unlike ordinary FTS4 tables, the user must supply an explicit
+ integer docid value. For example:
+
+ -- This statement is Ok:
+ INSERT INTO t1(docid, a, b, c) VALUES(1, 'a b c', 'd e f', 'g h i');
+
+ -- This statement causes an error, as no docid value has been provided:
+ INSERT INTO t1(a, b, c) VALUES('j k l', 'm n o', 'p q r');
+
+ It is not possible to UPDATE or DELETE a row stored in a contentless FTS4
+ table. Attempting to do so is an error.
+
+ Contentless FTS4 tables also support SELECT statements. However, it is
+ an error to attempt to retrieve the value of any table column other than
+ the docid column. The auxiliary function matchinfo() may be used, but
+ snippet() and offsets() may not. For example:
+
+ -- The following statements are Ok:
+ SELECT docid FROM t1 WHERE t1 MATCH 'xxx';
+ SELECT docid FROM t1 WHERE a MATCH 'xxx';
+ SELECT matchinfo(t1) FROM t1 WHERE t1 MATCH 'xxx';
+
+ -- The following statements all cause errors, as the value of columns
+ -- other than docid are required to evaluate them.
+ SELECT * FROM t1;
+ SELECT a, b FROM t1 WHERE t1 MATCH 'xxx';
+ SELECT docid FROM t1 WHERE a LIKE 'xxx%';
+ SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'xxx';
+
+ Errors related to attempting to retrieve column values other than docid
+ are runtime errors that occur within sqlite3_step(). In some cases, for
+ example if the MATCH expression in a SELECT query matches zero rows, there
+ may be no error at all even if a statement does refer to column values
+ other than docid.
+
+EXTERNAL CONTENT FTS4 TABLES
+
+ An "external content" FTS4 table is similar to a contentless table, except
+ that if evaluation of a query requires the value of a column other than
+ docid, FTS4 attempts to retrieve that value from a table (or view, or
+ virtual table) nominated by the user (hereafter referred to as the "content
+ table"). The FTS4 module never writes to the content table, and writing
+ to the content table does not affect the full-text index. It is the
+ responsibility of the user to ensure that the content table and the
+ full-text index are consistent.
+
+ An external content FTS4 table is created by setting the content option
+ to the name of a table (or view, or virtual table) that may be queried by
+ FTS4 to retrieve column values when required. If the nominated table does
+ not exist, then an external content table behaves in the same way as
+ a contentless table. For example:
+
+ CREATE TABLE t2(id INTEGER PRIMARY KEY, a, b, c);
+ CREATE VIRTUAL TABLE t3 USING fts4(content="t2", a, c);
+
+ Assuming the nominated table does exist, then its columns must be the same
+ as or a superset of those defined for the FTS table.
+
+ When a users query on the FTS table requires a column value other than
+ docid, FTS attempts to read this value from the corresponding column of
+ the row in the content table with a rowid value equal to the current FTS
+ docid. Or, if such a row cannot be found in the content table, a NULL
+ value is used instead. For example:
+
+ CREATE TABLE t2(id INTEGER PRIMARY KEY, a, b, c, d);
+ CREATE VIRTUAL TABLE t3 USING fts4(content="t2", b, c);
+
+ INSERT INTO t2 VALUES(2, 'a b', 'c d', 'e f');
+ INSERT INTO t2 VALUES(3, 'g h', 'i j', 'k l');
+ INSERT INTO t3(docid, b, c) SELECT id, b, c FROM t2;
+
+ -- The following query returns a single row with two columns containing
+ -- the text values "i j" and "k l".
+ --
+ -- The query uses the full-text index to discover that the MATCH
+ -- term matches the row with docid=3. It then retrieves the values
+ -- of columns b and c from the row with rowid=3 in the content table
+ -- to return.
+ --
+ SELECT * FROM t3 WHERE t3 MATCH 'k';
+
+ -- Following the UPDATE, the query still returns a single row, this
+ -- time containing the text values "xxx" and "yyy". This is because the
+ -- full-text index still indicates that the row with docid=3 matches
+ -- the FTS4 query 'k', even though the documents stored in the content
+ -- table have been modified.
+ --
+ UPDATE t2 SET b = 'xxx', c = 'yyy' WHERE rowid = 3;
+ SELECT * FROM t3 WHERE t3 MATCH 'k';
+
+ -- Following the DELETE below, the query returns one row containing two
+ -- NULL values. NULL values are returned because FTS is unable to find
+ -- a row with rowid=3 within the content table.
+ --
+ DELETE FROM t2;
+ SELECT * FROM t3 WHERE t3 MATCH 'k';
+
+ When a row is deleted from an external content FTS4 table, FTS4 needs to
+ retrieve the column values of the row being deleted from the content table.
+ This is so that FTS4 can update the full-text index entries for each token
+ that occurs within the deleted row to indicate that that row has been
+ deleted. If the content table row cannot be found, or if it contains values
+ inconsistent with the contents of the FTS index, the results can be difficult
+ to predict. The FTS index may be left containing entries corresponding to the
+ deleted row, which can lead to seemingly nonsensical results being returned
+ by subsequent SELECT queries. The same applies when a row is updated, as
+ internally an UPDATE is the same as a DELETE followed by an INSERT.
+
+ Instead of writing separately to the full-text index and the content table,
+ some users may wish to use database triggers to keep the full-text index
+ up to date with respect to the set of documents stored in the content table.
+ For example, using the tables from earlier examples:
+
+ CREATE TRIGGER t2_bu BEFORE UPDATE ON t2 BEGIN
+ DELETE FROM t3 WHERE docid=old.rowid;
+ END;
+ CREATE TRIGGER t2_bd BEFORE DELETE ON t2 BEGIN
+ DELETE FROM t3 WHERE docid=old.rowid;
+ END;
+
+ CREATE TRIGGER t2_bu AFTER UPDATE ON t2 BEGIN
+ INSERT INTO t3(docid, b, c) VALUES(new.rowid, new.b, new.c);
+ END;
+ CREATE TRIGGER t2_bd AFTER INSERT ON t2 BEGIN
+ INSERT INTO t3(docid, b, c) VALUES(new.rowid, new.b, new.c);
+ END;
+
+ The DELETE trigger must be fired before the actual delete takes place
+ on the content table. This is so that FTS4 can still retrieve the original
+ values in order to update the full-text index. And the INSERT trigger must
+ be fired after the new row is inserted, so as to handle the case where the
+ rowid is assigned automatically within the system. The UPDATE trigger must
+ be split into two parts, one fired before and one after the update of the
+ content table, for the same reasons.
+
+ FTS4 features a special command similar to the 'optimize' command that
+ deletes the entire full-text index and rebuilds it based on the current
+ set of documents in the content table. Assuming again that "t3" is the
+ name of the external content FTS4 table, the command is:
+
+ INSERT INTO t3(t3) VALUES('rebuild');
+
+ This command may also be used with ordinary FTS4 tables, although it may
+ only be useful if the full-text index has somehow become corrupt. It is an
+ error to attempt to rebuild the full-text index maintained by a contentless
+ FTS4 table.
+
+
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
index 67a0ea20..12013f2b 100644
--- a/ext/fts3/fts3.c
+++ b/ext/fts3/fts3.c
@@ -312,6 +312,11 @@
SQLITE_EXTENSION_INIT1
#endif
+static int fts3EvalNext(Fts3Cursor *pCsr);
+static int fts3EvalStart(Fts3Cursor *pCsr);
+static int fts3TermSegReaderCursor(
+ Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
+
/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
@@ -433,7 +438,7 @@ static void fts3GetReverseVarint(
sqlite3_int64 *pVal
){
sqlite3_int64 iVal;
- char *p = *pp;
+ char *p;
/* Pointer p now points at the first byte past the varint we are
** interested in. So, unless the doclist is corrupt, the 0x80 bit is
@@ -463,6 +468,7 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
sqlite3_free(p->zSegmentsTbl);
sqlite3_free(p->zReadExprlist);
sqlite3_free(p->zWriteExprlist);
+ sqlite3_free(p->zContentTbl);
/* Invoke the tokenizer destructor to free the tokenizer. */
p->pTokenizer->pModule->xDestroy(p->pTokenizer);
@@ -502,16 +508,19 @@ static void fts3DbExec(
** The xDestroy() virtual table method.
*/
static int fts3DestroyMethod(sqlite3_vtab *pVtab){
- int rc = SQLITE_OK; /* Return code */
Fts3Table *p = (Fts3Table *)pVtab;
- sqlite3 *db = p->db;
+ int rc = SQLITE_OK; /* Return code */
+ const char *zDb = p->zDb; /* Name of database (e.g. "main", "temp") */
+ sqlite3 *db = p->db; /* Database handle */
/* Drop the shadow tables */
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", p->zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", p->zDb,p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", p->zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", p->zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", p->zDb, p->zName);
+ if( p->zContentTbl==0 ){
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
+ }
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
/* If everything has worked, invoke fts3DisconnectMethod() to free the
** memory associated with the Fts3Table structure and return SQLITE_OK.
@@ -573,23 +582,27 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){
static int fts3CreateTables(Fts3Table *p){
int rc = SQLITE_OK; /* Return code */
int i; /* Iterator variable */
- char *zContentCols; /* Columns of %_content table */
sqlite3 *db = p->db; /* The database connection */
- /* Create a list of user columns for the content table */
- zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
- for(i=0; zContentCols && inColumn; i++){
- char *z = p->azColumn[i];
- zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
- }
- if( zContentCols==0 ) rc = SQLITE_NOMEM;
+ if( p->zContentTbl==0 ){
+ char *zContentCols; /* Columns of %_content table */
+
+ /* Create a list of user columns for the content table */
+ zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
+ for(i=0; zContentCols && inColumn; i++){
+ char *z = p->azColumn[i];
+ zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
+ }
+ if( zContentCols==0 ) rc = SQLITE_NOMEM;
+
+ /* Create the content table */
+ fts3DbExec(&rc, db,
+ "CREATE TABLE %Q.'%q_content'(%s)",
+ p->zDb, p->zName, zContentCols
+ );
+ sqlite3_free(zContentCols);
+ }
- /* Create the content table */
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_content'(%s)",
- p->zDb, p->zName, zContentCols
- );
- sqlite3_free(zContentCols);
/* Create other tables */
fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);",
@@ -740,8 +753,8 @@ static char *fts3QuoteId(char const *zInput){
}
/*
-** Return a list of comma separated SQL expressions that could be used
-** in a SELECT statement such as the following:
+** Return a list of comma separated SQL expressions and a FROM clause that
+** could be used in a SELECT statement such as the following:
**
** SELECT FROM %_content AS x ...
**
@@ -752,7 +765,7 @@ static char *fts3QuoteId(char const *zInput){
** table has the three user-defined columns "a", "b", and "c", the following
** string is returned:
**
-** "docid, unzip(x.'a'), unzip(x.'b'), unzip(x.'c')"
+** "docid, unzip(x.'a'), unzip(x.'b'), unzip(x.'c') FROM %_content AS x"
**
** The pointer returned points to a buffer allocated by sqlite3_malloc(). It
** is the responsibility of the caller to eventually free it.
@@ -768,16 +781,28 @@ static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){
char *zFunction;
int i;
- if( !zFunc ){
- zFunction = "";
+ if( p->zContentTbl==0 ){
+ if( !zFunc ){
+ zFunction = "";
+ }else{
+ zFree = zFunction = fts3QuoteId(zFunc);
+ }
+ fts3Appendf(pRc, &zRet, "docid");
+ for(i=0; inColumn; i++){
+ fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]);
+ }
+ sqlite3_free(zFree);
}else{
- zFree = zFunction = fts3QuoteId(zFunc);
+ fts3Appendf(pRc, &zRet, "rowid");
+ for(i=0; inColumn; i++){
+ fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]);
+ }
}
- fts3Appendf(pRc, &zRet, "docid");
- for(i=0; inColumn; i++){
- fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]);
- }
- sqlite3_free(zFree);
+ fts3Appendf(pRc, &zRet, "FROM '%q'.'%q%s' AS x",
+ p->zDb,
+ (p->zContentTbl ? p->zContentTbl : p->zName),
+ (p->zContentTbl ? "" : "_content")
+ );
return zRet;
}
@@ -820,9 +845,23 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
return zRet;
}
+/*
+** This function interprets the string at (*pp) as a non-negative integer
+** value. It reads the integer and sets *pnOut to the value read, then
+** sets *pp to point to the byte immediately following the last byte of
+** the integer value.
+**
+** Only decimal digits ('0'..'9') may be part of an integer value.
+**
+** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
+** the output value undefined. Otherwise SQLITE_OK is returned.
+**
+** This function is used when parsing the "prefix=" FTS4 parameter.
+*/
static int fts3GobbleInt(const char **pp, int *pnOut){
- const char *p = *pp;
- int nInt = 0;
+ const char *p; /* Iterator pointer */
+ int nInt = 0; /* Output value */
+
for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
nInt = nInt * 10 + (p[0] - '0');
}
@@ -832,15 +871,30 @@ static int fts3GobbleInt(const char **pp, int *pnOut){
return SQLITE_OK;
}
-
+/*
+** This function is called to allocate an array of Fts3Index structures
+** representing the indexes maintained by the current FTS table. FTS tables
+** always maintain the main "terms" index, but may also maintain one or
+** more "prefix" indexes, depending on the value of the "prefix=" parameter
+** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
+**
+** Argument zParam is passed the value of the "prefix=" option if one was
+** specified, or NULL otherwise.
+**
+** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
+** the allocated array. *pnIndex is set to the number of elements in the
+** array. If an error does occur, an SQLite error code is returned.
+**
+** Regardless of whether or not an error is returned, it is the responsibility
+** of the caller to call sqlite3_free() on the output array to free it.
+*/
static int fts3PrefixParameter(
const char *zParam, /* ABC in prefix=ABC parameter to parse */
int *pnIndex, /* OUT: size of *apIndex[] array */
- struct Fts3Index **apIndex, /* OUT: Array of indexes for this table */
- struct Fts3Index **apFree /* OUT: Free this with sqlite3_free() */
+ struct Fts3Index **apIndex /* OUT: Array of indexes for this table */
){
- struct Fts3Index *aIndex;
- int nIndex = 1;
+ struct Fts3Index *aIndex; /* Allocated array */
+ int nIndex = 1; /* Number of entries in array */
if( zParam && zParam[0] ){
const char *p;
@@ -851,7 +905,7 @@ static int fts3PrefixParameter(
}
aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
- *apIndex = *apFree = aIndex;
+ *apIndex = aIndex;
*pnIndex = nIndex;
if( !aIndex ){
return SQLITE_NOMEM;
@@ -872,6 +926,91 @@ static int fts3PrefixParameter(
return SQLITE_OK;
}
+/*
+** This function is called when initializing an FTS4 table that uses the
+** content=xxx option. It determines the number of and names of the columns
+** of the new FTS4 table.
+**
+** The third argument passed to this function is the value passed to the
+** config=xxx option (i.e. "xxx"). This function queries the database for
+** a table of that name. If found, the output variables are populated
+** as follows:
+**
+** *pnCol: Set to the number of columns table xxx has,
+**
+** *pnStr: Set to the total amount of space required to store a copy
+** of each columns name, including the nul-terminator.
+**
+** *pazCol: Set to point to an array of *pnCol strings. Each string is
+** the name of the corresponding column in table xxx. The array
+** and its contents are allocated using a single allocation. It
+** is the responsibility of the caller to free this allocation
+** by eventually passing the *pazCol value to sqlite3_free().
+**
+** If the table cannot be found, an error code is returned and the output
+** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is
+** returned (and the output variables are undefined).
+*/
+static int fts3ContentColumns(
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */
+ const char *zTbl, /* Name of content table */
+ const char ***pazCol, /* OUT: Malloc'd array of column names */
+ int *pnCol, /* OUT: Size of array *pazCol */
+ int *pnStr /* OUT: Bytes of string content */
+){
+ int rc = SQLITE_OK; /* Return code */
+ char *zSql; /* "SELECT *" statement on zTbl */
+ sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */
+
+ zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl);
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ }
+ sqlite3_free(zSql);
+
+ if( rc==SQLITE_OK ){
+ const char **azCol; /* Output array */
+ int nStr = 0; /* Size of all column names (incl. 0x00) */
+ int nCol; /* Number of table columns */
+ int i; /* Used to iterate through columns */
+
+ /* Loop through the returned columns. Set nStr to the number of bytes of
+ ** space required to store a copy of each column name, including the
+ ** nul-terminator byte. */
+ nCol = sqlite3_column_count(pStmt);
+ for(i=0; i MATCHINFO */
- { "prefix", 6, 0 }, /* 1 -> PREFIX */
- { "compress", 8, 0 }, /* 2 -> COMPRESS */
- { "uncompress", 10, 0 }, /* 3 -> UNCOMPRESS */
- { "order", 5, 0 } /* 4 -> ORDER */
+ { "matchinfo", 9 }, /* 0 -> MATCHINFO */
+ { "prefix", 6 }, /* 1 -> PREFIX */
+ { "compress", 8 }, /* 2 -> COMPRESS */
+ { "uncompress", 10 }, /* 3 -> UNCOMPRESS */
+ { "order", 5 }, /* 4 -> ORDER */
+ { "content", 7 } /* 5 -> CONTENT */
};
int iOpt;
@@ -1012,13 +1151,20 @@ static int fts3InitVtab(
case 4: /* ORDER */
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
- && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 3))
+ && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
){
*pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
rc = SQLITE_ERROR;
}
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
break;
+
+ default: /* CONTENT */
+ assert( iOpt==5 );
+ sqlite3_free(zUncompress);
+ zContent = zVal;
+ zVal = 0;
+ break;
}
}
sqlite3_free(zVal);
@@ -1031,6 +1177,26 @@ static int fts3InitVtab(
aCol[nCol++] = z;
}
}
+
+ /* If a content=xxx option was specified, the following:
+ **
+ ** 1. Ignore any compress= and uncompress= options.
+ **
+ ** 2. If no column names were specified as part of the CREATE VIRTUAL
+ ** TABLE statement, use all columns from the content table.
+ */
+ if( rc==SQLITE_OK && zContent ){
+ sqlite3_free(zCompress);
+ sqlite3_free(zUncompress);
+ zCompress = 0;
+ zUncompress = 0;
+ if( nCol==0 ){
+ sqlite3_free((void*)aCol);
+ aCol = 0;
+ rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
+ }
+ assert( rc!=SQLITE_OK || nCol>0 );
+ }
if( rc!=SQLITE_OK ) goto fts3_init_out;
if( nCol==0 ){
@@ -1046,7 +1212,7 @@ static int fts3InitVtab(
}
assert( pTokenizer );
- rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex, &aFree);
+ rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
if( rc==SQLITE_ERROR ){
assert( zPrefix );
*pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
@@ -1075,6 +1241,8 @@ static int fts3InitVtab(
p->bHasDocsize = (isFts4 && bNoDocsize==0);
p->bHasStat = isFts4;
p->bDescIdx = bDescIdx;
+ p->zContentTbl = zContent;
+ zContent = 0;
TESTONLY( p->inTransaction = -1 );
TESTONLY( p->mxSavepoint = -1 );
@@ -1133,9 +1301,10 @@ static int fts3InitVtab(
fts3_init_out:
sqlite3_free(zPrefix);
- sqlite3_free(aFree);
+ sqlite3_free(aIndex);
sqlite3_free(zCompress);
sqlite3_free(zUncompress);
+ sqlite3_free(zContent);
sqlite3_free((void *)aCol);
if( rc!=SQLITE_OK ){
if( p ){
@@ -1287,35 +1456,64 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
return SQLITE_OK;
}
+/*
+** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then
+** compose and prepare an SQL statement of the form:
+**
+** "SELECT FROM %_content WHERE rowid = ?"
+**
+** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
+** it. If an error occurs, return an SQLite error code.
+**
+** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK.
+*/
+static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
+ int rc = SQLITE_OK;
+ if( pCsr->pStmt==0 ){
+ Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
+ char *zSql;
+ zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
+ if( !zSql ) return SQLITE_NOMEM;
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
+ sqlite3_free(zSql);
+ }
+ *ppStmt = pCsr->pStmt;
+ return rc;
+}
+
/*
** Position the pCsr->pStmt statement so that it is on the row
** of the %_content table that contains the last match. Return
** SQLITE_OK on success.
*/
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
+ int rc = SQLITE_OK;
if( pCsr->isRequireSeek ){
- sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
- pCsr->isRequireSeek = 0;
- if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
- return SQLITE_OK;
- }else{
- int rc = sqlite3_reset(pCsr->pStmt);
- if( rc==SQLITE_OK ){
- /* If no row was found and no error has occured, then the %_content
- ** table is missing a row that is present in the full-text index.
- ** The data structures are corrupt.
- */
- rc = SQLITE_CORRUPT_VTAB;
+ sqlite3_stmt *pStmt = 0;
+
+ rc = fts3CursorSeekStmt(pCsr, &pStmt);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
+ pCsr->isRequireSeek = 0;
+ if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
+ return SQLITE_OK;
+ }else{
+ rc = sqlite3_reset(pCsr->pStmt);
+ if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
+ /* If no row was found and no error has occured, then the %_content
+ ** table is missing a row that is present in the full-text index.
+ ** The data structures are corrupt. */
+ rc = FTS_CORRUPT_VTAB;
+ pCsr->isEof = 1;
+ }
}
- pCsr->isEof = 1;
- if( pContext ){
- sqlite3_result_error_code(pContext, rc);
- }
- return rc;
}
- }else{
- return SQLITE_OK;
}
+
+ if( rc!=SQLITE_OK && pContext ){
+ sqlite3_result_error_code(pContext, rc);
+ }
+ return rc;
}
/*
@@ -1365,7 +1563,7 @@ static int fts3ScanInteriorNode(
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
if( zCsr>zEnd ){
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
while( zCsrzEnd ){
- rc = SQLITE_CORRUPT_VTAB;
+ rc = FTS_CORRUPT_VTAB;
goto finish_scan;
}
if( nPrefix+nSuffix>nAlloc ){
@@ -1396,6 +1594,7 @@ static int fts3ScanInteriorNode(
}
zBuffer = zNew;
}
+ assert( zBuffer );
memcpy(&zBuffer[nPrefix], zCsr, nSuffix);
nBuffer = nPrefix + nSuffix;
zCsr += nSuffix;
@@ -1724,8 +1923,6 @@ static void fts3PoslistMerge(
}
/*
-** nToken==1 searches for adjacent positions.
-**
** This function is used to merge two position lists into one. When it is
** called, *pp1 and *pp2 must both point to position lists. A position-list is
** the part of a doclist that follows each document id. For example, if a row
@@ -1745,6 +1942,8 @@ static void fts3PoslistMerge(
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
** when the *pp1 token appears before the *pp2 token, but not more than nToken
** slots before it.
+**
+** e.g. nToken==1 searches for adjacent positions.
*/
static int fts3PoslistPhraseMerge(
char **pp, /* IN/OUT: Preallocated output buffer */
@@ -1754,7 +1953,7 @@ static int fts3PoslistPhraseMerge(
char **pp1, /* IN/OUT: Left input list */
char **pp2 /* IN/OUT: Right input list */
){
- char *p = (pp ? *pp : 0);
+ char *p = *pp;
char *p1 = *pp1;
char *p2 = *pp2;
int iCol1 = 0;
@@ -1763,7 +1962,7 @@ static int fts3PoslistPhraseMerge(
/* Never set both isSaveLeft and isExact for the same invocation. */
assert( isSaveLeft==0 || isExact==0 );
- assert( *p1!=0 && *p2!=0 );
+ assert( p!=0 && *p1!=0 && *p2!=0 );
if( *p1==POS_COLUMN ){
p1++;
p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
@@ -1780,7 +1979,7 @@ static int fts3PoslistPhraseMerge(
sqlite3_int64 iPos1 = 0;
sqlite3_int64 iPos2 = 0;
- if( pp && iCol1 ){
+ if( iCol1 ){
*p++ = POS_COLUMN;
p += sqlite3Fts3PutVarint(p, iCol1);
}
@@ -1795,16 +1994,10 @@ static int fts3PoslistPhraseMerge(
|| (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken)
){
sqlite3_int64 iSave;
- if( !pp ){
- fts3PoslistCopy(0, &p2);
- fts3PoslistCopy(0, &p1);
- *pp1 = p1;
- *pp2 = p2;
- return 1;
- }
iSave = isSaveLeft ? iPos1 : iPos2;
fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2;
pSave = 0;
+ assert( p );
}
if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){
if( (*p2&0xFE)==0 ) break;
@@ -1853,7 +2046,7 @@ static int fts3PoslistPhraseMerge(
fts3PoslistCopy(0, &p1);
*pp1 = p1;
*pp2 = p2;
- if( !pp || *pp==p ){
+ if( *pp==p ){
return 0;
}
*p++ = 0x00;
@@ -1911,22 +2104,34 @@ static int fts3PoslistNearMerge(
}
/*
-** A pointer to an instance of this structure is used as the context
-** argument to sqlite3Fts3SegReaderIterate()
+** An instance of this function is used to merge together the (potentially
+** large number of) doclists for each term that matches a prefix query.
+** See function fts3TermSelectMerge() for details.
*/
typedef struct TermSelect TermSelect;
struct TermSelect {
- int isReqPos;
- char *aaOutput[16]; /* Malloc'd output buffer */
- int anOutput[16]; /* Size of output in bytes */
+ char *aaOutput[16]; /* Malloc'd output buffers */
+ int anOutput[16]; /* Size each output buffer in bytes */
};
-
+/*
+** This function is used to read a single varint from a buffer. Parameter
+** pEnd points 1 byte past the end of the buffer. When this function is
+** called, if *pp points to pEnd or greater, then the end of the buffer
+** has been reached. In this case *pp is set to 0 and the function returns.
+**
+** If *pp does not point to or past pEnd, then a single varint is read
+** from *pp. *pp is then set to point 1 byte past the end of the read varint.
+**
+** If bDescIdx is false, the value read is added to *pVal before returning.
+** If it is true, the value read is subtracted from *pVal before this
+** function returns.
+*/
static void fts3GetDeltaVarint3(
- char **pp,
- char *pEnd,
- int bDescIdx,
- sqlite3_int64 *pVal
+ char **pp, /* IN/OUT: Point to read varint from */
+ char *pEnd, /* End of buffer */
+ int bDescIdx, /* True if docids are descending */
+ sqlite3_int64 *pVal /* IN/OUT: Integer value */
){
if( *pp>=pEnd ){
*pp = 0;
@@ -1941,6 +2146,21 @@ static void fts3GetDeltaVarint3(
}
}
+/*
+** This function is used to write a single varint to a buffer. The varint
+** is written to *pp. Before returning, *pp is set to point 1 byte past the
+** end of the value written.
+**
+** If *pbFirst is zero when this function is called, the value written to
+** the buffer is that of parameter iVal.
+**
+** If *pbFirst is non-zero when this function is called, then the value
+** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
+** (if bDescIdx is non-zero).
+**
+** Before returning, this function always sets *pbFirst to 1 and *piPrev
+** to the value of parameter iVal.
+*/
static void fts3PutDeltaVarint3(
char **pp, /* IN/OUT: Output pointer */
int bDescIdx, /* True for descending docids */
@@ -1961,10 +2181,34 @@ static void fts3PutDeltaVarint3(
*pbFirst = 1;
}
-#define COMPARE_DOCID(i1, i2) ((bDescIdx?-1:1) * (i1-i2))
+/*
+** This macro is used by various functions that merge doclists. The two
+** arguments are 64-bit docid values. If the value of the stack variable
+** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
+** Otherwise, (i2-i1).
+**
+** Using this makes it easier to write code that can merge doclists that are
+** sorted in either ascending or descending order.
+*/
+#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
+
+/*
+** This function does an "OR" merge of two doclists (output contains all
+** positions contained in either argument doclist). If the docids in the
+** input doclists are sorted in ascending order, parameter bDescDoclist
+** should be false. If they are sorted in ascending order, it should be
+** passed a non-zero value.
+**
+** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
+** containing the output doclist and SQLITE_OK is returned. In this case
+** *pnOut is set to the number of bytes in the output doclist.
+**
+** If an error occurs, an SQLite error code is returned. The output values
+** are undefined in this case.
+*/
static int fts3DoclistOrMerge(
- int bDescIdx, /* True if arguments are desc */
+ int bDescDoclist, /* True if arguments are desc */
char *a1, int n1, /* First doclist */
char *a2, int n2, /* Second doclist */
char **paOut, int *pnOut /* OUT: Malloc'd doclist */
@@ -1982,38 +2226,81 @@ static int fts3DoclistOrMerge(
*paOut = 0;
*pnOut = 0;
- aOut = sqlite3_malloc(n1+n2);
+
+ /* Allocate space for the output. Both the input and output doclists
+ ** are delta encoded. If they are in ascending order (bDescDoclist==0),
+ ** then the first docid in each list is simply encoded as a varint. For
+ ** each subsequent docid, the varint stored is the difference between the
+ ** current and previous docid (a positive number - since the list is in
+ ** ascending order).
+ **
+ ** The first docid written to the output is therefore encoded using the
+ ** same number of bytes as it is in whichever of the input lists it is
+ ** read from. And each subsequent docid read from the same input list
+ ** consumes either the same or less bytes as it did in the input (since
+ ** the difference between it and the previous value in the output must
+ ** be a positive value less than or equal to the delta value read from
+ ** the input list). The same argument applies to all but the first docid
+ ** read from the 'other' list. And to the contents of all position lists
+ ** that will be copied and merged from the input to the output.
+ **
+ ** However, if the first docid copied to the output is a negative number,
+ ** then the encoding of the first docid from the 'other' input list may
+ ** be larger in the output than it was in the input (since the delta value
+ ** may be a larger positive integer than the actual docid).
+ **
+ ** The space required to store the output is therefore the sum of the
+ ** sizes of the two inputs, plus enough space for exactly one of the input
+ ** docids to grow.
+ **
+ ** A symetric argument may be made if the doclists are in descending
+ ** order.
+ */
+ aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
if( !aOut ) return SQLITE_NOMEM;
p = aOut;
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
while( p1 || p2 ){
- sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
+ sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
if( p2 && p1 && iDiff==0 ){
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
fts3PoslistMerge(&p, &p1, &p2);
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}else if( !p2 || (p1 && iDiff<0) ){
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
fts3PoslistCopy(&p, &p1);
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
}else{
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i2);
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
fts3PoslistCopy(&p, &p2);
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}
}
*paOut = aOut;
*pnOut = (p-aOut);
+ assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
return SQLITE_OK;
}
+/*
+** This function does a "phrase" merge of two doclists. In a phrase merge,
+** the output contains a copy of each position from the right-hand input
+** doclist for which there is a position in the left-hand input doclist
+** exactly nDist tokens before it.
+**
+** If the docids in the input doclists are sorted in ascending order,
+** parameter bDescDoclist should be false. If they are sorted in ascending
+** order, it should be passed a non-zero value.
+**
+** The right-hand input doclist is overwritten by this function.
+*/
static void fts3DoclistPhraseMerge(
- int bDescIdx, /* True if arguments are desc */
+ int bDescDoclist, /* True if arguments are desc */
int nDist, /* Distance from left to right (1=adjacent) */
char *aLeft, int nLeft, /* Left doclist */
char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
@@ -2036,32 +2323,82 @@ static void fts3DoclistPhraseMerge(
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
while( p1 && p2 ){
- sqlite3_int64 iDiff = COMPARE_DOCID(i1, i2);
+ sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
if( iDiff==0 ){
char *pSave = p;
sqlite3_int64 iPrevSave = iPrev;
int bFirstOutSave = bFirstOut;
- fts3PutDeltaVarint3(&p, bDescIdx, &iPrev, &bFirstOut, i1);
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
p = pSave;
iPrev = iPrevSave;
bFirstOut = bFirstOutSave;
}
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}else if( iDiff<0 ){
fts3PoslistCopy(0, &p1);
- fts3GetDeltaVarint3(&p1, pEnd1, bDescIdx, &i1);
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
}else{
fts3PoslistCopy(0, &p2);
- fts3GetDeltaVarint3(&p2, pEnd2, bDescIdx, &i2);
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}
}
*pnRight = p - aOut;
}
+/*
+** Argument pList points to a position list nList bytes in size. This
+** function checks to see if the position list contains any entries for
+** a token in position 0 (of any column). If so, it writes argument iDelta
+** to the output buffer pOut, followed by a position list consisting only
+** of the entries from pList at position 0, and terminated by an 0x00 byte.
+** The value returned is the number of bytes written to pOut (if any).
+*/
+int sqlite3Fts3FirstFilter(
+ sqlite3_int64 iDelta, /* Varint that may be written to pOut */
+ char *pList, /* Position list (no 0x00 term) */
+ int nList, /* Size of pList in bytes */
+ char *pOut /* Write output here */
+){
+ int nOut = 0;
+ int bWritten = 0; /* True once iDelta has been written */
+ char *p = pList;
+ char *pEnd = &pList[nList];
+
+ if( *p!=0x01 ){
+ if( *p==0x02 ){
+ nOut += sqlite3Fts3PutVarint(&pOut[nOut], iDelta);
+ pOut[nOut++] = 0x02;
+ bWritten = 1;
+ }
+ fts3ColumnlistCopy(0, &p);
+ }
+
+ while( paaOutput[0]==0 ){
/* If this is the first term selected, copy the doclist to the output
** buffer using memcpy(). */
@@ -2201,6 +2539,13 @@ static int fts3SegReaderCursorAppend(
return SQLITE_OK;
}
+/*
+** Add seg-reader objects to the Fts3MultiSegReader object passed as the
+** 8th argument.
+**
+** This function returns SQLITE_OK if successful, or an SQLite error code
+** otherwise.
+*/
static int fts3SegReaderCursor(
Fts3Table *p, /* FTS3 table handle */
int iIndex, /* Index to search (from 0 to p->nIndex-1) */
@@ -2209,11 +2554,11 @@ static int fts3SegReaderCursor(
int nTerm, /* Size of zTerm in bytes */
int isPrefix, /* True for a prefix search */
int isScan, /* True to scan from zTerm to EOF */
- Fts3MultiSegReader *pCsr /* Cursor object to populate */
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
){
- int rc = SQLITE_OK;
- int rc2;
- sqlite3_stmt *pStmt = 0;
+ int rc = SQLITE_OK; /* Error code */
+ sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
+ int rc2; /* Result of sqlite3_reset() */
/* If iLevel is less than 0 and this is not a scan, include a seg-reader
** for the pending-terms. If this is a scan, then this call must be being
@@ -2302,24 +2647,42 @@ int sqlite3Fts3SegReaderCursor(
);
}
+/*
+** In addition to its current configuration, have the Fts3MultiSegReader
+** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+*/
static int fts3SegReaderCursorAddZero(
- Fts3Table *p,
- const char *zTerm,
- int nTerm,
- Fts3MultiSegReader *pCsr
+ Fts3Table *p, /* FTS virtual table handle */
+ const char *zTerm, /* Term to scan doclist of */
+ int nTerm, /* Number of bytes in zTerm */
+ Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
){
return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
}
-
-int sqlite3Fts3TermSegReaderCursor(
+/*
+** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
+** if isPrefix is true, to scan the doclist for all terms for which
+** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
+** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
+** an SQLite error code.
+**
+** It is the responsibility of the caller to free this object by eventually
+** passing it to fts3SegReaderCursorFree()
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+** Output parameter *ppSegcsr is set to 0 if an error occurs.
+*/
+static int fts3TermSegReaderCursor(
Fts3Cursor *pCsr, /* Virtual table cursor handle */
const char *zTerm, /* Term to query for */
int nTerm, /* Size of zTerm in bytes */
int isPrefix, /* True for a prefix search */
Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
){
- Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
+ Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
int rc = SQLITE_NOMEM; /* Return code */
pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
@@ -2363,6 +2726,9 @@ int sqlite3Fts3TermSegReaderCursor(
return rc;
}
+/*
+** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
+*/
static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
sqlite3Fts3SegReaderFinish(pSegcsr);
sqlite3_free(pSegcsr);
@@ -2370,35 +2736,26 @@ static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
/*
** This function retreives the doclist for the specified term (or term
-** prefix) from the database.
-**
-** The returned doclist may be in one of two formats, depending on the
-** value of parameter isReqPos. If isReqPos is zero, then the doclist is
-** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
-** is non-zero, then the returned list is in the same format as is stored
-** in the database without the found length specifier at the start of on-disk
-** doclists.
+** prefix) from the database.
*/
static int fts3TermSelect(
Fts3Table *p, /* Virtual table handle */
Fts3PhraseToken *pTok, /* Token to query for */
int iColumn, /* Column to query (or -ve for all columns) */
- int isReqPos, /* True to include position lists in output */
int *pnOut, /* OUT: Size of buffer at *ppOut */
char **ppOut /* OUT: Malloced result buffer */
){
int rc; /* Return code */
- Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
- TermSelect tsc; /* Context object for fts3TermSelectCb() */
+ Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
+ TermSelect tsc; /* Object for pair-wise doclist merging */
Fts3SegFilter filter; /* Segment term filter configuration */
pSegcsr = pTok->pSegcsr;
memset(&tsc, 0, sizeof(TermSelect));
- tsc.isReqPos = isReqPos;
- filter.flags = FTS3_SEGMENT_IGNORE_EMPTY
+ filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
| (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
- | (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
+ | (pTok->bFirst ? FTS3_SEGMENT_FIRST : 0)
| (iColumnnColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
filter.iCol = iColumn;
filter.zTerm = pTok->z;
@@ -2408,13 +2765,11 @@ static int fts3TermSelect(
while( SQLITE_OK==rc
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
){
- rc = fts3TermSelectCb(p, (void *)&tsc,
- pSegcsr->zTerm, pSegcsr->nTerm, pSegcsr->aDoclist, pSegcsr->nDoclist
- );
+ rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
}
if( rc==SQLITE_OK ){
- rc = fts3TermSelectMerge(p, &tsc);
+ rc = fts3TermSelectFinishMerge(p, &tsc);
}
if( rc==SQLITE_OK ){
*ppOut = tsc.aaOutput[0];
@@ -2440,24 +2795,15 @@ static int fts3TermSelect(
** that the doclist is simply a list of docids stored as delta encoded
** varints.
*/
-static int fts3DoclistCountDocids(int isPoslist, char *aList, int nList){
+static int fts3DoclistCountDocids(char *aList, int nList){
int nDoc = 0; /* Return value */
if( aList ){
char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
char *p = aList; /* Cursor */
- if( !isPoslist ){
- /* The number of docids in the list is the same as the number of
- ** varints. In FTS3 a varint consists of a single byte with the 0x80
- ** bit cleared and zero or more bytes with the 0x80 bit set. So to
- ** count the varints in the buffer, just count the number of bytes
- ** with the 0x80 bit clear. */
- while( pbase.pVtab)->pSegments==0 );
return rc;
@@ -2550,8 +2896,8 @@ static int fts3FilterMethod(
return SQLITE_NOMEM;
}
- rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn,
- iCol, zQuery, -1, &pCsr->pExpr
+ rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->bHasStat,
+ p->nColumn, iCol, zQuery, -1, &pCsr->pExpr
);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_ERROR ){
@@ -2564,7 +2910,7 @@ static int fts3FilterMethod(
rc = sqlite3Fts3ReadLock(p);
if( rc!=SQLITE_OK ) return rc;
- rc = sqlite3Fts3EvalStart(pCsr, pCsr->pExpr, 1);
+ rc = fts3EvalStart(pCsr);
sqlite3Fts3SegmentsClose(p);
if( rc!=SQLITE_OK ) return rc;
@@ -2578,23 +2924,24 @@ static int fts3FilterMethod(
** row by docid.
*/
if( idxNum==FTS3_FULLSCAN_SEARCH ){
- const char *zSort = (pCsr->bDesc ? "DESC" : "ASC");
- const char *zTmpl = "SELECT %s FROM %Q.'%q_content' AS x ORDER BY docid %s";
- zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist, p->zDb, p->zName, zSort);
- }else{
- const char *zTmpl = "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?";
- zSql = sqlite3_mprintf(zTmpl, p->zReadExprlist, p->zDb, p->zName);
+ zSql = sqlite3_mprintf(
+ "SELECT %s ORDER BY rowid %s",
+ p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
+ );
+ if( zSql ){
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
+ sqlite3_free(zSql);
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+ }else if( idxNum==FTS3_DOCID_SEARCH ){
+ rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
+ }
}
- if( !zSql ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
- sqlite3_free(zSql);
if( rc!=SQLITE_OK ) return rc;
- if( idxNum==FTS3_DOCID_SEARCH ){
- rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
- if( rc!=SQLITE_OK ) return rc;
- }
-
return fts3NextMethod(pCursor);
}
@@ -2646,7 +2993,7 @@ static int fts3ColumnMethod(
sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
}else{
rc = fts3CursorSeek(0, pCsr);
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
}
}
@@ -2730,7 +3077,7 @@ static int fts3RollbackMethod(sqlite3_vtab *pVtab){
*/
static void fts3ReversePoslist(char *pStart, char **ppPoslist){
char *p = &(*ppPoslist)[-2];
- char c;
+ char c = 0;
while( p>pStart && (c=*p--)==0 );
while( p>pStart && (*p & 0x80) | c ){
@@ -2939,15 +3286,22 @@ static int fts3RenameMethod(
sqlite3 *db = p->db; /* Database connection */
int rc; /* Return Code */
+ /* As it happens, the pending terms table is always empty here. This is
+ ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
+ ** always opens a savepoint transaction. And the xSavepoint() method
+ ** flushes the pending terms table. But leave the (no-op) call to
+ ** PendingTermsFlush() in in case that changes.
+ */
+ assert( p->nPendingData==0 );
rc = sqlite3Fts3PendingTermsFlush(p);
- if( rc!=SQLITE_OK ){
- return rc;
+
+ if( p->zContentTbl==0 ){
+ fts3DbExec(&rc, db,
+ "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';",
+ p->zDb, p->zName, zName
+ );
}
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';",
- p->zDb, p->zName, zName
- );
if( p->bHasDocsize ){
fts3DbExec(&rc, db,
"ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';",
@@ -2971,6 +3325,11 @@ static int fts3RenameMethod(
return rc;
}
+/*
+** The xSavepoint() method.
+**
+** Flush the contents of the pending-terms table to disk.
+*/
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
UNUSED_PARAMETER(iSavepoint);
assert( ((Fts3Table *)pVtab)->inTransaction );
@@ -2978,6 +3337,12 @@ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
return fts3SyncMethod(pVtab);
}
+
+/*
+** The xRelease() method.
+**
+** This is a no-op.
+*/
static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
UNUSED_PARAMETER(iSavepoint);
@@ -2987,6 +3352,12 @@ static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
TESTONLY( p->mxSavepoint = iSavepoint-1 );
return SQLITE_OK;
}
+
+/*
+** The xRollbackTo() method.
+**
+** Discard the contents of the pending terms table.
+*/
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts3Table *p = (Fts3Table*)pVtab;
UNUSED_PARAMETER(iSavepoint);
@@ -3136,18 +3507,6 @@ int sqlite3Fts3Init(sqlite3 *db){
return rc;
}
-#if !SQLITE_CORE
-int sqlite3_extension_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi)
- return sqlite3Fts3Init(db);
-}
-#endif
-
-
/*
** Allocate an Fts3MultiSegReader for each token in the expression headed
** by pExpr.
@@ -3164,11 +3523,11 @@ int sqlite3_extension_init(
** doclist and then traversed.
*/
static void fts3EvalAllocateReaders(
- Fts3Cursor *pCsr,
- Fts3Expr *pExpr,
+ Fts3Cursor *pCsr, /* FTS cursor handle */
+ Fts3Expr *pExpr, /* Allocate readers for this expression */
int *pnToken, /* OUT: Total number of tokens in phrase. */
int *pnOr, /* OUT: Total number of OR nodes in expr. */
- int *pRc
+ int *pRc /* IN/OUT: Error code */
){
if( pExpr && SQLITE_OK==*pRc ){
if( pExpr->eType==FTSQUERY_PHRASE ){
@@ -3177,7 +3536,7 @@ static void fts3EvalAllocateReaders(
*pnToken += nToken;
for(i=0; ipPhrase->aToken[i];
- int rc = sqlite3Fts3TermSegReaderCursor(pCsr,
+ int rc = fts3TermSegReaderCursor(pCsr,
pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
);
if( rc!=SQLITE_OK ){
@@ -3195,12 +3554,20 @@ static void fts3EvalAllocateReaders(
}
}
+/*
+** Arguments pList/nList contain the doclist for token iToken of phrase p.
+** It is merged into the main doclist stored in p->doclist.aAll/nAll.
+**
+** This function assumes that pList points to a buffer allocated using
+** sqlite3_malloc(). This function takes responsibility for eventually
+** freeing the buffer.
+*/
static void fts3EvalPhraseMergeToken(
- Fts3Table *pTab,
- Fts3Phrase *p,
- int iToken,
- char *pList,
- int nList
+ Fts3Table *pTab, /* FTS Table pointer */
+ Fts3Phrase *p, /* Phrase to merge pList/nList into */
+ int iToken, /* Token pList/nList corresponds to */
+ char *pList, /* Pointer to doclist */
+ int nList /* Number of bytes in pList */
){
assert( iToken!=p->iDoclistToken );
@@ -3249,9 +3616,15 @@ static void fts3EvalPhraseMergeToken(
if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
}
+/*
+** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
+** does not take deferred tokens into account.
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+*/
static int fts3EvalPhraseLoad(
- Fts3Cursor *pCsr,
- Fts3Phrase *p
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Phrase *p /* Phrase object */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int iToken;
@@ -3264,7 +3637,7 @@ static int fts3EvalPhraseLoad(
if( pToken->pSegcsr ){
int nThis = 0;
char *pThis = 0;
- rc = fts3TermSelect(pTab, pToken, p->iColumn, 1, &nThis, &pThis);
+ rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
if( rc==SQLITE_OK ){
fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
}
@@ -3275,25 +3648,32 @@ static int fts3EvalPhraseLoad(
return rc;
}
+/*
+** This function is called on each phrase after the position lists for
+** any deferred tokens have been loaded into memory. It updates the phrases
+** current position list to include only those positions that are really
+** instances of the phrase (after considering deferred tokens). If this
+** means that the phrase does not appear in the current row, doclist.pList
+** and doclist.nList are both zeroed.
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+*/
static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
- int iToken;
- int rc = SQLITE_OK;
-
- int nMaxUndeferred = pPhrase->iDoclistToken;
- char *aPoslist = 0;
- int nPoslist = 0;
- int iPrev = -1;
+ int iToken; /* Used to iterate through phrase tokens */
+ char *aPoslist = 0; /* Position list for deferred tokens */
+ int nPoslist = 0; /* Number of bytes in aPoslist */
+ int iPrev = -1; /* Token number of previous deferred token */
assert( pPhrase->doclist.bFreeList==0 );
- for(iToken=0; rc==SQLITE_OK && iTokennToken; iToken++){
+ for(iToken=0; iTokennToken; iToken++){
Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
Fts3DeferredToken *pDeferred = pToken->pDeferred;
if( pDeferred ){
char *pList;
int nList;
- rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList);
+ int rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList);
if( rc!=SQLITE_OK ) return rc;
if( pList==0 ){
@@ -3328,6 +3708,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
}
if( iPrev>=0 ){
+ int nMaxUndeferred = pPhrase->iDoclistToken;
if( nMaxUndeferred<0 ){
pPhrase->doclist.pList = aPoslist;
pPhrase->doclist.nList = nPoslist;
@@ -3376,9 +3757,15 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
** expression to initialize the mechanism for returning rows. Once this
** function has been called successfully on an Fts3Phrase, it may be
** used with fts3EvalPhraseNext() to iterate through the matching docids.
+**
+** If parameter bOptOk is true, then the phrase may (or may not) use the
+** incremental loading strategy. Otherwise, the entire doclist is loaded into
+** memory within this call.
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
- int rc;
+ int rc; /* Error code */
Fts3PhraseToken *pFirst = &p->aToken[0];
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
@@ -3387,6 +3774,7 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
&& p->nToken==1
&& pFirst->pSegcsr
&& pFirst->pSegcsr->bLookup
+ && pFirst->bFirst==0
){
/* Use the incremental approach. */
int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
@@ -3406,7 +3794,13 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
/*
** This function is used to iterate backwards (from the end to start)
-** through doclists.
+** through doclists. It is used by this module to iterate through phrase
+** doclists in reverse and by the fts3_write.c module to iterate through
+** pending-terms lists when writing to databases with "order=desc".
+**
+** The doclist may be sorted in ascending (parameter bDescIdx==0) or
+** descending (parameter bDescIdx==1) order of docid. Regardless, this
+** function iterates from the end of the doclist to the beginning.
*/
void sqlite3Fts3DoclistPrev(
int bDescIdx, /* True if the doclist is desc */
@@ -3471,9 +3865,9 @@ void sqlite3Fts3DoclistPrev(
** successfully advanced, *pbEof is set to 0.
*/
static int fts3EvalPhraseNext(
- Fts3Cursor *pCsr,
- Fts3Phrase *p,
- u8 *pbEof
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Phrase *p, /* Phrase object to advance to next docid */
+ u8 *pbEof /* OUT: Set to 1 if EOF */
){
int rc = SQLITE_OK;
Fts3Doclist *pDL = &p->doclist;
@@ -3519,10 +3913,10 @@ static int fts3EvalPhraseNext(
/* pIter now points just past the 0x00 that terminates the position-
** list for document pDL->iDocid. However, if this position-list was
- ** edited in place by fts3EvalNearTrim2(), then pIter may not actually
+ ** edited in place by fts3EvalNearTrim(), then pIter may not actually
** point to the start of the next docid value. The following line deals
** with this case by advancing pIter past the zero-padding added by
- ** fts3EvalNearTrim2(). */
+ ** fts3EvalNearTrim(). */
while( pIterpNextDocid = pIter;
@@ -3534,11 +3928,27 @@ static int fts3EvalPhraseNext(
return rc;
}
+/*
+**
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
+** expression. Also the Fts3Expr.bDeferred variable is set to true for any
+** expressions for which all descendent tokens are deferred.
+**
+** If parameter bOptOk is zero, then it is guaranteed that the
+** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
+** each phrase in the expression (subject to deferred token processing).
+** Or, if bOptOk is non-zero, then one or more tokens within the expression
+** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
+**
+** If an error occurs within this function, *pRc is set to an SQLite error
+** code before returning.
+*/
static void fts3EvalStartReaders(
- Fts3Cursor *pCsr,
- Fts3Expr *pExpr,
- int bOptOk,
- int *pRc
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Expr *pExpr, /* Expression to initialize phrases in */
+ int bOptOk, /* True to enable incremental loading */
+ int *pRc /* IN/OUT: Error code */
){
if( pExpr && SQLITE_OK==*pRc ){
if( pExpr->eType==FTSQUERY_PHRASE ){
@@ -3557,25 +3967,44 @@ static void fts3EvalStartReaders(
}
}
+/*
+** An array of the following structures is assembled as part of the process
+** of selecting tokens to defer before the query starts executing (as part
+** of the xFilter() method). There is one element in the array for each
+** token in the FTS expression.
+**
+** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
+** to phrases that are connected only by AND and NEAR operators (not OR or
+** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
+** separately. The root of a tokens AND/NEAR cluster is stored in
+** Fts3TokenAndCost.pRoot.
+*/
typedef struct Fts3TokenAndCost Fts3TokenAndCost;
struct Fts3TokenAndCost {
Fts3Phrase *pPhrase; /* The phrase the token belongs to */
int iToken; /* Position of token in phrase */
Fts3PhraseToken *pToken; /* The token itself */
- Fts3Expr *pRoot;
- int nOvfl;
+ Fts3Expr *pRoot; /* Root of NEAR/AND cluster */
+ int nOvfl; /* Number of overflow pages to load doclist */
int iCol; /* The column the token must match */
};
+/*
+** This function is used to populate an allocated Fts3TokenAndCost array.
+**
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+** Otherwise, if an error occurs during execution, *pRc is set to an
+** SQLite error code.
+*/
static void fts3EvalTokenCosts(
- Fts3Cursor *pCsr,
- Fts3Expr *pRoot,
- Fts3Expr *pExpr,
- Fts3TokenAndCost **ppTC,
- Fts3Expr ***ppOr,
- int *pRc
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */
+ Fts3Expr *pExpr, /* Expression to consider */
+ Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */
+ Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */
+ int *pRc /* IN/OUT: Error code */
){
- if( *pRc==SQLITE_OK && pExpr ){
+ if( *pRc==SQLITE_OK ){
if( pExpr->eType==FTSQUERY_PHRASE ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
int i;
@@ -3589,6 +4018,11 @@ static void fts3EvalTokenCosts(
*pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
}
}else if( pExpr->eType!=FTSQUERY_NOT ){
+ assert( pExpr->eType==FTSQUERY_OR
+ || pExpr->eType==FTSQUERY_AND
+ || pExpr->eType==FTSQUERY_NEAR
+ );
+ assert( pExpr->pLeft && pExpr->pRight );
if( pExpr->eType==FTSQUERY_OR ){
pRoot = pExpr->pLeft;
**ppOr = pRoot;
@@ -3605,19 +4039,30 @@ static void fts3EvalTokenCosts(
}
}
+/*
+** Determine the average document (row) size in pages. If successful,
+** write this value to *pnPage and return SQLITE_OK. Otherwise, return
+** an SQLite error code.
+**
+** The average document size in pages is calculated by first calculating
+** determining the average size in bytes, B. If B is less than the amount
+** of data that will fit on a single leaf page of an intkey table in
+** this database, then the average docsize is 1. Otherwise, it is 1 plus
+** the number of overflow pages consumed by a record B bytes in size.
+*/
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
if( pCsr->nRowAvg==0 ){
/* The average document size, which is required to calculate the cost
- ** of each doclist, has not yet been determined. Read the required
- ** data from the %_stat table to calculate it.
- **
- ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
- ** varints, where nCol is the number of columns in the FTS3 table.
- ** The first varint is the number of documents currently stored in
- ** the table. The following nCol varints contain the total amount of
- ** data stored in all rows of each column of the table, from left
- ** to right.
- */
+ ** of each doclist, has not yet been determined. Read the required
+ ** data from the %_stat table to calculate it.
+ **
+ ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
+ ** varints, where nCol is the number of columns in the FTS3 table.
+ ** The first varint is the number of documents currently stored in
+ ** the table. The following nCol varints contain the total amount of
+ ** data stored in all rows of each column of the table, from left
+ ** to right.
+ */
int rc;
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
sqlite3_stmt *pStmt;
@@ -3638,7 +4083,7 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
}
if( nDoc==0 || nByte==0 ){
sqlite3_reset(pStmt);
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
pCsr->nDoc = nDoc;
@@ -3652,68 +4097,130 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
return SQLITE_OK;
}
+/*
+** This function is called to select the tokens (if any) that will be
+** deferred. The array aTC[] has already been populated when this is
+** called.
+**
+** This function is called once for each AND/NEAR cluster in the
+** expression. Each invocation determines which tokens to defer within
+** the cluster with root node pRoot. See comments above the definition
+** of struct Fts3TokenAndCost for more details.
+**
+** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
+** called on each token to defer. Otherwise, an SQLite error code is
+** returned.
+*/
static int fts3EvalSelectDeferred(
- Fts3Cursor *pCsr,
- Fts3Expr *pRoot,
- Fts3TokenAndCost *aTC,
- int nTC
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Expr *pRoot, /* Consider tokens with this root node */
+ Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */
+ int nTC /* Number of entries in aTC[] */
){
- int nDocSize = 0;
- int nDocEst = 0;
- int rc = SQLITE_OK;
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int ii;
+ int nDocSize = 0; /* Number of pages per doc loaded */
+ int rc = SQLITE_OK; /* Return code */
+ int ii; /* Iterator variable for various purposes */
+ int nOvfl = 0; /* Total overflow pages used by doclists */
+ int nToken = 0; /* Total number of tokens in cluster */
- int nOvfl = 0;
- int nTerm = 0;
+ int nMinEst = 0; /* The minimum count for any phrase so far. */
+ int nLoad4 = 1; /* (Phrases that will be loaded)^4. */
+ /* Tokens are never deferred for FTS tables created using the content=xxx
+ ** option. The reason being that it is not guaranteed that the content
+ ** table actually contains the same data as the index. To prevent this from
+ ** causing any problems, the deferred token optimization is completely
+ ** disabled for content=xxx tables. */
+ if( pTab->zContentTbl ){
+ return SQLITE_OK;
+ }
+
+ /* Count the tokens in this AND/NEAR cluster. If none of the doclists
+ ** associated with the tokens spill onto overflow pages, or if there is
+ ** only 1 token, exit early. No tokens to defer in this case. */
for(ii=0; ii0 );
- for(ii=0; iinOvfl)
+ /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
+ ** of the number of overflow pages that will be loaded by the pager layer
+ ** to retrieve the entire doclist for the token from the full-text index.
+ ** Load the doclists for tokens that are either:
+ **
+ ** a. The cheapest token in the entire query (i.e. the one visited by the
+ ** first iteration of this loop), or
+ **
+ ** b. Part of a multi-token phrase.
+ **
+ ** After each token doclist is loaded, merge it with the others from the
+ ** same phrase and count the number of documents that the merged doclist
+ ** contains. Set variable "nMinEst" to the smallest number of documents in
+ ** any phrase doclist for which 1 or more token doclists have been loaded.
+ ** Let nOther be the number of other phrases for which it is certain that
+ ** one or more tokens will not be deferred.
+ **
+ ** Then, for each token, defer it if loading the doclist would result in
+ ** loading N or more overflow pages into memory, where N is computed as:
+ **
+ ** (nMinEst + 4^nOther - 1) / (4^nOther)
+ */
+ for(ii=0; iinOvfl)
){
- pTC = &aTC[jj];
+ pTC = &aTC[iTC];
}
}
assert( pTC );
- /* At this point pTC points to the cheapest remaining token. */
- if( ii==0 ){
- if( pTC->nOvfl ){
- nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
- }else{
+ if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
+ /* The number of overflow pages to load for this (and therefore all
+ ** subsequent) tokens is greater than the estimated number of pages
+ ** that will be loaded if all subsequent tokens are deferred.
+ */
+ Fts3PhraseToken *pToken = pTC->pToken;
+ rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
+ fts3SegReaderCursorFree(pToken->pSegcsr);
+ pToken->pSegcsr = 0;
+ }else{
+ /* Set nLoad4 to the value of (4^nOther) for the next iteration of the
+ ** for-loop. Except, limit the value to 2^24 to prevent it from
+ ** overflowing the 32-bit integer it is stored in. */
+ if( ii<12 ) nLoad4 = nLoad4*4;
+
+ if( ii==0 || pTC->pPhrase->nToken>1 ){
+ /* Either this is the cheapest token in the entire query, or it is
+ ** part of a multi-token phrase. Either way, the entire doclist will
+ ** (eventually) be loaded into memory. It may as well be now. */
Fts3PhraseToken *pToken = pTC->pToken;
int nList = 0;
char *pList = 0;
- rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
+ rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
assert( rc==SQLITE_OK || pList==0 );
-
if( rc==SQLITE_OK ){
- nDocEst = fts3DoclistCountDocids(1, pList, nList);
+ int nCount;
fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
+ nCount = fts3DoclistCountDocids(
+ pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
+ );
+ if( ii==0 || nCountnOvfl>=(nDocEst*nDocSize) ){
- Fts3PhraseToken *pToken = pTC->pToken;
- rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
- fts3SegReaderCursorFree(pToken->pSegcsr);
- pToken->pSegcsr = 0;
- }
- nDocEst = 1 + (nDocEst/4);
}
pTC->pToken = 0;
}
@@ -3721,36 +4228,29 @@ static int fts3EvalSelectDeferred(
return rc;
}
-int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
+/*
+** This function is called from within the xFilter method. It initializes
+** the full-text query currently stored in pCsr->pExpr. To iterate through
+** the results of a query, the caller does:
+**
+** fts3EvalStart(pCsr);
+** while( 1 ){
+** fts3EvalNext(pCsr);
+** if( pCsr->bEof ) break;
+** ... return row pCsr->iPrevId to the caller ...
+** }
+*/
+static int fts3EvalStart(Fts3Cursor *pCsr){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc = SQLITE_OK;
int nToken = 0;
int nOr = 0;
/* Allocate a MultiSegReader for each token in the expression. */
- fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
+ fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
- /* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
- ** This call will eventually also be responsible for determining which
- ** tokens are 'deferred' until the document text is loaded into memory.
- **
- ** Each token in each phrase is dealt with using one of the following
- ** three strategies:
- **
- ** 1. Entire doclist loaded into memory as part of the
- ** fts3EvalStartReaders() call.
- **
- ** 2. Doclist loaded into memory incrementally, as part of each
- ** sqlite3Fts3EvalNext() call.
- **
- ** 3. Token doclist is never loaded. Instead, documents are loaded into
- ** memory and scanned for the token as part of the sqlite3Fts3EvalNext()
- ** call. This is known as a "deferred" token.
- */
-
- /* If bOptOk is true, check if there are any tokens that should be deferred.
- */
- if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
+ /* Determine which, if any, tokens in the expression should be deferred. */
+ if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
Fts3TokenAndCost *aTC;
Fts3Expr **apOr;
aTC = (Fts3TokenAndCost *)sqlite3_malloc(
@@ -3766,7 +4266,7 @@ int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
Fts3TokenAndCost *pTC = aTC;
Fts3Expr **ppOr = apOr;
- fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
+ fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
nToken = pTC-aTC;
nOr = ppOr-apOr;
@@ -3781,11 +4281,14 @@ int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
}
}
- fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
+ fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
return rc;
}
-static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
+/*
+** Invalidate the current position list for phrase pPhrase.
+*/
+static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
if( pPhrase->doclist.bFreeList ){
sqlite3_free(pPhrase->doclist.pList);
}
@@ -3794,8 +4297,30 @@ static void fts3EvalZeroPoslist(Fts3Phrase *pPhrase){
pPhrase->doclist.bFreeList = 0;
}
-static int fts3EvalNearTrim2(
- int nNear,
+/*
+** This function is called to edit the position list associated with
+** the phrase object passed as the fifth argument according to a NEAR
+** condition. For example:
+**
+** abc NEAR/5 "def ghi"
+**
+** Parameter nNear is passed the NEAR distance of the expression (5 in
+** the example above). When this function is called, *paPoslist points to
+** the position list, and *pnToken is the number of phrase tokens in, the
+** phrase on the other side of the NEAR operator to pPhrase. For example,
+** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
+** the position list associated with phrase "abc".
+**
+** All positions in the pPhrase position list that are not sufficiently
+** close to a position in the *paPoslist position list are removed. If this
+** leaves 0 positions, zero is returned. Otherwise, non-zero.
+**
+** Before returning, *paPoslist is set to point to the position lsit
+** associated with pPhrase. And *pnToken is set to the number of tokens in
+** pPhrase.
+*/
+static int fts3EvalNearTrim(
+ int nNear, /* NEAR distance. As in "NEAR/nNear". */
char *aTmp, /* Temporary space to use */
char **paPoslist, /* IN/OUT: Position list */
int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
@@ -3827,6 +4352,172 @@ static int fts3EvalNearTrim2(
return res;
}
+/*
+** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
+** Otherwise, it advances the expression passed as the second argument to
+** point to the next matching row in the database. Expressions iterate through
+** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
+** or descending if it is non-zero.
+**
+** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
+** successful, the following variables in pExpr are set:
+**
+** Fts3Expr.bEof (non-zero if EOF - there is no next row)
+** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row)
+**
+** If the expression is of type FTSQUERY_PHRASE, and the expression is not
+** at EOF, then the following variables are populated with the position list
+** for the phrase for the visited row:
+**
+** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes)
+** FTs3Expr.pPhrase->doclist.pList (pointer to position list)
+**
+** It says above that this function advances the expression to the next
+** matching row. This is usually true, but there are the following exceptions:
+**
+** 1. Deferred tokens are not taken into account. If a phrase consists
+** entirely of deferred tokens, it is assumed to match every row in
+** the db. In this case the position-list is not populated at all.
+**
+** Or, if a phrase contains one or more deferred tokens and one or
+** more non-deferred tokens, then the expression is advanced to the
+** next possible match, considering only non-deferred tokens. In other
+** words, if the phrase is "A B C", and "B" is deferred, the expression
+** is advanced to the next row that contains an instance of "A * C",
+** where "*" may match any single token. The position list in this case
+** is populated as for "A * C" before returning.
+**
+** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
+** advanced to point to the next row that matches "x AND y".
+**
+** See fts3EvalTestDeferredAndNear() for details on testing if a row is
+** really a match, taking into account deferred tokens and NEAR operators.
+*/
+static void fts3EvalNextRow(
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Expr *pExpr, /* Expr. to advance to next matching row */
+ int *pRc /* IN/OUT: Error code */
+){
+ if( *pRc==SQLITE_OK ){
+ int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */
+ assert( pExpr->bEof==0 );
+ pExpr->bStart = 1;
+
+ switch( pExpr->eType ){
+ case FTSQUERY_NEAR:
+ case FTSQUERY_AND: {
+ Fts3Expr *pLeft = pExpr->pLeft;
+ Fts3Expr *pRight = pExpr->pRight;
+ assert( !pLeft->bDeferred || !pRight->bDeferred );
+
+ if( pLeft->bDeferred ){
+ /* LHS is entirely deferred. So we assume it matches every row.
+ ** Advance the RHS iterator to find the next row visited. */
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ pExpr->iDocid = pRight->iDocid;
+ pExpr->bEof = pRight->bEof;
+ }else if( pRight->bDeferred ){
+ /* RHS is entirely deferred. So we assume it matches every row.
+ ** Advance the LHS iterator to find the next row visited. */
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ pExpr->iDocid = pLeft->iDocid;
+ pExpr->bEof = pLeft->bEof;
+ }else{
+ /* Neither the RHS or LHS are deferred. */
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
+ sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+ if( iDiff==0 ) break;
+ if( iDiff<0 ){
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ }else{
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ }
+ }
+ pExpr->iDocid = pLeft->iDocid;
+ pExpr->bEof = (pLeft->bEof || pRight->bEof);
+ }
+ break;
+ }
+
+ case FTSQUERY_OR: {
+ Fts3Expr *pLeft = pExpr->pLeft;
+ Fts3Expr *pRight = pExpr->pRight;
+ sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+
+ assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
+ assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
+
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ }else{
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ }
+
+ pExpr->bEof = (pLeft->bEof && pRight->bEof);
+ iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
+ pExpr->iDocid = pLeft->iDocid;
+ }else{
+ pExpr->iDocid = pRight->iDocid;
+ }
+
+ break;
+ }
+
+ case FTSQUERY_NOT: {
+ Fts3Expr *pLeft = pExpr->pLeft;
+ Fts3Expr *pRight = pExpr->pRight;
+
+ if( pRight->bStart==0 ){
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ assert( *pRc!=SQLITE_OK || pRight->bStart );
+ }
+
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ if( pLeft->bEof==0 ){
+ while( !*pRc
+ && !pRight->bEof
+ && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
+ ){
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ }
+ }
+ pExpr->iDocid = pLeft->iDocid;
+ pExpr->bEof = pLeft->bEof;
+ break;
+ }
+
+ default: {
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ fts3EvalInvalidatePoslist(pPhrase);
+ *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
+ pExpr->iDocid = pPhrase->doclist.iDocid;
+ break;
+ }
+ }
+ }
+}
+
+/*
+** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
+** cluster, then this function returns 1 immediately.
+**
+** Otherwise, it checks if the current row really does match the NEAR
+** expression, using the data currently stored in the position lists
+** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
+**
+** If the current row is a match, the position list associated with each
+** phrase in the NEAR expression is edited in place to contain only those
+** phrase instances sufficiently close to their peers to satisfy all NEAR
+** constraints. In this case it returns 1. If the NEAR expression does not
+** match the current row, 0 is returned. The position lists may or may not
+** be edited if 0 is returned.
+*/
static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
int res = 1;
@@ -3848,7 +4539,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
**
** The right-hand child of a NEAR node is always a phrase. The
** left-hand child may be either a phrase or a NEAR node. There are
- ** no exceptions to this.
+ ** no exceptions to this - it's the way the parser in fts3_expr.c works.
*/
if( *pRc==SQLITE_OK
&& pExpr->eType==FTSQUERY_NEAR
@@ -3875,17 +4566,20 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
Fts3Phrase *pPhrase = p->pRight->pPhrase;
int nNear = p->nNear;
- res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
nToken = pExpr->pRight->pPhrase->nToken;
for(p=pExpr->pLeft; p && res; p=p->pLeft){
- int nNear = p->pParent->nNear;
- Fts3Phrase *pPhrase = (
+ int nNear;
+ Fts3Phrase *pPhrase;
+ assert( p->pParent && p->pParent->pLeft==p );
+ nNear = p->pParent->nNear;
+ pPhrase = (
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
);
- res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
}
@@ -3896,128 +4590,29 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
}
/*
-** This macro is used by the fts3EvalNext() function. The two arguments are
-** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
-** the macro returns (i1 - i2). Or if it is "ORDER BY docid DESC", then
-** it returns (i2 - i1). This allows the same code to be used for merging
-** doclists in ascending or descending order.
+** This function is a helper function for fts3EvalTestDeferredAndNear().
+** Assuming no error occurs or has occurred, It returns non-zero if the
+** expression passed as the second argument matches the row that pCsr
+** currently points to, or zero if it does not.
+**
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+** If an error occurs during execution of this function, *pRc is set to
+** the appropriate SQLite error code. In this case the returned value is
+** undefined.
*/
-#define DOCID_CMP(i1, i2) ((pCsr->bDesc?-1:1) * (i1-i2))
-
-static void fts3EvalNext(
- Fts3Cursor *pCsr,
- Fts3Expr *pExpr,
- int *pRc
+static int fts3EvalTestExpr(
+ Fts3Cursor *pCsr, /* FTS cursor handle */
+ Fts3Expr *pExpr, /* Expr to test. May or may not be root. */
+ int *pRc /* IN/OUT: Error code */
){
- if( *pRc==SQLITE_OK ){
- assert( pExpr->bEof==0 );
- pExpr->bStart = 1;
-
- switch( pExpr->eType ){
- case FTSQUERY_NEAR:
- case FTSQUERY_AND: {
- Fts3Expr *pLeft = pExpr->pLeft;
- Fts3Expr *pRight = pExpr->pRight;
- assert( !pLeft->bDeferred || !pRight->bDeferred );
- if( pLeft->bDeferred ){
- fts3EvalNext(pCsr, pRight, pRc);
- pExpr->iDocid = pRight->iDocid;
- pExpr->bEof = pRight->bEof;
- }else if( pRight->bDeferred ){
- fts3EvalNext(pCsr, pLeft, pRc);
- pExpr->iDocid = pLeft->iDocid;
- pExpr->bEof = pLeft->bEof;
- }else{
- fts3EvalNext(pCsr, pLeft, pRc);
- fts3EvalNext(pCsr, pRight, pRc);
-
- while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
- sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
- if( iDiff==0 ) break;
- if( iDiff<0 ){
- fts3EvalNext(pCsr, pLeft, pRc);
- }else{
- fts3EvalNext(pCsr, pRight, pRc);
- }
- }
-
- pExpr->iDocid = pLeft->iDocid;
- pExpr->bEof = (pLeft->bEof || pRight->bEof);
- }
- break;
- }
-
- case FTSQUERY_OR: {
- Fts3Expr *pLeft = pExpr->pLeft;
- Fts3Expr *pRight = pExpr->pRight;
- sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
-
- assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
- assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
-
- if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
- fts3EvalNext(pCsr, pLeft, pRc);
- }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
- fts3EvalNext(pCsr, pRight, pRc);
- }else{
- fts3EvalNext(pCsr, pLeft, pRc);
- fts3EvalNext(pCsr, pRight, pRc);
- }
-
- pExpr->bEof = (pLeft->bEof && pRight->bEof);
- iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
- if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
- pExpr->iDocid = pLeft->iDocid;
- }else{
- pExpr->iDocid = pRight->iDocid;
- }
-
- break;
- }
-
- case FTSQUERY_NOT: {
- Fts3Expr *pLeft = pExpr->pLeft;
- Fts3Expr *pRight = pExpr->pRight;
-
- if( pRight->bStart==0 ){
- fts3EvalNext(pCsr, pRight, pRc);
- assert( *pRc!=SQLITE_OK || pRight->bStart );
- }
-
- fts3EvalNext(pCsr, pLeft, pRc);
- if( pLeft->bEof==0 ){
- while( !*pRc
- && !pRight->bEof
- && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
- ){
- fts3EvalNext(pCsr, pRight, pRc);
- }
- }
- pExpr->iDocid = pLeft->iDocid;
- pExpr->bEof = pLeft->bEof;
- break;
- }
-
- default: {
- Fts3Phrase *pPhrase = pExpr->pPhrase;
- fts3EvalZeroPoslist(pPhrase);
- *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
- pExpr->iDocid = pPhrase->doclist.iDocid;
- break;
- }
- }
- }
-}
-
-static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
- int bHit = 1;
+ int bHit = 1; /* Return value */
if( *pRc==SQLITE_OK ){
switch( pExpr->eType ){
case FTSQUERY_NEAR:
case FTSQUERY_AND:
bHit = (
- fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
- && fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
+ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
+ && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
&& fts3EvalNearTest(pExpr, pRc)
);
@@ -4043,27 +4638,27 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
Fts3Expr *p;
for(p=pExpr; p->pPhrase==0; p=p->pLeft){
if( p->pRight->iDocid==pCsr->iPrevId ){
- fts3EvalZeroPoslist(p->pRight->pPhrase);
+ fts3EvalInvalidatePoslist(p->pRight->pPhrase);
}
}
if( p->iDocid==pCsr->iPrevId ){
- fts3EvalZeroPoslist(p->pPhrase);
+ fts3EvalInvalidatePoslist(p->pPhrase);
}
}
break;
case FTSQUERY_OR: {
- int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
- int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
+ int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
+ int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
bHit = bHit1 || bHit2;
break;
}
case FTSQUERY_NOT:
bHit = (
- fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
- && !fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
+ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
+ && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
);
break;
@@ -4074,7 +4669,7 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
Fts3Phrase *pPhrase = pExpr->pPhrase;
assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
if( pExpr->bDeferred ){
- fts3EvalZeroPoslist(pPhrase);
+ fts3EvalInvalidatePoslist(pPhrase);
}
*pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
bHit = (pPhrase->doclist.pList!=0);
@@ -4090,27 +4685,49 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
}
/*
-** Return 1 if both of the following are true:
+** This function is called as the second part of each xNext operation when
+** iterating through the results of a full-text query. At this point the
+** cursor points to a row that matches the query expression, with the
+** following caveats:
+**
+** * Up until this point, "NEAR" operators in the expression have been
+** treated as "AND".
+**
+** * Deferred tokens have not yet been considered.
+**
+** If *pRc is not SQLITE_OK when this function is called, it immediately
+** returns 0. Otherwise, it tests whether or not after considering NEAR
+** operators and deferred tokens the current row is still a match for the
+** expression. It returns 1 if both of the following are true:
**
** 1. *pRc is SQLITE_OK when this function returns, and
**
** 2. After scanning the current FTS table row for the deferred tokens,
-** it is determined that the row does not match the query.
+** it is determined that the row does *not* match the query.
**
** Or, if no error occurs and it seems the current row does match the FTS
** query, return 0.
*/
-static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
+static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
int rc = *pRc;
int bMiss = 0;
if( rc==SQLITE_OK ){
+
+ /* If there are one or more deferred tokens, load the current row into
+ ** memory and scan it to determine the position list for each deferred
+ ** token. Then, see if this row is really a match, considering deferred
+ ** tokens and NEAR operators (neither of which were taken into account
+ ** earlier, by fts3EvalNextRow()).
+ */
if( pCsr->pDeferred ){
rc = fts3CursorSeek(0, pCsr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
}
}
- bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
+ bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
+
+ /* Free the position-lists accumulated for each deferred token above. */
sqlite3Fts3FreeDeferredDoclists(pCsr);
*pRc = rc;
}
@@ -4121,7 +4738,7 @@ static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
** Advance to the next document that matches the FTS expression in
** Fts3Cursor.pExpr.
*/
-int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
+static int fts3EvalNext(Fts3Cursor *pCsr){
int rc = SQLITE_OK; /* Return Code */
Fts3Expr *pExpr = pCsr->pExpr;
assert( pCsr->isEof==0 );
@@ -4133,19 +4750,19 @@ int sqlite3Fts3EvalNext(Fts3Cursor *pCsr){
sqlite3_reset(pCsr->pStmt);
}
assert( sqlite3_data_count(pCsr->pStmt)==0 );
- fts3EvalNext(pCsr, pExpr, &rc);
+ fts3EvalNextRow(pCsr, pExpr, &rc);
pCsr->isEof = pExpr->bEof;
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
pCsr->iPrevId = pExpr->iDocid;
- }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
+ }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
}
return rc;
}
/*
** Restart interation for expression pExpr so that the next call to
-** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental
+** fts3EvalNext() visits the first row. Do not allow incremental
** loading or merging of phrase doclists for this iteration.
**
** If *pRc is other than SQLITE_OK when this function is called, it is
@@ -4161,7 +4778,7 @@ static void fts3EvalRestart(
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pPhrase ){
- fts3EvalZeroPoslist(pPhrase);
+ fts3EvalInvalidatePoslist(pPhrase);
if( pPhrase->bIncr ){
assert( pPhrase->nToken==1 );
assert( pPhrase->aToken[0].pSegcsr );
@@ -4277,14 +4894,14 @@ static int fts3EvalGatherStats(
assert( sqlite3_data_count(pCsr->pStmt)==0 );
/* Advance to the next document */
- fts3EvalNext(pCsr, pRoot, &rc);
+ fts3EvalNextRow(pCsr, pRoot, &rc);
pCsr->isEof = pRoot->bEof;
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
pCsr->iPrevId = pRoot->iDocid;
}while( pCsr->isEof==0
&& pRoot->eType==FTSQUERY_NEAR
- && fts3EvalLoadDeferred(pCsr, &rc)
+ && fts3EvalTestDeferredAndNear(pCsr, &rc)
);
if( rc==SQLITE_OK && pCsr->isEof==0 ){
@@ -4306,10 +4923,10 @@ static int fts3EvalGatherStats(
*/
fts3EvalRestart(pCsr, pRoot, &rc);
do {
- fts3EvalNext(pCsr, pRoot, &rc);
+ fts3EvalNextRow(pCsr, pRoot, &rc);
assert( pRoot->bEof==0 );
}while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
- fts3EvalLoadDeferred(pCsr, &rc);
+ fts3EvalTestDeferredAndNear(pCsr, &rc);
}
}
return rc;
@@ -4440,7 +5057,7 @@ void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
if( pPhrase ){
int i;
sqlite3_free(pPhrase->doclist.aAll);
- fts3EvalZeroPoslist(pPhrase);
+ fts3EvalInvalidatePoslist(pPhrase);
memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
for(i=0; inToken; i++){
fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
@@ -4449,4 +5066,27 @@ void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
}
}
+/*
+** Return SQLITE_CORRUPT_VTAB.
+*/
+#ifdef SQLITE_DEBUG
+int sqlite3Fts3Corrupt(){
+ return SQLITE_CORRUPT_VTAB;
+}
+#endif
+
+#if !SQLITE_CORE
+/*
+** Initialize API pointer table, if required.
+*/
+int sqlite3_extension_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ SQLITE_EXTENSION_INIT2(pApi)
+ return sqlite3Fts3Init(db);
+}
+#endif
+
#endif
diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h
index 16643796..78392ec3 100644
--- a/ext/fts3/fts3Int.h
+++ b/ext/fts3/fts3Int.h
@@ -27,7 +27,14 @@
# define SQLITE_ENABLE_FTS3
#endif
-#ifdef SQLITE_ENABLE_FTS3
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* If not building as part of the core, include sqlite3ext.h. */
+#ifndef SQLITE_CORE
+# include "sqlite3ext.h"
+extern const sqlite3_api_routines *sqlite3_api;
+#endif
+
#include "sqlite3.h"
#include "fts3_tokenizer.h"
#include "fts3_hash.h"
@@ -150,6 +157,13 @@ typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */
#endif /* SQLITE_AMALGAMATION */
+#ifdef SQLITE_DEBUG
+int sqlite3Fts3Corrupt(void);
+# define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt()
+#else
+# define FTS_CORRUPT_VTAB SQLITE_CORRUPT_VTAB
+#endif
+
typedef struct Fts3Table Fts3Table;
typedef struct Fts3Cursor Fts3Cursor;
typedef struct Fts3Expr Fts3Expr;
@@ -177,6 +191,7 @@ struct Fts3Table {
int nColumn; /* number of named columns in virtual table */
char **azColumn; /* column names. malloced */
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
+ char *zContentTbl; /* content=xxx option, or NULL */
/* Precompiled statements used by the implementation. Each of these
** statements is run and reset within a single virtual table API call.
@@ -217,7 +232,7 @@ struct Fts3Table {
int nPendingData; /* Current bytes of pending data */
sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
-#if defined(SQLITE_DEBUG)
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
/* State variables used for validating that the transaction control
** methods of the virtual table are called at appropriate times. These
** values do not contribution to the FTS computation; they are used for
@@ -290,7 +305,7 @@ struct Fts3Doclist {
int bFreeList; /* True if pList should be sqlite3_free()d */
char *pList; /* Pointer to position list following iDocid */
int nList; /* Length of position list */
-} doclist;
+};
/*
** A "phrase" is a sequence of one or more tokens that must match in
@@ -302,6 +317,7 @@ struct Fts3PhraseToken {
char *z; /* Text of the token */
int n; /* Number of bytes in buffer z */
int isPrefix; /* True if token ends with a "*" character */
+ int bFirst; /* True if token must appear at position 0 */
/* Variables above this point are populated when the expression is
** parsed (by code in fts3_expr.c). Below this point the variables are
@@ -420,6 +436,7 @@ int sqlite3Fts3SegReaderCursor(
#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
#define FTS3_SEGMENT_PREFIX 0x00000008
#define FTS3_SEGMENT_SCAN 0x00000010
+#define FTS3_SEGMENT_FIRST 0x00000020
/* Type passed as 4th argument to SegmentReaderIterate() */
struct Fts3SegFilter {
@@ -459,8 +476,8 @@ int sqlite3Fts3GetVarint32(const char *, int *);
int sqlite3Fts3VarintLen(sqlite3_uint64);
void sqlite3Fts3Dequote(char *);
void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
-
int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
+int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
/* fts3_tokenizer.c */
const char *sqlite3Fts3NextToken(const char *, int *);
@@ -479,7 +496,7 @@ void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
/* fts3_expr.c */
int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
- char **, int, int, const char *, int, Fts3Expr **
+ char **, int, int, int, const char *, int, Fts3Expr **
);
void sqlite3Fts3ExprFree(Fts3Expr *);
#ifdef SQLITE_TEST
@@ -490,19 +507,8 @@ int sqlite3Fts3InitTerm(sqlite3 *db);
/* fts3_aux.c */
int sqlite3Fts3InitAux(sqlite3 *db);
-int sqlite3Fts3TermSegReaderCursor(
- Fts3Cursor *pCsr, /* Virtual table cursor handle */
- const char *zTerm, /* Term to query for */
- int nTerm, /* Size of zTerm in bytes */
- int isPrefix, /* True for a prefix search */
- Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
-);
-
void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
-int sqlite3Fts3EvalStart(Fts3Cursor *, Fts3Expr *, int);
-int sqlite3Fts3EvalNext(Fts3Cursor *pCsr);
-
int sqlite3Fts3MsrIncrStart(
Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
int sqlite3Fts3MsrIncrNext(
@@ -513,5 +519,5 @@ int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
-#endif /* SQLITE_ENABLE_FTS3 */
+#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */
diff --git a/ext/fts3/fts3_expr.c b/ext/fts3/fts3_expr.c
index 7eb2962d..1c3a7907 100644
--- a/ext/fts3/fts3_expr.c
+++ b/ext/fts3/fts3_expr.c
@@ -93,6 +93,7 @@ typedef struct ParseContext ParseContext;
struct ParseContext {
sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
const char **azCol; /* Array of column names for fts3 table */
+ int bFts4; /* True to allow FTS4-only syntax */
int nCol; /* Number of entries in azCol[] */
int iDefaultCol; /* Default column to query */
int isNot; /* True if getNextNode() sees a unary - */
@@ -180,9 +181,21 @@ static int getNextToken(
pRet->pPhrase->aToken[0].isPrefix = 1;
iEnd++;
}
- if( !sqlite3_fts3_enable_parentheses && iStart>0 && z[iStart-1]=='-' ){
- pParse->isNot = 1;
+
+ while( 1 ){
+ if( !sqlite3_fts3_enable_parentheses
+ && iStart>0 && z[iStart-1]=='-'
+ ){
+ pParse->isNot = 1;
+ iStart--;
+ }else if( pParse->bFts4 && iStart>0 && z[iStart-1]=='^' ){
+ pRet->pPhrase->aToken[0].bFirst = 1;
+ iStart--;
+ }else{
+ break;
+ }
}
+
}
nConsumed = iEnd;
}
@@ -281,6 +294,7 @@ static int getNextString(
pToken->n = nByte;
pToken->isPrefix = (iEndbFirst = (iBegin>0 && zInput[iBegin-1]=='^');
nToken = ii+1;
}
}
@@ -302,8 +316,12 @@ static int getNextString(
p->pPhrase->nToken = nToken;
zBuf = (char *)&p->pPhrase->aToken[nToken];
- memcpy(zBuf, zTemp, nTemp);
- sqlite3_free(zTemp);
+ if( zTemp ){
+ memcpy(zBuf, zTemp, nTemp);
+ sqlite3_free(zTemp);
+ }else{
+ assert( nTemp==0 );
+ }
for(jj=0; jjpPhrase->nToken; jj++){
p->pPhrase->aToken[jj].z = zBuf;
@@ -728,6 +746,7 @@ exprparse_out:
int sqlite3Fts3ExprParse(
sqlite3_tokenizer *pTokenizer, /* Tokenizer module */
char **azCol, /* Array of column names for fts3 table */
+ int bFts4, /* True to allow FTS4-only syntax */
int nCol, /* Number of entries in azCol[] */
int iDefaultCol, /* Default column to query */
const char *z, int n, /* Text of MATCH query */
@@ -741,6 +760,7 @@ int sqlite3Fts3ExprParse(
sParse.nCol = nCol;
sParse.iDefaultCol = iDefaultCol;
sParse.nNest = 0;
+ sParse.bFts4 = bFts4;
if( z==0 ){
*ppExpr = 0;
return SQLITE_OK;
@@ -930,7 +950,7 @@ static void fts3ExprTest(
}
rc = sqlite3Fts3ExprParse(
- pTokenizer, azCol, nCol, nCol, zExpr, nExpr, &pExpr
+ pTokenizer, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
);
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
sqlite3_result_error(context, "Error parsing expression", -1);
diff --git a/ext/fts3/fts3_hash.c b/ext/fts3/fts3_hash.c
index b7c3e8b5..57c59b58 100644
--- a/ext/fts3/fts3_hash.c
+++ b/ext/fts3/fts3_hash.c
@@ -30,7 +30,6 @@
#include
#include
-#include "sqlite3.h"
#include "fts3_hash.h"
/*
diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c
index b569eb13..23ef25c5 100644
--- a/ext/fts3/fts3_snippet.c
+++ b/ext/fts3/fts3_snippet.c
@@ -368,6 +368,7 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
int iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
+ assert( iFirst>=0 );
pPhrase->pHead = pCsr;
pPhrase->pTail = pCsr;
pPhrase->iHead = iFirst;
@@ -848,7 +849,7 @@ static int fts3MatchinfoSelectDoctotal(
a = sqlite3_column_blob(pStmt, 0);
a += sqlite3Fts3GetVarint(a, &nDoc);
- if( nDoc==0 ) return SQLITE_CORRUPT_VTAB;
+ if( nDoc==0 ) return FTS_CORRUPT_VTAB;
*pnDoc = (u32)nDoc;
if( paLen ) *paLen = a;
@@ -1409,7 +1410,7 @@ void sqlite3Fts3Offsets(
if( !pTerm ){
/* All offsets for this column have been gathered. */
- break;
+ rc = SQLITE_DONE;
}else{
assert( iCurrent<=iMinPos );
if( 0==(0xFE&*pTerm->pList) ){
@@ -1426,8 +1427,8 @@ void sqlite3Fts3Offsets(
"%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
);
rc = fts3StringAppend(&res, aBuffer, -1);
- }else if( rc==SQLITE_DONE ){
- rc = SQLITE_CORRUPT_VTAB;
+ }else if( rc==SQLITE_DONE && pTab->zContentTbl==0 ){
+ rc = FTS_CORRUPT_VTAB;
}
}
}
diff --git a/ext/fts3/fts3_test.c b/ext/fts3/fts3_test.c
index c5f72d84..72735f3d 100644
--- a/ext/fts3/fts3_test.c
+++ b/ext/fts3/fts3_test.c
@@ -19,6 +19,8 @@
#include
#include
+#ifdef SQLITE_TEST
+
/* Required so that the "ifdef SQLITE_ENABLE_FTS3" below works */
#include "fts3Int.h"
@@ -319,3 +321,4 @@ int Sqlitetestfts3_Init(Tcl_Interp *interp){
);
return TCL_OK;
}
+#endif /* ifdef SQLITE_TEST */
diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c
index c4ad6a5c..6494bb96 100644
--- a/ext/fts3/fts3_tokenizer.c
+++ b/ext/fts3/fts3_tokenizer.c
@@ -23,12 +23,7 @@
** * The FTS3 module is being built into the core of
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
-#include "sqlite3ext.h"
-#ifndef SQLITE_CORE
- SQLITE_EXTENSION_INIT1
-#endif
#include "fts3Int.h"
-
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
#include
diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c
index 36f2249e..2904a9ac 100644
--- a/ext/fts3/fts3_write.c
+++ b/ext/fts3/fts3_write.c
@@ -256,7 +256,7 @@ static int fts3SqlStmt(
/* 4 */ "DELETE FROM %Q.'%q_segdir'",
/* 5 */ "DELETE FROM %Q.'%q_docsize'",
/* 6 */ "DELETE FROM %Q.'%q_stat'",
-/* 7 */ "SELECT %s FROM %Q.'%q_content' AS x WHERE rowid=?",
+/* 7 */ "SELECT %s WHERE rowid=?",
/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1",
/* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
@@ -298,7 +298,7 @@ static int fts3SqlStmt(
if( eStmt==SQL_CONTENT_INSERT ){
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
}else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
- zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist, p->zDb, p->zName);
+ zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
}else{
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
}
@@ -341,7 +341,7 @@ static int fts3SelectDocsize(
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
rc = sqlite3_reset(pStmt);
- if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT_VTAB;
+ if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
pStmt = 0;
}else{
rc = SQLITE_OK;
@@ -409,17 +409,24 @@ static void fts3SqlExec(
** not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. It can
** still happen if the user reads data directly from the %_segments or
** %_segdir tables instead of going through FTS3 though.
+**
+** This reasoning does not apply to a content=xxx table.
*/
int sqlite3Fts3ReadLock(Fts3Table *p){
int rc; /* Return code */
sqlite3_stmt *pStmt; /* Statement used to obtain lock */
- rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0);
- if( rc==SQLITE_OK ){
- sqlite3_bind_null(pStmt, 1);
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
+ if( p->zContentTbl==0 ){
+ rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_null(pStmt, 1);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ }
+ }else{
+ rc = SQLITE_OK;
}
+
return rc;
}
@@ -780,6 +787,18 @@ static int fts3InsertData(
int rc; /* Return code */
sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */
+ if( p->zContentTbl ){
+ sqlite3_value *pRowid = apVal[p->nColumn+3];
+ if( sqlite3_value_type(pRowid)==SQLITE_NULL ){
+ pRowid = apVal[1];
+ }
+ if( sqlite3_value_type(pRowid)!=SQLITE_INTEGER ){
+ return SQLITE_CONSTRAINT;
+ }
+ *piDocid = sqlite3_value_int64(pRowid);
+ return SQLITE_OK;
+ }
+
/* Locate the statement handle used to insert data into the %_content
** table. The SQL for this statement is:
**
@@ -830,14 +849,16 @@ static int fts3InsertData(
** Remove all data from the FTS3 table. Clear the hash table containing
** pending terms.
*/
-static int fts3DeleteAll(Fts3Table *p){
+static int fts3DeleteAll(Fts3Table *p, int bContent){
int rc = SQLITE_OK; /* Return code */
/* Discard the contents of the pending-terms hash table. */
sqlite3Fts3PendingTermsClear(p);
- /* Delete everything from the %_content, %_segments and %_segdir tables. */
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0);
+ /* Delete everything from the shadow tables. Except, leave %_content as
+ ** is if bContent is false. */
+ assert( p->zContentTbl==0 || bContent==0 );
+ if( bContent ) fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0);
fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0);
fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
if( p->bHasDocsize ){
@@ -1145,7 +1166,7 @@ static int fts3SegReaderNext(
if( nPrefix<0 || nSuffix<=0
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
){
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
if( nPrefix+nSuffix>pReader->nTermAlloc ){
@@ -1175,7 +1196,7 @@ static int fts3SegReaderNext(
if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
){
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
return SQLITE_OK;
}
@@ -2125,12 +2146,18 @@ static void fts3SegWriterFree(SegmentWriter *pWriter){
static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){
sqlite3_stmt *pStmt;
int rc;
- rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid);
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- *pisEmpty = sqlite3_column_int(pStmt, 0);
+ if( p->zContentTbl ){
+ /* If using the content=xxx option, assume the table is never empty */
+ *pisEmpty = 0;
+ rc = SQLITE_OK;
+ }else{
+ rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid);
+ if( rc==SQLITE_OK ){
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ *pisEmpty = sqlite3_column_int(pStmt, 0);
+ }
+ rc = sqlite3_reset(pStmt);
}
- rc = sqlite3_reset(pStmt);
}
return rc;
}
@@ -2482,6 +2509,7 @@ int sqlite3Fts3SegReaderStep(
int isColFilter = (pCsr->pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER);
int isPrefix = (pCsr->pFilter->flags & FTS3_SEGMENT_PREFIX);
int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN);
+ int isFirst = (pCsr->pFilter->flags & FTS3_SEGMENT_FIRST);
Fts3SegReader **apSegment = pCsr->apSegment;
int nSegment = pCsr->nSegment;
@@ -2541,6 +2569,7 @@ int sqlite3Fts3SegReaderStep(
assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
if( nMerge==1
&& !isIgnoreEmpty
+ && !isFirst
&& (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
){
pCsr->nDoclist = apSegment[0]->nDoclist;
@@ -2606,12 +2635,24 @@ int sqlite3Fts3SegReaderStep(
}
pCsr->aBuffer = aNew;
}
- nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta);
- iPrev = iDocid;
- if( isRequirePos ){
- memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
- nDoclist += nList;
- pCsr->aBuffer[nDoclist++] = '\0';
+
+ if( isFirst ){
+ char *a = &pCsr->aBuffer[nDoclist];
+ int nWrite;
+
+ nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a);
+ if( nWrite ){
+ iPrev = iDocid;
+ nDoclist += nWrite;
+ }
+ }else{
+ nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta);
+ iPrev = iDocid;
+ if( isRequirePos ){
+ memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
+ nDoclist += nList;
+ pCsr->aBuffer[nDoclist++] = '\0';
+ }
}
}
@@ -2787,9 +2828,9 @@ static void fts3DecodeIntArray(
** a blob of varints.
*/
static void fts3InsertDocsize(
- int *pRC, /* Result code */
- Fts3Table *p, /* Table into which to insert */
- u32 *aSz /* Sizes of each column */
+ int *pRC, /* Result code */
+ Fts3Table *p, /* Table into which to insert */
+ u32 *aSz /* Sizes of each column, in tokens */
){
char *pBlob; /* The BLOB encoding of the document size */
int nBlob; /* Number of bytes in the BLOB */
@@ -2911,6 +2952,86 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
}
+/*
+** This function is called when the user executes the following statement:
+**
+** INSERT INTO () VALUES('rebuild');
+**
+** The entire FTS index is discarded and rebuilt. If the table is one
+** created using the content=xxx option, then the new index is based on
+** the current contents of the xxx table. Otherwise, it is rebuilt based
+** on the contents of the %_content table.
+*/
+static int fts3DoRebuild(Fts3Table *p){
+ int rc; /* Return Code */
+
+ rc = fts3DeleteAll(p, 0);
+ if( rc==SQLITE_OK ){
+ u32 *aSz = 0;
+ u32 *aSzIns = 0;
+ u32 *aSzDel = 0;
+ sqlite3_stmt *pStmt = 0;
+ int nEntry = 0;
+
+ /* Compose and prepare an SQL statement to loop through the content table */
+ char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+ sqlite3_free(zSql);
+ }
+
+ if( rc==SQLITE_OK ){
+ int nByte = sizeof(u32) * (p->nColumn+1)*3;
+ aSz = (u32 *)sqlite3_malloc(nByte);
+ if( aSz==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(aSz, 0, nByte);
+ aSzIns = &aSz[p->nColumn+1];
+ aSzDel = &aSzIns[p->nColumn+1];
+ }
+ }
+
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
+ int iCol;
+ rc = fts3PendingTermsDocid(p, sqlite3_column_int64(pStmt, 0));
+ aSz[p->nColumn] = 0;
+ for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){
+ const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
+ rc = fts3PendingTermsAdd(p, z, iCol, &aSz[iCol]);
+ aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
+ }
+ if( p->bHasDocsize ){
+ fts3InsertDocsize(&rc, p, aSz);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3_finalize(pStmt);
+ pStmt = 0;
+ }else{
+ nEntry++;
+ for(iCol=0; iCol<=p->nColumn; iCol++){
+ aSzIns[iCol] += aSz[iCol];
+ }
+ }
+ }
+ if( p->bHasStat ){
+ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry);
+ }
+ sqlite3_free(aSz);
+
+ if( pStmt ){
+ int rc2 = sqlite3_finalize(pStmt);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }
+ }
+
+ return rc;
+}
+
/*
** Handle a 'special' INSERT of the form:
**
@@ -2928,6 +3049,8 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
return SQLITE_NOMEM;
}else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
rc = fts3DoOptimize(p, 0);
+ }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){
+ rc = fts3DoRebuild(p);
#ifdef SQLITE_TEST
}else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
p->nNodeSize = atoi(&zVal[9]);
@@ -3008,6 +3131,7 @@ int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
Fts3PhraseToken *pPT = pDef->pToken;
if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
+ && (pPT->bFirst==0 || iPos==0)
&& (pPT->n==nToken || (pPT->isPrefix && pPT->nz, pPT->n))
){
@@ -3099,14 +3223,18 @@ static int fts3DeleteByRowid(
/* Deleting this row means the whole table is empty. In this case
** delete the contents of all three tables and throw away any
** data in the pendingTerms hash table. */
- rc = fts3DeleteAll(p);
+ rc = fts3DeleteAll(p, 1);
*pnDoc = *pnDoc - 1;
}else{
sqlite3_int64 iRemove = sqlite3_value_int64(pRowid);
rc = fts3PendingTermsDocid(p, iRemove);
fts3DeleteTerms(&rc, p, pRowid, aSzDel);
- fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
- if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
+ if( p->zContentTbl==0 ){
+ fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
+ if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
+ }else{
+ *pnDoc = *pnDoc - 1;
+ }
if( p->bHasDocsize ){
fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
}
@@ -3129,7 +3257,6 @@ int sqlite3Fts3UpdateMethod(
Fts3Table *p = (Fts3Table *)pVtab;
int rc = SQLITE_OK; /* Return Code */
int isRemove = 0; /* True for an UPDATE or DELETE */
- sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
u32 *aSzIns = 0; /* Sizes of inserted documents */
u32 *aSzDel; /* Sizes of deleted documents */
int nChng = 0; /* Net change in number of documents */
@@ -3167,7 +3294,7 @@ int sqlite3Fts3UpdateMethod(
** detect the conflict and return SQLITE_CONSTRAINT before beginning to
** modify the database file.
*/
- if( nArg>1 ){
+ if( nArg>1 && p->zContentTbl==0 ){
/* Find the value object that holds the new rowid value. */
sqlite3_value *pNewRowid = apVal[3+p->nColumn];
if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){
@@ -3212,19 +3339,21 @@ int sqlite3Fts3UpdateMethod(
assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
isRemove = 1;
- iRemove = sqlite3_value_int64(apVal[0]);
}
/* If this is an INSERT or UPDATE operation, insert the new record. */
if( nArg>1 && rc==SQLITE_OK ){
if( bInsertDone==0 ){
rc = fts3InsertData(p, apVal, pRowid);
- if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT_VTAB;
+ if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){
+ rc = FTS_CORRUPT_VTAB;
+ }
}
- if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
+ if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
rc = fts3PendingTermsDocid(p, *pRowid);
}
if( rc==SQLITE_OK ){
+ assert( p->iPrevDocid==*pRowid );
rc = fts3InsertTerms(p, apVal, aSzIns);
}
if( p->bHasDocsize ){
diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c
index 2375069e..884482ea 100644
--- a/ext/rtree/rtree.c
+++ b/ext/rtree/rtree.c
@@ -1268,7 +1268,8 @@ static int rtreeFilter(
rc = SQLITE_NOMEM;
}else{
memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc);
- assert( (idxStr==0 && argc==0) || (int)strlen(idxStr)==argc*2 );
+ assert( (idxStr==0 && argc==0)
+ || (idxStr && (int)strlen(idxStr)==argc*2) );
for(ii=0; iiaConstraint[ii];
p->op = idxStr[ii*2];
@@ -1569,7 +1570,10 @@ static int ChooseLeaf(
float fMinGrowth = 0.0;
float fMinArea = 0.0;
+#if VARIANT_RSTARTREE_CHOOSESUBTREE
float fMinOverlap = 0.0;
+ float overlap;
+#endif
int nCell = NCELL(pNode);
RtreeCell cell;
@@ -1601,7 +1605,6 @@ static int ChooseLeaf(
int bBest = 0;
float growth;
float area;
- float overlap = 0.0;
nodeGetCell(pRtree, pNode, iCell, &cell);
growth = cellGrowth(pRtree, &cell, pCell);
area = cellArea(pRtree, &cell);
@@ -1609,6 +1612,8 @@ static int ChooseLeaf(
#if VARIANT_RSTARTREE_CHOOSESUBTREE
if( ii==(pRtree->iDepth-1) ){
overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell);
+ }else{
+ overlap = 0.0;
}
if( (iCell==0)
|| (overlap>tclsqlite3.c
cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
+sqlite3.c-debug: target_source $(TOP)/tool/mksqlite3c.tcl
+ tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros
+ echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
+ cat sqlite3.c >>tclsqlite3.c
+ echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
+ echo '#line 1 "tclsqlite.c"' >>tclsqlite3.c
+ cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
+
+sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl
+ tclsh $(TOP)/tool/split-sqlite3c.tcl
+
fts2amal.c: target_source $(TOP)/ext/fts2/mkfts2amal.tcl
tclsh $(TOP)/ext/fts2/mkfts2amal.tcl
@@ -417,7 +432,7 @@ tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
# Rules to build opcodes.c and opcodes.h
#
opcodes.c: opcodes.h $(TOP)/mkopcodec.awk
- sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c
+ $(NAWK) -f $(TOP)/mkopcodec.awk opcodes.h >opcodes.c
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
cat parse.h $(TOP)/src/vdbe.c | \
@@ -506,6 +521,16 @@ tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a
$(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \
$(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)
+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 >> $@
+ echo "static const char *tclsh_main_loop(void){" >> $@
+ echo "static const char *zMainloop = " >> $@
+ $(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@
+ echo "; return zMainloop; }" >> $@
+
+sqlite3_analyzer$(EXE): sqlite3_analyzer.c
+ $(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB)
# Rules to build the 'testfixture' application.
#
@@ -548,16 +573,6 @@ threadtest3$(EXE): sqlite3.o $(TOP)/test/threadtest3.c $(TOP)/test/tt3_checkpoin
threadtest: threadtest3$(EXE)
./threadtest3$(EXE)
-sqlite3_analyzer$(EXE): $(TOP)/src/tclsqlite.c sqlite3.c $(TESTSRC) \
- $(TOP)/tool/spaceanal.tcl
- $(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl \
- >spaceanal_tcl.h
- $(TCCX) $(TCL_FLAGS) -DTCLSH=2 $(TESTFIXTURE_FLAGS) \
- -DSQLITE_TEST=1 -DSQLITE_PRIVATE="" \
- $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \
- -o sqlite3_analyzer$(EXE) \
- $(LIBTCL) $(THREADLIB)
-
TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO)
$(TEST_EXTENSION): $(TOP)/src/test_loadext.c
$(MKSHLIB) $(TOP)/src/test_loadext.c -o $(TEST_EXTENSION)
@@ -565,6 +580,13 @@ $(TEST_EXTENSION): $(TOP)/src/test_loadext.c
extensiontest: testfixture$(EXE) $(TEST_EXTENSION)
./testfixture$(EXE) $(TOP)/test/loadext.test
+# 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.o
+ nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0
+
# Standard install and cleanup targets
#
@@ -574,10 +596,16 @@ install: sqlite3 libsqlite3.a sqlite3.h
mv sqlite3.h /usr/include
clean:
- rm -f *.o sqlite3 libsqlite3.a sqlite3.h opcodes.*
- rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h
+ rm -f *.o sqlite3 sqlite3.exe libsqlite3.a sqlite3.h opcodes.*
+ rm -f lemon lemon.exe lempar.c parse.* sqlite*.tar.gz
+ rm -f mkkeywordhash mkkeywordhash.exe keywordhash.h
rm -f $(PUBLISH)
rm -f *.da *.bb *.bbg gmon.out
rm -rf tsrc target_source
rm -f testloadext.dll libtestloadext.so
+ rm -f amalgamation-testfixture amalgamation-testfixture.exe
+ rm -f fts3-testfixture fts3-testfixture.exe
+ rm -f testfixture testfixture.exe
+ rm -f threadtest3 threadtest3.exe
rm -f sqlite3.c fts?amal.c tclsqlite3.c
+ rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
diff --git a/manifest b/manifest
index b2251f24..307b0c39 100644
--- a/manifest
+++ b/manifest
@@ -1,12 +1,12 @@
-C Release\scandidate\s3.7.7.1.
-D 2011-06-28T17:39:05.200
+C Version\s3.7.9
+D 2011-11-01T00:52:41.132
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
-F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e
+F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
-F Makefile.msc 11082f65b452b908d93013292c17850378c39284
-F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151
+F Makefile.msc dcad80fa69f17d46fe6778ba873fc108ca16298d
+F Makefile.vxworks 1deb39c8bb047296c30161ffa10c1b5423e632f9
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
-F VERSION 5d587aa6adf86fd587768fe736359bd9f5e43890
+F VERSION bb37c274b503bbe73f00ea4f374eb817cba4b171
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
@@ -23,10 +23,10 @@ F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 405a958bdb3af382a809dccb08a44694923ddd61
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
-F configure b8e6049719c5f649670388236e2253183243b873 x
+F configure 806c06aef5895860da49600ce098dbe4d5a8435c x
F configure.ac 298a759c086e72c013da459c2aec02a104f4224f
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
-F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
+F doc/lemon.html 3091574143dd3415669b6745843ff8d011d33549
F doc/pager-invariants.txt 870107036470d7c419e93768676fae2f8749cf9e
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1
@@ -59,32 +59,33 @@ F ext/fts2/fts2_tokenizer.c 26e993a00b2bd5b6e73c155597361710b12ffe25
F ext/fts2/fts2_tokenizer.h a7e46462d935a314b2682287f12f27530a3ee08e
F ext/fts2/fts2_tokenizer1.c 0123d21078e053bd98fd6186c5c6dc6d67969f2e
F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
+F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c ca776037493d0081da70a6afc0df80f5ce347cb7
+F ext/fts3/fts3.c 246ef2d0cef67517d156d39c9247cd6c432f0d79
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h fa493ccbad78a2c99ad1c984f651c0c202e68536
+F ext/fts3/fts3Int.h def7a900f98c5ab5fa4772e922bfa219d5097f05
F ext/fts3/fts3_aux.c 0ebfa7b86cf8ff6a0861605fcc63b83ec1b70691
-F ext/fts3/fts3_expr.c 23791de01b3a5d313d76e02befd2601d4096bc2b
-F ext/fts3/fts3_hash.c aad95afa01cf2a5ffaa448e4b0ab043880cd1efb
+F ext/fts3/fts3_expr.c f5df26bddf46a5916b2a5f80c4027996e92b7b15
+F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
F ext/fts3/fts3_icu.c 6c8f395cdf9e1e3afa7fadb7e523dbbf381c6dfa
F ext/fts3/fts3_porter.c 8d946908f4812c005d3d33fcbe78418b1f4eb70c
-F ext/fts3/fts3_snippet.c 58b2ba2b934c1e2a2f6ac857d7f3c7e1a14b4532
+F ext/fts3/fts3_snippet.c 1f9ee6a8e0e242649645968dcec4deb253d86c2a
F ext/fts3/fts3_term.c a5457992723455a58804cb75c8cbd8978db5c2ef
-F ext/fts3/fts3_test.c c0aae3219df989d3e827d07846097adf8cb09945
-F ext/fts3/fts3_tokenizer.c 6089986ebcfc19d4b7aabd2b92773368efa4354f
+F ext/fts3/fts3_test.c 24fa13f330db011500acb95590da9eee24951894
+F ext/fts3/fts3_tokenizer.c 9ff7ec66ae3c5c0340fa081958e64f395c71a106
F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
F ext/fts3/fts3_tokenizer1.c 0dde8f307b8045565cf63797ba9acfaff1c50c68
-F ext/fts3/fts3_write.c 194829c8fd024a448fc899e5ff02a8ed06595529
+F ext/fts3/fts3_write.c c097228bff4d33c6b8a270c9717b9f8339068776
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
F ext/icu/icu.c eb9ae1d79046bd7871aa97ee6da51eb770134b5a
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/rtree.c b431c54d1ed05f04f2987e8a4fbb931acb40c312
+F ext/rtree/rtree.c 692e9192d148f318b3dca9f744600346a175eedd
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 28e1b8da4da98093ce3210187434dd760a8d89d8
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -104,11 +105,11 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
-F main.mk d799fb600383cee11fed58876a7cccb749dd2614
+F main.mk ac48970ca7506c9034f5c7b2212111fbeb0a1aaa
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
-F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1
+F mkopcodec.awk f6fccee29e68493bfd90a2e0466ede5fa94dd2fc
F mkopcodeh.awk 29b84656502eee5f444c3147f331ee686956ab0e
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F publish.sh 313c5b2425f2cf5e547db7549a9796acc4508f22
@@ -118,90 +119,90 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c ac80a0f31189f8b4a524ebf661e47e84536ee7f5
-F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a
+F src/analyze.c 5a1db16a651ce6310c8b046b2cbb736e030e14b9
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
-F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
+F src/backup.c 4368158da74d4711888e03264105c5c527d76caf
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
-F src/btree.c 8c46f0ab69ad9549c75a3a91fed87abdaa743e2f
+F src/btree.c 32199e2d939233ade25340eaba450f818b37c079
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
-F src/build.c 5a428625d21ad409514afb40ad083bee25dd957a
+F src/build.c 8af67a08a852ff4c63701963cb1ab7166f577814
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
-F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
-F src/date.c d3c11de76392ea62637bfac0f4655889fc2f5a85
-F src/delete.c 4925f9121525fc871f5d8d13c1f7dcc91abb38bb
-F src/expr.c ab46ab0f0c44979a8164ca31728d7d10ae5e8106
+F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33
+F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
+F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8
+F src/expr.c fbf116f90cabc917ae50bba24a73a0b55519a0c8
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
-F src/fkey.c 9fabba17a4d4778dc660f0cb9d781fc86d7b9d41
-F src/func.c 59bb046d7e3df1ab512ac339ccb0a6f996a17cb7
-F src/global.c c70a46f28680f8d7c097dbc0430ccf3b932e90b0
+F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
+F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9
+F src/global.c e230227de13601714b29f9363028514aada5ae2f
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c 3eea5a53d2644116fb865afaa4699fabe62b441c
+F src/insert.c ca18783512323f74aaf4ee74b46ffd75ec80d031
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
-F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
-F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
-F src/main.c fa654e1802e14a5f6c09c37971c3b69c1001d9c8
+F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
+F src/loadext.c d0d2022a5a07274d408820b978b9e549189d314f
+F src/main.c df06f5229b8046f85dde253dfd7fe35ae9e4902e
F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
-F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
+F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
F src/memjournal.c 0ebce851677a7ac035ba1512a7e65851b34530c6
F src/mutex.c 6949180803ff05a7d0e2b9334a95b4fb5a00e23f
-F src/mutex.h fe2ef5e1c4dae531d5a544f9241f19c56d26803d
+F src/mutex.h 2a79e0c10c26412546b501ee0f3d92b42decf63e
F src/mutex_noop.c d5cfbca87168c661a0b118cd8e329a908e453151
F src/mutex_os2.c 882d735098c07c8c6a5472b8dd66e19675fe117f
F src/mutex_unix.c b4f4e923bb8de93ec3f251fadb50855f23df9579
F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
-F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
+F src/os.c 5d9b02782ed36345348d6fe21d7762ed3a9cfd2a
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
-F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
+F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
-F src/os_unix.c 07acbb3e074e52b48a4248c06f66c9a91db1a0ce
-F src/os_win.c eafcd6b91cf204a7ef29ac1ef2a1b7132e132e58
-F src/pager.c 120550e7ef01dafaa2cbb4a0528c0d87c8f12b41
-F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
+F src/os_unix.c ddda0b1c5ae536669634d7bff31b3f8f4d654866
+F src/os_win.c 49d418916428a59d773f39993db0ecde56ab4c37
+F src/pager.c ad62daa0c21e27ae332b3ceb4f579a2a97046ddc
+F src/pager.h 9f81b08efb06db4ba8be69446e10b005c351373d
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 49e718c095810c6b3334e3a6d89970aceaddefce
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
-F src/pcache1.c 912bd5687d6df344698d8e69560f347b6e21c18a
-F src/pragma.c ebcd20f1e654f5cb3aeef864ed69c4697719fbaa
+F src/pcache1.c 24f5e85a78514584b46190260ba7ab0a66312197
+F src/pragma.c da8ef96b3eec351e81e0061c39810e548bcc96d7
F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4
-F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
+F src/printf.c 03104cbff6959ff45df69dc9060ba6212f60a869
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
-F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
+F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
-F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
-F src/shell.c 0e0173b3e79d956368013e759f084caa7995ecb1
-F src/sqlite.h.in 4b7255c10d39c5faf089dbd29cde7c367ff39f1f
-F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
-F src/sqliteInt.h 7b72f7c6929757c0678d94524dbc7e7e3d6dc398
+F src/select.c 80f3ac44a8514b1d107b80f5df4a424ae059d2b6
+F src/shell.c f0ab793261ab045a0b8c47fa2707e8a894d2898f
+F src/sqlite.h.in ff950aef7b378963c67add42dda5d446a0b7330e
+F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
+F src/sqliteInt.h c74457cd2c4bd77683bac76e698bf2ec2d3e13f9
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
-F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
+F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
-F src/tclsqlite.c 5db825be61708b1a2b3f8f6e185e9b753829acef
-F src/test1.c 8eef932f1024f1076a8adb8a6f5d9c5267c9e969
+F src/tclsqlite.c de581e2e71f5e7f98366156afad83b4742ac6fe0
+F src/test1.c 0f41b7c67719207a5de24b009e172c4dcf189827
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
F src/test5.c e1a19845625144caf038031234a12185e40d315c
-F src/test6.c c7256cc21d2409486d094277d5b017e8eced44ba
+F src/test6.c 3191b4ab964a144230ff9ef96c093520375c7b2a
F src/test7.c 2e0781754905c8adc3268d8f0967e7633af58843
-F src/test8.c 6b1d12912a04fe6fca8c45bb9c3ea022f4352228
+F src/test8.c 99f70341d6ec480313775127f4cd14b4a47db557
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
-F src/test_config.c 791a9acbf9a695cf9c12ff6bbe874dfde9a8c5f3
+F src/test_config.c bc8826296a7b3a86eeaba1ac2af5551d1c20c35b
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
@@ -212,83 +213,84 @@ F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
-F src/test_malloc.c 7ca7be34e0e09ef0ed6619544552ed95732e41f6
-F src/test_multiplex.c a7457a1ac46964b7f897d75ecfd447410ec067e6
+F src/test_malloc.c 8d416f29ad8573f32601f6056c9d2b17472e9ad5
+F src/test_multiplex.c 3fc368022c46fe44ec22c5e1ed727223a54a6a1d
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
F src/test_osinst.c 62b0b8ef21ce754cc94e17bb42377ed8795dba32
F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
-F src/test_quota.c cc4f67e12558a252ea4a11720be268348f4b1595
-F src/test_rtree.c 30c981837445a4e187ee850a49c4760d9642f7c3
+F src/test_quota.c a391c866217e92986c6f523f05b08aa6956c8419
+F src/test_rtree.c 6d06306e29946dc36f528a3a2cdc3add794656f1
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
-F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
+F src/test_stat.c 69de4361c7a69fc1136d31ab7144408cd00805c7
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
-F src/test_syscall.c 162c4ec0137a549c009bb9ecab550527743cfc5d
+F src/test_syscall.c a992d8c80ea91fbf21fb2dd570db40e77dd7e6ae
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
-F src/test_thread.c fe9a7803fc1d69cccb60f016f28c1cedf2d9fcfa
-F src/test_vfs.c 956cb3f5cbd2a0d09129540e615bb0fb761c083d
+F src/test_thread.c 35022393dd54d147b998b6b7f7e945b01114d666
+F src/test_vfs.c b0baec983bd6f872715a4b44c8f39104fec333af
F src/test_vfstrace.c 0b884e06094a746da729119a2cabdc7aa790063d
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c c819d9f72168a035d545a5bdafe9b085b20df705
-F src/trigger.c c836a6caac16ba96611558922106858f6ca3d6bf
-F src/update.c 80d77311d91ebc06b27149e75701f1b3e9356622
-F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0
-F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
-F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
-F src/vdbe.c 50b5b4ef29d928a4f60905f820ee1ab2f8ced29f
-F src/vdbe.h 5cf09e7ee8a3f7d93bc51f196a96550786afe7a1
-F src/vdbeInt.h ad84226cc0adcb1185c22b70696b235a1678bb45
-F src/vdbeapi.c 2f908c65337b16c6249ab378d477e74492cf759b
-F src/vdbeaux.c 4d100407e3c72e163854aff8903d19d5ecdf46c0
-F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
-F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
+F src/trigger.c 1cfb80e2290ef66ea89cb4e821caae65a02c0d56
+F src/update.c 25e046a8f69d5e557aabde2000487b8545509d8d
+F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
+F src/util.c df83983bd57057df4951516880066b42b7055269
+F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa
+F src/vdbe.c 326994a64a9a08853122200dc9f62cb96b8f0831
+F src/vdbe.h f0725ee997db869ecae5bb70a71612aabeca7755
+F src/vdbeInt.h 9498fc98a2c9e349a4ef13455ff5a3e898f40176
+F src/vdbeapi.c 4dbba7f94f127f6ea8d2d0505ee1f98e5ffbf546
+F src/vdbeaux.c a950e34449a508d48d90475acc287943a4094f3a
+F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
+F src/vdbemem.c 2fc78b3e0fabcc1eaa23cd79dd2e30e6dcfe1e56
+F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
-F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
-F src/wal.c 0c70ad7b1cac6005fa5e2cbefd23ee05e391c290
+F src/vtab.c e9318d88feac85be8e27ee783ac8f5397933fc8a
+F src/wal.c 9658df8d404b82e6b2d40fd05944463214e2d935
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
-F test/8_3_names.test b93687beebd17f6ebf812405a6833bae5d1f4199
+F src/where.c 7c85f4c93058e27100d404f0777aaeb0d1b296ae
+F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
-F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
-F test/alter.test a3f570072b53d7c0fe463bab3f5affa8e113c487
-F test/alter2.test 75f731508f1bf27ba09a6075c66cd02216ba464b
-F test/alter3.test 8677e48d95536f7a6ed86a1a774744dadcc22b07
-F test/alter4.test 1e5dd6b951e9f65ca66422edff02e56df82dd403
+F test/all.test 52fc8dee494092031a556911d404ca30a749a30b
+F test/alter.test 66f5818f9848c4f22de022a345fae25bcd30f8fb
+F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
+F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
+F test/alter4.test b2debc14d8cbe4c1d12ccd6a41eef88a8c1f15d5
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
-F test/analyze.test c8cb89e8736336f1f0646c8123e6028a14c7b55e
-F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
-F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
+F test/analyze.test f8ab7d15858b4093b06caf5e57e2a5ff7104bdae
+F test/analyze3.test c3c7f6c3951900c188cf94b2d5ee3246d6b3ff89
F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
-F test/analyze5.test 1de8d66b11aae5a1453aa042d62e834a476bac9c
-F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290
-F test/analyze7.test 5508e7828164ea0b518ed219bed7320a481863d4
-F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
-F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
-F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
+F test/analyze5.test 713354664c5ff1853ab2cbcb740f0cf5cb7c802e
+F test/analyze6.test bd3625806a5ee6f7bef72d06295bd319f0290af2
+F test/analyze7.test d3587aa5af75c9048d031b94fceca2534fa75d1d
+F test/analyze8.test 4ca170de2ba30ccb1af2c0406803db72262f9691
+F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
+F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
+F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
-F test/async5.test f3592d79c84d6e83a5f50d3fd500445f7d97dfdf
-F test/attach.test 2bb09073d7d5499127db00f50780766dcea913e1
-F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
-F test/attach3.test bd9830bc3a0d22ed1310c9bff6896927937017dc
-F test/attach4.test 31f9eb0ca7bdbc393cc4657b877903a226a83d4b
-F test/attachmalloc.test 1d5b821a676f7bf0b00d87cc106b78966789ba57
-F test/auth.test b047105c32da7db70b842fd24056723125ecc2ff
+F test/async5.test 0dd8701bd588bf6e70c2557a22ae3f22b2567b4c
+F test/attach.test 0e6f8de2589f11a5f474ef57fe5af2877e61c0e8
+F test/attach2.test e54436ed956d3d88bdee61221da59bf3935a0966
+F test/attach3.test d89ccfe4fe6e2b5e368d480fcdfe4b496c54cf4e
+F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
+F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
+F test/auth.test 304e82f31592820d3bde26ab6b75deaa123e1a6f
F test/auth2.test 270baddc8b9c273682760cffba6739d907bd2882
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
-F test/autoinc.test 85ef3180a737e6580086a018c09c6f1a52759b46
-F test/autoindex1.test 860fc83f4fefb0c68ad062afc3ff43faa1534fc4
-F test/autovacuum.test bb7c0885e6f8f1d633045de48f2b66082162766d
-F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6
+F test/autoinc.test bd30d372d00045252f6c2e41b5f41455e1975acf
+F test/autoindex1.test 058d0b331ae6840a61bbee910d8cbae27bfd5991
+F test/autovacuum.test fcaf4616ae5bb18098db1cb36262565e5c841c3c
+F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
-F test/backcompat.test 0f23ff8d516acdf42f3d866a66d85306de2d02bc
-F test/backup.test 004d3b78bffd990741ab50133ed4347c25c172b1
-F test/backup2.test b7c69f937c912e85ac8a5dbd1e1cf290302b2d49
-F test/backup_ioerr.test 1f012e692f42c0442ae652443258f70e9f20fa38
+F test/backcompat.test 71eeb75ea567c060774c4e8db4b0e703f21c7677
+F test/backup.test 6970614b002b056ae5bab5b76559905e02b6f0b2
+F test/backup2.test b4966934b2dc10a9a6546114566ea69b34a5185e
+F test/backup_ioerr.test 40d208bc9224b666ee3ed423f49bc9062a36a9d0
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
@@ -310,9 +312,9 @@ F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test 754baab2f18089fc9bcba7afaeb4dc907c6c6de2
F test/capi2.test 835d4cee9f542ea50fa8d01f3fe6de80b0627360
-F test/capi3.test 5c1ea6c940f2d7c4d5af8ef1ec2f92a267d2e37a
+F test/capi3.test 7200dff6acb17b9a4b6f9918f554eaae04968ddd
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
-F test/capi3c.test bea67403a5e37a4b33230ee4723e315a2ffb31e7
+F test/capi3c.test ccf0acf045dbacd09f6229aa4efed670aaba76a9
F test/capi3d.test cd36571f014f34bdc4421967f6453cbb597d5d16
F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
@@ -322,88 +324,92 @@ F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04
F test/collate2.test 04cebe4a033be319d6ddbb3bbc69464e01700b49
F test/collate3.test d28d2cfab2c3a3d4628ae4b2b7afc9965daa3b4c
F test/collate4.test 3d3f123f83fd8ccda6f48d617e44e661b9870c7d
-F test/collate5.test fe0f43c4740d7b71b959cac668d19e42f2e06e4d
+F test/collate5.test 67f1d3e848e230ff4802815a79acb0a8b5e69bd7
F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907
-F test/collate7.test fac8db7aac3978466c04ae892cc74dcf2bc031aa
+F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868
F test/collate8.test df26649cfcbddf109c04122b340301616d3a88f6
F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/colmeta.test 087c42997754b8c648819832241daf724f813322
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
F test/conflict.test cabc41f7616675df71b4fddabca3bd5d9221915a
-F test/corrupt.test 1a5bef8b2d178859af69814ecedcd37219a89968
-F test/corrupt2.test 808a28d0ca3b97e9aa8c91cd2b485ea2700b76d1
-F test/corrupt3.test e3006aaf579d2ed7f1b94bf4cc695d3c784fa5af
+F test/corrupt.test 4aabd06cff3fe759e3e658bcc17b71789710665e
+F test/corrupt2.test 9c0ab4becd50e9050bc1ebb8675456a4e5587bf0
+F test/corrupt3.test 889d7cdb811800303aa722d7813fe8a4299cf726
F test/corrupt4.test b963f9e01e0f92d15c76fb0747876fd4b96dc30a
F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff
F test/corrupt6.test 4e4161aef1f30b9f34582bb4142334b7f47eacae
F test/corrupt7.test a90caf89c7d7cb7893ea4d92529bd0c129317ee4
F test/corrupt8.test 48eb37ffb9a03bceada62219e2bd4c92f4b0cb75
-F test/corrupt9.test fad0bc26a5c972580a8d763c62f24094f4e8ef25
-F test/corruptA.test 856ea7a2eb5c1c767abbdf02679ac6cb158e4643
-F test/corruptB.test 44133515cf46c4d7bba691e3bcfa478080413af0
-F test/corruptC.test 483aa35dadfd96bdf549e38d75ffc2942576477e
-F test/corruptD.test 63a449a3146b460231535d04a409d14ce71795ad
-F test/corruptE.test 7290b61145d954be549340e462ca84826d8a31a3
+F test/corrupt9.test 959179e68dc0b7b99f424cf3e0381c86dcdd0112
+F test/corruptA.test fafa652aa585753be4f6b62ff0bb250266eaf7ce
+F test/corruptB.test 20d4a20cbed23958888c3e8995b424a47223d647
+F test/corruptC.test 62a767fe64acb1975f58cc6171192839c783edbb
+F test/corruptD.test 99b1999dbfa7cc04aaeac9d695a2445d4e7c7458
+F test/corruptE.test 1b9eb20a8711251ce57b44a257e241085b39b52d
F test/count.test 454e1ce985c94d13efeac405ce54439f49336163
-F test/crash.test 1b6ac8410689ff78028887f445062dc897c9ac89
+F test/crash.test 519dc29f6fea151f015a23236e555239353946eb
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
-F test/crash3.test 776f9363554c029fcce71d9e6600fa0ba6359ce7
-F test/crash4.test 02ff4f15c149ca1e88a5c299b4896c84d9450c3b
-F test/crash5.test 80a2f7073381837fc082435c97df52a830abcd80
-F test/crash6.test 9c730cf06335003cb1f5cfceddacd044155336e0
-F test/crash7.test e20a7b9ee1d16eaef7c94a4cb7ed2191b4d05970
-F test/crash8.test 76b95451933fe172ce8e26bff22d5c663c8ae473
+F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
+F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
+F test/crash5.test 69226a1b948d8961395b7ad2a1df084c212ce8cf
+F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
+F test/crash7.test 6c6a369af266af2ef50ab34df8f94d719065e2c1
+F test/crash8.test 38767cb504bbe491de6be4a7006b154973a2309f
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
-F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272
+F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test a18a2ce81add84b17b06559e82ad7bb91bc6ddff
-F test/dbstatus.test 175b088308f2ce3f7afb8208f25c10878ee05921
+F test/dbstatus.test 9eb484ba837c6f3f9bbcaecc29e6060a8c3ba6d2
+F test/dbstatus2.test dc57b0d9610851c0ff58a8e1b5b191678398b72a
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
-F test/delete.test f7629d9eb245dfca170169cc5c7a735dec34aeb4
+F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
-F test/descidx1.test b1353c1a15cfbee97b13a1dcedaf0fe78163ba6a
+F test/descidx1.test 533dcbda614b0463b0ea029527fd27e5a9ab2d66
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test fe720e8b37d59f4cef808b0bf4e1b391c2e56b6f
-F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb
+F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
+F test/distinct.test df5b11ad606439129c88720a86787bc9ca181f31
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_createtable.test 4771686a586b6ae414f927c389b2c101cc05c028
F test/e_delete.test e2ae0d3fce5efd70fef99025e932afffc5616fab
F test/e_droptrigger.test ddd4b28ed8a3d81bd5153fa0ab7559529a2ca03a
F test/e_dropview.test b347bab30fc8de67b131594b3cd6f3d3bdaa753d
-F test/e_expr.test 71b55f90c9336ecec5a99641679036931260c754
+F test/e_expr.test d93ccded2409c66637dc1649a02f169e041b63d8
F test/e_fkey.test 38039b840ab19331000b0f0eb1d82baa7208a67a
-F test/e_fts3.test 75bb0aee26384ef586165e21018a17f7cd843469
+F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test 76d4bb5da9b28014d515d91ffe29a79a1e99f2bc
F test/e_reindex.test a064f0878b8f848fbca38f1f61f82f15a3000c64
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
-F test/e_select.test 7ac53674e822d4d77bbb4a9a4aaefa5fdc9e493f
+F test/e_select.test 8d7fac7a268eaeb80b9a7ba7964505b9d30f5458
F test/e_select2.test 5c3d3da19c7b3e90ae444579db2b70098599ab92
F test/e_update.test b926341a65955d69a6375c9eb4fd82e7089bc83a
F test/e_uri.test 6f35b491f80dac005c8144f38b2dfb4d96483596
F test/e_vacuum.test 6c09c2af7f2f140518f371c5342100118f779dcf
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
-F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
-F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
-F test/enc4.test b145fa25feb56ea1d51a5bc43ca268c0cf691a67
+F test/enc2.test 796c59832e2b9a52842f382ffda8f3e989db03ad
+F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
+F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test f14fadd76da53405e9885e2431cacf7191d83cdb
+F test/errmsg.test 3bb606db9d040cc6854459f8f5e5a2bcd9b7fd2a
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
-F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
-F test/exclusive2.test 343d55130c12c67b8bf10407acec043a6c26c86b
+F test/exclusive.test a1b324cb21834a490cd052d409d34789cfef57cb
+F test/exclusive2.test 372be98f6de44dd78734e364b7b626ea211761a6
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
-F test/exists.test 5e2d64b4eb5a9d08876599bdae2e1213d2d12e2a
+F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
-F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
-F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
-F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c
+F test/fallocate.test b5d34437bd7ab01d41b1464b8117aefd4d32160e
+F test/filectrl.test 4eb0178956ca25a756e6d79711a90fec7157b454
+F test/filefmt.test ffa17b5aebc3eb4b1e3be1ccb5ee906ffbd97f6e
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
F test/fkey2.test 080969fe219b3b082b0e097ac18c6af2e5b0631f
F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e
F test/fkey4.test c6c8f9f9be885f95c85c7bceb26f243ad906fd49
-F test/fkey_malloc.test a5ede29bd2f6e56dea78c3d43fb86dd696c068c8
+F test/fkey_malloc.test c3a12acd053c976de09036498eef09b83afa4a80
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
+F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
F test/fts1b.test 5d8a01aefbecc8b7442b36c94c05eb7a845462d5
F test/fts1c.test 85a525ce7428907469b4cce13d5563ce542ce64c
@@ -411,12 +417,12 @@ F test/fts1d.test a73deace5c18df4a549b12908bade4f05dcf1a2f
F test/fts1e.test 77244843e925560b5a0b70069c3e7ab62f181ed2
F test/fts1f.test 2d6cb10d8b7a4e6edc321bbdb3982f1f48774714
F test/fts1i.test 6bfe08cdfdced063a39a50c8601da65e6274d879
-F test/fts1j.test e4c0ffcd0ba2adce09c6b7b43ffd0749b5fda5c7
+F test/fts1j.test e3797475796043a161e348c46a309664cac83f7f
F test/fts1k.test 65d3b41487b9f738d11b0f00eca375c0ca6bd970
F test/fts1l.test 15c119ed2362b2b28d5300c0540a6a43eab66c36
F test/fts1m.test 2d9ca67b095d49f037a914087cc0a61e89da4f0c
F test/fts1n.test a2317dcd27b1d087ee3878b30e0a59c593c98b7a
-F test/fts1o.test 382b8b07a2d6de5610814d9477117c4430464b9c
+F test/fts1o.test fd92f82ea9090dbc2a13d4cd58aafe5afa371b6a
F test/fts1porter.test d86e9c3e0c7f8ff95add6582b4b585fb4e02b96d
F test/fts2.test e3fb95f96a650411574efc136f3fb10eef479ed7
F test/fts2a.test 473a5c8b473a4e21a8e3fddaed1e59666e0c6ab7
@@ -428,12 +434,12 @@ F test/fts2f.test cf84096235991709c1e61caa389632aa0a4f976d
F test/fts2g.test d49d6f6c900e6e20a0fb980ec1cd568dee12af76
F test/fts2h.test 223af921323b409d4b5b18ff4e51619541b174bb
F test/fts2i.test 1b22451d1f13f7c509baec620dc3a4a754885dd6
-F test/fts2j.test f68d7611f76309bc8b94170f3740d9fbbc061d9b
+F test/fts2j.test 298fa1670aa21cd445b282d139b70c72e7ade12b
F test/fts2k.test c7ebf4a4937594aa07459e3e1bca1251c1be8659
F test/fts2l.test 3333336621524cf7d60bb62d6ef6ab69647866ed
F test/fts2m.test 4b30142ead6f3ed076e880a2a464064c5ad58c51
F test/fts2n.test 12b9c5352128cebd1c6b8395e43788d4b09087c2
-F test/fts2o.test c6a79567d85403dc4d15b89f3f9799a0a0aef065
+F test/fts2o.test 09cd920d585ebf1c2910b6be869efa286e308a84
F test/fts2p.test 4b48c35c91e6a7dbf5ac8d1e5691823cc999aafb
F test/fts2q.test b2fbbe038b7a31a52a6079b215e71226d8c6a682
F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
@@ -449,14 +455,14 @@ F test/fts3af.test d394978c534eabf22dd0837e718b913fd66b499c
F test/fts3ag.test 0b7d303f61ae5d620c4efb5e825713ea34ff9441
F test/fts3ah.test dc9f66c32c296f1bc8bcc4535126bddfeca62894
F test/fts3ai.test d29cee6ed653e30de478066881cec8aa766531b2
-F test/fts3aj.test 584facbc9ac4381a7ec624bfde677340ffc2a5a4
+F test/fts3aj.test 0ed71e1dd9b03b843a857dc3eb9b15630e0104fc
F test/fts3ak.test bd14deafe9d1586e8e9bf032411026ac4f8c925d
F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
-F test/fts3ao.test b83f99f70e9eec85f27d75801a974b3f820e01f9
+F test/fts3ao.test e7b80272efcced57d1d087a9da5c690dd7c21fd9
F test/fts3atoken.test 402ef2f7c2fb4b3d4fa0587df6441c1447e799b3
-F test/fts3auto.test f1cb0a55130897013ca5850dbee2945c2908a45a
+F test/fts3auto.test c1a30b37002b7c764a96937fbc71065b73d69494
F test/fts3aux1.test 0b02743955d56fc0d4d66236a26177bd1b726de0
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
@@ -465,65 +471,70 @@ F test/fts3conf.test 8e65ea56f88ced6cdd2252bdddb1a8327ae5af7e
F test/fts3corrupt.test 7b0f91780ca36118d73324ec803187208ad33b32
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
-F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
-F test/fts3defer.test 7c8a38d5f617d7b52ae1c43ed73c536e7e895a35
+F test/fts3d.test bf640d79722b720fa1c81834c48cdaa45d531b1a
+F test/fts3defer.test 2ea3fa028f8d9523f9c33dd8acc4555d567ea4ac
F test/fts3defer2.test 35867d33ba6db03f6c73bd6f5fc333ae14f68c81
+F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
-F test/fts3fault.test f83e556465bb69dc8bc676339eca408dce4ca246
-F test/fts3fault2.test dc96203af6ba31ce20163fc35460e1556e8edf4d
-F test/fts3malloc.test 9c8cc3f885bb4dfc66d0460c52f68f45e4710d1b
-F test/fts3matchinfo.test 08a82d18cc08abb28aec41d412b4c2ef25ba6a5f
+F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
+F test/fts3fault2.test b62a2bc843c20414405f80e5eeb78e39bc68fe53
+F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
+F test/fts3malloc.test b86ea33db9e8c58c0c2f8027a9fcadaf6a1568be
+F test/fts3matchinfo.test 6507fe1c342e542300d65ea637d4110eccf894e6
F test/fts3near.test 2e318ee434d32babd27c167142e2b94ddbab4844
-F test/fts3prefix.test 36246609111ec1683f7ea5ed27666ce2cefb5676
+F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
F test/fts3query.test ef79d31fdb355d094baec1c1b24b60439a1fb8a2
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 8bb266521d7c5495c0ae522bb4d376ad5387d4a2
-F test/fts3snippet.test a12f22a3ba4dd59751a57c79b031d07ab5f51ddd
-F test/fts3sort.test 63d52c1812904b751f9e1ff487472e44833f5402
-F test/fts4aa.test 148d9eb54901af23b5d402b1f388f43e559e1728
+F test/fts3snippet.test 8e956051221a34c7daeb504f023cb54d5fa5a8b2
+F test/fts3sort.test 95be0b19d7e41c44b29014f13ea8bddd495fd659
+F test/fts4aa.test 6e7f90420b837b2c685f3bcbe84c868492d40a68
+F test/fts4content.test 2624253c7e5a32d0c0d51f776dcd4526f0a51097
F test/func.test 6c5ce11e3a0021ca3c0649234e2d4454c89110ca
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
-F test/func3.test 7ba2ca5a1e9bca900ba2c230cf04bd67184bc1bc
+F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
-F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c
-F test/fuzzer1.test 3105b5a89a6cb0d475f0877debec942fe4143462
-F test/hook.test f2277c309e4ee8067d95d6b9b315568e9d5329b2
+F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
+F test/fuzzer1.test ddfb04f3bd5cfdda3b1aa15b78d3ad055c9cc50f
+F test/hook.test 5f3749de6462a6b87b4209b74adf7df5ac2df639
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
-F test/incrblob.test 76e787ca3301d9bfa6906031c626d26f8dd707de
+F test/incrblob.test 3307c04876fe025e10256e3cc8050ab5a84aa27f
F test/incrblob2.test edc3a96e557bd61fb39acc8d2edd43371fbbaa19
F test/incrblob3.test aedbb35ea1b6450c33b98f2b6ed98e5020be8dc7
-F test/incrblob_err.test c577c91d4ed9e8336cdb188b15d6ee2a6fe9604e
+F test/incrblob_err.test d2562d2771ebffd4b3af89ef64c140dd44371597
F test/incrblobfault.test 917c0292224c64a56ef7215fd633a3a82f805be0
-F test/incrvacuum.test 453d1e490d8f5ad2c9b3a54282a0690d6ae56462
-F test/incrvacuum2.test ae04573b73ad52179f56e194fff0fbe43b509d23
-F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
+F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
+F test/incrvacuum2.test 62fbeb85459fe4e501684d8fb5b6e98a23e3b0c0
+F test/incrvacuum_ioerr.test 22f208d01c528403240e05beecc41dc98ed01637
F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
+F test/index4.test 2983216eb8c86ee62d9ed7cb206b5cc3331c0026
F test/indexedby.test be501e381b82b2f8ab406309ba7aac46e221f4ad
+F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
-F test/insert4.test b3e02648a5fc3075c29e13c369b5127bf859b5a2
-F test/insert5.test 1f93cbe9742110119133d7e8e3ccfe6d7c249766
+F test/insert4.test 63ea672b0fc6d3a9a0ccee774a771510b1e684c4
+F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test 42e7cf98646fd9cb4a3b131a93ed3c50b9e149f1
F test/intpkey.test 537669fd535f62632ca64828e435b9e54e8d677f
-F test/io.test 1b895d6774491895cbc75659969f07ca01860c88
-F test/ioerr.test 622aebd2f24779cafaf5dd3e3c2b349ce40ade3b
+F test/io.test b278aa8fa609ed0dcc825df31b2d9f526c5a52bd
+F test/ioerr.test 40bb2cfcab63fb6aa7424cd97812a84bc16b5fb8
F test/ioerr2.test 1b56cb80d5b0726ee3ba325ca175734541e32955
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
-F test/ioerr4.test fc6eddfec2efc2f1ed217b9eae4c1c1d3516ce86
+F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/join.test 8d63cc4d230a7affafa4b6ab0b97c49b8ccb365c
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
@@ -531,40 +542,40 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe
F test/join6.test bf82cf3f979e9eade83ad0d056a66c5ed71d1901
-F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
-F test/journal2.test 50a3604768494d4a337f194f0a9480e7c57dcb72
-F test/journal3.test ff175219be1b02d2f7e54297ad7e491b7533edb6
-F test/jrnlmode.test e3fe6c4a2c3213d285650dc8e33aab7eaaa5ce53
-F test/jrnlmode2.test a19e28de1a6ec898067e46a122f1b71c9323bf00
-F test/jrnlmode3.test c6522b276ba315fd1416198de6fc1da9e72409fb
+F test/journal1.test 8b71ef1ed5798bdc0e6eb616d8694e2c2c188d4d
+F test/journal2.test 29937bdbb253bbfd92057610120bdc0aa7e84a0a
+F test/journal3.test 6fd28532c88b447db844186bc190523108b6dbb4
+F test/jrnlmode.test 9ee3a78f53d52cca737db69293d15dc41c0cbd36
+F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
+F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05
F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
-F test/like.test a47f52692aac96ba82508efba74819214cdebc17
+F test/like.test 7b4aaa4a8192fdec90e0a905984c92a688c51e48
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/limit.test 2db7b3b34fb925b8e847d583d2eb67531d0ce67e
-F test/loadext.test 0393ce12d9616aa87597dd0ec88181de181f6db0
+F test/loadext.test dab17f7014f8079698dbd4b02705562b0ce6db5f
F test/loadext2.test 0bcaeb4d81cd5b6e883fdfea3c1bdbe1f173cbca
F test/lock.test db74fdf5a73bad29ab3d862ea78bf1068972cc1d
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
-F test/lock4.test c82268c031d39345d05efa672f80b025481b3ae5
-F test/lock5.test b2abb5e711bc59b0eae00f6c97a36ec9f458fada
+F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
+F test/lock5.test 5ad6a1f536036ff1be915cfdd41481aeafda3273
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64
F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
-F test/main.test 9d7bbfcc1b52c88ba7b2ba6554068ecf9939f252
+F test/main.test 39c4bb8a157f57298ed1659d6df89d9f35aaf2c8
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
-F test/malloc.test 76017be66cec4375a4b4ea5c71245e27a9fe2d0b
-F test/malloc3.test 4128b1e6ffa506103b278ad97af89174f310c7ca
+F test/malloc.test bc745155ff4252d4f35ec8316625b0dfe2abc659
+F test/malloc3.test de8eca0c3e748878845fdca3663ec4b642073caf
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
-F test/malloc5.test 4d16d1bb26d2deddd7c4f480deec341f9b2d0e22
+F test/malloc5.test 30dc30b57fa22552eba0d8c95210d96c3d958a39
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
F test/malloc9.test 2307c6ee3703b0a21391f3ea92388b4b73f9105e
-F test/mallocA.test 4b650c745aab289079454f4d1c02abe5c97ab6b3
+F test/mallocA.test 47006c8d70f29b030652e251cb9d35ba60289198
F test/mallocAll.test 98f1be74bc9f49a858bc4f361fc58e26486798be
F test/mallocB.test bc475ab850cda896142ab935bbfbc74c24e51ed6
F test/mallocC.test 3dffe16532f109293ce1ccecd0c31dca55ef08c4
@@ -576,75 +587,75 @@ F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
F test/mallocK.test d79968641d1b70d88f6c01bdb9a7eb4a55582cc9
-F test/malloc_common.tcl 50d0ed21eed0ae9548b58935bd29ac89a05a54fa
-F test/manydb.test b3d3bc4c25657e7f68d157f031eb4db7b3df0d3c
+F test/malloc_common.tcl 2930895b0962823ec679853e67e58dd6d8198b3c
+F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test 708a028d6d373e5b3842e4bdc8ba80998c9a4da6
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
-F test/memsubsys1.test 679db68394a5692791737b150852173b3e2fea10
-F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc
+F test/memsubsys1.test 16ce163ac1ace3d71bf0eaa6a821ed153addd91f
+F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9
F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
-F test/misc1.test e56baf44656dd68d6475a4b44521045a60241e9b
-F test/misc2.test a628db7b03e18973e5d446c67696b03de718c9fd
-F test/misc3.test 72c5dc87a78e7865c5ec7a969fc572913dbe96b6
+F test/misc1.test 55cb2bfbf4a8cd61f4be1effc30426ad41696bff
+F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
+F test/misc3.test fe55130a43e444ee75e2156ff75dc96e964b5738
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
-F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd
+F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
-F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3
-F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
-F test/multiplex.test 555080c87abfc72ba68e2f3df01d4a9a7a4fdf58
+F test/misc7.test eafaa41b9133d7a2ded4641bbe5f340731d35a52
+F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054
+F test/multiplex.test 9df8bf738b3b97c718fceb3fadb30900ba494418
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
-F test/nan.test dc212a22b36109fd1ae37154292444ef249c5ec2
-F test/notify1.test 8433bc74bd952fb8a6e3f8d7a4c2b28dfd69e310
-F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
-F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
+F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
+F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
+F test/notify2.test 9503e51b9a272a5405c205ad61b7623d5a9ca489
+F test/notify3.test a86259abbfb923aa27d30f0fc038c88e5251488a
F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
F test/null.test a8b09b8ed87852742343b33441a9240022108993
-F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
-F test/oserror.test 3fe52e0bd2891a9bf7cdeb639554992453d46301
-F test/pager1.test 228a831060dab96bc91b03ba2a85cedefd1ab38a
+F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
+F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
+F test/pager1.test 1b630b3248c7d28862fe9e190cfe52234b502504
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
-F test/pagerfault.test 4194b8ea2a5da7958cd155556605ff554e1b065a
+F test/pagerfault.test 452f2cc23e3bfcfa935f4442aec1da4fe1dc0442
F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401
F test/pagerfault3.test f16e2efcb5fc9996d1356f7cbc44c998318ae1d7
-F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
-F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
+F test/pageropt.test 9191867ed19a2b3db6c42d1b36b6fbc657cd1ab0
+F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
-F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
-F test/permutations.test 1e8892ebf1bd6e9e8036f4841c72a91bf72da74a
-F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850
-F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
-F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
+F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
+F test/permutations.test 522823b47238cb1754198f80817fe9f9158ede55
+F test/pragma.test 1ea0c85be853135bb7468e6eed48ee12b04794d4
+F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
+F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
-F test/quota.test 48c3a5a98687d67ef06fc16d2e603284756bbec3
+F test/quota.test 1c59a396e8f7b5d8466fa74b59f2aeb778d74f7a
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test 1084050991e9ba22c1c10edd8d84673b501cc25a
F test/rdonly.test c267d050a1d9a6a321de502b737daf28821a518d
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
-F test/releasetest.tcl c0c0865f1dff08dde08a964ef49e83217ebedbf8
-F test/rollback.test 1a83118ea6db4e7d8c10eaa63871b5e90502ffdc
+F test/releasetest.tcl fa302d03fd9acfce6d910553a33473bfcf561958
+F test/rollback.test a1b4784b864331eae8b2a98c189efa2a8b11ff07
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test e58e0acef38b527ed1b0b70d3ada588f804af287
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
-F test/savepoint.test a1bef7ace82cc7922975fa96b06176e9bd5114cf
+F test/savepoint.test e575217b07d6a6e895e66f4eda076570815e0027
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
-F test/savepoint6.test 76d3948568b2cdc0c13a671cadcae75009b183d6
+F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
-F test/securedel.test 328d2921c0ca49bdd3352e516b0377fc07143254
+F test/securedel.test 87a2561151af1f1e349071a89fdd77059f50113c
F test/select1.test f67ca2dfc05df41c7b86eb32ca409b427a5f43b0
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
@@ -655,15 +666,15 @@ F test/select7.test dad6f00f0d49728a879d6eb6451d4752db0b0abe
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select9.test 74c0fb2c6eecb0219cbed0cbe3df136f8fbf9343
F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532
-F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b
+F test/selectB.test 0d072c5846071b569766e6cd7f923f646a8b2bfa
F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25
-F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c
-F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e
-F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c
-F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962
-F test/shared4.test d0fadacb50bb6981b2fb9dc6d1da30fa1edddf83
-F test/shared6.test 990d2584b5db28e6e1f24742c711b26e59757b67
-F test/shared7.test 8114027cb5e8c376e467115703d46e5ac4e77739
+F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
+F test/shared.test 34945a516532b11182c3eb26e31247eee3c9ae48
+F test/shared2.test 8f71d4eb4d5261280de92284df74172545c852cc
+F test/shared3.test ebf77f023f4bdaa8f74f65822b559e86ce5c6257
+F test/shared4.test 72d90821e8d2fc918a08f16d32880868d8ee8e9d
+F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
+F test/shared7.test 960760bc8d03e1419e70dea69cf41db62853616e
F test/shared_err.test 91e26ec4f3fbe07951967955585137e2f18993de
F test/sharedlock.test ffa0a3c4ac192145b310f1254f8afca4d553eabf
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
@@ -675,32 +686,33 @@ F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
F test/speed1p.test c4a469f29f135f4d76c55b1f2a52f36e209466cc
F test/speed2.test 53177056baf6556dcbdcf032bbdfc41c1aa74ded
-F test/speed3.test 5a419039e9da95d906adb2298af2849600c81c11
+F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
-F test/sqllimits1.test e90a0ed94452076f6a10209d378e06b5f75ef0a0
-F test/stat.test c7b20ea43003dc2dc33335e231c27be8284c4a2a
+F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
+F test/stat.test 36bc951bdc2beac4224cc54396fd6a7dc65336f4
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796
+F test/subquery2.test edcad5c118f0531c2e21bf16a09bbb105252d4cd
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
-F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082
-F test/sync.test 2bd73b585089c99e76b3e1796c42059b7d89d872
-F test/syscall.test 707c95e4ab7863e13f1293c6b0c76bead30249b3
+F test/superlock.test 7b1167925e9d30a5d1f0701d24812fdda42c3a86
+F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
+F test/syscall.test 966addf703faee6a5d509abe6d8885e393e552fd
F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f
-F test/table.test 04ba066432430657712d167ebf28080fe878d305
+F test/table.test a59d985ca366e39b17b175f387f9d5db5a18d4e2
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
-F test/tclsqlite.test 8c154101e704170c2be10f137a5499ac2c6da8d3
+F test/tclsqlite.test 5ebcbb0dccc3fbc1edc3bba84c38e2c2d574c5aa
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
-F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
-F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
-F test/tester.tcl 7d3d17914ca5397a82f801db733b81d4a82f50c3
-F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
-F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
-F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
+F test/temptable.test 51edd31c65ed1560dd600b1796e8325df96318e2
+F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d
+F test/tester.tcl 0b2999b578964297663de4870babbbee29225622
+F test/thread001.test 7cc2ce08f9cde95964736d11e91f9ab610f82f91
+F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
+F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
F test/thread004.test f51dfc3936184aaf73ee85f315224baad272a87f
-F test/thread005.test bf5c374ca65dd89fd56c8fe511ccfb46875bda5e
+F test/thread005.test 50d10b5684399676174bd96c94ad4250b1a2c8b6
F test/thread1.test df115faa10a4ba1d456e9d4d9ec165016903eae4
F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
@@ -709,17 +721,18 @@ F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9
F test/threadtest3.c 0ed13e09690f6204d7455fac3b0e8ece490f6eef
F test/tkt-02a8e81d44.test 58494de77be2cf249228ada3f313fa399821c6ab
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
-F test/tkt-2d1a5c67d.test 73574c758502bf23260c17f97fcd9316dfb5a060
+F test/tkt-2d1a5c67d.test b028a811049eb472cb2d3a43fc8ce4f6894eebda
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
-F test/tkt-31338dca7e.test 5741cd48de500347a437ba1be58c8335e83c5a5e
+F test/tkt-31338dca7e.test 1f714c14b6682c5db715e0bda347926a3456f7a9
F test/tkt-313723c356.test c47f8a9330523e6f35698bf4489bcb29609b53ac
F test/tkt-38cb5df375.test 9e9b19857dba0896a8efdaf334d405ba423492f2
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
F test/tkt-3fe897352e.test 10de1a67bd5c66b238a4c96abe55531b37bb4f00
F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e
+F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
F test/tkt-5d863f876e.test 884072c2de496ddbb90c387c9ebc0d4f44a91b8e
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
-F test/tkt-5ee23731f.test 3581260f2a71e51db94e1506ba6b0f7311d002a9
+F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
F test/tkt-78e04e52ea.test ab52f0c1e2de6e46c910f4cc16b086bba05952b7
F test/tkt-80ba201079.test a09684db1a0bd55b8838f606adccee456a51ddbf
@@ -728,16 +741,20 @@ F test/tkt-8454a207b9.test c583a9f814a82a2b5ba95207f55001c9f0cd816c
F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5
F test/tkt-94c04eaadb.test be5ea61cb04dfdc047d19b5c5a9e75fa3da67a7f
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
+F test/tkt-b1d3a2e531.test 610ef582413171b379652663111b1f996d9f8f78
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
F test/tkt-b72787b1.test e6b62b2b2785c04d0d698d6a603507e384165049
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
-F test/tkt-cbd054fa6b.test f14f97ea43662e6f70c9e63287081e8be5d9d589
+F test/tkt-c48d99d690.test bed446e3513ae10eec1b86fdd186ef750226c408
+F test/tkt-cbd054fa6b.test bd9fb546f63bc0c79d1776978d059fa51c5b1c63
F test/tkt-d11f09d36e.test fb44f7961aa6d4b632fb7b9768239832210b5fc7
+F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
F test/tkt-d82e3f3721.test 731359dfdcdb36fea0559cd33fec39dd0ceae8e6
-F test/tkt-f3e5abed55.test 19fb59268da6f20a69a181b9c14154132d1c65e3
+F test/tkt-f3e5abed55.test 669bb076f2ac573c7398ce00f40cd0ca502043a9
F test/tkt-f777251dc7a.test 6f24c053bc5cdb7e1e19be9a72c8887cf41d5e87
F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
F test/tkt-f973c7ac31.test 1da0ed15ec2c7749fb5ce2828cd69d07153ad9f4
+F test/tkt-fa7bf5ec.test 9102dfea58aa371d78969da735f9392c57e2e035
F test/tkt-fc62af4523.test 72825d3febdedcd5593a27989fc05accdbfc2bb4
F test/tkt1435.test f8c52c41de6e5ca02f1845f3a46e18e25cadac00
F test/tkt1443.test bacc311da5c96a227bf8c167e77a30c99f8e8368
@@ -751,8 +768,8 @@ F test/tkt1536.test 83ff7a7b6e248016f8d682d4f7a4ae114070d466
F test/tkt1537.test e3a14332de9770be8ff14bd15c19a49cbec10808
F test/tkt1567.test 18023cc3626a365f0118e17b66decedec93b1a6f
F test/tkt1644.test 80b6a2bb17885f3cf1cb886d97cdad13232bb869
-F test/tkt1667.test 5d208e8d8cbcf82a446b315774290b66b464bc5f
-F test/tkt1873.test 255a002b9afdcf8b0fa3188984e2c964202340e9
+F test/tkt1667.test 4700d931ed19ea3983e8e703becb28079250b460
+F test/tkt1873.test 0e1b8c023050a430c2525179ed4022ddc7c31264
F test/tkt2141.test f543d96f50d5a5dc0bc744f7db74ea166720ce46
F test/tkt2192.test ff40157e5f42e65f844255d220fc6b290470942f
F test/tkt2213.test a9702175601a57b61aba095a233b001d6f362474
@@ -766,13 +783,13 @@ F test/tkt2450.test 77ed94863f2049c1420288ddfea2d41e5e0971d6
F test/tkt2565.test 8be666e927cb207aae88188f31c331870878b650
F test/tkt2640.test 28134f5d1e05658ef182520cf0b680fa3de5211b
F test/tkt2643.test 3f3ebb743da00d4fed4fcf6daed92a0e18e57813
-F test/tkt2686.test 08f0f584461bc4990376936daa0a9bd3e6e81671
+F test/tkt2686.test 6ee01c9b9e9c48f6d3a1fdd553b1cc4258f903d6
F test/tkt2767.test 569000d842678f9cf2db7e0d1b27cbc9011381b0
-F test/tkt2817.test 94646b604c7dbae7058782f6582c05e200700aa9
-F test/tkt2820.test 017fdee33aaef7abc092beab6088816f1942304b
+F test/tkt2817.test f31839e01f4243cff7399ef654d3af3558cb8d8d
+F test/tkt2820.test 39940276b3436d125deb7d8ebeee053e4cf13213
F test/tkt2822.test a2b27a58df62d1b2e712f91dbe42ad3b7e0e77cc
F test/tkt2832.test a9b0b74a02dca166a04d9e37739c414b10929caa
-F test/tkt2854.test b81dc3144901b123fe5674471adf5a47ca48a7c3
+F test/tkt2854.test e432965db29e27e16f539b2ba7f502eb2ccc49af
F test/tkt2920.test a8737380e4ae6424e00c0273dc12775704efbebf
F test/tkt2927.test 4752868b9eeeb07a217f7f19f4cbaac98d6d086d
F test/tkt2942.test c5c87d179799ca6d1fbe83c815510b87cd5ec7ce
@@ -788,7 +805,7 @@ F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed
F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b
F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812
F test/tkt3442.test 0adb70e9fe9cb750a702065a68ad647409dbc158
-F test/tkt3457.test edbf54b05cbe5165f00192becbd621038f1615e4
+F test/tkt3457.test eb68bb3b19c8677cff06c639ff15d206dbf17fd6
F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19
F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218
F test/tkt3508.test d75704db9501625c7f7deec119fcaf1696aefb7d
@@ -797,7 +814,7 @@ F test/tkt3527.test ee4af96183579565987e58873a7490bc04934ffb
F test/tkt3541.test 5dc257bde9bc833ab9cc6844bf170b998dbb950a
F test/tkt3554.test f599967f279077bace39220cbe76085c7b423725
F test/tkt3581.test 1966b7193f1e3f14951cce8c66907ae69454e9a3
-F test/tkt35xx.test ed9721bd9eb1693b3b4d3cf2a093fa7f92af0c93
+F test/tkt35xx.test 69d038ce5898f1b64f2084b780bbab1cf9be0a25
F test/tkt3630.test 929f64852103054125200bc825c316d5f75d42f7
F test/tkt3718.test 3b59dcb5c4e7754dacd91e7fd353a61492cc402a
F test/tkt3731.test 0c5f4cbffe102d43c3b2188af91a9e36348f974b
@@ -806,7 +823,7 @@ F test/tkt3761.test b95ea9c98f21cf91325f18a984887e62caceab33
F test/tkt3762.test 2a9f3b03df44ec49ec0cfa8d5da6574c2a7853df
F test/tkt3773.test 430b06567ce40285dfd2c4834a2a61816403efeb
F test/tkt3791.test a6624b9a80b216a26cf473607f42f3e51898c267
-F test/tkt3793.test 754b73f0e6a9349c70dc57e522cf3247272ecd5d
+F test/tkt3793.test d90ffd75c52413908d15e1c44fc2ea9c80fcc449
F test/tkt3810.test 90fa0635dfa7da9680c8cd3513350a49b3a8ae12
F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
@@ -828,103 +845,109 @@ F test/trace2.test 962175290996d5f06dc4402ca218bbfc7df4cb20
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22
F test/trans3.test d728abaa318ca364dc370e06576aa7e5fbed7e97
-F test/trigger1.test 2e18561f85e448bb633c9c9de792e9bbf7b2dd3e
+F test/trigger1.test 38c657eaf9907344c9e0bcb16af94a452c6babde
F test/trigger2.test 834187beafd1db383af0c659cfa49b0576832816
F test/trigger3.test d2c60d8be271c355d61727411e753181e877230a
-F test/trigger4.test 8e90ee98cba940cd5f96493f82e55083806ab8a0
+F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
F test/trigger7.test b39e6dee1debe0ff9c2ef66326668f149f07c9c4
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
-F test/triggerA.test eaf11a29db2a11967d2d4b49d37f92bce598194e
+F test/triggerA.test e0aaba16d3547193d36bbd82a1b0ed75e9c88d40
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
-F test/triggerC.test 02c690febf608ae20b9af86184a9867f79855b1d
-F test/triggerD.test c6add3817351451e419f6ff9e9a259b02b6e2de7
+F test/triggerC.test 4d4bdaf0230c206b50d350330107ef9802bc2d4f
+F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
F test/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
F test/unixexcl.test 9d80a54d86d2261f660758928959368ffc36151e
-F test/unordered.test e81169ce2a8f31b2c6b66af691887e1376ab3ced
+F test/unordered.test f53095cee37851bf30130fa1bf299a8845e837bb
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
-F test/uri.test 53de9a2549cbda9c343223236918ef502f6a9051
+F test/uri.test 0d289d32396bdbc491e9dc845f1a52e13f861e0b
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
-F test/vacuum.test 29b60e8cc9e573b39676df6c4a75fe9e02d04a09
-F test/vacuum2.test 91a84c9b08adfc4472097d2e8deb0150214e0e76
-F test/vacuum3.test f39ad1428347c5808cd2da7578c470f186a4d0ce
+F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
+F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
+F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 7701bb609fe8bf6535514e8b849a309e8f00573b
-F test/view.test 45f518205ecdb6dd23a86dd4a99bb4ae945e625d
-F test/vtab1.test 7b79832824cbae37ff01a06ed155027f7c15bf9e
+F test/view.test b182a67ec43f490b156b5a710827a341be83dd17
+F test/vtab1.test 12fbb309ce830c4064e44f275eb02a65c2780076
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
F test/vtab6.test c7f290d172609d636fbfc58166eadcb55d5c117c
-F test/vtab7.test a8c3c3cb3eb60be364991bd714e4927e26c4cd85
+F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
F test/vtabA.test c86e1990b7e1e2bb34602a06fffa4c69f2b516dc
F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796
-F test/vtabC.test 1cf7896ab6859bfe3074244b2b0e12de5cbdd766
+F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
F test/vtabD.test 74167b1578e5886fe4c886d6bef2fd1406444c42
F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
+F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
-F test/wal.test 5617ad308bfdb8a8885220d8a261a6096a8d7e57
-F test/wal2.test aa0fb2314b3235be4503c06873e41ebfc0757782
-F test/wal3.test 5c396cc22497244d627306f4c1d360167353f8dd
-F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
-F test/wal5.test f06a0427e06db00347e32eb9fa99d6a5c0f2d088
-F test/wal6.test 07aa31ca8892d0527f2c5c5a9a2a87aa421dfaa8
+F test/wal.test e11da8d5ea8a38a247339455098357e9adf63d76
+F test/wal2.test ad6412596815f553cd30f271d291ab003092bc7e
+F test/wal3.test 18da4e65c30c43c646ad40e145e9a074e4062fc9
+F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
+F test/wal5.test 1bbfaa316dc2a1d0d1fac3f4500c38a90055a41b
+F test/wal6.test 2e3bc767d9c2ce35c47106148d43fcbd072a93b3
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
-F test/walbak.test 4df1c7369da0301caeb9a48fa45997fd592380e4
-F test/walbig.test e882bc1d014afffbfa2b6ba36e0f07d30a633ad0
-F test/walcksum.test a37b36375c595e61bdb7e1ec49b5f0979b6fc7ce
-F test/walcrash.test e763841551d6b23677ccb419797c1589dcbdbaf5
+F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877
+F test/walbig.test 0ab8a430ef420a3114f7092e0f30fc9585ffa155
+F test/walcksum.test f5447800a157c9e2234fbb8e80243f0813941bde
+F test/walcrash.test 4fcb661faf71db91214156d52d43ee327f52bde1
F test/walcrash2.test 019d60b89d96c1937adb2b30b850ac7e86e5a142
-F test/walfault.test 58fce626359c9376fe35101b5c0f2df8040aa839
+F test/walfault.test efb0d5724893133e71b8d9d90abdb781845a6bb0
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
-F test/walmode.test 22ddccd073c817ac9ead62b88ac446e8dedc7d2c
-F test/walnoshm.test a074428046408f4eb5c6a00e09df8cc97ff93317
-F test/walro.test 2d5d69e2e99da19ce6faab340330234fc4ca0720
+F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
+F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
+F test/walpersist.test fd40d33765b2693f721c90c66d97f99757559006
+F test/walro.test e6bb27762c9f22601cbb8bff6e0acfd124e74b63
F test/walshared.test 6dda2293880c300baf5d791c307f653094585761
-F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
-F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
+F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
+F test/walthread.test a2ed5270eb695284d4ad27d252517bdc3317ee2a
F test/where.test de337a3fe0a459ec7c93db16a519657a90552330
F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554
-F test/where3.test 8e1175c7ef710c70502858fc4fb08d784b3620b9
+F test/where3.test 667e75642102c97a00bf9b23d3cb267db321d006
F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
-F test/where7.test aa4cfcd6f66e2a4ef87b6717327325bf4d547502
+F test/where7.test 814d7373413398e074f134cff5f8872e2c08bd3b
F test/where8.test a6c740fd286d7883e274e17b6230a9d672a7ab1f
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
-F test/where9.test 24f19ad14bb1b831564ced5273e681e495662848
+F test/where9.test bed66dcfc69a54a99661c0c9906189cb5e58f4e2
F test/whereA.test 24c234263c8fe358f079d5e57d884fb569d2da0a
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
+F test/win32lock.test b2a539e85ae6b2d78475e016a9636b4451dc7fb9
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F tool/build-shell.sh 12aa4391073a777fcb6dcc490b219a018ae98bac
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
+F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
-F tool/lemon.c d51c68d405ff7f9bad99268ca3c20a198eb983ed
+F tool/lemon.c 949328f67cac94969d3112b105b8457edf27f44e
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
-F tool/mksqlite3c.tcl 1fa0ed9cfdc768bf5de7e65fda8d97a46dd2a7e6
+F tool/mksqlite3c-noext.tcl 105023aa86f696a74b1d6a4929d1e1c3baf9471c
+F tool/mksqlite3c.tcl 9fbac513cd9d5ac95ad55630f49bb16c5347ab75
F tool/mksqlite3h.tcl 78013ad79a5e492e5f764f3c7a8ef834255061f8
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
-F tool/omittest.tcl 8086c014cbae90f1f2b564d59d05a5e4ac1783c9
+F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
+F tool/omittest.tcl 72a49b8a9a8b0bf213a438180307a0df836d4380
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
@@ -938,18 +961,21 @@ F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02
F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
-F tool/spaceanal.tcl b91879d52bf77a1ff5382493284f429d32a63490
+F tool/spaceanal.tcl 15f6cd939b4ecc14d061de7e8ace89e26c30c40b
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
-F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00
-F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
+F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
+F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
+F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d
-P de8ad5f8176d5573c02ec39b14cca324cfef5cb9
-R 627b3b91e5169f5233cd18fa7efa5202
-U dan
-Z 94b0ac9079eaca2f6ca6db06cfa18fd2
+F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
+F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
+P 6635cd9a7714b681dd8aa96e90be462a40d10178
+R b059ff356abfc5b4524a9b548916f43e
+T +sym-version-3.7.9 *
+U drh
+Z a9ecbb5c487c786a176874d979505217
diff --git a/manifest.uuid b/manifest.uuid
index 735e9cae..cf01f92c 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-af0d91adf497f5f36ec3813f04235a6e195a605f
+c7c6050ef060877ebe77b41d959e9df13f8c9b5e
diff --git a/mkopcodec.awk b/mkopcodec.awk
index ec809530..2ef77d4c 100644
--- a/mkopcodec.awk
+++ b/mkopcodec.awk
@@ -17,13 +17,18 @@ BEGIN {
print " || defined(SQLITE_DEBUG)"
print "const char *sqlite3OpcodeName(int i){"
print " static const char *const azName[] = { \"?\","
+ mx = 0
}
/define OP_/ {
sub("OP_","",$2)
- i++
- printf " /* %3d */ \"%s\",\n", $3, $2
+ i = $3+0
+ label[i] = $2
+ if( mx1) is the average number of rows in
+** the index which have the same value for the first N-1 columns. For
+** a K-column index, there will be K+1 integers in the stat column. If
+** the index is unique, then the last integer will be 1.
+**
+** The list of integers in the stat column can optionally be followed
+** by the keyword "unordered". The "unordered" keyword, if it is present,
+** must be separated from the last integer by a single space. If the
+** "unordered" keyword is present, then the query planner assumes that
+** the index is unordered and will not use the index for a range query.
+**
+** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
+** column contains a single integer which is the (estimated) number of
+** rows in the table identified by sqlite_stat1.tbl.
+**
+** Format of sqlite_stat2:
+**
+** The sqlite_stat2 is only created and is only used if SQLite is compiled
+** with SQLITE_ENABLE_STAT2 and if the SQLite version number is between
+** 3.6.18 and 3.7.8. The "stat2" table contains additional information
+** about the distribution of keys within an index. The index is identified by
+** the "idx" column and the "tbl" column is the name of the table to which
+** the index belongs. There are usually 10 rows in the sqlite_stat2
+** table for each index.
+**
+** The sqlite_stat2 entries for an index that have sampleno between 0 and 9
+** inclusive are samples of the left-most key value in the index taken at
+** evenly spaced points along the index. Let the number of samples be S
+** (10 in the standard build) and let C be the number of rows in the index.
+** Then the sampled rows are given by:
+**
+** rownumber = (i*C*2 + C)/(S*2)
+**
+** For i between 0 and S-1. Conceptually, the index space is divided into
+** S uniform buckets and the samples are the middle row from each bucket.
+**
+** The format for sqlite_stat2 is recorded here for legacy reference. This
+** version of SQLite does not support sqlite_stat2. It neither reads nor
+** writes the sqlite_stat2 table. This version of SQLite only supports
+** sqlite_stat3.
+**
+** Format for sqlite_stat3:
+**
+** The sqlite_stat3 is an enhancement to sqlite_stat2. A new name is
+** used to avoid compatibility problems.
+**
+** The format of the sqlite_stat3 table is similar to the format of
+** the sqlite_stat2 table. There are multiple entries for each index.
+** The idx column names the index and the tbl column is the table of the
+** index. If the idx and tbl columns are the same, then the sample is
+** of the INTEGER PRIMARY KEY. The sample column is a value taken from
+** the left-most column of the index. The nEq column is the approximate
+** number of entires in the index whose left-most column exactly matches
+** the sample. nLt is the approximate number of entires whose left-most
+** column is less than the sample. The nDLt column is the approximate
+** number of distinct left-most entries in the index that are less than
+** the sample.
+**
+** Future versions of SQLite might change to store a string containing
+** multiple integers values in the nDLt column of sqlite_stat3. The first
+** integer will be the number of prior index entires that are distinct in
+** the left-most column. The second integer will be the number of prior index
+** entries that are distinct in the first two columns. The third integer
+** will be the number of prior index entries that are distinct in the first
+** three columns. And so forth. With that extension, the nDLt field is
+** similar in function to the sqlite_stat1.stat field.
+**
+** There can be an arbitrary number of sqlite_stat3 entries per index.
+** The ANALYZE command will typically generate sqlite_stat3 tables
+** that contain between 10 and 40 samples which are distributed across
+** the key space, though not uniformly, and which include samples with
+** largest possible nEq values.
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"
@@ -17,16 +119,16 @@
/*
** This routine generates code that opens the sqlite_stat1 table for
** writing with cursor iStatCur. If the library was built with the
-** SQLITE_ENABLE_STAT2 macro defined, then the sqlite_stat2 table is
+** SQLITE_ENABLE_STAT3 macro defined, then the sqlite_stat3 table is
** opened for writing using cursor (iStatCur+1)
**
** If the sqlite_stat1 tables does not previously exist, it is created.
-** Similarly, if the sqlite_stat2 table does not exist and the library
-** is compiled with SQLITE_ENABLE_STAT2 defined, it is created.
+** Similarly, if the sqlite_stat3 table does not exist and the library
+** is compiled with SQLITE_ENABLE_STAT3 defined, it is created.
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
-** the sqlite_stat1 and (if applicable) sqlite_stat2 tables associated
+** the sqlite_stat1 and (if applicable) sqlite_stat3 tables associated
** with the named table are deleted. If zWhere==0, then code is generated
** to delete all stat table entries.
*/
@@ -42,8 +144,8 @@ static void openStatTable(
const char *zCols;
} aTable[] = {
{ "sqlite_stat1", "tbl,idx,stat" },
-#ifdef SQLITE_ENABLE_STAT2
- { "sqlite_stat2", "tbl,idx,sampleno,sample" },
+#ifdef SQLITE_ENABLE_STAT3
+ { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
#endif
};
@@ -59,6 +161,9 @@ static void openStatTable(
assert( sqlite3VdbeDb(v)==db );
pDb = &db->aDb[iDb];
+ /* Create new statistic tables if they do not exist, or clear them
+ ** if they do already exist.
+ */
for(i=0; ia[0])*mxSample;
+ p = sqlite3_malloc( n );
+ if( p==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ memset(p, 0, n);
+ p->a = (struct Stat3Sample*)&p[1];
+ p->nRow = nRow;
+ p->mxSample = mxSample;
+ p->nPSample = p->nRow/(mxSample/3+1) + 1;
+ sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);
+ sqlite3_result_blob(context, p, sizeof(p), sqlite3_free);
+}
+static const FuncDef stat3InitFuncdef = {
+ 2, /* nArg */
+ SQLITE_UTF8, /* iPrefEnc */
+ 0, /* flags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ stat3Init, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat3_init", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+};
+
+
+/*
+** Implementation of the stat3_push(nEq,nLt,nDLt,rowid,P) SQL function. The
+** arguments describe a single key instance. This routine makes the
+** decision about whether or not to retain this key for the sqlite_stat3
+** table.
+**
+** The return value is NULL.
+*/
+static void stat3Push(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[4]);
+ tRowcnt nEq = sqlite3_value_int64(argv[0]);
+ tRowcnt nLt = sqlite3_value_int64(argv[1]);
+ tRowcnt nDLt = sqlite3_value_int64(argv[2]);
+ i64 rowid = sqlite3_value_int64(argv[3]);
+ u8 isPSample = 0;
+ u8 doInsert = 0;
+ int iMin = p->iMin;
+ struct Stat3Sample *pSample;
+ int i;
+ u32 h;
+
+ UNUSED_PARAMETER(context);
+ UNUSED_PARAMETER(argc);
+ if( nEq==0 ) return;
+ h = p->iPrn = p->iPrn*1103515245 + 12345;
+ if( (nLt/p->nPSample)!=((nEq+nLt)/p->nPSample) ){
+ doInsert = isPSample = 1;
+ }else if( p->nSamplemxSample ){
+ doInsert = 1;
+ }else{
+ if( nEq>p->a[iMin].nEq || (nEq==p->a[iMin].nEq && h>p->a[iMin].iHash) ){
+ doInsert = 1;
+ }
+ }
+ if( !doInsert ) return;
+ if( p->nSample==p->mxSample ){
+ assert( p->nSample - iMin - 1 >= 0 );
+ memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1));
+ pSample = &p->a[p->nSample-1];
+ }else{
+ pSample = &p->a[p->nSample++];
+ }
+ pSample->iRowid = rowid;
+ pSample->nEq = nEq;
+ pSample->nLt = nLt;
+ pSample->nDLt = nDLt;
+ pSample->iHash = h;
+ pSample->isPSample = isPSample;
+
+ /* Find the new minimum */
+ if( p->nSample==p->mxSample ){
+ pSample = p->a;
+ i = 0;
+ while( pSample->isPSample ){
+ i++;
+ pSample++;
+ assert( inSample );
+ }
+ nEq = pSample->nEq;
+ h = pSample->iHash;
+ iMin = i;
+ for(i++, pSample++; inSample; i++, pSample++){
+ if( pSample->isPSample ) continue;
+ if( pSample->nEqnEq==nEq && pSample->iHashnEq;
+ h = pSample->iHash;
+ }
+ }
+ p->iMin = iMin;
+ }
+}
+static const FuncDef stat3PushFuncdef = {
+ 5, /* nArg */
+ SQLITE_UTF8, /* iPrefEnc */
+ 0, /* flags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ stat3Push, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat3_push", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+};
+
+/*
+** Implementation of the stat3_get(P,N,...) SQL function. This routine is
+** used to query the results. Content is returned for the Nth sqlite_stat3
+** row where N is between 0 and S-1 and S is the number of samples. The
+** value returned depends on the number of arguments.
+**
+** argc==2 result: rowid
+** argc==3 result: nEq
+** argc==4 result: nLt
+** argc==5 result: nDLt
+*/
+static void stat3Get(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int n = sqlite3_value_int(argv[1]);
+ Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[0]);
+
+ assert( p!=0 );
+ if( p->nSample<=n ) return;
+ switch( argc ){
+ case 2: sqlite3_result_int64(context, p->a[n].iRowid); break;
+ case 3: sqlite3_result_int64(context, p->a[n].nEq); break;
+ case 4: sqlite3_result_int64(context, p->a[n].nLt); break;
+ default: sqlite3_result_int64(context, p->a[n].nDLt); break;
+ }
+}
+static const FuncDef stat3GetFuncdef = {
+ -1, /* nArg */
+ SQLITE_UTF8, /* iPrefEnc */
+ 0, /* flags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ stat3Get, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat3_get", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+};
+#endif /* SQLITE_ENABLE_STAT3 */
+
+
+
+
/*
** Generate code to do an analysis of all indices associated with
** a single table.
@@ -119,20 +444,27 @@ static void analyzeOneTable(
int iDb; /* Index of database containing pTab */
int regTabname = iMem++; /* Register containing table name */
int regIdxname = iMem++; /* Register containing index name */
- int regSampleno = iMem++; /* Register containing next sample number */
- int regCol = iMem++; /* Content of a column analyzed table */
+ int regStat1 = iMem++; /* The stat column of sqlite_stat1 */
+#ifdef SQLITE_ENABLE_STAT3
+ int regNumEq = regStat1; /* Number of instances. Same as regStat1 */
+ int regNumLt = iMem++; /* Number of keys less than regSample */
+ int regNumDLt = iMem++; /* Number of distinct keys less than regSample */
+ int regSample = iMem++; /* The next sample value */
+ int regRowid = regSample; /* Rowid of a sample */
+ int regAccum = iMem++; /* Register to hold Stat3Accum object */
+ int regLoop = iMem++; /* Loop counter */
+ int regCount = iMem++; /* Number of rows in the table or index */
+ int regTemp1 = iMem++; /* Intermediate register */
+ int regTemp2 = iMem++; /* Intermediate register */
+ int once = 1; /* One-time initialization */
+ int shortJump = 0; /* Instruction address */
+ int iTabCur = pParse->nTab++; /* Table cursor */
+#endif
+ int regCol = iMem++; /* Content of a column in analyzed table */
int regRec = iMem++; /* Register holding completed record */
int regTemp = iMem++; /* Temporary use register */
- int regRowid = iMem++; /* Rowid for the inserted record */
+ int regNewRowid = iMem++; /* Rowid for the inserted record */
-#ifdef SQLITE_ENABLE_STAT2
- int addr = 0; /* Instruction address */
- int regTemp2 = iMem++; /* Temporary use register */
- int regSamplerecno = iMem++; /* Index of next sample to record */
- int regRecno = iMem++; /* Current sample index */
- int regLast = iMem++; /* Index of last sample to record */
- int regFirst = iMem++; /* Index of first sample to record */
-#endif
v = sqlite3GetVdbe(pParse);
if( v==0 || NEVER(pTab==0) ){
@@ -165,9 +497,14 @@ static void analyzeOneTable(
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int nCol;
KeyInfo *pKey;
+ int addrIfNot = 0; /* address of OP_IfNot */
+ int *aChngAddr; /* Array of jump instruction addresses */
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
+ VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
nCol = pIdx->nColumn;
+ aChngAddr = sqlite3DbMallocRaw(db, sizeof(int)*nCol);
+ if( aChngAddr==0 ) continue;
pKey = sqlite3IndexKeyinfo(pParse, pIdx);
if( iMem+1+(nCol*2)>pParse->nMem ){
pParse->nMem = iMem+1+(nCol*2);
@@ -182,31 +519,20 @@ static void analyzeOneTable(
/* Populate the register containing the index name. */
sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0);
-#ifdef SQLITE_ENABLE_STAT2
-
- /* If this iteration of the loop is generating code to analyze the
- ** first index in the pTab->pIndex list, then register regLast has
- ** not been populated. In this case populate it now. */
- if( pTab->pIndex==pIdx ){
- sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES, regSamplerecno);
- sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES*2-1, regTemp);
- sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES*2, regTemp2);
-
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regLast);
- sqlite3VdbeAddOp2(v, OP_Null, 0, regFirst);
- addr = sqlite3VdbeAddOp3(v, OP_Lt, regSamplerecno, 0, regLast);
- sqlite3VdbeAddOp3(v, OP_Divide, regTemp2, regLast, regFirst);
- sqlite3VdbeAddOp3(v, OP_Multiply, regLast, regTemp, regLast);
- sqlite3VdbeAddOp2(v, OP_AddImm, regLast, SQLITE_INDEX_SAMPLES*2-2);
- sqlite3VdbeAddOp3(v, OP_Divide, regTemp2, regLast, regLast);
- sqlite3VdbeJumpHere(v, addr);
+#ifdef SQLITE_ENABLE_STAT3
+ if( once ){
+ once = 0;
+ sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
}
-
- /* Zero the regSampleno and regRecno registers. */
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regSampleno);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regRecno);
- sqlite3VdbeAddOp2(v, OP_Copy, regFirst, regSamplerecno);
-#endif
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regCount);
+ sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_STAT3_SAMPLES, regTemp1);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumEq);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumLt);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regNumDLt);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regCount, regAccum,
+ (char*)&stat3InitFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 2);
+#endif /* SQLITE_ENABLE_STAT3 */
/* The block of memory cells initialized here is used as follows.
**
@@ -236,75 +562,83 @@ static void analyzeOneTable(
endOfLoop = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
topOfLoop = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1);
+ sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); /* Increment row counter */
for(i=0; iazColl!=0 );
assert( pIdx->azColl[i]!=0 );
pColl = sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
- sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1,
- (char*)pColl, P4_COLLSEQ);
+ aChngAddr[i] = sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1,
+ (char*)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
- }
- if( db->mallocFailed ){
- /* If a malloc failure has occurred, then the result of the expression
- ** passed as the second argument to the call to sqlite3VdbeJumpHere()
- ** below may be negative. Which causes an assert() to fail (or an
- ** out-of-bounds write if SQLITE_DEBUG is not defined). */
- return;
+ VdbeComment((v, "jump if column %d changed", i));
+#ifdef SQLITE_ENABLE_STAT3
+ if( i==0 ){
+ sqlite3VdbeAddOp2(v, OP_AddImm, regNumEq, 1);
+ VdbeComment((v, "incr repeat count"));
+ }
+#endif
}
sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
for(i=0; inColumn, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt);
+ sqlite3VdbeAddOp2(v, OP_AddImm, regNumDLt, 1);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regNumEq);
+#endif
}
- sqlite3VdbeJumpHere(v, addr2); /* Set jump dest for the OP_Ne */
sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
}
+ sqlite3DbFree(db, aChngAddr);
- /* End of the analysis loop. */
+ /* Always jump here after updating the iMem+1...iMem+1+nCol counters */
sqlite3VdbeResolveLabel(v, endOfLoop);
+
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
+#ifdef SQLITE_ENABLE_STAT3
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
+ (char*)&stat3PushFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 5);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regLoop);
+ shortJump =
+ sqlite3VdbeAddOp2(v, OP_AddImm, regLoop, 1);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regTemp1,
+ (char*)&stat3GetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 2);
+ sqlite3VdbeAddOp1(v, OP_IsNull, regTemp1);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, shortJump, regTemp1);
+ sqlite3VdbeAddOp3(v, OP_Column, iTabCur, pIdx->aiColumn[0], regSample);
+ sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[0], regSample);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumEq,
+ (char*)&stat3GetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 3);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumLt,
+ (char*)&stat3GetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 4);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumDLt,
+ (char*)&stat3GetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 5);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regRec, "bbbbbb", 0);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, shortJump);
+ sqlite3VdbeJumpHere(v, shortJump+2);
+#endif
/* Store the results in sqlite_stat1.
**
@@ -324,22 +658,22 @@ static void analyzeOneTable(
** If K>0 then it is always the case the D>0 so division by zero
** is never possible.
*/
- sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regSampleno);
+ sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
if( jZeroRows<0 ){
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
}
for(i=0; ipIndex==0 ){
sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb);
VdbeComment((v, "%s", pTab->zName));
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regSampleno);
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat1);
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
- jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regSampleno);
+ jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1);
}else{
sqlite3VdbeJumpHere(v, jZeroRows);
jZeroRows = sqlite3VdbeAddOp0(v, OP_Goto);
}
sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
if( pParse->nMemnMem = regRec;
sqlite3VdbeJumpHere(v, jZeroRows);
}
+
/*
** Generate code that will cause the most recent index analysis to
** be loaded into internal hash tables where is can be used.
@@ -388,7 +723,7 @@ static void analyzeDatabase(Parse *pParse, int iDb){
sqlite3BeginWriteOperation(pParse, 0, iDb);
iStatCur = pParse->nTab;
- pParse->nTab += 2;
+ pParse->nTab += 3;
openStatTable(pParse, iDb, iStatCur, 0, 0);
iMem = pParse->nMem+1;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
@@ -413,7 +748,7 @@ static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
sqlite3BeginWriteOperation(pParse, 0, iDb);
iStatCur = pParse->nTab;
- pParse->nTab += 2;
+ pParse->nTab += 3;
if( pOnlyIdx ){
openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx");
}else{
@@ -518,7 +853,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
Index *pIndex;
Table *pTable;
int i, c, n;
- unsigned int v;
+ tRowcnt v;
const char *z;
assert( argc==3 );
@@ -561,10 +896,10 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
** and its contents.
*/
void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
if( pIdx->aSample ){
int j;
- for(j=0; jnSample; j++){
IndexSample *p = &pIdx->aSample[j];
if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
sqlite3DbFree(db, p->u.z);
@@ -572,25 +907,157 @@ void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
}
sqlite3DbFree(db, pIdx->aSample);
}
+ if( db && db->pnBytesFreed==0 ){
+ pIdx->nSample = 0;
+ pIdx->aSample = 0;
+ }
#else
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(pIdx);
#endif
}
+#ifdef SQLITE_ENABLE_STAT3
/*
-** Load the content of the sqlite_stat1 and sqlite_stat2 tables. The
+** Load content from the sqlite_stat3 table into the Index.aSample[]
+** arrays of all indices.
+*/
+static int loadStat3(sqlite3 *db, const char *zDb){
+ int rc; /* Result codes from subroutines */
+ sqlite3_stmt *pStmt = 0; /* An SQL statement being run */
+ char *zSql; /* Text of the SQL statement */
+ Index *pPrevIdx = 0; /* Previous index in the loop */
+ int idx = 0; /* slot in pIdx->aSample[] for next sample */
+ int eType; /* Datatype of a sample */
+ IndexSample *pSample; /* A slot in pIdx->aSample[] */
+
+ if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
+ return SQLITE_OK;
+ }
+
+ zSql = sqlite3MPrintf(db,
+ "SELECT idx,count(*) FROM %Q.sqlite_stat3"
+ " GROUP BY idx", zDb);
+ if( !zSql ){
+ return SQLITE_NOMEM;
+ }
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ sqlite3DbFree(db, zSql);
+ if( rc ) return rc;
+
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ char *zIndex; /* Index name */
+ Index *pIdx; /* Pointer to the index object */
+ int nSample; /* Number of samples */
+
+ zIndex = (char *)sqlite3_column_text(pStmt, 0);
+ if( zIndex==0 ) continue;
+ nSample = sqlite3_column_int(pStmt, 1);
+ pIdx = sqlite3FindIndex(db, zIndex, zDb);
+ if( pIdx==0 ) continue;
+ assert( pIdx->nSample==0 );
+ pIdx->nSample = nSample;
+ pIdx->aSample = sqlite3MallocZero( nSample*sizeof(IndexSample) );
+ pIdx->avgEq = pIdx->aiRowEst[1];
+ if( pIdx->aSample==0 ){
+ db->mallocFailed = 1;
+ sqlite3_finalize(pStmt);
+ return SQLITE_NOMEM;
+ }
+ }
+ rc = sqlite3_finalize(pStmt);
+ if( rc ) return rc;
+
+ zSql = sqlite3MPrintf(db,
+ "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
+ if( !zSql ){
+ return SQLITE_NOMEM;
+ }
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ sqlite3DbFree(db, zSql);
+ if( rc ) return rc;
+
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ char *zIndex; /* Index name */
+ Index *pIdx; /* Pointer to the index object */
+ int i; /* Loop counter */
+ tRowcnt sumEq; /* Sum of the nEq values */
+
+ zIndex = (char *)sqlite3_column_text(pStmt, 0);
+ if( zIndex==0 ) continue;
+ pIdx = sqlite3FindIndex(db, zIndex, zDb);
+ if( pIdx==0 ) continue;
+ if( pIdx==pPrevIdx ){
+ idx++;
+ }else{
+ pPrevIdx = pIdx;
+ idx = 0;
+ }
+ assert( idxnSample );
+ pSample = &pIdx->aSample[idx];
+ pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 1);
+ pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 2);
+ pSample->nDLt = (tRowcnt)sqlite3_column_int64(pStmt, 3);
+ if( idx==pIdx->nSample-1 ){
+ if( pSample->nDLt>0 ){
+ for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq;
+ pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt;
+ }
+ if( pIdx->avgEq<=0 ) pIdx->avgEq = 1;
+ }
+ eType = sqlite3_column_type(pStmt, 4);
+ pSample->eType = (u8)eType;
+ switch( eType ){
+ case SQLITE_INTEGER: {
+ pSample->u.i = sqlite3_column_int64(pStmt, 4);
+ break;
+ }
+ case SQLITE_FLOAT: {
+ pSample->u.r = sqlite3_column_double(pStmt, 4);
+ break;
+ }
+ case SQLITE_NULL: {
+ break;
+ }
+ default: assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); {
+ const char *z = (const char *)(
+ (eType==SQLITE_BLOB) ?
+ sqlite3_column_blob(pStmt, 4):
+ sqlite3_column_text(pStmt, 4)
+ );
+ int n = z ? sqlite3_column_bytes(pStmt, 4) : 0;
+ pSample->nByte = n;
+ if( n < 1){
+ pSample->u.z = 0;
+ }else{
+ pSample->u.z = sqlite3Malloc(n);
+ if( pSample->u.z==0 ){
+ db->mallocFailed = 1;
+ sqlite3_finalize(pStmt);
+ return SQLITE_NOMEM;
+ }
+ memcpy(pSample->u.z, z, n);
+ }
+ }
+ }
+ }
+ return sqlite3_finalize(pStmt);
+}
+#endif /* SQLITE_ENABLE_STAT3 */
+
+/*
+** Load the content of the sqlite_stat1 and sqlite_stat3 tables. The
** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
-** arrays. The contents of sqlite_stat2 are used to populate the
+** arrays. The contents of sqlite_stat3 are used to populate the
** Index.aSample[] arrays.
**
** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
-** is returned. In this case, even if SQLITE_ENABLE_STAT2 was defined
-** during compilation and the sqlite_stat2 table is present, no data is
+** is returned. In this case, even if SQLITE_ENABLE_STAT3 was defined
+** during compilation and the sqlite_stat3 table is present, no data is
** read from it.
**
-** If SQLITE_ENABLE_STAT2 was defined during compilation and the
-** sqlite_stat2 table is not present in the database, SQLITE_ERROR is
+** If SQLITE_ENABLE_STAT3 was defined during compilation and the
+** sqlite_stat3 table is not present in the database, SQLITE_ERROR is
** returned. However, in this case, data is read from the sqlite_stat1
** table (if it is present) before returning.
**
@@ -612,8 +1079,10 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3DefaultRowEst(pIdx);
+#ifdef SQLITE_ENABLE_STAT3
sqlite3DeleteIndexSamples(db, pIdx);
pIdx->aSample = 0;
+#endif
}
/* Check to make sure the sqlite_stat1 table exists */
@@ -625,7 +1094,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Load new statistics out of the sqlite_stat1 table */
zSql = sqlite3MPrintf(db,
- "SELECT tbl, idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
+ "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -634,78 +1103,10 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
}
- /* Load the statistics from the sqlite_stat2 table. */
-#ifdef SQLITE_ENABLE_STAT2
- if( rc==SQLITE_OK && !sqlite3FindTable(db, "sqlite_stat2", sInfo.zDatabase) ){
- rc = SQLITE_ERROR;
- }
+ /* Load the statistics from the sqlite_stat3 table. */
+#ifdef SQLITE_ENABLE_STAT3
if( rc==SQLITE_OK ){
- sqlite3_stmt *pStmt = 0;
-
- zSql = sqlite3MPrintf(db,
- "SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase);
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- sqlite3DbFree(db, zSql);
- }
-
- if( rc==SQLITE_OK ){
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- char *zIndex; /* Index name */
- Index *pIdx; /* Pointer to the index object */
-
- zIndex = (char *)sqlite3_column_text(pStmt, 0);
- pIdx = zIndex ? sqlite3FindIndex(db, zIndex, sInfo.zDatabase) : 0;
- if( pIdx ){
- int iSample = sqlite3_column_int(pStmt, 1);
- if( iSample=0 ){
- int eType = sqlite3_column_type(pStmt, 2);
-
- if( pIdx->aSample==0 ){
- static const int sz = sizeof(IndexSample)*SQLITE_INDEX_SAMPLES;
- pIdx->aSample = (IndexSample *)sqlite3DbMallocRaw(0, sz);
- if( pIdx->aSample==0 ){
- db->mallocFailed = 1;
- break;
- }
- memset(pIdx->aSample, 0, sz);
- }
-
- assert( pIdx->aSample );
- {
- IndexSample *pSample = &pIdx->aSample[iSample];
- pSample->eType = (u8)eType;
- if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- pSample->u.r = sqlite3_column_double(pStmt, 2);
- }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
- const char *z = (const char *)(
- (eType==SQLITE_BLOB) ?
- sqlite3_column_blob(pStmt, 2):
- sqlite3_column_text(pStmt, 2)
- );
- int n = sqlite3_column_bytes(pStmt, 2);
- if( n>24 ){
- n = 24;
- }
- pSample->nByte = (u8)n;
- if( n < 1){
- pSample->u.z = 0;
- }else{
- pSample->u.z = sqlite3DbStrNDup(0, z, n);
- if( pSample->u.z==0 ){
- db->mallocFailed = 1;
- break;
- }
- }
- }
- }
- }
- }
- }
- rc = sqlite3_finalize(pStmt);
- }
+ rc = loadStat3(db, sInfo.zDatabase);
}
#endif
diff --git a/src/backup.c b/src/backup.c
index 4d7ae318..bdf96bd8 100644
--- a/src/backup.c
+++ b/src/backup.c
@@ -410,102 +410,106 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** the case where the source and destination databases have the
** same schema version.
*/
- if( rc==SQLITE_DONE
- && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK
- ){
- int nDestTruncate;
-
- if( p->pDestDb ){
- sqlite3ResetInternalSchema(p->pDestDb, -1);
- }
-
- /* Set nDestTruncate to the final number of pages in the destination
- ** database. The complication here is that the destination page
- ** size may be different to the source page size.
- **
- ** If the source page size is smaller than the destination page size,
- ** round up. In this case the call to sqlite3OsTruncate() below will
- ** fix the size of the file. However it is important to call
- ** sqlite3PagerTruncateImage() here so that any pages in the
- ** destination file that lie beyond the nDestTruncate page mark are
- ** journalled by PagerCommitPhaseOne() before they are destroyed
- ** by the file truncation.
- */
- assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
- assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
- if( pgszSrcpDest->pBt) ){
- nDestTruncate--;
+ if( rc==SQLITE_DONE ){
+ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+ if( rc==SQLITE_OK ){
+ if( p->pDestDb ){
+ sqlite3ResetInternalSchema(p->pDestDb, -1);
+ }
+ if( destMode==PAGER_JOURNALMODE_WAL ){
+ rc = sqlite3BtreeSetVersion(p->pDest, 2);
}
- }else{
- nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
}
- sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
-
- if( pgszSrc= iSize || (
- nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
- && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
- ));
-
- /* This call ensures that all data required to recreate the original
- ** database has been stored in the journal for pDestPager and the
- ** journal synced to disk. So at this point we may safely modify
- ** the database file in any way, knowing that if a power failure
- ** occurs, the original database will be reconstructed from the
- ** journal file. */
- rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
-
- /* Write the extra pages and truncate the database file as required. */
- iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
- for(
- iOff=PENDING_BYTE+pgszSrc;
- rc==SQLITE_OK && iOffpSrc) );
+ assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
+ if( pgszSrcpDest->pBt) ){
+ nDestTruncate--;
}
- sqlite3PagerUnref(pSrcPg);
- }
- if( rc==SQLITE_OK ){
- rc = backupTruncateFile(pFile, iSize);
+ }else{
+ nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
}
+ sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
- /* Sync the database file to disk. */
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerSync(pDestPager);
+ if( pgszSrc= iSize || (
+ nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
+ && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
+ ));
+
+ /* This call ensures that all data required to recreate the original
+ ** database has been stored in the journal for pDestPager and the
+ ** journal synced to disk. So at this point we may safely modify
+ ** the database file in any way, knowing that if a power failure
+ ** occurs, the original database will be reconstructed from the
+ ** journal file. */
+ rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
+
+ /* Write the extra pages and truncate the database file as required */
+ iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
+ for(
+ iOff=PENDING_BYTE+pgszSrc;
+ rc==SQLITE_OK && iOffpDest, 0))
+ ){
+ rc = SQLITE_DONE;
}
- }else{
- rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
- }
-
- /* Finish committing the transaction to the destination database. */
- if( SQLITE_OK==rc
- && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
- ){
- rc = SQLITE_DONE;
}
}
@@ -539,14 +543,14 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
*/
int sqlite3_backup_finish(sqlite3_backup *p){
sqlite3_backup **pp; /* Ptr to head of pagers backup list */
- sqlite3_mutex *mutex; /* Mutex to protect source database */
+ MUTEX_LOGIC( sqlite3_mutex *mutex; ) /* Mutex to protect source database */
int rc; /* Value to return */
/* Enter the mutexes */
if( p==0 ) return SQLITE_OK;
sqlite3_mutex_enter(p->pSrcDb->mutex);
sqlite3BtreeEnter(p->pSrc);
- mutex = p->pSrcDb->mutex;
+ MUTEX_LOGIC( mutex = p->pSrcDb->mutex; )
if( p->pDestDb ){
sqlite3_mutex_enter(p->pDestDb->mutex);
}
@@ -665,10 +669,18 @@ void sqlite3BackupRestart(sqlite3_backup *pBackup){
*/
int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
int rc;
+ sqlite3_file *pFd; /* File descriptor for database pTo */
sqlite3_backup b;
sqlite3BtreeEnter(pTo);
sqlite3BtreeEnter(pFrom);
+ assert( sqlite3BtreeIsInTrans(pTo) );
+ pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
+ if( pFd->pMethods ){
+ i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
+ sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte);
+ }
+
/* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set
** to 0. This is used by the implementations of sqlite3_backup_step()
** and sqlite3_backup_finish() to detect that they are being called
@@ -692,8 +704,11 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
rc = sqlite3_backup_finish(&b);
if( rc==SQLITE_OK ){
pTo->pBt->pageSizeFixed = 0;
+ }else{
+ sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
}
+ assert( sqlite3BtreeIsInTrans(pTo)==0 );
sqlite3BtreeLeave(pFrom);
sqlite3BtreeLeave(pTo);
return rc;
diff --git a/src/btree.c b/src/btree.c
index 3d7162db..d64e172f 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -656,18 +656,21 @@ static int btreeMoveto(
int rc; /* Status code */
UnpackedRecord *pIdxKey; /* Unpacked index key */
char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */
+ char *pFree = 0;
if( pKey ){
assert( nKey==(i64)(int)nKey );
- pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey,
- aSpace, sizeof(aSpace));
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+ pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
+ );
if( pIdxKey==0 ) return SQLITE_NOMEM;
+ sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
}else{
pIdxKey = 0;
}
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
- if( pKey ){
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ if( pFree ){
+ sqlite3DbFree(pCur->pKeyInfo->db, pFree);
}
return rc;
}
@@ -1763,17 +1766,19 @@ int sqlite3BtreeOpen(
if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
int nFullPathname = pVfs->mxPathname+1;
char *zFullPathname = sqlite3Malloc(nFullPathname);
- sqlite3_mutex *mutexShared;
+ MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
p->sharable = 1;
if( !zFullPathname ){
sqlite3_free(p);
return SQLITE_NOMEM;
}
sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
+#if SQLITE_THREADSAFE
mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
sqlite3_mutex_enter(mutexOpen);
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(mutexShared);
+#endif
for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
assert( pBt->nRef>0 );
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
@@ -1879,9 +1884,9 @@ int sqlite3BtreeOpen(
/* Add the new BtShared object to the linked list sharable BtShareds.
*/
if( p->sharable ){
- sqlite3_mutex *mutexShared;
+ MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
pBt->nRef = 1;
- mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
@@ -1963,12 +1968,12 @@ btree_open_out:
*/
static int removeFromSharingList(BtShared *pBt){
#ifndef SQLITE_OMIT_SHARED_CACHE
- sqlite3_mutex *pMaster;
+ MUTEX_LOGIC( sqlite3_mutex *pMaster; )
BtShared *pList;
int removed = 0;
assert( sqlite3_mutex_notheld(pBt->mutex) );
- pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
sqlite3_mutex_enter(pMaster);
pBt->nRef--;
if( pBt->nRef<=0 ){
@@ -2743,11 +2748,12 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( eType==PTRMAP_OVERFLOW1 ){
CellInfo info;
btreeParseCellPtr(pPage, pCell, &info);
- if( info.iOverflow ){
- if( iFrom==get4byte(&pCell[info.iOverflow]) ){
- put4byte(&pCell[info.iOverflow], iTo);
- break;
- }
+ if( info.iOverflow
+ && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
+ && iFrom==get4byte(&pCell[info.iOverflow])
+ ){
+ put4byte(&pCell[info.iOverflow], iTo);
+ break;
}
}else{
if( get4byte(pCell)==iFrom ){
@@ -3468,7 +3474,8 @@ static int btreeCursor(
return SQLITE_READONLY;
}
if( iTable==1 && btreePagecount(pBt)==0 ){
- return SQLITE_EMPTY;
+ assert( wrFlag==0 );
+ iTable = 0;
}
/* Now that no other errors can occur, finish filling in the BtCursor
@@ -3933,21 +3940,55 @@ static int accessPayload(
/* Need to read this page properly. It contains some of the
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
- DbPage *pDbPage;
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ sqlite3_file *fd;
+#endif
int a = amt;
- rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
- if( rc==SQLITE_OK ){
- aPayload = sqlite3PagerGetData(pDbPage);
- nextPage = get4byte(aPayload);
- if( a + offset > ovflSize ){
- a = ovflSize - offset;
- }
- rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
- sqlite3PagerUnref(pDbPage);
- offset = 0;
- amt -= a;
- pBuf += a;
+ if( a + offset > ovflSize ){
+ a = ovflSize - offset;
}
+
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ /* If all the following are true:
+ **
+ ** 1) this is a read operation, and
+ ** 2) data is required from the start of this overflow page, and
+ ** 3) the database is file-backed, and
+ ** 4) there is no open write-transaction, and
+ ** 5) the database is not a WAL database,
+ **
+ ** then data can be read directly from the database file into the
+ ** output buffer, bypassing the page-cache altogether. This speeds
+ ** up loading large records that span many overflow pages.
+ */
+ if( eOp==0 /* (1) */
+ && offset==0 /* (2) */
+ && pBt->inTransaction==TRANS_READ /* (4) */
+ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
+ && pBt->pPage1->aData[19]==0x01 /* (5) */
+ ){
+ u8 aSave[4];
+ u8 *aWrite = &pBuf[-4];
+ memcpy(aSave, aWrite, 4);
+ rc = sqlite3OsRead(fd, aWrite, a+4, pBt->pageSize * (nextPage-1));
+ nextPage = get4byte(aWrite);
+ memcpy(aWrite, aSave, 4);
+ }else
+#endif
+
+ {
+ DbPage *pDbPage;
+ rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
+ if( rc==SQLITE_OK ){
+ aPayload = sqlite3PagerGetData(pDbPage);
+ nextPage = get4byte(aPayload);
+ rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
+ sqlite3PagerUnref(pDbPage);
+ offset = 0;
+ }
+ }
+ amt -= a;
+ pBuf += a;
}
}
}
@@ -4222,6 +4263,9 @@ static int moveToRoot(BtCursor *pCur){
releasePage(pCur->apPage[i]);
}
pCur->iPage = 0;
+ }else if( pCur->pgnoRoot==0 ){
+ pCur->eState = CURSOR_INVALID;
+ return SQLITE_OK;
}else{
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
if( rc!=SQLITE_OK ){
@@ -4331,7 +4375,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
if( pCur->eState==CURSOR_INVALID ){
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
*pRes = 1;
}else{
assert( pCur->apPage[pCur->iPage]->nCell>0 );
@@ -4370,7 +4414,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
if( CURSOR_INVALID==pCur->eState ){
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
*pRes = 1;
}else{
assert( pCur->eState==CURSOR_VALID );
@@ -4443,12 +4487,12 @@ int sqlite3BtreeMovetoUnpacked(
if( rc ){
return rc;
}
- assert( pCur->apPage[pCur->iPage] );
- assert( pCur->apPage[pCur->iPage]->isInit );
- assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID );
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
+ assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
if( pCur->eState==CURSOR_INVALID ){
*pRes = -1;
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
return SQLITE_OK;
}
assert( pCur->apPage[0]->intKey || pIdxKey );
@@ -4543,7 +4587,6 @@ int sqlite3BtreeMovetoUnpacked(
if( c==0 ){
if( pPage->intKey && !pPage->leaf ){
lwr = idx;
- upr = lwr - 1;
break;
}else{
*pRes = 0;
@@ -4561,7 +4604,7 @@ int sqlite3BtreeMovetoUnpacked(
}
pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2);
}
- assert( lwr==upr+1 );
+ assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
chldPg = 0;
@@ -4826,6 +4869,8 @@ static int allocateBtreePage(
pTrunk = 0;
goto end_allocate_page;
}
+ assert( pTrunk!=0 );
+ assert( pTrunk->aData!=0 );
k = get4byte(&pTrunk->aData[4]); /* # of leaves on this trunk page */
if( k==0 && !searchList ){
@@ -5175,6 +5220,9 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
if( info.iOverflow==0 ){
return SQLITE_OK; /* No overflow pages. Return without doing anything */
}
+ if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
+ return SQLITE_CORRUPT; /* Cell extends past end of page */
+ }
ovflPgno = get4byte(&pCell[info.iOverflow]);
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
@@ -5950,13 +5998,15 @@ static int balance_nonroot(
** four bytes of the divider cell. So the pointer is safe to use
** later on.
**
- ** Unless SQLite is compiled in secure-delete mode. In this case,
+ ** But not if we are in secure-delete mode. In secure-delete mode,
** the dropCell() routine will overwrite the entire cell with zeroes.
** In this case, temporarily copy the cell into the aOvflSpace[]
** buffer. It will be copied out again as soon as the aSpace[] buffer
** is allocated. */
if( pBt->secureDelete ){
- int iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
+ int iOff;
+
+ iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
if( (iOff+szNew[i])>(int)pBt->usableSize ){
rc = SQLITE_CORRUPT_BKPT;
memset(apOld, 0, (i+1)*sizeof(MemPage*));
@@ -6376,6 +6426,7 @@ static int balance_nonroot(
/* Cell i is the cell immediately following the last cell on old
** sibling page j. If the siblings are not leaf pages of an
** intkey b-tree, then cell i was a divider cell. */
+ assert( j+1 < ArraySize(apCopy) );
pOld = apCopy[++j];
iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow;
if( pOld->nOverflow ){
@@ -7358,6 +7409,11 @@ int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */
+
+ if( pCur->pgnoRoot==0 ){
+ *pnEntry = 0;
+ return SQLITE_OK;
+ }
rc = moveToRoot(pCur);
/* Unless an error occurs, the following loop runs one iteration for each
@@ -8142,7 +8198,6 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
BtShared *pBt = pBtree->pBt;
int rc; /* Return code */
- assert( pBtree->inTrans==TRANS_NONE );
assert( iVersion==1 || iVersion==2 );
/* If setting the version fields to 1, do not automatically open the
diff --git a/src/build.c b/src/build.c
index 97758cbc..e23aab6b 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1674,7 +1674,7 @@ void sqlite3CreateView(
const char *z;
Token sEnd;
DbFixer sFix;
- Token *pName;
+ Token *pName = 0;
int iDb;
sqlite3 *db = pParse->db;
@@ -1980,6 +1980,100 @@ static void destroyTable(Parse *pParse, Table *pTab){
#endif
}
+/*
+** Remove entries from the sqlite_statN tables (for N in (1,2,3))
+** after a DROP INDEX or DROP TABLE command.
+*/
+static void sqlite3ClearStatTables(
+ Parse *pParse, /* The parsing context */
+ int iDb, /* The database number */
+ const char *zType, /* "idx" or "tbl" */
+ const char *zName /* Name of index or table */
+){
+ int i;
+ const char *zDbName = pParse->db->aDb[iDb].zName;
+ for(i=1; i<=3; i++){
+ char zTab[24];
+ sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
+ if( sqlite3FindTable(pParse->db, zTab, zDbName) ){
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.%s WHERE %s=%Q",
+ zDbName, zTab, zType, zName
+ );
+ }
+ }
+}
+
+/*
+** Generate code to drop a table.
+*/
+void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
+ Vdbe *v;
+ sqlite3 *db = pParse->db;
+ Trigger *pTrigger;
+ Db *pDb = &db->aDb[iDb];
+
+ v = sqlite3GetVdbe(pParse);
+ assert( v!=0 );
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3VdbeAddOp0(v, OP_VBegin);
+ }
+#endif
+
+ /* Drop all triggers associated with the table being dropped. Code
+ ** is generated to remove entries from sqlite_master and/or
+ ** sqlite_temp_master if required.
+ */
+ pTrigger = sqlite3TriggerList(pParse, pTab);
+ while( pTrigger ){
+ assert( pTrigger->pSchema==pTab->pSchema ||
+ pTrigger->pSchema==db->aDb[1].pSchema );
+ sqlite3DropTriggerPtr(pParse, pTrigger);
+ pTrigger = pTrigger->pNext;
+ }
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* Remove any entries of the sqlite_sequence table associated with
+ ** the table being dropped. This is done before the table is dropped
+ ** at the btree level, in case the sqlite_sequence table needs to
+ ** move as a result of the drop (can happen in auto-vacuum mode).
+ */
+ if( pTab->tabFlags & TF_Autoincrement ){
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.sqlite_sequence WHERE name=%Q",
+ pDb->zName, pTab->zName
+ );
+ }
+#endif
+
+ /* Drop all SQLITE_MASTER table and index entries that refer to the
+ ** table. The program name loops through the master table and deletes
+ ** every row that refers to a table of the same name as the one being
+ ** dropped. Triggers are handled seperately because a trigger can be
+ ** created in the temp database that refers to a table in another
+ ** database.
+ */
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
+ pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
+ if( !isView && !IsVirtual(pTab) ){
+ destroyTable(pParse, pTab);
+ }
+
+ /* Remove the table entry from SQLite's internal schema and modify
+ ** the schema cookie.
+ */
+ if( IsVirtual(pTab) ){
+ sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
+ }
+ sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
+ sqlite3ChangeCookie(pParse, iDb);
+ sqliteViewResetAll(db, iDb);
+}
+
/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
@@ -2048,7 +2142,8 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
}
#endif
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
+ && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
goto exit_drop_table;
}
@@ -2072,75 +2167,11 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
*/
v = sqlite3GetVdbe(pParse);
if( v ){
- Trigger *pTrigger;
- Db *pDb = &db->aDb[iDb];
sqlite3BeginWriteOperation(pParse, 1, iDb);
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab) ){
- sqlite3VdbeAddOp0(v, OP_VBegin);
- }
-#endif
+ sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
sqlite3FkDropTable(pParse, pName, pTab);
-
- /* Drop all triggers associated with the table being dropped. Code
- ** is generated to remove entries from sqlite_master and/or
- ** sqlite_temp_master if required.
- */
- pTrigger = sqlite3TriggerList(pParse, pTab);
- while( pTrigger ){
- assert( pTrigger->pSchema==pTab->pSchema ||
- pTrigger->pSchema==db->aDb[1].pSchema );
- sqlite3DropTriggerPtr(pParse, pTrigger);
- pTrigger = pTrigger->pNext;
- }
-
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- /* Remove any entries of the sqlite_sequence table associated with
- ** the table being dropped. This is done before the table is dropped
- ** at the btree level, in case the sqlite_sequence table needs to
- ** move as a result of the drop (can happen in auto-vacuum mode).
- */
- if( pTab->tabFlags & TF_Autoincrement ){
- sqlite3NestedParse(pParse,
- "DELETE FROM %s.sqlite_sequence WHERE name=%Q",
- pDb->zName, pTab->zName
- );
- }
-#endif
-
- /* Drop all SQLITE_MASTER table and index entries that refer to the
- ** table. The program name loops through the master table and deletes
- ** every row that refers to a table of the same name as the one being
- ** dropped. Triggers are handled seperately because a trigger can be
- ** created in the temp database that refers to a table in another
- ** database.
- */
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
- pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
-
- /* Drop any statistics from the sqlite_stat1 table, if it exists */
- if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb->zName, pTab->zName
- );
- }
-
- if( !isView && !IsVirtual(pTab) ){
- destroyTable(pParse, pTab);
- }
-
- /* Remove the table entry from SQLite's internal schema and modify
- ** the schema cookie.
- */
- if( IsVirtual(pTab) ){
- sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
- }
- sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
- sqlite3ChangeCookie(pParse, iDb);
+ sqlite3CodeDropTable(pParse, pTab, iDb, isView);
}
- sqliteViewResetAll(db, iDb);
exit_drop_table:
sqlite3SrcListDelete(db, pName);
@@ -2308,11 +2339,15 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
Table *pTab = pIndex->pTable; /* The table that is indexed */
int iTab = pParse->nTab++; /* Btree cursor used for pTab */
int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
+ int iSorter; /* Cursor opened by OpenSorter (if in use) */
int addr1; /* Address of top of loop */
+ int addr2; /* Address to jump to for next iteration */
int tnum; /* Root page of index */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
+#ifdef SQLITE_OMIT_MERGE_SORT
int regIdxKey; /* Registers containing the index key */
+#endif
int regRecord; /* Register holding assemblied index record */
sqlite3 *db = pParse->db; /* The database connection */
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
@@ -2341,10 +2376,44 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
if( memRootPage>=0 ){
sqlite3VdbeChangeP5(v, 1);
}
+
+#ifndef SQLITE_OMIT_MERGE_SORT
+ /* Open the sorter cursor if we are to use one. */
+ iSorter = pParse->nTab++;
+ sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
+#else
+ iSorter = iTab;
+#endif
+
+ /* Open the table. Loop through all rows of the table, inserting index
+ ** records into the sorter. */
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
regRecord = sqlite3GetTempReg(pParse);
+
+#ifndef SQLITE_OMIT_MERGE_SORT
+ sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
+ sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
+ sqlite3VdbeJumpHere(v, addr1);
+ addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
+ if( pIndex->onError!=OE_None ){
+ int j2 = sqlite3VdbeCurrentAddr(v) + 3;
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
+ addr2 = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
+ sqlite3HaltConstraint(
+ pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
+ );
+ }else{
+ addr2 = sqlite3VdbeCurrentAddr(v);
+ }
+ sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+#else
regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
+ addr2 = addr1 + 1;
if( pIndex->onError!=OE_None ){
const int regRowid = regIdxKey + pIndex->nColumn;
const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
@@ -2363,13 +2432,16 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3HaltConstraint(
pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
}
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+#endif
sqlite3ReleaseTempReg(pParse, regRecord);
- sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
+ sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
sqlite3VdbeJumpHere(v, addr1);
+
sqlite3VdbeAddOp1(v, OP_Close, iTab);
sqlite3VdbeAddOp1(v, OP_Close, iIdx);
+ sqlite3VdbeAddOp1(v, OP_Close, iSorter);
}
/*
@@ -2439,6 +2511,7 @@ Index *sqlite3CreateIndex(
assert( pName1 && pName2 );
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
if( iDb<0 ) goto exit_create_index;
+ assert( pName && pName->z );
#ifndef SQLITE_OMIT_TEMPDB
/* If the index name was unqualified, check if the the table
@@ -2466,6 +2539,7 @@ Index *sqlite3CreateIndex(
assert( db->aDb[iDb].pSchema==pTab->pSchema );
}else{
assert( pName==0 );
+ assert( pStart==0 );
pTab = pParse->pNewTable;
if( !pTab ) goto exit_create_index;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -2508,6 +2582,7 @@ Index *sqlite3CreateIndex(
if( pName ){
zName = sqlite3NameFromToken(db, pName);
if( zName==0 ) goto exit_create_index;
+ assert( pName->z!=0 );
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto exit_create_index;
}
@@ -2587,8 +2662,8 @@ Index *sqlite3CreateIndex(
nCol = pList->nExpr;
pIndex = sqlite3DbMallocZero(db,
sizeof(Index) + /* Index structure */
+ sizeof(tRowcnt)*(nCol+1) + /* Index.aiRowEst */
sizeof(int)*nCol + /* Index.aiColumn */
- sizeof(int)*(nCol+1) + /* Index.aiRowEst */
sizeof(char *)*nCol + /* Index.azColl */
sizeof(u8)*nCol + /* Index.aSortOrder */
nName + 1 + /* Index.zName */
@@ -2597,10 +2672,10 @@ Index *sqlite3CreateIndex(
if( db->mallocFailed ){
goto exit_create_index;
}
- pIndex->azColl = (char**)(&pIndex[1]);
+ pIndex->aiRowEst = (tRowcnt*)(&pIndex[1]);
+ pIndex->azColl = (char**)(&pIndex->aiRowEst[nCol+1]);
pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
- pIndex->aiRowEst = (unsigned *)(&pIndex->aiColumn[nCol]);
- pIndex->aSortOrder = (u8 *)(&pIndex->aiRowEst[nCol+1]);
+ pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]);
pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
zExtra = (char *)(&pIndex->zName[nName+1]);
memcpy(pIndex->zName, zName, nName+1);
@@ -2791,7 +2866,7 @@ Index *sqlite3CreateIndex(
/* A named index with an explicit CREATE INDEX statement */
zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
onError==OE_None ? "" : " UNIQUE",
- pEnd->z - pName->z + 1,
+ (int)(pEnd->z - pName->z) + 1,
pName->z);
}else{
/* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
@@ -2877,9 +2952,9 @@ exit_create_index:
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
- unsigned *a = pIdx->aiRowEst;
+ tRowcnt *a = pIdx->aiRowEst;
int i;
- unsigned n;
+ tRowcnt n;
assert( a!=0 );
a[0] = pIdx->pTable->nRowEst;
if( a[0]<10 ) a[0] = 10;
@@ -2949,15 +3024,9 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
- db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
- pIndex->zName
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName
);
- if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q",
- db->aDb[iDb].zName, pIndex->zName
- );
- }
+ sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
sqlite3ChangeCookie(pParse, iDb);
destroyRootPage(pParse, pIndex->tnum, iDb);
sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
@@ -3329,8 +3398,9 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
** operator with A. This routine shifts that operator over to B.
*/
void sqlite3SrcListShiftJoinType(SrcList *p){
- if( p && p->a ){
+ if( p ){
int i;
+ assert( p->a || p->nSrc==0 );
for(i=p->nSrc-1; i>0; i--){
p->a[i].jointype = p->a[i-1].jointype;
}
@@ -3368,13 +3438,10 @@ void sqlite3BeginTransaction(Parse *pParse, int type){
** Commit a transaction
*/
void sqlite3CommitTransaction(Parse *pParse){
- sqlite3 *db;
Vdbe *v;
assert( pParse!=0 );
- db = pParse->db;
- assert( db!=0 );
-/* if( db->aDb[0].pBt==0 ) return; */
+ assert( pParse->db!=0 );
if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){
return;
}
@@ -3388,13 +3455,10 @@ void sqlite3CommitTransaction(Parse *pParse){
** Rollback a transaction
*/
void sqlite3RollbackTransaction(Parse *pParse){
- sqlite3 *db;
Vdbe *v;
assert( pParse!=0 );
- db = pParse->db;
- assert( db!=0 );
-/* if( db->aDb[0].pBt==0 ) return; */
+ assert( pParse->db!=0 );
if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ){
return;
}
diff --git a/src/ctime.c b/src/ctime.c
index a128f61a..1688069c 100644
--- a/src/ctime.c
+++ b/src/ctime.c
@@ -114,8 +114,8 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_ENABLE_RTREE
"ENABLE_RTREE",
#endif
-#ifdef SQLITE_ENABLE_STAT2
- "ENABLE_STAT2",
+#ifdef SQLITE_ENABLE_STAT3
+ "ENABLE_STAT3",
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
"ENABLE_UNLOCK_NOTIFY",
@@ -144,6 +144,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_LOCK_TRACE
"LOCK_TRACE",
#endif
+#ifdef SQLITE_MAX_SCHEMA_RETRY
+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
+#endif
#ifdef SQLITE_MEMDEBUG
"MEMDEBUG",
#endif
@@ -257,6 +260,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_MEMORYDB
"OMIT_MEMORYDB",
#endif
+#ifdef SQLITE_OMIT_MERGE_SORT
+ "OMIT_MERGE_SORT",
+#endif
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
"OMIT_OR_OPTIMIZATION",
#endif
diff --git a/src/date.c b/src/date.c
index c0744e8c..758dd7c8 100644
--- a/src/date.c
+++ b/src/date.c
@@ -289,12 +289,18 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
}
/*
-** Set the time to the current time reported by the VFS
+** Set the time to the current time reported by the VFS.
+**
+** Return the number of errors.
*/
-static void setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
+static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
sqlite3 *db = sqlite3_context_db_handle(context);
- sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD);
- p->validJD = 1;
+ if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
+ p->validJD = 1;
+ return 0;
+ }else{
+ return 1;
+ }
}
/*
@@ -324,8 +330,7 @@ static int parseDateOrTime(
}else if( parseHhMmSs(zDate, p)==0 ){
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0){
- setDateTimeToCurrent(context, p);
- return 0;
+ return setDateTimeToCurrent(context, p);
}else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
p->validJD = 1;
@@ -427,7 +432,9 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#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);
+#endif
sqlite3_mutex_enter(mutex);
pX = localtime(t);
#ifndef SQLITE_OMIT_BUILTIN_TEST
@@ -750,8 +757,9 @@ static int isDate(
int eType;
memset(p, 0, sizeof(*p));
if( argc==0 ){
- setDateTimeToCurrent(context, p);
- }else if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
+ return setDateTimeToCurrent(context, p);
+ }
+ if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
|| eType==SQLITE_INTEGER ){
p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
p->validJD = 1;
@@ -1063,31 +1071,28 @@ static void currentTimeFunc(
char *zFormat = (char *)sqlite3_user_data(context);
sqlite3 *db;
sqlite3_int64 iT;
+ struct tm *pTm;
+ struct tm sNow;
char zBuf[20];
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
db = sqlite3_context_db_handle(context);
- sqlite3OsCurrentTimeInt64(db->pVfs, &iT);
+ if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
t = iT/1000 - 10000*(sqlite3_int64)21086676;
#ifdef HAVE_GMTIME_R
- {
- struct tm sNow;
- gmtime_r(&t, &sNow);
- strftime(zBuf, 20, zFormat, &sNow);
- }
+ pTm = gmtime_r(&t, &sNow);
#else
- {
- struct tm *pTm;
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- pTm = gmtime(&t);
- strftime(zBuf, 20, zFormat, pTm);
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- }
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+ pTm = gmtime(&t);
+ if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
#endif
-
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ if( pTm ){
+ strftime(zBuf, 20, zFormat, &sNow);
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ }
}
#endif
diff --git a/src/delete.c b/src/delete.c
index ec0ecec7..147a5ca8 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -371,7 +371,9 @@ void sqlite3DeleteFrom(
/* Collect rowids of every row to be deleted.
*/
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
+ pWInfo = sqlite3WhereBegin(
+ pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
+ );
if( pWInfo==0 ) goto delete_from_cleanup;
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
diff --git a/src/expr.c b/src/expr.c
index be2f4d7c..d5061737 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -403,7 +403,8 @@ Expr *sqlite3ExprAlloc(
}else{
int c;
pNew->u.zToken = (char*)&pNew[1];
- memcpy(pNew->u.zToken, pToken->z, pToken->n);
+ assert( pToken->z!=0 || pToken->n==0 );
+ if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
pNew->u.zToken[pToken->n] = 0;
if( dequote && nExtra>=3
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
@@ -901,7 +902,9 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
- pNewItem->isPopulated = pOldItem->isPopulated;
+ pNewItem->addrFillSub = pOldItem->addrFillSub;
+ pNewItem->regReturn = pOldItem->regReturn;
+ pNewItem->isCorrelated = pOldItem->isCorrelated;
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
pNewItem->notIndexed = pOldItem->notIndexed;
pNewItem->pIndex = pOldItem->pIndex;
@@ -1440,11 +1443,19 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
sqlite3 *db = pParse->db; /* Database connection */
- Expr *pExpr = p->pEList->a[0].pExpr; /* Expression */
- int iCol = pExpr->iColumn; /* Index of column */
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
- Table *pTab = p->pSrc->a[0].pTab; /* Table . */
+ Table *pTab; /* Table . */
+ Expr *pExpr; /* Expression */
+ int iCol; /* Index of column */
int iDb; /* Database idx for pTab */
+
+ assert( p ); /* Because of isCandidateForInOpt(p) */
+ assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
+ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
+ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
+ pTab = p->pSrc->a[0].pTab;
+ pExpr = p->pEList->a[0].pExpr;
+ iCol = pExpr->iColumn;
/* Code an OP_VerifyCookie and OP_TableLock for . */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -1460,8 +1471,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
int iMem = ++pParse->nMem;
int iAddr;
- iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+ iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
eType = IN_INDEX_ROWID;
@@ -1492,8 +1502,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
char *pKey;
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
- iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+ iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
@@ -1574,7 +1583,7 @@ int sqlite3CodeSubselect(
int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
int isRowid /* If true, LHS of IN operator is a rowid */
){
- int testAddr = 0; /* One-time test address */
+ int testAddr = -1; /* One-time test address */
int rReg = 0; /* Register storing resulting */
Vdbe *v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return 0;
@@ -1592,15 +1601,13 @@ int sqlite3CodeSubselect(
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
int mem = ++pParse->nMem;
- sqlite3VdbeAddOp1(v, OP_If, mem);
- testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
- assert( testAddr>0 || pParse->db->mallocFailed );
+ testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
}
#ifndef SQLITE_OMIT_EXPLAIN
if( pParse->explain==2 ){
char *zMsg = sqlite3MPrintf(
- pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr?"":"CORRELATED ",
+ pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
);
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
@@ -1692,9 +1699,9 @@ int sqlite3CodeSubselect(
** this code only executes once. Because for a non-constant
** expression we need to rerun this code each time.
*/
- if( testAddr && !sqlite3ExprIsConstant(pE2) ){
- sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
- testAddr = 0;
+ if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
+ sqlite3VdbeChangeToNoop(v, testAddr);
+ testAddr = -1;
}
/* Evaluate the expression and insert it into the temp table */
@@ -1763,8 +1770,8 @@ int sqlite3CodeSubselect(
}
}
- if( testAddr ){
- sqlite3VdbeJumpHere(v, testAddr-1);
+ if( testAddr>=0 ){
+ sqlite3VdbeJumpHere(v, testAddr);
}
sqlite3ExprCachePop(pParse, 1);
@@ -2286,7 +2293,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
inReg = pCol->iMem;
break;
}else if( pAggInfo->useSortingIdx ){
- sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,
+ sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
pCol->iSorterColumn, target);
break;
}
@@ -3455,7 +3462,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
}
}else if( pA->op!=TK_COLUMN && pA->u.zToken ){
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
- if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){
+ if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
return 2;
}
}
diff --git a/src/fkey.c b/src/fkey.c
index dda8a50d..82e4cdc4 100644
--- a/src/fkey.c
+++ b/src/fkey.c
@@ -560,7 +560,7 @@ static void fkScanChildren(
** clause. If the constraint is not deferred, throw an exception for
** each row found. Otherwise, for deferred constraints, increment the
** deferred constraint counter by nIncr for each row selected. */
- pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
if( nIncr>0 && pFKey->isDeferred==0 ){
sqlite3ParseToplevel(pParse)->mayAbort = 1;
}
@@ -734,7 +734,24 @@ void sqlite3FkCheck(
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
}
if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
+ assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
if( !isIgnoreErrors || db->mallocFailed ) return;
+ if( pTo==0 ){
+ /* If isIgnoreErrors is true, then a table is being dropped. In this
+ ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
+ ** before actually dropping it in order to check FK constraints.
+ ** If the parent table of an FK constraint on the current table is
+ ** missing, behave as if it is empty. i.e. decrement the relevant
+ ** FK counter for each row of the current table with non-NULL keys.
+ */
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
+ for(i=0; inCol; i++){
+ int iReg = pFKey->aCol[i].iFrom + regOld + 1;
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump);
+ }
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
+ }
continue;
}
assert( pFKey->nCol==1 || (aiFree && pIdx) );
@@ -1107,6 +1124,7 @@ static Trigger *fkActionTrigger(
fkTriggerDelete(db, pTrigger);
return 0;
}
+ assert( pStep!=0 );
switch( action ){
case OE_Restrict:
diff --git a/src/func.c b/src/func.c
index 16de6bbb..3a1879ca 100644
--- a/src/func.c
+++ b/src/func.c
@@ -332,16 +332,15 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
if( z2 ){
z1 = contextMalloc(context, ((i64)n)+1);
if( z1 ){
- memcpy(z1, z2, n+1);
- for(i=0; z1[i]; i++){
- z1[i] = (char)sqlite3Toupper(z1[i]);
+ for(i=0; idb->flags & SQLITE_CountRows)!=0 ){
+ return 0;
+ }
/* If we get this far, it means either:
**
diff --git a/src/lempar.c b/src/lempar.c
index fb52490e..cb6025e8 100644
--- a/src/lempar.c
+++ b/src/lempar.c
@@ -716,7 +716,9 @@ void Parse(
){
YYMINORTYPE yyminorunion;
int yyact; /* The parser action. */
+#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
int yyendofinput; /* True if we are at the end of input */
+#endif
#ifdef YYERRORSYMBOL
int yyerrorhit = 0; /* True if yymajor has invoked an error */
#endif
@@ -739,7 +741,9 @@ void Parse(
yypParser->yystack[0].major = 0;
}
yyminorunion.yy0 = yyminor;
+#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
yyendofinput = (yymajor==0);
+#endif
ParseARG_STORE;
#ifndef NDEBUG
@@ -751,7 +755,6 @@ void Parse(
do{
yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
if( yyactyyerrcnt--;
yymajor = YYNOCODE;
diff --git a/src/loadext.c b/src/loadext.c
index c832e684..e9c97adf 100644
--- a/src/loadext.c
+++ b/src/loadext.c
@@ -84,6 +84,8 @@
# define sqlite3_create_module 0
# define sqlite3_create_module_v2 0
# define sqlite3_declare_vtab 0
+# define sqlite3_vtab_config 0
+# define sqlite3_vtab_on_conflict 0
#endif
#ifdef SQLITE_OMIT_SHARED_CACHE
@@ -107,6 +109,7 @@
#define sqlite3_blob_open 0
#define sqlite3_blob_read 0
#define sqlite3_blob_write 0
+#define sqlite3_blob_reopen 0
#endif
/*
@@ -372,6 +375,9 @@ static const sqlite3_api_routines sqlite3Apis = {
0,
0,
#endif
+ sqlite3_blob_reopen,
+ sqlite3_vtab_config,
+ sqlite3_vtab_on_conflict,
};
/*
@@ -397,7 +403,7 @@ static int sqlite3LoadExtension(
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
char *zErrmsg = 0;
void **aHandle;
- const int nMsg = 300;
+ int nMsg = 300 + sqlite3Strlen30(zFile);
if( pzErrMsg ) *pzErrMsg = 0;
@@ -434,6 +440,7 @@ static int sqlite3LoadExtension(
sqlite3OsDlSym(pVfs, handle, zProc);
if( xInit==0 ){
if( pzErrMsg ){
+ nMsg += sqlite3Strlen30(zProc);
*pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
diff --git a/src/main.c b/src/main.c
index b2366304..42bbba5d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -106,7 +106,7 @@ char *sqlite3_temp_directory = 0;
** without blocking.
*/
int sqlite3_initialize(void){
- sqlite3_mutex *pMaster; /* The main static mutex */
+ MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
int rc; /* Result code */
#ifdef SQLITE_OMIT_WSD
@@ -140,7 +140,7 @@ int sqlite3_initialize(void){
** malloc subsystem - this implies that the allocation of a static
** mutex must not require support from the malloc subsystem.
*/
- pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
sqlite3_mutex_enter(pMaster);
sqlite3GlobalConfig.isMutexInit = 1;
if( !sqlite3GlobalConfig.isMallocInit ){
@@ -234,6 +234,16 @@ int sqlite3_initialize(void){
#endif
#endif
+ /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
+ ** compile-time option.
+ */
+#ifdef SQLITE_EXTRA_INIT
+ if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
+ int SQLITE_EXTRA_INIT(void);
+ rc = SQLITE_EXTRA_INIT();
+ }
+#endif
+
return rc;
}
@@ -1204,13 +1214,13 @@ int sqlite3_overload_function(
int nArg
){
int nName = sqlite3Strlen30(zName);
- int rc;
+ int rc = SQLITE_OK;
sqlite3_mutex_enter(db->mutex);
if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){
- sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
- 0, sqlite3InvalidFunction, 0, 0, 0);
+ rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
+ 0, sqlite3InvalidFunction, 0, 0, 0);
}
- rc = sqlite3ApiExit(db, SQLITE_OK);
+ rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -2272,6 +2282,7 @@ opendb_out:
sqlite3_mutex_leave(db->mutex);
}
rc = sqlite3_errcode(db);
+ assert( db!=0 || rc==SQLITE_NOMEM );
if( rc==SQLITE_NOMEM ){
sqlite3_close(db);
db = 0;
diff --git a/src/mem3.c b/src/mem3.c
index e2d66815..1a1b791f 100644
--- a/src/mem3.c
+++ b/src/mem3.c
@@ -433,7 +433,7 @@ static void *memsys3MallocUnsafe(int nByte){
** This function assumes that the necessary mutexes, if any, are
** already held by the caller. Hence "Unsafe".
*/
-void memsys3FreeUnsafe(void *pOld){
+static void memsys3FreeUnsafe(void *pOld){
Mem3Block *p = (Mem3Block*)pOld;
int i;
u32 size, x;
@@ -508,7 +508,7 @@ static void *memsys3Malloc(int nBytes){
/*
** Free memory.
*/
-void memsys3Free(void *pPrior){
+static void memsys3Free(void *pPrior){
assert( pPrior );
memsys3Enter();
memsys3FreeUnsafe(pPrior);
@@ -518,7 +518,7 @@ void memsys3Free(void *pPrior){
/*
** Change the size of an existing memory allocation
*/
-void *memsys3Realloc(void *pPrior, int nBytes){
+static void *memsys3Realloc(void *pPrior, int nBytes){
int nOld;
void *p;
if( pPrior==0 ){
diff --git a/src/mutex.h b/src/mutex.h
index c24f3da4..b0e552c7 100644
--- a/src/mutex.h
+++ b/src/mutex.h
@@ -60,12 +60,15 @@
*/
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
-#define sqlite3_mutex_enter(X)
+#define sqlite3_mutex_enter(X)
#define sqlite3_mutex_try(X) SQLITE_OK
-#define sqlite3_mutex_leave(X)
+#define sqlite3_mutex_leave(X)
#define sqlite3_mutex_held(X) ((void)(X),1)
#define sqlite3_mutex_notheld(X) ((void)(X),1)
#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8)
#define sqlite3MutexInit() SQLITE_OK
#define sqlite3MutexEnd()
+#define MUTEX_LOGIC(X)
+#else
+#define MUTEX_LOGIC(X) X
#endif /* defined(SQLITE_MUTEX_OMIT) */
diff --git a/src/os.c b/src/os.c
index ba0438ad..0b13c86e 100644
--- a/src/os.c
+++ b/src/os.c
@@ -136,7 +136,7 @@ int sqlite3OsOpen(
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
** reaching the VFS. */
- rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f3f, pFlagsOut);
+ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}
@@ -208,7 +208,7 @@ int sqlite3OsOpenMalloc(
){
int rc = SQLITE_NOMEM;
sqlite3_file *pFile;
- pFile = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile);
+ pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
if( pFile ){
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
if( rc!=SQLITE_OK ){
@@ -297,12 +297,12 @@ static void vfsUnlink(sqlite3_vfs *pVfs){
** true.
*/
int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
- sqlite3_mutex *mutex = 0;
+ MUTEX_LOGIC(sqlite3_mutex *mutex;)
#ifndef SQLITE_OMIT_AUTOINIT
int rc = sqlite3_initialize();
if( rc ) return rc;
#endif
- mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
sqlite3_mutex_enter(mutex);
vfsUnlink(pVfs);
if( makeDflt || vfsList==0 ){
diff --git a/src/os_common.h b/src/os_common.h
index eba856be..f6c3e7ff 100644
--- a/src/os_common.h
+++ b/src/os_common.h
@@ -29,11 +29,14 @@
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
-#ifdef SQLITE_DEBUG
-int sqlite3OSTrace = 0;
-#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+# ifndef SQLITE_DEBUG_OS_TRACE
+# define SQLITE_DEBUG_OS_TRACE 0
+# endif
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
-#define OSTRACE(X)
+# define OSTRACE(X)
#endif
/*
diff --git a/src/os_unix.c b/src/os_unix.c
index 682e74c9..0ea6daf2 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -208,7 +208,6 @@ struct unixFile {
sqlite3_io_methods const *pMethod; /* Always the first entry */
unixInodeInfo *pInode; /* Info about locks on this inode */
int h; /* The file descriptor */
- int dirfd; /* File descriptor for the directory */
unsigned char eFileLock; /* The type of lock held on this fd */
unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
int lastErrno; /* The unix errno from last I/O error */
@@ -250,8 +249,14 @@ struct unixFile {
/*
** Allowed values for the unixFile.ctrlFlags bitmask:
*/
-#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
-#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
+#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
+#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
+#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
+#ifndef SQLITE_DISABLE_DIRSYNC
+# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
+#else
+# define UNIXFILE_DIRSYNC 0x00
+#endif
/*
** Include code that is common to all os_*.c files
@@ -297,6 +302,9 @@ static int posixOpen(const char *zFile, int flags, int mode){
return open(zFile, flags, mode);
}
+/* Forward reference */
+static int openDirectory(const char*, int*);
+
/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
@@ -393,6 +401,12 @@ static struct unix_syscall {
#endif
#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
+ { "unlink", (sqlite3_syscall_ptr)unlink, 0 },
+#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent)
+
+ { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
+#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
+
}; /* End of the overrideable system calls */
/*
@@ -514,7 +528,7 @@ static int unixMutexHeld(void) {
#endif
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
/*
** Helper function for printing out trace information from debugging
** binaries. This returns the string represetation of the supplied
@@ -677,7 +691,9 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
case ENODEV:
case ENXIO:
case ENOENT:
+#ifdef ESTALE /* ESTALE is not defined on Interix systems */
case ESTALE:
+#endif
case ENOSYS:
/* these should force the client to close the file and reconnect */
@@ -1347,14 +1363,14 @@ static int unixLock(sqlite3_file *id, int eFileLock){
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
- unixInodeInfo *pInode = pFile->pInode;
+ unixInodeInfo *pInode;
struct flock lock;
int tErrno = 0;
assert( pFile );
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
- azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
+ azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
/* If there is already a lock of this type or more restrictive on the
** unixFile, do nothing. Don't use the end_lock: exit path, as
@@ -1558,7 +1574,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
unixInodeInfo *pInode;
struct flock lock;
int rc = SQLITE_OK;
- int h;
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
@@ -1570,14 +1585,10 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
return SQLITE_OK;
}
unixEnterMutex();
- h = pFile->h;
pInode = pFile->pInode;
assert( pInode->nShared!=0 );
if( pFile->eFileLock>SHARED_LOCK ){
assert( pInode->eFileLock==pFile->eFileLock );
- SimulateIOErrorBenign(1);
- SimulateIOError( h=(-1) )
- SimulateIOErrorBenign(0);
#ifndef NDEBUG
/* When reducing a lock such that other processes can start
@@ -1588,11 +1599,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
** the file has changed and hence might not know to flush their
** cache. The use of a stale cache can lead to database corruption.
*/
-#if 0
- assert( pFile->inNormalWrite==0
- || pFile->dbUpdate==0
- || pFile->transCntrChng==1 );
-#endif
pFile->inNormalWrite = 0;
#endif
@@ -1694,9 +1700,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
- SimulateIOErrorBenign(1);
- SimulateIOError( h=(-1) )
- SimulateIOErrorBenign(0);
if( unixFileLock(pFile, &lock)==0 ){
pInode->eFileLock = NO_LOCK;
}else{
@@ -1747,10 +1750,6 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){
*/
static int closeUnixFile(sqlite3_file *id){
unixFile *pFile = (unixFile*)id;
- if( pFile->dirfd>=0 ){
- robust_close(pFile, pFile->dirfd, __LINE__);
- pFile->dirfd=-1;
- }
if( pFile->h>=0 ){
robust_close(pFile, pFile->h, __LINE__);
pFile->h = -1;
@@ -1758,7 +1757,7 @@ static int closeUnixFile(sqlite3_file *id){
#if OS_VXWORKS
if( pFile->pId ){
if( pFile->isDelete ){
- unlink(pFile->pId->zCanonicalName);
+ osUnlink(pFile->pId->zCanonicalName);
}
vxworksReleaseFileId(pFile->pId);
pFile->pId = 0;
@@ -2007,7 +2006,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
/* To fully unlock the database, delete the lock file */
assert( eFileLock==NO_LOCK );
- if( unlink(zLockFile) ){
+ if( osUnlink(zLockFile) ){
int rc = 0;
int tErrno = errno;
if( ENOENT != tErrno ){
@@ -2513,11 +2512,12 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
+ afpLockingContext *context;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+ context = (afpLockingContext *) pFile->lockingContext;
if( context->reserved ){
*pResOut = 1;
return SQLITE_OK;
@@ -2657,7 +2657,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
** operating system calls for the specified lock.
*/
if( eFileLock==SHARED_LOCK ){
- int lrc1, lrc2, lrc1Errno;
+ int lrc1, lrc2, lrc1Errno = 0;
long lk, mask;
assert( pInode->nShared==0 );
@@ -3031,17 +3031,19 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
#elif defined(USE_PREAD64)
do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
#else
- newOffset = lseek(id->h, offset, SEEK_SET);
- SimulateIOError( newOffset-- );
- if( newOffset!=offset ){
- if( newOffset == -1 ){
- ((unixFile*)id)->lastErrno = errno;
- }else{
- ((unixFile*)id)->lastErrno = 0;
+ do{
+ newOffset = lseek(id->h, offset, SEEK_SET);
+ SimulateIOError( newOffset-- );
+ if( newOffset!=offset ){
+ if( newOffset == -1 ){
+ ((unixFile*)id)->lastErrno = errno;
+ }else{
+ ((unixFile*)id)->lastErrno = 0;
+ }
+ return -1;
}
- return -1;
- }
- do{ got = osWrite(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
+ got = osWrite(id->h, pBuf, cnt);
+ }while( got<0 && errno==EINTR );
#endif
TIMER_END;
if( got<0 ){
@@ -3131,11 +3133,11 @@ 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 (slower) fsync().
-** If you know that your system does support fdatasync() correctly,
+** 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
*/
-#if !defined(fdatasync) && !defined(__linux__)
+#if !defined(fdatasync)
# define fdatasync fsync
#endif
@@ -3243,6 +3245,50 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
return rc;
}
+/*
+** Open a file descriptor to the directory containing file zFilename.
+** If successful, *pFd is set to the opened file descriptor and
+** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
+** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
+** value.
+**
+** The directory file descriptor is used for only one thing - to
+** fsync() a directory to make sure file creation and deletion events
+** are flushed to disk. Such fsyncs are not needed on newer
+** journaling filesystems, but are required on older filesystems.
+**
+** This routine can be overridden using the xSetSysCall interface.
+** The ability to override this routine was added in support of the
+** chromium sandbox. Opening a directory is a security risk (we are
+** told) so making it overrideable allows the chromium sandbox to
+** replace this routine with a harmless no-op. To make this routine
+** a no-op, replace it with a stub that returns SQLITE_OK but leaves
+** *pFd set to a negative number.
+**
+** If SQLITE_OK is returned, the caller is responsible for closing
+** the file descriptor *pFd using close().
+*/
+static int openDirectory(const char *zFilename, int *pFd){
+ int ii;
+ int fd = -1;
+ char zDirname[MAX_PATHNAME+1];
+
+ sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
+ for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
+ if( ii>0 ){
+ zDirname[ii] = '\0';
+ fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
+ if( fd>=0 ){
+#ifdef FD_CLOEXEC
+ osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
+#endif
+ OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
+ }
+ }
+ *pFd = fd;
+ return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
+}
+
/*
** Make sure all writes to a particular file are committed to disk.
**
@@ -3283,28 +3329,23 @@ static int unixSync(sqlite3_file *id, int flags){
pFile->lastErrno = errno;
return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
}
- if( pFile->dirfd>=0 ){
- OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
+
+ /* Also fsync the directory containing the file if the DIRSYNC flag
+ ** is set. This is a one-time occurrance. Many systems (examples: AIX)
+ ** are unable to fsync a directory, so ignore errors on the fsync.
+ */
+ if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
+ int dirfd;
+ OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
HAVE_FULLFSYNC, isFullsync));
-#ifndef SQLITE_DISABLE_DIRSYNC
- /* The directory sync is only attempted if full_fsync is
- ** turned off or unavailable. If a full_fsync occurred above,
- ** then the directory sync is superfluous.
- */
- if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
- /*
- ** We have received multiple reports of fsync() returning
- ** errors when applied to directories on certain file systems.
- ** A failed directory sync is not a big deal. So it seems
- ** better to ignore the error. Ticket #1657
- */
- /* pFile->lastErrno = errno; */
- /* return SQLITE_IOERR; */
+ rc = osOpenDirectory(pFile->zPath, &dirfd);
+ if( rc==SQLITE_OK && dirfd>=0 ){
+ full_fsync(dirfd, 0, 0);
+ robust_close(pFile, dirfd, __LINE__);
+ }else if( rc==SQLITE_CANTOPEN ){
+ rc = SQLITE_OK;
}
-#endif
- /* Only need to sync once, so close the directory when we are done */
- robust_close(pFile, pFile->dirfd, __LINE__);
- pFile->dirfd = -1;
+ pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
}
return rc;
}
@@ -3386,14 +3427,12 @@ static int proxyFileControl(sqlite3_file*,int,void*);
/*
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
-** file-control operation.
-**
-** If the user has configured a chunk-size for this file, it could be
-** that the file needs to be extended at this point. Otherwise, the
-** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
+** file-control operation. Enlarge the database to nBytes in size
+** (rounded up to the next chunk-size). If the database is already
+** nBytes or larger, this routine is a no-op.
*/
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
- if( pFile->szChunk ){
+ if( pFile->szChunk>0 ){
i64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
@@ -3442,21 +3481,37 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
+ unixFile *pFile = (unixFile*)id;
switch( op ){
case SQLITE_FCNTL_LOCKSTATE: {
- *(int*)pArg = ((unixFile*)id)->eFileLock;
+ *(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
- *(int*)pArg = ((unixFile*)id)->lastErrno;
+ *(int*)pArg = pFile->lastErrno;
return SQLITE_OK;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
- ((unixFile*)id)->szChunk = *(int *)pArg;
+ pFile->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
- return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
+ int rc;
+ SimulateIOErrorBenign(1);
+ rc = fcntlSizeHint(pFile, *(i64 *)pArg);
+ SimulateIOErrorBenign(0);
+ return rc;
+ }
+ case SQLITE_FCNTL_PERSIST_WAL: {
+ int bPersist = *(int*)pArg;
+ if( bPersist<0 ){
+ *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
+ }else if( bPersist==0 ){
+ pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
+ }else{
+ pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
+ }
+ return SQLITE_OK;
}
#ifndef NDEBUG
/* The pager calls this method to signal that it has done
@@ -3572,11 +3627,9 @@ struct unixShm {
unixShmNode *pShmNode; /* The underlying unixShmNode object */
unixShm *pNext; /* Next unixShm with the same unixShmNode */
u8 hasMutex; /* True if holding the unixShmNode mutex */
+ u8 id; /* Id of this connection within its unixShmNode */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
-#ifdef SQLITE_DEBUG
- u8 id; /* Id of this connection within its unixShmNode */
-#endif
};
/*
@@ -3672,7 +3725,7 @@ static void unixShmPurge(unixFile *pFd){
if( p && p->nRef==0 ){
int i;
assert( p->pInode==pFd->pInode );
- if( p->mutex ) sqlite3_mutex_free(p->mutex);
+ sqlite3_mutex_free(p->mutex);
for(i=0; inRegion; i++){
if( p->h>=0 ){
munmap(p->apRegion[i], p->szRegion);
@@ -3788,16 +3841,15 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
}
if( pInode->bProcessLock==0 ){
- pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
- (sStat.st_mode & 0777));
+ const char *zRO;
+ int openFlags = O_RDWR | O_CREAT;
+ zRO = sqlite3_uri_parameter(pDbFd->zPath, "readonly_shm");
+ if( zRO && sqlite3GetBoolean(zRO) ){
+ openFlags = O_RDONLY;
+ pShmNode->isReadonly = 1;
+ }
+ pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
if( pShmNode->h<0 ){
- const char *zRO;
- zRO = sqlite3_uri_parameter(pDbFd->zPath, "readonly_shm");
- if( zRO && sqlite3GetBoolean(zRO) ){
- pShmNode->h = robust_open(zShmFilename, O_RDONLY,
- (sStat.st_mode & 0777));
- pShmNode->isReadonly = 1;
- }
if( pShmNode->h<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
goto shm_open_err;
@@ -4141,7 +4193,7 @@ static int unixShmUnmap(
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
- if( deleteFlag && pShmNode->h>=0 ) unlink(pShmNode->zFilename);
+ if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
unixShmPurge(pDbFd);
}
unixLeaveMutex();
@@ -4454,7 +4506,7 @@ typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
static int fillInUnixFile(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
int h, /* Open file descriptor of file being opened */
- int dirfd, /* Directory file descriptor */
+ int syncDir, /* True to sync directory on first sync */
sqlite3_file *pId, /* Write to the unixFile structure here */
const char *zFilename, /* Name of the file being opened */
int noLock, /* Omit locking if true */
@@ -4483,9 +4535,11 @@ static int fillInUnixFile(
assert( zFilename==0 || zFilename[0]=='/' );
#endif
+ /* No locking occurs in temporary files */
+ assert( zFilename!=0 || noLock );
+
OSTRACE(("OPEN %-3d %s\n", h, zFilename));
pNew->h = h;
- pNew->dirfd = dirfd;
pNew->zPath = zFilename;
if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
pNew->ctrlFlags = UNIXFILE_EXCL;
@@ -4495,6 +4549,9 @@ static int fillInUnixFile(
if( isReadOnly ){
pNew->ctrlFlags |= UNIXFILE_RDONLY;
}
+ if( syncDir ){
+ pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
+ }
#if OS_VXWORKS
pNew->pId = vxworksFindFileId(zFilename);
@@ -4582,6 +4639,7 @@ static int fillInUnixFile(
*/
char *zLockFile;
int nFilename;
+ assert( zFilename!=0 );
nFilename = (int)strlen(zFilename) + 6;
zLockFile = (char *)sqlite3_malloc(nFilename);
if( zLockFile==0 ){
@@ -4621,13 +4679,12 @@ static int fillInUnixFile(
if( rc!=SQLITE_OK ){
if( h>=0 ) robust_close(pNew, h, __LINE__);
h = -1;
- unlink(zFilename);
+ osUnlink(zFilename);
isDelete = 0;
}
pNew->isDelete = isDelete;
#endif
if( rc!=SQLITE_OK ){
- if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__);
if( h>=0 ) robust_close(pNew, h, __LINE__);
}else{
pNew->pMethod = pLockingStyle;
@@ -4636,37 +4693,6 @@ static int fillInUnixFile(
return rc;
}
-/*
-** Open a file descriptor to the directory containing file zFilename.
-** If successful, *pFd is set to the opened file descriptor and
-** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
-** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
-** value.
-**
-** If SQLITE_OK is returned, the caller is responsible for closing
-** the file descriptor *pFd using close().
-*/
-static int openDirectory(const char *zFilename, int *pFd){
- int ii;
- int fd = -1;
- char zDirname[MAX_PATHNAME+1];
-
- sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
- for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
- if( ii>0 ){
- zDirname[ii] = '\0';
- fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
- if( fd>=0 ){
-#ifdef FD_CLOEXEC
- osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
-#endif
- OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
- }
- }
- *pFd = fd;
- return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
-}
-
/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
@@ -4781,7 +4807,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
**
** Even if a subsequent open() call does succeed, the consequences of
** not searching for a resusable file descriptor are not dire. */
- if( 0==stat(zPath, &sStat) ){
+ if( 0==osStat(zPath, &sStat) ){
unixInodeInfo *pInode;
unixEnterMutex();
@@ -4848,16 +4874,24 @@ static int findCreateFileMode(
** "-journalNN"
** "-walNN"
**
- ** where NN is a 4 digit decimal number. The NN naming schemes are
+ ** where NN is a decimal number. The NN naming schemes are
** used by the test_multiplex.c module.
*/
nDb = sqlite3Strlen30(zPath) - 1;
- while( nDb>0 && zPath[nDb]!='-' ) nDb--;
- if( nDb==0 ) return SQLITE_OK;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ while( nDb>0 && !sqlite3Isalnum(zPath[nDb]) ) nDb--;
+ if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
+#else
+ while( zPath[nDb]!='-' ){
+ assert( nDb>0 );
+ assert( zPath[nDb]!='\n' );
+ nDb--;
+ }
+#endif
memcpy(zDb, zPath, nDb);
zDb[nDb] = '\0';
- if( 0==stat(zDb, &sStat) ){
+ if( 0==osStat(zDb, &sStat) ){
*pMode = sStat.st_mode & 0777;
}else{
rc = SQLITE_IOERR_FSTAT;
@@ -4899,7 +4933,6 @@ static int unixOpen(
){
unixFile *p = (unixFile *)pFile;
int fd = -1; /* File descriptor returned by open() */
- int dirfd = -1; /* Directory file descriptor */
int openFlags = 0; /* Flags to pass to open() */
int eType = flags&0xFFFFFF00; /* Type of file to open */
int noLock; /* True to omit locking primitives */
@@ -4913,12 +4946,15 @@ static int unixOpen(
#if SQLITE_ENABLE_LOCKING_STYLE
int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
#endif
+#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
+ struct statfs fsInfo;
+#endif
/* If creating a master or main-file journal, this function will open
** a file-descriptor on the directory too. The first time unixSync()
** is called the directory file descriptor will be fsync()ed and close()d.
*/
- int isOpenDirectory = (isCreate && (
+ int syncDir = (isCreate && (
eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
@@ -4972,7 +5008,7 @@ static int unixOpen(
p->pUnused = pUnused;
}else if( !zName ){
/* If zName is NULL, the upper layer is requesting a temp file. */
- assert(isDelete && !isOpenDirectory);
+ assert(isDelete && !syncDir);
rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
if( rc!=SQLITE_OK ){
return rc;
@@ -5028,7 +5064,7 @@ static int unixOpen(
#if OS_VXWORKS
zPath = zName;
#else
- unlink(zName);
+ osUnlink(zName);
#endif
}
#if SQLITE_ENABLE_LOCKING_STYLE
@@ -5037,19 +5073,6 @@ static int unixOpen(
}
#endif
- if( isOpenDirectory ){
- rc = openDirectory(zPath, &dirfd);
- if( rc!=SQLITE_OK ){
- /* It is safe to close fd at this point, because it is guaranteed not
- ** to be open on a database file. If it were open on a database file,
- ** it would not be safe to close as this would release any locks held
- ** on the file by this process. */
- assert( eType!=SQLITE_OPEN_MAIN_DB );
- robust_close(p, fd, __LINE__);
- goto open_finished;
- }
- }
-
#ifdef FD_CLOEXEC
osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
@@ -5058,10 +5081,8 @@ static int unixOpen(
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
- struct statfs fsInfo;
if( fstatfs(fd, &fsInfo) == -1 ){
((unixFile*)pFile)->lastErrno = errno;
- if( dirfd>=0 ) robust_close(p, dirfd, __LINE__);
robust_close(p, fd, __LINE__);
return SQLITE_IOERR_ACCESS;
}
@@ -5083,7 +5104,6 @@ static int unixOpen(
if( envforce!=NULL ){
useProxy = atoi(envforce)>0;
}else{
- struct statfs fsInfo;
if( statfs(zPath, &fsInfo) == -1 ){
/* In theory, the close(fd) call is sub-optimal. If the file opened
** with fd is a database file, and there are other connections open
@@ -5093,9 +5113,6 @@ static int unixOpen(
** not while other file descriptors opened by the same process on
** the same file are working. */
p->lastErrno = errno;
- if( dirfd>=0 ){
- robust_close(p, dirfd, __LINE__);
- }
robust_close(p, fd, __LINE__);
rc = SQLITE_IOERR_ACCESS;
goto open_finished;
@@ -5103,7 +5120,7 @@ static int unixOpen(
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
}
if( useProxy ){
- rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
+ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
isDelete, isReadonly);
if( rc==SQLITE_OK ){
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
@@ -5121,7 +5138,7 @@ static int unixOpen(
}
#endif
- rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
+ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
isDelete, isReadonly);
open_finished:
if( rc!=SQLITE_OK ){
@@ -5143,13 +5160,13 @@ static int unixDelete(
int rc = SQLITE_OK;
UNUSED_PARAMETER(NotUsed);
SimulateIOError(return SQLITE_IOERR_DELETE);
- if( unlink(zPath)==(-1) && errno!=ENOENT ){
+ if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
}
#ifndef SQLITE_DISABLE_DIRSYNC
if( dirSync ){
int fd;
- rc = openDirectory(zPath, &fd);
+ rc = osOpenDirectory(zPath, &fd);
if( rc==SQLITE_OK ){
#if OS_VXWORKS
if( fsync(fd)==-1 )
@@ -5160,6 +5177,8 @@ static int unixDelete(
rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
}
robust_close(0, fd, __LINE__);
+ }else if( rc==SQLITE_CANTOPEN ){
+ rc = SQLITE_OK;
}
}
#endif
@@ -5202,7 +5221,7 @@ static int unixAccess(
*pResOut = (osAccess(zPath, amode)==0);
if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
struct stat buf;
- if( 0==stat(zPath, &buf) && buf.st_size==0 ){
+ if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
*pResOut = 0;
}
}
@@ -5400,10 +5419,12 @@ int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
** proleptic Gregorian calendar.
**
-** On success, return 0. Return 1 if the time and date cannot be found.
+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
+** cannot be found.
*/
static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
+ int rc = SQLITE_OK;
#if defined(NO_GETTOD)
time_t t;
time(&t);
@@ -5414,8 +5435,11 @@ static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
*piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
#else
struct timeval sNow;
- gettimeofday(&sNow, 0);
- *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
+ if( gettimeofday(&sNow, 0)==0 ){
+ *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
+ }else{
+ rc = SQLITE_ERROR;
+ }
#endif
#ifdef SQLITE_TEST
@@ -5424,7 +5448,7 @@ static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
}
#endif
UNUSED_PARAMETER(NotUsed);
- return 0;
+ return rc;
}
/*
@@ -5433,11 +5457,12 @@ static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
** return 0. Return 1 if the time and date cannot be found.
*/
static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
- sqlite3_int64 i;
+ sqlite3_int64 i = 0;
+ int rc;
UNUSED_PARAMETER(NotUsed);
- unixCurrentTimeInt64(0, &i);
+ rc = unixCurrentTimeInt64(0, &i);
*prNow = i/86400000.0;
- return 0;
+ return rc;
}
/*
@@ -5721,7 +5746,6 @@ static int proxyCreateUnixFile(
int islockfile /* if non zero missing dirs will be created */
) {
int fd = -1;
- int dirfd = -1;
unixFile *pNew;
int rc = SQLITE_OK;
int openFlags = O_RDWR | O_CREAT;
@@ -5786,7 +5810,7 @@ static int proxyCreateUnixFile(
pUnused->flags = openFlags;
pNew->pUnused = pUnused;
- rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0);
+ rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
if( rc==SQLITE_OK ){
*ppFile = pNew;
return SQLITE_OK;
@@ -5826,6 +5850,8 @@ static int proxyGetHostID(unsigned char *pHostID, int *pError){
return SQLITE_IOERR;
}
}
+#else
+ UNUSED_PARAMETER(pError);
#endif
#ifdef SQLITE_TEST
/* simulate multiple hosts by creating unique hostid file paths */
@@ -5900,7 +5926,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
end_breaklock:
if( rc ){
if( fd>=0 ){
- unlink(tPath);
+ osUnlink(tPath);
robust_close(pFile, fd, __LINE__);
}
fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
@@ -5918,6 +5944,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
int nTries = 0;
struct timespec conchModTime;
+ memset(&conchModTime, 0, sizeof(conchModTime));
do {
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
nTries ++;
@@ -6149,11 +6176,12 @@ static int proxyTakeConch(unixFile *pFile){
end_takeconch:
OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
if( rc==SQLITE_OK && pFile->openFlags ){
+ int fd;
if( pFile->h>=0 ){
robust_close(pFile, pFile->h, __LINE__);
}
pFile->h = -1;
- int fd = robust_open(pCtx->dbPath, pFile->openFlags,
+ fd = robust_open(pCtx->dbPath, pFile->openFlags,
SQLITE_DEFAULT_FILE_PERMISSIONS);
OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
if( fd>=0 ){
@@ -6723,7 +6751,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==16 );
+ assert( ArraySize(aSyscall)==18 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
diff --git a/src/os_win.c b/src/os_win.c
index bd0f2f21..45180304 100644
--- a/src/os_win.c
+++ b/src/os_win.c
@@ -102,8 +102,9 @@ struct winFile {
const sqlite3_io_methods *pMethod; /*** Must be first ***/
sqlite3_vfs *pVfs; /* The VFS used to open this file */
HANDLE h; /* Handle for accessing the file */
- unsigned char locktype; /* Type of lock currently held on this file */
+ u8 locktype; /* Type of lock currently held on this file */
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
+ u8 bPersistWal; /* True to persist WAL files */
DWORD lastErrno; /* The Windows errno from the last I/O error */
DWORD sectorSize; /* Sector size of the device file is on */
winShm *pShm; /* Instance of shared memory on this file */
@@ -118,6 +119,76 @@ struct winFile {
#endif
};
+/*
+ * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
+ * various Win32 API heap functions instead of our own.
+ */
+#ifdef SQLITE_WIN32_MALLOC
+/*
+ * The initial size of the Win32-specific heap. This value may be zero.
+ */
+#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
+# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
+ (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
+#endif
+
+/*
+ * The maximum size of the Win32-specific heap. This value may be zero.
+ */
+#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
+# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
+#endif
+
+/*
+ * The extra flags to use in calls to the Win32 heap APIs. This value may be
+ * zero for the default behavior.
+ */
+#ifndef SQLITE_WIN32_HEAP_FLAGS
+# define SQLITE_WIN32_HEAP_FLAGS (0)
+#endif
+
+/*
+** The winMemData structure stores information required by the Win32-specific
+** sqlite3_mem_methods implementation.
+*/
+typedef struct winMemData winMemData;
+struct winMemData {
+#ifndef NDEBUG
+ u32 magic; /* Magic number to detect structure corruption. */
+#endif
+ HANDLE hHeap; /* The handle to our heap. */
+ BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
+};
+
+#ifndef NDEBUG
+#define WINMEM_MAGIC 0x42b2830b
+#endif
+
+static struct winMemData win_mem_data = {
+#ifndef NDEBUG
+ WINMEM_MAGIC,
+#endif
+ NULL, FALSE
+};
+
+#ifndef NDEBUG
+#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
+#else
+#define winMemAssertMagic()
+#endif
+
+#define winMemGetHeap() win_mem_data.hHeap
+
+static void *winMemMalloc(int nBytes);
+static void winMemFree(void *pPrior);
+static void *winMemRealloc(void *pPrior, int nBytes);
+static int winMemSize(void *p);
+static int winMemRoundup(int n);
+static int winMemInit(void *pAppData);
+static void winMemShutdown(void *pAppData);
+
+const sqlite3_mem_methods *sqlite3MemGetWin32(void);
+#endif /* SQLITE_WIN32_MALLOC */
/*
** Forward prototypes.
@@ -170,6 +241,188 @@ static int sqlite3_os_type = 0;
}
#endif /* SQLITE_OS_WINCE */
+#ifdef SQLITE_WIN32_MALLOC
+/*
+** Allocate nBytes of memory.
+*/
+static void *winMemMalloc(int nBytes){
+ HANDLE hHeap;
+ void *p;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+ assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+ assert( nBytes>=0 );
+ p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
+ if( !p ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
+ nBytes, GetLastError(), (void*)hHeap);
+ }
+ return p;
+}
+
+/*
+** Free memory.
+*/
+static void winMemFree(void *pPrior){
+ HANDLE hHeap;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+ assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+#endif
+ if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
+ if( !HeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
+ pPrior, GetLastError(), (void*)hHeap);
+ }
+}
+
+/*
+** Change the size of an existing memory allocation
+*/
+static void *winMemRealloc(void *pPrior, int nBytes){
+ HANDLE hHeap;
+ void *p;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+ assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+#endif
+ assert( nBytes>=0 );
+ if( !pPrior ){
+ p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
+ }else{
+ p = HeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
+ }
+ if( !p ){
+ sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
+ pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, GetLastError(),
+ (void*)hHeap);
+ }
+ return p;
+}
+
+/*
+** Return the size of an outstanding allocation, in bytes.
+*/
+static int winMemSize(void *p){
+ HANDLE hHeap;
+ SIZE_T n;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+ assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+ if( !p ) return 0;
+ n = HeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
+ if( n==(SIZE_T)-1 ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
+ p, GetLastError(), (void*)hHeap);
+ return 0;
+ }
+ return (int)n;
+}
+
+/*
+** Round up a request size to the next valid allocation size.
+*/
+static int winMemRoundup(int n){
+ return n;
+}
+
+/*
+** Initialize this module.
+*/
+static int winMemInit(void *pAppData){
+ winMemData *pWinMemData = (winMemData *)pAppData;
+
+ if( !pWinMemData ) return SQLITE_ERROR;
+ assert( pWinMemData->magic==WINMEM_MAGIC );
+ if( !pWinMemData->hHeap ){
+ pWinMemData->hHeap = HeapCreate(SQLITE_WIN32_HEAP_FLAGS,
+ SQLITE_WIN32_HEAP_INIT_SIZE,
+ SQLITE_WIN32_HEAP_MAX_SIZE);
+ if( !pWinMemData->hHeap ){
+ sqlite3_log(SQLITE_NOMEM,
+ "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
+ GetLastError(), SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE,
+ SQLITE_WIN32_HEAP_MAX_SIZE);
+ return SQLITE_NOMEM;
+ }
+ pWinMemData->bOwned = TRUE;
+ }
+ assert( pWinMemData->hHeap!=0 );
+ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+ assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+ return SQLITE_OK;
+}
+
+/*
+** Deinitialize this module.
+*/
+static void winMemShutdown(void *pAppData){
+ winMemData *pWinMemData = (winMemData *)pAppData;
+
+ if( !pWinMemData ) return;
+ if( pWinMemData->hHeap ){
+ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
+#ifdef SQLITE_WIN32_MALLOC_VALIDATE
+ assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+ if( pWinMemData->bOwned ){
+ if( !HeapDestroy(pWinMemData->hHeap) ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
+ GetLastError(), (void*)pWinMemData->hHeap);
+ }
+ pWinMemData->bOwned = FALSE;
+ }
+ pWinMemData->hHeap = NULL;
+ }
+}
+
+/*
+** Populate the low-level memory allocation function pointers in
+** sqlite3GlobalConfig.m with pointers to the routines in this file. The
+** arguments specify the block of memory to manage.
+**
+** This routine is only called by sqlite3_config(), and therefore
+** is not required to be threadsafe (it is not).
+*/
+const sqlite3_mem_methods *sqlite3MemGetWin32(void){
+ static const sqlite3_mem_methods winMemMethods = {
+ winMemMalloc,
+ winMemFree,
+ winMemRealloc,
+ winMemSize,
+ winMemRoundup,
+ winMemInit,
+ winMemShutdown,
+ &win_mem_data
+ };
+ return &winMemMethods;
+}
+
+void sqlite3MemSetDefault(void){
+ sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
+}
+#endif /* SQLITE_WIN32_MALLOC */
+
/*
** Convert a UTF-8 string to microsoft unicode (UTF-16?).
**
@@ -402,6 +655,54 @@ static int winLogErrorAtLine(
return errcode;
}
+/*
+** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
+** will be retried following a locking error - probably caused by
+** antivirus software. Also the initial delay before the first retry.
+** The delay increases linearly with each retry.
+*/
+#ifndef SQLITE_WIN32_IOERR_RETRY
+# define SQLITE_WIN32_IOERR_RETRY 10
+#endif
+#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
+# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
+#endif
+static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
+static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
+
+/*
+** If a ReadFile() or WriteFile() error occurs, invoke this routine
+** to see if it should be retried. Return TRUE to retry. Return FALSE
+** to give up with an error.
+*/
+static int retryIoerr(int *pnRetry){
+ DWORD e;
+ if( *pnRetry>=win32IoerrRetry ){
+ return 0;
+ }
+ e = GetLastError();
+ if( e==ERROR_ACCESS_DENIED ||
+ e==ERROR_LOCK_VIOLATION ||
+ e==ERROR_SHARING_VIOLATION ){
+ Sleep(win32IoerrRetryDelay*(1+*pnRetry));
+ ++*pnRetry;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+** Log a I/O error retry episode.
+*/
+static void logIoerr(int nRetry){
+ if( nRetry ){
+ sqlite3_log(SQLITE_IOERR,
+ "delayed %dms for lock/sharing conflict",
+ win32IoerrRetryDelay*nRetry*(nRetry+1)/2
+ );
+ }
+}
+
#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
@@ -820,6 +1121,7 @@ static int winRead(
){
winFile *pFile = (winFile*)id; /* file handle */
DWORD nRead; /* Number of bytes actually read from file */
+ int nRetry = 0; /* Number of retrys */
assert( id!=0 );
SimulateIOError(return SQLITE_IOERR_READ);
@@ -828,10 +1130,12 @@ static int winRead(
if( seekWinFile(pFile, offset) ){
return SQLITE_FULL;
}
- if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
+ while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
+ if( retryIoerr(&nRetry) ) continue;
pFile->lastErrno = GetLastError();
return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
}
+ logIoerr(nRetry);
if( nRead<(DWORD)amt ){
/* Unread parts of the buffer must be zero-filled */
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
@@ -853,6 +1157,7 @@ static int winWrite(
){
int rc; /* True if error has occured, else false */
winFile *pFile = (winFile*)id; /* File handle */
+ int nRetry = 0; /* Number of retries */
assert( amt>0 );
assert( pFile );
@@ -867,7 +1172,12 @@ static int winWrite(
int nRem = amt; /* Number of bytes yet to be written */
DWORD nWrite; /* Bytes written by each WriteFile() call */
- while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
+ while( nRem>0 ){
+ if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
+ if( retryIoerr(&nRetry) ) continue;
+ break;
+ }
+ if( nWrite<=0 ) break;
aRem += nWrite;
nRem -= nWrite;
}
@@ -883,6 +1193,8 @@ static int winWrite(
return SQLITE_FULL;
}
return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
+ }else{
+ logIoerr(nRetry);
}
return SQLITE_OK;
}
@@ -904,7 +1216,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
** actual file size after the operation may be larger than the requested
** size).
*/
- if( pFile->szChunk ){
+ if( pFile->szChunk>0 ){
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
}
@@ -933,9 +1245,19 @@ int sqlite3_fullsync_count = 0;
** Make sure all writes to a particular file are committed to disk.
*/
static int winSync(sqlite3_file *id, int flags){
-#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
- winFile *pFile = (winFile*)id;
+#ifndef SQLITE_NO_SYNC
+ /*
+ ** Used only when SQLITE_NO_SYNC is not defined.
+ */
BOOL rc;
+#endif
+#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
+ (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
+ /*
+ ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
+ ** OSTRACE() macros.
+ */
+ winFile *pFile = (winFile*)id;
#else
UNUSED_PARAMETER(id);
#endif
@@ -1276,29 +1598,62 @@ static int winUnlock(sqlite3_file *id, int locktype){
** Control and query of the open file handle.
*/
static int winFileControl(sqlite3_file *id, int op, void *pArg){
+ winFile *pFile = (winFile*)id;
switch( op ){
case SQLITE_FCNTL_LOCKSTATE: {
- *(int*)pArg = ((winFile*)id)->locktype;
+ *(int*)pArg = pFile->locktype;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
- *(int*)pArg = (int)((winFile*)id)->lastErrno;
+ *(int*)pArg = (int)pFile->lastErrno;
return SQLITE_OK;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
- ((winFile*)id)->szChunk = *(int *)pArg;
+ pFile->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
- sqlite3_int64 sz = *(sqlite3_int64*)pArg;
- SimulateIOErrorBenign(1);
- winTruncate(id, sz);
- SimulateIOErrorBenign(0);
+ if( pFile->szChunk>0 ){
+ sqlite3_int64 oldSz;
+ int rc = winFileSize(id, &oldSz);
+ if( rc==SQLITE_OK ){
+ sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
+ if( newSz>oldSz ){
+ SimulateIOErrorBenign(1);
+ rc = winTruncate(id, newSz);
+ SimulateIOErrorBenign(0);
+ }
+ }
+ return rc;
+ }
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_PERSIST_WAL: {
+ int bPersist = *(int*)pArg;
+ if( bPersist<0 ){
+ *(int*)pArg = pFile->bPersistWal;
+ }else{
+ pFile->bPersistWal = bPersist!=0;
+ }
return SQLITE_OK;
}
case SQLITE_FCNTL_SYNC_OMITTED: {
return SQLITE_OK;
}
+ case SQLITE_FCNTL_WIN32_AV_RETRY: {
+ int *a = (int*)pArg;
+ if( a[0]>0 ){
+ win32IoerrRetry = a[0];
+ }else{
+ a[0] = win32IoerrRetry;
+ }
+ if( a[1]>0 ){
+ win32IoerrRetryDelay = a[1];
+ }else{
+ a[1] = win32IoerrRetryDelay;
+ }
+ return SQLITE_OK;
+ }
}
return SQLITE_NOTFOUND;
}
@@ -2107,6 +2462,7 @@ static int winOpen(
winFile *pFile = (winFile*)id;
void *zConverted; /* Filename in OS encoding */
const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
+ int cnt = 0;
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
@@ -2226,31 +2582,31 @@ static int winOpen(
#endif
if( isNT() ){
- h = CreateFileW((WCHAR*)zConverted,
- dwDesiredAccess,
- dwShareMode,
- NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL
- );
+ while( (h = CreateFileW((WCHAR*)zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL))==INVALID_HANDLE_VALUE &&
+ retryIoerr(&cnt) ){}
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
}else{
- h = CreateFileA((char*)zConverted,
- dwDesiredAccess,
- dwShareMode,
- NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL
- );
+ while( (h = CreateFileA((char*)zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL))==INVALID_HANDLE_VALUE &&
+ retryIoerr(&cnt) ){}
#endif
}
+ logIoerr(cnt);
+
OSTRACE(("OPEN %d %s 0x%lx %s\n",
h, zName, dwDesiredAccess,
h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
@@ -2259,7 +2615,7 @@ static int winOpen(
pFile->lastErrno = GetLastError();
winLogError(SQLITE_CANTOPEN, "winOpen", zUtf8Name);
free(zConverted);
- if( isReadWrite ){
+ if( isReadWrite && !isExclusive ){
return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
}else{
@@ -2316,15 +2672,13 @@ static int winOpen(
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
** up and returning an error.
*/
-#define MX_DELETION_ATTEMPTS 5
static int winDelete(
sqlite3_vfs *pVfs, /* Not used on win32 */
const char *zFilename, /* Name of file to delete */
int syncDir /* Not used on win32 */
){
int cnt = 0;
- DWORD rc;
- DWORD error = 0;
+ int rc;
void *zConverted;
UNUSED_PARAMETER(pVfs);
UNUSED_PARAMETER(syncDir);
@@ -2335,34 +2689,30 @@ static int winDelete(
return SQLITE_NOMEM;
}
if( isNT() ){
- do{
- DeleteFileW(zConverted);
- }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
- || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
- && (++cnt < MX_DELETION_ATTEMPTS)
- && (Sleep(100), 1) );
+ rc = 1;
+ while( GetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&
+ (rc = DeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){}
+ rc = rc ? SQLITE_OK : SQLITE_ERROR;
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
}else{
- do{
- DeleteFileA(zConverted);
- }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
- || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
- && (++cnt < MX_DELETION_ATTEMPTS)
- && (Sleep(100), 1) );
+ rc = 1;
+ while( GetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&
+ (rc = DeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){}
+ rc = rc ? SQLITE_OK : SQLITE_ERROR;
#endif
}
+ if( rc ){
+ rc = winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
+ }else{
+ logIoerr(cnt);
+ }
free(zConverted);
- OSTRACE(("DELETE \"%s\" %s\n", zFilename,
- ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
- "ok" : "failed" ));
-
- return ( (rc == INVALID_FILE_ATTRIBUTES)
- && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
- winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
+ OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
+ return rc;
}
/*
@@ -2385,11 +2735,13 @@ static int winAccess(
return SQLITE_NOMEM;
}
if( isNT() ){
+ int cnt = 0;
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
memset(&sAttrData, 0, sizeof(sAttrData));
- if( GetFileAttributesExW((WCHAR*)zConverted,
+ while( !(rc = GetFileAttributesExW((WCHAR*)zConverted,
GetFileExInfoStandard,
- &sAttrData) ){
+ &sAttrData)) && retryIoerr(&cnt) ){}
+ if( rc ){
/* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
** as if it does not exist.
*/
@@ -2401,6 +2753,7 @@ static int winAccess(
attr = sAttrData.dwFileAttributes;
}
}else{
+ logIoerr(cnt);
if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
free(zConverted);
@@ -2425,7 +2778,8 @@ static int winAccess(
rc = attr!=INVALID_FILE_ATTRIBUTES;
break;
case SQLITE_ACCESS_READWRITE:
- rc = (attr & FILE_ATTRIBUTE_READONLY)==0;
+ rc = attr!=INVALID_FILE_ATTRIBUTES &&
+ (attr & FILE_ATTRIBUTE_READONLY)==0;
break;
default:
assert(!"Invalid flags argument");
@@ -2627,7 +2981,7 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
UNUSED_PARAMETER(pVfs);
getLastErrorMsg(nBuf, zBufOut);
}
-void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
+static void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
UNUSED_PARAMETER(pVfs);
#if SQLITE_OS_WINCE
/* The GetProcAddressA() routine is only available on wince. */
@@ -2638,7 +2992,7 @@ void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
return (void(*)(void))GetProcAddress((HANDLE)pHandle, zSymbol);
#endif
}
-void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
+static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
UNUSED_PARAMETER(pVfs);
FreeLibrary((HANDLE)pHandle);
}
@@ -2712,7 +3066,8 @@ int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
** proleptic Gregorian calendar.
**
-** On success, return 0. Return 1 if the time and date cannot be found.
+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
+** cannot be found.
*/
static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
/* FILETIME structure is a 64-bit value representing the number of
@@ -2732,7 +3087,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
GetSystemTime(&time);
/* if SystemTimeToFileTime() fails, it returns zero. */
if (!SystemTimeToFileTime(&time,&ft)){
- return 1;
+ return SQLITE_ERROR;
}
#else
GetSystemTimeAsFileTime( &ft );
@@ -2748,7 +3103,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
}
#endif
UNUSED_PARAMETER(pVfs);
- return 0;
+ return SQLITE_OK;
}
/*
@@ -2756,7 +3111,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
** current time and date as a Julian Day number into *prNow and
** return 0. Return 1 if the time and date cannot be found.
*/
-int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
+static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
int rc;
sqlite3_int64 i;
rc = winCurrentTimeInt64(pVfs, &i);
diff --git a/src/pager.c b/src/pager.c
index 7ff9a9a0..63dda3dd 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -670,8 +670,8 @@ struct Pager {
char *zJournal; /* Name of the journal file */
int (*xBusyHandler)(void*); /* Function to call when busy */
void *pBusyHandlerArg; /* Context argument for xBusyHandler */
+ int nHit, nMiss; /* Total cache hits and misses */
#ifdef SQLITE_TEST
- int nHit, nMiss; /* Cache hits and missing */
int nRead, nWrite; /* Database pages read/written */
#endif
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
@@ -2703,7 +2703,6 @@ static int pager_playback(Pager *pPager, int isHot){
rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
pPager->journalOff = szJ;
break;
}else if( rc==SQLITE_IOERR_SHORT_READ ){
@@ -2965,6 +2964,7 @@ static int pagerWalFrames(
#endif
assert( pPager->pWal );
+ assert( pList );
#ifdef SQLITE_DEBUG
/* Verify that the page list is in accending order */
for(p=pList; p && p->pDirty; p=p->pDirty){
@@ -3739,6 +3739,7 @@ static int pagerSyncHotJournal(Pager *pPager){
int sqlite3PagerClose(Pager *pPager){
u8 *pTmp = (u8 *)pPager->pTmpSpace;
+ assert( assert_pager_state(pPager) );
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
/* pPager->errCode = 0; */
@@ -4168,7 +4169,7 @@ static int pagerStress(void *p, PgHdr *pPg){
**
** Spilling is also prohibited when in an error state since that could
** lead to database corruption. In the current implementaton it
- ** is impossible for sqlite3PCacheFetch() to be called with createFlag==1
+ ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
** while in the error state, hence it is impossible for this routine to
** be called in the error state. Nevertheless, we include a NEVER()
** test for the error state as a safeguard against future changes.
@@ -5004,14 +5005,13 @@ int sqlite3PagerAcquire(
/* In this case the pcache already contains an initialized copy of
** the page. Return without further ado. */
assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
- PAGER_INCR(pPager->nHit);
+ pPager->nHit++;
return SQLITE_OK;
}else{
/* The pager cache has created a new page. Its content needs to
** be initialized. */
- PAGER_INCR(pPager->nMiss);
pPg = *ppPage;
pPg->pPager = pPager;
@@ -5047,6 +5047,7 @@ int sqlite3PagerAcquire(
IOTRACE(("ZERO %p %d\n", pPager, pgno));
}else{
assert( pPg->pPager==pPager );
+ pPager->nMiss++;
rc = readDbPage(pPg);
if( rc!=SQLITE_OK ){
goto pager_acquire_err;
@@ -6081,6 +6082,31 @@ int *sqlite3PagerStats(Pager *pPager){
}
#endif
+/*
+** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
+** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
+** current cache hit or miss count, according to the value of eStat. If the
+** reset parameter is non-zero, the cache hit or miss count is zeroed before
+** returning.
+*/
+void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
+ int *piStat;
+
+ assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
+ || eStat==SQLITE_DBSTATUS_CACHE_MISS
+ );
+ if( eStat==SQLITE_DBSTATUS_CACHE_HIT ){
+ piStat = &pPager->nHit;
+ }else{
+ piStat = &pPager->nMiss;
+ }
+
+ *pnVal += *piStat;
+ if( reset ){
+ *piStat = 0;
+ }
+}
+
/*
** Return true if this is an in-memory pager.
*/
@@ -6810,6 +6836,13 @@ int sqlite3PagerCloseWal(Pager *pPager){
return rc;
}
+/*
+** Unless this is an in-memory or temporary database, clear the pager cache.
+*/
+void sqlite3PagerClearCache(Pager *pPager){
+ if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
+}
+
#ifdef SQLITE_HAS_CODEC
/*
** This function is called by the wal module when writing page content
diff --git a/src/pager.h b/src/pager.h
index eab7ddaf..e36e6c2e 100644
--- a/src/pager.h
+++ b/src/pager.h
@@ -155,6 +155,8 @@ const char *sqlite3PagerJournalname(Pager*);
int sqlite3PagerNosync(Pager*);
void *sqlite3PagerTempSpace(Pager*);
int sqlite3PagerIsMemdb(Pager*);
+void sqlite3PagerCacheStat(Pager *, int, int, int *);
+void sqlite3PagerClearCache(Pager *);
/* Functions used to truncate the database file. */
void sqlite3PagerTruncateImage(Pager*,Pgno);
diff --git a/src/pcache1.c b/src/pcache1.c
index e47265a2..077a7b21 100644
--- a/src/pcache1.c
+++ b/src/pcache1.c
@@ -24,6 +24,7 @@ typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;
+
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each others unpinned
** pages when they are under memory pressure. A PGroup is an instance of
@@ -288,15 +289,22 @@ static int pcache1MemSize(void *p){
*/
static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
int nByte = sizeof(PgHdr1) + pCache->szPage;
- void *pPg = pcache1Alloc(nByte);
- PgHdr1 *p;
+ PgHdr1 *p = 0;
+ void *pPg;
+
+ /* The group mutex must be released before pcache1Alloc() is called. This
+ ** is because it may call sqlite3_release_memory(), which assumes that
+ ** this mutex is not held. */
+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+ pcache1LeaveMutex(pCache->pGroup);
+ pPg = pcache1Alloc(nByte);
+ pcache1EnterMutex(pCache->pGroup);
+
if( pPg ){
p = PAGE_TO_PGHDR1(pCache, pPg);
if( pCache->bPurgeable ){
pCache->pGroup->nCurrentPage++;
}
- }else{
- p = 0;
}
return p;
}
@@ -311,10 +319,11 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
static void pcache1FreePage(PgHdr1 *p){
if( ALWAYS(p) ){
PCache1 *pCache = p->pCache;
+ assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
+ pcache1Free(PGHDR1_TO_PAGE(p));
if( pCache->bPurgeable ){
pCache->pGroup->nCurrentPage--;
}
- pcache1Free(PGHDR1_TO_PAGE(p));
}
}
@@ -752,9 +761,7 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
*/
if( !pPage ){
if( createFlag==1 ) sqlite3BeginBenignMalloc();
- pcache1LeaveMutex(pGroup);
pPage = pcache1AllocPage(pCache);
- pcache1EnterMutex(pGroup);
if( createFlag==1 ) sqlite3EndBenignMalloc();
}
diff --git a/src/pragma.c b/src/pragma.c
index cd2aab22..13a97334 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -467,7 +467,7 @@ void sqlite3Pragma(
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3CodeVerifySchema(pParse, iDb);
iReg = ++pParse->nMem;
- if( zLeft[0]=='p' ){
+ if( sqlite3Tolower(zLeft[0])=='p' ){
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
}else{
sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, sqlite3Atoi(zRight));
@@ -533,8 +533,10 @@ void sqlite3Pragma(
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
int ii; /* Loop counter */
- /* Force the schema to be loaded on all databases. This cases all
- ** database files to be opened and the journal_modes set. */
+ /* Force the schema to be loaded on all databases. This causes all
+ ** database files to be opened and the journal_modes set. This is
+ ** necessary because subsequent processing must know if the databases
+ ** are in WAL mode. */
if( sqlite3ReadSchema(pParse) ){
goto pragma_out;
}
@@ -1078,7 +1080,7 @@ void sqlite3Pragma(
{ OP_ResultRow, 3, 1, 0},
};
- int isQuick = (zLeft[0]=='q');
+ int isQuick = (sqlite3Tolower(zLeft[0])=='q');
/* Initialize the VDBE program */
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
diff --git a/src/printf.c b/src/printf.c
index 2a3dd81d..0babee51 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -7,48 +7,10 @@
**
**************************************************************************
**
-** The following modules is an enhanced replacement for the "printf" subroutines
-** found in the standard C library. The following enhancements are
-** supported:
-**
-** + Additional functions. The standard set of "printf" functions
-** includes printf, fprintf, sprintf, vprintf, vfprintf, and
-** vsprintf. This module adds the following:
-**
-** * snprintf -- Works like sprintf, but has an extra argument
-** which is the size of the buffer written to.
-**
-** * mprintf -- Similar to sprintf. Writes output to memory
-** obtained from malloc.
-**
-** * xprintf -- Calls a function to dispose of output.
-**
-** * nprintf -- No output, but returns the number of characters
-** that would have been output by printf.
-**
-** * A v- version (ex: vsnprintf) of every function is also
-** supplied.
-**
-** + A few extensions to the formatting notation are supported:
-**
-** * The "=" flag (similar to "-") causes the output to be
-** be centered in the appropriately sized field.
-**
-** * The %b field outputs an integer in binary notation.
-**
-** * The %c field now accepts a precision. The character output
-** is repeated by the number of times the precision specifies.
-**
-** * The %' field works like %c, but takes as its character the
-** next character of the format string, instead of the next
-** argument. For example, printf("%.78'-") prints 78 minus
-** signs, the same as printf("%.78c",'-').
-**
-** + When compiled using GCC on a SPARC, this version of printf is
-** faster than the library printf for SUN OS 4.1.
-**
-** + All functions are fully reentrant.
-**
+** This file contains code for a set of "printf"-like routines. These
+** routines format strings much like the printf() from the standard C
+** library, though the implementation here has enhancements to support
+** SQLlite.
*/
#include "sqliteInt.h"
@@ -187,43 +149,15 @@ static void appendSpace(StrAccum *pAccum, int N){
/*
** On machines with a small stack size, you can redefine the
-** SQLITE_PRINT_BUF_SIZE to be less than 350.
+** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
*/
#ifndef SQLITE_PRINT_BUF_SIZE
-# if defined(SQLITE_SMALL_STACK)
-# define SQLITE_PRINT_BUF_SIZE 50
-# else
-# define SQLITE_PRINT_BUF_SIZE 350
-# endif
+# define SQLITE_PRINT_BUF_SIZE 70
#endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
/*
-** The root program. All variations call this core.
-**
-** INPUTS:
-** func This is a pointer to a function taking three arguments
-** 1. A pointer to anything. Same as the "arg" parameter.
-** 2. A pointer to the list of characters to be output
-** (Note, this list is NOT null terminated.)
-** 3. An integer number of characters to be output.
-** (Note: This number might be zero.)
-**
-** arg This is the pointer to anything which will be passed as the
-** first argument to "func". Use it for whatever you like.
-**
-** fmt This is the format string, as in the usual print.
-**
-** ap This is a pointer to a list of arguments. Same as in
-** vfprint.
-**
-** OUTPUTS:
-** The return value is the total number of characters sent to
-** the function "func". Returns -1 on a error.
-**
-** Note that the order in which automatic variables are declared below
-** seems to make a big difference in determining how fast this beast
-** will run.
+** Render a string given by "fmt" into the StrAccum object.
*/
void sqlite3VXPrintf(
StrAccum *pAccum, /* Accumulate results here */
@@ -246,23 +180,23 @@ void sqlite3VXPrintf(
etByte flag_long; /* True if "l" flag is present */
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
+ etByte xtype = 0; /* Conversion paradigm */
+ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
sqlite_uint64 longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
- char buf[etBUFSIZE]; /* Conversion buffer */
- char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
- etByte xtype = 0; /* Conversion paradigm */
- char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
+ char *zOut; /* Rendering buffer */
+ int nOut; /* Size of the rendering buffer */
+ char *zExtra; /* Malloced memory used by some conversion */
#ifndef SQLITE_OMIT_FLOATING_POINT
int exp, e2; /* exponent of real numbers */
+ int nsd; /* Number of significant digits returned */
double rounder; /* Used for rounding floating point values */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
- etByte flag_exp; /* True to force display of the exponent */
- int nsd; /* Number of significant digits returned */
#endif
+ char buf[etBUFSIZE]; /* Conversion buffer */
- length = 0;
bufpt = 0;
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
@@ -307,9 +241,6 @@ void sqlite3VXPrintf(
c = *++fmt;
}
}
- if( width > etBUFSIZE-10 ){
- width = etBUFSIZE-10;
- }
/* Get the precision */
if( c=='.' ){
precision = 0;
@@ -356,12 +287,6 @@ void sqlite3VXPrintf(
}
zExtra = 0;
-
- /* Limit the precision to prevent overflowing buf[] during conversion */
- if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){
- precision = etBUFSIZE-40;
- }
-
/*
** At this point, variables are initialized as follows:
**
@@ -426,16 +351,26 @@ void sqlite3VXPrintf(
if( flag_zeropad && precisionmallocFailed = 1;
+ return;
+ }
+ }
+ bufpt = &zOut[nOut-1];
if( xtype==etORDINAL ){
static const char zOrd[] = "thstndrd";
int x = (int)(longvalue % 10);
if( x>=4 || (longvalue/10)%10==1 ){
x = 0;
}
- buf[etBUFSIZE-3] = zOrd[x*2];
- buf[etBUFSIZE-2] = zOrd[x*2+1];
- bufpt -= 2;
+ *(--bufpt) = zOrd[x*2+1];
+ *(--bufpt) = zOrd[x*2];
}
{
register const char *cset; /* Use registers for speed */
@@ -447,7 +382,7 @@ void sqlite3VXPrintf(
longvalue = longvalue/base;
}while( longvalue>0 );
}
- length = (int)(&buf[etBUFSIZE-1]-bufpt);
+ length = (int)(&zOut[nOut-1]-bufpt);
for(idx=precision-length; idx>0; idx--){
*(--bufpt) = '0'; /* Zero pad */
}
@@ -458,7 +393,7 @@ void sqlite3VXPrintf(
pre = &aPrefix[infop->prefix];
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
}
- length = (int)(&buf[etBUFSIZE-1]-bufpt);
+ length = (int)(&zOut[nOut-1]-bufpt);
break;
case etFLOAT:
case etEXP:
@@ -468,7 +403,6 @@ void sqlite3VXPrintf(
length = 0;
#else
if( precision<0 ) precision = 6; /* Set default precision */
- if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
@@ -516,7 +450,6 @@ void sqlite3VXPrintf(
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
- flag_exp = xtype==etEXP;
if( xtype!=etFLOAT ){
realvalue += rounder;
if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
@@ -537,6 +470,14 @@ void sqlite3VXPrintf(
}else{
e2 = exp;
}
+ if( e2+precision+width > etBUFSIZE - 15 ){
+ bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
+ if( bufpt==0 ){
+ pAccum->mallocFailed = 1;
+ return;
+ }
+ }
+ zOut = bufpt;
nsd = 0;
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
@@ -568,7 +509,7 @@ void sqlite3VXPrintf(
/* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){
while( bufpt[-1]=='0' ) *(--bufpt) = 0;
- assert( bufpt>buf );
+ assert( bufpt>zOut );
if( bufpt[-1]=='.' ){
if( flag_altform2 ){
*(bufpt++) = '0';
@@ -578,7 +519,7 @@ void sqlite3VXPrintf(
}
}
/* Add the "eNNN" suffix */
- if( flag_exp || xtype==etEXP ){
+ if( xtype==etEXP ){
*(bufpt++) = aDigits[infop->charset];
if( exp<0 ){
*(bufpt++) = '-'; exp = -exp;
@@ -597,8 +538,8 @@ void sqlite3VXPrintf(
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
- length = (int)(bufpt-buf);
- bufpt = buf;
+ length = (int)(bufpt-zOut);
+ bufpt = zOut;
/* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */
@@ -736,9 +677,7 @@ void sqlite3VXPrintf(
appendSpace(pAccum, nspace);
}
}
- if( zExtra ){
- sqlite3_free(zExtra);
- }
+ sqlite3_free(zExtra);
}/* End for loop over the format string */
} /* End of function */
@@ -752,6 +691,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
testcase(p->mallocFailed);
return;
}
+ assert( p->zText!=0 || p->nChar==0 );
if( N<0 ){
N = sqlite3Strlen30(z);
}
@@ -783,7 +723,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
zNew = sqlite3_realloc(zOld, p->nAlloc);
}
if( zNew ){
- if( zOld==0 ) memcpy(zNew, p->zText, p->nChar);
+ if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
p->zText = zNew;
}else{
p->mallocFailed = 1;
@@ -792,6 +732,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
}
}
}
+ assert( p->zText );
memcpy(&p->zText[p->nChar], z, N);
p->nChar += N;
}
diff --git a/src/resolve.c b/src/resolve.c
index 74d6aaef..6d857f00 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -98,6 +98,24 @@ static void resolveAlias(
sqlite3DbFree(db, pDup);
}
+
+/*
+** Return TRUE if the name zCol occurs anywhere in the USING clause.
+**
+** Return FALSE if the USING clause is NULL or if it does not contain
+** zCol.
+*/
+static int nameInUsingClause(IdList *pUsing, const char *zCol){
+ if( pUsing ){
+ int k;
+ for(k=0; knId; k++){
+ if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1;
+ }
+ }
+ return 0;
+}
+
+
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr
@@ -189,7 +207,14 @@ static int lookupName(
}
for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- IdList *pUsing;
+ /* If there has been exactly one prior match and this match
+ ** is for the right-hand table of a NATURAL JOIN or is in a
+ ** USING clause, then skip this match.
+ */
+ if( cnt==1 ){
+ if( pItem->jointype & JT_NATURAL ) continue;
+ if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
+ }
cnt++;
pExpr->iTable = pItem->iCursor;
pExpr->pTab = pTab;
@@ -197,26 +222,6 @@ static int lookupName(
pSchema = pTab->pSchema;
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
- if( inSrc-1 ){
- if( pItem[1].jointype & JT_NATURAL ){
- /* If this match occurred in the left table of a natural join,
- ** then skip the right table to avoid a duplicate match */
- pItem++;
- i++;
- }else if( (pUsing = pItem[1].pUsing)!=0 ){
- /* If this match occurs on a column that is in the USING clause
- ** of a join, skip the search of the right table of the join
- ** to avoid a duplicate match there. */
- int k;
- for(k=0; knId; k++){
- if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
- pItem++;
- i++;
- break;
- }
- }
- }
- }
break;
}
}
@@ -996,11 +1001,25 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
for(i=0; ipSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[i];
if( pItem->pSelect ){
+ NameContext *pNC; /* Used to iterate name contexts */
+ int nRef = 0; /* Refcount for pOuterNC and outer contexts */
const char *zSavedContext = pParse->zAuthContext;
+
+ /* Count the total number of references to pOuterNC and all of its
+ ** parent contexts. After resolving references to expressions in
+ ** pItem->pSelect, check if this value has changed. If so, then
+ ** SELECT statement pItem->pSelect must be correlated. Set the
+ ** pItem->isCorrelated flag if this is the case. */
+ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
+
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
+
+ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
+ assert( pItem->isCorrelated==0 && nRef<=0 );
+ pItem->isCorrelated = (nRef!=0);
}
}
diff --git a/src/select.c b/src/select.c
index 8dcfb84b..571a7782 100644
--- a/src/select.c
+++ b/src/select.c
@@ -65,6 +65,7 @@ Select *sqlite3SelectNew(
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */
if( pNew==0 ){
+ assert( db->mallocFailed );
pNew = &standin;
memset(pNew, 0, sizeof(*pNew));
}
@@ -89,7 +90,10 @@ Select *sqlite3SelectNew(
clearSelect(db, pNew);
if( pNew!=&standin ) sqlite3DbFree(db, pNew);
pNew = 0;
+ }else{
+ assert( pNew->pSrc!=0 || pParse->nErr>0 );
}
+ assert( pNew!=&standin );
return pNew;
}
@@ -419,12 +423,18 @@ static void pushOntoSorter(
int nExpr = pOrderBy->nExpr;
int regBase = sqlite3GetTempRange(pParse, nExpr+2);
int regRecord = sqlite3GetTempReg(pParse);
+ int op;
sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
+ if( pSelect->selFlags & SF_UseSorter ){
+ op = OP_SorterInsert;
+ }else{
+ op = OP_IdxInsert;
+ }
+ sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
if( pSelect->iLimit ){
@@ -893,9 +903,20 @@ static void generateSortTail(
}else{
regRowid = sqlite3GetTempReg(pParse);
}
- addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
- codeOffset(v, p, addrContinue);
- sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);
+ if( p->selFlags & SF_UseSorter ){
+ int regSortOut = ++pParse->nMem;
+ int ptab2 = pParse->nTab++;
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
+ codeOffset(v, p, addrContinue);
+ sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
+ sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
+ sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
+ }else{
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
+ codeOffset(v, p, addrContinue);
+ sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
+ }
switch( eDest ){
case SRT_Table:
case SRT_EphemTab: {
@@ -948,7 +969,11 @@ static void generateSortTail(
/* The bottom of the loop
*/
sqlite3VdbeResolveLabel(v, addrContinue);
- sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
+ if( p->selFlags & SF_UseSorter ){
+ sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
+ }
sqlite3VdbeResolveLabel(v, addrBreak);
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
@@ -1247,7 +1272,10 @@ static int selectColumnsFromExprList(
}else{
Expr *pColExpr = p; /* The expression that is the result column name */
Table *pTab; /* Table associated with this expression */
- while( pColExpr->op==TK_DOT ) pColExpr = pColExpr->pRight;
+ while( pColExpr->op==TK_DOT ){
+ pColExpr = pColExpr->pRight;
+ assert( pColExpr!=0 );
+ }
if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
@@ -3721,6 +3749,7 @@ int sqlite3Select(
int distinct; /* Table to use for the distinct set */
int rc = 1; /* Value to return from this function */
int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
+ int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
sqlite3 *db; /* The database connection */
@@ -3779,7 +3808,11 @@ int sqlite3Select(
Select *pSub = pItem->pSelect;
int isAggSub;
- if( pSub==0 || pItem->isPopulated ) continue;
+ if( pSub==0 ) continue;
+ if( pItem->addrFillSub ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+ continue;
+ }
/* Increment Parse.nHeight by the height of the largest expression
** tree refered to by this, the parent select. The child select
@@ -3790,21 +3823,44 @@ int sqlite3Select(
*/
pParse->nHeight += sqlite3SelectExprHeight(p);
- /* Check to see if the subquery can be absorbed into the parent. */
isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
+ /* This subquery can be absorbed into its parent. */
if( isAggSub ){
isAgg = 1;
p->selFlags |= SF_Aggregate;
}
i = -1;
}else{
+ /* Generate a subroutine that will fill an ephemeral table with
+ ** the content of this subquery. pItem->addrFillSub will point
+ ** to the address of the generated subroutine. pItem->regReturn
+ ** is a register allocated to hold the subroutine return address
+ */
+ int topAddr;
+ int onceAddr = 0;
+ int retAddr;
+ assert( pItem->addrFillSub==0 );
+ pItem->regReturn = ++pParse->nMem;
+ topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
+ pItem->addrFillSub = topAddr+1;
+ VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
+ if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
+ /* If the subquery is no correlated and if we are not inside of
+ ** a trigger, then we only need to compute the value of the subquery
+ ** once. */
+ int regOnce = ++pParse->nMem;
+ onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
+ }
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- assert( pItem->isPopulated==0 );
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
- pItem->isPopulated = 1;
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+ if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
+ retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
+ VdbeComment((v, "end %s", pItem->pTab->zName));
+ sqlite3VdbeChangeP1(v, topAddr, retAddr);
+
}
if( /*pParse->nErr ||*/ db->mallocFailed ){
goto select_end;
@@ -3847,16 +3903,6 @@ int sqlite3Select(
}
#endif
- /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
- ** GROUP BY might use an index, DISTINCT never does.
- */
- assert( p->pGroupBy==0 || (p->selFlags & SF_Aggregate)!=0 );
- if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ){
- p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
- pGroupBy = p->pGroupBy;
- p->selFlags &= ~SF_Distinct;
- }
-
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then disable the ORDER BY clause since the GROUP BY
** will cause elements to come out in the correct order. This is
@@ -3869,6 +3915,30 @@ int sqlite3Select(
pOrderBy = 0;
}
+ /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
+ ** if the select-list is the same as the ORDER BY list, then this query
+ ** can be rewritten as a GROUP BY. In other words, this:
+ **
+ ** SELECT DISTINCT xyz FROM ... ORDER BY xyz
+ **
+ ** is transformed to:
+ **
+ ** SELECT xyz FROM ... GROUP BY xyz
+ **
+ ** The second form is preferred as a single index (or temp-table) may be
+ ** used for both the ORDER BY and DISTINCT processing. As originally
+ ** written the query must use a temp-table for at least one of the ORDER
+ ** BY and DISTINCT, and an index or separate temp-table for the other.
+ */
+ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
+ && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
+ ){
+ p->selFlags &= ~SF_Distinct;
+ p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
+ pGroupBy = p->pGroupBy;
+ pOrderBy = 0;
+ }
+
/* If there is an ORDER BY clause, then this sorting
** index might end up being unused if the data can be
** extracted in pre-sorted order. If that is the case, then the
@@ -3899,27 +3969,30 @@ int sqlite3Select(
iEnd = sqlite3VdbeMakeLabel(v);
p->nSelectRow = (double)LARGEST_INT64;
computeLimitRegisters(pParse, p, iEnd);
+ if( p->iLimit==0 && addrSortIndex>=0 ){
+ sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
+ p->selFlags |= SF_UseSorter;
+ }
/* Open a virtual index to use for the distinct set.
*/
if( p->selFlags & SF_Distinct ){
KeyInfo *pKeyInfo;
- assert( isAgg || pGroupBy );
distinct = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
- (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
+ (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
}else{
- distinct = -1;
+ distinct = addrDistinctIndex = -1;
}
/* Aggregate and non-aggregate queries are handled differently */
if( !isAgg && pGroupBy==0 ){
- /* This case is for non-aggregate queries
- ** Begin the database scan
- */
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
+ ExprList *pDist = (isDistinct ? p->pEList : 0);
+
+ /* Begin the database scan. */
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
if( pWInfo==0 ) goto select_end;
if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
@@ -3928,14 +4001,56 @@ int sqlite3Select(
** into an OP_Noop.
*/
if( addrSortIndex>=0 && pOrderBy==0 ){
- sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
+ sqlite3VdbeChangeToNoop(v, addrSortIndex);
p->addrOpenEphm[2] = -1;
}
- /* Use the standard inner loop
- */
- assert(!isDistinct);
- selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
+ if( pWInfo->eDistinct ){
+ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
+
+ assert( addrDistinctIndex>=0 );
+ pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
+
+ assert( isDistinct );
+ assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
+ || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
+ );
+ distinct = -1;
+ if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
+ int iJump;
+ int iExpr;
+ int iFlag = ++pParse->nMem;
+ int iBase = pParse->nMem+1;
+ int iBase2 = iBase + pEList->nExpr;
+ pParse->nMem += (pEList->nExpr*2);
+
+ /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
+ ** OP_Integer initializes the "first row" flag. */
+ pOp->opcode = OP_Integer;
+ pOp->p1 = 1;
+ pOp->p2 = iFlag;
+
+ sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
+ iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
+ sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
+ for(iExpr=0; iExprnExpr; iExpr++){
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
+ sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
+ sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+ }
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
+
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
+ assert( sqlite3VdbeCurrentAddr(v)==iJump );
+ sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
+ }else{
+ pOp->opcode = OP_Noop;
+ }
+ }
+
+ /* Use the standard inner loop. */
+ selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
pWInfo->iContinue, pWInfo->iBreak);
/* End the database scan loop.
@@ -3952,6 +4067,8 @@ int sqlite3Select(
int iAbortFlag; /* Mem address which causes query abort if positive */
int groupBySort; /* Rows come from source in GROUP BY order */
int addrEnd; /* End of processing for this SELECT */
+ int sortPTab = 0; /* Pseudotable used to decode sorting results */
+ int sortOut = 0; /* Output register from the sorter */
/* Remove any and all aliases between the result set and the
** GROUP BY clause.
@@ -4013,12 +4130,12 @@ int sqlite3Select(
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
- ** that we do not need it after all, the OpenEphemeral instruction
+ ** that we do not need it after all, the OP_SorterOpen instruction
** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
- addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
@@ -4045,7 +4162,7 @@ int sqlite3Select(
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
if( pWInfo==0 ) goto select_end;
if( pGroupBy==0 ){
/* The optimizer is able to deliver rows in group by order so
@@ -4099,11 +4216,14 @@ int sqlite3Select(
}
regRecord = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
+ sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nCol);
sqlite3WhereEnd(pWInfo);
- sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
+ sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
+ sortOut = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
+ sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort"));
sAggInfo.useSortingIdx = 1;
sqlite3ExprCacheClear(pParse);
@@ -4116,9 +4236,13 @@ int sqlite3Select(
*/
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3ExprCacheClear(pParse);
+ if( groupBySort ){
+ sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut);
+ }
for(j=0; jnExpr; j++){
if( groupBySort ){
- sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j);
+ sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
+ if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
}else{
sAggInfo.directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
@@ -4157,10 +4281,10 @@ int sqlite3Select(
/* End of the loop
*/
if( groupBySort ){
- sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop);
+ sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
}else{
sqlite3WhereEnd(pWInfo);
- sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
+ sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
/* Output the final row of result
@@ -4307,7 +4431,7 @@ int sqlite3Select(
** of output.
*/
resetAccumulator(pParse, &sAggInfo);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDel);
goto select_end;
diff --git a/src/shell.c b/src/shell.c
index a54c922e..07623e52 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -12,11 +12,22 @@
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
*/
-#if defined(_WIN32) || defined(WIN32)
+#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
/* This needs to come before any includes for MSVC compiler */
#define _CRT_SECURE_NO_WARNINGS
#endif
+/*
+** Enable large-file support for fopen() and friends on unix.
+*/
+#ifndef SQLITE_DISABLE_LFS
+# define _LARGE_FILE 1
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif
+# define _LARGEFILE_SOURCE 1
+#endif
+
#include
#include
#include
@@ -60,7 +71,7 @@
#else
/* Make sure isatty() has a prototype.
*/
-extern int isatty();
+extern int isatty(int);
#endif
#if defined(_WIN32_WCE)
@@ -74,6 +85,11 @@ extern int isatty();
/* True if the timer is enabled */
static int enableTimer = 0;
+/* ctype macros that work with signed characters */
+#define IsSpace(X) isspace((unsigned char)X)
+#define IsDigit(X) isdigit((unsigned char)X)
+#define ToLower(X) (char)tolower((unsigned char)X)
+
#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
#include
#include
@@ -265,23 +281,23 @@ static void iotracePrintf(const char *zFormat, ...){
*/
static int isNumber(const char *z, int *realnum){
if( *z=='-' || *z=='+' ) z++;
- if( !isdigit(*z) ){
+ if( !IsDigit(*z) ){
return 0;
}
z++;
if( realnum ) *realnum = 0;
- while( isdigit(*z) ){ z++; }
+ while( IsDigit(*z) ){ z++; }
if( *z=='.' ){
z++;
- if( !isdigit(*z) ) return 0;
- while( isdigit(*z) ){ z++; }
+ if( !IsDigit(*z) ) return 0;
+ while( IsDigit(*z) ){ z++; }
if( realnum ) *realnum = 1;
}
if( *z=='e' || *z=='E' ){
z++;
if( *z=='+' || *z=='-' ) z++;
- if( !isdigit(*z) ) return 0;
- while( isdigit(*z) ){ z++; }
+ if( !IsDigit(*z) ) return 0;
+ while( IsDigit(*z) ){ z++; }
if( realnum ) *realnum = 1;
}
return *z==0;
@@ -322,7 +338,6 @@ static char *local_getline(char *zPrompt, FILE *in){
char *zLine;
int nLine;
int n;
- int eol;
if( zPrompt && *zPrompt ){
printf("%s",zPrompt);
@@ -332,8 +347,7 @@ static char *local_getline(char *zPrompt, FILE *in){
zLine = malloc( nLine );
if( zLine==0 ) return 0;
n = 0;
- eol = 0;
- while( !eol ){
+ while( 1 ){
if( n+100>nLine ){
nLine = nLine*2 + 100;
zLine = realloc(zLine, nLine);
@@ -345,7 +359,6 @@ static char *local_getline(char *zPrompt, FILE *in){
return 0;
}
zLine[n] = 0;
- eol = 1;
break;
}
while( zLine[n] ){ n++; }
@@ -353,7 +366,7 @@ static char *local_getline(char *zPrompt, FILE *in){
n--;
if( n>0 && zLine[n-1]=='\r' ) n--;
zLine[n] = 0;
- eol = 1;
+ break;
}
}
zLine = realloc( zLine, n+1 );
@@ -402,6 +415,7 @@ struct callback_data {
int statsOn; /* True to display memory stats before each finalize */
int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */
+ int nErr; /* Number of errors seen */
int mode; /* An output mode setting */
int writableSchema; /* True if PRAGMA writable_schema=ON */
int showHeader; /* True to show column names in List or Column mode */
@@ -927,27 +941,33 @@ static char *appendText(char *zIn, char const *zAppend, char quote){
** querying the SQLITE_MASTER table.
*/
static int run_table_dump_query(
- FILE *out, /* Send output here */
- sqlite3 *db, /* Database to query */
- const char *zSelect, /* SELECT statement to extract content */
- const char *zFirstRow /* Print before first row, if not NULL */
+ struct callback_data *p, /* Query context */
+ const char *zSelect, /* SELECT statement to extract content */
+ const char *zFirstRow /* Print before first row, if not NULL */
){
sqlite3_stmt *pSelect;
int rc;
- rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0);
+ rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
if( rc!=SQLITE_OK || !pSelect ){
+ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
+ p->nErr++;
return rc;
}
rc = sqlite3_step(pSelect);
while( rc==SQLITE_ROW ){
if( zFirstRow ){
- fprintf(out, "%s", zFirstRow);
+ fprintf(p->out, "%s", zFirstRow);
zFirstRow = 0;
}
- fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0));
+ fprintf(p->out, "%s;\n", sqlite3_column_text(pSelect, 0));
rc = sqlite3_step(pSelect);
}
- return sqlite3_finalize(pSelect);
+ rc = sqlite3_finalize(pSelect);
+ if( rc!=SQLITE_OK ){
+ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
+ p->nErr++;
+ }
+ return rc;
}
/*
@@ -1029,7 +1049,12 @@ static int display_stats(
fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
- fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur);
+ fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1;
+ sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
+ fprintf(pArg->out, "Page cache hits: %d\n", iCur);
+ iHiwtr = iCur = -1;
+ sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
+ fprintf(pArg->out, "Page cache misses: %d\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur);
@@ -1069,6 +1094,7 @@ static int shell_exec(
){
sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
int rc = SQLITE_OK; /* Return Code */
+ int rc2;
const char *zLeftover; /* Tail of unprocessed SQL */
if( pzErrMsg ){
@@ -1085,7 +1111,7 @@ static int shell_exec(
if( !pStmt ){
/* this happens for a comment or white-space */
zSql = zLeftover;
- while( isspace(zSql[0]) ) zSql++;
+ while( IsSpace(zSql[0]) ) zSql++;
continue;
}
@@ -1162,10 +1188,11 @@ static int shell_exec(
/* Finalize the statement just executed. If this fails, save a
** copy of the error message. Otherwise, set zSql to point to the
** next statement to execute. */
- rc = sqlite3_finalize(pStmt);
+ rc2 = sqlite3_finalize(pStmt);
+ if( rc!=SQLITE_NOMEM ) rc = rc2;
if( rc==SQLITE_OK ){
zSql = zLeftover;
- while( isspace(zSql[0]) ) zSql++;
+ while( IsSpace(zSql[0]) ) zSql++;
}else if( pzErrMsg ){
*pzErrMsg = save_err_msg(db);
}
@@ -1268,10 +1295,10 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
zSelect = appendText(zSelect, "|| ')' FROM ", 0);
zSelect = appendText(zSelect, zTable, '"');
- rc = run_table_dump_query(p->out, p->db, zSelect, zPrepStmt);
+ rc = run_table_dump_query(p, zSelect, zPrepStmt);
if( rc==SQLITE_CORRUPT ){
zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
- rc = run_table_dump_query(p->out, p->db, zSelect, 0);
+ run_table_dump_query(p, zSelect, 0);
}
if( zSelect ) free(zSelect);
}
@@ -1287,19 +1314,30 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
*/
static int run_schema_dump_query(
struct callback_data *p,
- const char *zQuery,
- char **pzErrMsg
+ const char *zQuery
){
int rc;
- rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg);
+ char *zErr = 0;
+ rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
if( rc==SQLITE_CORRUPT ){
char *zQ2;
int len = strlen30(zQuery);
- if( pzErrMsg ) sqlite3_free(*pzErrMsg);
+ fprintf(p->out, "/****** CORRUPTION ERROR *******/\n");
+ if( zErr ){
+ fprintf(p->out, "/****** %s ******/\n", zErr);
+ sqlite3_free(zErr);
+ zErr = 0;
+ }
zQ2 = malloc( len+100 );
if( zQ2==0 ) return rc;
sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery);
- rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg);
+ rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
+ if( rc ){
+ fprintf(p->out, "/****** ERROR: %s ******/\n", zErr);
+ }else{
+ rc = SQLITE_CORRUPT;
+ }
+ sqlite3_free(zErr);
free(zQ2);
}
return rc;
@@ -1436,7 +1474,7 @@ static int booleanValue(char *zArg){
int val = atoi(zArg);
int j;
for(j=0; zArg[j]; j++){
- zArg[j] = (char)tolower(zArg[j]);
+ zArg[j] = ToLower(zArg[j]);
}
if( strcmp(zArg,"on")==0 ){
val = 1;
@@ -1462,7 +1500,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
/* Parse the input line into tokens.
*/
while( zLine[i] && nArgout, "PRAGMA foreign_keys=OFF;\n");
fprintf(p->out, "BEGIN TRANSACTION;\n");
p->writableSchema = 0;
- sqlite3_exec(p->db, "PRAGMA writable_schema=ON", 0, 0, 0);
+ sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
+ p->nErr = 0;
if( nArg==1 ){
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'", 0
+ "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
);
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
- "WHERE name=='sqlite_sequence'", 0
+ "WHERE name=='sqlite_sequence'"
);
- run_table_dump_query(p->out, p->db,
+ run_table_dump_query(p,
"SELECT sql FROM sqlite_master "
"WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
);
@@ -1574,8 +1612,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE tbl_name LIKE shellstatic() AND type=='table'"
- " AND sql NOT NULL", 0);
- run_table_dump_query(p->out, p->db,
+ " AND sql NOT NULL");
+ run_table_dump_query(p,
"SELECT sql FROM sqlite_master "
"WHERE sql NOT NULL"
" AND type IN ('index','trigger','view')"
@@ -1588,13 +1626,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
p->writableSchema = 0;
}
- sqlite3_exec(p->db, "PRAGMA writable_schema=OFF", 0, 0, 0);
- if( zErrMsg ){
- fprintf(stderr,"Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- }else{
- fprintf(p->out, "COMMIT;\n");
- }
+ sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
+ sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
+ fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
}else
if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
@@ -1673,7 +1707,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(stderr, "Error: non-null separator required for import\n");
return 1;
}
- zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
+ zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
if( zSql==0 ){
fprintf(stderr, "Error: out of memory\n");
return 1;
@@ -1695,7 +1729,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(stderr, "Error: out of memory\n");
return 1;
}
- sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
+ sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zTable);
j = strlen30(zSql);
for(i=1; i1 ){
int i;
- for(i=0; azArg[1][i]; i++) azArg[1][i] = (char)tolower(azArg[1][i]);
+ for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]);
if( strcmp(azArg[1],"sqlite_master")==0 ){
char *new_argv[2], *new_colv[2];
new_argv[0] = "CREATE TABLE sqlite_master (\n"
@@ -2202,7 +2235,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( testctrl<0 ){
testctrl = aCtrl[i].ctrlCode;
}else{
- fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[i]);
+ fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);
testctrl = -1;
break;
}
@@ -2339,7 +2372,7 @@ static int _contains_semicolon(const char *z, int N){
*/
static int _all_whitespace(const char *z){
for(; *z; z++){
- if( isspace(*(unsigned char*)z) ) continue;
+ if( IsSpace(z[0]) ) continue;
if( *z=='/' && z[1]=='*' ){
z += 2;
while( *z && (*z!='*' || z[1]!='/') ){ z++; }
@@ -2364,11 +2397,11 @@ static int _all_whitespace(const char *z){
** as is the Oracle "/".
*/
static int _is_command_terminator(const char *zLine){
- while( isspace(*(unsigned char*)zLine) ){ zLine++; };
+ while( IsSpace(zLine[0]) ){ zLine++; };
if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
return 1; /* Oracle */
}
- if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o'
+ if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
&& _all_whitespace(&zLine[2]) ){
return 1; /* SQL Server */
}
@@ -2438,7 +2471,7 @@ static int process_input(struct callback_data *p, FILE *in){
nSqlPrior = nSql;
if( zSql==0 ){
int i;
- for(i=0; zLine[i] && isspace((unsigned char)zLine[i]); i++){}
+ for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
if( zLine[i]!=0 ){
nSql = strlen30(zLine);
zSql = malloc( nSql+3 );
@@ -2632,6 +2665,9 @@ static const char zOptions[] =
#ifdef SQLITE_ENABLE_VFSTRACE
" -vfstrace enable tracing of all VFS calls\n"
#endif
+#ifdef SQLITE_ENABLE_MULTIPLEX
+ " -multiplex enable the multiplexor VFS\n"
+#endif
;
static void usage(int showDetail){
fprintf(stderr,
@@ -2707,6 +2743,7 @@ int main(int argc, char **argv){
}else if( strcmp(argv[i],"-batch")==0 ){
stdin_is_interactive = 0;
}else if( strcmp(argv[i],"-heap")==0 ){
+#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
int j, c;
const char *zSize;
sqlite3_int64 szHeap;
@@ -2719,7 +2756,6 @@ int main(int argc, char **argv){
if( c=='G' ){ szHeap *= 1000000000; break; }
}
if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
-#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#endif
#ifdef SQLITE_ENABLE_VFSTRACE
@@ -2732,6 +2768,11 @@ int main(int argc, char **argv){
int makeDefault
);
vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
+#endif
+#ifdef SQLITE_ENABLE_MULTIPLEX
+ }else if( strcmp(argv[i],"-multiplex")==0 ){
+ extern int sqlite3_multiple_initialize(const char*,int);
+ sqlite3_multiplex_initialize(0, 1);
#endif
}else if( strcmp(argv[i],"-vfs")==0 ){
sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[++i]);
@@ -2851,8 +2892,14 @@ int main(int argc, char **argv){
i++;
}else if( strcmp(z,"-vfs")==0 ){
i++;
+#ifdef SQLITE_ENABLE_VFSTRACE
}else if( strcmp(z,"-vfstrace")==0 ){
i++;
+#endif
+#ifdef SQLITE_ENABLE_MULTIPLEX
+ }else if( strcmp(z,"-multiplex")==0 ){
+ i++;
+#endif
}else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
usage(1);
}else{
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 2e6ca2b7..ed183307 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -736,6 +736,41 @@ struct sqlite3_io_methods {
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.
+**
+** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
+** retry counts and intervals for certain disk I/O operations for the
+** windows [VFS] in order to work to provide robustness against
+** anti-virus programs. By default, the windows VFS will retry file read,
+** file write, and file delete operations up to 10 times, with a delay
+** of 25 milliseconds before the first retry and with the delay increasing
+** by an additional 25 milliseconds with each subsequent retry. This
+** opcode allows those to values (10 retries and 25 milliseconds of delay)
+** to be adjusted. The values are changed for all database connections
+** within the same process. The argument is a pointer to an array of two
+** integers where the first integer i the new retry count and the second
+** integer is the delay. If either integer is negative, then the setting
+** is not changed but instead the prior value of that setting is written
+** into the array entry, allowing the current retry settings to be
+** interrogated. The zDbName parameter is ignored.
+**
+** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
+** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
+** write ahead log and shared memory files used for transaction control
+** are automatically deleted when the latest connection to the database
+** closes. Setting persistent WAL mode causes those files to persist after
+** close. Persisting the files is useful when other processes that do not
+** have write permission on the directory containing the database file want
+** to read the database file, as the WAL and shared memory files must exist
+** in order for the database to be readable. The fourth parameter to
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
+** WAL mode. If the integer is -1, then it is overwritten with the current
+** WAL persistence setting.
+**
+** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
+** a write transaction to indicate that, unless it is rolled back for some
+** reason, the entire database file will be overwritten by the current
+** transaction. This is used by VACUUM operations.
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_GET_LOCKPROXYFILE 2
@@ -745,7 +780,9 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CHUNK_SIZE 6
#define SQLITE_FCNTL_FILE_POINTER 7
#define SQLITE_FCNTL_SYNC_OMITTED 8
-
+#define SQLITE_FCNTL_WIN32_AV_RETRY 9
+#define SQLITE_FCNTL_PERSIST_WAL 10
+#define SQLITE_FCNTL_OVERWRITE 11
/*
** CAPI3REF: Mutex Handle
@@ -1173,16 +1210,10 @@ int sqlite3_db_config(sqlite3*, int op, ...);
** order to verify that SQLite recovers gracefully from such
** conditions.
**
-** The xMalloc and xFree methods must work like the
-** malloc() and free() functions from the standard C library.
-** The xRealloc method must work like realloc() from the standard C library
-** with the exception that if the second argument to xRealloc is zero,
-** xRealloc must be a no-op - it must not perform any allocation or
-** deallocation. ^SQLite guarantees that the second argument to
+** The xMalloc, xRealloc, and xFree methods must work like the
+** malloc(), realloc() and free() functions from the standard C library.
+** ^SQLite guarantees that the second argument to
** xRealloc is always a value returned by a prior call to xRoundup.
-** And so in cases where xRoundup always returns a positive number,
-** xRealloc can perform exactly as the standard library realloc() and
-** still be in compliance with this specification.
**
** xSize should return the allocated size of a memory allocation
** previously obtained from xMalloc or xRealloc. The allocated size
@@ -1368,8 +1399,8 @@ struct sqlite3_mem_methods {
** allocator is engaged to handle all of SQLites memory allocation needs.
** The first pointer (the memory pointer) must be aligned to an 8-byte
** boundary or subsequent behavior of SQLite will be undefined.
-** The minimum allocation size is capped at 2^12. Reasonable values
-** for the minimum allocation size are 2^5 through 2^8.
+** The minimum allocation size is capped at 2**12. Reasonable values
+** for the minimum allocation size are 2**5 through 2**8.
**
** [[SQLITE_CONFIG_MUTEX]] SQLITE_CONFIG_MUTEX
** ^(This option takes a single argument which is a pointer to an
@@ -2768,7 +2799,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** that the supplied string is nul-terminated, then there is a small
** performance advantage to be gained by passing an nByte parameter that
** is equal to the number of bytes in the input string including
-** the nul-terminator bytes.
+** the nul-terminator bytes as this saves SQLite from having to
+** make a copy of the input string.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only
@@ -2819,7 +2851,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** ^The specific value of WHERE-clause [parameter] might influence the
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
-** and the [SQLITE_ENABLE_STAT2] compile-time option is enabled.
+** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** the
**
**
@@ -2989,6 +3021,13 @@ typedef struct sqlite3_context sqlite3_context;
** number of bytes in the value, not the number of characters.)^
** ^If the fourth parameter is negative, the length of the string is
** the number of bytes up to the first zero terminator.
+** If a non-negative fourth parameter is provided to sqlite3_bind_text()
+** or sqlite3_bind_text16() then that parameter must be the byte offset
+** where the NUL terminator would occur assuming the string were NUL
+** terminated. If any NUL characters occur at byte offsets less than
+** the value of the fourth parameter then the resulting string value will
+** contain embedded NULs. The result of expressions involving strings
+** with embedded NULs is undefined.
**
** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
@@ -3322,6 +3361,12 @@ int sqlite3_step(sqlite3_stmt*);
** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
** interfaces) then sqlite3_data_count(P) returns 0.
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
+** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
+** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P)
+** will return non-zero if previous call to [sqlite3_step](P) returned
+** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
+** where it always returns zero since each step of that multi-step
+** pragma returns 0 columns of data.
**
** See also: [sqlite3_column_count()]
*/
@@ -4001,7 +4046,12 @@ typedef void (*sqlite3_destructor_type)(void*);
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text
** pointed to by the 2nd parameter are taken as the application-defined
-** function result.
+** function result. If the 3rd parameter is non-negative, then it
+** must be the byte offset into the string where the NUL terminator would
+** appear if the string where NUL terminated. If any NUL characters occur
+** in the string at a byte offset that is less than the value of the 3rd
+** parameter, then the resulting string will contain embedded NULs and the
+** result of expressions operating on strings with embedded NULs is undefined.
** ^If the 4th parameter to the sqlite3_result_text* interfaces
** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
** function as the destructor on the text or BLOB result when it has
@@ -5784,6 +5834,18 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
**
+**
+** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(SQLITE_DBSTATUS_CACHE_HIT
+** This parameter returns the number of pager cache hits that have
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
+** is always 0.
+**
+**
+** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(SQLITE_DBSTATUS_CACHE_MISS
+** This parameter returns the number of pager cache misses that have
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
+** is always 0.
+**
**
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
@@ -5793,7 +5855,9 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
-#define SQLITE_DBSTATUS_MAX 6 /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_CACHE_HIT 7
+#define SQLITE_DBSTATUS_CACHE_MISS 8
+#define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */
/*
@@ -5847,7 +5911,6 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** A non-zero value in this counter may indicate an opportunity to
** improvement performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.
-**
**
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h
index e45e691f..5abcde2c 100644
--- a/src/sqlite3ext.h
+++ b/src/sqlite3ext.h
@@ -49,8 +49,10 @@ struct sqlite3_api_routines {
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
- int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*));
- int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*));
+ int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
+ int eTextRep,const char*));
+ int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
+ int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
@@ -75,10 +77,18 @@ struct sqlite3_api_routines {
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
- int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));
- int (*create_collation16)(sqlite3*,const void*,int,void*,int(*)(void*,int,const void*,int,const void*));
- int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
- int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
+ int (*create_collation)(sqlite3*,const char*,int,void*,
+ int(*)(void*,int,const void*,int,const void*));
+ int (*create_collation16)(sqlite3*,const void*,int,void*,
+ int(*)(void*,int,const void*,int,const void*));
+ int (*create_function)(sqlite3*,const char*,int,int,void*,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*));
+ int (*create_function16)(sqlite3*,const void*,int,int,void*,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
@@ -123,16 +133,19 @@ struct sqlite3_api_routines {
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
- int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*);
+ int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
+ const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
- int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*);
+ int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
+ char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
- void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*);
+ void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
+ sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
@@ -154,15 +167,19 @@ struct sqlite3_api_routines {
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
/* Added by 3.4.1 */
- int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *));
+ int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
+ void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
int (*blob_bytes)(sqlite3_blob*);
int (*blob_close)(sqlite3_blob*);
- int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**);
+ int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
+ int,sqlite3_blob**);
int (*blob_read)(sqlite3_blob*,void*,int,int);
int (*blob_write)(sqlite3_blob*,const void*,int,int);
- int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*));
+ int (*create_collation_v2)(sqlite3*,const char*,int,void*,
+ int(*)(void*,int,const void*,int,const void*),
+ void(*)(void*));
int (*file_control)(sqlite3*,const char*,int,void*);
sqlite3_int64 (*memory_highwater)(int);
sqlite3_int64 (*memory_used)(void);
@@ -198,7 +215,11 @@ struct sqlite3_api_routines {
int (*backup_step)(sqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
- int (*create_function_v2)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*),void(*xDestroy)(void*));
+ int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*),
+ void(*xDestroy)(void*));
int (*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
@@ -212,6 +233,9 @@ struct sqlite3_api_routines {
int (*wal_autocheckpoint)(sqlite3*,int);
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
+ int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
+ int (*vtab_config)(sqlite3*,int op,...);
+ int (*vtab_on_conflict)(sqlite3*);
};
/*
@@ -412,6 +436,9 @@ struct sqlite3_api_routines {
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook sqlite3_api->wal_hook
+#define sqlite3_blob_reopen sqlite3_api->blob_reopen
+#define sqlite3_vtab_config sqlite3_api->vtab_config
+#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
#endif /* SQLITE_CORE */
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 09f64b79..9e276541 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -76,13 +76,6 @@
#include
#endif
-/*
-** The number of samples of an index that SQLite takes in order to
-** construct a histogram of the table content when running ANALYZE
-** and with SQLITE_ENABLE_STAT2
-*/
-#define SQLITE_INDEX_SAMPLES 10
-
/*
** The following macros are used to cast pointers to integers and
** integers to pointers. The way you do this varies from one compiler
@@ -147,19 +140,25 @@
** specify which memory allocation subsystem to use.
**
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
+** SQLITE_WIN32_MALLOC // Use Win32 native heap API
** SQLITE_MEMDEBUG // Debugging version of system malloc()
**
+** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
+** assert() macro is enabled, each call into the Win32 native heap subsystem
+** will cause HeapValidate to be called. If heap validation should fail, an
+** assertion will be triggered.
+**
** (Historical note: There used to be several other options, but we've
-** pared it down to just these two.)
+** pared it down to just these three.)
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
# error "At most one of the following compile-time configuration options\
- is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
+ is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG"
#endif
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif
@@ -445,6 +444,18 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
*/
#define SQLITE_MAX_U32 ((((u64)1)<<32)-1)
+/*
+** The datatype used to store estimates of the number of rows in a
+** table or index. This is an unsigned integer type. For 99.9% of
+** the world, a 32-bit integer is sufficient. But a 64-bit integer
+** can be used at compile-time if desired.
+*/
+#ifdef SQLITE_64BIT_STATS
+ typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
+#else
+ typedef u32 tRowcnt; /* 32-bit is the default */
+#endif
+
/*
** Macros to determine whether the machine is big or little endian,
** evaluated at runtime.
@@ -956,6 +967,7 @@ struct sqlite3 {
#define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */
#define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */
+#define SQLITE_DistinctOpt 0x80 /* DISTINCT using indexes */
#define SQLITE_OptMask 0xff /* Mask of all disablable opts */
/*
@@ -1277,7 +1289,7 @@ struct Table {
Column *aCol; /* Information about each column */
Index *pIndex; /* List of SQL indexes on this table. */
int tnum; /* Root BTree node for this table (see note above) */
- unsigned nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
+ tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
u16 nRef; /* Number of pointers to this Table */
u8 tabFlags; /* Mask of TF_* values */
@@ -1476,7 +1488,7 @@ struct Index {
char *zName; /* Name of this index */
int nColumn; /* Number of columns in the table used by this index */
int *aiColumn; /* Which columns are used by this index. 1st is 0 */
- unsigned *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
+ tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
Table *pTable; /* The SQL table being indexed */
int tnum; /* Page containing root of this index in database file */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
@@ -1487,20 +1499,29 @@ struct Index {
Schema *pSchema; /* Schema containing this index */
u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */
char **azColl; /* Array of collation sequence names for index */
- IndexSample *aSample; /* Array of SQLITE_INDEX_SAMPLES samples */
+#ifdef SQLITE_ENABLE_STAT3
+ int nSample; /* Number of elements in aSample[] */
+ tRowcnt avgEq; /* Average nEq value for key values not in aSample */
+ IndexSample *aSample; /* Samples of the left-most key */
+#endif
};
/*
-** Each sample stored in the sqlite_stat2 table is represented in memory
-** using a structure of this type.
+** Each sample stored in the sqlite_stat3 table is represented in memory
+** using a structure of this type. See documentation at the top of the
+** analyze.c source file for additional information.
*/
struct IndexSample {
union {
char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
- double r; /* Value if eType is SQLITE_FLOAT or SQLITE_INTEGER */
+ double r; /* Value if eType is SQLITE_FLOAT */
+ i64 i; /* Value if eType is SQLITE_INTEGER */
} u;
u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */
- u8 nByte; /* Size in byte of text or blob. */
+ int nByte; /* Size in byte of text or blob. */
+ tRowcnt nEq; /* Est. number of rows where the key equals this sample */
+ tRowcnt nLt; /* Est. number of rows where key is less than this sample */
+ tRowcnt nDLt; /* Est. number of distinct keys less than this sample */
};
/*
@@ -1535,6 +1556,7 @@ struct AggInfo {
u8 useSortingIdx; /* In direct mode, reference the sorting index rather
** than the source table */
int sortingIdx; /* Cursor number of the sorting index */
+ int sortingIdxPTab; /* Cursor number of pseudo-table */
ExprList *pGroupBy; /* The group by clause */
int nSortingColumn; /* Number of columns in the sorting index */
struct AggInfo_col { /* For each column used in source tables */
@@ -1844,9 +1866,11 @@ struct SrcList {
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pTab; /* An SQL table corresponding to zName */
Select *pSelect; /* A SELECT statement used in place of a table name */
- u8 isPopulated; /* Temporary table associated with SELECT is populated */
+ int addrFillSub; /* Address of subroutine to manifest a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
u8 jointype; /* Type of join between this able and the previous */
u8 notIndexed; /* True if there is a NOT INDEXED clause */
+ u8 isCorrelated; /* True if sub-query is correlated */
#ifndef SQLITE_OMIT_EXPLAIN
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
#endif
@@ -1949,10 +1973,10 @@ struct WhereLevel {
#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */
#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
-#define WHERE_OMIT_OPEN 0x0010 /* Table cursors are already open */
-#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */
-#define WHERE_FORCE_TABLE 0x0040 /* Do not use an index-only search */
-#define WHERE_ONETABLE_ONLY 0x0080 /* Only code the 1st table in pTabList */
+#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
+#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
+#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
+#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
/*
** The WHERE clause processing routine has two halves. The
@@ -1966,6 +1990,7 @@ struct WhereInfo {
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
+ u8 eDistinct;
SrcList *pTabList; /* List of tables in the join */
int iTop; /* The very beginning of the WHERE loop */
int iContinue; /* Jump here to continue with next record */
@@ -1977,6 +2002,9 @@ struct WhereInfo {
WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
+#define WHERE_DISTINCT_UNIQUE 1
+#define WHERE_DISTINCT_ORDERED 2
+
/*
** A NameContext defines a context in which to resolve table and column
** names. The context consists of a list of tables (the pSrcList) field and
@@ -2062,6 +2090,7 @@ struct Select {
#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
+#define SF_UseSorter 0x0040 /* Sort using a sorter */
/*
@@ -2701,6 +2730,7 @@ void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
#endif
void sqlite3DropTable(Parse*, SrcList*, int, int);
+void sqlite3CodeDropTable(Parse*, Table*, int, int);
void sqlite3DeleteTable(sqlite3*, Table*);
#ifndef SQLITE_OMIT_AUTOINCREMENT
void sqlite3AutoincrementBegin(Parse *pParse);
@@ -2738,7 +2768,7 @@ Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *,
#endif
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
+WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
void sqlite3WhereEnd(WhereInfo*);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
@@ -2957,7 +2987,7 @@ void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void sqlite3ValueFree(sqlite3_value*);
sqlite3_value *sqlite3ValueNew(sqlite3 *);
char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
#endif
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
@@ -3059,6 +3089,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
# define sqlite3VtabUnlock(X)
# define sqlite3VtabUnlockList(X)
# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
+# define sqlite3GetVTable(X,Y) ((VTable*)0)
#else
void sqlite3VtabClear(sqlite3 *db, Table*);
int sqlite3VtabSync(sqlite3 *db, char **);
@@ -3068,6 +3099,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
void sqlite3VtabUnlock(VTable *);
void sqlite3VtabUnlockList(sqlite3*);
int sqlite3VtabSavepoint(sqlite3 *, int, int);
+ VTable *sqlite3GetVTable(sqlite3*, Table*);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
void sqlite3VtabMakeWritable(Parse*,Table*);
@@ -3087,7 +3119,6 @@ int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
int sqlite3TempInMemory(const sqlite3*);
-VTable *sqlite3GetVTable(sqlite3*, Table*);
const char *sqlite3JournalModename(int);
int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
diff --git a/src/status.c b/src/status.c
index b8c1d58d..b23238bb 100644
--- a/src/status.c
+++ b/src/status.c
@@ -218,6 +218,28 @@ int sqlite3_db_status(
break;
}
+ /*
+ ** Set *pCurrent to the total cache hits or misses encountered by all
+ ** pagers the database handle is connected to. *pHighwater is always set
+ ** to zero.
+ */
+ case SQLITE_DBSTATUS_CACHE_HIT:
+ case SQLITE_DBSTATUS_CACHE_MISS: {
+ int i;
+ int nRet = 0;
+ assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
+
+ for(i=0; inDb; i++){
+ if( db->aDb[i].pBt ){
+ Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
+ sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
+ }
+ }
+ *pHighwater = 0;
+ *pCurrent = nRet;
+ break;
+ }
+
default: {
rc = SQLITE_ERROR;
}
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index ad4d27a1..c8f0fbd3 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -107,6 +107,11 @@ typedef struct IncrblobChannel IncrblobChannel;
/*
** There is one instance of this structure for each SQLite database
** that has been opened by the SQLite TCL interface.
+**
+** If this module is built with SQLITE_TEST defined (to create the SQLite
+** testfixture executable), then it may be configured to use either
+** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements.
+** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used.
*/
typedef struct SqliteDb SqliteDb;
struct SqliteDb {
@@ -135,6 +140,9 @@ struct SqliteDb {
IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
int nStep, nSort, nIndex; /* Statistics for most recent operation */
int nTransaction; /* Number of nested [transaction] methods */
+#ifdef SQLITE_TEST
+ int bLegacyPrepare; /* True to use sqlite3_prepare() */
+#endif
};
struct IncrblobChannel {
@@ -429,20 +437,33 @@ static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
return pNew;
}
+/*
+** Free a single SqlPreparedStmt object.
+*/
+static void dbFreeStmt(SqlPreparedStmt *pStmt){
+#ifdef SQLITE_TEST
+ if( sqlite3_sql(pStmt->pStmt)==0 ){
+ Tcl_Free((char *)pStmt->zSql);
+ }
+#endif
+ sqlite3_finalize(pStmt->pStmt);
+ Tcl_Free((char *)pStmt);
+}
+
/*
** Finalize and free a list of prepared statements
*/
-static void flushStmtCache( SqliteDb *pDb ){
+static void flushStmtCache(SqliteDb *pDb){
SqlPreparedStmt *pPreStmt;
+ SqlPreparedStmt *pNext;
- while( pDb->stmtList ){
- sqlite3_finalize( pDb->stmtList->pStmt );
- pPreStmt = pDb->stmtList;
- pDb->stmtList = pDb->stmtList->pNext;
- Tcl_Free( (char*)pPreStmt );
+ for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pNext){
+ pNext = pPreStmt->pNext;
+ dbFreeStmt(pPreStmt);
}
pDb->nStmt = 0;
pDb->stmtLast = 0;
+ pDb->stmtList = 0;
}
/*
@@ -898,7 +919,7 @@ static int auth_callback(
Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
Tcl_DStringFree(&str);
- zReply = Tcl_GetStringResult(pDb->interp);
+ zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
if( strcmp(zReply,"SQLITE_OK")==0 ){
rc = SQLITE_OK;
}else if( strcmp(zReply,"SQLITE_DENY")==0 ){
@@ -947,14 +968,12 @@ static char *local_getline(char *zPrompt, FILE *in){
char *zLine;
int nLine;
int n;
- int eol;
nLine = 100;
zLine = malloc( nLine );
if( zLine==0 ) return 0;
n = 0;
- eol = 0;
- while( !eol ){
+ while( 1 ){
if( n+100>nLine ){
nLine = nLine*2 + 100;
zLine = realloc(zLine, nLine);
@@ -966,14 +985,13 @@ static char *local_getline(char *zPrompt, FILE *in){
return 0;
}
zLine[n] = 0;
- eol = 1;
break;
}
while( zLine[n] ){ n++; }
if( n>0 && zLine[n-1]=='\n' ){
n--;
zLine[n] = 0;
- eol = 1;
+ break;
}
}
zLine = realloc( zLine, n+1 );
@@ -1030,6 +1048,27 @@ static int DbTransPostCmd(
return rc;
}
+/*
+** Unless SQLITE_TEST is defined, this function is a simple wrapper around
+** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either
+** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending
+** on whether or not the [db_use_legacy_prepare] command has been used to
+** configure the connection.
+*/
+static int dbPrepare(
+ SqliteDb *pDb, /* Database object */
+ const char *zSql, /* SQL to compile */
+ sqlite3_stmt **ppStmt, /* OUT: Prepared statement */
+ const char **pzOut /* OUT: Pointer to next SQL statement */
+){
+#ifdef SQLITE_TEST
+ if( pDb->bLegacyPrepare ){
+ return sqlite3_prepare(pDb->db, zSql, -1, ppStmt, pzOut);
+ }
+#endif
+ return sqlite3_prepare_v2(pDb->db, zSql, -1, ppStmt, pzOut);
+}
+
/*
** Search the cache for a prepared-statement object that implements the
** first SQL statement in the buffer pointed to by parameter zIn. If
@@ -1100,7 +1139,7 @@ static int dbPrepareAndBind(
if( pPreStmt==0 ){
int nByte;
- if( SQLITE_OK!=sqlite3_prepare_v2(pDb->db, zSql, -1, &pStmt, pzOut) ){
+ if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
return TCL_ERROR;
}
@@ -1127,6 +1166,14 @@ static int dbPrepareAndBind(
pPreStmt->nSql = (*pzOut - zSql);
pPreStmt->zSql = sqlite3_sql(pStmt);
pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1];
+#ifdef SQLITE_TEST
+ if( pPreStmt->zSql==0 ){
+ char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1);
+ memcpy(zCopy, zSql, pPreStmt->nSql);
+ zCopy[pPreStmt->nSql] = '\0';
+ pPreStmt->zSql = zCopy;
+ }
+#endif
}
assert( pPreStmt );
assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql );
@@ -1180,7 +1227,6 @@ static int dbPrepareAndBind(
return TCL_OK;
}
-
/*
** Release a statement reference obtained by calling dbPrepareAndBind().
** There should be exactly one call to this function for each call to
@@ -1205,8 +1251,7 @@ static void dbReleaseStmt(
if( pDb->maxStmt<=0 || discard ){
/* If the cache is turned off, deallocated the statement */
- sqlite3_finalize(pPreStmt->pStmt);
- Tcl_Free((char *)pPreStmt);
+ dbFreeStmt(pPreStmt);
}else{
/* Add the prepared statement to the beginning of the cache list. */
pPreStmt->pNext = pDb->stmtList;
@@ -1226,11 +1271,11 @@ static void dbReleaseStmt(
/* If we have too many statement in cache, remove the surplus from
** the end of the cache list. */
while( pDb->nStmt>pDb->maxStmt ){
- sqlite3_finalize(pDb->stmtLast->pStmt);
- pDb->stmtLast = pDb->stmtLast->pPrev;
- Tcl_Free((char*)pDb->stmtLast->pNext);
+ SqlPreparedStmt *pLast = pDb->stmtLast;
+ pDb->stmtLast = pLast->pPrev;
pDb->stmtLast->pNext = 0;
pDb->nStmt--;
+ dbFreeStmt(pLast);
}
}
}
@@ -1363,9 +1408,12 @@ static void dbEvalRowInfo(
** no further rows available. This is similar to SQLITE_DONE.
*/
static int dbEvalStep(DbEvalContext *p){
+ const char *zPrevSql = 0; /* Previous value of p->zSql */
+
while( p->zSql[0] || p->pPreStmt ){
int rc;
if( p->pPreStmt==0 ){
+ zPrevSql = (p->zSql==zPrevSql ? 0 : p->zSql);
rc = dbPrepareAndBind(p->pDb, p->zSql, &p->zSql, &p->pPreStmt);
if( rc!=TCL_OK ) return rc;
}else{
@@ -1392,8 +1440,19 @@ static int dbEvalStep(DbEvalContext *p){
if( rcs!=SQLITE_OK ){
/* If a run-time error occurs, report the error and stop reading
** the SQL. */
- Tcl_SetObjResult(pDb->interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
dbReleaseStmt(pDb, pPreStmt, 1);
+#if SQLITE_TEST
+ if( p->pDb->bLegacyPrepare && rcs==SQLITE_SCHEMA && zPrevSql ){
+ /* If the runtime error was an SQLITE_SCHEMA, and the database
+ ** handle is configured to use the legacy sqlite3_prepare()
+ ** interface, retry prepare()/step() on the same SQL statement.
+ ** This only happens once. If there is a second SQLITE_SCHEMA
+ ** error, the error will be returned to the caller. */
+ p->zSql = zPrevSql;
+ continue;
+ }
+#endif
+ Tcl_SetObjResult(pDb->interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
return TCL_ERROR;
}else{
dbReleaseStmt(pDb, pPreStmt, 0);
@@ -2059,7 +2118,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
zCommit = "COMMIT";
while( (zLine = local_getline(0, in))!=0 ){
char *z;
- i = 0;
lineno++;
azCol[0] = zLine;
for(i=0, z=zLine; *z; z++){
@@ -2180,6 +2238,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
if( choice==DB_ONECOLUMN ){
if( rc==TCL_OK ){
Tcl_SetObjResult(interp, dbEvalColumnValue(&sEval, 0));
+ }else if( rc==TCL_BREAK ){
+ Tcl_ResetResult(interp);
}
}else if( rc==TCL_BREAK || rc==TCL_OK ){
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc==TCL_OK));
@@ -2486,14 +2546,16 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
** Change the encryption key on the currently open database.
*/
case DB_REKEY: {
+#ifdef SQLITE_HAS_CODEC
int nKey;
void *pKey;
+#endif
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "KEY");
return TCL_ERROR;
}
- pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
#ifdef SQLITE_HAS_CODEC
+ pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
rc = sqlite3_rekey(pDb->db, pKey, nKey);
if( rc ){
Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
@@ -2856,8 +2918,6 @@ static int DbObjCmdAdaptor(
*/
static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
SqliteDb *p;
- void *pKey = 0;
- int nKey = 0;
const char *zArg;
char *zErrMsg;
int i;
@@ -2865,6 +2925,10 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
const char *zVfs = 0;
int flags;
Tcl_DString translatedFilename;
+#ifdef SQLITE_HAS_CODEC
+ void *pKey = 0;
+ int nKey = 0;
+#endif
/* In normal use, each TCL interpreter runs in a single thread. So
** by default, we can turn of mutexing on SQLite database connections.
@@ -2896,7 +2960,9 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
for(i=3; i+1 \"\n"
- "} else {\n"
- "puts -nonewline \"% \"\n"
- "}\n"
- "flush stdout\n"
- "append line [gets stdin]\n"
- "if {[info complete $line]} {\n"
- "if {[catch {uplevel #0 $line} result]} {\n"
- "puts stderr \"Error: $result\"\n"
- "} elseif {$result!=\"\"} {\n"
- "puts $result\n"
+static const char *tclsh_main_loop(void){
+ static const char zMainloop[] =
+ "set line {}\n"
+ "while {![eof stdin]} {\n"
+ "if {$line!=\"\"} {\n"
+ "puts -nonewline \"> \"\n"
+ "} else {\n"
+ "puts -nonewline \"% \"\n"
+ "}\n"
+ "flush stdout\n"
+ "append line [gets stdin]\n"
+ "if {[info complete $line]} {\n"
+ "if {[catch {uplevel #0 $line} result]} {\n"
+ "puts stderr \"Error: $result\"\n"
+ "} elseif {$result!=\"\"} {\n"
+ "puts $result\n"
+ "}\n"
+ "set line {}\n"
+ "} else {\n"
+ "append line \\n\n"
"}\n"
- "set line {}\n"
- "} else {\n"
- "append line \\n\n"
"}\n"
- "}\n"
-;
+ ;
+ return zMainloop;
+}
#endif
#if TCLSH==2
-static char zMainloop[] =
-#include "spaceanal_tcl.h"
-;
+static const char *tclsh_main_loop(void);
#endif
#ifdef SQLITE_TEST
@@ -3527,6 +3594,44 @@ static int init_all_cmd(
init_all(slave);
return TCL_OK;
}
+
+/*
+** Tclcmd: db_use_legacy_prepare DB BOOLEAN
+**
+** The first argument to this command must be a database command created by
+** [sqlite3]. If the second argument is true, then the handle is configured
+** to use the sqlite3_prepare_v2() function to prepare statements. If it
+** is false, sqlite3_prepare().
+*/
+static int db_use_legacy_prepare_cmd(
+ ClientData cd,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ Tcl_CmdInfo cmdInfo;
+ SqliteDb *pDb;
+ int bPrepare;
+
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
+ return TCL_ERROR;
+ }
+
+ if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
+ Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0);
+ return TCL_ERROR;
+ }
+ pDb = (SqliteDb*)cmdInfo.objClientData;
+ if( Tcl_GetBooleanFromObj(interp, objv[2], &bPrepare) ){
+ return TCL_ERROR;
+ }
+
+ pDb->bLegacyPrepare = bPrepare;
+
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+}
#endif
/*
@@ -3547,6 +3652,17 @@ static void init_all(Tcl_Interp *interp){
Md5_Init(interp);
#endif
+ /* Install the [register_dbstat_vtab] command to access the implementation
+ ** of virtual table dbstat (source file test_stat.c). This command is
+ ** required for testfixture and sqlite3_analyzer, but not by the production
+ ** Tcl extension. */
+#if defined(SQLITE_TEST) || TCLSH==2
+ {
+ extern int SqlitetestStat_Init(Tcl_Interp*);
+ SqlitetestStat_Init(interp);
+ }
+#endif
+
#ifdef SQLITE_TEST
{
extern int Sqliteconfig_Init(Tcl_Interp*);
@@ -3576,7 +3692,6 @@ static void init_all(Tcl_Interp *interp){
extern int Sqlitetestbackup_Init(Tcl_Interp*);
extern int Sqlitetestintarray_Init(Tcl_Interp*);
extern int Sqlitetestvfs_Init(Tcl_Interp *);
- extern int SqlitetestStat_Init(Tcl_Interp*);
extern int Sqlitetestrtree_Init(Tcl_Interp*);
extern int Sqlitequota_Init(Tcl_Interp*);
extern int Sqlitemultiplex_Init(Tcl_Interp*);
@@ -3620,7 +3735,6 @@ static void init_all(Tcl_Interp *interp){
Sqlitetestbackup_Init(interp);
Sqlitetestintarray_Init(interp);
Sqlitetestvfs_Init(interp);
- SqlitetestStat_Init(interp);
Sqlitetestrtree_Init(interp);
Sqlitequota_Init(interp);
Sqlitemultiplex_Init(interp);
@@ -3633,7 +3747,12 @@ static void init_all(Tcl_Interp *interp){
Sqlitetestfts3_Init(interp);
#endif
- Tcl_CreateObjCommand(interp,"load_testfixture_extensions",init_all_cmd,0,0);
+ Tcl_CreateObjCommand(
+ interp, "load_testfixture_extensions", init_all_cmd, 0, 0
+ );
+ Tcl_CreateObjCommand(
+ interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0
+ );
#ifdef SQLITE_SSE
Sqlitetestsse_Init(interp);
@@ -3651,12 +3770,13 @@ int TCLSH_MAIN(int argc, char **argv){
** sqlite3_initialize() is. */
sqlite3_shutdown();
+ Tcl_FindExecutable(argv[0]);
+ interp = Tcl_CreateInterp();
+
#if TCLSH==2
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
#endif
- Tcl_FindExecutable(argv[0]);
- interp = Tcl_CreateInterp();
init_all(interp);
if( argc>=2 ){
int i;
@@ -3677,7 +3797,7 @@ int TCLSH_MAIN(int argc, char **argv){
}
}
if( TCLSH==2 || argc<=1 ){
- Tcl_GlobalEval(interp, zMainloop);
+ Tcl_GlobalEval(interp, tclsh_main_loop());
}
return 0;
}
diff --git a/src/test1.c b/src/test1.c
index 7fdf54b1..26342522 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -4395,7 +4395,7 @@ static u8 *sqlite3_stack_baseline = 0;
static void prepStack(void){
int i;
u32 bigBuf[65536];
- for(i=0; ievName ){
+ HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
+ if ( ev ){
+ SetEvent(ev);
+ CloseHandle(ev);
+ }
+ }
+ if( p->delay1 ) Sleep(p->delay1);
+ if( LockFile(p->h, 0, 0, 100000000, 0) ){
+ Sleep(p->delay2);
+ UnlockFile(p->h, 0, 0, 100000000, 0);
+ p->ok = 1;
+ }else{
+ p->err = 1;
+ }
+ CloseHandle(p->h);
+ p->h = 0;
+ p->delay1 = 0;
+ p->delay2 = 0;
+}
+#endif
+
+#if SQLITE_OS_WIN
+/*
+** lock_win32_file FILENAME DELAY1 DELAY2
+**
+** Get an exclusive manditory lock on file for DELAY2 milliseconds.
+** Wait DELAY1 milliseconds before acquiring the lock.
+*/
+static int win32_file_lock(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
+ const char *zFilename;
+ char zBuf[200];
+ int retry = 0;
+ HANDLE ev;
+ DWORD wResult;
+
+ if( objc!=4 && objc!=1 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
+ return TCL_ERROR;
+ }
+ if( objc==1 ){
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
+ x.ok, x.err, x.delay1, x.delay2, x.h);
+ Tcl_AppendResult(interp, zBuf, (char*)0);
+ return TCL_OK;
+ }
+ while( x.h && retry<30 ){
+ retry++;
+ Sleep(100);
+ }
+ if( x.h ){
+ Tcl_AppendResult(interp, "busy", (char*)0);
+ return TCL_ERROR;
+ }
+ if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
+ if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
+ zFilename = Tcl_GetString(objv[1]);
+ x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ if( !x.h ){
+ Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
+ return TCL_ERROR;
+ }
+ ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
+ if ( !ev ){
+ Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
+ return TCL_ERROR;
+ }
+ _beginthread(win32_file_locker, 0, (void*)&x);
+ Sleep(0);
+ if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
+ Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
+ CloseHandle(ev);
+ return TCL_ERROR;
+ }
+ CloseHandle(ev);
+ return TCL_OK;
+}
+#endif
+
/*
** optimization_control DB OPT BOOLEAN
@@ -5754,6 +5928,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "restore_prng_state", restore_prng_state, 0 },
{ "reset_prng_state", reset_prng_state, 0 },
{ "optimization_control", optimization_control,0},
+#if SQLITE_OS_WIN
+ { "lock_win32_file", win32_file_lock, 0 },
+#endif
{ "tcl_objproc", runAsObjProc, 0 },
/* sqlite3_column_*() API */
@@ -5802,7 +5979,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
- { "file_control_sizehint_test", file_control_sizehint_test, 0 },
+ { "file_control_sizehint_test", file_control_sizehint_test, 0 },
+ { "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
+ { "file_control_persist_wal", file_control_persist_wal, 0 },
{ "sqlite3_vfs_list", vfs_list, 0 },
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
diff --git a/src/test6.c b/src/test6.c
index c9c8a4d2..23fb14c5 100644
--- a/src/test6.c
+++ b/src/test6.c
@@ -505,6 +505,16 @@ static int cfCheckReservedLock(sqlite3_file *pFile, int *pResOut){
return sqlite3OsCheckReservedLock(((CrashFile *)pFile)->pRealFile, pResOut);
}
static int cfFileControl(sqlite3_file *pFile, int op, void *pArg){
+ if( op==SQLITE_FCNTL_SIZE_HINT ){
+ CrashFile *pCrash = (CrashFile *)pFile;
+ i64 nByte = *(i64 *)pArg;
+ if( nByte>pCrash->iSize ){
+ if( SQLITE_OK==writeListAppend(pFile, nByte, 0, 0) ){
+ pCrash->iSize = nByte;
+ }
+ }
+ return SQLITE_OK;
+ }
return sqlite3OsFileControl(((CrashFile *)pFile)->pRealFile, op, pArg);
}
diff --git a/src/test8.c b/src/test8.c
index b3e6058a..283d790b 100644
--- a/src/test8.c
+++ b/src/test8.c
@@ -1232,12 +1232,50 @@ static int echoRename(sqlite3_vtab *vtab, const char *zNewName){
return rc;
}
+static int echoSavepoint(sqlite3_vtab *pVTab, int iSavepoint){
+ assert( pVTab );
+ return SQLITE_OK;
+}
+
+static int echoRelease(sqlite3_vtab *pVTab, int iSavepoint){
+ assert( pVTab );
+ return SQLITE_OK;
+}
+
+static int echoRollbackTo(sqlite3_vtab *pVTab, int iSavepoint){
+ assert( pVTab );
+ return SQLITE_OK;
+}
+
/*
** A virtual table module that merely "echos" the contents of another
** table (like an SQL VIEW).
*/
static sqlite3_module echoModule = {
- 0, /* iVersion */
+ 1, /* iVersion */
+ echoCreate,
+ echoConnect,
+ echoBestIndex,
+ echoDisconnect,
+ echoDestroy,
+ echoOpen, /* xOpen - open a cursor */
+ echoClose, /* xClose - close a cursor */
+ echoFilter, /* xFilter - configure scan constraints */
+ echoNext, /* xNext - advance a cursor */
+ echoEof, /* xEof */
+ echoColumn, /* xColumn - read data */
+ echoRowid, /* xRowid - read data */
+ echoUpdate, /* xUpdate - write data */
+ echoBegin, /* xBegin - begin transaction */
+ echoSync, /* xSync - sync transaction */
+ echoCommit, /* xCommit - commit transaction */
+ echoRollback, /* xRollback - rollback transaction */
+ echoFindFunction, /* xFindFunction - function overloading */
+ echoRename /* xRename - rename the table */
+};
+
+static sqlite3_module echoModuleV2 = {
+ 2, /* iVersion */
echoCreate,
echoConnect,
echoBestIndex,
@@ -1257,6 +1295,9 @@ static sqlite3_module echoModule = {
echoRollback, /* xRollback - rollback transaction */
echoFindFunction, /* xFindFunction - function overloading */
echoRename, /* xRename - rename the table */
+ echoSavepoint,
+ echoRelease,
+ echoRollbackTo
};
/*
@@ -1284,9 +1325,18 @@ static int register_echo_module(
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+
+ /* Virtual table module "echo" */
pMod = sqlite3_malloc(sizeof(EchoModule));
pMod->interp = interp;
sqlite3_create_module_v2(db, "echo", &echoModule, (void*)pMod, moduleDestroy);
+
+ /* Virtual table module "echo_v2" */
+ pMod = sqlite3_malloc(sizeof(EchoModule));
+ pMod->interp = interp;
+ sqlite3_create_module_v2(db, "echo_v2",
+ &echoModuleV2, (void*)pMod, moduleDestroy
+ );
return TCL_OK;
}
diff --git a/src/test_config.c b/src/test_config.c
index a2796c77..ce72f873 100644
--- a/src/test_config.c
+++ b/src/test_config.c
@@ -55,6 +55,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY);
#endif
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ Tcl_SetVar2(interp, "sqlite_options", "direct_read", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "direct_read", "0", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_DISABLE_DIRSYNC
Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
#else
@@ -363,6 +369,12 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "0", TCL_GLOBAL_ONLY);
#endif
+#ifdef SQLITE_OMIT_MERGE_SORT
+ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
#else
@@ -412,10 +424,10 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
#endif
-#ifdef SQLITE_ENABLE_STAT2
- Tcl_SetVar2(interp, "sqlite_options", "stat2", "1", TCL_GLOBAL_ONLY);
+#ifdef SQLITE_ENABLE_STAT3
+ Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY);
#else
- Tcl_SetVar2(interp, "sqlite_options", "stat2", "0", TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY);
#endif
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
@@ -571,6 +583,7 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
LINKVAR( DEFAULT_PAGE_SIZE );
LINKVAR( DEFAULT_FILE_FORMAT );
LINKVAR( MAX_ATTACHED );
+ LINKVAR( MAX_DEFAULT_PAGE_SIZE );
{
static const int cv_TEMP_STORE = SQLITE_TEMP_STORE;
diff --git a/src/test_malloc.c b/src/test_malloc.c
index 5023dca4..e955d579 100644
--- a/src/test_malloc.c
+++ b/src/test_malloc.c
@@ -1222,7 +1222,7 @@ static int test_dump_memsys3(
return TCL_ERROR;
}
- switch( (int)clientData ){
+ switch( SQLITE_PTR_TO_INT(clientData) ){
case 3: {
#ifdef SQLITE_ENABLE_MEMSYS3
extern void sqlite3Memsys3Dump(const char*);
@@ -1325,11 +1325,13 @@ static int test_db_status(
{ "STMT_USED", SQLITE_DBSTATUS_STMT_USED },
{ "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT },
{ "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE },
- { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }
+ { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL },
+ { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT },
+ { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS }
};
Tcl_Obj *pResult;
if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
+ Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
@@ -1460,7 +1462,7 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
};
int i;
for(i=0; i
#include
+#include
#include "test_multiplex.h"
#ifndef SQLITE_CORE
@@ -78,20 +84,26 @@
/************************ Shim Definitions ******************************/
-#define SQLITE_MULTIPLEX_VFS_NAME "multiplex"
+#ifndef SQLITE_MULTIPLEX_VFS_NAME
+# define SQLITE_MULTIPLEX_VFS_NAME "multiplex"
+#endif
/* This is the limit on the chunk size. It may be changed by calling
** the xFileControl() interface. It will be rounded up to a
-** multiple of MAX_PAGE_SIZE. We default it here to 1GB.
+** multiple of MAX_PAGE_SIZE. We default it here to 2GiB less 64KiB.
*/
-#define SQLITE_MULTIPLEX_CHUNK_SIZE (MAX_PAGE_SIZE*16384)
+#ifndef SQLITE_MULTIPLEX_CHUNK_SIZE
+# define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112
+#endif
/* Default limit on number of chunks. Care should be taken
** so that values for chunks numbers fit in the SQLITE_MULTIPLEX_EXT_FMT
** format specifier. It may be changed by calling
** the xFileControl() interface.
*/
-#define SQLITE_MULTIPLEX_MAX_CHUNKS 32
+#ifndef SQLITE_MULTIPLEX_MAX_CHUNKS
+# define SQLITE_MULTIPLEX_MAX_CHUNKS 32
+#endif
/* If SQLITE_MULTIPLEX_EXT_OVWR is defined, the
** last SQLITE_MULTIPLEX_EXT_SZ characters of the
@@ -119,13 +131,15 @@ typedef struct multiplexConn multiplexConn;
** group.
*/
struct multiplexGroup {
- sqlite3_file **pReal; /* Handles to each chunk */
- char *bOpen; /* array of bools - 0 if chunk not opened */
+ struct multiplexReal { /* For each chunk */
+ sqlite3_file *p; /* Handle for the chunk */
+ char *z; /* Name of this chunk */
+ } *aReal; /* list of all chunks */
+ int nReal; /* Number of chunks */
char *zName; /* Base filename of this group */
int nName; /* Length of base filename */
int flags; /* Flags used for original opening */
- int nChunkSize; /* Chunk size used for this group */
- int nMaxChunks; /* Max number of chunks for this group */
+ unsigned int szChunk; /* Chunk size used for this group */
int bEnabled; /* TRUE to use Multiplex VFS for this file */
multiplexGroup *pNext, *pPrev; /* Doubly linked list of all group objects */
};
@@ -184,12 +198,6 @@ static struct {
/* List of multiplexGroup objects.
*/
multiplexGroup *pGroups;
-
- /* Storage for temp file names. Allocated during
- ** initialization to the max pathname of the underlying VFS.
- */
- char *zName;
-
} gMultiplex;
/************************* Utility Routines *********************************/
@@ -265,7 +273,8 @@ static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){
attempts++;
sqlite3_randomness(8, &zBuf[j]);
for(i=0; i<8; i++){
- zBuf[j+i] = (char)zChars[ ((unsigned char)zBuf[j+i])%(sizeof(zChars)-1) ];
+ unsigned char uc = (unsigned char)zBuf[j+i];
+ zBuf[j+i] = (char)zChars[uc%(sizeof(zChars)-1)];
}
memcpy(&zBuf[j+i], ".tmp", 5);
rc = pOrigVfs->xAccess(pOrigVfs, zBuf, SQLITE_ACCESS_EXISTS, &exists);
@@ -279,35 +288,69 @@ static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){
return rc;
}
+/* Compute the filename for the iChunk-th chunk
+*/
+static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
+ if( iChunk>=pGroup->nReal ){
+ struct multiplexReal *p;
+ p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p));
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
+ pGroup->aReal = p;
+ pGroup->nReal = iChunk+1;
+ }
+ if( pGroup->aReal[iChunk].z==0 ){
+ char *z;
+ int n = pGroup->nName;
+ pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+3 );
+ if( z==0 ){
+ return SQLITE_NOMEM;
+ }
+ memcpy(z, pGroup->zName, n+1);
+ if( iChunk>0 ){
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ if( n>3 && z[n-3]=='.' ){
+ n--;
+ }else if( n>4 && z[n-4]=='.' ){
+ n -= 2;
+ }
+#endif
+ sqlite3_snprintf(3,&z[n],"%02d",iChunk);
+ }
+ }
+ return SQLITE_OK;
+}
+
/* Translate an sqlite3_file* that is really a multiplexGroup* into
** the sqlite3_file* for the underlying original VFS.
*/
-static sqlite3_file *multiplexSubOpen(multiplexConn *pConn, int iChunk, int *rc, int *pOutFlags){
- multiplexGroup *pGroup = pConn->pGroup;
+static sqlite3_file *multiplexSubOpen(
+ multiplexGroup *pGroup,
+ int iChunk,
+ int *rc,
+ int *pOutFlags
+){
+ sqlite3_file *pSubOpen = 0;
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
- if( iChunknMaxChunks ){
- sqlite3_file *pSubOpen = pGroup->pReal[iChunk]; /* Real file descriptor */
- if( !pGroup->bOpen[iChunk] ){
- memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1);
- if( iChunk ){
-#ifdef SQLITE_MULTIPLEX_EXT_OVWR
- sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, SQLITE_MULTIPLEX_EXT_FMT, iChunk);
-#else
- sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, iChunk);
-#endif
- }
- *rc = pOrigVfs->xOpen(pOrigVfs, gMultiplex.zName, pSubOpen, pGroup->flags, pOutFlags);
- if( *rc==SQLITE_OK ){
- pGroup->bOpen[iChunk] = -1;
- return pSubOpen;
- }
- return NULL;
+ *rc = multiplexSubFilename(pGroup, iChunk);
+ if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
+ pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
+ if( pSubOpen==0 ){
+ *rc = SQLITE_NOMEM;
+ return 0;
+ }
+ pGroup->aReal[iChunk].p = pSubOpen;
+ *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen,
+ pGroup->flags, pOutFlags);
+ if( *rc!=SQLITE_OK ){
+ sqlite3_free(pSubOpen);
+ pGroup->aReal[iChunk].p = 0;
+ return 0;
}
- *rc = SQLITE_OK;
- return pSubOpen;
}
- *rc = SQLITE_FULL;
- return NULL;
+ return pSubOpen;
}
/*
@@ -366,6 +409,36 @@ static int multiplexFuncInit(
return rc;
}
+/*
+** Close a single sub-file in the connection group.
+*/
+static void multiplexSubClose(
+ multiplexGroup *pGroup,
+ int iChunk,
+ sqlite3_vfs *pOrigVfs
+){
+ sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p;
+ if( pSubOpen ){
+ pSubOpen->pMethods->xClose(pSubOpen);
+ if( pOrigVfs ) pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
+ sqlite3_free(pGroup->aReal[iChunk].p);
+ }
+ sqlite3_free(pGroup->aReal[iChunk].z);
+ memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk]));
+}
+
+/*
+** Deallocate memory held by a multiplexGroup
+*/
+static void multiplexFreeComponents(multiplexGroup *pGroup){
+ int i;
+ for(i=0; inReal; i++){ multiplexSubClose(pGroup, i, 0); }
+ sqlite3_free(pGroup->aReal);
+ pGroup->aReal = 0;
+ pGroup->nReal = 0;
+}
+
+
/************************* VFS Method Wrappers *****************************/
/*
@@ -382,16 +455,17 @@ static int multiplexOpen(
int flags, /* Flags to control the opening */
int *pOutFlags /* Flags showing results of opening */
){
- int rc = SQLITE_OK; /* Result code */
- multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */
- multiplexGroup *pGroup; /* Corresponding multiplexGroup object */
- sqlite3_file *pSubOpen; /* Real file descriptor */
+ int rc = SQLITE_OK; /* Result code */
+ multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */
+ multiplexGroup *pGroup; /* Corresponding multiplexGroup object */
+ sqlite3_file *pSubOpen = 0; /* Real file descriptor */
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
int nName;
- int i;
int sz;
+ char *zToFree = 0;
UNUSED_PARAMETER(pVfs);
+ memset(pConn, 0, pVfs->szOsFile);
/* We need to create a group structure and manage
** access to this group of files.
@@ -405,28 +479,22 @@ static int multiplexOpen(
** it.
*/
if( !zName ){
- rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, gMultiplex.zName);
- zName = gMultiplex.zName;
+ zName = zToFree = sqlite3_malloc( pOrigVfs->mxPathname + 10 );
+ if( zName==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, zToFree);
+ }
}
if( rc==SQLITE_OK ){
/* allocate space for group */
nName = multiplexStrlen30(zName);
- sz = sizeof(multiplexGroup) /* multiplexGroup */
- + (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS) /* pReal[] */
- + (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS) /* *pReal */
- + SQLITE_MULTIPLEX_MAX_CHUNKS /* bOpen[] */
- + nName + 1; /* zName */
-#ifndef SQLITE_MULTIPLEX_EXT_OVWR
- sz += SQLITE_MULTIPLEX_EXT_SZ;
- assert(nName+SQLITE_MULTIPLEX_EXT_SZ < pOrigVfs->mxPathname);
-#else
- assert(nName >= SQLITE_MULTIPLEX_EXT_SZ);
- assert(nName < pOrigVfs->mxPathname);
-#endif
+ sz = sizeof(multiplexGroup) /* multiplexGroup */
+ + nName + 1; /* zName */
pGroup = sqlite3_malloc( sz );
if( pGroup==0 ){
- rc=SQLITE_NOMEM;
+ rc = SQLITE_NOMEM;
}
}
@@ -436,32 +504,58 @@ static int multiplexOpen(
pMultiplexOpen->pGroup = pGroup;
memset(pGroup, 0, sz);
pGroup->bEnabled = -1;
- pGroup->nChunkSize = SQLITE_MULTIPLEX_CHUNK_SIZE;
- pGroup->nMaxChunks = SQLITE_MULTIPLEX_MAX_CHUNKS;
- pGroup->pReal = (sqlite3_file **)p;
- p += (sizeof(sqlite3_file *)*pGroup->nMaxChunks);
- for(i=0; inMaxChunks; i++){
- pGroup->pReal[i] = (sqlite3_file *)p;
- p += pOrigVfs->szOsFile;
+ pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE;
+ if( flags & SQLITE_OPEN_URI ){
+ const char *zChunkSize;
+ zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
+ if( zChunkSize ){
+ unsigned int n = 0;
+ int i;
+ for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){
+ n = n*10 + zChunkSize[i] - '0';
+ }
+ if( n>0 ){
+ pGroup->szChunk = (n+0xffff)&~0xffff;
+ }else{
+ /* A zero or negative chunksize disabled the multiplexor */
+ pGroup->bEnabled = 0;
+ }
+ }
}
- /* bOpen[] vals should all be zero from memset above */
- pGroup->bOpen = p;
- p += pGroup->nMaxChunks;
pGroup->zName = p;
/* save off base filename, name length, and original open flags */
memcpy(pGroup->zName, zName, nName+1);
pGroup->nName = nName;
pGroup->flags = flags;
- pSubOpen = multiplexSubOpen(pMultiplexOpen, 0, &rc, pOutFlags);
+ rc = multiplexSubFilename(pGroup, 1);
+ if( rc==SQLITE_OK ){
+ pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags);
+ }
if( pSubOpen ){
- /* if this file is already larger than chunk size, disable
- ** the multiplex feature.
- */
+ int exists, rc2, rc3;
sqlite3_int64 sz;
- int rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
- if( (rc2==SQLITE_OK) && (sz>pGroup->nChunkSize) ){
- pGroup->bEnabled = 0;
+
+ rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
+ if( rc2==SQLITE_OK ){
+ /* If the first overflow file exists and if the size of the main file
+ ** is different from the chunk size, that means the chunk size is set
+ ** set incorrectly. So fix it.
+ **
+ ** Or, if the first overflow file does not exist and the main file is
+ ** larger than the chunk size, that means the chunk size is too small.
+ ** But we have no way of determining the intended chunk size, so
+ ** just disable the multiplexor all togethre.
+ */
+ rc3 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
+ SQLITE_ACCESS_EXISTS, &exists);
+ if( rc3==SQLITE_OK && exists && sz==(sz&0xffff0000) && sz>0
+ && sz!=pGroup->szChunk ){
+ pGroup->szChunk = sz;
+ }else if( rc3==SQLITE_OK && !exists && sz>pGroup->szChunk ){
+ pGroup->bEnabled = 0;
+ }
}
+
if( pSubOpen->pMethods->iVersion==1 ){
pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
}else{
@@ -472,17 +566,18 @@ static int multiplexOpen(
if( gMultiplex.pGroups ) gMultiplex.pGroups->pPrev = pGroup;
gMultiplex.pGroups = pGroup;
}else{
+ multiplexFreeComponents(pGroup);
sqlite3_free(pGroup);
}
}
multiplexLeave();
+ sqlite3_free(zToFree);
return rc;
}
/*
** This is the xDelete method used for the "multiplex" VFS.
-** It attempts to delete the filename specified, as well
-** as additional files with the SQLITE_MULTIPLEX_EXT_FMT extension.
+** It attempts to delete the filename specified.
*/
static int multiplexDelete(
sqlite3_vfs *pVfs, /* The multiplex VFS */
@@ -490,41 +585,7 @@ static int multiplexDelete(
int syncDir
){
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
- int rc = SQLITE_OK;
- int nName = multiplexStrlen30(zName);
- int i;
-
- UNUSED_PARAMETER(pVfs);
-
- multiplexEnter();
- memcpy(gMultiplex.zName, zName, nName+1);
- for(i=0; ixAccess(pOrigVfs, gMultiplex.zName,
- SQLITE_ACCESS_EXISTS, &exists);
- if( rc2==SQLITE_OK && exists ){
- /* if it exists, delete it */
- rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, syncDir);
- if( rc2!=SQLITE_OK ) rc = rc2;
- }else{
- /* stop at first "gap" */
- break;
- }
- }
- multiplexLeave();
- return rc;
+ return pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
}
static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
@@ -572,17 +633,8 @@ static int multiplexClose(sqlite3_file *pConn){
multiplexConn *p = (multiplexConn*)pConn;
multiplexGroup *pGroup = p->pGroup;
int rc = SQLITE_OK;
- int i;
multiplexEnter();
- /* close any open handles */
- for(i=0; inMaxChunks; i++){
- if( pGroup->bOpen[i] ){
- sqlite3_file *pSubOpen = pGroup->pReal[i];
- int rc2 = pSubOpen->pMethods->xClose(pSubOpen);
- if( rc2!=SQLITE_OK ) rc = rc2;
- pGroup->bOpen[i] = 0;
- }
- }
+ multiplexFreeComponents(pGroup);
/* remove from linked list */
if( pGroup->pNext ) pGroup->pNext->pPrev = pGroup->pPrev;
if( pGroup->pPrev ){
@@ -610,17 +662,22 @@ static int multiplexRead(
int rc = SQLITE_OK;
multiplexEnter();
if( !pGroup->bEnabled ){
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
- rc = ( !pSubOpen ) ? SQLITE_IOERR_READ : pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst);
+ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
+ if( pSubOpen==0 ){
+ rc = SQLITE_IOERR_READ;
+ }else{
+ rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst);
+ }
}else{
while( iAmt > 0 ){
- int i = (int)(iOfst / pGroup->nChunkSize);
- sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL);
+ int i = (int)(iOfst / pGroup->szChunk);
+ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
if( pSubOpen ){
- int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) - pGroup->nChunkSize;
+ int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk;
if( extra<0 ) extra = 0;
iAmt -= extra;
- rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst % pGroup->nChunkSize);
+ rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt,
+ iOfst % pGroup->szChunk);
if( rc!=SQLITE_OK ) break;
pBuf = (char *)pBuf + iAmt;
iOfst += iAmt;
@@ -650,17 +707,23 @@ static int multiplexWrite(
int rc = SQLITE_OK;
multiplexEnter();
if( !pGroup->bEnabled ){
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
- rc = ( !pSubOpen ) ? SQLITE_IOERR_WRITE : pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst);
+ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
+ if( pSubOpen==0 ){
+ rc = SQLITE_IOERR_WRITE;
+ }else{
+ rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst);
+ }
}else{
while( iAmt > 0 ){
- int i = (int)(iOfst / pGroup->nChunkSize);
- sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL);
+ int i = (int)(iOfst / pGroup->szChunk);
+ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
if( pSubOpen ){
- int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) - pGroup->nChunkSize;
+ int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) -
+ pGroup->szChunk;
if( extra<0 ) extra = 0;
iAmt -= extra;
- rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst % pGroup->nChunkSize);
+ rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt,
+ iOfst % pGroup->szChunk);
if( rc!=SQLITE_OK ) break;
pBuf = (char *)pBuf + iAmt;
iOfst += iAmt;
@@ -685,38 +748,24 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
int rc = SQLITE_OK;
multiplexEnter();
if( !pGroup->bEnabled ){
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
- rc = ( !pSubOpen ) ? SQLITE_IOERR_TRUNCATE : pSubOpen->pMethods->xTruncate(pSubOpen, size);
+ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
+ if( pSubOpen==0 ){
+ rc = SQLITE_IOERR_TRUNCATE;
+ }else{
+ rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
+ }
}else{
int rc2;
int i;
sqlite3_file *pSubOpen;
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
- memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1);
/* delete the chunks above the truncate limit */
- for(i=(int)(size / pGroup->nChunkSize)+1; inMaxChunks; i++){
- /* close any open chunks before deleting them */
- if( pGroup->bOpen[i] ){
- pSubOpen = pGroup->pReal[i];
- rc2 = pSubOpen->pMethods->xClose(pSubOpen);
- if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE;
- pGroup->bOpen[i] = 0;
- }
-#ifdef SQLITE_MULTIPLEX_EXT_OVWR
- sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1,
- gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ,
- SQLITE_MULTIPLEX_EXT_FMT, i);
-#else
- sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1,
- gMultiplex.zName+pGroup->nName,
- SQLITE_MULTIPLEX_EXT_FMT, i);
-#endif
- rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, 0);
- if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE;
+ for(i=(int)(size / pGroup->szChunk)+1; inReal; i++){
+ multiplexSubClose(pGroup, i, pOrigVfs);
}
- pSubOpen = multiplexSubOpen(p, (int)(size / pGroup->nChunkSize), &rc2, NULL);
+ pSubOpen = multiplexSubOpen(pGroup, (int)(size/pGroup->szChunk), &rc2,0);
if( pSubOpen ){
- rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->nChunkSize);
+ rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
if( rc2!=SQLITE_OK ) rc = rc2;
}else{
rc = SQLITE_IOERR_TRUNCATE;
@@ -734,10 +783,9 @@ static int multiplexSync(sqlite3_file *pConn, int flags){
int rc = SQLITE_OK;
int i;
multiplexEnter();
- for(i=0; inMaxChunks; i++){
- /* if we don't have it open, we don't need to sync it */
- if( pGroup->bOpen[i] ){
- sqlite3_file *pSubOpen = pGroup->pReal[i];
+ for(i=0; inReal; i++){
+ sqlite3_file *pSubOpen = pGroup->aReal[i].p;
+ if( pSubOpen ){
int rc2 = pSubOpen->pMethods->xSync(pSubOpen, flags);
if( rc2!=SQLITE_OK ) rc = rc2;
}
@@ -757,39 +805,28 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
int i;
multiplexEnter();
if( !pGroup->bEnabled ){
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
- rc = ( !pSubOpen ) ? SQLITE_IOERR_FSTAT : pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
+ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
+ if( pSubOpen==0 ){
+ rc = SQLITE_IOERR_FSTAT;
+ }else{
+ rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
+ }
}else{
+ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;
*pSize = 0;
- for(i=0; inMaxChunks; i++){
- sqlite3_file *pSubOpen = NULL;
- /* if not opened already, check to see if the chunk exists */
- if( pGroup->bOpen[i] ){
- pSubOpen = pGroup->pReal[i];
+ for(i=0; 1; i++){
+ sqlite3_file *pSubOpen = 0;
+ int exists = 0;
+ rc = multiplexSubFilename(pGroup, i);
+ if( rc ) break;
+ rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z,
+ SQLITE_ACCESS_EXISTS, &exists);
+ if( rc2==SQLITE_OK && exists){
+ /* if it exists, open it */
+ pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
}else{
- sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
- int exists = 0;
- memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1);
- if( i ){
-#ifdef SQLITE_MULTIPLEX_EXT_OVWR
- sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1,
- gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ,
- SQLITE_MULTIPLEX_EXT_FMT, i);
-#else
- sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1,
- gMultiplex.zName+pGroup->nName,
- SQLITE_MULTIPLEX_EXT_FMT, i);
-#endif
- }
- rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName,
- SQLITE_ACCESS_EXISTS, &exists);
- if( rc2==SQLITE_OK && exists){
- /* if it exists, open it */
- pSubOpen = multiplexSubOpen(p, i, &rc, NULL);
- }else{
- /* stop at first "gap" */
- break;
- }
+ /* stop at first "gap" */
+ break;
}
if( pSubOpen ){
sqlite3_int64 sz;
@@ -797,7 +834,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
if( rc2!=SQLITE_OK ){
rc = rc2;
}else{
- if( sz>pGroup->nChunkSize ){
+ if( sz>pGroup->szChunk ){
rc = SQLITE_IOERR_FSTAT;
}
*pSize += sz;
@@ -816,7 +853,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
static int multiplexLock(sqlite3_file *pConn, int lock){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
return pSubOpen->pMethods->xLock(pSubOpen, lock);
}
@@ -828,7 +865,7 @@ static int multiplexLock(sqlite3_file *pConn, int lock){
static int multiplexUnlock(sqlite3_file *pConn, int lock){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
}
@@ -840,7 +877,7 @@ static int multiplexUnlock(sqlite3_file *pConn, int lock){
static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
}
@@ -867,28 +904,20 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
break;
case MULTIPLEX_CTRL_SET_CHUNK_SIZE:
if( pArg ) {
- int nChunkSize = *(int *)pArg;
- if( nChunkSize<1 ){
+ unsigned int szChunk = *(unsigned*)pArg;
+ if( szChunk<1 ){
rc = SQLITE_MISUSE;
}else{
/* Round up to nearest multiple of MAX_PAGE_SIZE. */
- nChunkSize = (nChunkSize + (MAX_PAGE_SIZE-1));
- nChunkSize &= ~(MAX_PAGE_SIZE-1);
- pGroup->nChunkSize = nChunkSize;
+ szChunk = (szChunk + (MAX_PAGE_SIZE-1));
+ szChunk &= ~(MAX_PAGE_SIZE-1);
+ pGroup->szChunk = szChunk;
rc = SQLITE_OK;
}
}
break;
case MULTIPLEX_CTRL_SET_MAX_CHUNKS:
- if( pArg ) {
- int nMaxChunks = *(int *)pArg;
- if(( nMaxChunks<1 ) || ( nMaxChunks>SQLITE_MULTIPLEX_MAX_CHUNKS )){
- rc = SQLITE_MISUSE;
- }else{
- pGroup->nMaxChunks = nMaxChunks;
- rc = SQLITE_OK;
- }
- }
+ rc = SQLITE_OK;
break;
case SQLITE_FCNTL_SIZE_HINT:
case SQLITE_FCNTL_CHUNK_SIZE:
@@ -896,7 +925,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
rc = SQLITE_OK;
break;
default:
- pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
if( pSubOpen ){
rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
}
@@ -910,7 +939,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
static int multiplexSectorSize(sqlite3_file *pConn){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
return pSubOpen->pMethods->xSectorSize(pSubOpen);
}
@@ -922,7 +951,7 @@ static int multiplexSectorSize(sqlite3_file *pConn){
static int multiplexDeviceCharacteristics(sqlite3_file *pConn){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
}
@@ -940,9 +969,9 @@ static int multiplexShmMap(
){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
- return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend, pp);
+ return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp);
}
return SQLITE_IOERR;
}
@@ -957,7 +986,7 @@ static int multiplexShmLock(
){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
}
@@ -969,7 +998,7 @@ static int multiplexShmLock(
static void multiplexShmBarrier(sqlite3_file *pConn){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
pSubOpen->pMethods->xShmBarrier(pSubOpen);
}
@@ -980,7 +1009,7 @@ static void multiplexShmBarrier(sqlite3_file *pConn){
static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){
multiplexConn *p = (multiplexConn*)pConn;
int rc;
- sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+ sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
if( pSubOpen ){
return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
}
@@ -1010,11 +1039,6 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){
if( !gMultiplex.pMutex ){
return SQLITE_NOMEM;
}
- gMultiplex.zName = sqlite3_malloc(pOrigVfs->mxPathname);
- if( !gMultiplex.zName ){
- sqlite3_mutex_free(gMultiplex.pMutex);
- return SQLITE_NOMEM;
- }
gMultiplex.pGroups = NULL;
gMultiplex.isInitialized = 1;
gMultiplex.pOrigVfs = pOrigVfs;
@@ -1047,7 +1071,8 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){
gMultiplex.sIoMethodsV1.xCheckReservedLock = multiplexCheckReservedLock;
gMultiplex.sIoMethodsV1.xFileControl = multiplexFileControl;
gMultiplex.sIoMethodsV1.xSectorSize = multiplexSectorSize;
- gMultiplex.sIoMethodsV1.xDeviceCharacteristics = multiplexDeviceCharacteristics;
+ gMultiplex.sIoMethodsV1.xDeviceCharacteristics =
+ multiplexDeviceCharacteristics;
gMultiplex.sIoMethodsV2 = gMultiplex.sIoMethodsV1;
gMultiplex.sIoMethodsV2.iVersion = 2;
gMultiplex.sIoMethodsV2.xShmMap = multiplexShmMap;
@@ -1074,7 +1099,6 @@ int sqlite3_multiplex_shutdown(void){
if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE;
if( gMultiplex.pGroups ) return SQLITE_MISUSE;
gMultiplex.isInitialized = 0;
- sqlite3_free(gMultiplex.zName);
sqlite3_mutex_free(gMultiplex.pMutex);
sqlite3_vfs_unregister(&gMultiplex.sThisVfs);
memset(&gMultiplex, 0, sizeof(gMultiplex));
@@ -1176,16 +1200,16 @@ static int test_multiplex_dump(
Tcl_NewIntObj(pGroup->flags));
/* count number of chunks with open handles */
- for(i=0; inMaxChunks; i++){
- if( pGroup->bOpen[i] ) nChunks++;
+ for(i=0; inReal; i++){
+ if( pGroup->aReal[i].p!=0 ) nChunks++;
}
Tcl_ListObjAppendElement(interp, pGroupTerm,
Tcl_NewIntObj(nChunks));
Tcl_ListObjAppendElement(interp, pGroupTerm,
- Tcl_NewIntObj(pGroup->nChunkSize));
+ Tcl_NewIntObj(pGroup->szChunk));
Tcl_ListObjAppendElement(interp, pGroupTerm,
- Tcl_NewIntObj(pGroup->nMaxChunks));
+ Tcl_NewIntObj(pGroup->nReal));
Tcl_ListObjAppendElement(interp, pResult, pGroupTerm);
}
diff --git a/src/test_quota.c b/src/test_quota.c
index 9b0e4a9d..74d1a6d3 100644
--- a/src/test_quota.c
+++ b/src/test_quota.c
@@ -95,6 +95,7 @@ struct quotaFile {
quotaGroup *pGroup; /* Quota group to which this file belongs */
sqlite3_int64 iSize; /* Current size of this file */
int nRef; /* Number of times this file is open */
+ int deleteOnClose; /* True to delete this file when it closes */
quotaFile *pNext, **ppPrev; /* Linked list of files in the same group */
};
@@ -164,12 +165,45 @@ static struct {
static void quotaEnter(void){ sqlite3_mutex_enter(gQuota.pMutex); }
static void quotaLeave(void){ sqlite3_mutex_leave(gQuota.pMutex); }
+/* Count the number of open files in a quotaGroup
+*/
+static int quotaGroupOpenFileCount(quotaGroup *pGroup){
+ int N = 0;
+ quotaFile *pFile = pGroup->pFiles;
+ while( pFile ){
+ if( pFile->nRef ) N++;
+ pFile = pFile->pNext;
+ }
+ return N;
+}
+
+/* Remove a file from a quota group.
+*/
+static void quotaRemoveFile(quotaFile *pFile){
+ quotaGroup *pGroup = pFile->pGroup;
+ pGroup->iSize -= pFile->iSize;
+ *pFile->ppPrev = pFile->pNext;
+ if( pFile->pNext ) pFile->pNext->ppPrev = pFile->ppPrev;
+ sqlite3_free(pFile);
+}
+
+/* Remove all files from a quota group. It is always the case that
+** all files will be closed when this routine is called.
+*/
+static void quotaRemoveAllFiles(quotaGroup *pGroup){
+ while( pGroup->pFiles ){
+ assert( pGroup->pFiles->nRef==0 );
+ quotaRemoveFile(pGroup->pFiles);
+ }
+}
+
/* If the reference count and threshold for a quotaGroup are both
** zero, then destroy the quotaGroup.
*/
static void quotaGroupDeref(quotaGroup *pGroup){
- if( pGroup->pFiles==0 && pGroup->iLimit==0 ){
+ if( pGroup->iLimit==0 && quotaGroupOpenFileCount(pGroup)==0 ){
+ quotaRemoveAllFiles(pGroup);
*pGroup->ppPrev = pGroup->pNext;
if( pGroup->pNext ) pGroup->pNext->ppPrev = pGroup->ppPrev;
if( pGroup->xDestroy ) pGroup->xDestroy(pGroup->pArg);
@@ -276,6 +310,17 @@ static sqlite3_file *quotaSubOpen(sqlite3_file *pConn){
return (sqlite3_file*)&p[1];
}
+/* Find a file in a quota group and return a pointer to that file.
+** Return NULL if the file is not in the group.
+*/
+static quotaFile *quotaFindFile(quotaGroup *pGroup, const char *zName){
+ quotaFile *pFile = pGroup->pFiles;
+ while( pFile && strcmp(pFile->zFilename, zName)!=0 ){
+ pFile = pFile->pNext;
+ }
+ return pFile;
+}
+
/************************* VFS Method Wrappers *****************************/
/*
** This is the xOpen method used for the "quota" VFS.
@@ -319,8 +364,7 @@ static int quotaOpen(
pSubOpen = quotaSubOpen(pConn);
rc = pOrigVfs->xOpen(pOrigVfs, zName, pSubOpen, flags, pOutFlags);
if( rc==SQLITE_OK ){
- for(pFile=pGroup->pFiles; pFile && strcmp(pFile->zFilename, zName);
- pFile=pFile->pNext){}
+ pFile = quotaFindFile(pGroup, zName);
if( pFile==0 ){
int nName = strlen(zName);
pFile = (quotaFile *)sqlite3_malloc( sizeof(*pFile) + nName + 1 );
@@ -337,6 +381,7 @@ static int quotaOpen(
pFile->ppPrev = &pGroup->pFiles;
pGroup->pFiles = pFile;
pFile->pGroup = pGroup;
+ pFile->deleteOnClose = (flags & SQLITE_OPEN_DELETEONCLOSE)!=0;
}
pFile->nRef++;
pQuotaOpen->pFile = pFile;
@@ -351,6 +396,49 @@ static int quotaOpen(
return rc;
}
+/*
+** This is the xDelete method used for the "quota" VFS.
+**
+** If the file being deleted is part of the quota group, then reduce
+** the size of the quota group accordingly. And remove the file from
+** the set of files in the quota group.
+*/
+static int quotaDelete(
+ sqlite3_vfs *pVfs, /* The quota VFS */
+ const char *zName, /* Name of file to be deleted */
+ int syncDir /* Do a directory sync after deleting */
+){
+ int rc; /* Result code */
+ quotaFile *pFile; /* Files in the quota */
+ quotaGroup *pGroup; /* The group file belongs to */
+ sqlite3_vfs *pOrigVfs = gQuota.pOrigVfs; /* Real VFS */
+
+ /* Do the actual file delete */
+ rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
+
+ /* If the file just deleted is a member of a quota group, then remove
+ ** it from that quota group.
+ */
+ if( rc==SQLITE_OK ){
+ quotaEnter();
+ pGroup = quotaGroupFind(zName);
+ if( pGroup ){
+ pFile = quotaFindFile(pGroup, zName);
+ if( pFile ){
+ if( pFile->nRef ){
+ pFile->deleteOnClose = 1;
+ }else{
+ quotaRemoveFile(pFile);
+ quotaGroupDeref(pGroup);
+ }
+ }
+ }
+ quotaLeave();
+ }
+ return rc;
+}
+
+
/************************ I/O Method Wrappers *******************************/
/* xClose requests get passed through to the original VFS. But we
@@ -367,11 +455,8 @@ static int quotaClose(sqlite3_file *pConn){
pFile->nRef--;
if( pFile->nRef==0 ){
quotaGroup *pGroup = pFile->pGroup;
- pGroup->iSize -= pFile->iSize;
- if( pFile->pNext ) pFile->pNext->ppPrev = pFile->ppPrev;
- *pFile->ppPrev = pFile->pNext;
+ if( pFile->deleteOnClose ) quotaRemoveFile(pFile);
quotaGroupDeref(pGroup);
- sqlite3_free(pFile);
}
quotaLeave();
return rc;
@@ -586,6 +671,7 @@ int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault){
gQuota.pOrigVfs = pOrigVfs;
gQuota.sThisVfs = *pOrigVfs;
gQuota.sThisVfs.xOpen = quotaOpen;
+ gQuota.sThisVfs.xDelete = quotaDelete;
gQuota.sThisVfs.szOsFile += sizeof(quotaConn);
gQuota.sThisVfs.zName = "quota";
gQuota.sIoMethodsV1.iVersion = 1;
@@ -617,19 +703,20 @@ int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault){
** All SQLite database connections must be closed before calling this
** routine.
**
-** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly one while
+** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while
** shutting down in order to free all remaining quota groups.
*/
int sqlite3_quota_shutdown(void){
quotaGroup *pGroup;
if( gQuota.isInitialized==0 ) return SQLITE_MISUSE;
for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){
- if( pGroup->pFiles ) return SQLITE_MISUSE;
+ if( quotaGroupOpenFileCount(pGroup)>0 ) return SQLITE_MISUSE;
}
while( gQuota.pGroup ){
pGroup = gQuota.pGroup;
gQuota.pGroup = pGroup->pNext;
pGroup->iLimit = 0;
+ assert( quotaGroupOpenFileCount(pGroup)==0 );
quotaGroupDeref(pGroup);
}
gQuota.isInitialized = 0;
@@ -708,6 +795,43 @@ int sqlite3_quota_set(
return SQLITE_OK;
}
+/*
+** Bring the named file under quota management. Or if it is already under
+** management, update its size.
+*/
+int sqlite3_quota_file(const char *zFilename){
+ char *zFull;
+ sqlite3_file *fd;
+ int rc;
+ int outFlags = 0;
+ sqlite3_int64 iSize;
+ fd = sqlite3_malloc(gQuota.sThisVfs.szOsFile + gQuota.sThisVfs.mxPathname+1);
+ if( fd==0 ) return SQLITE_NOMEM;
+ zFull = gQuota.sThisVfs.szOsFile + (char*)fd;
+ rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename,
+ gQuota.sThisVfs.mxPathname+1, zFull);
+ if( rc==SQLITE_OK ){
+ rc = quotaOpen(&gQuota.sThisVfs, zFull, fd,
+ SQLITE_OPEN_READONLY | SQLITE_OPEN_MAIN_DB, &outFlags);
+ }
+ if( rc==SQLITE_OK ){
+ fd->pMethods->xFileSize(fd, &iSize);
+ fd->pMethods->xClose(fd);
+ }else if( rc==SQLITE_CANTOPEN ){
+ quotaGroup *pGroup;
+ quotaFile *pFile;
+ quotaEnter();
+ pGroup = quotaGroupFind(zFull);
+ if( pGroup ){
+ pFile = quotaFindFile(pGroup, zFull);
+ if( pFile ) quotaRemoveFile(pFile);
+ }
+ quotaLeave();
+ }
+ sqlite3_free(fd);
+ return rc;
+}
+
/***************************** Test Code ***********************************/
#ifdef SQLITE_TEST
@@ -884,6 +1008,32 @@ static int test_quota_set(
return TCL_OK;
}
+/*
+** tclcmd: sqlite3_quota_file FILENAME
+*/
+static int test_quota_file(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ const char *zFilename; /* File pattern to configure */
+ int rc; /* Value returned by quota_file() */
+
+ /* Process arguments */
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
+ return TCL_ERROR;
+ }
+ zFilename = Tcl_GetString(objv[1]);
+
+ /* Invoke sqlite3_quota_file() */
+ rc = sqlite3_quota_file(zFilename);
+
+ Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
+ return TCL_OK;
+}
+
/*
** tclcmd: sqlite3_quota_dump
*/
@@ -917,6 +1067,8 @@ static int test_quota_dump(
Tcl_NewWideIntObj(pFile->iSize));
Tcl_ListObjAppendElement(interp, pFileTerm,
Tcl_NewWideIntObj(pFile->nRef));
+ Tcl_ListObjAppendElement(interp, pFileTerm,
+ Tcl_NewWideIntObj(pFile->deleteOnClose));
Tcl_ListObjAppendElement(interp, pGroupTerm, pFileTerm);
}
Tcl_ListObjAppendElement(interp, pResult, pGroupTerm);
@@ -939,6 +1091,7 @@ int Sqlitequota_Init(Tcl_Interp *interp){
{ "sqlite3_quota_initialize", test_quota_initialize },
{ "sqlite3_quota_shutdown", test_quota_shutdown },
{ "sqlite3_quota_set", test_quota_set },
+ { "sqlite3_quota_file", test_quota_file },
{ "sqlite3_quota_dump", test_quota_dump },
};
int i;
diff --git a/src/test_rtree.c b/src/test_rtree.c
index 5fc994dd..9745b005 100644
--- a/src/test_rtree.c
+++ b/src/test_rtree.c
@@ -18,6 +18,7 @@
/* Solely for the UNUSED_PARAMETER() macro. */
#include "sqliteInt.h"
+#ifdef SQLITE_ENABLE_RTREE
/*
** Type used to cache parameter information for the "circle" r-tree geometry
** callback.
@@ -230,6 +231,7 @@ static int cube_geom(
return SQLITE_OK;
}
+#endif /* SQLITE_ENABLE_RTREE */
static int register_cube_geom(
void * clientData,
diff --git a/src/test_stat.c b/src/test_stat.c
index c85463e5..ef817690 100644
--- a/src/test_stat.c
+++ b/src/test_stat.c
@@ -18,7 +18,9 @@
** for an example implementation.
*/
-#include "sqliteInt.h"
+#ifndef SQLITE_AMALGAMATION
+# include "sqliteInt.h"
+#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -62,20 +64,11 @@
" ncell INTEGER, /* Cells on page (0 for overflow) */" \
" payload INTEGER, /* Bytes of payload on this page */" \
" unused INTEGER, /* Bytes of unused space on this page */" \
- " mx_payload INTEGER /* Largest payload size of all cells */" \
+ " mx_payload INTEGER, /* Largest payload size of all cells */" \
+ " pgoffset INTEGER, /* Offset of page in file */" \
+ " pgsize INTEGER /* Size of the page */" \
");"
-#if 0
-#define VTAB_SCHEMA2 \
- "CREATE TABLE yy( " \
- " pageno INTEGER, /* B-tree page number */" \
- " cellno INTEGER, /* Cell number within page */" \
- " local INTEGER, /* Bytes of content stored locally */" \
- " payload INTEGER, /* Total cell payload size */" \
- " novfl INTEGER /* Number of overflow pages */" \
- ");"
-#endif
-
typedef struct StatTable StatTable;
typedef struct StatCursor StatCursor;
@@ -124,6 +117,8 @@ struct StatCursor {
int nPayload; /* Value of 'payload' column */
int nUnused; /* Value of 'unused' column */
int nMxPayload; /* Value of 'mx_payload' column */
+ i64 iOffset; /* Value of 'pgOffset' column */
+ int szPage; /* Value of 'pgSize' column */
};
struct StatTable {
@@ -281,6 +276,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
int iOff;
int nHdr;
int isLeaf;
+ int szPage;
u8 *aData = sqlite3PagerGetData(p->pPg);
u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];
@@ -301,10 +297,11 @@ static int statDecodePage(Btree *pBt, StatPage *p){
}
p->nUnused = nUnused;
p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]);
+ szPage = sqlite3BtreeGetPageSize(pBt);
if( p->nCell ){
int i; /* Used to iterate through cells */
- int nUsable = sqlite3BtreeGetPageSize(pBt) - sqlite3BtreeGetReserve(pBt);
+ int nUsable = szPage - sqlite3BtreeGetReserve(pBt);
p->aCell = sqlite3_malloc((p->nCell+1) * sizeof(StatCell));
memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell));
@@ -359,6 +356,32 @@ static int statDecodePage(Btree *pBt, StatPage *p){
return SQLITE_OK;
}
+/*
+** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on
+** the current value of pCsr->iPageno.
+*/
+static void statSizeAndOffset(StatCursor *pCsr){
+ StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab;
+ Btree *pBt = pTab->db->aDb[0].pBt;
+ Pager *pPager = sqlite3BtreePager(pBt);
+ sqlite3_file *fd;
+ sqlite3_int64 x[2];
+
+ /* The default page size and offset */
+ pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
+ pCsr->iOffset = pCsr->szPage * (pCsr->iPageno - 1);
+
+ /* If connected to a ZIPVFS backend, override the page size and
+ ** offset with actual values obtained from ZIPVFS.
+ */
+ fd = sqlite3PagerFile(pPager);
+ x[0] = pCsr->iPageno;
+ if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
+ pCsr->iOffset = x[0];
+ pCsr->szPage = x[1];
+ }
+}
+
/*
** Move a statvfs cursor to the next entry in the file.
*/
@@ -417,6 +440,7 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
pCsr->nUnused = nUsable - 4 - pCsr->nPayload;
}
pCell->iOvfl++;
+ statSizeAndOffset(pCsr);
return SQLITE_OK;
}
if( p->iRightChildPg ) break;
@@ -454,6 +478,7 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
pCsr->iPageno = p->iPgno;
statDecodePage(pBt, p);
+ statSizeAndOffset(pCsr);
switch( p->flags ){
case 0x05: /* table internal */
@@ -529,6 +554,12 @@ static int statColumn(
case 7: /* mx_payload */
sqlite3_result_int(ctx, pCsr->nMxPayload);
break;
+ case 8: /* pgoffset */
+ sqlite3_result_int64(ctx, pCsr->iOffset);
+ break;
+ case 9: /* pgsize */
+ sqlite3_result_int(ctx, pCsr->szPage);
+ break;
}
return SQLITE_OK;
}
@@ -568,7 +599,7 @@ int sqlite3_dbstat_register(sqlite3 *db){
#endif
-#ifdef SQLITE_TEST
+#if defined(SQLITE_TEST) || TCLSH==2
#include
static int test_dbstat(
@@ -604,4 +635,4 @@ int SqlitetestStat_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "register_dbstat_vtab", test_dbstat, 0, 0);
return TCL_OK;
}
-#endif
+#endif /* if defined(SQLITE_TEST) || TCLSH==2 */
diff --git a/src/test_syscall.c b/src/test_syscall.c
index b8b05c59..d484f22d 100644
--- a/src/test_syscall.c
+++ b/src/test_syscall.c
@@ -325,6 +325,7 @@ static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off){
*/
static int ts_write(int fd, const void *aBuf, size_t nBuf){
if( tsIsFailErrno("write") ){
+ if( tsErrno("write")==EINTR ) orig_write(fd, aBuf, nBuf/2);
return -1;
}
return orig_write(fd, aBuf, nBuf);
@@ -671,4 +672,3 @@ int SqlitetestSyscall_Init(Tcl_Interp *interp){
return TCL_OK;
}
#endif
-
diff --git a/src/test_thread.c b/src/test_thread.c
index 3a13dd66..aa894670 100644
--- a/src/test_thread.c
+++ b/src/test_thread.c
@@ -282,6 +282,21 @@ static int sqlthread_open(
zFilename = Tcl_GetString(objv[2]);
rc = sqlite3_open(zFilename, &db);
+#ifdef SQLITE_HAS_CODEC
+ if( db && objc>=4 ){
+ const char *zKey;
+ int nKey;
+ zKey = Tcl_GetStringFromObj(objv[3], &nKey);
+ rc = sqlite3_key(db, zKey, nKey);
+ if( rc!=SQLITE_OK ){
+ char *zErrMsg = sqlite3_mprintf("error %d: %s", rc, sqlite3_errmsg(db));
+ sqlite3_close(db);
+ Tcl_AppendResult(interp, zErrMsg, (char*)0);
+ sqlite3_free(zErrMsg);
+ return TCL_ERROR;
+ }
+ }
+#endif
Md5_Register(db);
sqlite3_busy_handler(db, xBusy, 0);
@@ -305,7 +320,7 @@ static int sqlthread_id(
Tcl_Obj *CONST objv[]
){
Tcl_ThreadId id = Tcl_GetCurrentThread();
- Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id));
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(SQLITE_PTR_TO_INT(id)));
UNUSED_PARAMETER(clientData);
UNUSED_PARAMETER(objc);
UNUSED_PARAMETER(objv);
@@ -349,7 +364,7 @@ static int sqlthread_proc(
if( rc!=TCL_OK ) return rc;
pSub = &aSub[iIndex];
- if( objc!=(pSub->nArg+2) ){
+ if( objc<(pSub->nArg+2) ){
Tcl_WrongNumArgs(interp, 2, objv, pSub->zUsage);
return TCL_ERROR;
}
diff --git a/src/test_vfs.c b/src/test_vfs.c
index a8b53526..546cb7cf 100644
--- a/src/test_vfs.c
+++ b/src/test_vfs.c
@@ -123,6 +123,8 @@ struct Testvfs {
#define TESTVFS_TRUNCATE_MASK 0x00002000
#define TESTVFS_ACCESS_MASK 0x00004000
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
+#define TESTVFS_READ_MASK 0x00010000
+
#define TESTVFS_ALL_MASK 0x0001FFFF
@@ -325,8 +327,22 @@ static int tvfsRead(
int iAmt,
sqlite_int64 iOfst
){
- TestvfsFd *p = tvfsGetFd(pFile);
- return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
+ int rc = SQLITE_OK;
+ TestvfsFd *pFd = tvfsGetFd(pFile);
+ Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
+ if( p->pScript && p->mask&TESTVFS_READ_MASK ){
+ tvfsExecTcl(p, "xRead",
+ Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
+ );
+ tvfsResultCode(p, &rc);
+ }
+ if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){
+ rc = SQLITE_IOERR;
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsRead(pFd->pReal, zBuf, iAmt, iOfst);
+ }
+ return rc;
}
/*
@@ -1030,6 +1046,7 @@ static int testvfs_obj_cmd(
{ "xSync", TESTVFS_SYNC_MASK },
{ "xDelete", TESTVFS_DELETE_MASK },
{ "xWrite", TESTVFS_WRITE_MASK },
+ { "xRead", TESTVFS_READ_MASK },
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
{ "xOpen", TESTVFS_OPEN_MASK },
{ "xClose", TESTVFS_CLOSE_MASK },
diff --git a/src/trigger.c b/src/trigger.c
index 6242de5e..22c4877b 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -117,15 +117,28 @@ void sqlite3BeginTrigger(
goto trigger_cleanup;
}
}
+ if( !pTableName || db->mallocFailed ){
+ goto trigger_cleanup;
+ }
+
+ /* A long-standing parser bug is that this syntax was allowed:
+ **
+ ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
+ ** ^^^^^^^^
+ **
+ ** To maintain backwards compatibility, ignore the database
+ ** name on pTableName if we are reparsing our of SQLITE_MASTER.
+ */
+ if( db->init.busy && iDb!=1 ){
+ sqlite3DbFree(db, pTableName->a[0].zDatabase);
+ pTableName->a[0].zDatabase = 0;
+ }
/* If the trigger name was unqualified, and the table is a temp table,
** then set iDb to 1 to create the trigger in the temporary database.
** If sqlite3SrcListLookup() returns 0, indicating the table does not
** exist, the error is caught by the block below.
*/
- if( !pTableName || db->mallocFailed ){
- goto trigger_cleanup;
- }
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( db->init.busy==0 && pName2->n==0 && pTab
&& pTab->pSchema==db->aDb[1].pSchema ){
diff --git a/src/update.c b/src/update.c
index d445f01f..1e305221 100644
--- a/src/update.c
+++ b/src/update.c
@@ -311,7 +311,9 @@ void sqlite3Update(
/* Begin the database scan
*/
sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0, WHERE_ONEPASS_DESIRED);
+ pWInfo = sqlite3WhereBegin(
+ pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
+ );
if( pWInfo==0 ) goto update_cleanup;
okOnePass = pWInfo->okOnePass;
@@ -354,6 +356,7 @@ void sqlite3Update(
}
}
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ assert( aRegIdx );
if( openAll || aRegIdx[i]>0 ){
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
@@ -527,6 +530,7 @@ void sqlite3Update(
/* Close all tables */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ assert( aRegIdx );
if( openAll || aRegIdx[i]>0 ){
sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0);
}
diff --git a/src/utf.c b/src/utf.c
index 17f3a09a..e94815b5 100644
--- a/src/utf.c
+++ b/src/utf.c
@@ -464,7 +464,7 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
** If a malloc failure occurs, NULL is returned and the db.mallocFailed
** flag set.
*/
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
Mem m;
memset(&m, 0, sizeof(m));
diff --git a/src/util.c b/src/util.c
index de735772..3356417e 100644
--- a/src/util.c
+++ b/src/util.c
@@ -331,7 +331,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
}
/* copy digits to exponent */
while( z=342 ){
+ if( esign<0 ){
+ result = 0.0*s;
+ }else{
+ result = 1e308*1e308*s; /* Infinity */
+ }
}else{
/* 1.0e+22 is the largest power of 10 than can be
** represented exactly. */
@@ -1149,12 +1155,15 @@ int sqlite3AbsInt32(int x){
#ifdef SQLITE_ENABLE_8_3_NAMES
/*
-** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
+** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
** three characters, then shorten the suffix on z[] to be the last three
** characters of the original suffix.
**
+** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
+** do the suffix shortening regardless of URI parameter.
+**
** Examples:
**
** test.db-journal => test.nal
@@ -1162,9 +1171,12 @@ int sqlite3AbsInt32(int x){
** test.db-shm => test.shm
*/
void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
+#if SQLITE_ENABLE_8_3_NAMES<2
const char *zOk;
zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
- if( zOk && sqlite3GetBoolean(zOk) ){
+ if( zOk && sqlite3GetBoolean(zOk) )
+#endif
+ {
int i, sz;
sz = sqlite3Strlen30(z);
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
diff --git a/src/vacuum.c b/src/vacuum.c
index 5a4ed320..58a3c9d6 100644
--- a/src/vacuum.c
+++ b/src/vacuum.c
@@ -45,7 +45,7 @@ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
return sqlite3_errcode(db);
}
VVA_ONLY( rc = ) sqlite3_step(pStmt);
- assert( rc!=SQLITE_ROW );
+ assert( rc!=SQLITE_ROW || (db->flags&SQLITE_CountRows) );
return vacuumFinalize(db, pStmt, pzErrMsg);
}
@@ -263,13 +263,11 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
);
if( rc ) goto end_of_vacuum;
- /* At this point, unless the main db was completely empty, there is now a
- ** transaction open on the vacuum database, but not on the main database.
- ** Open a btree level transaction on the main database. This allows a
- ** call to sqlite3BtreeCopyFile(). The main database btree level
- ** transaction is then committed, so the SQL level never knows it was
- ** opened for writing. This way, the SQL transaction used to create the
- ** temporary database never needs to be committed.
+ /* At this point, there is a write transaction open on both the
+ ** vacuum database and the main database. Assuming no error occurs,
+ ** both transactions are closed by this block - the main database
+ ** transaction by sqlite3BtreeCopyFile() and the other by an explicit
+ ** call to sqlite3BtreeCommit().
*/
{
u32 meta;
diff --git a/src/vdbe.c b/src/vdbe.c
index d965b967..22e6d9c5 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -157,6 +157,13 @@ int sqlite3_found_count = 0;
*/
#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
+/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
+#ifdef SQLITE_OMIT_MERGE_SORT
+# define isSorter(x) 0
+#else
+# define isSorter(x) ((x)->pSorter!=0)
+#endif
+
/*
** Argument pMem points at a register that will be passed to a
** user-defined function or returned to the user as the result of a query.
@@ -666,7 +673,7 @@ int sqlite3VdbeExec(
assert( pOp->p2<=p->nMem );
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
- sqlite3VdbeMemReleaseExternal(pOut);
+ MemReleaseExt(pOut);
pOut->flags = MEM_Int;
}
@@ -1027,6 +1034,11 @@ case OP_Move: {
zMalloc = pOut->zMalloc;
pOut->zMalloc = 0;
sqlite3VdbeMemMove(pOut, pIn1);
+#ifdef SQLITE_DEBUG
+ if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
+ pOut->pScopyFrom += p1 - pOp->p2;
+ }
+#endif
pIn1->zMalloc = zMalloc;
REGISTER_TRACE(p2++, pOut);
pIn1++;
@@ -2009,6 +2021,16 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
break;
}
+/* Opcode: Once P1 P2 * * *
+**
+** Jump to P2 if the value in register P1 is a not null or zero. If
+** the value is NULL or zero, fall through and change the P1 register
+** to an integer 1.
+**
+** When P1 is not used otherwise in a program, this opcode falls through
+** once and jumps on all subsequent invocations. It is the equivalent
+** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
+*/
/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true. The value
@@ -2021,6 +2043,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
** is considered true if it has a numeric value of zero. If the value
** in P1 is NULL then take the jump if P3 is true.
*/
+case OP_Once: /* jump, in1 */
case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
int c;
@@ -2037,6 +2060,12 @@ case OP_IfNot: { /* jump, in1 */
}
if( c ){
pc = pOp->p2-1;
+ }else if( pOp->opcode==OP_Once ){
+ assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
+ memAboutToChange(p, pIn1);
+ pIn1->flags = MEM_Int;
+ pIn1->u.i = 1;
+ REGISTER_TRACE(pOp->p1, pIn1);
}
break;
}
@@ -2106,6 +2135,7 @@ case OP_Column: {
u32 szField; /* Number of bytes in the content of a field */
int szHdr; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
+ u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
@@ -2117,7 +2147,6 @@ case OP_Column: {
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
- MemSetTypeFlag(pDest, MEM_Null);
zRec = 0;
/* This block sets the variable payloadSize to be the total number of
@@ -2149,7 +2178,7 @@ case OP_Column: {
zRec = (char*)pC->aRow;
}else if( pC->isIndex ){
assert( sqlite3BtreeCursorIsValid(pCrsr) );
- rc = sqlite3BtreeKeySize(pCrsr, &payloadSize64);
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
/* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
** payload size, so it is impossible for payloadSize64 to be
@@ -2158,10 +2187,10 @@ case OP_Column: {
payloadSize = (u32)payloadSize64;
}else{
assert( sqlite3BtreeCursorIsValid(pCrsr) );
- rc = sqlite3BtreeDataSize(pCrsr, &payloadSize);
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &payloadSize);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
}
- }else if( pC->pseudoTableReg>0 ){
+ }else if( ALWAYS(pC->pseudoTableReg>0) ){
pReg = &aMem[pC->pseudoTableReg];
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
@@ -2174,9 +2203,10 @@ case OP_Column: {
payloadSize = 0;
}
- /* If payloadSize is 0, then just store a NULL */
+ /* If payloadSize is 0, then just store a NULL. This can happen because of
+ ** nullRow or because of a corrupt database. */
if( payloadSize==0 ){
- assert( pDest->flags&MEM_Null );
+ MemSetTypeFlag(pDest, MEM_Null);
goto op_column_out;
}
assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
@@ -2283,8 +2313,14 @@ case OP_Column: {
for(i=0; ip4type==P4_MEM ){
sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
}else{
- assert( pDest->flags&MEM_Null );
+ MemSetTypeFlag(pDest, MEM_Null);
}
}
@@ -2538,7 +2574,7 @@ case OP_Count: { /* out2-prerelease */
BtCursor *pCrsr;
pCrsr = p->apCsr[pOp->p1]->pCursor;
- if( pCrsr ){
+ if( ALWAYS(pCrsr) ){
rc = sqlite3BtreeCount(pCrsr, &nEntry);
}else{
nEntry = 0;
@@ -3100,15 +3136,9 @@ case OP_OpenWrite: {
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
pCur->pKeyInfo = pKeyInfo;
- /* Since it performs no memory allocation or IO, the only values that
- ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK.
- ** SQLITE_EMPTY is only returned when attempting to open the table
- ** rooted at page 1 of a zero-byte database. */
- assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
- if( rc==SQLITE_EMPTY ){
- pCur->pCursor = 0;
- rc = SQLITE_OK;
- }
+ /* Since it performs no memory allocation or IO, the only value that
+ ** sqlite3BtreeCursor() may return is SQLITE_OK. */
+ assert( rc==SQLITE_OK );
/* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
** SQLite used to check if the root-page flags were sane at this point
@@ -3119,7 +3149,7 @@ case OP_OpenWrite: {
break;
}
-/* Opcode: OpenEphemeral P1 P2 * P4 *
+/* Opcode: OpenEphemeral P1 P2 * P4 P5
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if
@@ -3136,6 +3166,11 @@ case OP_OpenWrite: {
** to a TEMP table at the SQL level, or to a table opened by
** this opcode. Then this opcode was call OpenVirtual. But
** that created confusion with the whole virtual-table idea.
+**
+** The P5 parameter can be a mask of the BTREE_* flags defined
+** in btree.h. These flags control aspects of the operation of
+** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
+** added automatically.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
**
@@ -3172,7 +3207,7 @@ case OP_OpenEphemeral: {
if( pOp->p4.pKeyInfo ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY);
+ rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1,
@@ -3191,6 +3226,28 @@ case OP_OpenEphemeral: {
break;
}
+/* Opcode: OpenSorter P1 P2 * P4 *
+**
+** This opcode works like OP_OpenEphemeral except that it opens
+** a transient index that is specifically designed to sort large
+** tables using an external merge-sort algorithm.
+*/
+case OP_SorterOpen: {
+ VdbeCursor *pCx;
+#ifndef SQLITE_OMIT_MERGE_SORT
+ pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( pCx==0 ) goto no_mem;
+ pCx->pKeyInfo = pOp->p4.pKeyInfo;
+ pCx->pKeyInfo->enc = ENC(p->db);
+ pCx->isSorter = 1;
+ rc = sqlite3VdbeSorterInit(db, pCx);
+#else
+ pOp->opcode = OP_OpenEphemeral;
+ pc--;
+#endif
+ break;
+}
+
/* Opcode: OpenPseudo P1 P2 P3 * *
**
** Open a new cursor that points to a fake table that contains a single
@@ -3303,7 +3360,7 @@ case OP_SeekGt: { /* jump, in3 */
assert( OP_SeekGe == OP_SeekLt+2 );
assert( OP_SeekGt == OP_SeekLt+3 );
assert( pC->isOrdered );
- if( pC->pCursor!=0 ){
+ if( ALWAYS(pC->pCursor!=0) ){
oc = pOp->opcode;
pC->nullRow = 0;
if( pC->isTable ){
@@ -3491,6 +3548,7 @@ case OP_Found: { /* jump, in3 */
int alreadyExists;
VdbeCursor *pC;
int res;
+ char *pFree;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
@@ -3518,18 +3576,18 @@ case OP_Found: { /* jump, in3 */
r.flags = UNPACKED_PREFIX_MATCH;
pIdxKey = &r;
}else{
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+ pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
+ );
+ if( pIdxKey==0 ) goto no_mem;
assert( pIn3->flags & MEM_Blob );
assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
- pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
- aTempRec, sizeof(aTempRec));
- if( pIdxKey==0 ){
- goto no_mem;
- }
+ sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
}
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
if( pOp->p4.i==0 ){
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ sqlite3DbFree(db, pFree);
}
if( rc!=SQLITE_OK ){
break;
@@ -3661,7 +3719,7 @@ case OP_NotExists: { /* jump, in3 */
assert( pC->isTable );
assert( pC->pseudoTableReg==0 );
pCrsr = pC->pCursor;
- if( pCrsr!=0 ){
+ if( ALWAYS(pCrsr!=0) ){
res = 0;
iKey = pIn3->u.i;
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
@@ -4039,6 +4097,45 @@ case OP_ResetCount: {
break;
}
+/* Opcode: SorterCompare P1 P2 P3
+**
+** P1 is a sorter cursor. This instruction compares the record blob in
+** register P3 with the entry that the sorter cursor currently points to.
+** If, excluding the rowid fields at the end, the two records are a match,
+** fall through to the next instruction. Otherwise, jump to instruction P2.
+*/
+case OP_SorterCompare: {
+ VdbeCursor *pC;
+ int res;
+
+ pC = p->apCsr[pOp->p1];
+ assert( isSorter(pC) );
+ pIn3 = &aMem[pOp->p3];
+ rc = sqlite3VdbeSorterCompare(pC, pIn3, &res);
+ if( res ){
+ pc = pOp->p2-1;
+ }
+ break;
+};
+
+/* Opcode: SorterData P1 P2 * * *
+**
+** Write into register P2 the current sorter data for sorter cursor P1.
+*/
+case OP_SorterData: {
+ VdbeCursor *pC;
+#ifndef SQLITE_OMIT_MERGE_SORT
+ pOut = &aMem[pOp->p2];
+ pC = p->apCsr[pOp->p1];
+ assert( pC->isSorter );
+ rc = sqlite3VdbeSorterRowkey(pC, pOut);
+#else
+ pOp->opcode = OP_RowKey;
+ pc--;
+#endif
+ break;
+}
+
/* Opcode: RowData P1 P2 * * *
**
** Write into register P2 the complete row data for cursor P1.
@@ -4072,11 +4169,13 @@ case OP_RowData: {
/* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
- assert( pC->isTable || pOp->opcode==OP_RowKey );
+ assert( pC->isSorter==0 );
+ assert( pC->isTable || pOp->opcode!=OP_RowData );
assert( pC->isIndex || pOp->opcode==OP_RowData );
assert( pC!=0 );
assert( pC->nullRow==0 );
assert( pC->pseudoTableReg==0 );
+ assert( !pC->isSorter );
assert( pC->pCursor!=0 );
pCrsr = pC->pCursor;
assert( sqlite3BtreeCursorIsValid(pCrsr) );
@@ -4092,14 +4191,14 @@ case OP_RowData: {
if( pC->isIndex ){
assert( !pC->isTable );
- rc = sqlite3BtreeKeySize(pCrsr, &n64);
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
n = (u32)n64;
}else{
- rc = sqlite3BtreeDataSize(pCrsr, &n);
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
@@ -4181,6 +4280,7 @@ case OP_NullRow: {
assert( pC!=0 );
pC->nullRow = 1;
pC->rowidIsValid = 0;
+ assert( pC->pCursor || pC->pVtabCursor );
if( pC->pCursor ){
sqlite3BtreeClearCursor(pC->pCursor);
}
@@ -4204,9 +4304,8 @@ case OP_Last: { /* jump */
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pCrsr = pC->pCursor;
- if( pCrsr==0 ){
- res = 1;
- }else{
+ res = 0;
+ if( ALWAYS(pCrsr!=0) ){
rc = sqlite3BtreeLast(pCrsr, &res);
}
pC->nullRow = (u8)res;
@@ -4232,6 +4331,10 @@ case OP_Last: { /* jump */
** regression tests can determine whether or not the optimizer is
** correctly optimizing out sorts.
*/
+case OP_SorterSort: /* jump */
+#ifdef SQLITE_OMIT_MERGE_SORT
+ pOp->opcode = OP_Sort;
+#endif
case OP_Sort: { /* jump */
#ifdef SQLITE_TEST
sqlite3_sort_count++;
@@ -4256,8 +4359,13 @@ case OP_Rewind: { /* jump */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+ assert( pC->isSorter==(pOp->opcode==OP_SorterSort) );
res = 1;
- if( (pCrsr = pC->pCursor)!=0 ){
+ if( isSorter(pC) ){
+ rc = sqlite3VdbeSorterRewind(db, pC, &res);
+ }else{
+ pCrsr = pC->pCursor;
+ assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->atFirst = res==0 ?1:0;
pC->deferredMoveto = 0;
@@ -4272,7 +4380,7 @@ case OP_Rewind: { /* jump */
break;
}
-/* Opcode: Next P1 P2 * * P5
+/* Opcode: Next P1 P2 * P4 P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
@@ -4281,6 +4389,9 @@ case OP_Rewind: { /* jump */
**
** The P1 cursor must be for a real table, not a pseudo-table.
**
+** P4 is always of type P4_ADVANCE. The function pointer points to
+** sqlite3BtreeNext().
+**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
@@ -4295,13 +4406,19 @@ case OP_Rewind: { /* jump */
**
** The P1 cursor must be for a real table, not a pseudo-table.
**
+** P4 is always of type P4_ADVANCE. The function pointer points to
+** sqlite3BtreePrevious().
+**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
+case OP_SorterNext: /* jump */
+#ifdef SQLITE_OMIT_MERGE_SORT
+ pOp->opcode = OP_Next;
+#endif
case OP_Prev: /* jump */
case OP_Next: { /* jump */
VdbeCursor *pC;
- BtCursor *pCrsr;
int res;
CHECK_FOR_INTERRUPT;
@@ -4311,15 +4428,18 @@ case OP_Next: { /* jump */
if( pC==0 ){
break; /* See ticket #2273 */
}
- pCrsr = pC->pCursor;
- if( pCrsr==0 ){
- pC->nullRow = 1;
- break;
+ assert( pC->isSorter==(pOp->opcode==OP_SorterNext) );
+ if( isSorter(pC) ){
+ assert( pOp->opcode==OP_SorterNext );
+ rc = sqlite3VdbeSorterNext(db, pC, &res);
+ }else{
+ res = 1;
+ assert( pC->deferredMoveto==0 );
+ assert( pC->pCursor );
+ assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
+ assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
+ rc = pOp->p4.xAdvance(pC->pCursor, &res);
}
- res = 1;
- assert( pC->deferredMoveto==0 );
- rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
- sqlite3BtreePrevious(pCrsr, &res);
pC->nullRow = (u8)res;
pC->cacheStatus = CACHE_STALE;
if( res==0 ){
@@ -4345,6 +4465,10 @@ case OP_Next: { /* jump */
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
+case OP_SorterInsert: /* in2 */
+#ifdef SQLITE_OMIT_MERGE_SORT
+ pOp->opcode = OP_IdxInsert;
+#endif
case OP_IdxInsert: { /* in2 */
VdbeCursor *pC;
BtCursor *pCrsr;
@@ -4354,6 +4478,7 @@ case OP_IdxInsert: { /* in2 */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+ assert( pC->isSorter==(pOp->opcode==OP_SorterInsert) );
pIn2 = &aMem[pOp->p2];
assert( pIn2->flags & MEM_Blob );
pCrsr = pC->pCursor;
@@ -4361,13 +4486,17 @@ case OP_IdxInsert: { /* in2 */
assert( pC->isTable==0 );
rc = ExpandBlob(pIn2);
if( rc==SQLITE_OK ){
- nKey = pIn2->n;
- zKey = pIn2->z;
- rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3,
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
- );
- assert( pC->deferredMoveto==0 );
- pC->cacheStatus = CACHE_STALE;
+ if( isSorter(pC) ){
+ rc = sqlite3VdbeSorterWrite(db, pC, pIn2);
+ }else{
+ nKey = pIn2->n;
+ zKey = pIn2->z;
+ rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3,
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
+ );
+ assert( pC->deferredMoveto==0 );
+ pC->cacheStatus = CACHE_STALE;
+ }
}
}
break;
@@ -5337,7 +5466,7 @@ case OP_JournalMode: { /* out2-prerelease */
** in temporary storage or if the VFS does not support shared memory
*/
if( eNew==PAGER_JOURNALMODE_WAL
- && (zFilename[0]==0 /* Temp file */
+ && (sqlite3Strlen30(zFilename)==0 /* Temp file */
|| !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */
){
eNew = eOld;
@@ -5758,10 +5887,15 @@ case OP_VRename: {
assert( memIsValid(pName) );
REGISTER_TRACE(pOp->p1, pName);
assert( pName->flags & MEM_Str );
- rc = pVtab->pModule->xRename(pVtab, pName->z);
- importVtabErrMsg(p, pVtab);
- p->expired = 0;
-
+ testcase( pName->enc==SQLITE_UTF8 );
+ testcase( pName->enc==SQLITE_UTF16BE );
+ testcase( pName->enc==SQLITE_UTF16LE );
+ rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
+ if( rc==SQLITE_OK ){
+ rc = pVtab->pModule->xRename(pVtab, pName->z);
+ importVtabErrMsg(p, pVtab);
+ p->expired = 0;
+ }
break;
}
#endif
diff --git a/src/vdbe.h b/src/vdbe.h
index e66ee302..948c73bc 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -61,6 +61,7 @@ struct VdbeOp {
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
int *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
+ int (*xAdvance)(BtCursor *, int *);
} p4;
#ifdef SQLITE_DEBUG
char *zComment; /* Comment to improve readability */
@@ -116,6 +117,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
+#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
** is made. That copy is freed when the Vdbe is finalized. But if the
@@ -173,12 +175,12 @@ int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
-void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
-void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
-void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
+void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
+void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
+void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
-void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
+void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
@@ -210,9 +212,9 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
-UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int);
-void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
+void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
+UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
#ifndef SQLITE_OMIT_TRIGGER
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 0aeb3af7..803ae163 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -30,6 +30,9 @@ typedef struct VdbeOp Op;
*/
typedef unsigned char Bool;
+/* Opaque type used by code in vdbesort.c */
+typedef struct VdbeSorter VdbeSorter;
+
/*
** A cursor is a pointer into a single BTree within a database file.
** The cursor can seek to a BTree entry with a particular key, or
@@ -56,11 +59,13 @@ struct VdbeCursor {
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
+ Bool isSorter; /* True if a new-style sorter */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
+ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
/* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
** OP_IsUnique opcode on this cursor. */
@@ -380,6 +385,9 @@ int sqlite3VdbeMemNumerify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemReleaseExternal(Mem *p);
+#define MemReleaseExt(X) \
+ if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
+ sqlite3VdbeMemReleaseExternal(X);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
const char *sqlite3OpcodeName(int);
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
@@ -387,6 +395,25 @@ int sqlite3VdbeCloseStatement(Vdbe *, int);
void sqlite3VdbeFrameDelete(VdbeFrame*);
int sqlite3VdbeFrameRestore(VdbeFrame *);
void sqlite3VdbeMemStoreType(Mem *pMem);
+int sqlite3VdbeTransferError(Vdbe *p);
+
+#ifdef SQLITE_OMIT_MERGE_SORT
+# define sqlite3VdbeSorterInit(Y,Z) SQLITE_OK
+# define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK
+# define sqlite3VdbeSorterClose(Y,Z)
+# define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK
+# define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK
+# define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK
+# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
+#else
+int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
+void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
+int sqlite3VdbeSorterRowkey(VdbeCursor *, Mem *);
+int sqlite3VdbeSorterNext(sqlite3 *, VdbeCursor *, int *);
+int sqlite3VdbeSorterRewind(sqlite3 *, VdbeCursor *, int *);
+int sqlite3VdbeSorterWrite(sqlite3 *, VdbeCursor *, Mem *);
+int sqlite3VdbeSorterCompare(VdbeCursor *, Mem *, int *);
+#endif
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
void sqlite3VdbeEnter(Vdbe*);
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index a87b5c9a..adc9dba2 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -454,7 +454,7 @@ end_of_step:
** error has occured, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
*/
- rc = db->errCode = p->rc;
+ rc = sqlite3VdbeTransferError(p);
}
return (rc&db->errMask);
}
@@ -488,7 +488,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
- v->expired = 0;
+ assert( v->expired==0 );
}
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
/* This case occurs after failing to recompile an sql statement.
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 989a8003..75250238 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -433,6 +433,12 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
n = pOp[-1].p1;
if( n>nMaxArgs ) nMaxArgs = n;
#endif
+ }else if( opcode==OP_Next || opcode==OP_SorterNext ){
+ pOp->p4.xAdvance = sqlite3BtreeNext;
+ pOp->p4type = P4_ADVANCE;
+ }else if( opcode==OP_Prev ){
+ pOp->p4.xAdvance = sqlite3BtreePrevious;
+ pOp->p4type = P4_ADVANCE;
}
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
@@ -524,10 +530,9 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
** static array using sqlite3VdbeAddOpList but we want to make a
** few minor changes to the program.
*/
-void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
+void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
assert( p!=0 );
- assert( addr>=0 );
- if( p->nOp>addr ){
+ if( ((u32)p->nOp)>addr ){
p->aOp[addr].p1 = val;
}
}
@@ -536,10 +541,9 @@ void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
** Change the value of the P2 operand for a specific instruction.
** This routine is useful for setting a jump destination.
*/
-void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
+void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
assert( p!=0 );
- assert( addr>=0 );
- if( p->nOp>addr ){
+ if( ((u32)p->nOp)>addr ){
p->aOp[addr].p2 = val;
}
}
@@ -547,10 +551,9 @@ void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
/*
** Change the value of the P3 operand for a specific instruction.
*/
-void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
+void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
assert( p!=0 );
- assert( addr>=0 );
- if( p->nOp>addr ){
+ if( ((u32)p->nOp)>addr ){
p->aOp[addr].p3 = val;
}
}
@@ -572,8 +575,8 @@ void sqlite3VdbeChangeP5(Vdbe *p, u8 val){
** the address of the next instruction to be coded.
*/
void sqlite3VdbeJumpHere(Vdbe *p, int addr){
- assert( addr>=0 );
- sqlite3VdbeChangeP2(p, addr, p->nOp);
+ assert( addr>=0 || p->db->mallocFailed );
+ if( addr>=0 ) sqlite3VdbeChangeP2(p, addr, p->nOp);
}
@@ -667,18 +670,15 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
}
/*
-** Change N opcodes starting at addr to No-ops.
+** Change the opcode at addr into OP_Noop
*/
-void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
+void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
if( p->aOp ){
VdbeOp *pOp = &p->aOp[addr];
sqlite3 *db = p->db;
- while( N-- ){
- freeP4(db, pOp->p4type, pOp->p4.p);
- memset(pOp, 0, sizeof(pOp[0]));
- pOp->opcode = OP_Noop;
- pOp++;
- }
+ freeP4(db, pOp->p4type, pOp->p4.p);
+ memset(pOp, 0, sizeof(pOp[0]));
+ pOp->opcode = OP_Noop;
}
}
@@ -781,30 +781,29 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
** makes the code easier to read during debugging. None of this happens
** in a production build.
*/
-void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
- va_list ap;
- if( !p ) return;
+static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
assert( p->nOp>0 || p->aOp==0 );
assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
if( p->nOp ){
- char **pz = &p->aOp[p->nOp-1].zComment;
+ assert( p->aOp );
+ sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
+ p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap);
+ }
+}
+void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
+ va_list ap;
+ if( p ){
va_start(ap, zFormat);
- sqlite3DbFree(p->db, *pz);
- *pz = sqlite3VMPrintf(p->db, zFormat, ap);
+ vdbeVComment(p, zFormat, ap);
va_end(ap);
}
}
void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
va_list ap;
- if( !p ) return;
- sqlite3VdbeAddOp0(p, OP_Noop);
- assert( p->nOp>0 || p->aOp==0 );
- assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
- if( p->nOp ){
- char **pz = &p->aOp[p->nOp-1].zComment;
+ if( p ){
+ sqlite3VdbeAddOp0(p, OP_Noop);
va_start(ap, zFormat);
- sqlite3DbFree(p->db, *pz);
- *pz = sqlite3VMPrintf(p->db, zFormat, ap);
+ vdbeVComment(p, zFormat, ap);
va_end(ap);
}
}
@@ -834,7 +833,7 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
** zeros, which is correct. MSVC generates a warning, nevertheless. */
- static const VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
+ static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
assert( p->magic==VDBE_MAGIC_INIT );
if( addr<0 ){
#ifdef SQLITE_OMIT_TRACE
@@ -942,6 +941,10 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
sqlite3_snprintf(nTemp, zTemp, "program");
break;
}
+ case P4_ADVANCE: {
+ zTemp[0] = 0;
+ break;
+ }
default: {
zP4 = pOp->p4.z;
if( zP4==0 ){
@@ -1138,7 +1141,7 @@ int sqlite3VdbeList(
sqlite3 *db = p->db; /* The database connection */
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
- Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */
+ Mem *pMem = &p->aMem[1]; /* First Mem of result set */
assert( p->explain );
assert( p->magic==VDBE_MAGIC_RUN );
@@ -1149,6 +1152,7 @@ int sqlite3VdbeList(
** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
*/
releaseMemArray(pMem, 8);
+ p->pResultSet = 0;
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
@@ -1303,6 +1307,7 @@ int sqlite3VdbeList(
}
p->nResColumn = 8 - 4*(p->explain-1);
+ p->pResultSet = &p->aMem[1];
p->rc = SQLITE_OK;
rc = SQLITE_ROW;
}
@@ -1565,6 +1570,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
if( pCx==0 ){
return;
}
+ sqlite3VdbeSorterClose(p->db, pCx);
if( pCx->pBt ){
sqlite3BtreeClose(pCx->pBt);
/* The pCx->pCursor will be close automatically, if it exists, by
@@ -2304,6 +2310,30 @@ void sqlite3VdbeResetStepResult(Vdbe *p){
p->rc = SQLITE_OK;
}
+/*
+** Copy the error code and error message belonging to the VDBE passed
+** as the first argument to its database handle (so that they will be
+** returned by calls to sqlite3_errcode() and sqlite3_errmsg()).
+**
+** This function does not clear the VDBE error code or message, just
+** copies them to the database handle.
+*/
+int sqlite3VdbeTransferError(Vdbe *p){
+ sqlite3 *db = p->db;
+ int rc = p->rc;
+ if( p->zErrMsg ){
+ u8 mallocFailed = db->mallocFailed;
+ sqlite3BeginBenignMalloc();
+ sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
+ sqlite3EndBenignMalloc();
+ db->mallocFailed = mallocFailed;
+ db->errCode = rc;
+ }else{
+ sqlite3Error(db, rc, 0);
+ }
+ return rc;
+}
+
/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg. Return the result code.
@@ -2331,18 +2361,9 @@ int sqlite3VdbeReset(Vdbe *p){
** instructions yet, leave the main database error information unchanged.
*/
if( p->pc>=0 ){
- if( p->zErrMsg ){
- sqlite3BeginBenignMalloc();
- sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT);
- sqlite3EndBenignMalloc();
- db->errCode = p->rc;
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
- }else if( p->rc ){
- sqlite3Error(db, p->rc, 0);
- }else{
- sqlite3Error(db, SQLITE_OK, 0);
- }
+ sqlite3VdbeTransferError(p);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = 0;
if( p->runOnlyOnce ) p->expired = 1;
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
@@ -2822,57 +2843,70 @@ u32 sqlite3VdbeSerialGet(
return 0;
}
-
/*
-** Given the nKey-byte encoding of a record in pKey[], parse the
-** record into a UnpackedRecord structure. Return a pointer to
-** that structure.
+** This routine is used to allocate sufficient space for an UnpackedRecord
+** structure large enough to be used with sqlite3VdbeRecordUnpack() if
+** the first argument is a pointer to KeyInfo structure pKeyInfo.
**
-** The calling function might provide szSpace bytes of memory
-** space at pSpace. This space can be used to hold the returned
-** VDbeParsedRecord structure if it is large enough. If it is
-** not big enough, space is obtained from sqlite3_malloc().
+** The space is either allocated using sqlite3DbMallocRaw() or from within
+** the unaligned buffer passed via the second and third arguments (presumably
+** stack space). If the former, then *ppFree is set to a pointer that should
+** be eventually freed by the caller using sqlite3DbFree(). Or, if the
+** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
+** before returning.
**
-** The returned structure should be closed by a call to
-** sqlite3VdbeDeleteUnpackedRecord().
-*/
-UnpackedRecord *sqlite3VdbeRecordUnpack(
- KeyInfo *pKeyInfo, /* Information about the record format */
- int nKey, /* Size of the binary record */
- const void *pKey, /* The binary record */
- char *pSpace, /* Unaligned space available to hold the object */
- int szSpace /* Size of pSpace[] in bytes */
+** If an OOM error occurs, NULL is returned.
+*/
+UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
+ KeyInfo *pKeyInfo, /* Description of the record */
+ char *pSpace, /* Unaligned space available */
+ int szSpace, /* Size of pSpace[] in bytes */
+ char **ppFree /* OUT: Caller should free this pointer */
){
- const unsigned char *aKey = (const unsigned char *)pKey;
- UnpackedRecord *p; /* The unpacked record that we will return */
- int nByte; /* Memory space needed to hold p, in bytes */
- int d;
- u32 idx;
- u16 u; /* Unsigned loop counter */
- u32 szHdr;
- Mem *pMem;
- int nOff; /* Increase pSpace by this much to 8-byte align it */
-
- /*
- ** We want to shift the pointer pSpace up such that it is 8-byte aligned.
+ UnpackedRecord *p; /* Unpacked record to return */
+ int nOff; /* Increment pSpace by nOff to align it */
+ int nByte; /* Number of bytes required for *p */
+
+ /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
** it by. If pSpace is already 8-byte aligned, nOff should be zero.
*/
nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
- pSpace += nOff;
- szSpace -= nOff;
nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
- if( nByte>szSpace ){
- p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
- if( p==0 ) return 0;
- p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
+ if( nByte>szSpace+nOff ){
+ p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
+ *ppFree = (char *)p;
+ if( !p ) return 0;
}else{
- p = (UnpackedRecord*)pSpace;
- p->flags = UNPACKED_NEED_DESTROY;
+ p = (UnpackedRecord*)&pSpace[nOff];
+ *ppFree = 0;
}
+
+ p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nField + 1;
- p->aMem = pMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
+ return p;
+}
+
+/*
+** Given the nKey-byte encoding of a record in pKey[], populate the
+** UnpackedRecord structure indicated by the fourth argument with the
+** contents of the decoded record.
+*/
+void sqlite3VdbeRecordUnpack(
+ KeyInfo *pKeyInfo, /* Information about the record format */
+ int nKey, /* Size of the binary record */
+ const void *pKey, /* The binary record */
+ UnpackedRecord *p /* Populate this structure before returning. */
+){
+ const unsigned char *aKey = (const unsigned char *)pKey;
+ int d;
+ u32 idx; /* Offset in aKey[] to read from */
+ u16 u; /* Unsigned loop counter */
+ u32 szHdr;
+ Mem *pMem = p->aMem;
+
+ p->flags = 0;
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
idx = getVarint32(aKey, szHdr);
d = szHdr;
@@ -2891,31 +2925,6 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
}
assert( u<=pKeyInfo->nField + 1 );
p->nField = u;
- return (void*)p;
-}
-
-/*
-** This routine destroys a UnpackedRecord object.
-*/
-void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
-#ifdef SQLITE_DEBUG
- int i;
- Mem *pMem;
-
- assert( p!=0 );
- assert( p->flags & UNPACKED_NEED_DESTROY );
- for(i=0, pMem=p->aMem; inField; i++, pMem++){
- /* The unpacked record is always constructed by the
- ** sqlite3VdbeUnpackRecord() function above, which makes all
- ** strings and blobs static. And none of the elements are
- ** ever transformed, so there is never anything to delete.
- */
- if( NEVER(pMem->zMalloc) ) sqlite3VdbeMemRelease(pMem);
- }
-#endif
- if( p->flags & UNPACKED_NEED_FREE ){
- sqlite3DbFree(p->pKeyInfo->db, p);
- }
}
/*
@@ -3069,7 +3078,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
** this code can safely assume that nCellKey is 32-bits
*/
assert( sqlite3BtreeCursorIsValid(pCur) );
- rc = sqlite3BtreeKeySize(pCur, &nCellKey);
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
@@ -3144,7 +3153,7 @@ int sqlite3VdbeIdxKeyCompare(
Mem m;
assert( sqlite3BtreeCursorIsValid(pCur) );
- rc = sqlite3BtreeKeySize(pCur, &nCellKey);
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
/* nCellKey will always be between 0 and 0xffffffff because of the say
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index a8728e6d..ae77a47b 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -273,7 +273,7 @@ int sqlite3_blob_open(
/* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
- sqlite3VdbeChangeToNoop(v, 2, 1);
+ sqlite3VdbeChangeToNoop(v, 2);
#else
sqlite3VdbeChangeP1(v, 2, iDb);
sqlite3VdbeChangeP2(v, 2, pTab->tnum);
@@ -283,7 +283,7 @@ int sqlite3_blob_open(
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
- sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
+ sqlite3VdbeChangeToNoop(v, 4 - flags);
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
sqlite3VdbeChangeP3(v, 3 + flags, iDb);
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 882c6863..e6e91562 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -271,24 +271,18 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
*/
void sqlite3VdbeMemReleaseExternal(Mem *p){
assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
- testcase( p->flags & MEM_Agg );
- testcase( p->flags & MEM_Dyn );
- testcase( p->flags & MEM_RowSet );
- testcase( p->flags & MEM_Frame );
- if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame) ){
- if( p->flags&MEM_Agg ){
- sqlite3VdbeMemFinalize(p, p->u.pDef);
- assert( (p->flags & MEM_Agg)==0 );
- sqlite3VdbeMemRelease(p);
- }else if( p->flags&MEM_Dyn && p->xDel ){
- assert( (p->flags&MEM_RowSet)==0 );
- p->xDel((void *)p->z);
- p->xDel = 0;
- }else if( p->flags&MEM_RowSet ){
- sqlite3RowSetClear(p->u.pRowSet);
- }else if( p->flags&MEM_Frame ){
- sqlite3VdbeMemSetNull(p);
- }
+ if( p->flags&MEM_Agg ){
+ sqlite3VdbeMemFinalize(p, p->u.pDef);
+ assert( (p->flags & MEM_Agg)==0 );
+ sqlite3VdbeMemRelease(p);
+ }else if( p->flags&MEM_Dyn && p->xDel ){
+ assert( (p->flags&MEM_RowSet)==0 );
+ p->xDel((void *)p->z);
+ p->xDel = 0;
+ }else if( p->flags&MEM_RowSet ){
+ sqlite3RowSetClear(p->u.pRowSet);
+ }else if( p->flags&MEM_Frame ){
+ sqlite3VdbeMemSetNull(p);
}
}
@@ -298,7 +292,7 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
** (Mem.type==SQLITE_TEXT).
*/
void sqlite3VdbeMemRelease(Mem *p){
- sqlite3VdbeMemReleaseExternal(p);
+ MemReleaseExt(p);
sqlite3DbFree(p->db, p->zMalloc);
p->z = 0;
p->zMalloc = 0;
@@ -620,7 +614,7 @@ void sqlite3VdbeMemPrepareToChange(Vdbe *pVdbe, Mem *pMem){
*/
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
assert( (pFrom->flags & MEM_RowSet)==0 );
- sqlite3VdbeMemReleaseExternal(pTo);
+ MemReleaseExt(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->xDel = 0;
if( (pFrom->flags&MEM_Static)==0 ){
@@ -638,7 +632,7 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
int rc = SQLITE_OK;
assert( (pFrom->flags & MEM_RowSet)==0 );
- sqlite3VdbeMemReleaseExternal(pTo);
+ MemReleaseExt(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->flags &= ~MEM_Dyn;
@@ -1032,11 +1026,11 @@ int sqlite3ValueFromExpr(
}
op = pExpr->op;
- /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT2.
+ /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3.
** The ifdef here is to enable us to achieve 100% branch test coverage even
- ** when SQLITE_ENABLE_STAT2 is omitted.
+ ** when SQLITE_ENABLE_STAT3 is omitted.
*/
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
if( op==TK_REGISTER ) op = pExpr->op2;
#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
diff --git a/src/vdbesort.c b/src/vdbesort.c
new file mode 100644
index 00000000..c4499970
--- /dev/null
+++ b/src/vdbesort.c
@@ -0,0 +1,882 @@
+/*
+** 2011 July 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.
+**
+*************************************************************************
+** This file contains code for the VdbeSorter object, used in concert with
+** a VdbeCursor to sort large numbers of keys (as may be required, for
+** example, by CREATE INDEX statements on tables too large to fit in main
+** memory).
+*/
+
+#include "sqliteInt.h"
+#include "vdbeInt.h"
+
+#ifndef SQLITE_OMIT_MERGE_SORT
+
+typedef struct VdbeSorterIter VdbeSorterIter;
+typedef struct SorterRecord SorterRecord;
+
+/*
+** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
+**
+** As keys are added to the sorter, they are written to disk in a series
+** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly
+** the same as the cache-size allowed for temporary databases. In order
+** to allow the caller to extract keys from the sorter in sorted order,
+** all PMAs currently stored on disk must be merged together. This comment
+** describes the data structure used to do so. The structure supports
+** merging any number of arrays in a single pass with no redundant comparison
+** operations.
+**
+** The aIter[] array contains an iterator for each of the PMAs being merged.
+** An aIter[] iterator either points to a valid key or else is at EOF. For
+** the purposes of the paragraphs below, we assume that the array is actually
+** N elements in size, where N is the smallest power of 2 greater to or equal
+** to the number of iterators being merged. The extra aIter[] elements are
+** treated as if they are empty (always at EOF).
+**
+** The aTree[] array is also N elements in size. The value of N is stored in
+** the VdbeSorter.nTree variable.
+**
+** The final (N/2) elements of aTree[] contain the results of comparing
+** pairs of iterator keys together. Element i contains the result of
+** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the
+** aTree element is set to the index of it.
+**
+** For the purposes of this comparison, EOF is considered greater than any
+** other key value. If the keys are equal (only possible with two EOF
+** values), it doesn't matter which index is stored.
+**
+** The (N/4) elements of aTree[] that preceed the final (N/2) described
+** above contains the index of the smallest of each block of 4 iterators.
+** And so on. So that aTree[1] contains the index of the iterator that
+** currently points to the smallest key value. aTree[0] is unused.
+**
+** Example:
+**
+** aIter[0] -> Banana
+** aIter[1] -> Feijoa
+** aIter[2] -> Elderberry
+** aIter[3] -> Currant
+** aIter[4] -> Grapefruit
+** aIter[5] -> Apple
+** aIter[6] -> Durian
+** aIter[7] -> EOF
+**
+** aTree[] = { X, 5 0, 5 0, 3, 5, 6 }
+**
+** The current element is "Apple" (the value of the key indicated by
+** iterator 5). When the Next() operation is invoked, iterator 5 will
+** be advanced to the next key in its segment. Say the next key is
+** "Eggplant":
+**
+** aIter[5] -> Eggplant
+**
+** The contents of aTree[] are updated first by comparing the new iterator
+** 5 key to the current key of iterator 4 (still "Grapefruit"). The iterator
+** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree.
+** The value of iterator 6 - "Durian" - is now smaller than that of iterator
+** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (BananaaAlloc);
+ memset(pIter, 0, sizeof(VdbeSorterIter));
+}
+
+/*
+** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
+** no error occurs, or an SQLite error code if one does.
+*/
+static int vdbeSorterIterNext(
+ sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */
+ VdbeSorterIter *pIter /* Iterator to advance */
+){
+ int rc; /* Return Code */
+ int nRead; /* Number of bytes read */
+ int nRec = 0; /* Size of record in bytes */
+ int iOff = 0; /* Size of serialized size varint in bytes */
+
+ assert( pIter->iEof>=pIter->iReadOff );
+ if( pIter->iEof-pIter->iReadOff>5 ){
+ nRead = 5;
+ }else{
+ nRead = (int)(pIter->iEof - pIter->iReadOff);
+ }
+ if( nRead<=0 ){
+ /* This is an EOF condition */
+ vdbeSorterIterZero(db, pIter);
+ return SQLITE_OK;
+ }
+
+ rc = sqlite3OsRead(pIter->pFile, pIter->aAlloc, nRead, pIter->iReadOff);
+ if( rc==SQLITE_OK ){
+ iOff = getVarint32(pIter->aAlloc, nRec);
+ if( (iOff+nRec)>nRead ){
+ int nRead2; /* Number of extra bytes to read */
+ if( (iOff+nRec)>pIter->nAlloc ){
+ int nNew = pIter->nAlloc*2;
+ while( (iOff+nRec)>nNew ) nNew = nNew*2;
+ pIter->aAlloc = sqlite3DbReallocOrFree(db, pIter->aAlloc, nNew);
+ if( !pIter->aAlloc ) return SQLITE_NOMEM;
+ pIter->nAlloc = nNew;
+ }
+
+ nRead2 = iOff + nRec - nRead;
+ rc = sqlite3OsRead(
+ pIter->pFile, &pIter->aAlloc[nRead], nRead2, pIter->iReadOff+nRead
+ );
+ }
+ }
+
+ assert( rc!=SQLITE_OK || nRec>0 );
+ pIter->iReadOff += iOff+nRec;
+ pIter->nKey = nRec;
+ pIter->aKey = &pIter->aAlloc[iOff];
+ return rc;
+}
+
+/*
+** Write a single varint, value iVal, to file-descriptor pFile. Return
+** SQLITE_OK if successful, or an SQLite error code if some error occurs.
+**
+** The value of *piOffset when this function is called is used as the byte
+** offset in file pFile to write to. Before returning, *piOffset is
+** incremented by the number of bytes written.
+*/
+static int vdbeSorterWriteVarint(
+ sqlite3_file *pFile, /* File to write to */
+ i64 iVal, /* Value to write as a varint */
+ i64 *piOffset /* IN/OUT: Write offset in file pFile */
+){
+ u8 aVarint[9]; /* Buffer large enough for a varint */
+ int nVarint; /* Number of used bytes in varint */
+ int rc; /* Result of write() call */
+
+ nVarint = sqlite3PutVarint(aVarint, iVal);
+ rc = sqlite3OsWrite(pFile, aVarint, nVarint, *piOffset);
+ *piOffset += nVarint;
+
+ return rc;
+}
+
+/*
+** Read a single varint from file-descriptor pFile. Return SQLITE_OK if
+** successful, or an SQLite error code if some error occurs.
+**
+** The value of *piOffset when this function is called is used as the
+** byte offset in file pFile from whence to read the varint. If successful
+** (i.e. if no IO error occurs), then *piOffset is set to the offset of
+** the first byte past the end of the varint before returning. *piVal is
+** set to the integer value read. If an error occurs, the final values of
+** both *piOffset and *piVal are undefined.
+*/
+static int vdbeSorterReadVarint(
+ sqlite3_file *pFile, /* File to read from */
+ i64 *piOffset, /* IN/OUT: Read offset in pFile */
+ i64 *piVal /* OUT: Value read from file */
+){
+ u8 aVarint[9]; /* Buffer large enough for a varint */
+ i64 iOff = *piOffset; /* Offset in file to read from */
+ int rc; /* Return code */
+
+ rc = sqlite3OsRead(pFile, aVarint, 9, iOff);
+ if( rc==SQLITE_OK ){
+ *piOffset += getVarint(aVarint, (u64 *)piVal);
+ }
+
+ return rc;
+}
+
+/*
+** Initialize iterator pIter to scan through the PMA stored in file pFile
+** starting at offset iStart and ending at offset iEof-1. This function
+** leaves the iterator pointing to the first key in the PMA (or EOF if the
+** PMA is empty).
+*/
+static int vdbeSorterIterInit(
+ sqlite3 *db, /* Database handle */
+ VdbeSorter *pSorter, /* Sorter object */
+ i64 iStart, /* Start offset in pFile */
+ VdbeSorterIter *pIter, /* Iterator to populate */
+ i64 *pnByte /* IN/OUT: Increment this value by PMA size */
+){
+ int rc;
+
+ assert( pSorter->iWriteOff>iStart );
+ assert( pIter->aAlloc==0 );
+ pIter->pFile = pSorter->pTemp1;
+ pIter->iReadOff = iStart;
+ pIter->nAlloc = 128;
+ pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
+ if( !pIter->aAlloc ){
+ rc = SQLITE_NOMEM;
+ }else{
+ i64 nByte; /* Total size of PMA in bytes */
+ rc = vdbeSorterReadVarint(pSorter->pTemp1, &pIter->iReadOff, &nByte);
+ *pnByte += nByte;
+ pIter->iEof = pIter->iReadOff + nByte;
+ }
+ if( rc==SQLITE_OK ){
+ rc = vdbeSorterIterNext(db, pIter);
+ }
+ return rc;
+}
+
+
+/*
+** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
+** size nKey2 bytes). Argument pKeyInfo supplies the collation functions
+** used by the comparison. If an error occurs, return an SQLite error code.
+** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive
+** value, depending on whether key1 is smaller, equal to or larger than key2.
+**
+** If the bOmitRowid argument is non-zero, assume both keys end in a rowid
+** field. For the purposes of the comparison, ignore it. Also, if bOmitRowid
+** is true and key1 contains even a single NULL value, it is considered to
+** be less than key2. Even if key2 also contains NULL values.
+**
+** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
+** has been allocated and contains an unpacked record that is used as key2.
+*/
+static void vdbeSorterCompare(
+ VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
+ int bOmitRowid, /* Ignore rowid field at end of keys */
+ void *pKey1, int nKey1, /* Left side of comparison */
+ void *pKey2, int nKey2, /* Right side of comparison */
+ int *pRes /* OUT: Result of comparison */
+){
+ KeyInfo *pKeyInfo = pCsr->pKeyInfo;
+ VdbeSorter *pSorter = pCsr->pSorter;
+ UnpackedRecord *r2 = pSorter->pUnpacked;
+ int i;
+
+ if( pKey2 ){
+ sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
+ }
+
+ if( bOmitRowid ){
+ r2->nField = pKeyInfo->nField;
+ assert( r2->nField>0 );
+ for(i=0; inField; i++){
+ if( r2->aMem[i].flags & MEM_Null ){
+ *pRes = -1;
+ return;
+ }
+ }
+ r2->flags |= UNPACKED_PREFIX_MATCH;
+ }
+
+ *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
+}
+
+/*
+** This function is called to compare two iterator keys when merging
+** multiple b-tree segments. Parameter iOut is the index of the aTree[]
+** value to recalculate.
+*/
+static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int i1;
+ int i2;
+ int iRes;
+ VdbeSorterIter *p1;
+ VdbeSorterIter *p2;
+
+ assert( iOutnTree && iOut>0 );
+
+ if( iOut>=(pSorter->nTree/2) ){
+ i1 = (iOut - pSorter->nTree/2) * 2;
+ i2 = i1 + 1;
+ }else{
+ i1 = pSorter->aTree[iOut*2];
+ i2 = pSorter->aTree[iOut*2+1];
+ }
+
+ p1 = &pSorter->aIter[i1];
+ p2 = &pSorter->aIter[i2];
+
+ if( p1->pFile==0 ){
+ iRes = i2;
+ }else if( p2->pFile==0 ){
+ iRes = i1;
+ }else{
+ int res;
+ assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */
+ vdbeSorterCompare(
+ pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res
+ );
+ if( res<=0 ){
+ iRes = i1;
+ }else{
+ iRes = i2;
+ }
+ }
+
+ pSorter->aTree[iOut] = iRes;
+ return SQLITE_OK;
+}
+
+/*
+** Initialize the temporary index cursor just opened as a sorter cursor.
+*/
+int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
+ int pgsz; /* Page size of main database */
+ int mxCache; /* Cache size */
+ VdbeSorter *pSorter; /* The new sorter */
+ char *d; /* Dummy */
+
+ assert( pCsr->pKeyInfo && pCsr->pBt==0 );
+ pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
+ if( pSorter==0 ){
+ return SQLITE_NOMEM;
+ }
+
+ pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d);
+ if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM;
+ assert( pSorter->pUnpacked==(UnpackedRecord *)d );
+
+ if( !sqlite3TempInMemory(db) ){
+ pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+ pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
+ mxCache = db->aDb[0].pSchema->cache_size;
+ if( mxCachemxPmaSize = mxCache * pgsz;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Free the list of sorted records starting at pRecord.
+*/
+static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
+ SorterRecord *p;
+ SorterRecord *pNext;
+ for(p=pRecord; p; p=pNext){
+ pNext = p->pNext;
+ sqlite3DbFree(db, p);
+ }
+}
+
+/*
+** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
+*/
+void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ if( pSorter ){
+ if( pSorter->aIter ){
+ int i;
+ for(i=0; inTree; i++){
+ vdbeSorterIterZero(db, &pSorter->aIter[i]);
+ }
+ sqlite3DbFree(db, pSorter->aIter);
+ }
+ if( pSorter->pTemp1 ){
+ sqlite3OsCloseFree(pSorter->pTemp1);
+ }
+ vdbeSorterRecordFree(db, pSorter->pRecord);
+ sqlite3DbFree(db, pSorter->pUnpacked);
+ sqlite3DbFree(db, pSorter);
+ pCsr->pSorter = 0;
+ }
+}
+
+/*
+** Allocate space for a file-handle and open a temporary file. If successful,
+** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK.
+** Otherwise, set *ppFile to 0 and return an SQLite error code.
+*/
+static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
+ int dummy;
+ return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile,
+ SQLITE_OPEN_TEMP_JOURNAL |
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+ SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy
+ );
+}
+
+/*
+** Merge the two sorted lists p1 and p2 into a single list.
+** Set *ppOut to the head of the new list.
+*/
+static void vdbeSorterMerge(
+ VdbeCursor *pCsr, /* For pKeyInfo */
+ SorterRecord *p1, /* First list to merge */
+ SorterRecord *p2, /* Second list to merge */
+ SorterRecord **ppOut /* OUT: Head of merged list */
+){
+ SorterRecord *pFinal = 0;
+ SorterRecord **pp = &pFinal;
+ void *pVal2 = p2 ? p2->pVal : 0;
+
+ while( p1 && p2 ){
+ int res;
+ vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
+ if( res<=0 ){
+ *pp = p1;
+ pp = &p1->pNext;
+ p1 = p1->pNext;
+ pVal2 = 0;
+ }else{
+ *pp = p2;
+ pp = &p2->pNext;
+ p2 = p2->pNext;
+ if( p2==0 ) break;
+ pVal2 = p2->pVal;
+ }
+ }
+ *pp = p1 ? p1 : p2;
+ *ppOut = pFinal;
+}
+
+/*
+** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK
+** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
+** occurs.
+*/
+static int vdbeSorterSort(VdbeCursor *pCsr){
+ int i;
+ SorterRecord **aSlot;
+ SorterRecord *p;
+ VdbeSorter *pSorter = pCsr->pSorter;
+
+ aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
+ if( !aSlot ){
+ return SQLITE_NOMEM;
+ }
+
+ p = pSorter->pRecord;
+ while( p ){
+ SorterRecord *pNext = p->pNext;
+ p->pNext = 0;
+ for(i=0; aSlot[i]; i++){
+ vdbeSorterMerge(pCsr, p, aSlot[i], &p);
+ aSlot[i] = 0;
+ }
+ aSlot[i] = p;
+ p = pNext;
+ }
+
+ p = 0;
+ for(i=0; i<64; i++){
+ vdbeSorterMerge(pCsr, p, aSlot[i], &p);
+ }
+ pSorter->pRecord = p;
+
+ sqlite3_free(aSlot);
+ return SQLITE_OK;
+}
+
+
+/*
+** Write the current contents of the in-memory linked-list to a PMA. Return
+** SQLITE_OK if successful, or an SQLite error code otherwise.
+**
+** The format of a PMA is:
+**
+** * A varint. This varint contains the total number of bytes of content
+** in the PMA (not including the varint itself).
+**
+** * One or more records packed end-to-end in order of ascending keys.
+** Each record consists of a varint followed by a blob of data (the
+** key). The varint is the number of bytes in the blob of data.
+*/
+static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
+ int rc = SQLITE_OK; /* Return code */
+ VdbeSorter *pSorter = pCsr->pSorter;
+
+ if( pSorter->nInMemory==0 ){
+ assert( pSorter->pRecord==0 );
+ return rc;
+ }
+
+ rc = vdbeSorterSort(pCsr);
+
+ /* If the first temporary PMA file has not been opened, open it now. */
+ if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
+ rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
+ assert( rc!=SQLITE_OK || pSorter->pTemp1 );
+ assert( pSorter->iWriteOff==0 );
+ assert( pSorter->nPMA==0 );
+ }
+
+ if( rc==SQLITE_OK ){
+ i64 iOff = pSorter->iWriteOff;
+ SorterRecord *p;
+ SorterRecord *pNext = 0;
+ static const char eightZeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ pSorter->nPMA++;
+ rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nInMemory, &iOff);
+ for(p=pSorter->pRecord; rc==SQLITE_OK && p; p=pNext){
+ pNext = p->pNext;
+ rc = vdbeSorterWriteVarint(pSorter->pTemp1, p->nVal, &iOff);
+
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsWrite(pSorter->pTemp1, p->pVal, p->nVal, iOff);
+ iOff += p->nVal;
+ }
+
+ sqlite3DbFree(db, p);
+ }
+
+ /* This assert verifies that unless an error has occurred, the size of
+ ** the PMA on disk is the same as the expected size stored in
+ ** pSorter->nInMemory. */
+ assert( rc!=SQLITE_OK || pSorter->nInMemory==(
+ iOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nInMemory)
+ ));
+
+ pSorter->iWriteOff = iOff;
+ if( rc==SQLITE_OK ){
+ /* Terminate each file with 8 extra bytes so that from any offset
+ ** in the file we can always read 9 bytes without a SHORT_READ error */
+ rc = sqlite3OsWrite(pSorter->pTemp1, eightZeros, 8, iOff);
+ }
+ pSorter->pRecord = p;
+ }
+
+ return rc;
+}
+
+/*
+** Add a record to the sorter.
+*/
+int sqlite3VdbeSorterWrite(
+ sqlite3 *db, /* Database handle */
+ VdbeCursor *pCsr, /* Sorter cursor */
+ Mem *pVal /* Memory cell containing record */
+){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int rc = SQLITE_OK; /* Return Code */
+ SorterRecord *pNew; /* New list element */
+
+ assert( pSorter );
+ pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n;
+
+ pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord));
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pNew->pVal = (void *)&pNew[1];
+ memcpy(pNew->pVal, pVal->z, pVal->n);
+ pNew->nVal = pVal->n;
+ pNew->pNext = pSorter->pRecord;
+ pSorter->pRecord = pNew;
+ }
+
+ /* See if the contents of the sorter should now be written out. They
+ ** are written out when either of the following are true:
+ **
+ ** * The total memory allocated for the in-memory list is greater
+ ** than (page-size * cache-size), or
+ **
+ ** * The total memory allocated for the in-memory list is greater
+ ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
+ */
+ if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && (
+ (pSorter->nInMemory>pSorter->mxPmaSize)
+ || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
+ )){
+ rc = vdbeSorterListToPMA(db, pCsr);
+ pSorter->nInMemory = 0;
+ }
+
+ return rc;
+}
+
+/*
+** Helper function for sqlite3VdbeSorterRewind().
+*/
+static int vdbeSorterInitMerge(
+ sqlite3 *db, /* Database handle */
+ VdbeCursor *pCsr, /* Cursor handle for this sorter */
+ i64 *pnByte /* Sum of bytes in all opened PMAs */
+){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int rc = SQLITE_OK; /* Return code */
+ int i; /* Used to iterator through aIter[] */
+ i64 nByte = 0; /* Total bytes in all opened PMAs */
+
+ /* Initialize the iterators. */
+ for(i=0; iaIter[i];
+ rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
+ pSorter->iReadOff = pIter->iEof;
+ assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff );
+ if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break;
+ }
+
+ /* Initialize the aTree[] array. */
+ for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
+ rc = vdbeSorterDoCompare(pCsr, i);
+ }
+
+ *pnByte = nByte;
+ return rc;
+}
+
+/*
+** Once the sorter has been populated, this function is called to prepare
+** for iterating through its contents in sorted order.
+*/
+int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int rc; /* Return code */
+ sqlite3_file *pTemp2 = 0; /* Second temp file to use */
+ i64 iWrite2 = 0; /* Write offset for pTemp2 */
+ int nIter; /* Number of iterators used */
+ int nByte; /* Bytes of space required for aIter/aTree */
+ int N = 2; /* Power of 2 >= nIter */
+
+ assert( pSorter );
+
+ /* If no data has been written to disk, then do not do so now. Instead,
+ ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly
+ ** from the in-memory list. */
+ if( pSorter->nPMA==0 ){
+ *pbEof = !pSorter->pRecord;
+ assert( pSorter->aTree==0 );
+ return vdbeSorterSort(pCsr);
+ }
+
+ /* Write the current b-tree to a PMA. Close the b-tree cursor. */
+ rc = vdbeSorterListToPMA(db, pCsr);
+ if( rc!=SQLITE_OK ) return rc;
+
+ /* Allocate space for aIter[] and aTree[]. */
+ nIter = pSorter->nPMA;
+ if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
+ assert( nIter>0 );
+ while( NaIter = (VdbeSorterIter *)sqlite3DbMallocZero(db, nByte);
+ if( !pSorter->aIter ) return SQLITE_NOMEM;
+ pSorter->aTree = (int *)&pSorter->aIter[N];
+ pSorter->nTree = N;
+
+ do {
+ int iNew; /* Index of new, merged, PMA */
+
+ for(iNew=0;
+ rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNTnPMA;
+ iNew++
+ ){
+ i64 nWrite; /* Number of bytes in new PMA */
+
+ /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1,
+ ** initialize an iterator for each of them and break out of the loop.
+ ** These iterators will be incrementally merged as the VDBE layer calls
+ ** sqlite3VdbeSorterNext().
+ **
+ ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs,
+ ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs
+ ** are merged into a single PMA that is written to file pTemp2.
+ */
+ rc = vdbeSorterInitMerge(db, pCsr, &nWrite);
+ assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile );
+ if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
+ break;
+ }
+
+ /* Open the second temp file, if it is not already open. */
+ if( pTemp2==0 ){
+ assert( iWrite2==0 );
+ rc = vdbeSorterOpenTempFile(db, &pTemp2);
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = vdbeSorterWriteVarint(pTemp2, nWrite, &iWrite2);
+ }
+
+ if( rc==SQLITE_OK ){
+ int bEof = 0;
+ while( rc==SQLITE_OK && bEof==0 ){
+ int nToWrite;
+ VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ];
+ assert( pIter->pFile );
+ nToWrite = pIter->nKey + sqlite3VarintLen(pIter->nKey);
+ rc = sqlite3OsWrite(pTemp2, pIter->aAlloc, nToWrite, iWrite2);
+ iWrite2 += nToWrite;
+ if( rc==SQLITE_OK ){
+ rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
+ }
+ }
+ }
+ }
+
+ if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
+ break;
+ }else{
+ sqlite3_file *pTmp = pSorter->pTemp1;
+ pSorter->nPMA = iNew;
+ pSorter->pTemp1 = pTemp2;
+ pTemp2 = pTmp;
+ pSorter->iWriteOff = iWrite2;
+ pSorter->iReadOff = 0;
+ iWrite2 = 0;
+ }
+ }while( rc==SQLITE_OK );
+
+ if( pTemp2 ){
+ sqlite3OsCloseFree(pTemp2);
+ }
+ *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
+ return rc;
+}
+
+/*
+** Advance to the next element in the sorter.
+*/
+int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int rc; /* Return code */
+
+ if( pSorter->aTree ){
+ int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
+ int i; /* Index of aTree[] to recalculate */
+
+ rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
+ for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
+ rc = vdbeSorterDoCompare(pCsr, i);
+ }
+
+ *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
+ }else{
+ SorterRecord *pFree = pSorter->pRecord;
+ pSorter->pRecord = pFree->pNext;
+ pFree->pNext = 0;
+ vdbeSorterRecordFree(db, pFree);
+ *pbEof = !pSorter->pRecord;
+ rc = SQLITE_OK;
+ }
+ return rc;
+}
+
+/*
+** Return a pointer to a buffer owned by the sorter that contains the
+** current key.
+*/
+static void *vdbeSorterRowkey(
+ VdbeSorter *pSorter, /* Sorter object */
+ int *pnKey /* OUT: Size of current key in bytes */
+){
+ void *pKey;
+ if( pSorter->aTree ){
+ VdbeSorterIter *pIter;
+ pIter = &pSorter->aIter[ pSorter->aTree[1] ];
+ *pnKey = pIter->nKey;
+ pKey = pIter->aKey;
+ }else{
+ *pnKey = pSorter->pRecord->nVal;
+ pKey = pSorter->pRecord->pVal;
+ }
+ return pKey;
+}
+
+/*
+** Copy the current sorter key into the memory cell pOut.
+*/
+int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ void *pKey; int nKey; /* Sorter key to copy into pOut */
+
+ pKey = vdbeSorterRowkey(pSorter, &nKey);
+ if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){
+ return SQLITE_NOMEM;
+ }
+ pOut->n = nKey;
+ MemSetTypeFlag(pOut, MEM_Blob);
+ memcpy(pOut->z, pKey, nKey);
+
+ return SQLITE_OK;
+}
+
+/*
+** Compare the key in memory cell pVal with the key that the sorter cursor
+** passed as the first argument currently points to. For the purposes of
+** the comparison, ignore the rowid field at the end of each record.
+**
+** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
+** Otherwise, set *pRes to a negative, zero or positive value if the
+** key in pVal is smaller than, equal to or larger than the current sorter
+** key.
+*/
+int sqlite3VdbeSorterCompare(
+ VdbeCursor *pCsr, /* Sorter cursor */
+ Mem *pVal, /* Value to compare to current sorter key */
+ int *pRes /* OUT: Result of comparison */
+){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ void *pKey; int nKey; /* Sorter key to compare pVal with */
+
+ pKey = vdbeSorterRowkey(pSorter, &nKey);
+ vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
+ return SQLITE_OK;
+}
+
+#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
diff --git a/src/vtab.c b/src/vtab.c
index 223ef4e7..8119cb55 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -891,7 +891,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
for(i=0; rc==SQLITE_OK && inVTrans; i++){
VTable *pVTab = db->aVTrans[i];
const sqlite3_module *pMod = pVTab->pMod->pModule;
- if( pMod->iVersion>=2 ){
+ if( pVTab->pVtab && pMod->iVersion>=2 ){
int (*xMethod)(sqlite3_vtab *, int);
switch( op ){
case SAVEPOINT_BEGIN:
@@ -906,7 +906,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
break;
}
if( xMethod && pVTab->iSavepoint>iSavepoint ){
- rc = xMethod(db->aVTrans[i]->pVtab, iSavepoint);
+ rc = xMethod(pVTab->pVtab, iSavepoint);
}
}
}
diff --git a/src/wal.c b/src/wal.c
index b9a03dff..f2b31871 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -1804,13 +1804,15 @@ int sqlite3WalClose(
*/
rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
if( rc==SQLITE_OK ){
+ int bPersistWal = -1;
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
}
rc = sqlite3WalCheckpoint(
pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
);
- if( rc==SQLITE_OK ){
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal);
+ if( rc==SQLITE_OK && bPersistWal!=1 ){
isDelete = 1;
}
}
@@ -2341,7 +2343,7 @@ int sqlite3WalRead(
int sz;
i64 iOffset;
sz = pWal->hdr.szPage;
- sz = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
+ sz = (sz&0xfe00) + ((sz&0x0001)<<16);
testcase( sz<=32768 );
testcase( sz>=65536 );
iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
diff --git a/src/where.c b/src/where.c
index cf30d94d..05414da5 100644
--- a/src/where.c
+++ b/src/where.c
@@ -118,21 +118,31 @@ struct WhereTerm {
#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
#else
-# define TERM_VNULL 0x00 /* Disabled if not using stat2 */
+# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
#endif
/*
** An instance of the following structure holds all information about a
** WHERE clause. Mostly this is a container for one or more WhereTerms.
+**
+** Explanation of pOuter: For a WHERE clause of the form
+**
+** a AND ((b AND c) OR (d AND e)) AND f
+**
+** There are separate WhereClause objects for the whole clause and for
+** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the
+** subclauses points to the WhereClause object for the whole clause.
*/
struct WhereClause {
Parse *pParse; /* The parser context */
WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */
Bitmask vmask; /* Bitmask identifying virtual table cursors */
+ WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
+ u16 wctrlFlags; /* Might include WHERE_AND_ONLY */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
@@ -253,6 +263,7 @@ struct WhereCost {
#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
+#define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */
/*
** Initialize a preallocated WhereClause structure.
@@ -260,14 +271,17 @@ struct WhereCost {
static void whereClauseInit(
WhereClause *pWC, /* The WhereClause to be initialized */
Parse *pParse, /* The parsing context */
- WhereMaskSet *pMaskSet /* Mapping from table cursor numbers to bitmasks */
+ WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmasks */
+ u16 wctrlFlags /* Might include WHERE_AND_ONLY */
){
pWC->pParse = pParse;
pWC->pMaskSet = pMaskSet;
+ pWC->pOuter = 0;
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
pWC->vmask = 0;
+ pWC->wctrlFlags = wctrlFlags;
}
/* Forward reference */
@@ -466,11 +480,19 @@ static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){
static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
Bitmask mask = 0;
while( pS ){
+ SrcList *pSrc = pS->pSrc;
mask |= exprListTableUsage(pMaskSet, pS->pEList);
mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
mask |= exprTableUsage(pMaskSet, pS->pWhere);
mask |= exprTableUsage(pMaskSet, pS->pHaving);
+ if( ALWAYS(pSrc!=0) ){
+ int i;
+ for(i=0; inSrc; i++){
+ mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect);
+ mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn);
+ }
+ }
pS = pS->pPrior;
}
return mask;
@@ -575,36 +597,38 @@ static WhereTerm *findTerm(
int k;
assert( iCur>=0 );
op &= WO_ALL;
- for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
- if( pTerm->leftCursor==iCur
- && (pTerm->prereqRight & notReady)==0
- && pTerm->u.leftColumn==iColumn
- && (pTerm->eOperator & op)!=0
- ){
- if( pIdx && pTerm->eOperator!=WO_ISNULL ){
- Expr *pX = pTerm->pExpr;
- CollSeq *pColl;
- char idxaff;
- int j;
- Parse *pParse = pWC->pParse;
-
- idxaff = pIdx->pTable->aCol[iColumn].affinity;
- if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
-
- /* Figure out the collation sequence required from an index for
- ** it to be useful for optimising expression pX. Store this
- ** value in variable pColl.
- */
- assert(pX->pLeft);
- pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
- assert(pColl || pParse->nErr);
-
- for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
- if( NEVER(j>=pIdx->nColumn) ) return 0;
+ for(; pWC; pWC=pWC->pOuter){
+ for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
+ if( pTerm->leftCursor==iCur
+ && (pTerm->prereqRight & notReady)==0
+ && pTerm->u.leftColumn==iColumn
+ && (pTerm->eOperator & op)!=0
+ ){
+ if( pIdx && pTerm->eOperator!=WO_ISNULL ){
+ Expr *pX = pTerm->pExpr;
+ CollSeq *pColl;
+ char idxaff;
+ int j;
+ Parse *pParse = pWC->pParse;
+
+ idxaff = pIdx->pTable->aCol[iColumn].affinity;
+ if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
+
+ /* Figure out the collation sequence required from an index for
+ ** it to be useful for optimising expression pX. Store this
+ ** value in variable pColl.
+ */
+ assert(pX->pLeft);
+ pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
+ assert(pColl || pParse->nErr);
+
+ for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
+ if( NEVER(j>=pIdx->nColumn) ) return 0;
+ }
+ if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
}
- if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
+ return pTerm;
}
- return pTerm;
}
}
return 0;
@@ -681,7 +705,7 @@ static int isLikeOrGlob(
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
z = (char *)sqlite3_value_text(pVal);
}
- sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); /* IMP: R-23257-02778 */
+ sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
}else if( op==TK_STRING ){
z = pRight->u.zToken;
@@ -699,7 +723,7 @@ static int isLikeOrGlob(
*ppPrefix = pPrefix;
if( op==TK_VARIABLE ){
Vdbe *v = pParse->pVdbe;
- sqlite3VdbeSetVarmask(v, pRight->iColumn); /* IMP: R-23257-02778 */
+ sqlite3VdbeSetVarmask(v, pRight->iColumn);
if( *pisComplete && pRight->u.zToken[1] ){
/* If the rhs of the LIKE expression is a variable, and the current
** value of the variable means there is no need to invoke the LIKE
@@ -868,7 +892,7 @@ static void exprAnalyzeOrTerm(
if( pOrInfo==0 ) return;
pTerm->wtFlags |= TERM_ORINFO;
pOrWc = &pOrInfo->wc;
- whereClauseInit(pOrWc, pWC->pParse, pMaskSet);
+ whereClauseInit(pOrWc, pWC->pParse, pMaskSet, pWC->wctrlFlags);
whereSplit(pOrWc, pExpr, TK_OR);
exprAnalyzeAll(pSrc, pOrWc);
if( db->mallocFailed ) return;
@@ -895,9 +919,10 @@ static void exprAnalyzeOrTerm(
pOrTerm->wtFlags |= TERM_ANDINFO;
pOrTerm->eOperator = WO_AND;
pAndWC = &pAndInfo->wc;
- whereClauseInit(pAndWC, pWC->pParse, pMaskSet);
+ whereClauseInit(pAndWC, pWC->pParse, pMaskSet, pWC->wctrlFlags);
whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
exprAnalyzeAll(pSrc, pAndWC);
+ pAndWC->pOuter = pWC;
testcase( db->mallocFailed );
if( !db->mallocFailed ){
for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){
@@ -1331,8 +1356,8 @@ static void exprAnalyze(
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
-#ifdef SQLITE_ENABLE_STAT2
- /* When sqlite_stat2 histogram data is available an operator of the
+#ifdef SQLITE_ENABLE_STAT3
+ /* When sqlite_stat3 histogram data is available an operator of the
** form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form.
@@ -1370,7 +1395,7 @@ static void exprAnalyze(
pNewTerm->prereqAll = pTerm->prereqAll;
}
}
-#endif /* SQLITE_ENABLE_STAT2 */
+#endif /* SQLITE_ENABLE_STAT */
/* Prevent ON clause terms of a LEFT JOIN from being used to drive
** an index for tables to the left of the join.
@@ -1397,6 +1422,162 @@ static int referencesOtherTables(
return 0;
}
+/*
+** This function searches the expression list passed as the second argument
+** for an expression of type TK_COLUMN that refers to the same column and
+** uses the same collation sequence as the iCol'th column of index pIdx.
+** Argument iBase is the cursor number used for the table that pIdx refers
+** to.
+**
+** If such an expression is found, its index in pList->a[] is returned. If
+** no expression is found, -1 is returned.
+*/
+static int findIndexCol(
+ Parse *pParse, /* Parse context */
+ ExprList *pList, /* Expression list to search */
+ int iBase, /* Cursor for table associated with pIdx */
+ Index *pIdx, /* Index to match column of */
+ int iCol /* Column of index to match */
+){
+ int i;
+ const char *zColl = pIdx->azColl[iCol];
+
+ for(i=0; inExpr; i++){
+ Expr *p = pList->a[i].pExpr;
+ if( p->op==TK_COLUMN
+ && p->iColumn==pIdx->aiColumn[iCol]
+ && p->iTable==iBase
+ ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
+ if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/*
+** This routine determines if pIdx can be used to assist in processing a
+** DISTINCT qualifier. In other words, it tests whether or not using this
+** index for the outer loop guarantees that rows with equal values for
+** all expressions in the pDistinct list are delivered grouped together.
+**
+** For example, the query
+**
+** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
+**
+** can benefit from any index on columns "b" and "c".
+*/
+static int isDistinctIndex(
+ Parse *pParse, /* Parsing context */
+ WhereClause *pWC, /* The WHERE clause */
+ Index *pIdx, /* The index being considered */
+ int base, /* Cursor number for the table pIdx is on */
+ ExprList *pDistinct, /* The DISTINCT expressions */
+ int nEqCol /* Number of index columns with == */
+){
+ Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
+ int i; /* Iterator variable */
+
+ if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
+ testcase( pDistinct->nExpr==BMS-1 );
+
+ /* Loop through all the expressions in the distinct list. If any of them
+ ** are not simple column references, return early. Otherwise, test if the
+ ** WHERE clause contains a "col=X" clause. If it does, the expression
+ ** can be ignored. If it does not, and the column does not belong to the
+ ** same table as index pIdx, return early. Finally, if there is no
+ ** matching "col=X" expression and the column is on the same table as pIdx,
+ ** set the corresponding bit in variable mask.
+ */
+ for(i=0; inExpr; i++){
+ WhereTerm *pTerm;
+ Expr *p = pDistinct->a[i].pExpr;
+ if( p->op!=TK_COLUMN ) return 0;
+ pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
+ if( pTerm ){
+ Expr *pX = pTerm->pExpr;
+ CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
+ CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
+ if( p1==p2 ) continue;
+ }
+ if( p->iTable!=base ) return 0;
+ mask |= (((Bitmask)1) << i);
+ }
+
+ for(i=nEqCol; mask && inColumn; i++){
+ int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
+ if( iExpr<0 ) break;
+ mask &= ~(((Bitmask)1) << iExpr);
+ }
+
+ return (mask==0);
+}
+
+
+/*
+** Return true if the DISTINCT expression-list passed as the third argument
+** is redundant. A DISTINCT list is redundant if the database contains a
+** UNIQUE index that guarantees that the result of the query will be distinct
+** anyway.
+*/
+static int isDistinctRedundant(
+ Parse *pParse,
+ SrcList *pTabList,
+ WhereClause *pWC,
+ ExprList *pDistinct
+){
+ Table *pTab;
+ Index *pIdx;
+ int i;
+ int iBase;
+
+ /* If there is more than one table or sub-select in the FROM clause of
+ ** this query, then it will not be possible to show that the DISTINCT
+ ** clause is redundant. */
+ if( pTabList->nSrc!=1 ) return 0;
+ iBase = pTabList->a[0].iCursor;
+ pTab = pTabList->a[0].pTab;
+
+ /* If any of the expressions is an IPK column on table iBase, then return
+ ** true. Note: The (p->iTable==iBase) part of this test may be false if the
+ ** current SELECT is a correlated sub-query.
+ */
+ for(i=0; inExpr; i++){
+ Expr *p = pDistinct->a[i].pExpr;
+ if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
+ }
+
+ /* Loop through all indices on the table, checking each to see if it makes
+ ** the DISTINCT qualifier redundant. It does so if:
+ **
+ ** 1. The index is itself UNIQUE, and
+ **
+ ** 2. All of the columns in the index are either part of the pDistinct
+ ** list, or else the WHERE clause contains a term of the form "col=X",
+ ** where X is a constant value. The collation sequences of the
+ ** comparison and select-list expressions must match those of the index.
+ */
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->onError==OE_None ) continue;
+ for(i=0; inColumn; i++){
+ int iCol = pIdx->aiColumn[i];
+ if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx)
+ && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i)
+ ){
+ break;
+ }
+ }
+ if( i==pIdx->nColumn ){
+ /* This index implies that the DISTINCT qualifier is redundant. */
+ return 1;
+ }
+ }
+
+ return 0;
+}
/*
** This routine decides if pIdx can be used to satisfy the ORDER BY
@@ -1433,7 +1614,10 @@ static int isSortingIndex(
struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
sqlite3 *db = pParse->db;
- assert( pOrderBy!=0 );
+ if( !pOrderBy ) return 0;
+ if( wsFlags & WHERE_COLUMN_IN ) return 0;
+ if( pIdx->bUnordered ) return 0;
+
nTerm = pOrderBy->nExpr;
assert( nTerm>0 );
@@ -1633,11 +1817,14 @@ static void bestOrClauseIndex(
WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */
WhereTerm *pTerm; /* A single term of the WHERE clause */
- /* No OR-clause optimization allowed if the INDEXED BY or NOT INDEXED clauses
- ** are used */
+ /* The OR-clause optimization is disallowed if the INDEXED BY or
+ ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */
if( pSrc->notIndexed || pSrc->pIndex!=0 ){
return;
}
+ if( pWC->wctrlFlags & WHERE_AND_ONLY ){
+ return;
+ }
/* Search the WHERE clause terms for a usable WO_OR term. */
for(pTerm=pWC->a; pTermpParse;
tempWC.pMaskSet = pWC->pMaskSet;
+ tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.a = pOrTerm;
+ tempWC.wctrlFlags = 0;
tempWC.nTerm = 1;
bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost);
}else{
@@ -1746,6 +1935,10 @@ static void bestAutomaticIndex(
WhereTerm *pWCEnd; /* End of pWC->a[] */
Table *pTable; /* Table tht might be indexed */
+ if( pParse->nQueryLoop<=(double)1 ){
+ /* There is no point in building an automatic index for a single scan */
+ return;
+ }
if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
/* Automatic indices are disabled at run-time */
return;
@@ -1758,6 +1951,10 @@ static void bestAutomaticIndex(
/* The NOT INDEXED clause appears in the SQL. */
return;
}
+ if( pSrc->isCorrelated ){
+ /* The source is a correlated sub-query. No point in indexing it. */
+ return;
+ }
assert( pParse->nQueryLoop >= (double)1 );
pTable = pSrc->pTab;
@@ -1826,8 +2023,7 @@ static void constructAutomaticIndex(
v = pParse->pVdbe;
assert( v!=0 );
regIsInit = ++pParse->nMem;
- addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
+ addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
/* Count the number of columns that will be added to the index
** and used to match WHERE clause constraints */
@@ -1974,6 +2170,7 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator==WO_IN );
testcase( pTerm->eOperator==WO_ISNULL );
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
nTerm++;
}
@@ -2024,6 +2221,7 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator==WO_IN );
testcase( pTerm->eOperator==WO_ISNULL );
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
pIdxCons[j].iColumn = pTerm->u.leftColumn;
pIdxCons[j].iTermOffset = i;
pIdxCons[j].op = (u8)pTerm->eOperator;
@@ -2250,67 +2448,85 @@ static void bestVirtualIndex(
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+#ifdef SQLITE_ENABLE_STAT3
/*
-** Argument pIdx is a pointer to an index structure that has an array of
-** SQLITE_INDEX_SAMPLES evenly spaced samples of the first indexed column
-** stored in Index.aSample. These samples divide the domain of values stored
-** the index into (SQLITE_INDEX_SAMPLES+1) regions.
-** Region 0 contains all values less than the first sample value. Region
-** 1 contains values between the first and second samples. Region 2 contains
-** values between samples 2 and 3. And so on. Region SQLITE_INDEX_SAMPLES
-** contains values larger than the last sample.
+** Estimate the location of a particular key among all keys in an
+** index. Store the results in aStat as follows:
**
-** If the index contains many duplicates of a single value, then it is
-** possible that two or more adjacent samples can hold the same value.
-** When that is the case, the smallest possible region code is returned
-** when roundUp is false and the largest possible region code is returned
-** when roundUp is true.
+** aStat[0] Est. number of rows less than pVal
+** aStat[1] Est. number of rows equal to pVal
**
-** If successful, this function determines which of the regions value
-** pVal lies in, sets *piRegion to the region index (a value between 0
-** and SQLITE_INDEX_SAMPLES+1, inclusive) and returns SQLITE_OK.
-** Or, if an OOM occurs while converting text values between encodings,
-** SQLITE_NOMEM is returned and *piRegion is undefined.
+** Return SQLITE_OK on success.
*/
-#ifdef SQLITE_ENABLE_STAT2
-static int whereRangeRegion(
+static int whereKeyStats(
Parse *pParse, /* Database connection */
Index *pIdx, /* Index to consider domain of */
sqlite3_value *pVal, /* Value to consider */
- int roundUp, /* Return largest valid region if true */
- int *piRegion /* OUT: Region of domain in which value lies */
+ int roundUp, /* Round up if true. Round down if false */
+ tRowcnt *aStat /* OUT: stats written here */
){
- assert( roundUp==0 || roundUp==1 );
- if( ALWAYS(pVal) ){
- IndexSample *aSample = pIdx->aSample;
- int i = 0;
- int eType = sqlite3_value_type(pVal);
+ tRowcnt n;
+ IndexSample *aSample;
+ int i, eType;
+ int isEq = 0;
+ i64 v;
+ double r, rS;
- if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
- double r = sqlite3_value_double(pVal);
- for(i=0; i=SQLITE_TEXT ) break;
- if( roundUp ){
- if( aSample[i].u.r>r ) break;
- }else{
- if( aSample[i].u.r>=r ) break;
+ assert( roundUp==0 || roundUp==1 );
+ assert( pIdx->nSample>0 );
+ if( pVal==0 ) return SQLITE_ERROR;
+ n = pIdx->aiRowEst[0];
+ aSample = pIdx->aSample;
+ eType = sqlite3_value_type(pVal);
+
+ if( eType==SQLITE_INTEGER ){
+ v = sqlite3_value_int64(pVal);
+ r = (i64)v;
+ for(i=0; inSample; i++){
+ if( aSample[i].eType==SQLITE_NULL ) continue;
+ if( aSample[i].eType>=SQLITE_TEXT ) break;
+ if( aSample[i].eType==SQLITE_INTEGER ){
+ if( aSample[i].u.i>=v ){
+ isEq = aSample[i].u.i==v;
+ break;
+ }
+ }else{
+ assert( aSample[i].eType==SQLITE_FLOAT );
+ if( aSample[i].u.r>=r ){
+ isEq = aSample[i].u.r==r;
+ break;
}
}
- }else if( eType==SQLITE_NULL ){
- i = 0;
- if( roundUp ){
- while( inSample; i++){
+ if( aSample[i].eType==SQLITE_NULL ) continue;
+ if( aSample[i].eType>=SQLITE_TEXT ) break;
+ if( aSample[i].eType==SQLITE_FLOAT ){
+ rS = aSample[i].u.r;
+ }else{
+ rS = aSample[i].u.i;
}
- }else{
+ if( rS>=r ){
+ isEq = rS==r;
+ break;
+ }
+ }
+ }else if( eType==SQLITE_NULL ){
+ i = 0;
+ if( aSample[0].eType==SQLITE_NULL ) isEq = 1;
+ }else{
+ assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
+ for(i=0; inSample; i++){
+ if( aSample[i].eType==SQLITE_TEXT || aSample[i].eType==SQLITE_BLOB ){
+ break;
+ }
+ }
+ if( inSample ){
sqlite3 *db = pParse->db;
CollSeq *pColl;
const u8 *z;
- int n;
-
- /* pVal comes from sqlite3ValueFromExpr() so the type cannot be NULL */
- assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
-
if( eType==SQLITE_BLOB ){
z = (const u8 *)sqlite3_value_blob(pVal);
pColl = db->pDfltColl;
@@ -2329,12 +2545,12 @@ static int whereRangeRegion(
assert( z && pColl && pColl->xCmp );
}
n = sqlite3ValueBytes(pVal, pColl->enc);
-
- for(i=0; inSample; i++){
int c;
int eSampletype = aSample[i].eType;
- if( eSampletype==SQLITE_NULL || eSampletypeenc!=SQLITE_UTF8 ){
int nSample;
@@ -2352,16 +2568,47 @@ static int whereRangeRegion(
{
c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
}
- if( c-roundUp>=0 ) break;
+ if( c>=0 ){
+ if( c==0 ) isEq = 1;
+ break;
+ }
}
}
+ }
- assert( i>=0 && i<=SQLITE_INDEX_SAMPLES );
- *piRegion = i;
+ /* At this point, aSample[i] is the first sample that is greater than
+ ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less
+ ** than pVal. If aSample[i]==pVal, then isEq==1.
+ */
+ if( isEq ){
+ assert( inSample );
+ aStat[0] = aSample[i].nLt;
+ aStat[1] = aSample[i].nEq;
+ }else{
+ tRowcnt iLower, iUpper, iGap;
+ if( i==0 ){
+ iLower = 0;
+ iUpper = aSample[0].nLt;
+ }else{
+ iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
+ iLower = aSample[i-1].nEq + aSample[i-1].nLt;
+ }
+ aStat[1] = pIdx->avgEq;
+ if( iLower>=iUpper ){
+ iGap = 0;
+ }else{
+ iGap = iUpper - iLower;
+ }
+ if( roundUp ){
+ iGap = (iGap*2)/3;
+ }else{
+ iGap = iGap/3;
+ }
+ aStat[0] = iLower + iGap;
}
return SQLITE_OK;
}
-#endif /* #ifdef SQLITE_ENABLE_STAT2 */
+#endif /* SQLITE_ENABLE_STAT3 */
/*
** If expression pExpr represents a literal value, set *pp to point to
@@ -2379,7 +2626,7 @@ static int whereRangeRegion(
**
** If an error occurs, return an error code. Otherwise, SQLITE_OK.
*/
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
static int valueFromExpr(
Parse *pParse,
Expr *pExpr,
@@ -2390,7 +2637,7 @@ static int valueFromExpr(
|| (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
){
int iVar = pExpr->iColumn;
- sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); /* IMP: R-23257-02778 */
+ sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
*pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
return SQLITE_OK;
}
@@ -2427,17 +2674,15 @@ static int valueFromExpr(
**
** then nEq should be passed 0.
**
-** The returned value is an integer between 1 and 100, inclusive. A return
-** value of 1 indicates that the proposed range scan is expected to visit
-** approximately 1/100th (1%) of the rows selected by the nEq equality
-** constraints (if any). A return value of 100 indicates that it is expected
-** that the range scan will visit every row (100%) selected by the equality
-** constraints.
+** The returned value is an integer divisor to reduce the estimated
+** search space. A return value of 1 means that range constraints are
+** no help at all. A return value of 2 means range constraints are
+** expected to reduce the search space by half. And so forth...
**
-** In the absence of sqlite_stat2 ANALYZE data, each range inequality
-** reduces the search space by 3/4ths. Hence a single constraint (x>?)
-** results in a return of 25 and a range constraint (x>? AND x) results
-** in a return of 6.
+** In the absence of sqlite_stat3 ANALYZE data, each range inequality
+** reduces the search space by a factor of 4. Hence a single constraint (x>?)
+** results in a return of 4 and a range constraint (x>? AND x) results
+** in a return of 16.
*/
static int whereRangeScanEst(
Parse *pParse, /* Parsing & code generating context */
@@ -2445,84 +2690,72 @@ static int whereRangeScanEst(
int nEq, /* index into p->aCol[] of the range-compared column */
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
- int *piEst /* OUT: Return value */
+ double *pRangeDiv /* OUT: Reduce search space by this divisor */
){
int rc = SQLITE_OK;
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
- if( nEq==0 && p->aSample ){
- sqlite3_value *pLowerVal = 0;
- sqlite3_value *pUpperVal = 0;
- int iEst;
- int iLower = 0;
- int iUpper = SQLITE_INDEX_SAMPLES;
- int roundUpUpper = 0;
- int roundUpLower = 0;
+ if( nEq==0 && p->nSample ){
+ sqlite3_value *pRangeVal;
+ tRowcnt iLower = 0;
+ tRowcnt iUpper = p->aiRowEst[0];
+ tRowcnt a[2];
u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
if( pLower ){
Expr *pExpr = pLower->pExpr->pRight;
- rc = valueFromExpr(pParse, pExpr, aff, &pLowerVal);
+ rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE );
- roundUpLower = (pLower->eOperator==WO_GT) ?1:0;
+ if( rc==SQLITE_OK
+ && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
+ ){
+ iLower = a[0];
+ if( pLower->eOperator==WO_GT ) iLower += a[1];
+ }
+ sqlite3ValueFree(pRangeVal);
}
if( rc==SQLITE_OK && pUpper ){
Expr *pExpr = pUpper->pExpr->pRight;
- rc = valueFromExpr(pParse, pExpr, aff, &pUpperVal);
+ rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE );
- roundUpUpper = (pUpper->eOperator==WO_LE) ?1:0;
- }
-
- if( rc!=SQLITE_OK || (pLowerVal==0 && pUpperVal==0) ){
- sqlite3ValueFree(pLowerVal);
- sqlite3ValueFree(pUpperVal);
- goto range_est_fallback;
- }else if( pLowerVal==0 ){
- rc = whereRangeRegion(pParse, p, pUpperVal, roundUpUpper, &iUpper);
- if( pLower ) iLower = iUpper/2;
- }else if( pUpperVal==0 ){
- rc = whereRangeRegion(pParse, p, pLowerVal, roundUpLower, &iLower);
- if( pUpper ) iUpper = (iLower + SQLITE_INDEX_SAMPLES + 1)/2;
- }else{
- rc = whereRangeRegion(pParse, p, pUpperVal, roundUpUpper, &iUpper);
- if( rc==SQLITE_OK ){
- rc = whereRangeRegion(pParse, p, pLowerVal, roundUpLower, &iLower);
+ if( rc==SQLITE_OK
+ && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
+ ){
+ iUpper = a[0];
+ if( pUpper->eOperator==WO_LE ) iUpper += a[1];
}
+ sqlite3ValueFree(pRangeVal);
}
- WHERETRACE(("range scan regions: %d..%d\n", iLower, iUpper));
-
- iEst = iUpper - iLower;
- testcase( iEst==SQLITE_INDEX_SAMPLES );
- assert( iEst<=SQLITE_INDEX_SAMPLES );
- if( iEst<1 ){
- *piEst = 50/SQLITE_INDEX_SAMPLES;
- }else{
- *piEst = (iEst*100)/SQLITE_INDEX_SAMPLES;
+ if( rc==SQLITE_OK ){
+ if( iUpper<=iLower ){
+ *pRangeDiv = (double)p->aiRowEst[0];
+ }else{
+ *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower);
+ }
+ WHERETRACE(("range scan regions: %u..%u div=%g\n",
+ (u32)iLower, (u32)iUpper, *pRangeDiv));
+ return SQLITE_OK;
}
- sqlite3ValueFree(pLowerVal);
- sqlite3ValueFree(pUpperVal);
- return rc;
}
-range_est_fallback:
#else
UNUSED_PARAMETER(pParse);
UNUSED_PARAMETER(p);
UNUSED_PARAMETER(nEq);
#endif
assert( pLower || pUpper );
- *piEst = 100;
- if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *piEst /= 4;
- if( pUpper ) *piEst /= 4;
+ *pRangeDiv = (double)1;
+ if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4;
+ if( pUpper ) *pRangeDiv *= (double)4;
return rc;
}
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
/*
** Estimate the number of rows that will be returned based on
** an equality constraint x=VALUE and where that VALUE occurs in
** the histogram data. This only works when x is the left-most
-** column of an index and sqlite_stat2 histogram data is available
+** column of an index and sqlite_stat3 histogram data is available
** for that index. When pExpr==NULL that means the constraint is
** "x IS NULL" instead of "x=VALUE".
**
@@ -2542,12 +2775,12 @@ static int whereEqualScanEst(
double *pnRow /* Write the revised row estimate here */
){
sqlite3_value *pRhs = 0; /* VALUE on right-hand side of pTerm */
- int iLower, iUpper; /* Range of histogram regions containing pRhs */
u8 aff; /* Column affinity */
int rc; /* Subfunction return code */
- double nRowEst; /* New estimate of the number of rows */
+ tRowcnt a[2]; /* Statistics */
assert( p->aSample!=0 );
+ assert( p->nSample>0 );
aff = p->pTable->aCol[p->aiColumn[0]].affinity;
if( pExpr ){
rc = valueFromExpr(pParse, pExpr, aff, &pRhs);
@@ -2556,26 +2789,18 @@ static int whereEqualScanEst(
pRhs = sqlite3ValueNew(pParse->db);
}
if( pRhs==0 ) return SQLITE_NOTFOUND;
- rc = whereRangeRegion(pParse, p, pRhs, 0, &iLower);
- if( rc ) goto whereEqualScanEst_cancel;
- rc = whereRangeRegion(pParse, p, pRhs, 1, &iUpper);
- if( rc ) goto whereEqualScanEst_cancel;
- WHERETRACE(("equality scan regions: %d..%d\n", iLower, iUpper));
- if( iLower>=iUpper ){
- nRowEst = p->aiRowEst[0]/(SQLITE_INDEX_SAMPLES*2);
- if( nRowEst<*pnRow ) *pnRow = nRowEst;
- }else{
- nRowEst = (iUpper-iLower)*p->aiRowEst[0]/SQLITE_INDEX_SAMPLES;
- *pnRow = nRowEst;
+ rc = whereKeyStats(pParse, p, pRhs, 0, a);
+ if( rc==SQLITE_OK ){
+ WHERETRACE(("equality scan regions: %d\n", (int)a[1]));
+ *pnRow = a[1];
}
-
whereEqualScanEst_cancel:
sqlite3ValueFree(pRhs);
return rc;
}
-#endif /* defined(SQLITE_ENABLE_STAT2) */
+#endif /* defined(SQLITE_ENABLE_STAT3) */
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
/*
** Estimate the number of rows that will be returned based on
** an IN constraint where the right-hand side of the IN operator
@@ -2598,60 +2823,25 @@ static int whereInScanEst(
ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
double *pnRow /* Write the revised row estimate here */
){
- sqlite3_value *pVal = 0; /* One value from list */
- int iLower, iUpper; /* Range of histogram regions containing pRhs */
- u8 aff; /* Column affinity */
- int rc = SQLITE_OK; /* Subfunction return code */
- double nRowEst; /* New estimate of the number of rows */
- int nSpan = 0; /* Number of histogram regions spanned */
- int nSingle = 0; /* Histogram regions hit by a single value */
- int nNotFound = 0; /* Count of values that are not constants */
- int i; /* Loop counter */
- u8 aSpan[SQLITE_INDEX_SAMPLES+1]; /* Histogram regions that are spanned */
- u8 aSingle[SQLITE_INDEX_SAMPLES+1]; /* Histogram regions hit once */
+ int rc = SQLITE_OK; /* Subfunction return code */
+ double nEst; /* Number of rows for a single term */
+ double nRowEst = (double)0; /* New estimate of the number of rows */
+ int i; /* Loop counter */
assert( p->aSample!=0 );
- aff = p->pTable->aCol[p->aiColumn[0]].affinity;
- memset(aSpan, 0, sizeof(aSpan));
- memset(aSingle, 0, sizeof(aSingle));
- for(i=0; inExpr; i++){
- sqlite3ValueFree(pVal);
- rc = valueFromExpr(pParse, pList->a[i].pExpr, aff, &pVal);
- if( rc ) break;
- if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
- nNotFound++;
- continue;
- }
- rc = whereRangeRegion(pParse, p, pVal, 0, &iLower);
- if( rc ) break;
- rc = whereRangeRegion(pParse, p, pVal, 1, &iUpper);
- if( rc ) break;
- if( iLower>=iUpper ){
- aSingle[iLower] = 1;
- }else{
- assert( iLower>=0 && iUpper<=SQLITE_INDEX_SAMPLES );
- while( iLowernExpr; i++){
+ nEst = p->aiRowEst[0];
+ rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst);
+ nRowEst += nEst;
}
if( rc==SQLITE_OK ){
- for(i=nSpan=0; i<=SQLITE_INDEX_SAMPLES; i++){
- if( aSpan[i] ){
- nSpan++;
- }else if( aSingle[i] ){
- nSingle++;
- }
- }
- nRowEst = (nSpan*2+nSingle)*p->aiRowEst[0]/(2*SQLITE_INDEX_SAMPLES)
- + nNotFound*p->aiRowEst[1];
if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
*pnRow = nRowEst;
- WHERETRACE(("IN row estimate: nSpan=%d, nSingle=%d, nNotFound=%d, est=%g\n",
- nSpan, nSingle, nNotFound, nRowEst));
+ WHERETRACE(("IN row estimate: est=%g\n", nRowEst));
}
- sqlite3ValueFree(pVal);
return rc;
}
-#endif /* defined(SQLITE_ENABLE_STAT2) */
+#endif /* defined(SQLITE_ENABLE_STAT3) */
/*
@@ -2689,6 +2879,7 @@ static void bestBtreeIndex(
Bitmask notReady, /* Mask of cursors not available for indexing */
Bitmask notValid, /* Cursors not available for any purpose */
ExprList *pOrderBy, /* The ORDER BY clause */
+ ExprList *pDistinct, /* The select-list if query is DISTINCT */
WhereCost *pCost /* Lowest cost query plan */
){
int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
@@ -2697,7 +2888,7 @@ static void bestBtreeIndex(
int eqTermMask; /* Current mask of valid equality operators */
int idxEqTermMask; /* Index mask of valid equality operators */
Index sPk; /* A fake index object for the primary key */
- unsigned int aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
+ tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
int wsFlagMask; /* Allowed flags in pCost->plan.wsFlag */
@@ -2752,10 +2943,10 @@ static void bestBtreeIndex(
/* Loop over all indices looking for the best one to use
*/
for(; pProbe; pIdx=pProbe=pProbe->pNext){
- const unsigned int * const aiRowEst = pProbe->aiRowEst;
+ const tRowcnt * const aiRowEst = pProbe->aiRowEst;
double cost; /* Cost of using pProbe */
double nRow; /* Estimated number of rows in result set */
- double log10N; /* base-10 logarithm of nRow (inexact) */
+ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */
int rev; /* True to scan in reverse order */
int wsFlags = 0;
Bitmask used = 0;
@@ -2795,14 +2986,12 @@ static void bestBtreeIndex(
** IN operator must be a SELECT, not a value list, for this variable
** to be true.
**
- ** estBound:
- ** An estimate on the amount of the table that must be searched. A
- ** value of 100 means the entire table is searched. Range constraints
- ** might reduce this to a value less than 100 to indicate that only
- ** a fraction of the table needs searching. In the absence of
- ** sqlite_stat2 ANALYZE data, a single inequality reduces the search
- ** space to 1/4rd its original size. So an x>? constraint reduces
- ** estBound to 25. Two constraints (x>? AND x) reduce estBound to 6.
+ ** rangeDiv:
+ ** An estimate of a divisor by which to reduce the search space due
+ ** to inequality constraints. In the absence of sqlite_stat3 ANALYZE
+ ** data, a single inequality reduces the search space to 1/4rd its
+ ** original size (rangeDiv==4). Two inequalities reduce the search
+ ** space to 1/16th of its original size (rangeDiv==16).
**
** bSort:
** Boolean. True if there is an ORDER BY clause that will require an
@@ -2827,12 +3016,13 @@ static void bestBtreeIndex(
int nEq; /* Number of == or IN terms matching index */
int bInEst = 0; /* True if "x IN (SELECT...)" seen */
int nInMul = 1; /* Number of distinct equalities to lookup */
- int estBound = 100; /* Estimated reduction in search space */
+ double rangeDiv = (double)1; /* Estimated reduction in search space */
int nBound = 0; /* Number of range constraints seen */
- int bSort = 0; /* True if external sort required */
+ int bSort = !!pOrderBy; /* True if external sort required */
+ int bDist = !!pDistinct; /* True if index cannot help with DISTINCT */
int bLookup = 0; /* True if not a covering index */
WhereTerm *pTerm; /* A single term of the WHERE clause */
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
WhereTerm *pFirstTerm = 0; /* First term matching the index */
#endif
@@ -2842,6 +3032,7 @@ static void bestBtreeIndex(
pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx);
if( pTerm==0 ) break;
wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
+ testcase( pTerm->pWC!=pWC );
if( pTerm->eOperator & WO_IN ){
Expr *pExpr = pTerm->pExpr;
wsFlags |= WHERE_COLUMN_IN;
@@ -2856,28 +3047,30 @@ static void bestBtreeIndex(
}else if( pTerm->eOperator & WO_ISNULL ){
wsFlags |= WHERE_COLUMN_NULL;
}
-#ifdef SQLITE_ENABLE_STAT2
+#ifdef SQLITE_ENABLE_STAT3
if( nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
#endif
used |= pTerm->prereqRight;
}
- /* Determine the value of estBound. */
+ /* Determine the value of rangeDiv */
if( nEqnColumn && pProbe->bUnordered==0 ){
int j = pProbe->aiColumn[nEq];
if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx);
WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx);
- whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &estBound);
+ whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &rangeDiv);
if( pTop ){
nBound = 1;
wsFlags |= WHERE_TOP_LIMIT;
used |= pTop->prereqRight;
+ testcase( pTop->pWC!=pWC );
}
if( pBtm ){
nBound++;
wsFlags |= WHERE_BTM_LIMIT;
used |= pBtm->prereqRight;
+ testcase( pBtm->pWC!=pWC );
}
wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
}
@@ -2893,17 +3086,20 @@ static void bestBtreeIndex(
** naturally scan rows in the required order, set the appropriate flags
** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
** will scan rows in a different order, set the bSort variable. */
- if( pOrderBy ){
- if( (wsFlags & WHERE_COLUMN_IN)==0
- && pProbe->bUnordered==0
- && isSortingIndex(pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy,
- nEq, wsFlags, &rev)
- ){
- wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
- wsFlags |= (rev ? WHERE_REVERSE : 0);
- }else{
- bSort = 1;
- }
+ if( isSortingIndex(
+ pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
+ ){
+ bSort = 0;
+ wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
+ wsFlags |= (rev ? WHERE_REVERSE : 0);
+ }
+
+ /* If there is a DISTINCT qualifier and this index will scan rows in
+ ** order of the DISTINCT expressions, clear bDist and set the appropriate
+ ** flags in wsFlags. */
+ if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
+ bDist = 0;
+ wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
}
/* If currently calculating the cost of using an index (not the IPK
@@ -2937,27 +3133,30 @@ static void bestBtreeIndex(
nInMul = (int)(nRow / aiRowEst[nEq]);
}
-#ifdef SQLITE_ENABLE_STAT2
- /* If the constraint is of the form x=VALUE and histogram
+#ifdef SQLITE_ENABLE_STAT3
+ /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
+ ** and we do not think that values of x are unique and if histogram
** data is available for column x, then it might be possible
** to get a better estimate on the number of rows based on
** VALUE and how common that value is according to the histogram.
*/
- if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
+ if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
+ assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
testcase( pFirstTerm->eOperator==WO_EQ );
testcase( pFirstTerm->eOperator==WO_ISNULL );
whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
- }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
+ }else if( bInEst==0 ){
+ assert( pFirstTerm->eOperator==WO_IN );
whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
}
}
-#endif /* SQLITE_ENABLE_STAT2 */
+#endif /* SQLITE_ENABLE_STAT3 */
/* Adjust the number of output rows and downward to reflect rows
** that are excluded by range constraints.
*/
- nRow = (nRow * (double)estBound) / (double)100;
+ nRow = nRow/rangeDiv;
if( nRow<1 ) nRow = 1;
/* Experiments run on real SQLite databases show that the time needed
@@ -2968,7 +3167,7 @@ static void bestBtreeIndex(
** slower with larger records, presumably because fewer records fit
** on one page and hence more pages have to be fetched.
**
- ** The ANALYZE command and the sqlite_stat1 and sqlite_stat2 tables do
+ ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do
** not give us data on the relative sizes of table and index records.
** So this computation assumes table records are about twice as big
** as index records
@@ -3020,6 +3219,9 @@ static void bestBtreeIndex(
if( bSort ){
cost += nRow*estLog(nRow)*3;
}
+ if( bDist ){
+ cost += nRow*estLog(nRow)*3;
+ }
/**** Cost of using this index has now been computed ****/
@@ -3083,10 +3285,10 @@ static void bestBtreeIndex(
WHERETRACE((
- "%s(%s): nEq=%d nInMul=%d estBound=%d bSort=%d bLookup=%d wsFlags=0x%x\n"
+ "%s(%s): nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%x\n"
" notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f used=0x%llx\n",
pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"),
- nEq, nInMul, estBound, bSort, bLookup, wsFlags,
+ nEq, nInMul, (int)rangeDiv, bSort, bLookup, wsFlags,
notReady, log10N, nRow, cost, used
));
@@ -3165,7 +3367,7 @@ static void bestIndex(
}else
#endif
{
- bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
+ bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
}
}
@@ -3590,7 +3792,8 @@ static Bitmask codeOneLoopStart(
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
- Bitmask notReady /* Which tables are currently available */
+ Bitmask notReady, /* Which tables are currently available */
+ Expr *pWhere /* Complete WHERE clause */
){
int j, k; /* Loop counters */
int iCur; /* The VDBE cursor for the table */
@@ -4072,7 +4275,8 @@ static Bitmask codeOneLoopStart(
int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
- int ii;
+ int ii; /* Loop counter */
+ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
pTerm = pLevel->plan.u.pTerm;
assert( pTerm!=0 );
@@ -4122,13 +4326,28 @@ static Bitmask codeOneLoopStart(
}
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
+ /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
+ ** Then for every term xN, evaluate as the subexpression: xN AND z
+ ** That way, terms in y that are factored into the disjunction will
+ ** be picked up by the recursive calls to sqlite3WhereBegin() below.
+ */
+ if( pWC->nTerm>1 ){
+ pAndExpr = sqlite3ExprAlloc(pParse->db, TK_AND, 0, 0);
+ pAndExpr->pRight = pWhere;
+ }
+
for(ii=0; iinTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
+ Expr *pOrExpr = pOrTerm->pExpr;
+ if( pAndExpr ){
+ pAndExpr->pLeft = pOrExpr;
+ pOrExpr = pAndExpr;
+ }
/* Loop through table entries that match term pOrTerm. */
- pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
- WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
+ pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
+ WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
if( pSubWInfo ){
explainOneScan(
@@ -4156,6 +4375,7 @@ static Bitmask codeOneLoopStart(
}
}
}
+ sqlite3DbFree(pParse->db, pAndExpr);
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
@@ -4368,6 +4588,7 @@ WhereInfo *sqlite3WhereBegin(
SrcList *pTabList, /* A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
+ ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
){
int i; /* Loop counter */
@@ -4428,11 +4649,15 @@ WhereInfo *sqlite3WhereBegin(
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
pMaskSet = (WhereMaskSet*)&pWC[1];
+ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
+ ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
+ if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
+
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator.
*/
initMaskSet(pMaskSet);
- whereClauseInit(pWC, pParse, pMaskSet);
+ whereClauseInit(pWC, pParse, pMaskSet, wctrlFlags);
sqlite3ExprCodeConstants(pParse, pWhere);
whereSplit(pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
@@ -4495,6 +4720,15 @@ WhereInfo *sqlite3WhereBegin(
goto whereBeginError;
}
+ /* Check if the DISTINCT qualifier, if there is one, is redundant.
+ ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
+ ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
+ */
+ if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
+ pDistinct = 0;
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ }
+
/* Chose the best index to use for each table in the FROM clause.
**
** This loop fills in the following fields:
@@ -4578,6 +4812,7 @@ WhereInfo *sqlite3WhereBegin(
int doNotReorder; /* True if this table should not be reordered */
WhereCost sCost; /* Cost information from best[Virtual]Index() */
ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
+ ExprList *pDist; /* DISTINCT clause for index to optimize */
doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
if( j!=iFrom && doNotReorder ) break;
@@ -4588,6 +4823,7 @@ WhereInfo *sqlite3WhereBegin(
}
mask = (isOptimal ? m : notReady);
pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
+ pDist = (i==0 ? pDistinct : 0);
if( pTabItem->pIndex==0 ) nUnconstrained++;
WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
@@ -4602,7 +4838,7 @@ WhereInfo *sqlite3WhereBegin(
#endif
{
bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
- &sCost);
+ pDist, &sCost);
}
assert( isOptimal || (sCost.used¬Ready)==0 );
@@ -4660,9 +4896,14 @@ WhereInfo *sqlite3WhereBegin(
WHERETRACE(("*** Optimizer selects table %d for loop %d"
" with cost=%g and nRow=%g\n",
bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
- if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){
+ /* The ALWAYS() that follows was added to hush up clang scan-build */
+ if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 && ALWAYS(ppOrderBy) ){
*ppOrderBy = 0;
}
+ if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
+ assert( pWInfo->eDistinct==0 );
+ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+ }
andFlags &= bestPlan.plan.wsFlags;
pLevel->plan = bestPlan.plan;
testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
@@ -4745,7 +4986,7 @@ WhereInfo *sqlite3WhereBegin(
}else
#endif
if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
- && (wctrlFlags & WHERE_OMIT_OPEN)==0 ){
+ && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
testcase( pTab->nCol==BMS-1 );
@@ -4790,7 +5031,7 @@ WhereInfo *sqlite3WhereBegin(
for(i=0; ia[i];
explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
- notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
+ notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere);
pWInfo->iContinue = pLevel->addrCont;
}
@@ -4925,7 +5166,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
assert( pTab!=0 );
if( (pTab->tabFlags & TF_Ephemeral)==0
&& pTab->pSelect==0
- && (pWInfo->wctrlFlags & WHERE_OMIT_CLOSE)==0
+ && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0
){
int ws = pLevel->plan.wsFlags;
if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
diff --git a/test/8_3_names.test b/test/8_3_names.test
index 418685e6..b53e28a9 100644
--- a/test/8_3_names.test
+++ b/test/8_3_names.test
@@ -67,8 +67,8 @@ do_test 8_3_names-2.1 {
file exists test.nal
} 1
forcedelete test2.db test2.nal test2.db-journal
-file copy test.db test2.db
-file copy test.nal test2.nal
+copy_file test.db test2.db
+copy_file test.nal test2.nal
do_test 8_3_names-2.2 {
db eval {
COMMIT;
@@ -101,8 +101,8 @@ do_test 8_3_names-3.1 {
file exists test.nal
} 0
forcedelete test2.db test2.nal test2.db-journal
-file copy test.db test2.db
-file copy test.db-journal test2.db-journal
+copy_file test.db test2.db
+copy_file test.db-journal test2.db-journal
do_test 8_3_names-3.2 {
db eval {
COMMIT;
diff --git a/test/all.test b/test/all.test
index 96712466..54302d02 100644
--- a/test/all.test
+++ b/test/all.test
@@ -38,6 +38,7 @@ run_test_suite pcache10
run_test_suite pcache50
run_test_suite pcache90
run_test_suite pcache100
+run_test_suite prepare
if {$::tcl_platform(platform)=="unix"} {
ifcapable !default_autovacuum {
diff --git a/test/alter.test b/test/alter.test
index 359034d5..1481bc20 100644
--- a/test/alter.test
+++ b/test/alter.test
@@ -221,8 +221,8 @@ do_test alter-1.7 {
#
ifcapable attach {
do_test alter-1.8.1 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
ATTACH 'test2.db' AS aux;
}
@@ -412,8 +412,8 @@ do_test alter-3.1.8 {
# Make sure "ON" cannot be used as a database, table or column name without
# quoting. Otherwise the sqlite_alter_trigger() function might not work.
-file delete -force test3.db
-file delete -force test3.db-journal
+forcedelete test3.db
+forcedelete test3.db-journal
ifcapable attach {
do_test alter-3.2.1 {
catchsql {
@@ -846,7 +846,7 @@ do_test alter-14.2 {
set system_table_list {1 sqlite_master}
catchsql ANALYZE
ifcapable analyze { lappend system_table_list 2 sqlite_stat1 }
-ifcapable stat2 { lappend system_table_list 3 sqlite_stat2 }
+ifcapable stat3 { lappend system_table_list 4 sqlite_stat3 }
foreach {tn tbl} $system_table_list {
do_test alter-15.$tn.1 {
diff --git a/test/alter2.test b/test/alter2.test
index 712960c0..14be637f 100644
--- a/test/alter2.test
+++ b/test/alter2.test
@@ -137,6 +137,7 @@ do_test alter2-1.8 {
do_test alter2-1.9 {
# ALTER TABLE abc ADD COLUMN d;
alter_table abc {CREATE TABLE abc(a, b, c, d);}
+ if {[permutation] == "prepare"} { db cache flush }
execsql { SELECT * FROM abc; }
execsql {
UPDATE abc SET d = 11 WHERE c IS NULL AND a<4;
@@ -314,8 +315,8 @@ do_test alter2-6.1 {
} {2}
ifcapable attach {
do_test alter2-6.2 {
- file delete -force test2.db-journal
- file delete -force test2.db
+ forcedelete test2.db-journal
+ forcedelete test2.db
execsql {
ATTACH 'test2.db' AS aux;
CREATE TABLE aux.t1(a, b);
diff --git a/test/alter3.test b/test/alter3.test
index 74ba33c5..28d293e2 100644
--- a/test/alter3.test
+++ b/test/alter3.test
@@ -196,7 +196,7 @@ ifcapable schema_version {
do_test alter3-4.1 {
db close
- file delete -force test.db
+ forcedelete test.db
set ::DB [sqlite3 db test.db]
execsql {
PRAGMA legacy_file_format=ON;
@@ -237,8 +237,8 @@ do_test alter3-4.99 {
ifcapable attach {
do_test alter3-5.1 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 'one');
diff --git a/test/alter4.test b/test/alter4.test
index 738db3fd..cda45533 100644
--- a/test/alter4.test
+++ b/test/alter4.test
@@ -178,7 +178,7 @@ ifcapable schema_version {
do_test alter4-4.1 {
db close
- file delete -force test.db
+ forcedelete test.db
set ::DB [sqlite3 db test.db]
execsql {
CREATE TEMP TABLE t1(a, b);
@@ -213,8 +213,8 @@ do_test alter4-4.99 {
ifcapable attach {
do_test alter4-5.1 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
CREATE TEMP TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 'one');
diff --git a/test/analyze.test b/test/analyze.test
index 766cd50d..362702a9 100644
--- a/test/analyze.test
+++ b/test/analyze.test
@@ -287,6 +287,64 @@ do_test analyze-4.3 {
}
} {}
+# Verify that DROP TABLE and DROP INDEX remove entries from the
+# sqlite_stat1 and sqlite_stat3 tables.
+#
+do_test analyze-5.0 {
+ execsql {
+ DELETE FROM t3;
+ DELETE FROM t4;
+ INSERT INTO t3 VALUES(1,2,3,4);
+ INSERT INTO t3 VALUES(5,6,7,8);
+ INSERT INTO t3 SELECT a+8, b+8, c+8, d+8 FROM t3;
+ INSERT INTO t3 SELECT a+16, b+16, c+16, d+16 FROM t3;
+ INSERT INTO t3 SELECT a+32, b+32, c+32, d+32 FROM t3;
+ INSERT INTO t3 SELECT a+64, b+64, c+64, d+64 FROM t3;
+ INSERT INTO t4 SELECT a, b, c FROM t3;
+ ANALYZE;
+ SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
+ }
+} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
+ifcapable stat3 {
+ do_test analyze-5.1 {
+ execsql {
+ SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
+ }
+ } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
+}
+do_test analyze-5.2 {
+ execsql {
+ DROP INDEX t3i2;
+ SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
+ }
+} {t3i1 t3i3 t4i1 t4i2 t3 t4}
+ifcapable stat3 {
+ do_test analyze-5.3 {
+ execsql {
+ SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
+ }
+ } {t3i1 t3i3 t4i1 t4i2 t3 t4}
+}
+do_test analyze-5.4 {
+ execsql {
+ DROP TABLE t3;
+ SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
+ }
+} {t4i1 t4i2 t4}
+ifcapable stat3 {
+ do_test analyze-5.5 {
+ execsql {
+ SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+ SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
+ }
+ } {t4i1 t4i2 t4}
+}
+
# This test corrupts the database file so it must be the last test
# in the series.
#
diff --git a/test/analyze2.test b/test/analyze2.test
deleted file mode 100644
index de2567bb..00000000
--- a/test/analyze2.test
+++ /dev/null
@@ -1,554 +0,0 @@
-# 2009 August 06
-#
-# 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 the extra functionality provided by the ANALYZE
-# command when the library is compiled with SQLITE_ENABLE_STAT2 defined.
-#
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-ifcapable !stat2 {
- finish_test
- return
-}
-
-set testprefix analyze2
-
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
-
-#--------------------------------------------------------------------
-# Test organization:
-#
-# analyze2-1.*: Tests to verify that ANALYZE creates and populates the
-# sqlite_stat2 table as expected.
-#
-# analyze2-2.*: Test that when a table has two indexes on it and either
-# index may be used for the scan, the index suggested by
-# the contents of sqlite_stat2 table is prefered.
-#
-# analyze2-3.*: Similar to the previous block of tests, but using tables
-# that contain a mixture of NULL, numeric, text and blob
-# values.
-#
-# analyze2-4.*: Check that when an indexed column uses a collation other
-# than BINARY, the collation is taken into account when
-# using the contents of sqlite_stat2 to estimate the cost
-# of a range scan.
-#
-# analyze2-5.*: Check that collation sequences are used as described above
-# even when the only available version of the collation
-# function require UTF-16 encoded arguments.
-#
-# analyze2-6.*: Check that the library behaves correctly when one of the
-# sqlite_stat2 or sqlite_stat1 tables are missing.
-#
-# analyze2-7.*: Check that in a shared-schema situation, nothing goes
-# wrong if sqlite_stat2 data is read by one connection,
-# and freed by another.
-#
-
-proc eqp {sql {db db}} {
- uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
-}
-
-do_test analyze2-1.1 {
- execsql { CREATE TABLE t1(x PRIMARY KEY) }
- for {set i 0} {$i < 1000} {incr i} {
- execsql { INSERT INTO t1 VALUES($i) }
- }
- execsql {
- ANALYZE;
- SELECT * FROM sqlite_stat2;
- }
-} [list t1 sqlite_autoindex_t1_1 0 50 \
- t1 sqlite_autoindex_t1_1 1 149 \
- t1 sqlite_autoindex_t1_1 2 249 \
- t1 sqlite_autoindex_t1_1 3 349 \
- t1 sqlite_autoindex_t1_1 4 449 \
- t1 sqlite_autoindex_t1_1 5 549 \
- t1 sqlite_autoindex_t1_1 6 649 \
- t1 sqlite_autoindex_t1_1 7 749 \
- t1 sqlite_autoindex_t1_1 8 849 \
- t1 sqlite_autoindex_t1_1 9 949 \
-]
-
-do_test analyze2-1.2 {
- execsql {
- DELETE FROM t1 WHERe x>9;
- ANALYZE;
- SELECT tbl, idx, group_concat(sample, ' ') FROM sqlite_stat2;
- }
-} {t1 sqlite_autoindex_t1_1 {0 1 2 3 4 5 6 7 8 9}}
-do_test analyze2-1.3 {
- execsql {
- DELETE FROM t1 WHERE x>8;
- ANALYZE;
- SELECT * FROM sqlite_stat2;
- }
-} {}
-do_test analyze2-1.4 {
- execsql {
- DELETE FROM t1;
- ANALYZE;
- SELECT * FROM sqlite_stat2;
- }
-} {}
-
-do_test analyze2-2.1 {
- execsql {
- BEGIN;
- DROP TABLE t1;
- CREATE TABLE t1(x, y);
- CREATE INDEX t1_x ON t1(x);
- CREATE INDEX t1_y ON t1(y);
- }
- for {set i 0} {$i < 1000} {incr i} {
- execsql { INSERT INTO t1 VALUES($i, $i) }
- }
- execsql COMMIT
- execsql ANALYZE
-} {}
-do_eqp_test 2.2 {
- SELECT * FROM t1 WHERE x>500 AND y>700
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~100 rows)}
-}
-do_eqp_test 2.3 {
- SELECT * FROM t1 WHERE x>700 AND y>500
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>?) (~100 rows)}
-}
-do_eqp_test 2.3 {
- SELECT * FROM t1 WHERE y>700 AND x>500
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~100 rows)}
-}
-do_eqp_test 2.4 {
- SELECT * FROM t1 WHERE y>500 AND x>700
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>?) (~100 rows)}
-}
-do_eqp_test 2.5 {
- SELECT * FROM t1 WHERE x BETWEEN 100 AND 200 AND y BETWEEN 400 AND 700
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x) (~25 rows)}
-}
-do_eqp_test 2.6 {
- SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 400 AND 700
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y) (~75 rows)}
-}
-do_eqp_test 2.7 {
- SELECT * FROM t1 WHERE x BETWEEN -400 AND -300 AND y BETWEEN 100 AND 300
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x) (~12 rows)}
-}
-do_eqp_test 2.8 {
- SELECT * FROM t1 WHERE x BETWEEN 100 AND 300 AND y BETWEEN -400 AND -300
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y) (~12 rows)}
-}
-do_eqp_test 2.9 {
- SELECT * FROM t1 WHERE x BETWEEN 500 AND 100 AND y BETWEEN 100 AND 300
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x) (~12 rows)}
-}
-do_eqp_test 2.10 {
- SELECT * FROM t1 WHERE x BETWEEN 100 AND 300 AND y BETWEEN 500 AND 100
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y) (~12 rows)}
-}
-
-do_test analyze2-3.1 {
- set alphabet [list a b c d e f g h i j]
- execsql BEGIN
- for {set i 0} {$i < 1000} {incr i} {
- set str [lindex $alphabet [expr ($i/100)%10]]
- append str [lindex $alphabet [expr ($i/ 10)%10]]
- append str [lindex $alphabet [expr ($i/ 1)%10]]
- execsql { INSERT INTO t1 VALUES($str, $str) }
- }
- execsql COMMIT
- execsql ANALYZE
- execsql {
- SELECT tbl,idx,group_concat(sample,' ')
- FROM sqlite_stat2
- WHERE idx = 't1_x'
- GROUP BY tbl,idx
- }
-} {t1 t1_x {100 299 499 699 899 ajj cjj ejj gjj ijj}}
-do_test analyze2-3.2 {
- execsql {
- SELECT tbl,idx,group_concat(sample,' ')
- FROM sqlite_stat2
- WHERE idx = 't1_y'
- GROUP BY tbl,idx
- }
-} {t1 t1_y {100 299 499 699 899 ajj cjj ejj gjj ijj}}
-
-do_eqp_test 3.3 {
- SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 'a' AND 'b'
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y) (~50 rows)}
-}
-do_eqp_test 3.4 {
- SELECT * FROM t1 WHERE x BETWEEN 100 AND 400 AND y BETWEEN 'a' AND 'h'
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x) (~100 rows)}
-}
-do_eqp_test 3.5 {
- SELECT * FROM t1 WHERE x<'a' AND y>'h'
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~66 rows)}
-}
-do_eqp_test 3.6 {
- SELECT * FROM t1 WHERE x<444 AND y>'h'
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~66 rows)}
-}
-do_eqp_test 3.7 {
- SELECT * FROM t1 WHERE x<221 AND y>'g'
-} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x) (~66 rows)}
-}
-
-do_test analyze2-4.1 {
- execsql { CREATE TABLE t3(a COLLATE nocase, b) }
- execsql { CREATE INDEX t3a ON t3(a) }
- execsql { CREATE INDEX t3b ON t3(b) }
- set alphabet [list A b C d E f G h I j]
- execsql BEGIN
- for {set i 0} {$i < 1000} {incr i} {
- set str [lindex $alphabet [expr ($i/100)%10]]
- append str [lindex $alphabet [expr ($i/ 10)%10]]
- append str [lindex $alphabet [expr ($i/ 1)%10]]
- execsql { INSERT INTO t3 VALUES($str, $str) }
- }
- execsql COMMIT
- execsql ANALYZE
-} {}
-do_test analyze2-4.2 {
- execsql {
- PRAGMA automatic_index=OFF;
- SELECT tbl,idx,group_concat(sample,' ')
- FROM sqlite_stat2
- WHERE idx = 't3a'
- GROUP BY tbl,idx;
- PRAGMA automatic_index=ON;
- }
-} {t3 t3a {AfA bEj CEj dEj EEj fEj GEj hEj IEj jEj}}
-do_test analyze2-4.3 {
- execsql {
- SELECT tbl,idx,group_concat(sample,' ')
- FROM sqlite_stat2
- WHERE idx = 't3b'
- GROUP BY tbl,idx
- }
-} {t3 t3b {AbA CIj EIj GIj IIj bIj dIj fIj hIj jIj}}
-
-do_eqp_test 4.4 {
- SELECT * FROM t3 WHERE a > 'A' AND a < 'C' AND b > 'A' AND b < 'C'
-} {
- 0 0 0 {SEARCH TABLE t3 USING INDEX t3b (b>? AND b) (~11 rows)}
-}
-do_eqp_test 4.5 {
- SELECT * FROM t3 WHERE a > 'A' AND a < 'c' AND b > 'A' AND b < 'c'
-} {
- 0 0 0 {SEARCH TABLE t3 USING INDEX t3a (a>? AND a) (~22 rows)}
-}
-
-ifcapable utf16 {
- proc test_collate {enc lhs rhs} {
- # puts $enc
- return [string compare $lhs $rhs]
- }
- do_test analyze2-5.1 {
- add_test_collate db 0 0 1
- execsql { CREATE TABLE t4(x COLLATE test_collate) }
- execsql { CREATE INDEX t4x ON t4(x) }
- set alphabet [list a b c d e f g h i j]
- execsql BEGIN
- for {set i 0} {$i < 1000} {incr i} {
- set str [lindex $alphabet [expr ($i/100)%10]]
- append str [lindex $alphabet [expr ($i/ 10)%10]]
- append str [lindex $alphabet [expr ($i/ 1)%10]]
- execsql { INSERT INTO t4 VALUES($str) }
- }
- execsql COMMIT
- execsql ANALYZE
- } {}
- do_test analyze2-5.2 {
- execsql {
- SELECT tbl,idx,group_concat(sample,' ')
- FROM sqlite_stat2
- WHERE tbl = 't4'
- GROUP BY tbl,idx
- }
- } {t4 t4x {afa bej cej dej eej fej gej hej iej jej}}
- do_eqp_test 5.3 {
- SELECT * FROM t4 WHERE x>'ccc'
- } {0 0 0 {SEARCH TABLE t4 USING COVERING INDEX t4x (x>?) (~800 rows)}}
- do_eqp_test 5.4 {
- SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ccc' AND t42.x>'ggg'
- } {
- 0 0 1 {SEARCH TABLE t4 AS t42 USING COVERING INDEX t4x (x>?) (~300 rows)}
- 0 1 0 {SEARCH TABLE t4 AS t41 USING COVERING INDEX t4x (x>?) (~800 rows)}
- }
- do_eqp_test 5.5 {
- SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ddd' AND t42.x>'ccc'
- } {
- 0 0 0 {SEARCH TABLE t4 AS t41 USING COVERING INDEX t4x (x>?) (~700 rows)}
- 0 1 1 {SEARCH TABLE t4 AS t42 USING COVERING INDEX t4x (x>?) (~800 rows)}
- }
-}
-
-#--------------------------------------------------------------------
-# These tests, analyze2-6.*, verify that the library behaves correctly
-# when one of the sqlite_stat1 and sqlite_stat2 tables is missing.
-#
-# If the sqlite_stat1 table is not present, then the sqlite_stat2
-# table is not read. However, if it is the sqlite_stat2 table that
-# is missing, the data in the sqlite_stat1 table is still used.
-#
-# Tests analyze2-6.1.* test the libary when the sqlite_stat2 table
-# is missing. Tests analyze2-6.2.* test the library when sqlite_stat1
-# is not present.
-#
-do_test analyze2-6.0 {
- execsql {
- DROP TABLE IF EXISTS t4;
- CREATE TABLE t5(a, b); CREATE INDEX t5i ON t5(a, b);
- CREATE TABLE t6(a, b); CREATE INDEX t6i ON t6(a, b);
- }
- for {set ii 0} {$ii < 20} {incr ii} {
- execsql {
- INSERT INTO t5 VALUES($ii, $ii);
- INSERT INTO t6 VALUES($ii/10, $ii/10);
- }
- }
- execsql {
- CREATE TABLE master AS
- SELECT * FROM sqlite_master WHERE name LIKE 'sqlite_stat%'
- }
-} {}
-
-do_test analyze2-6.1.1 {
- eqp {SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a = 1 AND
- t6.a = 1 AND t6.b = 1
- }
-} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a=? AND b=?) (~9 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.1.2 {
- db cache flush
- execsql ANALYZE
- eqp {SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a = 1 AND
- t6.a = 1 AND t6.b = 1
- }
-} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.1.3 {
- sqlite3 db test.db
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a = 1 AND
- t6.a = 1 AND t6.b = 1
- }
-} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.1.4 {
- execsql {
- PRAGMA writable_schema = 1;
- DELETE FROM sqlite_master WHERE tbl_name = 'sqlite_stat2';
- }
- sqlite3 db test.db
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a = 1 AND
- t6.a = 1 AND t6.b = 1
- }
-} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.1.5 {
- execsql {
- PRAGMA writable_schema = 1;
- DELETE FROM sqlite_master WHERE tbl_name = 'sqlite_stat1';
- }
- sqlite3 db test.db
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a = 1 AND
- t6.a = 1 AND t6.b = 1
- }
-} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a=? AND b=?) (~9 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.1.6 {
- execsql {
- PRAGMA writable_schema = 1;
- INSERT INTO sqlite_master SELECT * FROM master;
- }
- sqlite3 db test.db
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a = 1 AND
- t6.a = 1 AND t6.b = 1
- }
-} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-
-do_test analyze2-6.2.1 {
- execsql {
- DELETE FROM sqlite_stat1;
- DELETE FROM sqlite_stat2;
- }
- sqlite3 db test.db
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- }
-} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.2.2 {
- db cache flush
- execsql ANALYZE
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- }
-} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.2.3 {
- sqlite3 db test.db
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- }
-} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.2.4 {
- execsql {
- PRAGMA writable_schema = 1;
- DELETE FROM sqlite_master WHERE tbl_name = 'sqlite_stat1';
- }
- sqlite3 db test.db
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- }
-} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.2.5 {
- execsql {
- PRAGMA writable_schema = 1;
- DELETE FROM sqlite_master WHERE tbl_name = 'sqlite_stat2';
- }
- sqlite3 db test.db
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- }
-} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-do_test analyze2-6.2.6 {
- execsql {
- PRAGMA writable_schema = 1;
- INSERT INTO sqlite_master SELECT * FROM master;
- }
- sqlite3 db test.db
- execsql ANALYZE
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- }
-} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-
-#--------------------------------------------------------------------
-# These tests, analyze2-7.*, test that the sqlite_stat2 functionality
-# works in shared-cache mode. Note that these tests reuse the database
-# created for the analyze2-6.* tests.
-#
-ifcapable shared_cache {
- db close
- set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
-
- proc incr_schema_cookie {zDb} {
- foreach iOffset {24 40} {
- set cookie [hexio_get_int [hexio_read $zDb $iOffset 4]]
- incr cookie
- hexio_write $zDb $iOffset [hexio_render_int32 $cookie]
- }
- }
-
- do_test analyze2-7.1 {
- sqlite3 db1 test.db
- sqlite3 db2 test.db
- db1 cache size 0
- db2 cache size 0
- execsql { SELECT count(*) FROM t5 } db1
- } {20}
- do_test analyze2-7.2 {
- incr_schema_cookie test.db
- execsql { SELECT count(*) FROM t5 } db2
- } {20}
- do_test analyze2-7.3 {
- incr_schema_cookie test.db
- execsql { SELECT count(*) FROM t5 } db1
- } {20}
- do_test analyze2-7.4 {
- incr_schema_cookie test.db
- execsql { SELECT count(*) FROM t5 } db2
- } {20}
-
- do_test analyze2-7.5 {
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- } db1
- } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
- do_test analyze2-7.6 {
- incr_schema_cookie test.db
- execsql { SELECT * FROM sqlite_master } db2
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- } db2
- } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
- do_test analyze2-7.7 {
- incr_schema_cookie test.db
- execsql { SELECT * FROM sqlite_master } db1
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- } db1
- } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-
- do_test analyze2-7.8 {
- execsql { DELETE FROM sqlite_stat2 } db2
- execsql { SELECT * FROM sqlite_master } db1
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- } db1
- } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
- do_test analyze2-7.9 {
- execsql { SELECT * FROM sqlite_master } db2
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- } db2
- } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-
- do_test analyze2-7.10 {
- incr_schema_cookie test.db
- execsql { SELECT * FROM sqlite_master } db1
- eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND
- t5.a>1 AND t5.a<15 AND
- t6.a>1
- } db1
- } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
-
- db1 close
- db2 close
- sqlite3_enable_shared_cache $::enable_shared_cache
-}
-
-finish_test
diff --git a/test/analyze3.test b/test/analyze3.test
index 2378ffaa..f705bc66 100644
--- a/test/analyze3.test
+++ b/test/analyze3.test
@@ -17,7 +17,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-ifcapable !stat2 {
+ifcapable !stat3 {
finish_test
return
}
@@ -70,7 +70,7 @@ proc sf_execsql {sql {db db}} {
# Show that there are two possible plans for querying the table with
# a range constraint on the indexed column - "full table scan" or "use
# the index". When the range is specified using literal values, SQLite
-# is able to pick the best plan based on the samples in sqlite_stat2.
+# is able to pick the best plan based on the samples in sqlite_stat3.
#
# analyze3-1.1.4 - 3.1.9
# Show that using SQL variables produces the same results as using
@@ -97,10 +97,10 @@ do_test analyze3-1.1.1 {
do_eqp_test analyze3-1.1.2 {
SELECT sum(y) FROM t1 WHERE x>200 AND x<300
-} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x) (~100 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x) (~179 rows)}}
do_eqp_test analyze3-1.1.3 {
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
-} {0 0 0 {SCAN TABLE t1 (~111 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x) (~959 rows)}}
do_test analyze3-1.1.4 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
@@ -117,17 +117,17 @@ do_test analyze3-1.1.6 {
} {199 0 14850}
do_test analyze3-1.1.7 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 }
-} {999 999 499500}
+} {2000 0 499500}
do_test analyze3-1.1.8 {
set l [string range "0" 0 end]
set u [string range "1100" 0 end]
sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
-} {999 999 499500}
+} {2000 0 499500}
do_test analyze3-1.1.9 {
set l [expr int(0)]
set u [expr int(1100)]
sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
-} {999 999 499500}
+} {2000 0 499500}
# The following tests are similar to the block above. The difference is
@@ -146,10 +146,10 @@ do_test analyze3-1.2.1 {
} {}
do_eqp_test analyze3-1.2.2 {
SELECT sum(y) FROM t2 WHERE x>1 AND x<2
-} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x) (~200 rows)}}
+} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x) (~196 rows)}}
do_eqp_test analyze3-1.2.3 {
SELECT sum(y) FROM t2 WHERE x>0 AND x<99
-} {0 0 0 {SCAN TABLE t2 (~111 rows)}}
+} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x) (~968 rows)}}
do_test analyze3-1.2.4 {
sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
} {161 0 4760}
@@ -165,17 +165,17 @@ do_test analyze3-1.2.6 {
} {161 0 integer integer 4760}
do_test analyze3-1.2.7 {
sf_execsql { SELECT sum(y) FROM t2 WHERE x>0 AND x<99 }
-} {999 999 490555}
+} {1981 0 490555}
do_test analyze3-1.2.8 {
set l [string range "0" 0 end]
set u [string range "99" 0 end]
sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
-} {999 999 text text 490555}
+} {1981 0 text text 490555}
do_test analyze3-1.2.9 {
set l [expr int(0)]
set u [expr int(99)]
sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
-} {999 999 integer integer 490555}
+} {1981 0 integer integer 490555}
# Same tests a third time. This time, column x has INTEGER affinity and
# is not the leftmost column of the table. This triggered a bug causing
@@ -193,10 +193,10 @@ do_test analyze3-1.3.1 {
} {}
do_eqp_test analyze3-1.3.2 {
SELECT sum(y) FROM t3 WHERE x>200 AND x<300
-} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x) (~100 rows)}}
+} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x) (~156 rows)}}
do_eqp_test analyze3-1.3.3 {
SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
-} {0 0 0 {SCAN TABLE t3 (~111 rows)}}
+} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x) (~989 rows)}}
do_test analyze3-1.3.4 {
sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
@@ -213,17 +213,17 @@ do_test analyze3-1.3.6 {
} {199 0 14850}
do_test analyze3-1.3.7 {
sf_execsql { SELECT sum(y) FROM t3 WHERE x>0 AND x<1100 }
-} {999 999 499500}
+} {2000 0 499500}
do_test analyze3-1.3.8 {
set l [string range "0" 0 end]
set u [string range "1100" 0 end]
sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
-} {999 999 499500}
+} {2000 0 499500}
do_test analyze3-1.3.9 {
set l [expr int(0)]
set u [expr int(1100)]
sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
-} {999 999 499500}
+} {2000 0 499500}
#-------------------------------------------------------------------------
# Test that the values of bound SQL variables may be used for the LIKE
@@ -248,7 +248,7 @@ do_test analyze3-2.1 {
} {}
do_eqp_test analyze3-2.2 {
SELECT count(a) FROM t1 WHERE b LIKE 'a%'
-} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b) (~30000 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b) (~31250 rows)}}
do_eqp_test analyze3-2.3 {
SELECT count(a) FROM t1 WHERE b LIKE '%a'
} {0 0 0 {SCAN TABLE t1 (~500000 rows)}}
diff --git a/test/analyze5.test b/test/analyze5.test
index a0469da1..1041d709 100644
--- a/test/analyze5.test
+++ b/test/analyze5.test
@@ -10,14 +10,14 @@
#***********************************************************************
#
# This file implements tests for SQLite library. The focus of the tests
-# in this file is the use of the sqlite_stat2 histogram data on tables
+# in this file is the use of the sqlite_stat3 histogram data on tables
# with many repeated values and only a few distinct values.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-ifcapable !stat2 {
+ifcapable !stat3 {
finish_test
return
}
@@ -55,114 +55,102 @@ do_test analyze5-1.0 {
CREATE INDEX t1y ON t1(y); -- integers 0 and very few 1s
CREATE INDEX t1z ON t1(z); -- integers 0, 1, 2, and 3
ANALYZE;
- SELECT sample FROM sqlite_stat2 WHERE idx='t1u' ORDER BY sampleno;
+ SELECT sample FROM sqlite_stat3 WHERE idx='t1u' ORDER BY nlt;
}
-} {alpha alpha alpha alpha bravo bravo bravo charlie charlie delta}
-do_test analyze5-1.1 {
- string tolower \
- [db eval {SELECT sample from sqlite_stat2 WHERE idx='t1v' ORDER BY sampleno}]
-} {alpha alpha alpha alpha bravo bravo bravo charlie charlie delta}
-do_test analyze5-1.2 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1w' ORDER BY sampleno}
-} {{} 0 0 0 0 1 1 1 2 2}
-do_test analyze5-1.3 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1x' ORDER BY sampleno}
-} {{} {} {} {} 1 1 1 2 2 3}
-do_test analyze5-1.4 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1y' ORDER BY sampleno}
-} {0 0 0 0 0 0 0 0 0 0}
-do_test analyze5-1.5 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1z' ORDER BY sampleno}
-} {0 0 0 0 1 1 1 2 2 3}
-do_test analyze5-1.6 {
- db eval {SELECT sample from sqlite_stat2 WHERE idx='t1t' ORDER BY sampleno}
-} {0.5 0.5 0.5 0.5 1.5 1.5 1.5 2.5 2.5 3.5}
+} {alpha bravo charlie delta}
+do_test analyze5-1.1 {
+ db eval {SELECT DISTINCT lower(sample) FROM sqlite_stat3 WHERE idx='t1v'
+ ORDER BY 1}
+} {alpha bravo charlie delta}
+do_test analyze5-1.2 {
+ db eval {SELECT idx, count(*) FROM sqlite_stat3 GROUP BY 1 ORDER BY 1}
+} {t1t 4 t1u 4 t1v 4 t1w 4 t1x 4 t1y 2 t1z 4}
# Verify that range queries generate the correct row count estimates
#
foreach {testid where index rows} {
1 {z>=0 AND z<=0} t1z 400
2 {z>=1 AND z<=1} t1z 300
- 3 {z>=2 AND z<=2} t1z 200
- 4 {z>=3 AND z<=3} t1z 100
- 5 {z>=4 AND z<=4} t1z 50
- 6 {z>=-1 AND z<=-1} t1z 50
- 7 {z>1 AND z<3} t1z 200
+ 3 {z>=2 AND z<=2} t1z 175
+ 4 {z>=3 AND z<=3} t1z 125
+ 5 {z>=4 AND z<=4} t1z 1
+ 6 {z>=-1 AND z<=-1} t1z 1
+ 7 {z>1 AND z<3} t1z 175
8 {z>0 AND z<100} t1z 600
9 {z>=1 AND z<100} t1z 600
10 {z>1 AND z<100} t1z 300
11 {z>=2 AND z<100} t1z 300
- 12 {z>2 AND z<100} t1z 100
- 13 {z>=3 AND z<100} t1z 100
- 14 {z>3 AND z<100} t1z 50
- 15 {z>=4 AND z<100} t1z 50
- 16 {z>=-100 AND z<=-1} t1z 50
+ 12 {z>2 AND z<100} t1z 125
+ 13 {z>=3 AND z<100} t1z 125
+ 14 {z>3 AND z<100} t1z 1
+ 15 {z>=4 AND z<100} t1z 1
+ 16 {z>=-100 AND z<=-1} t1z 1
17 {z>=-100 AND z<=0} t1z 400
- 18 {z>=-100 AND z<0} t1z 50
+ 18 {z>=-100 AND z<0} t1z 1
19 {z>=-100 AND z<=1} t1z 700
20 {z>=-100 AND z<2} t1z 700
- 21 {z>=-100 AND z<=2} t1z 900
- 22 {z>=-100 AND z<3} t1z 900
+ 21 {z>=-100 AND z<=2} t1z 875
+ 22 {z>=-100 AND z<3} t1z 875
31 {z>=0.0 AND z<=0.0} t1z 400
32 {z>=1.0 AND z<=1.0} t1z 300
- 33 {z>=2.0 AND z<=2.0} t1z 200
- 34 {z>=3.0 AND z<=3.0} t1z 100
- 35 {z>=4.0 AND z<=4.0} t1z 50
- 36 {z>=-1.0 AND z<=-1.0} t1z 50
- 37 {z>1.5 AND z<3.0} t1z 200
- 38 {z>0.5 AND z<100} t1z 600
+ 33 {z>=2.0 AND z<=2.0} t1z 175
+ 34 {z>=3.0 AND z<=3.0} t1z 125
+ 35 {z>=4.0 AND z<=4.0} t1z 1
+ 36 {z>=-1.0 AND z<=-1.0} t1z 1
+ 37 {z>1.5 AND z<3.0} t1z 174
+ 38 {z>0.5 AND z<100} t1z 599
39 {z>=1.0 AND z<100} t1z 600
- 40 {z>1.5 AND z<100} t1z 300
+ 40 {z>1.5 AND z<100} t1z 299
41 {z>=2.0 AND z<100} t1z 300
- 42 {z>2.1 AND z<100} t1z 100
- 43 {z>=3.0 AND z<100} t1z 100
- 44 {z>3.2 AND z<100} t1z 50
- 45 {z>=4.0 AND z<100} t1z 50
- 46 {z>=-100 AND z<=-1.0} t1z 50
+ 42 {z>2.1 AND z<100} t1z 124
+ 43 {z>=3.0 AND z<100} t1z 125
+ 44 {z>3.2 AND z<100} t1z 1
+ 45 {z>=4.0 AND z<100} t1z 1
+ 46 {z>=-100 AND z<=-1.0} t1z 1
47 {z>=-100 AND z<=0.0} t1z 400
- 48 {z>=-100 AND z<0.0} t1z 50
+ 48 {z>=-100 AND z<0.0} t1z 1
49 {z>=-100 AND z<=1.0} t1z 700
50 {z>=-100 AND z<2.0} t1z 700
- 51 {z>=-100 AND z<=2.0} t1z 900
- 52 {z>=-100 AND z<3.0} t1z 900
+ 51 {z>=-100 AND z<=2.0} t1z 875
+ 52 {z>=-100 AND z<3.0} t1z 875
- 101 {z=-1} t1z 50
+ 101 {z=-1} t1z 1
102 {z=0} t1z 400
103 {z=1} t1z 300
- 104 {z=2} t1z 200
- 105 {z=3} t1z 100
- 106 {z=4} t1z 50
- 107 {z=-10.0} t1z 50
+ 104 {z=2} t1z 175
+ 105 {z=3} t1z 125
+ 106 {z=4} t1z 1
+ 107 {z=-10.0} t1z 1
108 {z=0.0} t1z 400
109 {z=1.0} t1z 300
- 110 {z=2.0} t1z 200
- 111 {z=3.0} t1z 100
- 112 {z=4.0} t1z 50
- 113 {z=1.5} t1z 50
- 114 {z=2.5} t1z 50
+ 110 {z=2.0} t1z 175
+ 111 {z=3.0} t1z 125
+ 112 {z=4.0} t1z 1
+ 113 {z=1.5} t1z 1
+ 114 {z=2.5} t1z 1
- 201 {z IN (-1)} t1z 50
+ 201 {z IN (-1)} t1z 1
202 {z IN (0)} t1z 400
203 {z IN (1)} t1z 300
- 204 {z IN (2)} t1z 200
- 205 {z IN (3)} t1z 100
- 206 {z IN (4)} t1z 50
- 207 {z IN (0.5)} t1z 50
+ 204 {z IN (2)} t1z 175
+ 205 {z IN (3)} t1z 125
+ 206 {z IN (4)} t1z 1
+ 207 {z IN (0.5)} t1z 1
208 {z IN (0,1)} t1z 700
- 209 {z IN (0,1,2)} t1z 900
+ 209 {z IN (0,1,2)} t1z 875
210 {z IN (0,1,2,3)} {} 100
211 {z IN (0,1,2,3,4,5)} {} 100
- 212 {z IN (1,2)} t1z 500
+ 212 {z IN (1,2)} t1z 475
213 {z IN (2,3)} t1z 300
214 {z=3 OR z=2} t1z 300
- 215 {z IN (-1,3)} t1z 150
- 216 {z=-1 OR z=3} t1z 150
+ 215 {z IN (-1,3)} t1z 126
+ 216 {z=-1 OR z=3} t1z 126
- 300 {y=0} {} 100
- 301 {y=1} t1y 50
- 302 {y=0.1} t1y 50
+ 300 {y=0} t1y 974
+ 301 {y=1} t1y 26
+ 302 {y=0.1} t1y 1
400 {x IS NULL} t1x 400
@@ -204,16 +192,17 @@ db eval {
# Verify that range queries generate the correct row count estimates
#
foreach {testid where index rows} {
- 500 {x IS NULL AND u='charlie'} t1u 20
- 501 {x=1 AND u='charlie'} t1x 5
- 502 {x IS NULL} {} 100
- 503 {x=1} t1x 50
- 504 {x IS NOT NULL} t1x 25
+ 500 {x IS NULL AND u='charlie'} t1u 17
+ 501 {x=1 AND u='charlie'} t1x 1
+ 502 {x IS NULL} t1x 995
+ 503 {x=1} t1x 1
+ 504 {x IS NOT NULL} t1x 2
505 {+x IS NOT NULL} {} 500
506 {upper(x) IS NOT NULL} {} 500
} {
# Verify that the expected index is used with the expected row count
+if {$testid==50299} {breakpoint; set sqlite_where_trace 1}
do_test analyze5-1.${testid}a {
set x [lindex [eqp "SELECT * FROM t1 WHERE $where"] 3]
set idx {}
@@ -221,6 +210,7 @@ foreach {testid where index rows} {
regexp {~([0-9]+) rows} $x all nrow
list $idx $nrow
} [list $index $rows]
+if {$testid==50299} exit
# Verify that the same result is achieved regardless of whether or not
# the index is used
diff --git a/test/analyze6.test b/test/analyze6.test
index b090b5b0..74b7ec79 100644
--- a/test/analyze6.test
+++ b/test/analyze6.test
@@ -17,7 +17,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-ifcapable !stat2 {
+ifcapable !stat3 {
finish_test
return
}
diff --git a/test/analyze7.test b/test/analyze7.test
index 4892a223..5bdb04d7 100644
--- a/test/analyze7.test
+++ b/test/analyze7.test
@@ -82,14 +82,14 @@ do_test analyze7-3.1 {
do_test analyze7-3.2.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~86 rows)}}
-ifcapable stat2 {
- # If ENABLE_STAT2 is defined, SQLite comes up with a different estimated
+ifcapable stat3 {
+ # If ENABLE_STAT3 is defined, SQLite comes up with a different estimated
# row count for (c=2) than it does for (c=?).
do_test analyze7-3.2.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
- } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~51 rows)}}
+ } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~57 rows)}}
} else {
- # If ENABLE_STAT2 is not defined, the expected row count for (c=2) is the
+ # If ENABLE_STAT3 is not defined, the expected row count for (c=2) is the
# same as that for (c=?).
do_test analyze7-3.2.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
@@ -98,12 +98,14 @@ ifcapable stat2 {
do_test analyze7-3.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
-do_test analyze7-3.4 {
- execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
-} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
-do_test analyze7-3.5 {
- execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
-} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+ifcapable {!stat3} {
+ do_test analyze7-3.4 {
+ execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
+ } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
+ do_test analyze7-3.5 {
+ execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
+ } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+}
do_test analyze7-3.6 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?) (~1 rows)}}
diff --git a/test/analyze8.test b/test/analyze8.test
new file mode 100644
index 00000000..f3e2710a
--- /dev/null
+++ b/test/analyze8.test
@@ -0,0 +1,103 @@
+# 2011 August 13
+#
+# 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 tests for SQLite library. The focus of the tests
+# in this file is testing the capabilities of sqlite_stat3.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+ifcapable !stat3 {
+ finish_test
+ return
+}
+
+set testprefix analyze8
+
+proc eqp {sql {db db}} {
+ uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
+}
+
+# Scenario:
+#
+# Two indices. One has mostly singleton entries, but for a few
+# values there are hundreds of entries. The other has 10-20
+# entries per value.
+#
+# Verify that the query planner chooses the first index for the singleton
+# entries and the second index for the others.
+#
+do_test 1.0 {
+ db eval {
+ CREATE TABLE t1(a,b,c,d);
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1b ON t1(b);
+ CREATE INDEX t1c ON t1(c);
+ }
+ for {set i 0} {$i<1000} {incr i} {
+ if {$i%2==0} {set a $i} {set a [expr {($i%8)*100}]}
+ set b [expr {$i/10}]
+ set c [expr {$i/8}]
+ set c [expr {$c*$c*$c}]
+ db eval {INSERT INTO t1 VALUES($a,$b,$c,$i)}
+ }
+ db eval {ANALYZE}
+} {}
+
+# The a==100 comparison is expensive because there are many rows
+# with a==100. And so for those cases, choose the t1b index.
+#
+# Buf ro a==99 and a==101, there are far fewer rows so choose
+# the t1a index.
+#
+do_test 1.1 {
+ eqp {SELECT * FROM t1 WHERE a=100 AND b=55}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
+do_test 1.2 {
+ eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+do_test 1.3 {
+ eqp {SELECT * FROM t1 WHERE a=101 AND b=55}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+do_test 1.4 {
+ eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
+do_test 1.5 {
+ eqp {SELECT * FROM t1 WHERE a=99 AND b=56}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+do_test 1.6 {
+ eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+do_test 2.1 {
+ eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b) (~2 rows)}}
+
+# There are many more values of c between 0 and 100000 than there are
+# between 800000 and 900000. So t1c is more selective for the latter
+# range.
+#
+do_test 3.1 {
+ eqp {SELECT * FROM t1 WHERE b BETWEEN 50 AND 54 AND c BETWEEN 0 AND 100000}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b) (~6 rows)}}
+do_test 3.2 {
+ eqp {SELECT * FROM t1
+ WHERE b BETWEEN 50 AND 54 AND c BETWEEN 800000 AND 900000}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c) (~4 rows)}}
+do_test 3.3 {
+ eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~63 rows)}}
+do_test 3.4 {
+ eqp {SELECT * FROM t1
+ WHERE a=100 AND c BETWEEN 800000 AND 900000}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c) (~2 rows)}}
+
+finish_test
diff --git a/test/async.test b/test/async.test
index f1d641da..e1bc0864 100644
--- a/test/async.test
+++ b/test/async.test
@@ -68,7 +68,7 @@ foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
# Make sure everything is flushed through. This is because [source]ing
# the next test file will delete the database file on disk (using
- # [file delete]). If the asynchronous backend still has the file
+ # [delete_file]). If the asynchronous backend still has the file
# open, it will become confused.
#
flush_async_queue
diff --git a/test/async2.test b/test/async2.test
index ec4ae308..7994a721 100644
--- a/test/async2.test
+++ b/test/async2.test
@@ -51,7 +51,7 @@ foreach err [list ioerr malloc-transient malloc-persistent] {
for {set n 1} {$::go} {incr n} {
set ::sqlite_io_error_pending 0
sqlite3_memdebug_fail -1
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql $::setup_script
db close
diff --git a/test/async3.test b/test/async3.test
index 77c4d55d..9336b660 100644
--- a/test/async3.test
+++ b/test/async3.test
@@ -41,8 +41,8 @@ set paths {
do_test async3-1.0 {
file mkdir [file join chocolate banana vanilla]
- file delete -force chocolate/banana/vanilla/file.db
- file delete -force chocolate/banana/vanilla/file.db-journal
+ forcedelete chocolate/banana/vanilla/file.db
+ forcedelete chocolate/banana/vanilla/file.db-journal
} {}
do_test async3-1.1 {
diff --git a/test/async5.test b/test/async5.test
index 5ea4c70e..aa484fcc 100644
--- a/test/async5.test
+++ b/test/async5.test
@@ -20,7 +20,7 @@ if {[info commands sqlite3async_initialize] eq ""} {
}
db close
-file delete -force test2.db
+forcedelete test2.db
sqlite3async_initialize "" 1
sqlite3async_control halt never
sqlite3 db test.db
diff --git a/test/attach.test b/test/attach.test
index 1bb596cb..d57f5bfb 100644
--- a/test/attach.test
+++ b/test/attach.test
@@ -24,8 +24,8 @@ ifcapable !attach {
}
for {set i 2} {$i<=15} {incr i} {
- file delete -force test$i.db
- file delete -force test$i.db-journal
+ forcedelete test$i.db
+ forcedelete test$i.db-journal
}
do_test attach-1.1 {
@@ -628,7 +628,7 @@ do_test attach-5.1 {
db close
sqlite3 db test.db
db2 close
- file delete -force test2.db
+ forcedelete test2.db
sqlite3 db2 test2.db
catchsql {
ATTACH DATABASE 'test.db' AS orig;
@@ -725,7 +725,7 @@ if {$tcl_platform(platform)=="unix"} {
file attributes cannot-read -permission 0000
if {[file writable cannot-read]} {
puts "\n**** Tests do not work when run as root ****"
- file delete -force cannot-read
+ forcedelete cannot-read
exit 1
}
catchsql {
@@ -735,7 +735,7 @@ if {$tcl_platform(platform)=="unix"} {
do_test attach-6.2.2 {
db errorcode
} {14}
- file delete -force cannot-read
+ forcedelete cannot-read
}
# Check the error message if we try to access a database that has
@@ -749,12 +749,12 @@ for {set i 2} {$i<=15} {incr i} {
catch {db$i close}
}
db close
-file delete -force test2.db
-file delete -force no-such-file
+forcedelete test2.db
+forcedelete no-such-file
ifcapable subquery {
do_test attach-7.1 {
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
catchsql {
DETACH RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY
@@ -777,7 +777,7 @@ do_test attach-8.1 {
do_test attach-8.2 {
db errorcode
} {26}
-file delete -force test2.db
+forcedelete test2.db
do_test attach-8.3 {
sqlite3 db2 test2.db
db2 eval {CREATE TABLE t1(x); BEGIN EXCLUSIVE}
@@ -789,13 +789,13 @@ do_test attach-8.4 {
db errorcode
} {5}
db2 close
-file delete -force test2.db
+forcedelete test2.db
# Test that it is possible to attach the same database more than
# once when not in shared-cache mode. That this is not possible in
# shared-cache mode is tested in shared7.test.
do_test attach-9.1 {
- file delete -force test4.db
+ forcedelete test4.db
execsql {
ATTACH 'test4.db' AS aux1;
CREATE TABLE aux1.t1(a, b);
diff --git a/test/attach2.test b/test/attach2.test
index 3cc5af96..db230723 100644
--- a/test/attach2.test
+++ b/test/attach2.test
@@ -33,8 +33,8 @@ do_test attach2-1.1 {
CREATE TABLE t1(a,b);
CREATE INDEX x1 ON t1(a);
}
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
sqlite3 db2 test2.db
db2 eval {
CREATE TABLE t1(a,b);
@@ -327,7 +327,7 @@ do_test attach2-4.15 {
db close
db2 close
-file delete -force test2.db
+forcedelete test2.db
sqlite3_soft_heap_limit $soft_limit
# These tests - attach2-5.* - check that the master journal file is deleted
@@ -335,7 +335,7 @@ sqlite3_soft_heap_limit $soft_limit
#
# Update: It's not actually created if a rollback occurs, so that test
# doesn't really prove too much.
-foreach f [glob test.db*] {file delete -force $f}
+foreach f [glob test.db*] {forcedelete $f}
do_test attach2-5.1 {
sqlite3 db test.db
execsql {
diff --git a/test/attach3.test b/test/attach3.test
index 36d39991..f8614253 100644
--- a/test/attach3.test
+++ b/test/attach3.test
@@ -35,8 +35,8 @@ execsql {
}
# Create tables t1 and t2 in database file test2.db
-file delete -force test2.db
-file delete -force test2.db-journal
+forcedelete test2.db
+forcedelete test2.db-journal
sqlite3 db2 test2.db
execsql {
CREATE TABLE t1(a, b);
diff --git a/test/attach4.test b/test/attach4.test
index f597f5d0..77dd7e41 100644
--- a/test/attach4.test
+++ b/test/attach4.test
@@ -75,10 +75,12 @@ set L [list]
set S ""
foreach {name f} $files {
if {[permutation] == "journaltest"} {
- lappend L delete
+ set mode delete
} else {
- lappend L wal
+ set mode wal
}
+ ifcapable !wal { set mode delete }
+ lappend L $mode
append S "
PRAGMA $name.journal_mode = WAL;
UPDATE $name.tbl SET x = '$name';
diff --git a/test/attachmalloc.test b/test/attachmalloc.test
index c485c618..7fee1e1b 100644
--- a/test/attachmalloc.test
+++ b/test/attachmalloc.test
@@ -29,8 +29,8 @@ do_malloc_test attachmalloc-1 -tclprep {
catch { db close }
for {set i 2} {$i<=4} {incr i} {
catch { db$i close }
- file delete -force test$i.db
- file delete -force test$i.db-journal
+ forcedelete test$i.db
+ forcedelete test$i.db-journal
}
} -tclbody {
if {[catch {sqlite3 db test.db}]} {
@@ -48,8 +48,8 @@ do_malloc_test attachmalloc-1 -tclprep {
}
do_malloc_test attachmalloc-2 -tclprep {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
sqlite3 db2 test2.db
db2 eval {
CREATE TABLE t1(a, b, c);
diff --git a/test/auth.test b/test/auth.test
index 8d2159ec..211ae7e2 100644
--- a/test/auth.test
+++ b/test/auth.test
@@ -2321,10 +2321,10 @@ ifcapable compound&&subquery {
}
}
}
- ifcapable stat2 {
- set stat2 "sqlite_stat2 "
+ ifcapable stat3 {
+ set stat3 "sqlite_stat3 "
} else {
- set stat2 ""
+ set stat3 ""
}
do_test auth-5.2 {
execsql {
@@ -2333,7 +2333,7 @@ ifcapable compound&&subquery {
WHERE type='table'
ORDER BY name
}
- } "sqlite_stat1 ${stat2}t1 t2 t3 t4"
+ } "sqlite_stat1 ${stat3}t1 t2 t3 t4"
}
# Ticket #3944
diff --git a/test/autoinc.test b/test/autoinc.test
index 983b9b83..98f6919b 100644
--- a/test/autoinc.test
+++ b/test/autoinc.test
@@ -427,8 +427,8 @@ ifcapable tempdb {
#
ifcapable tempdb&&attach {
do_test autoinc-5.1 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
sqlite3 db2 test2.db
execsql {
CREATE TABLE t4(m INTEGER PRIMARY KEY AUTOINCREMENT, n);
@@ -520,7 +520,7 @@ do_test autoinc-7.2 {
do_test autoinc-8.1 {
catch {db2 close}
catch {db close}
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
set DB [sqlite3_connection_pointer db]
set STMT [sqlite3_prepare $DB {
diff --git a/test/autoindex1.test b/test/autoindex1.test
index bc628dc2..6c8d54d1 100644
--- a/test/autoindex1.test
+++ b/test/autoindex1.test
@@ -248,4 +248,14 @@ do_execsql_test autoindex1-600 {
0 1 1 {SEARCH SUBQUERY 1 AS y USING AUTOMATIC COVERING INDEX (sheep_no=?) (~8 rows)}
}
+
+do_execsql_test autoindex1-700 {
+ CREATE TABLE t5(a, b, c);
+ EXPLAIN QUERY PLAN SELECT a FROM t5 WHERE b=10 ORDER BY c;
+} {
+ 0 0 0 {SCAN TABLE t5 (~100000 rows)}
+ 0 0 0 {USE TEMP B-TREE FOR ORDER BY}
+}
+
+
finish_test
diff --git a/test/autovacuum.test b/test/autovacuum.test
index 57dfd52d..1aef18f3 100644
--- a/test/autovacuum.test
+++ b/test/autovacuum.test
@@ -467,7 +467,7 @@ do_test autovacuum-3.3 {
do_test autovacuum-3.4 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql {
PRAGMA auto_vacuum;
@@ -502,7 +502,7 @@ do_test autovacuum-4.0 {
# Reset everything just in case.
#
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
PRAGMA auto_vacuum = 1;
@@ -599,8 +599,8 @@ do_test autovacuum-6.1 {
#
do_test autovacuum-7.1 {
db close
- file delete -force test.db
- file delete -force test.db-journal
+ forcedelete test.db
+ forcedelete test.db-journal
sqlite3 db test.db
execsql {
diff --git a/test/autovacuum_ioerr2.test b/test/autovacuum_ioerr2.test
index dadb29c0..891d00eb 100644
--- a/test/autovacuum_ioerr2.test
+++ b/test/autovacuum_ioerr2.test
@@ -75,7 +75,7 @@ do_ioerr_test autovacuum-ioerr2-3 -sqlprep {
DROP TABLE abc2;
}
-file delete -force backup.db
+forcedelete backup.db
ifcapable subquery {
do_ioerr_test autovacuum-ioerr2-4 -tclprep {
if {![file exists backup.db]} {
@@ -99,9 +99,9 @@ ifcapable subquery {
dbb close
}
db close
- file delete -force test.db
- file delete -force test.db-journal
- copy_file backup.db test.db
+ forcedelete test.db
+ forcedelete test.db-journal
+ forcecopy backup.db test.db
set ::DB [sqlite3 db test.db]
execsql {
PRAGMA cache_size = 10;
diff --git a/test/backcompat.test b/test/backcompat.test
index fa643f9b..e8e2f615 100644
--- a/test/backcompat.test
+++ b/test/backcompat.test
@@ -61,7 +61,7 @@ foreach bin $binaries {
proc do_backcompat_test {rv bin1 bin2 script} {
- file delete -force test.db
+ forcedelete test.db
if {$bin1 != ""} { set ::bc_chan1 [launch_testfixture $bin1] }
set ::bc_chan2 [launch_testfixture $bin2]
@@ -152,7 +152,7 @@ proc read_file_system {} {
proc write_file_system {data} {
foreach f {test.db test.db-journal test.db-wal} d $data {
if {[string length $d] == 0} {
- file delete -force $f
+ forcedelete $f
} else {
write_file $f $d
}
diff --git a/test/backup.test b/test/backup.test
index 0e2c26f3..62698857 100644
--- a/test/backup.test
+++ b/test/backup.test
@@ -73,7 +73,7 @@ test_contents backup-1.2 db main db main
# Check that it is possible to create and finish backup operations.
#
do_test backup-1.3.1 {
- file delete test2.db
+ delete_file test2.db
sqlite3 db2 test2.db
sqlite3_backup B db2 main db main
} {B}
@@ -168,8 +168,8 @@ foreach pgsz_dest {512 1024 2048} {
foreach nPagePerStep {1 200} {
# Open the databases.
- catch { file delete test.db }
- catch { file delete test2.db }
+ catch { delete_file test.db }
+ catch { delete_file test2.db }
eval $zOpenScript
# Set to true if copying to an in-memory destination. Copying to an
@@ -279,8 +279,8 @@ foreach nSrcPg {10 64 65 66 100} {
foreach nDestRow {10 100} {
foreach nDestPgsz {512 1024 2048 4096} {
- catch { file delete test.db }
- catch { file delete test2.db }
+ catch { delete_file test.db }
+ catch { delete_file test2.db }
sqlite3 db test.db
sqlite3 db2 test2.db
@@ -327,8 +327,8 @@ foreach nDestPgsz {512 1024 2048 4096} {
#--------------------------------------------------------------------
do_test backup-3.$iTest.1 {
- catch { file delete -force test.db }
- catch { file delete -force test2.db }
+ catch { forcedelete test.db }
+ catch { forcedelete test2.db }
sqlite3 db test.db
set iTab 1
@@ -392,8 +392,8 @@ do_test backup-4.1.4 {
} {unknown database aux}
do_test backup-4.2.1 {
- catch { file delete -force test3.db }
- catch { file delete -force test4.db }
+ catch { forcedelete test3.db }
+ catch { forcedelete test4.db }
execsql {
ATTACH 'test3.db' AS aux1;
CREATE TABLE aux1.t1(a, b);
@@ -439,7 +439,7 @@ db close
db2 close
do_test backup-4.5.1 {
- catch { file delete -force test.db }
+ catch { forcedelete test.db }
sqlite3 db test.db
sqlite3 db2 :memory:
execsql {
@@ -491,12 +491,12 @@ db2 close
# 3) Backing up memory-to-file.
#
set iTest 0
-file delete -force bak.db-wal
+forcedelete bak.db-wal
foreach {writer file} {db test.db db3 test.db db :memory:} {
incr iTest
- catch { file delete bak.db }
+ catch { delete_file bak.db }
sqlite3 db2 bak.db
- catch { file delete $file }
+ catch { delete_file $file }
sqlite3 db $file
sqlite3 db3 $file
@@ -597,9 +597,9 @@ foreach {writer file} {db test.db db3 test.db db :memory:} {
catch {db close}
catch {db2 close}
catch {db3 close}
- catch { file delete bak.db }
+ catch { delete_file bak.db }
sqlite3 db2 bak.db
- catch { file delete $file }
+ catch { delete_file $file }
sqlite3 db $file
sqlite3 db3 $file
do_test backup-5.$iTest.5.1 {
@@ -644,8 +644,8 @@ foreach {writer file} {db test.db db3 test.db db :memory:} {
# Test the sqlite3_backup_remaining() and backup_pagecount() APIs.
#
do_test backup-6.1 {
- catch { file delete -force test.db }
- catch { file delete -force test2.db }
+ catch { forcedelete test.db }
+ catch { forcedelete test2.db }
sqlite3 db test.db
sqlite3 db2 test2.db
execsql {
@@ -701,8 +701,8 @@ catch {db2 close}
# backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY).
#
do_test backup-7.0 {
- catch { file delete -force test.db }
- catch { file delete -force test2.db }
+ catch { forcedelete test.db }
+ catch { forcedelete test2.db }
sqlite3 db2 test2.db
sqlite3 db test.db
execsql {
@@ -754,7 +754,7 @@ integrity_check backup-7.3.6 db2
do_test backup-7.3.1 {
db2 close
db3 close
- file delete -force test2.db
+ forcedelete test2.db
sqlite3 db2 test2.db
sqlite3 db3 test2.db
@@ -783,8 +783,8 @@ catch { db3 close }
# These tests reuse the database "test.db" left over from backup-7.*.
#
do_test backup-8.1 {
- catch { file delete -force test2.db }
- catch { file delete -force test3.db }
+ catch { forcedelete test2.db }
+ catch { forcedelete test3.db }
sqlite3 db2 test2.db
sqlite3 db3 test3.db
@@ -865,8 +865,8 @@ catch {db2 close}
ifcapable memorymanage {
db close
- file delete -force test.db
- file delete -force bak.db
+ forcedelete test.db
+ forcedelete bak.db
sqlite3 db test.db
sqlite3 db2 test.db
@@ -918,7 +918,7 @@ ifcapable memorymanage {
# 10.2.*: If the db is a file, the backup is not restarted.
#
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
foreach {tn file rc} {
1 test.db SQLITE_DONE
2 :memory: SQLITE_OK
@@ -948,7 +948,7 @@ foreach {tn file rc} {
} {1}
do_test backup-10.$tn.3 {
- file delete -force bak.db bak.db-journal
+ forcedelete bak.db bak.db-journal
sqlite3 db2 bak.db
sqlite3_backup B db2 main db main
B step 50
diff --git a/test/backup2.test b/test/backup2.test
index 749c460e..34924b02 100644
--- a/test/backup2.test
+++ b/test/backup2.test
@@ -61,7 +61,7 @@ set cksum [dbcksum db main]
# is identical to the original.
#
do_test backup2-2 {
- file delete -force bu1.db
+ forcedelete bu1.db
db backup bu1.db
sqlite3 db2 bu1.db
dbcksum db2 main
@@ -72,7 +72,7 @@ do_test backup2-2 {
#
do_test backup2-3.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
db2 eval {BEGIN EXCLUSIVE}
set rc [catch {db restore bu1.db} res]
@@ -82,7 +82,7 @@ do_test backup2-3.1 {
} {1 {restore failed: source database busy}}
do_test backup2-3.2 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
db restore bu1.db
dbcksum db main
@@ -96,7 +96,7 @@ do_test backup2-4 {
} $cksum
do_test backup2-5 {
db2 close
- file delete -force bu1.db bu2.db
+ forcedelete bu1.db bu2.db
db backup temp bu2.db
sqlite3 db2 bu2.db
dbcksum db2 main
@@ -127,7 +127,7 @@ do_test backup2-7 {
# Try to backup database that does not exist
#
do_test backup2-8 {
- file delete -force bu1.db
+ forcedelete bu1.db
set rc [catch {db backup aux1 bu1.db} res]
lappend rc $res
} {1 {backup failed: unknown database aux1}}
@@ -143,7 +143,7 @@ do_test backup2-9 {
#
if {$tcl_platform(platform)=="windows"} {
do_test backup2-10 {
- file delete -force bu3.db
+ forcedelete bu3.db
file mkdir bu3.db
set rc [catch {db restore temp bu3.db} res]
lappend rc $res
@@ -151,7 +151,7 @@ if {$tcl_platform(platform)=="windows"} {
}
if {$tcl_platform(platform)!="windows"} {
do_test backup2-10 {
- file delete -force bu3.db
+ forcedelete bu3.db
file mkdir bu3.db
set rc [catch {db restore temp bu3.db} res]
lappend rc $res
@@ -172,7 +172,7 @@ do_test backup2-12 {
lappend rc $res
} {1 {restore failed: unknown database aux1}}
do_test backup2-13 {
- file delete -force bu4.db
+ forcedelete bu4.db
set rc [catch {db restore bu4.db} res]
lappend rc $res
} {1 {cannot open source database: unable to open database file}}
@@ -184,6 +184,6 @@ do_test backup2-14 {
lappend rc $res
} {1 {wrong # args: should be "db restore ?DATABASE? FILENAME"}}
-file delete -force bu1.db bu2.db bu3.db bu4.db
+forcedelete bu1.db bu2.db bu3.db bu4.db
finish_test
diff --git a/test/backup_ioerr.test b/test/backup_ioerr.test
index 3b5e95df..313cff3d 100644
--- a/test/backup_ioerr.test
+++ b/test/backup_ioerr.test
@@ -60,7 +60,7 @@ do_test backup_ioerr-1.2 {
} {1}
do_test backup_ioerr-1.3 {
db close
- file delete -force test.db
+ forcedelete test.db
} {}
# Turn off IO error simulation.
@@ -155,8 +155,8 @@ for {set iError 1} {$bStop == 0} {incr iError} {
catch { ddb close }
catch { sdb close }
- catch { file delete -force test.db }
- catch { file delete -force bak.db }
+ catch { forcedelete test.db }
+ catch { forcedelete bak.db }
# Open the source and destination databases.
sqlite3 sdb test.db
diff --git a/test/capi3.test b/test/capi3.test
index cc1461a7..cbba04cd 100644
--- a/test/capi3.test
+++ b/test/capi3.test
@@ -697,7 +697,7 @@ if {![sqlite3 -has-codec]} {
# Now test that the library correctly handles bogus entries in the
# sqlite_master table (schema corruption).
do_test capi3-8.1 {
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
CREATE TABLE t1(a);
@@ -722,7 +722,7 @@ if {![sqlite3 -has-codec]} {
# Build a 5-field row record. The first field is a string 'table', and
# subsequent fields are all NULL.
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
CREATE TABLE t1(a);
@@ -739,8 +739,8 @@ if {![sqlite3 -has-codec]} {
} {1 {malformed database schema (?)}}
db close
}
-file delete -force test.db
-file delete -force test.db-journal
+forcedelete test.db
+forcedelete test.db-journal
# Test the english language string equivalents for sqlite error codes
diff --git a/test/capi3c.test b/test/capi3c.test
index af979438..c1d5510b 100644
--- a/test/capi3c.test
+++ b/test/capi3c.test
@@ -670,7 +670,7 @@ if {![sqlite3 -has-codec]} {
# Now test that the library correctly handles bogus entries in the
# sqlite_master table (schema corruption).
do_test capi3c-8.1 {
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
CREATE TABLE t1(a);
@@ -695,7 +695,7 @@ if {![sqlite3 -has-codec]} {
# Build a 5-field row record. The first field is a string 'table', and
# subsequent fields are all NULL.
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
CREATE TABLE t1(a);
@@ -712,8 +712,8 @@ if {![sqlite3 -has-codec]} {
} {1 {malformed database schema (?)}}
db close
}
-file delete -force test.db
-file delete -force test.db-journal
+forcedelete test.db
+forcedelete test.db-journal
# Test the english language string equivalents for sqlite error codes
diff --git a/test/collate5.test b/test/collate5.test
index 2e4b89d5..e5bea7a5 100644
--- a/test/collate5.test
+++ b/test/collate5.test
@@ -57,17 +57,17 @@ do_test collate5-1.1 {
execsql {
SELECT DISTINCT a FROM collate5t1;
}
-} {A B N}
+} {a b n}
do_test collate5-1.2 {
execsql {
SELECT DISTINCT b FROM collate5t1;
}
-} {{} Apple apple banana}
+} {apple Apple banana {}}
do_test collate5-1.3 {
execsql {
SELECT DISTINCT a, b FROM collate5t1;
}
-} {A Apple a apple B banana N {}}
+} {a apple A Apple b banana n {}}
# Ticket #3376
#
diff --git a/test/collate7.test b/test/collate7.test
index 22b67310..da97491e 100644
--- a/test/collate7.test
+++ b/test/collate7.test
@@ -44,7 +44,7 @@ do_test collate7-1.4 {
} {2}
do_test collate7-2.1 {
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
sqlite3_create_collation_v2 db CASELESS caseless_cmp {incr ::caseless_del}
execsql {
diff --git a/test/corrupt.test b/test/corrupt.test
index 719c19cc..09f3c5bd 100644
--- a/test/corrupt.test
+++ b/test/corrupt.test
@@ -15,7 +15,7 @@
#
# $Id: corrupt.test,v 1.12 2009/07/13 09:41:45 danielk1977 Exp $
-catch {file delete -force test.db test.db-journal test.bu}
+catch {forcedelete test.db test.db-journal test.bu}
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -51,22 +51,10 @@ do_test corrupt-1.1 {
} {}
integrity_check corrupt-1.2
-# Copy file $from into $to
-#
-proc copy_file {from to} {
- set f [open $from]
- fconfigure $f -translation binary
- set t [open $to w]
- fconfigure $t -translation binary
- puts -nonewline $t [read $f [file size $from]]
- close $t
- close $f
-}
-
# Setup for the tests. Make a backup copy of the good database in test.bu.
# Create a string of garbage data that is 256 bytes long.
#
-copy_file test.db test.bu
+forcecopy test.db test.bu
set fsize [file size test.db]
set junk "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
while {[string length $junk]<256} {append junk $junk}
@@ -79,7 +67,7 @@ set junk [string range $junk 0 255]
for {set i [expr {1*256}]} {$i<$fsize-256} {incr i 256} {
set tn [expr {$i/256}]
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
set fd [open test.db r+]
fconfigure $fd -translation binary
seek $fd $i
@@ -132,7 +120,7 @@ for {set i [expr {1*256}]} {$i<$fsize-256} {incr i 256} {
#
do_test corrupt-3.1 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
sqlite3 db test.db
list
} {}
@@ -181,7 +169,7 @@ do_test corrupt-3.6 {
do_test corrupt-4.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
PRAGMA page_size = 1024;
@@ -213,7 +201,7 @@ do_test corrupt-4.2 {
do_test corrupt-5.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql { PRAGMA page_size = 1024 }
@@ -236,7 +224,7 @@ do_test corrupt-5.2 {
# running this testcase under valgrind revealed the problem.
do_test corrupt-6.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
PRAGMA page_size = 1024; CREATE TABLE t1(x);
@@ -264,7 +252,7 @@ do_test corrupt-6.1 {
ifcapable oversize_cell_check {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
PRAGMA page_size = 1024; CREATE TABLE t1(x);
@@ -317,7 +305,7 @@ ifcapable oversize_cell_check {
}
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
do_test corrupt-8.1 {
sqlite3 db test.db
execsql {
@@ -335,7 +323,7 @@ do_test corrupt-8.1 {
} {1 {database disk image is malformed}}
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
do_test corrupt-8.2 {
sqlite3 db test.db
execsql {
diff --git a/test/corrupt2.test b/test/corrupt2.test
index bdbc0165..744a76ed 100644
--- a/test/corrupt2.test
+++ b/test/corrupt2.test
@@ -41,9 +41,9 @@ do_test corrupt2-1.1 {
do_test corrupt2-1.2 {
# Corrupt the 16 byte magic string at the start of the file
- file delete -force corrupt.db
- file delete -force corrupt.db-journal
- copy_file test.db corrupt.db
+ forcedelete corrupt.db
+ forcedelete corrupt.db-journal
+ forcecopy test.db corrupt.db
set f [open corrupt.db RDWR]
seek $f 8 start
puts $f blah
@@ -60,9 +60,9 @@ do_test corrupt2-1.3 {
db2 close
# Corrupt the page-size (bytes 16 and 17 of page 1).
- file delete -force corrupt.db
- file delete -force corrupt.db-journal
- copy_file test.db corrupt.db
+ forcedelete corrupt.db
+ forcedelete corrupt.db-journal
+ forcecopy test.db corrupt.db
set f [open corrupt.db RDWR]
fconfigure $f -encoding binary
seek $f 16 start
@@ -80,9 +80,9 @@ do_test corrupt2-1.4 {
db2 close
# Corrupt the free-block list on page 1.
- file delete -force corrupt.db
- file delete -force corrupt.db-journal
- copy_file test.db corrupt.db
+ forcedelete corrupt.db
+ forcedelete corrupt.db-journal
+ forcecopy test.db corrupt.db
set f [open corrupt.db RDWR]
fconfigure $f -encoding binary
seek $f 101 start
@@ -100,9 +100,9 @@ do_test corrupt2-1.5 {
db2 close
# Corrupt the free-block list on page 1.
- file delete -force corrupt.db
- file delete -force corrupt.db-journal
- copy_file test.db corrupt.db
+ forcedelete corrupt.db
+ forcedelete corrupt.db-journal
+ forcecopy test.db corrupt.db
set f [open corrupt.db RDWR]
fconfigure $f -encoding binary
seek $f 101 start
@@ -123,9 +123,9 @@ db2 close
# Corrupt a database by having 2 indices of the same name:
do_test corrupt2-2.1 {
- file delete -force corrupt.db
- file delete -force corrupt.db-journal
- copy_file test.db corrupt.db
+ forcedelete corrupt.db
+ forcedelete corrupt.db-journal
+ forcecopy test.db corrupt.db
sqlite3 db2 corrupt.db
execsql "
@@ -150,8 +150,8 @@ do_test corrupt2-2.1 {
db2 close
do_test corrupt2-3.1 {
- file delete -force corrupt.db
- file delete -force corrupt.db-journal
+ forcedelete corrupt.db
+ forcedelete corrupt.db-journal
sqlite3 db2 corrupt.db
execsql "
@@ -200,8 +200,8 @@ db2 close
unset -nocomplain result
do_test corrupt2-5.1 {
- file delete -force corrupt.db
- file delete -force corrupt.db-journal
+ forcedelete corrupt.db
+ forcedelete corrupt.db-journal
sqlite3 db2 corrupt.db
execsql "
@@ -257,8 +257,8 @@ proc corruption_test {args} {
array set A $args
catch {db close}
- file delete -force corrupt.db
- file delete -force corrupt.db-journal
+ forcedelete corrupt.db
+ forcedelete corrupt.db-journal
sqlite3 db corrupt.db
db eval $::presql
diff --git a/test/corrupt3.test b/test/corrupt3.test
index fba3ba79..a3827227 100644
--- a/test/corrupt3.test
+++ b/test/corrupt3.test
@@ -25,7 +25,7 @@ do_not_use_codec
# We must have the page_size pragma for these tests to work.
#
-ifcapable !pager_pragmas {
+ifcapable !pager_pragmas||direct_read {
finish_test
return
}
diff --git a/test/corrupt9.test b/test/corrupt9.test
index f083cf24..f199452f 100644
--- a/test/corrupt9.test
+++ b/test/corrupt9.test
@@ -86,7 +86,7 @@ integrity_check corrupt9-1.2
# Make sure the corruption is detected.
#
db close
-file copy -force test.db test.db-template
+forcecopy test.db test.db-template
corrupt_freelist test.db 1
sqlite3 db test.db
@@ -103,7 +103,7 @@ do_test corrupt9-2.2 {
db close
-file copy -force test.db-template test.db
+forcecopy test.db-template test.db
corrupt_freelist test.db 2
sqlite3 db test.db
do_test corrupt9-3.1 {
@@ -118,7 +118,7 @@ do_test corrupt9-3.2 {
} {1 {database disk image is malformed}}
db close
-file copy -force test.db-template test.db
+forcecopy test.db-template test.db
corrupt_freelist test.db 3
sqlite3 db test.db
do_test corrupt9-4.1 {
diff --git a/test/corruptA.test b/test/corruptA.test
index 9c7d228f..8b76d3a2 100644
--- a/test/corruptA.test
+++ b/test/corruptA.test
@@ -40,12 +40,12 @@ integrity_check corruptA-1.2
# is detected when opening the database file.
#
db close
-file copy -force test.db test.db-template
+forcecopy test.db test.db-template
set unreadable_version 02
ifcapable wal { set unreadable_version 03 }
do_test corruptA-2.1 {
- file copy -force test.db-template test.db
+ forcecopy test.db-template test.db
hexio_write test.db 19 $unreadable_version ;# the read format number
sqlite3 db test.db
catchsql {SELECT * FROM t1}
@@ -53,7 +53,7 @@ do_test corruptA-2.1 {
do_test corruptA-2.2 {
db close
- file copy -force test.db-template test.db
+ forcecopy test.db-template test.db
hexio_write test.db 21 41 ;# max embedded payload fraction
sqlite3 db test.db
catchsql {SELECT * FROM t1}
@@ -61,7 +61,7 @@ do_test corruptA-2.2 {
do_test corruptA-2.3 {
db close
- file copy -force test.db-template test.db
+ forcecopy test.db-template test.db
hexio_write test.db 22 1f ;# min embedded payload fraction
sqlite3 db test.db
catchsql {SELECT * FROM t1}
@@ -69,7 +69,7 @@ do_test corruptA-2.3 {
do_test corruptA-2.4 {
db close
- file copy -force test.db-template test.db
+ forcecopy test.db-template test.db
hexio_write test.db 23 21 ;# min leaf payload fraction
sqlite3 db test.db
catchsql {SELECT * FROM t1}
diff --git a/test/corruptB.test b/test/corruptB.test
index 4aa1d010..0ff2d6e9 100644
--- a/test/corruptB.test
+++ b/test/corruptB.test
@@ -46,7 +46,7 @@ do_test corruptB-1.1 {
} {1}
integrity_check corruptB-1.2
-file copy -force test.db bak.db
+forcecopy test.db bak.db
# Set the right-child of a B-Tree rootpage to refer to the root-page itself.
#
@@ -65,7 +65,7 @@ do_test corruptB-1.3.2 {
#
do_test corruptB-1.4.1 {
db close
- file copy -force bak.db test.db
+ forcecopy bak.db test.db
set cell_offset [hexio_get_int [hexio_read test.db [expr $offset+12] 2]]
hexio_write test.db [expr $offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
@@ -78,7 +78,7 @@ do_test corruptB-1.4.2 {
#
do_test corruptB-1.5.1 {
db close
- file copy -force bak.db test.db
+ forcecopy bak.db test.db
sqlite3 db test.db
execsql {
INSERT INTO t1 SELECT randomblob(200) FROM t1;
@@ -91,7 +91,7 @@ do_test corruptB-1.5.1 {
}
} {}
-file copy -force test.db bak.db
+forcecopy test.db bak.db
# Set the right-child pointer of the right-child of the root page to point
# back to the root page.
@@ -112,7 +112,7 @@ do_test corruptB-1.6.2 {
#
do_test corruptB-1.7.1 {
db close
- file copy -force bak.db test.db
+ forcecopy bak.db test.db
set cell_offset [hexio_get_int [hexio_read test.db [expr $c_offset+12] 2]]
hexio_write test.db [expr $c_offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
@@ -140,7 +140,7 @@ do_test corruptB-1.8.2 {
#
do_test corruptB-1.9.1 {
db close
- file copy -force bak.db test.db
+ forcecopy bak.db test.db
set cell_offset [hexio_get_int [hexio_read test.db [expr $c_offset+12] 2]]
hexio_write test.db [expr $c_offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
@@ -153,7 +153,7 @@ do_test corruptB-1.9.2 {
do_test corruptB-2.1.1 {
db close
- file copy -force bak.db test.db
+ forcecopy bak.db test.db
hexio_write test.db [expr $offset+8] [hexio_render_int32 0x6FFFFFFF]
} {4}
do_test corruptB-2.1.2 {
@@ -167,7 +167,7 @@ do_test corruptB-2.1.2 {
#
do_test corruptB-3.1.1 {
db close
- file copy -force bak.db test.db
+ forcecopy bak.db test.db
sqlite3 db test.db
set v [string repeat abcdefghij 200]
execsql {
diff --git a/test/corruptC.test b/test/corruptC.test
index 05804263..34e81a1b 100644
--- a/test/corruptC.test
+++ b/test/corruptC.test
@@ -17,7 +17,7 @@
#
# $Id: corruptC.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $
-catch {file delete -force test.db test.db-journal test.bu}
+catch {forcedelete test.db test.db-journal test.bu}
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -58,16 +58,10 @@ proc random {range} {
return [expr {round(rand()*$range)}]
}
-# Copy file $from into $to
-#
-proc copy_file {from to} {
- file copy -force $from $to
-}
-
# Setup for the tests. Make a backup copy of the good database in test.bu.
#
db close
-copy_file test.db test.bu
+forcecopy test.db test.bu
sqlite3 db test.db
set fsize [file size test.db]
@@ -92,7 +86,7 @@ expr srand($qseed)
# test that a corrupt content offset size is handled (seed 5577)
do_test corruptC-2.1 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 2053 [format %02x 0x04]
@@ -104,7 +98,7 @@ do_test corruptC-2.1 {
# test that a corrupt content offset size is handled (seed 5649)
do_test corruptC-2.2 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 27 [format %02x 0x08]
@@ -125,7 +119,7 @@ do_test corruptC-2.2 {
# test that a corrupt free cell size is handled (seed 13329)
do_test corruptC-2.3 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 1094 [format %02x 0x76]
@@ -137,7 +131,7 @@ do_test corruptC-2.3 {
# test that a corrupt free cell size is handled (seed 169571)
do_test corruptC-2.4 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 3119 [format %02x 0xdf]
@@ -149,7 +143,7 @@ do_test corruptC-2.4 {
# test that a corrupt free cell size is handled (seed 169571)
do_test corruptC-2.5 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 3119 [format %02x 0xdf]
@@ -169,7 +163,7 @@ Page 4: btreeInitPage() returns error code 11}}}
# test that a corrupt free cell size is handled (seed 169595)
do_test corruptC-2.6 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 619 [format %02x 0xe2]
@@ -182,7 +176,7 @@ do_test corruptC-2.6 {
# corruption (seed 178692)
do_test corruptC-2.7 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 3074 [format %02x 0xa0]
@@ -194,7 +188,7 @@ do_test corruptC-2.7 {
# corruption (seed 179069)
do_test corruptC-2.8 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 1393 [format %02x 0x7d]
@@ -210,7 +204,7 @@ do_test corruptC-2.8 {
# corruption (seed 170434)
do_test corruptC-2.9 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 2095 [format %02x 0xd6]
@@ -222,7 +216,7 @@ do_test corruptC-2.9 {
# corruption (seed 186504)
do_test corruptC-2.10 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 3130 [format %02x 0x02]
@@ -234,7 +228,7 @@ do_test corruptC-2.10 {
# corruption (seed 1589)
do_test corruptC-2.11 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 55 [format %02x 0xa7]
@@ -246,7 +240,7 @@ do_test corruptC-2.11 {
# corruption (seed 14166)
do_test corruptC-2.12 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 974 [format %02x 0x2e]
@@ -258,7 +252,7 @@ do_test corruptC-2.12 {
# corruption (seed 218803)
do_test corruptC-2.13 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 102 [format %02x 0x12]
@@ -269,7 +263,7 @@ do_test corruptC-2.13 {
do_test corruptC-2.14 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
sqlite3 db test.db
set blob [string repeat abcdefghij 10000]
@@ -286,7 +280,7 @@ do_test corruptC-2.14 {
#
do_test corruptC-2.15 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
hexio_write test.db 986 b9
sqlite3 db test.db
catchsql {SELECT count(*) FROM sqlite_master;}
@@ -300,7 +294,7 @@ for {set tn 0} {$tn<$fsize} {incr tn 1} {
# setup for test
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
sqlite3 db test.db
# Seek to a random location in the file, and write a random single byte
diff --git a/test/corruptD.test b/test/corruptD.test
index 61dada65..393d41ee 100644
--- a/test/corruptD.test
+++ b/test/corruptD.test
@@ -85,7 +85,7 @@ do_test corruptD-1.0 {
DELETE FROM t1 WHERE a = 30;
DELETE FROM t1 WHERE a = 40;
}
- copy_file test.db test.bu
+ forcecopy test.db test.bu
} {}
proc incr_change_counter {} {
@@ -96,7 +96,7 @@ proc incr_change_counter {} {
proc restore_file {} {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
sqlite3 db test.db
}
diff --git a/test/corruptE.test b/test/corruptE.test
index a47adba1..507721d8 100644
--- a/test/corruptE.test
+++ b/test/corruptE.test
@@ -16,8 +16,6 @@
#
# $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $
-catch {file delete -force test.db test.db-journal test.bu}
-
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -60,23 +58,17 @@ ifcapable {integrityck} {
integrity_check corruptE-1.2
}
-# Copy file $from into $to
-#
-proc copy_file {from to} {
- file copy -force $from $to
-}
-
# Setup for the tests. Make a backup copy of the good database in test.bu.
#
db close
-copy_file test.db test.bu
+forcecopy test.db test.bu
sqlite3 db test.db
set fsize [file size test.db]
do_test corruptE-2.1 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 2041 [format %02x 0x2e]
@@ -92,7 +84,7 @@ do_test corruptE-2.1 {
do_test corruptE-2.2 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 2047 [format %02x 0x84]
@@ -108,7 +100,7 @@ do_test corruptE-2.2 {
do_test corruptE-2.3 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 7420 [format %02x 0xa8]
@@ -124,7 +116,7 @@ do_test corruptE-2.3 {
do_test corruptE-2.4 {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 10233 [format %02x 0xd0]
@@ -165,7 +157,7 @@ set tc 1
foreach test $tests {
do_test corruptE-3.$tc {
db close
- copy_file test.bu test.db
+ forcecopy test.bu test.db
# insert corrupt byte(s)
hexio_write test.db [lindex $test 0] [format %02x [lindex $test 1]]
diff --git a/test/crash.test b/test/crash.test
index 42f41a36..f644dcaf 100644
--- a/test/crash.test
+++ b/test/crash.test
@@ -215,8 +215,8 @@ for {set i 1} {$i < $repeats} {incr i} {
#
ifcapable attach {
do_test crash-4.0 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
ATTACH 'test2.db' AS aux;
PRAGMA aux.default_cache_size = 10;
@@ -318,7 +318,7 @@ ifcapable attach {
# in test crash-5.3 for details.
#
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
do_test crash-5.1 {
execsql {
diff --git a/test/crash3.test b/test/crash3.test
index 9b7a6784..7958af99 100644
--- a/test/crash3.test
+++ b/test/crash3.test
@@ -73,7 +73,7 @@ foreach {sql res2} [list \
for {set ii 0} {$ii < 10} {incr ii} {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
do_test crash3-1.$tn.1 {
execsql {
@@ -106,7 +106,7 @@ foreach {sql res2} [list \
# This block tests both the IOCAP_SEQUENTIAL and IOCAP_SAFE_APPEND flags.
#
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
do_test crash3-2.0 {
execsql {
@@ -177,7 +177,7 @@ foreach {::crashfile ::delay ::char} {
#
for {set ii 0} {$ii < 10} {incr ii} {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
crashsql -file test.db -char {sequential atomic} {
CREATE TABLE abc(a, b, c);
}
diff --git a/test/crash4.test b/test/crash4.test
index 839299b5..f68caecd 100644
--- a/test/crash4.test
+++ b/test/crash4.test
@@ -63,7 +63,7 @@ foreach cmd $sql_cmd_list {
#
for {set cnt 1; set fin 0} {!$fin} {incr cnt} {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
do_test crash4-1.$cnt.1 {
set seed [expr {int(abs(rand()*10000))}]
set delay [expr {int($cnt/50)+1}]
diff --git a/test/crash5.test b/test/crash5.test
index e8faa01b..42248d71 100644
--- a/test/crash5.test
+++ b/test/crash5.test
@@ -34,7 +34,7 @@ for {set ii 0} {$ii < 10} {incr ii} {
# Set up the database so that it is an auto-vacuum database
# containing a single table (root page 3) with a single row.
# The row has an overflow page (page 4).
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
set c [string repeat 3 1500]
db eval {
diff --git a/test/crash6.test b/test/crash6.test
index d5ee439f..69c19464 100644
--- a/test/crash6.test
+++ b/test/crash6.test
@@ -23,7 +23,7 @@ ifcapable !crashtest {
for {set ii 0} {$ii < 10} {incr ii} {
catch {db close}
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
crashsql -delay 2 -file test.db {
PRAGMA auto_vacuum=OFF;
PRAGMA page_size=4096;
@@ -40,7 +40,7 @@ for {set ii 0} {$ii < 10} {incr ii} {
for {set ii 0} {$ii < 10} {incr ii} {
catch {db close}
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
PRAGMA auto_vacuum=OFF;
@@ -66,7 +66,7 @@ proc signature {} {
#
for {set ii 0} {$ii < 30} {incr ii} {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
set pagesize [expr 1024 << ($ii % 4)]
diff --git a/test/crash7.test b/test/crash7.test
index fc0596a8..4554a2ac 100644
--- a/test/crash7.test
+++ b/test/crash7.test
@@ -26,7 +26,7 @@ proc signature {} {
foreach f [list test.db test.db-journal] {
for {set ii 1} {$ii < 64} {incr ii} {
db close
- file delete test.db
+ delete_file test.db
sqlite3 db test.db
set from_size [expr 1024 << ($ii&3)]
diff --git a/test/crash8.test b/test/crash8.test
index 6424a1ab..8bc25865 100644
--- a/test/crash8.test
+++ b/test/crash8.test
@@ -243,7 +243,7 @@ do_test crash8-3.11 {
#
ifcapable pragma {
reset_db
- file delete -force test2.db
+ forcedelete test2.db
do_test crash8-4.1 {
execsql {
@@ -336,14 +336,14 @@ ifcapable pragma {
} {def}
do_test crash8-4.10 {
- file delete $zMasterJournal
+ delete_file $zMasterJournal
execsql { SELECT b FROM main.ab WHERE a = 0 }
} {jkl}
}
for {set i 1} {$i < 10} {incr i} {
catch { db close }
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
do_test crash8-5.$i.1 {
execsql {
@@ -367,7 +367,7 @@ for {set i 1} {$i < 10} {incr i} {
} {ok}
catch { db close }
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
do_test crash8-5.$i.2 {
execsql {
@@ -383,9 +383,9 @@ for {set i 1} {$i < 10} {incr i} {
BEGIN;
UPDATE t1 SET x = randomblob(900);
}
- file delete -force testX.db testX.db-journal testX.db-wal
- copy_file test.db testX.db
- copy_file test.db-journal testX.db-journal
+ forcedelete testX.db testX.db-journal testX.db-wal
+ forcecopy test.db testX.db
+ forcecopy test.db-journal testX.db-journal
db close
crashsql -file test.db -delay [expr ($::i%2) + 1] {
diff --git a/test/createtab.test b/test/createtab.test
index 3f036b76..01e0b612 100644
--- a/test/createtab.test
+++ b/test/createtab.test
@@ -27,7 +27,7 @@ ifcapable autovacuum {
#
for {set av 0} {$av<=$upperBound} {incr av} {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
# Create a table that spans multiple pages. It is important
diff --git a/test/dbstatus.test b/test/dbstatus.test
index 202f34a0..e1c8f3eb 100644
--- a/test/dbstatus.test
+++ b/test/dbstatus.test
@@ -56,6 +56,12 @@ proc lookaside {db} {
}
}
+ifcapable stat3 {
+ set STAT3 1
+} else {
+ set STAT3 0
+}
+
#---------------------------------------------------------------------------
# Run the dbstatus-2 and dbstatus-3 tests with several of different
# lookaside buffer sizes.
@@ -118,7 +124,7 @@ foreach ::lookaside_buffer_size {0 64 120} {
CREATE TABLE t2(c, d);
CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
}
- 6 {
+ 6y {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(a,b);
@@ -155,7 +161,7 @@ foreach ::lookaside_buffer_size {0 64 120} {
# Step 1.
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
db cache size 0
@@ -198,7 +204,11 @@ foreach ::lookaside_buffer_size {0 64 120} {
# much greater than just that reported by DBSTATUS_SCHEMA_USED in this
# case.
#
- if {[string match *x $tn] || $AUTOVACUUM} {
+ # Some of the memory used for sqlite_stat3 is unaccounted for by
+ # dbstatus.
+ #
+ if {[string match *x $tn] || $AUTOVACUUM
+ || ([string match *y $tn] && $STAT3)} {
do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
} else {
do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
@@ -287,7 +297,7 @@ foreach ::lookaside_buffer_size {0 64 120} {
# Step 1.
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
db cache size 1000
diff --git a/test/dbstatus2.test b/test/dbstatus2.test
new file mode 100644
index 00000000..4dfa9b8e
--- /dev/null
+++ b/test/dbstatus2.test
@@ -0,0 +1,76 @@
+# 2011 September 20
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# Tests for the sqlite3_stmt_status() function
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set ::testprefix dbstatus2
+
+do_execsql_test 1.0 {
+ PRAGMA page_size = 1024;
+ PRAGMA auto_vacuum = 0;
+
+ CREATE TABLE t1(a PRIMARY KEY, b);
+ INSERT INTO t1 VALUES(1, randomblob(600));
+ INSERT INTO t1 VALUES(2, randomblob(600));
+ INSERT INTO t1 VALUES(3, randomblob(600));
+}
+
+proc db_hit_miss {db {reset 0}} {
+ set nHit [sqlite3_db_status $db CACHE_HIT $reset]
+ set nMiss [sqlite3_db_status $db CACHE_MISS $reset]
+ list $nHit $nMiss
+}
+
+do_test 1.1 {
+ db close
+ sqlite3 db test.db
+ expr {[file size test.db] / 1024}
+} 6
+
+do_test 1.2 {
+ execsql { SELECT b FROM t1 WHERE a=2 }
+ db_hit_miss db
+} {{0 2 0} {0 4 0}}
+
+do_test 1.3 {
+ execsql { SELECT b FROM t1 WHERE a=2 }
+ db_hit_miss db
+} {{0 6 0} {0 4 0}}
+
+do_test 1.4 {
+ execsql { SELECT b FROM t1 WHERE a=2 }
+ db_hit_miss db
+} {{0 10 0} {0 4 0}}
+
+do_test 1.5 {
+ db_hit_miss db 1
+} {{0 10 0} {0 4 0}}
+
+do_test 1.6 {
+ db_hit_miss db 0
+} {{0 0 0} {0 0 0}}
+
+do_test 1.7 {
+ set fd [db incrblob main t1 b 1]
+ fconfigure $fd -translation binary
+ set len [string length [read $fd]]
+ close $fd
+ set len
+} 600
+do_test 1.8 { sqlite3_db_status db CACHE_HIT 0 } {0 2 0}
+do_test 1.9 { sqlite3_db_status db CACHE_MISS 0 } {0 1 0}
+
+
+finish_test
diff --git a/test/delete.test b/test/delete.test
index 61e979ef..47d35781 100644
--- a/test/delete.test
+++ b/test/delete.test
@@ -275,7 +275,7 @@ do_test delete-8.0 {
}
} {123}
db close
-catch {file delete -force test.db-journal}
+catch {forcedelete test.db-journal}
catch {file attributes test.db -permissions 0444}
catch {file attributes test.db -readonly 1}
sqlite3 db test.db
@@ -312,12 +312,12 @@ do_test delete-8.6 {
integrity_check delete-8.7
# Need to do the following for tcl 8.5 on mac. On that configuration, the
-# -readonly flag is taken so seriously that a subsequent [file delete -force]
+# -readonly flag is taken so seriously that a subsequent [forcedelete]
# (required before the next test file can be executed) will fail.
#
catch {file attributes test.db -readonly 0}
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
# The following tests verify that SQLite correctly handles the case
# where an index B-Tree is being scanned, the rowid column being read
diff --git a/test/descidx1.test b/test/descidx1.test
index 1154dc56..c7fab340 100644
--- a/test/descidx1.test
+++ b/test/descidx1.test
@@ -297,14 +297,14 @@ do_test descidx1-5.9 {
ifcapable legacyformat {
do_test descidx1-6.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {PRAGMA legacy_file_format}
} {1}
} else {
do_test descidx1-6.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {PRAGMA legacy_file_format}
} {0}
@@ -328,7 +328,7 @@ ifcapable vacuum {
}
do_test descidx1-6.4 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {PRAGMA legacy_file_format=NO}
execsql {PRAGMA legacy_file_format}
diff --git a/test/diskfull.test b/test/diskfull.test
index a71db91e..391dfb4f 100644
--- a/test/diskfull.test
+++ b/test/diskfull.test
@@ -82,8 +82,8 @@ proc do_diskfull_test {prefix sql} {
do_diskfull_test diskfull-2 VACUUM
# db close
-# file delete -force test.db
-# file delete -force test.db-journal
+# forcedelete test.db
+# forcedelete test.db-journal
# sqlite3 db test.db
#
# do_test diskfull-3.1 {
diff --git a/test/distinct.test b/test/distinct.test
new file mode 100644
index 00000000..e0a91360
--- /dev/null
+++ b/test/distinct.test
@@ -0,0 +1,166 @@
+# 2011 July 1
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is the DISTINCT modifier.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set testprefix distinct
+
+
+proc is_distinct_noop {sql} {
+ set sql1 $sql
+ set sql2 [string map {DISTINCT ""} $sql]
+
+ set program1 [list]
+ set program2 [list]
+ db eval "EXPLAIN $sql1" {
+ if {$opcode != "Noop"} { lappend program1 $opcode }
+ }
+ db eval "EXPLAIN $sql2" {
+ if {$opcode != "Noop"} { lappend program2 $opcode }
+ }
+
+ return [expr {$program1==$program2}]
+}
+
+proc do_distinct_noop_test {tn sql} {
+ uplevel [list do_test $tn [list is_distinct_noop $sql] 1]
+}
+proc do_distinct_not_noop_test {tn sql} {
+ uplevel [list do_test $tn [list is_distinct_noop $sql] 0]
+}
+
+proc do_temptables_test {tn sql temptables} {
+ uplevel [list do_test $tn [subst -novar {
+ set ret ""
+ db eval "EXPLAIN [set sql]" {
+ if {$opcode == "OpenEphemeral" || $opcode == "SorterOpen"} {
+ if {$p5 != "10" && $p5!="00"} { error "p5 = $p5" }
+ if {$p5 == "10"} {
+ lappend ret hash
+ } else {
+ lappend ret btree
+ }
+ }
+ }
+ set ret
+ }] $temptables]
+}
+
+
+#-------------------------------------------------------------------------
+# The following tests - distinct-1.* - check that the planner correctly
+# detects cases where a UNIQUE index means that a DISTINCT clause is
+# redundant. Currently the planner only detects such cases when there
+# is a single table in the FROM clause.
+#
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a, b, c, d);
+ CREATE UNIQUE INDEX i1 ON t1(b, c);
+ CREATE UNIQUE INDEX i2 ON t1(d COLLATE nocase);
+
+ CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
+
+ CREATE TABLE t3(c1 PRIMARY KEY, c2);
+ CREATE INDEX i3 ON t3(c2);
+}
+foreach {tn noop sql} {
+
+ 1 1 "SELECT DISTINCT b, c FROM t1"
+ 2 1 "SELECT DISTINCT c FROM t1 WHERE b = ?"
+ 3 1 "SELECT DISTINCT rowid FROM t1"
+ 4 1 "SELECT DISTINCT rowid, a FROM t1"
+ 5 1 "SELECT DISTINCT x FROM t2"
+ 6 1 "SELECT DISTINCT * FROM t2"
+ 7 1 "SELECT DISTINCT * FROM (SELECT * FROM t2)"
+
+ 8 1 "SELECT DISTINCT * FROM t1"
+
+ 8 0 "SELECT DISTINCT a, b FROM t1"
+
+ 9 0 "SELECT DISTINCT c FROM t1 WHERE b IN (1,2)"
+ 10 0 "SELECT DISTINCT c FROM t1"
+ 11 0 "SELECT DISTINCT b FROM t1"
+
+ 12 0 "SELECT DISTINCT a, d FROM t1"
+ 13 0 "SELECT DISTINCT a, b, c COLLATE nocase FROM t1"
+ 14 1 "SELECT DISTINCT a, d COLLATE nocase FROM t1"
+ 15 0 "SELECT DISTINCT a, d COLLATE binary FROM t1"
+ 16 1 "SELECT DISTINCT a, b, c COLLATE binary FROM t1"
+
+ 16 0 "SELECT DISTINCT t1.rowid FROM t1, t2"
+ 17 0 { /* Technically, it would be possible to detect that DISTINCT
+ ** is a no-op in cases like the following. But SQLite does not
+ ** do so. */
+ SELECT DISTINCT t1.rowid FROM t1, t2 WHERE t1.rowid=t2.rowid }
+
+ 18 1 "SELECT DISTINCT c1, c2 FROM t3"
+ 19 1 "SELECT DISTINCT c1 FROM t3"
+ 20 1 "SELECT DISTINCT * FROM t3"
+ 21 0 "SELECT DISTINCT c2 FROM t3"
+
+ 22 0 "SELECT DISTINCT * FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
+ 23 1 "SELECT DISTINCT rowid FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
+
+ 24 0 "SELECT DISTINCT rowid/2 FROM t1"
+ 25 1 "SELECT DISTINCT rowid/2, rowid FROM t1"
+ 26 1 "SELECT DISTINCT rowid/2, b FROM t1 WHERE c = ?"
+} {
+ if {$noop} {
+ do_distinct_noop_test 1.$tn $sql
+ } else {
+ do_distinct_not_noop_test 1.$tn $sql
+ }
+}
+
+#-------------------------------------------------------------------------
+# The following tests - distinct-2.* - test cases where an index is
+# used to deliver results in order of the DISTINCT expressions.
+#
+drop_all_tables
+do_execsql_test 2.0 {
+ CREATE TABLE t1(a, b, c);
+
+ CREATE INDEX i1 ON t1(a, b);
+ CREATE INDEX i2 ON t1(b COLLATE nocase, c COLLATE nocase);
+
+ INSERT INTO t1 VALUES('a', 'b', 'c');
+ INSERT INTO t1 VALUES('A', 'B', 'C');
+ INSERT INTO t1 VALUES('a', 'b', 'c');
+ INSERT INTO t1 VALUES('A', 'B', 'C');
+}
+
+foreach {tn sql temptables res} {
+ 1 "a, b FROM t1" {} {A B a b}
+ 2 "b, a FROM t1" {} {B A b a}
+ 3 "a, b, c FROM t1" {hash} {a b c A B C}
+ 4 "a, b, c FROM t1 ORDER BY a, b, c" {btree} {A B C a b c}
+ 5 "b FROM t1 WHERE a = 'a'" {} {b}
+ 6 "b FROM t1" {hash} {b B}
+ 7 "a FROM t1" {} {A a}
+ 8 "b COLLATE nocase FROM t1" {} {b}
+ 9 "b COLLATE nocase FROM t1 ORDER BY b COLLATE nocase" {} {B}
+} {
+ do_execsql_test 2.$tn.1 "SELECT DISTINCT $sql" $res
+ do_temptables_test 2.$tn.2 "SELECT DISTINCT $sql" $temptables
+}
+
+do_execsql_test 2.A {
+ SELECT (SELECT DISTINCT o.a FROM t1 AS i) FROM t1 AS o;
+} {a A a A}
+
+
+
+
+finish_test
diff --git a/test/e_expr.test b/test/e_expr.test
index b61b42da..3c9678c3 100644
--- a/test/e_expr.test
+++ b/test/e_expr.test
@@ -657,7 +657,7 @@ set sqlite_current_time 0
# EVIDENCE-OF: R-57598-59332 -- syntax diagram expr
#
-file delete -force test.db2
+forcedelete test.db2
execsql {
ATTACH 'test.db2' AS dbname;
CREATE TABLE dbname.tblname(cname);
@@ -1675,7 +1675,7 @@ db3 close
# Test statements related to the EXISTS and NOT EXISTS operators.
#
catch { db close }
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
do_execsql_test e_expr-34.1 {
@@ -1756,7 +1756,7 @@ foreach {tn e1 e2} {
#
catch { db close }
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
do_test e_expr-35.0 {
execsql {
diff --git a/test/e_fts3.test b/test/e_fts3.test
index 3f7ed0e5..2a580ca3 100644
--- a/test/e_fts3.test
+++ b/test/e_fts3.test
@@ -60,7 +60,7 @@ foreach {DO_MALLOC_TEST enc} {
# [foreach] loop is testing with OOM errors, disable the lookaside buffer.
#
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }
db eval "PRAGMA encoding = '$enc'"
@@ -637,7 +637,7 @@ read_test 8.2.2 { PRAGMA table_info(t9c) } {0 c\"1 {} 0 {} 0 1 c'2 {} 0 {} 0}
#
foreach DO_MALLOC_TEST {0 1 2} {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }
diff --git a/test/e_select.test b/test/e_select.test
index 6194872f..e0f5f0fb 100644
--- a/test/e_select.test
+++ b/test/e_select.test
@@ -1238,8 +1238,8 @@ do_select_tests e_select-5 {
3.1 "SELECT x FROM h2" {One Two Three Four one two three four}
3.2 "SELECT x FROM h1, h2 ON (x=b)" {One one Four four}
- 4.1 "SELECT DISTINCT x FROM h2" {four one three two}
- 4.2 "SELECT DISTINCT x FROM h1, h2 ON (x=b)" {four one}
+ 4.1 "SELECT DISTINCT x FROM h2" {One Two Three Four}
+ 4.2 "SELECT DISTINCT x FROM h1, h2 ON (x=b)" {One Four}
}
# EVIDENCE-OF: R-02054-15343 For the purposes of detecting duplicate
@@ -1253,11 +1253,11 @@ do_select_tests e_select-5.5 {
# sequence to compare text values with apply.
#
do_select_tests e_select-5.6 {
- 1 "SELECT DISTINCT b FROM h1" {I IV four i iv one}
- 2 "SELECT DISTINCT b COLLATE nocase FROM h1" {four i iv one}
- 3 "SELECT DISTINCT x FROM h2" {four one three two}
+ 1 "SELECT DISTINCT b FROM h1" {one I i four IV iv}
+ 2 "SELECT DISTINCT b COLLATE nocase FROM h1" {one I four IV}
+ 3 "SELECT DISTINCT x FROM h2" {One Two Three Four}
4 "SELECT DISTINCT x COLLATE binary FROM h2" {
- Four One Three Two four one three two
+ One Two Three Four one two three four
}
}
diff --git a/test/enc2.test b/test/enc2.test
index ce25bf39..415bc0f7 100644
--- a/test/enc2.test
+++ b/test/enc2.test
@@ -142,7 +142,7 @@ set encodings [list UTF-8 UTF-16le UTF-16be]
set sqlite_os_trace 0
set i 1
foreach enc $encodings {
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
db eval "PRAGMA encoding = \"$enc\""
execsql $dbcontents
@@ -172,13 +172,13 @@ foreach enc $encodings {
# encoding to the main database.
ifcapable attach {
do_test enc2-4.1 {
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
db eval "PRAGMA encoding = 'UTF-8'"
db eval "CREATE TABLE abc(a, b, c);"
} {}
do_test enc2-4.2 {
- file delete -force test2.db
+ forcedelete test2.db
sqlite3 db2 test2.db
db2 eval "PRAGMA encoding = 'UTF-16'"
db2 eval "CREATE TABLE abc(a, b, c);"
@@ -206,7 +206,7 @@ proc test_collate {enc lhs rhs} {
return $res
}
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
do_test enc2-5.0 {
execsql {
@@ -235,7 +235,7 @@ do_test enc2-5.3 {
} {one two three four five UTF-16BE}
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-5.4 {
@@ -265,7 +265,7 @@ do_test enc2-5.7 {
} {one two three four five UTF-8}
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-5.8 {
@@ -311,7 +311,7 @@ do_test enc2-5.14 {
} test_collate
db close
-file delete -force test.db
+forcedelete test.db
do_test enc2-5.15 {
sqlite3 db test.db; set ::DB [sqlite3_connection_pointer db]
@@ -333,7 +333,7 @@ proc test_function {enc arg} {
}
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-8'}
do_test enc2-6.0 {
@@ -366,7 +366,7 @@ do_test enc2-6.3 {
} {{UTF-16BE sqlite}}
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-6.3 {
@@ -399,7 +399,7 @@ do_test enc2-6.6 {
} {{UTF-16BE sqlite}}
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-6.7 {
@@ -433,7 +433,7 @@ do_test enc2-6.10 {
db close
-file delete -force test.db
+forcedelete test.db
# The following tests - enc2-7.* - function as follows:
#
@@ -493,7 +493,7 @@ ifcapable {complete} {
# Test that the encoding of an empty database may still be set after the
# (empty) schema has been initialized.
-file delete -force test.db
+forcedelete test.db
do_test enc2-9.1 {
sqlite3 db test.db
execsql {
@@ -537,7 +537,7 @@ do_test enc2-9.5 {
#
do_test enc2-10.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
db eval {
PRAGMA encoding=UTF16;
diff --git a/test/enc3.test b/test/enc3.test
index 44b21793..1d8a2581 100644
--- a/test/enc3.test
+++ b/test/enc3.test
@@ -81,7 +81,7 @@ ifcapable {bloblit && utf16} {
#
ifcapable {utf16 && shared_cache} {
db close
- file delete -force test8.db test8.db-journal
+ forcedelete test8.db test8.db-journal
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
sqlite3 dbaux test8.db
sqlite3 db test.db
@@ -100,7 +100,7 @@ ifcapable {utf16 && shared_cache} {
} dbaux
} {1 {attached databases must use the same text encoding as main database}}
dbaux close
- file delete -force test8.db test8.db-journal
+ forcedelete test8.db test8.db-journal
sqlite3_enable_shared_cache $::enable_shared_cache
}
diff --git a/test/enc4.test b/test/enc4.test
index 7de6e849..94869b6f 100644
--- a/test/enc4.test
+++ b/test/enc4.test
@@ -43,7 +43,7 @@ set vals [list\
set i 1
foreach enc $encodings {
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
db eval "PRAGMA encoding = \"$enc\""
@@ -93,7 +93,7 @@ foreach enc $encodings {
incr i
}
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
do_test enc4-4.1 {
diff --git a/test/errmsg.test b/test/errmsg.test
new file mode 100644
index 00000000..9f8409b1
--- /dev/null
+++ b/test/errmsg.test
@@ -0,0 +1,116 @@
+# 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.
+#
+#***********************************************************************
+# Test that if sqlite3_prepare_v2() is used to prepare a query, the
+# error-message associated with an sqlite3_step() error is available
+# immediately. Whereas if sqlite3_prepare() is used, it is not available
+# until sqlite3_finalize() or sqlite3_reset() has been called.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set testprefix errmsg
+
+# Test organization:
+#
+# errmsg-1.* User-defined SQL function errors
+# errmsg-2.* Errors generated by the VDBE (constraint failures etc.)
+# errmsg-3.* SQLITE_SCHEMA and statement recompilation errors.
+#
+
+proc error_messages_worker {prepare sql schema} {
+ set ret [list]
+
+ set stmt [$prepare db $sql -1 dummy]
+ execsql $schema
+ lappend ret [sqlite3_step $stmt]
+ lappend ret [sqlite3_errmsg db]
+ lappend ret [sqlite3_finalize $stmt]
+ lappend ret [sqlite3_errmsg db]
+
+ set ret
+}
+
+proc error_messages_v2 {sql {schema {}}} {
+ error_messages_worker sqlite3_prepare_v2 $sql $schema
+}
+
+proc error_messages {sql {schema {}}} {
+ error_messages_worker sqlite3_prepare $sql $schema
+}
+
+proc sql_error {msg} { error $msg }
+db func sql_error sql_error
+
+#-------------------------------------------------------------------------
+# Test error messages returned by user-defined SQL functions.
+#
+do_test 1.1 {
+ error_messages "SELECT sql_error('custom message')"
+} [list {*}{
+ SQLITE_ERROR {SQL logic error or missing database}
+ SQLITE_ERROR {custom message}
+}]
+do_test 1.2 {
+ error_messages_v2 "SELECT sql_error('custom message')"
+} [list {*}{
+ SQLITE_ERROR {custom message}
+ SQLITE_ERROR {custom message}
+}]
+
+#-------------------------------------------------------------------------
+# Test error messages generated directly by VDBE code (e.g. constraint
+# failures).
+#
+do_execsql_test 2.1 {
+ CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
+ INSERT INTO t1 VALUES('abc', 'def');
+}
+do_test 2.2 {
+ error_messages "INSERT INTO t1 VALUES('ghi', 'def')"
+} [list {*}{
+ SQLITE_ERROR {SQL logic error or missing database}
+ SQLITE_CONSTRAINT {column b is not unique}
+}]
+do_test 2.3 {
+ error_messages_v2 "INSERT INTO t1 VALUES('ghi', 'def')"
+} [list {*}{
+ SQLITE_CONSTRAINT {column b is not unique}
+ SQLITE_CONSTRAINT {column b is not unique}
+}]
+
+#-------------------------------------------------------------------------
+# Test SQLITE_SCHEMA errors. And, for _v2(), test that if the schema
+# change invalidates the SQL statement itself the error message is returned
+# correctly.
+#
+do_execsql_test 3.1.1 {
+ CREATE TABLE t2(a PRIMARY KEY, b UNIQUE);
+ INSERT INTO t2 VALUES('abc', 'def');
+}
+do_test 3.1.2 {
+ error_messages "SELECT a FROM t2" "DROP TABLE t2"
+} [list {*}{
+ SQLITE_ERROR {SQL logic error or missing database}
+ SQLITE_SCHEMA {database schema has changed}
+}]
+do_execsql_test 3.2.1 {
+ CREATE TABLE t2(a PRIMARY KEY, b UNIQUE);
+ INSERT INTO t2 VALUES('abc', 'def');
+}
+do_test 3.2.2 {
+ error_messages_v2 "SELECT a FROM t2" "DROP TABLE t2"
+} [list {*}{
+ SQLITE_ERROR {no such table: t2}
+ SQLITE_ERROR {no such table: t2}
+}]
+
+finish_test
diff --git a/test/exclusive.test b/test/exclusive.test
index db79d303..ffde8915 100644
--- a/test/exclusive.test
+++ b/test/exclusive.test
@@ -22,12 +22,12 @@ ifcapable {!pager_pragmas} {
return
}
-file delete -force test2.db-journal
-file delete -force test2.db
-file delete -force test3.db-journal
-file delete -force test3.db
-file delete -force test4.db-journal
-file delete -force test4.db
+forcedelete test2.db-journal
+forcedelete test2.db
+forcedelete test3.db-journal
+forcedelete test3.db
+forcedelete test4.db-journal
+forcedelete test4.db
#----------------------------------------------------------------------
# Test cases exclusive-1.X test the PRAGMA logic.
@@ -481,8 +481,8 @@ do_execsql_test exclusive-6.1 {
}
do_test exclusive-6.2 {
forcedelete test2.db test2.db-journal
- file copy test.db test2.db
- file copy test.db-journal test2.db-journal
+ copy_file test.db test2.db
+ copy_file test.db-journal test2.db-journal
sqlite3 db test2.db
} {}
diff --git a/test/exclusive2.test b/test/exclusive2.test
index 18f304db..2208da51 100644
--- a/test/exclusive2.test
+++ b/test/exclusive2.test
@@ -259,8 +259,8 @@ do_test exclusive2-2.8 {
db close
catch {close $::fd}
-file delete -force test.db
-file delete -force test.db-journal
+forcedelete test.db
+forcedelete test.db-journal
do_test exclusive2-3.0 {
sqlite3 db test.db
diff --git a/test/exists.test b/test/exists.test
index c7c14a24..fb73797d 100644
--- a/test/exists.test
+++ b/test/exists.test
@@ -159,7 +159,7 @@ foreach jm {rollback wal} {
sql1 { DROP INDEX IF EXISTS i2 }
sql2 { CREATE INDEX aux.i2 ON t2(x) }
sql1 { DROP INDEX IF EXISTS i2 }
- sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'index' }
+ sql2 { SELECT * FROM aux.sqlite_master WHERE type = 'index' }
} {}
# VIEW objects.
diff --git a/test/fallocate.test b/test/fallocate.test
index 05aa2a81..8a5fa323 100644
--- a/test/fallocate.test
+++ b/test/fallocate.test
@@ -79,7 +79,7 @@ ifcapable !wal { set skipwaltests 1 }
if {!$skipwaltests} {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
file_control_chunksize_test db main [expr 32*1024]
diff --git a/test/filectrl.test b/test/filectrl.test
index 67e81830..9f077d52 100644
--- a/test/filectrl.test
+++ b/test/filectrl.test
@@ -37,5 +37,5 @@ do_test filectrl-1.5 {
file_control_lockproxy_test db [pwd]
} {}
db close
-file delete -force .test_control_lockproxy.db-conch test.proxy
+forcedelete .test_control_lockproxy.db-conch test.proxy
finish_test
diff --git a/test/filefmt.test b/test/filefmt.test
index 72edbeeb..1165cd62 100644
--- a/test/filefmt.test
+++ b/test/filefmt.test
@@ -23,7 +23,7 @@ source $testdir/tester.tcl
do_not_use_codec
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
# Database begins with valid 16-byte header string.
#
@@ -63,7 +63,7 @@ ifcapable pager_pragmas {
&& $pagesize>$SQLITE_MAX_PAGE_SIZE} continue
do_test filefmt-1.5.$pagesize.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
db eval "PRAGMA auto_vacuum=OFF"
db eval "PRAGMA page_size=$pagesize"
@@ -105,7 +105,7 @@ do_test filefmt-1.7 {
ifcapable pager_pragmas {
do_test filefmt-1.8 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
db eval {PRAGMA page_size=512; CREATE TABLE t1(x)}
db close
@@ -125,7 +125,7 @@ ifcapable pager_pragmas {
# always derives this from the size of the file.
#
db close
-file delete -force test.db
+forcedelete test.db
set a_string_counter 1
proc a_string {n} {
@@ -157,7 +157,7 @@ integrity_check filefmt-2.1.5
do_test filefmt-2.1.6 { hexio_read test.db 28 4 } {00000010}
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
db func a_string a_string
diff --git a/test/fkey_malloc.test b/test/fkey_malloc.test
index 05a2a4f4..4a36f5f3 100644
--- a/test/fkey_malloc.test
+++ b/test/fkey_malloc.test
@@ -68,7 +68,7 @@ proc catch_fk_error {zSql} {
if {[string match {*foreign key*} $msg]} {
return ""
}
- if {$msg eq "out of memory"} {
+ if {$msg eq "out of memory" || $msg eq "constraint failed"} {
error 1
}
error $msg
diff --git a/test/fts-9fd058691.test b/test/fts-9fd058691.test
new file mode 100644
index 00000000..b228482d
--- /dev/null
+++ b/test/fts-9fd058691.test
@@ -0,0 +1,59 @@
+# 2011 October 13
+#
+# 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 the FTS SQLite module.
+#
+# This file implements tests to verify that ticket [9fd058691] has been
+# fixed.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# If SQLITE_ENABLE_FTS3 is defined, omit this file.
+ifcapable !fts3 {
+ finish_test
+ return
+}
+
+set ::testprefix fts3-9fd058691
+
+do_execsql_test 1.0 {
+ CREATE VIRTUAL TABLE fts USING fts3( tags TEXT);
+ INSERT INTO fts (tags) VALUES ('tag1');
+ SELECT * FROM fts WHERE tags MATCH 'tag1';
+} {tag1}
+
+do_test 1.1 {
+ db close
+ sqlite3 db test.db
+ execsql {
+ UPDATE fts SET tags = 'tag1' WHERE rowid = 1;
+ SELECT * FROM fts WHERE tags MATCH 'tag1';
+ }
+} {tag1}
+
+db close
+forcedelete test.db
+sqlite3 db test.db
+
+do_execsql_test 2.0 {
+ CREATE VIRTUAL TABLE fts USING fts3(tags TEXT);
+ INSERT INTO fts (docid, tags) VALUES (1, 'tag1');
+ INSERT INTO fts (docid, tags) VALUES (2, NULL);
+ INSERT INTO fts (docid, tags) VALUES (3, 'three');
+} {}
+
+do_test 2.1 {
+ execsql {
+ UPDATE fts SET tags = 'two' WHERE rowid = 2;
+ SELECT * FROM fts WHERE tags MATCH 'two';
+ }
+} {two}
+
+finish_test
diff --git a/test/fts1j.test b/test/fts1j.test
index 5ff0d0ed..4dac22ab 100644
--- a/test/fts1j.test
+++ b/test/fts1j.test
@@ -19,8 +19,8 @@ ifcapable !fts1 {
}
# Clean up anything left over from a previous pass.
-file delete -force test2.db
-file delete -force test2.db-journal
+forcedelete test2.db
+forcedelete test2.db-journal
sqlite3 db2 test2.db
db eval {
@@ -84,6 +84,6 @@ do_test fts1j-1.3 {
catch {db eval {DETACH DATABASE two}}
catch {db2 close}
-file delete -force test2.db
+forcedelete test2.db
finish_test
diff --git a/test/fts1o.test b/test/fts1o.test
index 92666c6f..61fd74ca 100644
--- a/test/fts1o.test
+++ b/test/fts1o.test
@@ -95,7 +95,7 @@ do_test fts1o-3.6 {
# Test that it is possible to rename an fts1 table in an attached
# database.
#
-file delete -force test2.db test2.db-journal
+forcedelete test2.db test2.db-journal
do_test fts1o-4.1 {
execsql {
diff --git a/test/fts2j.test b/test/fts2j.test
index b8a89b20..a8a2c07c 100644
--- a/test/fts2j.test
+++ b/test/fts2j.test
@@ -19,8 +19,8 @@ ifcapable !fts2 {
}
# Clean up anything left over from a previous pass.
-file delete -force test2.db
-file delete -force test2.db-journal
+forcedelete test2.db
+forcedelete test2.db-journal
sqlite3 db2 test2.db
db eval {
@@ -84,6 +84,6 @@ do_test fts2j-1.3 {
catch {db eval {DETACH DATABASE two}}
catch {db2 close}
-file delete -force test2.db
+forcedelete test2.db
finish_test
diff --git a/test/fts2o.test b/test/fts2o.test
index 5a33c455..63e71b95 100644
--- a/test/fts2o.test
+++ b/test/fts2o.test
@@ -109,7 +109,7 @@ do_test fts2o-2.12 {
# be run on an initially empty db.
#
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
do_test fts2o-3.1 {
@@ -134,7 +134,7 @@ do_test fts2o-3.2 {
# Test that it is possible to rename an fts2 table in an attached
# database.
#
-file delete -force test2.db test2.db-journal
+forcedelete test2.db test2.db-journal
do_test fts2o-3.1 {
execsql {
diff --git a/test/fts3aj.test b/test/fts3aj.test
index 60d26c02..f3d46f2a 100644
--- a/test/fts3aj.test
+++ b/test/fts3aj.test
@@ -19,8 +19,8 @@ ifcapable !fts3 {
}
# Clean up anything left over from a previous pass.
-file delete -force test2.db
-file delete -force test2.db-journal
+forcedelete test2.db
+forcedelete test2.db-journal
sqlite3 db2 test2.db
db eval {
@@ -84,6 +84,6 @@ do_test fts3aj-1.3 {
catch {db eval {DETACH DATABASE two}}
catch {db2 close}
-file delete -force test2.db
+forcedelete test2.db
finish_test
diff --git a/test/fts3ao.test b/test/fts3ao.test
index cd9df01e..786667a7 100644
--- a/test/fts3ao.test
+++ b/test/fts3ao.test
@@ -111,7 +111,7 @@ do_test fts3ao-2.12 {
# be run on an initially empty db.
#
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
do_test fts3ao-3.1 {
@@ -136,7 +136,7 @@ do_test fts3ao-3.2 {
# Test that it is possible to rename an fts3 table in an attached
# database.
#
-file delete -force test2.db test2.db-journal
+forcedelete test2.db test2.db-journal
do_test fts3ao-3.1 {
execsql {
@@ -200,6 +200,9 @@ do_test fts3ao-4.7 {
SELECT * FROM t5;
}
} {{the quick brown fox} {jumped over the} {lazy dog}}
+do_execsql_test fts3ao-4.8 {
+ SELECT snippet(t5, '[', ']') FROM t5 WHERE t5 MATCH 'the'
+} {{[the] quick brown fox} {jumped over [the]}}
# Test that it is possible to rename an FTS4 table. Renaming an FTS4 table
# involves renaming the extra %_docsize and %_stat tables.
diff --git a/test/fts3auto.test b/test/fts3auto.test
index 484fd6ac..1c58a172 100644
--- a/test/fts3auto.test
+++ b/test/fts3auto.test
@@ -107,15 +107,17 @@ proc do_fts3query_test {tn args} {
" $matchinfo_asc
}
-# fts3_make_deferrable TABLE TOKEN
+# fts3_make_deferrable TABLE TOKEN ?NROW?
#
-proc fts3_make_deferrable {tbl token} {
+proc fts3_make_deferrable {tbl token {nRow 0}} {
set stmt [sqlite3_prepare db "SELECT * FROM $tbl" -1 dummy]
set name [sqlite3_column_name $stmt 0]
sqlite3_finalize $stmt
- set nRow [db one "SELECT count(*) FROM $tbl"]
+ if {$nRow==0} {
+ set nRow [db one "SELECT count(*) FROM $tbl"]
+ }
set pgsz [db one "PRAGMA page_size"]
execsql BEGIN
for {set i 0} {$i < ($nRow * $pgsz * 1.2)/100} {incr i} {
@@ -653,6 +655,50 @@ foreach {tn pending create} {
catchsql { COMMIT }
}
+foreach {tn create} {
+ 1 "fts4(x)"
+ 2 "fts4(x, order=DESC)"
+} {
+ execsql [subst {
+ DROP TABLE IF EXISTS t1;
+ CREATE VIRTUAL TABLE t1 USING $create;
+ }]
+
+ foreach {x} {
+ "F E N O T K X V A X I E X A P G Q V H U"
+ "R V A E T C V Q N I E L O N U G J K L U"
+ "U Y I G W M V F J L X I D C H F P J Q B"
+ "S G D Z X R P G S S Y B K A S G A I L L"
+ "L S I C H T Z S R Q P R N K J X L F M J"
+ "C C C D P X B Z C M A D A C X S B T X V"
+ "W Y J M D R G V R K B X S A W R I T N C"
+ "P K L W T M S P O Y Y V V O E H Q A I R"
+ "C D Y I C Z F H J C O Y A Q F L S B D K"
+ "P G S C Y C Y V I M B D S Z D D Y W I E"
+ "Z K Z U E E S F Y X T U A L W O U J C Q"
+ "P A T Z S W L P L Q V Y Y I P W U X S S"
+ "I U I H U O F Z F R H R F T N D X A G M"
+ "N A B M S H K X S O Y D T X S B R Y H Z"
+ "L U D A S K I L S V Z J P U B E B Y H M"
+ } {
+ execsql { INSERT INTO t1 VALUES($x) }
+ }
+
+ # Add extra documents to the database such that token "B" will be considered
+ # deferrable if considering the other tokens means that 2 or fewer documents
+ # will be loaded into memory.
+ #
+ fts3_make_deferrable t1 B 2
+
+ # B is not deferred in either of the first two tests below, since filtering
+ # on "M" or "D" returns 10 documents or so. But filtering on "M * D" only
+ # returns 2, so B is deferred in this case.
+ #
+ do_fts3query_test 7.$tn.1 t1 {"M B"}
+ do_fts3query_test 7.$tn.2 t1 {"B D"}
+ do_fts3query_test 7.$tn.3 -deferred B t1 {"M B D"}
+}
+
set sqlite_fts3_enable_parentheses $sfep
finish_test
diff --git a/test/fts3d.test b/test/fts3d.test
index 715980d8..1ae992b3 100644
--- a/test/fts3d.test
+++ b/test/fts3d.test
@@ -304,4 +304,57 @@ do_test fts3d-5.1 {
}
} {{Index already optimal} 2 0}
+
+# ALTER TABLE RENAME should work regardless of the database encoding.
+#
+do_test fts3d-6.0 {
+ db close
+ forcedelete test.db
+ sqlite3 db test.db
+ db eval {
+ PRAGMA encoding=UTF8;
+ CREATE VIRTUAL TABLE fts USING fts3(a,b,c);
+ SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
+ }
+} {fts_content fts_segdir fts_segments}
+do_test fts3d-6.1 {
+ db eval {
+ ALTER TABLE fts RENAME TO xyz;
+ SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
+ }
+} {xyz_content xyz_segdir xyz_segments}
+do_test fts3d-6.2 {
+ db close
+ forcedelete test.db
+ sqlite3 db test.db
+ db eval {
+ PRAGMA encoding=UTF16le;
+ CREATE VIRTUAL TABLE fts USING fts3(a,b,c);
+ SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
+ }
+} {fts_content fts_segdir fts_segments}
+do_test fts3d-6.3 {
+ db eval {
+ ALTER TABLE fts RENAME TO xyz;
+ SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
+ }
+} {xyz_content xyz_segdir xyz_segments}
+do_test fts3d-6.4 {
+ db close
+ forcedelete test.db
+ sqlite3 db test.db
+ db eval {
+ PRAGMA encoding=UTF16be;
+ CREATE VIRTUAL TABLE fts USING fts3(a,b,c);
+ SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
+ }
+} {fts_content fts_segdir fts_segments}
+do_test fts3d-6.5 {
+ db eval {
+ ALTER TABLE fts RENAME TO xyz;
+ SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
+ }
+} {xyz_content xyz_segdir xyz_segments}
+
+
finish_test
diff --git a/test/fts3defer.test b/test/fts3defer.test
index 4bc0b0a7..bc50874e 100644
--- a/test/fts3defer.test
+++ b/test/fts3defer.test
@@ -426,6 +426,18 @@ foreach {tn setup} {
SELECT rowid FROM t1 WHERE t1 MATCH '"jk xduvfhk" OR "zm azavwm"'
} {8 15 26 92 96}
}
+
+ if {$tn>1} {
+ # These tests will not work with $tn==1, as in this case table t1 is
+ # created using FTS3. The ^ syntax is only available with FTS4 tables.
+ #
+ do_select_test 7.1 {
+ SELECT rowid FROM t1 WHERE t1 MATCH '^zm mjpavjuhw'
+ } {56 62}
+ do_select_test 7.2 {
+ SELECT rowid FROM t1 WHERE t1 MATCH '^azavwm zm'
+ } {43}
+ }
}
set testprefix fts3defer
@@ -449,5 +461,33 @@ do_execsql_test 3.3 {
SELECT count(*) FROM x1 WHERE x1 MATCH '"d e f"'
} {16}
+# At one point the following was causing a floating-point exception.
+#
+do_execsql_test 4.1 {
+ CREATE VIRTUAL TABLE x2 USING FTS4(x);
+ BEGIN;
+ INSERT INTO x2 VALUES('m m m m m m m m m m m m m m m m m m m m m m m m m m');
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 SELECT * FROM x2;
+ INSERT INTO x2 VALUES('a b c d e f g h i j k l m n o p q r s t u v w x y m');
+ COMMIT;
+}
+do_execsql_test 4.2 {
+ SELECT * FROM x2 WHERE x2 MATCH 'a b c d e f g h i j k l m n o p q r s';
+} {{a b c d e f g h i j k l m n o p q r s t u v w x y m}}
+
finish_test
diff --git a/test/fts3drop.test b/test/fts3drop.test
new file mode 100644
index 00000000..8b76eafe
--- /dev/null
+++ b/test/fts3drop.test
@@ -0,0 +1,61 @@
+# 2011 October 29
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#*************************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is testing the FTS3 module. More specifically,
+# that DROP TABLE commands can co-exist with savepoints inside transactions.
+# See ticket [48f299634a] for details.
+#
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix fts3drop
+
+# If SQLITE_ENABLE_FTS3 is defined, omit this file.
+ifcapable !fts3 {
+ finish_test
+ return
+}
+
+do_execsql_test 1.1 {
+ CREATE VIRTUAL TABLE f1 USING fts3;
+ INSERT INTO f1 VALUES('a b c');
+}
+
+do_execsql_test 1.2 {
+ BEGIN;
+ INSERT INTO f1 VALUES('d e f');
+ SAVEPOINT one;
+ INSERT INTO f1 VALUES('g h i');
+ DROP TABLE f1;
+ ROLLBACK TO one;
+ COMMIT;
+}
+
+do_execsql_test 1.3 {
+ SELECT * FROM f1;
+} {{a b c} {d e f}}
+
+do_execsql_test 1.4 {
+ BEGIN;
+ INSERT INTO f1 VALUES('g h i');
+ SAVEPOINT one;
+ INSERT INTO f1 VALUES('j k l');
+ DROP TABLE f1;
+ RELEASE one;
+ ROLLBACK;
+}
+
+do_execsql_test 1.5 {
+ SELECT * FROM f1;
+} {{a b c} {d e f}}
+
+finish_test
diff --git a/test/fts3fault.test b/test/fts3fault.test
index 2dd7bbbc..ab82daa9 100644
--- a/test/fts3fault.test
+++ b/test/fts3fault.test
@@ -18,8 +18,6 @@ set ::testprefix fts3fault
# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 { finish_test ; return }
-if 1 {
-
# Test error handling in the sqlite3Fts3Init() function. This is the
# function that registers the FTS3 module and various support functions
# with SQLite.
@@ -146,7 +144,8 @@ do_faultsim_test 7.2 -prep {
execsql { CREATE VIRTUAL TABLE t1 USING fts4(a, b, matchinfo=fs3) }
} -test {
faultsim_test_result {1 {unrecognized matchinfo: fs3}} \
- {1 {vtable constructor failed: t1}}
+ {1 {vtable constructor failed: t1}} \
+ {1 {SQL logic error or missing database}}
}
do_faultsim_test 7.3 -prep {
faultsim_delete_and_reopen
@@ -154,9 +153,8 @@ do_faultsim_test 7.3 -prep {
execsql { CREATE VIRTUAL TABLE t1 USING fts4(a, b, matchnfo=fts3) }
} -test {
faultsim_test_result {1 {unrecognized parameter: matchnfo=fts3}} \
- {1 {vtable constructor failed: t1}}
-}
-
+ {1 {vtable constructor failed: t1}} \
+ {1 {SQL logic error or missing database}}
}
proc mit {blob} {
diff --git a/test/fts3fault2.test b/test/fts3fault2.test
index fb877737..0178ed27 100644
--- a/test/fts3fault2.test
+++ b/test/fts3fault2.test
@@ -82,4 +82,53 @@ do_faultsim_test 2.1 -prep {
faultsim_test_result {0 {a * 1 1 a 0 1 1 b * 1 1 b 0 1 1 c * 1 1 c 0 1 1 x * 1 1 x 1 1 1 y * 1 1 y 1 1 1 z * 1 1 z 1 1 1}}
}
+do_faultsim_test 3.0 -faults oom* -prep {
+ faultsim_delete_and_reopen
+ db eval { CREATE TABLE 'xx yy'(a, b); }
+} -body {
+ execsql {
+ CREATE VIRTUAL TABLE tt USING fts4(content="xx yy");
+ }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
+do_faultsim_test 3.1 -faults oom* -prep {
+ faultsim_delete_and_reopen
+ db func zip zip
+ db func unzip unzip
+} -body {
+ execsql {
+ CREATE VIRTUAL TABLE tt USING fts4(compress=zip, uncompress=unzip);
+ }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
+do_test 4.0 {
+ faultsim_delete_and_reopen
+ execsql {
+ CREATE VIRTUAL TABLE ft USING fts4(a, b);
+ INSERT INTO ft VALUES('U U T C O', 'F N D E S');
+ INSERT INTO ft VALUES('P H X G B', 'I D M R U');
+ INSERT INTO ft VALUES('P P X D M', 'Y V N T C');
+ INSERT INTO ft VALUES('Z L Q O W', 'D F U N Q');
+ INSERT INTO ft VALUES('A J D U P', 'C H M Q E');
+ INSERT INTO ft VALUES('P S A O H', 'S Z C W D');
+ INSERT INTO ft VALUES('T B N L W', 'C A K T I');
+ INSERT INTO ft VALUES('K E Z L O', 'L L Y C E');
+ INSERT INTO ft VALUES('C R E S V', 'Q V F W P');
+ INSERT INTO ft VALUES('S K H G W', 'R W Q F G');
+ }
+ faultsim_save_and_close
+} {}
+do_faultsim_test 4.1 -prep {
+ faultsim_restore_and_reopen
+ db eval {SELECT * FROM sqlite_master}
+} -body {
+ execsql { INSERT INTO ft(ft) VALUES('rebuild') }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
finish_test
diff --git a/test/fts3first.test b/test/fts3first.test
new file mode 100644
index 00000000..673f818d
--- /dev/null
+++ b/test/fts3first.test
@@ -0,0 +1,163 @@
+# 2011 October 18
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/malloc_common.tcl
+
+ifcapable !fts3 {
+ finish_test
+ return
+}
+
+set testprefix fts3first
+
+proc lreverse {L} {
+ set res [list]
+ for {set ii [expr [llength $L]-1]} {$ii>=0} {incr ii -1} {
+ lappend res [lindex $L $ii]
+ }
+ set res
+}
+
+proc mit {blob} {
+ set scan(littleEndian) i*
+ set scan(bigEndian) I*
+ binary scan $blob $scan($::tcl_platform(byteOrder)) r
+ return $r
+}
+db func mit mit
+
+do_execsql_test 1.0 {
+ CREATE VIRTUAL TABLE x1 USING FTS4(a, b, c);
+ INSERT INTO x1(docid,a,b,c) VALUES(0, 'K H D S T', 'V M N Y K', 'S Z N Q S');
+ INSERT INTO x1(docid,a,b,c) VALUES(1, 'K N J L W', 'S Z W J Q', 'D U W S E');
+ INSERT INTO x1(docid,a,b,c) VALUES(2, 'B P M O I', 'R P H W S', 'R J L L E');
+ INSERT INTO x1(docid,a,b,c) VALUES(3, 'U R Q M L', 'M J K A V', 'Q W J T J');
+ INSERT INTO x1(docid,a,b,c) VALUES(4, 'N J C Y N', 'R U D X V', 'B O U A Q');
+ INSERT INTO x1(docid,a,b,c) VALUES(5, 'Q L X L U', 'I F N X S', 'U Q A N Y');
+ INSERT INTO x1(docid,a,b,c) VALUES(6, 'M R G U T', 'U V I Q P', 'X Y D L S');
+ INSERT INTO x1(docid,a,b,c) VALUES(7, 'D Y P O I', 'X J P K R', 'V O T H V');
+ INSERT INTO x1(docid,a,b,c) VALUES(8, 'R Y D L R', 'U U E S J', 'N W L M R');
+ INSERT INTO x1(docid,a,b,c) VALUES(9, 'Z P F N P', 'W A X D U', 'V A E Q A');
+ INSERT INTO x1(docid,a,b,c) VALUES(10, 'Q I A Q M', 'N D K H C', 'A H T Q Z');
+ INSERT INTO x1(docid,a,b,c) VALUES(11, 'T E R Q B', 'C I B C B', 'F Z U W R');
+ INSERT INTO x1(docid,a,b,c) VALUES(12, 'E S V U W', 'T P F W H', 'A M D J Q');
+ INSERT INTO x1(docid,a,b,c) VALUES(13, 'X S B X Y', 'U D N D P', 'X Z Y G F');
+ INSERT INTO x1(docid,a,b,c) VALUES(14, 'K H A B L', 'S R C C Z', 'D W E H J');
+ INSERT INTO x1(docid,a,b,c) VALUES(15, 'C E U C C', 'W F M N M', 'T Z U X T');
+ INSERT INTO x1(docid,a,b,c) VALUES(16, 'Q G C G H', 'H N N B H', 'B Q I H Y');
+ INSERT INTO x1(docid,a,b,c) VALUES(17, 'Q T S K B', 'W B D Y N', 'V J P E C');
+ INSERT INTO x1(docid,a,b,c) VALUES(18, 'A J M O Q', 'L G Y Y A', 'G N M R N');
+ INSERT INTO x1(docid,a,b,c) VALUES(19, 'T R Y P Y', 'N V Y B X', 'L Z T N T');
+
+ CREATE VIRTUAL TABLE x2 USING FTS4(a, b, c, order=DESC);
+ INSERT INTO x2(docid, a, b, c) SELECT docid, a, b, c FROM x1;
+}
+
+
+# Test queries.
+#
+foreach x {1 2} {
+ foreach {tn match res} {
+ 1 "^K" {0 1 14}
+ 2 "^S" {0 1 14}
+ 3 "^W" {9 15 17}
+ 4 "^J" {}
+ 5 "^E" {12}
+ 6 "V ^-E" {0 3 4 6 7 9 17 19}
+ 7 "V -^E" {0 3 4 6 7 9 17 19}
+ 8 "^-E V" {0 3 4 6 7 9 17 19}
+ 9 "-^E V" {0 3 4 6 7 9 17 19}
+ 10 "V" {0 3 4 6 7 9 12 17 19}
+
+ 11 {"^K H"} {0 14}
+ 12 {"K H"} {0 10 14}
+ 13 {"K ^H"} {}
+ } {
+ set rev [lreverse $res]
+ do_execsql_test 1.$x.$tn.1 {SELECT docid FROM x1 WHERE x1 MATCH $match} $res
+ do_execsql_test 1.$x.$tn.2 {SELECT docid FROM x2 WHERE x2 MATCH $match} $rev
+ }
+
+ do_execsql_test 1.$x.[expr $tn+1] {
+ INSERT INTO x1(x1) VALUES('optimize');
+ INSERT INTO x2(x2) VALUES('optimize');
+ } {}
+}
+
+# Test the snippet() function.
+#
+foreach {tn match res} {
+ 1 {^K} {{[K] H D S T} {[K] N J L W} {[K] H A B L}}
+ 2 {^X} {{[X] Y D L S} {[X] J P K R} {[X] S B X Y}}
+ 3 {^X Y} {{[X] [Y] D L S} {D [Y] P O I...[X] J P K R} {[X] S B X [Y]}}
+} {
+ set rev [lreverse $res]
+
+ do_execsql_test 1.3.$tn.1 {
+ SELECT snippet(x1, '[', ']', '...') FROM x1 WHERE x1 MATCH $match
+ } $res
+
+ do_execsql_test 1.3.$tn.2 {
+ SELECT snippet(x2, '[', ']', '...') FROM x2 WHERE x2 MATCH $match
+ } $rev
+}
+
+# Test matchinfo().
+#
+foreach {tn match res} {
+ 1 {^K} {
+ {1 3 3 0 0 0 0 0 0}
+ {1 3 3 0 0 0 0 0 0}
+ {1 3 3 0 0 0 0 0 0}
+ }
+ 2 {^X} {
+ {0 1 1 0 1 1 1 2 2}
+ {0 1 1 1 1 1 0 2 2}
+ {1 1 1 0 1 1 1 2 2}
+ }
+ 3 {^X Y} {
+ {0 1 1 0 1 1 1 2 2 0 6 5 0 5 4 1 4 4}
+ {0 1 1 1 1 1 0 2 2 1 6 5 0 5 4 0 4 4}
+ {1 1 1 0 1 1 1 2 2 1 6 5 0 5 4 1 4 4}
+ }
+} {
+ set rev [lreverse $res]
+
+ do_execsql_test 1.3.$tn.1 {
+ SELECT mit(matchinfo(x1, 'x')) FROM x1 WHERE x1 MATCH $match
+ } $res
+ do_execsql_test 1.3.$tn.2 {
+ SELECT mit(matchinfo(x2, 'x')) FROM x2 WHERE x2 MATCH $match
+ } $rev
+}
+
+# Test that ^ is ignored for FTS3 tables.
+#
+do_execsql_test 2.1 {
+ CREATE VIRTUAL TABLE x3 USING fts3;
+ INSERT INTO x3 VALUES('A B C');
+ INSERT INTO x3 VALUES('B A C');
+
+ CREATE VIRTUAL TABLE x4 USING fts4;
+ INSERT INTO x4 VALUES('A B C');
+ INSERT INTO x4 VALUES('B A C');
+}
+
+do_execsql_test 2.2.1 {
+ SELECT * FROM x3 WHERE x3 MATCH '^A';
+} {{A B C} {B A C}}
+do_execsql_test 2.2.2 {
+ SELECT * FROM x4 WHERE x4 MATCH '^A';
+} {{A B C}}
+
+finish_test
diff --git a/test/fts3malloc.test b/test/fts3malloc.test
index 932ea098..7eeee7fe 100644
--- a/test/fts3malloc.test
+++ b/test/fts3malloc.test
@@ -294,6 +294,7 @@ do_write_test fts3_malloc-5.1 ft_content {
do_test fts3_malloc-5.2 {
execsql { CREATE VIRTUAL TABLE ft8 USING fts3(x, tokenize porter) }
} {}
+
do_write_test fts3_malloc-5.3 ft_content {
INSERT INTO ft8 VALUES('short alongertoken reallyquitealotlongerimeanit andthistokenisjustsolongthatonemightbeforgivenforimaginingthatitwasmerelyacontrivedexampleandnotarealtoken')
}
diff --git a/test/fts3matchinfo.test b/test/fts3matchinfo.test
index 40366b6a..0e888580 100644
--- a/test/fts3matchinfo.test
+++ b/test/fts3matchinfo.test
@@ -19,6 +19,7 @@ source $testdir/tester.tcl
ifcapable !fts3 { finish_test ; return }
set testprefix fts3matchinfo
+set sqlite_fts3_enable_parentheses 0
proc mit {blob} {
set scan(littleEndian) i*
@@ -57,6 +58,9 @@ do_catchsql_test 2.0 {
do_catchsql_test 2.1 {
CREATE VIRTUAL TABLE x2 USING fts4(mtchinfo=fts3);
} {1 {unrecognized parameter: mtchinfo=fts3}}
+do_catchsql_test 2.2 {
+ CREATE VIRTUAL TABLE x2 USING fts4(matchinfo=fts5);
+} {1 {unrecognized matchinfo: fts5}}
# Check that with fts3, the "=" character is permitted in column definitions.
#
@@ -224,6 +228,18 @@ do_matchinfo_test 4.1.3 t4 {t4 MATCH 'a b'} { s {{2 0} {0 2}} }
do_matchinfo_test 4.1.4 t4 {t4 MATCH '"a b" c'} { s {{2 0} {0 2}} }
do_matchinfo_test 4.1.5 t4 {t4 MATCH 'a "b c"'} { s {{2 0} {0 2}} }
do_matchinfo_test 4.1.6 t4 {t4 MATCH 'd d'} { s {{1 0} {0 1}} }
+do_matchinfo_test 4.1.7 t4 {t4 MATCH 'f OR abcd'} {
+ x {
+ {0 1 1 1 1 1 0 0 0 0 0 0}
+ {1 1 1 0 1 1 0 0 0 0 0 0}
+ }
+}
+do_matchinfo_test 4.1.8 t4 {t4 MATCH 'f -abcd'} {
+ x {
+ {0 1 1 1 1 1}
+ {1 1 1 0 1 1}
+ }
+}
do_execsql_test 4.2.0 {
CREATE VIRTUAL TABLE t5 USING fts4;
diff --git a/test/fts3prefix.test b/test/fts3prefix.test
index f5e31f32..e7c197da 100644
--- a/test/fts3prefix.test
+++ b/test/fts3prefix.test
@@ -200,4 +200,14 @@ do_execsql_test 4.6 {
SELECT * FROM t3 WHERE t3 MATCH 'one*'
} {{one two three}}
+#-------------------------------------------------------------------------
+# Syntax tests.
+#
+do_catchsql_test 5.1 {
+ CREATE VIRTUAL TABLE t4 USING fts4(prefix="abc");
+} {1 {error parsing prefix parameter: abc}}
+do_catchsql_test 5.2 {
+ CREATE VIRTUAL TABLE t4 USING fts4(prefix="");
+} {0 {}}
+
finish_test
diff --git a/test/fts3snippet.test b/test/fts3snippet.test
index 359a87c6..b8646cdf 100644
--- a/test/fts3snippet.test
+++ b/test/fts3snippet.test
@@ -131,7 +131,7 @@ foreach {DO_MALLOC_TEST enc} {
} {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 0 0
db eval "PRAGMA encoding = \"$enc\""
diff --git a/test/fts3sort.test b/test/fts3sort.test
index ce5b5df7..be756043 100644
--- a/test/fts3sort.test
+++ b/test/fts3sort.test
@@ -138,6 +138,8 @@ foreach {tn param res} {
3 "order=dec" {1 {unrecognized order: dec}}
4 "order=xxx, order=asc" {1 {unrecognized order: xxx}}
5 "order=desc, order=asc" {0 {}}
+ 6 "order=xxxx, order=asc" {1 {unrecognized order: xxxx}}
+ 7 "order=desk" {1 {unrecognized order: desk}}
} {
execsql { DROP TABLE IF EXISTS t1 }
do_catchsql_test 2.1.$tn "
@@ -157,6 +159,27 @@ do_execsql_test 2.2 {
do_execsql_test 2.3 {
SELECT docid FROM t2 WHERE t2 MATCH 'aa';
} {3 1}
+do_execsql_test 2.4 {
+ SELECT docid FROM t2 WHERE t2 MATCH 'aa' ORDER BY content;
+} {1 3}
+
+#-------------------------------------------------------------------------
+# Test that ticket [56be976859] has been fixed.
+#
+do_execsql_test 3.1 {
+ CREATE VIRTUAL TABLE t3 USING fts4(x, order=DESC);
+ INSERT INTO t3(docid, x) VALUES(113382409004785664, 'aa');
+ INSERT INTO t3(docid, x) VALUES(1, 'ab');
+ SELECT rowid FROM t3 WHERE x MATCH 'a*' ORDER BY docid DESC;
+} {113382409004785664 1}
+do_execsql_test 3.2 {
+ CREATE VIRTUAL TABLE t4 USING fts4(x);
+ INSERT INTO t4(docid, x) VALUES(-113382409004785664, 'aa');
+ INSERT INTO t4(docid, x) VALUES(1, 'ab');
+ SELECT rowid FROM t4 WHERE x MATCH 'a*';
+} {-113382409004785664 1}
+
+
finish_test
diff --git a/test/fts4aa.test b/test/fts4aa.test
index 1131df3b..c5693317 100644
--- a/test/fts4aa.test
+++ b/test/fts4aa.test
@@ -1686,7 +1686,7 @@ foreach {q r} [array get fts4aa_res] {
#
do_test fts4aa-3.0 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
db eval {
PRAGMA page_size=65536;
diff --git a/test/fts4content.test b/test/fts4content.test
new file mode 100644
index 00000000..025b600b
--- /dev/null
+++ b/test/fts4content.test
@@ -0,0 +1,501 @@
+# 2011 October 03
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#*************************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is testing the content=xxx FTS4 option.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set ::testprefix fts4content
+
+# If SQLITE_ENABLE_FTS3 is defined, omit this file.
+ifcapable !fts3 {
+ finish_test
+ return
+}
+
+#-------------------------------------------------------------------------
+# Test organization:
+#
+# 1.* - Warm-body tests.
+#
+# 2.* - Querying a content=xxx FTS table.
+#
+# 3.* - Writing to a content=xxx FTS table.
+#
+# 4.* - The "INSERT INTO fts(fts) VALUES('rebuild')" command.
+#
+# 5.* - Check that CREATE TABLE, DROP TABLE and ALTER TABLE correctly
+# ignore any %_content table when used with the content=xxx option.
+#
+# 6.* - Test the effects of messing with the schema of table xxx after
+# creating a content=xxx FTS index.
+#
+# 7.* - Test that if content=xxx is specified and table xxx does not
+# exist, the FTS table can still be used for INSERT and some
+# SELECT statements.
+#
+
+do_execsql_test 1.1.1 {
+ CREATE TABLE t1(a, b, c);
+ INSERT INTO t1 VALUES('w x', 'x y', 'y z');
+ CREATE VIRTUAL TABLE ft1 USING fts4(content=t1);
+}
+
+do_execsql_test 1.1.2 {
+ PRAGMA table_info(ft1);
+} {
+ 0 a {} 0 {} 0
+ 1 b {} 0 {} 0
+ 2 c {} 0 {} 0
+}
+
+do_execsql_test 1.1.3 { SELECT *, rowid FROM ft1 } {{w x} {x y} {y z} 1}
+do_execsql_test 1.1.4 { SELECT a, c FROM ft1 WHERE rowid=1 } {{w x} {y z}}
+
+do_execsql_test 1.1.5 { INSERT INTO ft1(ft1) VALUES('rebuild') } {}
+do_execsql_test 1.1.6 { SELECT rowid FROM ft1 WHERE ft1 MATCH 'x' } {1}
+do_execsql_test 1.1.7 { SELECT rowid FROM ft1 WHERE ft1 MATCH 'a' } {}
+
+do_execsql_test 1.2.1 {
+ DROP TABLE ft1;
+ CREATE VIRTUAL TABLE ft1 USING fts4(content=t1, b);
+ PRAGMA table_info(ft1);
+} {
+ 0 b {} 0 {} 0
+}
+do_execsql_test 1.2.2 {
+ SELECT *, rowid FROM ft1
+} {{x y} 1}
+
+#-------------------------------------------------------------------------
+# The following block of tests - 2.* - test that a content=xxx FTS table
+# can be queried. Also tested are cases where rows identified in the FTS
+# are missing from the content table, and cases where the index is
+# inconsistent with the content table.
+#
+do_execsql_test 2.0 {
+ CREATE TABLE t2(x);
+ INSERT INTO t2 VALUES('O S W W F U C R Q I C N P Z Y Y E Y Y E'); -- 1
+ INSERT INTO t2 VALUES('Y X U V L B E H Y J C Y A I A P V F V K'); -- 2
+ INSERT INTO t2 VALUES('P W I N J H I I N I F B K D U Q B Z S F'); -- 3
+ INSERT INTO t2 VALUES('N R O R H J R H G M D I U U B O M P A U'); -- 4
+ INSERT INTO t2 VALUES('Y O V O G T P N G T N F I V B U M J M G'); -- 5
+ INSERT INTO t2 VALUES('J O B N K N E C H Z R K J O U G M K L S'); -- 6
+ INSERT INTO t2 VALUES('S Z S R I Q U A P W R X H K C Z U L S P'); -- 7
+ INSERT INTO t2 VALUES('J C H N R C K R V N M O F Z M Z A I H W'); -- 8
+ INSERT INTO t2 VALUES('O Y G I S J U U W O D Z F J K N R P R L'); -- 9
+ INSERT INTO t2 VALUES('B G L K U R U P V X Z I H V R W C Q A S'); -- 10
+ INSERT INTO t2 VALUES('T F T J F F Y V F W N X K Q A Y L X W G'); -- 11
+ INSERT INTO t2 VALUES('C J U H B Q X L C M M Y E G V F W V Z C'); -- 12
+ INSERT INTO t2 VALUES('B W L T F S G X D P H N G M R I O A X I'); -- 13
+ INSERT INTO t2 VALUES('N G Y O K Q K Z N M H U J E D H U W R K'); -- 14
+ INSERT INTO t2 VALUES('U D T R U Y F J D S J X E H Q G V A S Z'); -- 15
+ INSERT INTO t2 VALUES('M I W P J S H R J D Q I C G P C T P H R'); -- 16
+ INSERT INTO t2 VALUES('J M N I S L X Q C A B F C B Y D H V R J'); -- 17
+ INSERT INTO t2 VALUES('F V Z W J Q L P X Y E W B U Q N H X K T'); -- 18
+ INSERT INTO t2 VALUES('R F S R Y O F Q E I E G H C B H R X Y N'); -- 19
+ INSERT INTO t2 VALUES('U Q Q Q T E P D M F X P J G H X C Q D L'); -- 20
+}
+
+do_execsql_test 2.1 {
+ CREATE VIRTUAL TABLE ft2 USING fts4(content=t2);
+ INSERT INTO ft2(ft2) VALUES('rebuild');
+
+ -- Modify the backing table a bit: Row 17 is missing and the contents
+ -- of row 20 do not match the FTS index contents.
+ DELETE FROM t2 WHERE rowid = 17;
+ UPDATE t2 SET x = 'a b c d e f g h i j' WHERE rowid = 20;
+}
+
+foreach {tn match rowidlist} {
+ 1 {S} {1 3 6 7 9 10 13 15 16 17 19}
+ 2 {"S R"} {7 19}
+ 3 {"N K N"} {6}
+ 4 {"Q Q"} {20}
+ 5 {"B Y D"} {17}
+} {
+ do_execsql_test 2.2.1.$tn {
+ SELECT rowid FROM ft2 WHERE ft2 MATCH $match
+ } $rowidlist
+
+ do_execsql_test 2.2.2.$tn {
+ SELECT docid FROM ft2 WHERE ft2 MATCH $match
+ } $rowidlist
+}
+
+foreach {tn match result} {
+ 1 {"N K N"} {{J O B N K N E C H Z R K J O U G M K L S}}
+ 2 {"Q Q"} {{a b c d e f g h i j}}
+ 3 {"B Y D"} {{}}
+} {
+ do_execsql_test 2.3.$tn {
+ SELECT * FROM ft2 WHERE ft2 MATCH $match
+ } $result
+}
+
+foreach {tn match result} {
+ 1 {"N K N"} {{..O B [N] [K] [N] E..}}
+ 2 {"B Y D"} {{}}
+ 3 {"Q Q"} {{a [b] [c] [d] e f..}}
+} {
+ do_execsql_test 2.4.$tn {
+ SELECT snippet(ft2, '[', ']', '..', -1, 6) FROM ft2 WHERE ft2 MATCH $match
+ } $result
+}
+
+foreach {tn match result} {
+ 1 {"N K N"} {{0 0 6 1 0 1 8 1 0 2 10 1}}
+ 2 {"B Y D"} {{}}
+ 3 {"Q Q"} {{0 0 2 1 0 0 4 1 0 1 4 1 0 1 6 1}}
+ 4 {"Q D L"} {{}}
+} {
+ do_execsql_test 2.5.$tn {
+ SELECT offsets(ft2) FROM ft2 WHERE ft2 MATCH $match
+ } $result
+}
+
+#-------------------------------------------------------------------------
+# The following block of tests - 3.* - test that the FTS index can be
+# modified by writing to the table. But that this has no effect on the
+# content table.
+#
+
+do_execsql_test 3.1 {
+ CREATE TABLE t3(x, y);
+ CREATE VIRTUAL TABLE ft3 USING fts4(content=t3);
+}
+
+do_catchsql_test 3.1.1 {
+ INSERT INTO ft3 VALUES('a b c', 'd e f');
+} {1 {constraint failed}}
+do_execsql_test 3.1.2 {
+ INSERT INTO ft3(docid, x, y) VALUES(21, 'a b c', 'd e f');
+ SELECT rowid FROM ft3 WHERE ft3 MATCH '"a b c"';
+} {21}
+do_execsql_test 3.1.3 { SELECT * FROM t3 } {}
+
+# This DELETE does not work, since there is no row in [t3] to base the
+# DELETE on. So the SELECT on [ft3] still returns rowid 21.
+do_execsql_test 3.1.4 {
+ DELETE FROM ft3;
+ SELECT rowid FROM ft3 WHERE ft3 MATCH '"a b c"';
+} {21}
+
+# If the row is added to [t3] before the DELETE on [ft3], it works.
+do_execsql_test 3.1.5 {
+ INSERT INTO t3(rowid, x, y) VALUES(21, 'a b c', 'd e f');
+ DELETE FROM ft3;
+ SELECT rowid FROM ft3 WHERE ft3 MATCH '"a b c"';
+} {}
+do_execsql_test 3.1.6 { SELECT rowid FROM t3 } {21}
+
+do_execsql_test 3.2.1 {
+ INSERT INTO ft3(rowid, x, y) VALUES(0, 'R T M S M', 'A F O K H');
+ INSERT INTO ft3(rowid, x, y) VALUES(1, 'C Z J O X', 'U S Q D K');
+ INSERT INTO ft3(rowid, x, y) VALUES(2, 'N G H P O', 'N O P O C');
+ INSERT INTO ft3(rowid, x, y) VALUES(3, 'V H S D R', 'K N G E C');
+ INSERT INTO ft3(rowid, x, y) VALUES(4, 'J T R V U', 'U X S L C');
+ INSERT INTO ft3(rowid, x, y) VALUES(5, 'N A Y N G', 'X D G P Y');
+ INSERT INTO ft3(rowid, x, y) VALUES(6, 'I Q I S P', 'D R O Q B');
+ INSERT INTO ft3(rowid, x, y) VALUES(7, 'T K T Z J', 'B W D G O');
+ INSERT INTO ft3(rowid, x, y) VALUES(8, 'Y K F X T', 'D F G V G');
+ INSERT INTO ft3(rowid, x, y) VALUES(9, 'E L E T L', 'P W N F Z');
+ INSERT INTO ft3(rowid, x, y) VALUES(10, 'O G J G X', 'G J F E P');
+ INSERT INTO ft3(rowid, x, y) VALUES(11, 'O L N N Z', 'K E Z F D');
+ INSERT INTO ft3(rowid, x, y) VALUES(12, 'R Z M R J', 'X G I M Z');
+ INSERT INTO ft3(rowid, x, y) VALUES(13, 'L X N N X', 'R R N S T');
+ INSERT INTO ft3(rowid, x, y) VALUES(14, 'F L B J H', 'K W F L C');
+ INSERT INTO ft3(rowid, x, y) VALUES(15, 'P E B M V', 'E A A B U');
+ INSERT INTO ft3(rowid, x, y) VALUES(16, 'V E C F P', 'L U T V K');
+ INSERT INTO ft3(rowid, x, y) VALUES(17, 'T N O Z N', 'T P Q X N');
+ INSERT INTO ft3(rowid, x, y) VALUES(18, 'V W U W R', 'H O A A V');
+ INSERT INTO ft3(rowid, x, y) VALUES(19, 'A H N L F', 'I G H B O');
+}
+
+foreach {tn match rowidlist} {
+ 1 "N A" {5 19}
+ 2 "x:O" {1 2 10 11 17}
+ 3 "y:O" {0 2 6 7 18 19}
+} {
+ set res [list]
+ foreach rowid $rowidlist { lappend res $rowid {} {} }
+
+ do_execsql_test 3.2.2.$tn {
+ SELECT rowid, * FROM ft3 WHERE ft3 MATCH $match
+ } $res
+ do_execsql_test 3.2.3.$tn {
+ SELECT docid, * FROM ft3 WHERE ft3 MATCH $match
+ } $res
+}
+
+do_execsql_test 3.3.1 {
+ INSERT INTO t3(rowid, x, y) VALUES(0, 'R T M S M', 'A F O K H');
+ INSERT INTO t3(rowid, x, y) VALUES(1, 'C Z J O X', 'U S Q D K');
+ INSERT INTO t3(rowid, x, y) VALUES(2, 'N G H P O', 'N O P O C');
+ INSERT INTO t3(rowid, x, y) VALUES(3, 'V H S D R', 'K N G E C');
+ INSERT INTO t3(rowid, x, y) VALUES(4, 'J T R V U', 'U X S L C');
+ INSERT INTO t3(rowid, x, y) VALUES(5, 'N A Y N G', 'X D G P Y');
+ UPDATE ft3 SET x = y, y = x;
+ DELETE FROM t3;
+}
+
+foreach {tn match rowidlist} {
+ 1 "N A" {5 19}
+ 2 "x:O" {0 2 10 11 17}
+ 3 "y:O" {1 2 6 7 18 19}
+} {
+ set res [list]
+ foreach rowid $rowidlist { lappend res $rowid {} {} }
+
+ do_execsql_test 3.3.2.$tn {
+ SELECT rowid, * FROM ft3 WHERE ft3 MATCH $match
+ } $res
+ do_execsql_test 3.3.3.$tn {
+ SELECT docid, * FROM ft3 WHERE ft3 MATCH $match
+ } $res
+}
+
+do_execsql_test 3.3.1 {
+ INSERT INTO t3(rowid, x, y) VALUES(15, 'P E B M V', 'E A A B U');
+ INSERT INTO t3(rowid, x, y) VALUES(16, 'V E C F P', 'L U T V K');
+ INSERT INTO t3(rowid, x, y) VALUES(17, 'T N O Z N', 'T P Q X N');
+ INSERT INTO t3(rowid, x, y) VALUES(18, 'V W U W R', 'H O A A V');
+ INSERT INTO t3(rowid, x, y) VALUES(19, 'A H N L F', 'I G H B O');
+ DELETE FROM ft3;
+}
+
+foreach {tn match rowidlist} {
+ 1 "N A" {5}
+ 2 "x:O" {0 2 10 11}
+ 3 "y:O" {1 2 6 7}
+} {
+ set res [list]
+ foreach rowid $rowidlist { lappend res $rowid {} {} }
+
+ do_execsql_test 3.3.2.$tn {
+ SELECT rowid, * FROM ft3 WHERE ft3 MATCH $match
+ } $res
+ do_execsql_test 3.3.3.$tn {
+ SELECT docid, * FROM ft3 WHERE ft3 MATCH $match
+ } $res
+}
+
+
+#-------------------------------------------------------------------------
+# Test cases 4.* test the 'rebuild' command. On content=xxx and regular
+# FTS tables.
+#
+do_execsql_test 4.0 {
+ CREATE TABLE t4(x);
+ CREATE VIRTUAL TABLE ft4 USING fts4(content=t4);
+ CREATE VIRTUAL TABLE ft4x USING fts4(x);
+}
+
+do_execsql_test 4.1.1 {
+ INSERT INTO ft4x(ft4x) VALUES('rebuild');
+ INSERT INTO ft4(ft4) VALUES('rebuild');
+} {}
+do_execsql_test 4.1.2 {
+ SELECT id, quote(value) FROM ft4_stat
+} {0 X'000000'}
+do_execsql_test 4.1.3 {
+ SELECT id, quote(value) FROM ft4x_stat
+} {0 X'000000'}
+
+do_execsql_test 4.2.1 {
+ INSERT INTO ft4x VALUES('M G M F T');
+ INSERT INTO ft4x VALUES('Z Q C A U');
+ INSERT INTO ft4x VALUES('N L L V');
+ INSERT INTO ft4x VALUES('T F D X D');
+ INSERT INTO ft4x VALUES('Z H I S D');
+
+ SELECT id, quote(value) FROM ft4x_stat
+} {0 X'05182B'}
+
+do_execsql_test 4.2.2 {
+ INSERT INTO ft4(rowid, x) SELECT rowid, * FROM ft4x;
+ SELECT id, quote(value) FROM ft4_stat
+} {0 X'05182B'}
+
+do_execsql_test 4.2.3 {
+ SELECT docid, quote(size) FROM ft4_docsize
+} {1 X'05' 2 X'05' 3 X'04' 4 X'05' 5 X'05'}
+
+do_execsql_test 4.2.4 {
+ INSERT INTO ft4x(ft4x) VALUES('rebuild');
+ SELECT id, quote(value) FROM ft4x_stat;
+ SELECT docid, quote(size) FROM ft4x_docsize
+} {0 X'05182B' 1 X'05' 2 X'05' 3 X'04' 4 X'05' 5 X'05'}
+
+do_execsql_test 4.2.5 {
+ INSERT INTO ft4(ft4) VALUES('rebuild');
+ SELECT id, quote(value) FROM ft4_stat;
+ SELECT docid, quote(size) FROM ft4_docsize
+} {0 X'000000'}
+
+do_execsql_test 4.2.6 {
+ INSERT INTO t4(rowid, x) SELECT rowid, x FROM ft4x;
+ INSERT INTO ft4(ft4) VALUES('rebuild');
+ SELECT id, quote(value) FROM ft4_stat;
+ SELECT docid, quote(size) FROM ft4_docsize
+} {0 X'05182B' 1 X'05' 2 X'05' 3 X'04' 4 X'05' 5 X'05'}
+
+
+#-------------------------------------------------------------------------
+# Test cases 5.* test that the following commands do not create/move or
+# delete a %_content table when used with a content=xxx FTS table.
+#
+do_execsql_test 5.1.1 {
+ CREATE TABLE t5(a, b, c, d);
+ CREATE VIRTUAL TABLE ft5 USING fts4(content=t5);
+ SELECT name FROM sqlite_master WHERE name LIKE '%t5%';
+} {
+ t5 ft5 ft5_segments ft5_segdir
+ sqlite_autoindex_ft5_segdir_1 ft5_docsize ft5_stat
+}
+do_execsql_test 5.1.2 {
+ ALTER TABLE ft5 RENAME TO ft6;
+ SELECT name FROM sqlite_master WHERE name LIKE '%t5%';
+} {
+ t5
+}
+do_execsql_test 5.1.3 {
+ SELECT name FROM sqlite_master WHERE name LIKE '%t6%';
+} {
+ ft6 ft6_segments ft6_segdir
+ sqlite_autoindex_ft6_segdir_1 ft6_docsize ft6_stat
+}
+do_execsql_test 5.1.4 {
+ INSERT INTO t5 VALUES('a', 'b', 'c', 'd');
+ INSERT INTO ft6(ft6) VALUES('rebuild');
+ SELECT rowid FROM ft6 WHERE ft6 MATCH 'b';
+} {1}
+do_execsql_test 5.1.5 {
+ DROP TABLE ft6;
+ SELECT * FROM t5;
+} {a b c d}
+do_execsql_test 5.1.6 {
+ SELECT name FROM sqlite_master WHERE name LIKE '%t6%';
+} {
+}
+do_execsql_test 5.1.7 {
+ CREATE VIRTUAL TABLE ft5 USING fts4(content=t5);
+ CREATE TABLE t5_content(a, b);
+ DROP TABLE ft5;
+ SELECT name FROM sqlite_master WHERE name LIKE '%t5%';
+} {
+ t5 t5_content
+}
+
+#-------------------------------------------------------------------------
+# Test cases 6.* test
+#
+do_catchsql_test 6.1.1 {
+ CREATE VIRTUAL TABLE ft7 USING fts4(content=t7);
+} {1 {vtable constructor failed: ft7}}
+
+do_execsql_test 6.2.1 {
+ CREATE TABLE t7(one, two);
+ CREATE VIRTUAL TABLE ft7 USING fts4(content=t7);
+ INSERT INTO t7 VALUES('A B', 'B A');
+ INSERT INTO t7 VALUES('C D', 'A A');
+ SELECT * FROM ft7;
+} {
+ {A B} {B A} {C D} {A A}
+}
+
+do_catchsql_test 6.2.2 {
+ DROP TABLE t7;
+ SELECT * FROM ft7;
+} {1 {SQL logic error or missing database}}
+
+db close
+sqlite3 db test.db
+do_execsql_test 6.2.3 {
+ SELECT name FROM sqlite_master WHERE name LIKE '%t7%'
+} {
+ ft7 ft7_segments ft7_segdir sqlite_autoindex_ft7_segdir_1
+ ft7_docsize ft7_stat
+}
+do_catchsql_test 6.2.4 {
+ SELECT * FROM ft7;
+} {1 {vtable constructor failed: ft7}}
+do_execsql_test 6.2.5 {
+ CREATE TABLE t7(x, y);
+ INSERT INTO t7 VALUES('A B', 'B A');
+ INSERT INTO t7 VALUES('C D', 'A A');
+ SELECT * FROM ft7;
+} {
+ {A B} {B A} {C D} {A A}
+}
+
+do_execsql_test 6.2.6 {
+ INSERT INTO ft7(ft7) VALUES('rebuild');
+ SELECT rowid FROM ft7 WHERE ft7 MATCH '"A A"';
+} {2}
+
+do_execsql_test 6.2.7 {
+ DROP TABLE t7;
+ CREATE TABLE t7(x);
+}
+do_catchsql_test 6.2.8 {
+ SELECT * FROM ft7 WHERE ft7 MATCH '"A A"';
+} {1 {SQL logic error or missing database}}
+do_catchsql_test 6.2.9 {
+ SELECT * FROM ft7 WHERE ft7 MATCH '"A A"';
+} {1 {SQL logic error or missing database}}
+
+db close
+sqlite3 db test.db
+do_catchsql_test 6.2.10 {
+ SELECT rowid FROM ft7 WHERE ft7 MATCH '"A A"';
+} {0 2}
+do_catchsql_test 6.2.11 {
+ SELECT rowid, * FROM ft7 WHERE ft7 MATCH '"A A"';
+} {0 {2 {}}}
+
+#-------------------------------------------------------------------------
+# Test cases 7.*
+#
+do_execsql_test 7.1.1 {
+ CREATE VIRTUAL TABLE ft8 USING fts4(content=nosuchtable, x);
+ INSERT INTO ft8(docid, x) VALUES(13, 'U O N X G');
+ INSERT INTO ft8(docid, x) VALUES(14, 'C J J U B');
+ INSERT INTO ft8(docid, x) VALUES(15, 'N J Y G X');
+ INSERT INTO ft8(docid, x) VALUES(16, 'R Y D O R');
+ INSERT INTO ft8(docid, x) VALUES(17, 'I Y T Q O');
+}
+
+do_execsql_test 7.1.2 {
+ SELECT docid FROM ft8 WHERE ft8 MATCH 'N';
+} {13 15}
+
+do_execsql_test 7.2.1 {
+ CREATE VIRTUAL TABLE ft9 USING fts4(content=, x);
+ INSERT INTO ft9(docid, x) VALUES(13, 'U O N X G');
+ INSERT INTO ft9(docid, x) VALUES(14, 'C J J U B');
+ INSERT INTO ft9(docid, x) VALUES(15, 'N J Y G X');
+ INSERT INTO ft9(docid, x) VALUES(16, 'R Y D O R');
+ INSERT INTO ft9(docid, x) VALUES(17, 'I Y T Q O');
+}
+do_execsql_test 7.2.2 {
+ SELECT docid FROM ft9 WHERE ft9 MATCH 'N';
+} {13 15}
+do_execsql_test 7.2.3 {
+ SELECT name FROM sqlite_master WHERE name LIKE 'ft9_%';
+} {ft9_segments ft9_segdir ft9_docsize ft9_stat}
+
+do_catchsql_test 7.2.4 {
+ SELECT * FROM ft9 WHERE ft9 MATCH 'N';
+} {1 {SQL logic error or missing database}}
+
+finish_test
diff --git a/test/func3.test b/test/func3.test
index e58d730f..d5a462fe 100644
--- a/test/func3.test
+++ b/test/func3.test
@@ -17,24 +17,26 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
-do_test func3-1.1 {
- set destroyed 0
- proc destroy {} { set ::destroyed 1 }
- sqlite3_create_function_v2 db f2 -1 any -func f2 -destroy destroy
- set destroyed
-} 0
-do_test func3-1.2 {
- sqlite3_create_function_v2 db f2 -1 utf8 -func f2
- set destroyed
-} 0
-do_test func3-1.3 {
- sqlite3_create_function_v2 db f2 -1 utf16le -func f2
- set destroyed
-} 0
-do_test func3-1.4 {
- sqlite3_create_function_v2 db f2 -1 utf16be -func f2
- set destroyed
-} 1
+ifcapable utf16 {
+ do_test func3-1.1 {
+ set destroyed 0
+ proc destroy {} { set ::destroyed 1 }
+ sqlite3_create_function_v2 db f2 -1 any -func f2 -destroy destroy
+ set destroyed
+ } 0
+ do_test func3-1.2 {
+ sqlite3_create_function_v2 db f2 -1 utf8 -func f2
+ set destroyed
+ } 0
+ do_test func3-1.3 {
+ sqlite3_create_function_v2 db f2 -1 utf16le -func f2
+ set destroyed
+ } 0
+ do_test func3-1.4 {
+ sqlite3_create_function_v2 db f2 -1 utf16be -func f2
+ set destroyed
+ } 1
+}
do_test func3-2.1 {
set destroyed 0
diff --git a/test/fuzz_malloc.test b/test/fuzz_malloc.test
index f2209aab..1e31babd 100644
--- a/test/fuzz_malloc.test
+++ b/test/fuzz_malloc.test
@@ -47,7 +47,7 @@ proc do_fuzzy_malloc_test {testname args} {
sqlite3_memdebug_fail -1
db close
- file delete test.db test.db-journal
+ delete_file test.db test.db-journal
sqlite3 db test.db
set ::prep $::fuzzyopts(-sqlprep)
execsql $::prep
diff --git a/test/fuzzer1.test b/test/fuzzer1.test
index d0575d2d..6c232118 100644
--- a/test/fuzzer1.test
+++ b/test/fuzzer1.test
@@ -1376,7 +1376,7 @@ do_test fuzzer1-2.3 {
AND f2.distance<=200
AND streetname.n>=f2.word AND streetname.n<=(f2.word || x'F7BFBFBF')
}
-} {steelewood tallia tallu talwyn taymouth thelema trailer {tyler finley}}
+} {{tyler finley} trailer taymouth steelewood tallia tallu talwyn thelema}
finish_test
diff --git a/test/hook.test b/test/hook.test
index c4dfb2e4..a195275c 100644
--- a/test/hook.test
+++ b/test/hook.test
@@ -95,7 +95,7 @@ do_test hook-3.9 {
# Ticket #3564.
#
do_test hook-3.10 {
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
sqlite3 db2 test2.db
proc commit_hook {} {
set y [db2 one {SELECT y FROM t3 WHERE y>10}]
@@ -217,7 +217,7 @@ ifcapable trigger {
set ::update_hook {}
ifcapable attach {
do_test hook-4.2.3 {
- file delete -force test2.db
+ forcedelete test2.db
execsql {
ATTACH 'test2.db' AS aux;
CREATE TABLE aux.t3(a INTEGER PRIMARY KEY, b);
diff --git a/test/incrblob.test b/test/incrblob.test
index 9c9389eb..388c4ba3 100644
--- a/test/incrblob.test
+++ b/test/incrblob.test
@@ -120,7 +120,7 @@ foreach AutoVacuumMode [list 0 1] {
}
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql "PRAGMA auto_vacuum = $AutoVacuumMode"
@@ -379,7 +379,7 @@ ifcapable vtab {
#
ifcapable attach {
do_test incrblob-5.1 {
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
set ::size [expr [file size [info script]]]
execsql {
ATTACH 'test2.db' AS aux;
@@ -584,7 +584,7 @@ set ::data [read $fd 14000]
close $fd
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
do_test incrblob-7.2.1 {
diff --git a/test/incrblob_err.test b/test/incrblob_err.test
index b4c25877..35d37fee 100644
--- a/test/incrblob_err.test
+++ b/test/incrblob_err.test
@@ -35,6 +35,7 @@ do_malloc_test 1 -tclprep {
}
} -tclbody {
set ::blob [db incrblob blobs v 1]
+ fconfigure $::blob -translation binary
set rc [catch {puts -nonewline $::blob $::data}]
if {$rc} { error "out of memory" }
}
@@ -71,8 +72,7 @@ do_malloc_test 3 -tclprep {
if {$rc} {
error "out of memory"
}
-}
-
+}
do_ioerr_test incrblob_err-4 -cksum 1 -sqlprep {
CREATE TABLE blobs(k, v BLOB);
@@ -87,6 +87,7 @@ do_ioerr_test incrblob_err-5 -cksum 1 -sqlprep {
INSERT INTO blobs VALUES(1, zeroblob(length(CAST($::data AS BLOB))));
} -tclbody {
set ::blob [db incrblob blobs v 1]
+ fconfigure $::blob -translation binary
puts -nonewline $::blob $::data
close $::blob
}
@@ -96,6 +97,7 @@ do_ioerr_test incrblob_err-6 -cksum 1 -sqlprep {
INSERT INTO blobs VALUES(1, $::data || $::data || $::data);
} -tclbody {
set ::blob [db incrblob blobs v 1]
+ fconfigure $::blob -translation binary
seek $::blob -20 end
puts -nonewline $::blob "12345678900987654321"
close $::blob
diff --git a/test/incrvacuum.test b/test/incrvacuum.test
index d037d8e7..91f5c8e1 100644
--- a/test/incrvacuum.test
+++ b/test/incrvacuum.test
@@ -331,7 +331,7 @@ proc compare_dbs {A B tname} {
set ::str1 [string repeat abcdefghij 130]
set ::str2 [string repeat 1234567890 105]
-file delete -force test1.db test1.db-journal test2.db test2.db-journal
+forcedelete test1.db test1.db-journal test2.db test2.db-journal
sqlite3 db1 test1.db
sqlite3 db2 test2.db
execsql { PRAGMA auto_vacuum = 'none' } db1
@@ -475,7 +475,7 @@ do_test incrvacuum-8.1 {
#
do_test incrvacuum-9.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
@@ -593,7 +593,7 @@ do_test incrvacuum-10.8 {
# vacuum mode.
#
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
ifcapable default_autovacuum {
@@ -651,7 +651,7 @@ do_test incrvacuum-11.7 {
# auto_vacuum = XXX" statement is executed.
#
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
do_test incrvacuum-12.1 {
@@ -692,7 +692,7 @@ do_test incrvacuum-12.5 {
#
db2 close
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db ; set ::DB [sqlite3_connection_pointer db]
sqlite3 db2 test.db
@@ -743,7 +743,7 @@ if {[permutation] == ""} {
do_test incrvacuum-15.1 {
db close
db2 close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
set str [string repeat "abcdefghij" 500]
diff --git a/test/incrvacuum2.test b/test/incrvacuum2.test
index 902517c9..e67a0862 100644
--- a/test/incrvacuum2.test
+++ b/test/incrvacuum2.test
@@ -70,7 +70,7 @@ do_test incrvacuum2-1.4 {
#
ifcapable attach {
do_test incrvacuum2-2.1 {
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
execsql {
ATTACH DATABASE 'test2.db' AS aux;
PRAGMA aux.auto_vacuum=incremental;
diff --git a/test/incrvacuum_ioerr.test b/test/incrvacuum_ioerr.test
index 47027b82..946925d7 100644
--- a/test/incrvacuum_ioerr.test
+++ b/test/incrvacuum_ioerr.test
@@ -108,7 +108,7 @@ do_ioerr_test incrvacuum-ioerr-3 -start 1 -cksum 1 -tclprep {
ifcapable shared_cache {
catch { db close }
- file delete -force test.db
+ forcedelete test.db
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
# Create two connections to a single shared-cache:
diff --git a/test/index4.test b/test/index4.test
new file mode 100644
index 00000000..018ed744
--- /dev/null
+++ b/test/index4.test
@@ -0,0 +1,126 @@
+# 2011 July 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.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing the CREATE INDEX statement.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set testprefix index4
+
+do_execsql_test 1.1 {
+ BEGIN;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(randomblob(102));
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 2
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 4
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 8
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 16
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 32
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 64
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 128
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 256
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 512
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 1024
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 2048
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 4096
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 8192
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 16384
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 32768
+ INSERT INTO t1 SELECT randomblob(102) FROM t1; -- 65536
+ COMMIT;
+}
+
+do_execsql_test 1.2 {
+ CREATE INDEX i1 ON t1(x);
+}
+do_execsql_test 1.3 {
+ PRAGMA integrity_check
+} {ok}
+
+# The same test again - this time with limited memory.
+#
+ifcapable memorymanage {
+ set soft_limit [sqlite3_soft_heap_limit 50000]
+
+ db close
+ sqlite3 db test.db
+
+ do_execsql_test 1.4 {
+ PRAGMA cache_size = 10;
+ CREATE INDEX i2 ON t1(x);
+ }
+ do_execsql_test 1.5 {
+ PRAGMA integrity_check
+ } {ok}
+
+ sqlite3_soft_heap_limit $soft_limit
+}
+
+
+do_execsql_test 1.6 {
+ BEGIN;
+ DROP TABLE t1;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES('a');
+ INSERT INTO t1 VALUES('b');
+ INSERT INTO t1 VALUES('c');
+ INSERT INTO t1 VALUES('d');
+ INSERT INTO t1 VALUES('e');
+ INSERT INTO t1 VALUES('f');
+ INSERT INTO t1 VALUES('g');
+ INSERT INTO t1 VALUES(NULL);
+ INSERT INTO t1 SELECT randomblob(1202) FROM t1; -- 16
+ INSERT INTO t1 SELECT randomblob(2202) FROM t1; -- 32
+ INSERT INTO t1 SELECT randomblob(3202) FROM t1; -- 64
+ INSERT INTO t1 SELECT randomblob(4202) FROM t1; -- 128
+ INSERT INTO t1 SELECT randomblob(5202) FROM t1; -- 256
+ COMMIT;
+ CREATE INDEX i1 ON t1(x);
+ PRAGMA integrity_check
+} {ok}
+
+do_execsql_test 1.7 {
+ BEGIN;
+ DROP TABLE t1;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES('a');
+ COMMIT;
+ CREATE INDEX i1 ON t1(x);
+ PRAGMA integrity_check
+} {ok}
+
+do_execsql_test 1.8 {
+ BEGIN;
+ DROP TABLE t1;
+ CREATE TABLE t1(x);
+ COMMIT;
+ CREATE INDEX i1 ON t1(x);
+ PRAGMA integrity_check
+} {ok}
+
+do_execsql_test 2.1 {
+ BEGIN;
+ CREATE TABLE t2(x);
+ INSERT INTO t2 VALUES(14);
+ INSERT INTO t2 VALUES(35);
+ INSERT INTO t2 VALUES(15);
+ INSERT INTO t2 VALUES(35);
+ INSERT INTO t2 VALUES(16);
+ COMMIT;
+}
+do_catchsql_test 2.2 {
+ CREATE UNIQUE INDEX i3 ON t2(x);
+} {1 {indexed columns are not unique}}
+
+
+finish_test
diff --git a/test/indexfault.test b/test/indexfault.test
new file mode 100644
index 00000000..efe49321
--- /dev/null
+++ b/test/indexfault.test
@@ -0,0 +1,342 @@
+# 2011 August 08
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+source $testdir/malloc_common.tcl
+
+ifcapable !mergesort {
+ finish_test
+ return
+}
+
+set testprefix indexfault
+
+# Set up the custom fault-injector. This is further configured by using
+# different values for $::custom_filter and different implementations
+# of Tcl proc [xCustom] for each test case.
+#
+proc install_custom_faultsim {} {
+ set ::FAULTSIM(custom) [list \
+ -injectinstall custom_injectinstall \
+ -injectstart custom_injectstart \
+ -injectstop custom_injectstop \
+ -injecterrlist {{1 {disk I/O error}}} \
+ -injectuninstall custom_injectuninstall \
+ ]
+ proc custom_injectinstall {} {
+ testvfs shmfault -default true
+ shmfault filter $::custom_filter
+ shmfault script xCustom
+ }
+ proc custom_injectuninstall {} {
+ catch {db close}
+ catch {db2 close}
+ shmfault delete
+ }
+ set ::custom_ifail -1
+ set ::custom_nfail -1
+ proc custom_injectstart {iFail} {
+ set ::custom_ifail $iFail
+ set ::custom_nfail 0
+ }
+ proc custom_injectstop {} {
+ set ::custom_ifail -1
+ return $::custom_nfail
+ }
+}
+proc uninstall_custom_faultsim {} {
+ unset -nocomplain ::FAULTSIM(custom)
+}
+
+
+#-------------------------------------------------------------------------
+# These tests - indexfault-1.* - Build an index on a smallish table with
+# all different kinds of fault-injection. The CREATE INDEX is run once
+# with default options and once with a 50KB soft-heap-limit.
+#
+do_execsql_test 1.0 {
+ BEGIN;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(randomblob(202));
+ INSERT INTO t1 SELECT randomblob(202) FROM t1; -- 2
+ INSERT INTO t1 SELECT randomblob(202) FROM t1; -- 4
+ INSERT INTO t1 SELECT randomblob(202) FROM t1; -- 8
+ INSERT INTO t1 SELECT randomblob(202) FROM t1; -- 16
+ INSERT INTO t1 SELECT randomblob(202) FROM t1; -- 32
+ INSERT INTO t1 SELECT randomblob(202) FROM t1; -- 64
+ INSERT INTO t1 SELECT randomblob(202) FROM t1; -- 128
+ INSERT INTO t1 SELECT randomblob(202) FROM t1; -- 256
+ COMMIT;
+}
+faultsim_save_and_close
+
+do_faultsim_test 1.1 -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql { CREATE INDEX i1 ON t1(x) }
+ faultsim_test_result {0 {}}
+ faultsim_integrity_check
+}
+ifcapable memorymanage {
+ set soft_limit [sqlite3_soft_heap_limit 50000]
+ do_faultsim_test 2.1 -prep {
+ faultsim_restore_and_reopen
+ } -body {
+ execsql { CREATE INDEX i1 ON t1(x) }
+ faultsim_test_result {0 {}}
+ }
+ sqlite3_soft_heap_limit $soft_limit
+}
+
+#-------------------------------------------------------------------------
+# These are similar to the indexfault-1.* tests, except they create an
+# index with more than one column.
+#
+sqlite3 db test.db
+do_execsql_test 2.0 {
+ BEGIN;
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(t,u,v,w,x,y,z);
+ INSERT INTO t1 VALUES(
+ randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+ randomblob(30), randomblob(30), randomblob(30)
+ );
+ INSERT INTO t1 SELECT
+ randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+ randomblob(30), randomblob(30), randomblob(30) FROM t1; -- 2
+ INSERT INTO t1 SELECT
+ randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+ randomblob(30), randomblob(30), randomblob(30) FROM t1; -- 4
+ INSERT INTO t1 SELECT
+ randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+ randomblob(30), randomblob(30), randomblob(30) FROM t1; -- 8
+ INSERT INTO t1 SELECT
+ randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+ randomblob(30), randomblob(30), randomblob(30) FROM t1; -- 16
+ INSERT INTO t1 SELECT
+ randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+ randomblob(30), randomblob(30), randomblob(30) FROM t1; -- 32
+ INSERT INTO t1 SELECT
+ randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+ randomblob(30), randomblob(30), randomblob(30) FROM t1; -- 64
+ INSERT INTO t1 SELECT
+ randomblob(30), randomblob(30), randomblob(30), randomblob(30),
+ randomblob(30), randomblob(30), randomblob(30) FROM t1; -- 128
+ COMMIT;
+}
+faultsim_save_and_close
+
+do_faultsim_test 2.1 -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql { CREATE INDEX i1 ON t1(t,u,v,w,x,y,z) }
+ faultsim_test_result {0 {}}
+ faultsim_integrity_check
+}
+ifcapable memorymanage {
+ set soft_limit [sqlite3_soft_heap_limit 50000]
+ do_faultsim_test 2.2 -prep {
+ faultsim_restore_and_reopen
+ } -body {
+ execsql { CREATE INDEX i1 ON t1(t,u,v,w,x,y,z) }
+ faultsim_test_result {0 {}}
+ }
+ sqlite3_soft_heap_limit $soft_limit
+}
+
+#-------------------------------------------------------------------------
+# The following tests - indexfault-2.* - all attempt to build a index
+# on table t1 in the main database with injected IO errors. Individual
+# test cases work as follows:
+#
+# 3.1: IO errors injected into xOpen() calls.
+# 3.2: As 7.1, but with a low (50KB) soft-heap-limit.
+#
+# 3.3: IO errors injected into the first 200 write() calls made on the
+# second temporary file.
+# 3.4: As 7.3, but with a low (50KB) soft-heap-limit.
+#
+# 3.5: After a certain amount of data has been read from the main database
+# file (and written into the temporary b-tree), sqlite3_release_memory()
+# is called to free as much memory as possible. This causes the temp
+# b-tree to be flushed to disk. So that before its contents can be
+# transfered to a PMA they must be read back from disk - creating extra
+# opportunities for IO errors.
+#
+install_custom_faultsim
+
+# Set up a table to build indexes on. Save the setup using the
+# [faultsim_save_and_close] mechanism.
+#
+sqlite3 db test.db
+do_execsql_test 3.0 {
+ BEGIN;
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(randomblob(11000));
+ INSERT INTO t1 SELECT randomblob(11001) FROM t1; -- 2
+ INSERT INTO t1 SELECT randomblob(11002) FROM t1; -- 4
+ INSERT INTO t1 SELECT randomblob(11003) FROM t1; -- 8
+ INSERT INTO t1 SELECT randomblob(11004) FROM t1; -- 16
+ INSERT INTO t1 SELECT randomblob(11005) FROM t1; -- 32
+ INSERT INTO t1 SELECT randomblob(11006) FROM t1; -- 64
+ INSERT INTO t1 SELECT randomblob(11007) FROM t1; -- 128
+ INSERT INTO t1 SELECT randomblob(11008) FROM t1; -- 256
+ INSERT INTO t1 SELECT randomblob(11009) FROM t1; -- 512
+ COMMIT;
+}
+faultsim_save_and_close
+
+set ::custom_filter xOpen
+proc xCustom {args} {
+ incr ::custom_ifail -1
+ if {$::custom_ifail==0} {
+ incr ::custom_nfail
+ return "SQLITE_IOERR"
+ }
+ return "SQLITE_OK"
+}
+do_faultsim_test 3.1 -faults custom -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql { CREATE INDEX i1 ON t1(x) }
+ faultsim_test_result {0 {}}
+}
+ifcapable memorymanage {
+ set soft_limit [sqlite3_soft_heap_limit 50000]
+ do_faultsim_test 3.2 -faults custom -prep {
+ faultsim_restore_and_reopen
+ } -body {
+ execsql { CREATE INDEX i1 ON t1(x) }
+ faultsim_test_result {0 {}}
+ }
+ sqlite3_soft_heap_limit $soft_limit
+}
+
+set ::custom_filter {xOpen xWrite}
+proc xCustom {method args} {
+ if {$method == "xOpen"} {
+ if {[lindex $args 0] == ""} {
+ incr ::nTmpOpen 1
+ if {$::nTmpOpen == 3} { return "failme" }
+ }
+ return "SQLITE_OK"
+ }
+ if {$::custom_ifail<200 && [lindex $args 1] == "failme"} {
+ incr ::custom_ifail -1
+ if {$::custom_ifail==0} {
+ incr ::custom_nfail
+ return "SQLITE_IOERR"
+ }
+ }
+ return "SQLITE_OK"
+}
+
+do_faultsim_test 3.3 -faults custom -prep {
+ faultsim_restore_and_reopen
+ set ::nTmpOpen 0
+} -body {
+ execsql { CREATE INDEX i1 ON t1(x) }
+ faultsim_test_result {0 {}}
+}
+
+ifcapable memorymanage {
+ set soft_limit [sqlite3_soft_heap_limit 50000]
+ do_faultsim_test 3.4 -faults custom -prep {
+ faultsim_restore_and_reopen
+ set ::nTmpOpen 0
+ } -body {
+ execsql { CREATE INDEX i1 ON t1(x) }
+ faultsim_test_result {0 {}}
+ }
+ sqlite3_soft_heap_limit $soft_limit
+}
+
+uninstall_custom_faultsim
+
+#-------------------------------------------------------------------------
+# Test 4: After a certain amount of data has been read from the main database
+# file (and written into the temporary b-tree), sqlite3_release_memory() is
+# called to free as much memory as possible. This causes the temp b-tree to be
+# flushed to disk. So that before its contents can be transfered to a PMA they
+# must be read back from disk - creating extra opportunities for IO errors.
+#
+install_custom_faultsim
+
+catch { db close }
+forcedelete test.db
+sqlite3 db test.db
+
+do_execsql_test 4.0 {
+ BEGIN;
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(randomblob(11000));
+ INSERT INTO t1 SELECT randomblob(11001) FROM t1; -- 2
+ INSERT INTO t1 SELECT randomblob(11002) FROM t1; -- 4
+ INSERT INTO t1 SELECT randomblob(11003) FROM t1; -- 8
+ INSERT INTO t1 SELECT randomblob(11004) FROM t1; -- 16
+ INSERT INTO t1 SELECT randomblob(11005) FROM t1; -- 32
+ INSERT INTO t1 SELECT randomblob(11005) FROM t1; -- 64
+ COMMIT;
+}
+faultsim_save_and_close
+
+testvfs tvfs
+tvfs script xRead
+tvfs filter xRead
+set ::nRead 0
+proc xRead {method file args} {
+ if {[file tail $file] == "test.db"} { incr ::nRead }
+}
+
+do_test 4.1 {
+ sqlite3 db test.db -vfs tvfs
+ execsql { CREATE INDEX i1 ON t1(x) }
+} {}
+
+db close
+tvfs delete
+
+set ::custom_filter xRead
+proc xCustom {method file args} {
+ incr ::nReadCall
+ if {$::nReadCall >= ($::nRead/5)} {
+ if {$::nReadCall == ($::nRead/5)} {
+ set nByte [sqlite3_release_memory [expr 64*1024*1024]]
+ sqlite3_soft_heap_limit 20000
+ }
+ if {$file == ""} {
+ incr ::custom_ifail -1
+ if {$::custom_ifail==0} {
+ incr ::custom_nfail
+ return "SQLITE_IOERR"
+ }
+ }
+ }
+ return "SQLITE_OK"
+}
+
+do_faultsim_test 4.2 -faults custom -prep {
+ faultsim_restore_and_reopen
+ set ::nReadCall 0
+ sqlite3_soft_heap_limit 0
+} -body {
+ execsql { CREATE INDEX i1 ON t1(x) }
+ faultsim_test_result {0 {}}
+}
+
+uninstall_custom_faultsim
+
+finish_test
diff --git a/test/insert4.test b/test/insert4.test
index 44b428a1..cb02b9dc 100644
--- a/test/insert4.test
+++ b/test/insert4.test
@@ -112,7 +112,7 @@ do_test insert4-2.4.1 {
INSERT INTO t3 SELECT DISTINCT * FROM t2;
SELECT * FROM t3;
}
-} {1 9 9 1}
+} {9 1 1 9}
xferopt_test insert4-2.4.2 0
do_test insert4-2.4.3 {
catchsql {
diff --git a/test/insert5.test b/test/insert5.test
index e48c2c32..1e58902e 100644
--- a/test/insert5.test
+++ b/test/insert5.test
@@ -34,7 +34,7 @@ proc uses_temp_table {sql} {
# Construct the sample database.
#
do_test insert5-1.0 {
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
execsql {
CREATE TABLE MAIN(Id INTEGER, Id1 INTEGER);
CREATE TABLE B(Id INTEGER, Id1 INTEGER);
diff --git a/test/io.test b/test/io.test
index 0cc26eff..58caeeeb 100644
--- a/test/io.test
+++ b/test/io.test
@@ -225,7 +225,7 @@ do_test io-2.6.2 {
}
} {1 {unable to open database file}}
do_test io-2.6.3 {
- file delete -force test.db-journal
+ forcedelete test.db-journal
catchsql { COMMIT }
} {0 {}}
do_test io-2.6.4 {
@@ -237,7 +237,7 @@ do_test io-2.6.4 {
# is created during execution of the COMMIT statement, so we have to
# use the same technique to check that it is created as in the above
# block.
-file delete -force test2.db test2.db-journal
+forcedelete test2.db test2.db-journal
ifcapable attach {
do_test io-2.7.1 {
execsql {
@@ -261,7 +261,7 @@ ifcapable attach {
catchsql { COMMIT }
} {1 {unable to open database file}}
do_test io-2.7.5 {
- file delete -force test2.db-journal
+ forcedelete test2.db-journal
catchsql { COMMIT }
} {1 {cannot commit - no transaction is active}}
do_test io-2.7.6 {
@@ -304,7 +304,7 @@ do_test io-2.9.1 {
do_test io-2.9.2 {
execsql { ROLLBACK; }
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db -vfs devsym
execsql {
PRAGMA auto_vacuum = OFF;
@@ -375,7 +375,7 @@ sqlite3_simulate_device -char sequential -sectorsize 0
ifcapable pager_pragmas {
do_test io-3.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db -vfs devsym
db eval {
PRAGMA auto_vacuum=OFF;
@@ -544,7 +544,7 @@ foreach {char sectorsize pgsize} {
incr tn
if {$pgsize>$::SQLITE_MAX_PAGE_SIZE} continue
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3_simulate_device -char $char -sectorsize $sectorsize
sqlite3 db test.db -vfs devsym
db eval {
diff --git a/test/ioerr.test b/test/ioerr.test
index f9b95555..b237439e 100644
--- a/test/ioerr.test
+++ b/test/ioerr.test
@@ -183,8 +183,8 @@ if {$tcl_platform(platform)!="windows"} {
BEGIN;
INSERT INTO t1 VALUES(3, 4);
}
- copy_file test2.db test.db
- copy_file test2.db-journal test.db-journal
+ forcecopy test2.db test.db
+ forcecopy test2.db-journal test.db-journal
db2 close
} -tclbody {
sqlite3 db test.db
@@ -219,11 +219,11 @@ if {$tcl_platform(platform)=="unix"} {
BEGIN;
INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2);
}
- copy_file test.db-journal test2.db-journal
+ forcecopy test.db-journal test2.db-journal
execsql {
COMMIT;
}
- copy_file test2.db-journal test.db-journal
+ forcecopy test2.db-journal test.db-journal
set f [open test.db-journal a]
fconfigure $f -encoding binary
puts -nonewline $f "hello"
diff --git a/test/ioerr4.test b/test/ioerr4.test
index 3a74a88a..defa3268 100644
--- a/test/ioerr4.test
+++ b/test/ioerr4.test
@@ -31,7 +31,7 @@ do_test ioerr4-1.1 {
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
} {0}
do_test ioerr4-1.2 {
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
sqlite3 db2 test.db
db eval {
@@ -79,12 +79,12 @@ do_test ioerr4-1.6 {
#
db close
db2 close
-file copy -force test.db test.db-bu
+forcecopy test.db test.db-bu
do_ioerr_test ioerr4-2 -tclprep {
catch {db2 close}
db close
- file delete -force test.db test.db-journal
- file copy -force test.db-bu test.db
+ forcedelete test.db test.db-journal
+ forcecopy test.db-bu test.db
sqlite3_enable_shared_cache 1
set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
db eval {PRAGMA auto_vacuum=INCREMENTAL}
@@ -94,7 +94,7 @@ do_ioerr_test ioerr4-2 -tclprep {
}
db2 close
-file delete -force test.db-bu
+forcedelete test.db-bu
sqlite3_enable_shared_cache $::enable_shared_cache
finish_test
diff --git a/test/journal1.test b/test/journal1.test
index a1b17b41..2fdadfd6 100644
--- a/test/journal1.test
+++ b/test/journal1.test
@@ -20,7 +20,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
# These tests will not work on windows because windows uses
-# manditory file locking which breaks the file copy command.
+# manditory file locking which breaks the copy_file command.
#
if {$tcl_platform(platform)=="windows"} {
finish_test
@@ -51,13 +51,13 @@ do_test journal1-1.2 {
BEGIN;
DELETE FROM t1;
}
- file copy -force test.db-journal test.db-journal-bu
+ forcecopy test.db-journal test.db-journal-bu
execsql {
ROLLBACK;
}
db close
- file delete test.db
- file copy test.db-journal-bu test.db-journal
+ delete_file test.db
+ copy_file test.db-journal-bu test.db-journal
sqlite3 db test.db
catchsql {
SELECT * FROM sqlite_master
diff --git a/test/journal2.test b/test/journal2.test
index 2b5d8fa8..25ce9416 100644
--- a/test/journal2.test
+++ b/test/journal2.test
@@ -167,7 +167,7 @@ do_test journal2-1.13 {
} {1 {disk I/O error}}
db2 close
unset ::tvfs_error_on_write
-file copy -force test.db testX.db
+forcecopy test.db testX.db
do_test journal2-1.14 { file exists test.db-journal } 1
do_test journal2-1.15 {
diff --git a/test/journal3.test b/test/journal3.test
index 7d297222..f1bf89f8 100644
--- a/test/journal3.test
+++ b/test/journal3.test
@@ -35,7 +35,7 @@ if {$::tcl_platform(platform) == "unix"} {
db close
set effective [format %.5o [expr $permissions & ~$umask]]
do_test journal3-1.2.$tn.1 {
- catch { file delete -force test.db-journal }
+ catch { forcedelete test.db-journal }
file attributes test.db -permissions $permissions
file attributes test.db -permissions
} $permissions
diff --git a/test/jrnlmode.test b/test/jrnlmode.test
index eab74d65..b1007c49 100644
--- a/test/jrnlmode.test
+++ b/test/jrnlmode.test
@@ -200,7 +200,7 @@ ifcapable attach {
}
ifcapable attach {
- file delete -force test2.db
+ forcedelete test2.db
do_test jrnlmode-2.1 {
execsql {
ATTACH 'test2.db' AS aux;
@@ -242,8 +242,8 @@ ifcapable attach {
# Test caes jrnlmode-3.X verify that ticket #3127 has been fixed.
#
db close
- file delete -force test2.db
- file delete -force test.db
+ forcedelete test2.db
+ forcedelete test.db
sqlite3 db test.db
do_test jrnlmode-3.1 {
@@ -270,7 +270,7 @@ ifcapable attach {
ifcapable autovacuum&&pragma {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
do_test jrnlmode-4.1 {
execsql {
@@ -303,7 +303,7 @@ ifcapable autovacuum&&pragma {
# pragma.
ifcapable pragma {
db close
- file delete -force test.db test2.db test3.db
+ forcedelete test.db test2.db test3.db
sqlite3 db test.db
do_test jrnlmode-5.1 {
@@ -511,7 +511,7 @@ ifcapable pragma {
ifcapable pragma {
catch { db close }
do_test jrnlmode-7.1 {
- foreach f [glob -nocomplain test.db*] { file delete -force $f }
+ foreach f [glob -nocomplain test.db*] { forcedelete $f }
sqlite3 db test.db
execsql {
PRAGMA journal_mode = memory;
diff --git a/test/jrnlmode2.test b/test/jrnlmode2.test
index dc3bc270..6ea87d70 100644
--- a/test/jrnlmode2.test
+++ b/test/jrnlmode2.test
@@ -112,7 +112,7 @@ do_test jrnlmode2-2.4 {
do_test jrnlmode2-2.5 {
db close
- file delete test.db-journal
+ delete_file test.db-journal
} {}
do_test jrnlmode2-2.6 {
sqlite3 db2 test.db -readonly 1
diff --git a/test/jrnlmode3.test b/test/jrnlmode3.test
index 6ae1346e..43da6579 100644
--- a/test/jrnlmode3.test
+++ b/test/jrnlmode3.test
@@ -48,7 +48,7 @@ do_test jrnlmode3-1.2 {
} {1}
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
do_test jrnlmode3-2.1 {
@@ -85,7 +85,7 @@ foreach fromjmode $all_journal_modes {
# Start with a fresh database connection an empty database file.
#
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
# Initialize the journal mode.
diff --git a/test/like.test b/test/like.test
index bd9a6c39..767efd58 100644
--- a/test/like.test
+++ b/test/like.test
@@ -70,12 +70,15 @@ do_test like-1.4 {
}
} {ABC abc}
do_test like-1.5.1 {
+ # Use sqlite3_exec() to verify fix for ticket [25ee81271091] 2011-06-26
+ sqlite3_exec db {PRAGMA case_sensitive_like=on}
+} {0 {}}
+do_test like-1.5.2 {
execsql {
- PRAGMA case_sensitive_like=on;
SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
}
} {abc}
-do_test like-1.5.2 {
+do_test like-1.5.3 {
execsql {
PRAGMA case_sensitive_like; -- no argument; does not change setting
SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
@@ -305,8 +308,8 @@ do_test like-3.18 {
#
do_test like-3.19 {
set sqlite_like_count 0
+ db eval {CREATE INDEX i1 ON t1(x);}
queryplan {
- CREATE INDEX i1 ON t1(x);
SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
}
} {abc abcd nosort {} i1}
@@ -519,7 +522,7 @@ do_test like-5.24 {
}
} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
do_test like-5.25 {
- queryplan {
+ db eval {
PRAGMA case_sensitive_like=on;
CREATE TABLE t3(x TEXT);
CREATE INDEX i3 ON t3(x);
@@ -527,6 +530,8 @@ do_test like-5.25 {
INSERT INTO t3 VALUES('zZ-lower-upper');
INSERT INTO t3 VALUES('Zz-upper-lower');
INSERT INTO t3 VALUES('zz-lower-lower');
+ }
+ queryplan {
SELECT x FROM t3 WHERE x LIKE 'zz%';
}
} {zz-lower-lower nosort {} i3}
diff --git a/test/loadext.test b/test/loadext.test
index db5745b4..8f8339ec 100644
--- a/test/loadext.test
+++ b/test/loadext.test
@@ -134,7 +134,7 @@ sqlite3_enable_load_extension db 1
# Try to load an extension for which the file does not exist.
#
do_test loadext-2.1 {
- file delete -force ${testextension}xx
+ forcedelete ${testextension}xx
set rc [catch {
sqlite3_load_extension db "${testextension}xx"
} msg]
diff --git a/test/lock4.test b/test/lock4.test
index 06ee88df..b0b1c74f 100644
--- a/test/lock4.test
+++ b/test/lock4.test
@@ -26,7 +26,7 @@ do_test lock4-1.1 {
PRAGMA auto_vacuum=OFF;
CREATE TABLE t1(x);
}
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
sqlite3 db2 test2.db
db2 eval {
PRAGMA auto_vacuum=OFF;
diff --git a/test/lock5.test b/test/lock5.test
index 6ec86ba7..f0d49550 100644
--- a/test/lock5.test
+++ b/test/lock5.test
@@ -24,7 +24,7 @@ if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
return
}
db close
-file delete -force test.db.lock
+forcedelete test.db.lock
ifcapable lock_proxy_pragmas {
set ::using_proxy 0
@@ -100,7 +100,7 @@ do_test lock5-dotfile.X {
#####################################################################
-file delete -force test.db
+forcedelete test.db
if {[catch {sqlite3 db test.db -vfs unix-flock} msg]} {
finish_test
return
diff --git a/test/main.test b/test/main.test
index dbf90410..5bbc52b8 100644
--- a/test/main.test
+++ b/test/main.test
@@ -301,7 +301,7 @@ ifcapable {trigger} {
if {[permutation] == ""} {
do_test main-2.0 {
catch {db close}
- file delete -force test.db
+ forcedelete test.db
set fd [open test.db w]
puts $fd hi!
close $fd
@@ -314,16 +314,16 @@ if {[permutation] == ""} {
#
do_test main-3.1 {
catch {db close}
- foreach f [glob -nocomplain testdb/*] {file delete -force $f}
- file delete -force testdb
+ foreach f [glob -nocomplain testdb/*] {forcedelete $f}
+ forcedelete testdb
sqlite3 db testdb
set v [catch {execsql {SELECT * from T1 where x!!5}} msg]
lappend v $msg
} {1 {unrecognized token: "!!"}}
do_test main-3.2 {
catch {db close}
- foreach f [glob -nocomplain testdb/*] {file delete -force $f}
- file delete -force testdb
+ foreach f [glob -nocomplain testdb/*] {forcedelete $f}
+ forcedelete testdb
sqlite3 db testdb
set v [catch {execsql {SELECT * from T1 where ^x}} msg]
lappend v $msg
@@ -442,8 +442,8 @@ do_test main-3.2.30 {
do_test main-3.3 {
catch {db close}
- foreach f [glob -nocomplain testdb/*] {file delete -force $f}
- file delete -force testdb
+ foreach f [glob -nocomplain testdb/*] {forcedelete $f}
+ forcedelete testdb
sqlite3 db testdb
execsql {
create table T1(X REAL); /* C-style comments allowed */
diff --git a/test/malloc.test b/test/malloc.test
index 9bd5314b..0d213d7b 100644
--- a/test/malloc.test
+++ b/test/malloc.test
@@ -270,7 +270,7 @@ do_malloc_test 9 -sqlprep {
do_malloc_test 10 -tclprep {
catch {db2 close}
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
sqlite3_extended_result_codes db 1
db eval {CREATE TABLE abc(a, b, c)}
@@ -341,8 +341,8 @@ if {$tcl_platform(platform)!="windows"} {
BEGIN;
INSERT INTO t1 VALUES(3, 4);
}
- copy_file test2.db test.db
- copy_file test2.db-journal test.db-journal
+ forcecopy test2.db test.db
+ forcecopy test2.db-journal test.db-journal
db2 close
} -tclbody {
sqlite3 db test.db
@@ -499,7 +499,7 @@ unset static_string
ifcapable attach {
do_malloc_test 20 -tclprep {
db close
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
sqlite3 db test2.db
sqlite3_extended_result_codes db 1
db eval {CREATE TABLE t1(x);}
@@ -867,32 +867,6 @@ if {[db eval {PRAGMA locking_mode}]!="exclusive"} {
catch { db2 close }
}
-ifcapable stat2&&utf16 {
- do_malloc_test 38 -tclprep {
- add_test_collate db 0 0 1
- execsql {
- ANALYZE;
- CREATE TABLE t4(x COLLATE test_collate);
- CREATE INDEX t4x ON t4(x);
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 0, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 1, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 2, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 3, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 4, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 5, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 6, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 7, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 8, 'aaa');
- INSERT INTO sqlite_stat2 VALUES('t4', 't4x', 9, 'aaa');
- }
- db close
- sqlite3 db test.db
- sqlite3_db_config_lookaside db 0 0 0
- add_test_collate db 0 0 1
- } -sqlbody {
- SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ddd' AND t42.x>'ccc'
- }
-}
# Test that if an OOM error occurs, aux-data is still correctly destroyed.
# This test case was causing either a memory-leak or an assert() failure
diff --git a/test/malloc3.test b/test/malloc3.test
index 73d2d396..2dfde466 100644
--- a/test/malloc3.test
+++ b/test/malloc3.test
@@ -463,7 +463,7 @@ TEST 29 {
# Test a simple multi-file transaction
#
-file delete -force test2.db
+forcedelete test2.db
ifcapable attach {
SQL {ATTACH 'test2.db' AS aux;}
SQL {BEGIN}
@@ -650,7 +650,7 @@ run_test $::run_test_script 1
# Close and reopen the db.
db close
-file delete -force test.db test.db-journal test2.db test2.db-journal
+forcedelete test.db test.db-journal test2.db test2.db-journal
sqlite3 db test.db
sqlite3_extended_result_codes db 1
set ::DB [sqlite3_connection_pointer db]
diff --git a/test/malloc5.test b/test/malloc5.test
index 73885b22..71f56bbb 100644
--- a/test/malloc5.test
+++ b/test/malloc5.test
@@ -219,7 +219,7 @@ do_test malloc5-4.2 {
execsql {SELECT * FROM abc}
set nMaxBytes [sqlite3_memory_highwater 1]
puts -nonewline " (Highwater mark: $nMaxBytes) "
- expr $nMaxBytes <= 100000
+ expr $nMaxBytes <= 110000
} {1}
do_test malloc5-4.3 {
# Check that the content of table abc is at least roughly as expected.
@@ -275,7 +275,7 @@ proc nPage {db} {
set stats(page)
}
db close
-file delete -force test.db test.db-journal test2.db test2.db-journal
+forcedelete test.db test.db-journal test2.db test2.db-journal
# This block of test-cases (malloc5-6.1.*) prepares two database files
# for the subsequent tests.
@@ -304,7 +304,7 @@ do_test malloc5-6.1.1 {
SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
COMMIT;
}
- copy_file test.db test2.db
+ forcecopy test.db test2.db
sqlite3 db2 test2.db
list \
[expr ([file size test.db]/1024)>20] [expr ([file size test2.db]/1024)>20]
diff --git a/test/mallocA.test b/test/mallocA.test
index 08f69302..89951276 100644
--- a/test/mallocA.test
+++ b/test/mallocA.test
@@ -27,7 +27,7 @@ if {!$MEMDEBUG} {
# Construct a test database
#
-file delete -force test.db.bu
+forcedelete test.db.bu
db eval {
CREATE TABLE t1(a COLLATE NOCASE,b,c);
INSERT INTO t1 VALUES(1,2,3);
@@ -38,7 +38,7 @@ db eval {
CREATE TABLE t2(x,y,z);
}
db close
-file copy test.db test.db.bu
+copy_file test.db test.db.bu
do_malloc_test mallocA-1 -testdb test.db.bu -sqlbody {
@@ -74,5 +74,5 @@ do_test malloc-99.X {
set sqlite_open_file_count
} {0}
-file delete -force test.db.bu
+forcedelete test.db.bu
finish_test
diff --git a/test/malloc_common.tcl b/test/malloc_common.tcl
index e7f61564..5937b958 100644
--- a/test/malloc_common.tcl
+++ b/test/malloc_common.tcl
@@ -408,7 +408,7 @@ proc do_malloc_test {tn args} {
set zRepeat "transient"
if {$::iRepeat} {set zRepeat "persistent"}
restore_prng_state
- foreach file [glob -nocomplain test.db-mj*] {file delete -force $file}
+ foreach file [glob -nocomplain test.db-mj*] {forcedelete $file}
do_test ${tn}.${zRepeat}.${::n} {
@@ -425,7 +425,7 @@ proc do_malloc_test {tn args} {
forcedelete test2.db-journal
forcedelete test2.db-wal
if {[info exists ::mallocopts(-testdb)]} {
- file copy $::mallocopts(-testdb) test.db
+ copy_file $::mallocopts(-testdb) test.db
}
catch { sqlite3 db test.db }
if {[info commands db] ne ""} {
diff --git a/test/manydb.test b/test/manydb.test
index b9a8eaf8..974a5b8e 100644
--- a/test/manydb.test
+++ b/test/manydb.test
@@ -44,7 +44,7 @@ foreach fd $filehandles {
close $fd
}
catch {
- file delete -force testfile.1
+ forcedelete testfile.1
}
set N [expr $i / $num_fd_per_openwrite_db]
@@ -92,7 +92,7 @@ for {set i 0} {$i<$N} {incr i} {
for {set i 0} {$i<$N} {incr i} {
do_test manydb-3.$i {
db$i close
- file delete -force $dbname($i)
+ forcedelete $dbname($i)
} {}
}
diff --git a/test/memsubsys1.test b/test/memsubsys1.test
index 3bb2cc71..7eecf083 100644
--- a/test/memsubsys1.test
+++ b/test/memsubsys1.test
@@ -32,7 +32,7 @@ if {[permutation] == "memsubsys1"} {
#
proc build_test_db {testname pragmas} {
catch {db close}
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 0 0
db eval $pragmas
diff --git a/test/memsubsys2.test b/test/memsubsys2.test
index ec554775..a40f4e4f 100644
--- a/test/memsubsys2.test
+++ b/test/memsubsys2.test
@@ -24,7 +24,7 @@ sqlite3_reset_auto_extension
#
proc build_test_db {testname pragmas} {
catch {db close}
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
db eval $pragmas
db eval {
diff --git a/test/misc1.test b/test/misc1.test
index a78e4884..e3f1b955 100644
--- a/test/misc1.test
+++ b/test/misc1.test
@@ -491,7 +491,7 @@ do_test misc1-14.2b {
} {1}
do_test misc1-14.3 {
cd ..
- file delete -force tempdir
+ forcedelete tempdir
execsql {COMMIT}
file exists ./test.db-journal
} {0}
diff --git a/test/misc2.test b/test/misc2.test
index f6fc3833..bb544c5f 100644
--- a/test/misc2.test
+++ b/test/misc2.test
@@ -165,7 +165,7 @@ do_test misc2-6.1 {
ifcapable tclvar {
do_test misc2-7.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql {
CREATE TABLE t1(x);
@@ -265,7 +265,7 @@ ifcapable tclvar {
#
do_test misc2-7.11 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql {
CREATE TABLE t1(x);
@@ -361,7 +361,7 @@ ifcapable tclvar {
}
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
catchsql { pragma recursive_triggers = off }
diff --git a/test/misc3.test b/test/misc3.test
index 94a43c43..81a8266b 100644
--- a/test/misc3.test
+++ b/test/misc3.test
@@ -270,7 +270,11 @@ ifcapable {explain} {
CREATE UNIQUE INDEX ex1i1 ON ex1(a);
EXPLAIN REINDEX;
}]
- regexp { IsUnique \d+ \d+ \d+ \d+ } $x
+ ifcapable mergesort {
+ regexp { SorterCompare \d+ \d+ \d+ } $x
+ } else {
+ regexp { IsUnique \d+ \d+ \d+ \d+ } $x
+ }
} {1}
if {[regexp {16} [db one {PRAGMA encoding}]]} {
do_test misc3-6.11-utf16 {
diff --git a/test/misc5.test b/test/misc5.test
index 34b2284b..14ba44ea 100644
--- a/test/misc5.test
+++ b/test/misc5.test
@@ -505,7 +505,7 @@ ifcapable subquery {
)
ORDER BY LOWER(artist) ASC;
}
- } {one}
+ } {two}
}
# Ticket #1370. Do not overwrite small files (less than 1024 bytes)
@@ -514,7 +514,7 @@ ifcapable subquery {
if {[permutation] == ""} {
do_test misc5-4.1 {
db close
- file delete -force test.db
+ forcedelete test.db
set fd [open test.db w]
puts $fd "This is not really a database"
close $fd
@@ -544,7 +544,7 @@ do_test misc5-5.4 {
# a UNION ALL query causes an error, not a crash.
#
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
ifcapable subquery&&compound {
do_test misc5-6.1 {
diff --git a/test/misc7.test b/test/misc7.test
index 7d2ba6e8..9dee3278 100644
--- a/test/misc7.test
+++ b/test/misc7.test
@@ -30,7 +30,7 @@ do_test misc7-3 {
# Try to open a directory:
#
do_test misc7-4 {
- file delete mydir
+ delete_file mydir
file mkdir mydir
set rc [catch {
sqlite3 db2 ./mydir
@@ -41,7 +41,7 @@ do_test misc7-4 {
# Try to open a file with a directory where its journal file should be.
#
do_test misc7-5 {
- file delete mydir
+ delete_file mydir
file mkdir mydir-journal
sqlite3 db2 ./mydir
catchsql {
@@ -152,8 +152,8 @@ db2 close
# after the omit_readlock pragma has been exercised.
#
do_test misc7-7.1 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
PRAGMA omit_readlock = 1;
ATTACH 'test2.db' AS aux;
@@ -254,8 +254,8 @@ ifcapable vtab {
}
db close
-file delete -force test.db
-file delete -force test.db-journal
+forcedelete test.db
+forcedelete test.db-journal
sqlite3 db test.db
ifcapable explain {
@@ -278,8 +278,8 @@ ifcapable explain {
}
db close
-file delete -force test.db
-file delete -force test.db-journal
+forcedelete test.db
+forcedelete test.db-journal
sqlite3 db test.db
#--------------------------------------------------------------------
@@ -323,8 +323,8 @@ do_test misc7-15.2 {
} {}
db close
-file delete -force test.db
-file delete -force test.db-journal
+forcedelete test.db
+forcedelete test.db-journal
sqlite3 db test.db
do_ioerr_test misc7-16 -sqlprep {
@@ -385,15 +385,15 @@ if {$tcl_platform(platform)!="windows" && $tcl_platform(platform)!="os2"} {
BEGIN;
DELETE FROM t3 WHERE (oid%3)==0;
}
- copy_file test.db bak.db
- copy_file test.db-journal bak.db-journal
+ forcecopy test.db bak.db
+ forcecopy test.db-journal bak.db-journal
execsql {
COMMIT;
}
db close
- copy_file bak.db test.db
- copy_file bak.db-journal test.db-journal
+ forcecopy bak.db test.db
+ forcecopy bak.db-journal test.db-journal
sqlite3 db test.db
catch {file attributes test.db-journal -permissions r--------}
@@ -484,6 +484,6 @@ do_test misc7-21.1 {
db close
-file delete -force test.db
+forcedelete test.db
finish_test
diff --git a/test/misuse.test b/test/misuse.test
index 3734aa01..71ee0118 100644
--- a/test/misuse.test
+++ b/test/misuse.test
@@ -39,8 +39,8 @@ proc catchsql2 {sql} {
#
do_test misuse-1.1 {
db close
- catch {file delete -force test2.db}
- catch {file delete -force test2.db-journal}
+ catch {forcedelete test2.db}
+ catch {forcedelete test2.db-journal}
sqlite3 db test2.db; set ::DB [sqlite3_connection_pointer db]
execsql {
CREATE TABLE t1(a,b);
diff --git a/test/multiplex.test b/test/multiplex.test
index 9278e842..3abdcf45 100644
--- a/test/multiplex.test
+++ b/test/multiplex.test
@@ -49,6 +49,7 @@ proc multiplex_set {db name chunk_size max_chunks} {
# and files with the chunk extension.
proc multiplex_delete {name} {
global g_max_chunks
+ forcedelete $name
for {set i 0} {$i<$g_max_chunks} {incr i} {
forcedelete [multiplex_name $name $i]
forcedelete [multiplex_name $name-journal $i]
@@ -78,10 +79,9 @@ do_test multiplex-1.8 { sqlite3_multiplex_shutdown } {SQLITE_OK}
do_test multiplex-1.9.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK}
do_test multiplex-1.9.2 { sqlite3 db test.db } {}
do_test multiplex-1.9.3 { multiplex_set db main 32768 16 } {SQLITE_OK}
-do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 } {SQLITE_MISUSE}
-do_test multiplex-1.9.5 { multiplex_set db main -1 16 } {SQLITE_MISUSE}
+do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 } {SQLITE_OK}
do_test multiplex-1.9.6 { multiplex_set db main 31 16 } {SQLITE_OK}
-do_test multiplex-1.9.7 { multiplex_set db main 32768 100 } {SQLITE_MISUSE}
+do_test multiplex-1.9.7 { multiplex_set db main 32768 100 } {SQLITE_OK}
do_test multiplex-1.9.8 { multiplex_set db main 1073741824 1 } {SQLITE_OK}
do_test multiplex-1.9.9 { db close } {}
do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown } {SQLITE_OK}
@@ -89,10 +89,9 @@ do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown } {SQLITE_OK}
do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK}
do_test multiplex-1.10.2 { sqlite3 db test.db } {}
do_test multiplex-1.10.3 { lindex [ catchsql { SELECT multiplex_control(2, 32768); } ] 0 } {0}
-do_test multiplex-1.10.4 { lindex [ catchsql { SELECT multiplex_control(3, -1); } ] 0 } {1}
-do_test multiplex-1.10.5 { lindex [ catchsql { SELECT multiplex_control(2, -1); } ] 0 } {1}
+do_test multiplex-1.10.4 { lindex [ catchsql { SELECT multiplex_control(3, -1); } ] 0 } {0}
do_test multiplex-1.10.6 { lindex [ catchsql { SELECT multiplex_control(2, 31); } ] 0 } {0}
-do_test multiplex-1.10.7 { lindex [ catchsql { SELECT multiplex_control(3, 100); } ] 0 } {1}
+do_test multiplex-1.10.7 { lindex [ catchsql { SELECT multiplex_control(3, 100); } ] 0 } {0}
do_test multiplex-1.10.8 { lindex [ catchsql { SELECT multiplex_control(2, 1073741824); } ] 0 } {0}
do_test multiplex-1.10.9 { db close } {}
do_test multiplex-1.10.10 { sqlite3_multiplex_shutdown } {SQLITE_OK}
@@ -146,8 +145,9 @@ do_test multiplex-1.13.7 { sqlite3_multiplex_shutdown }
sqlite3_multiplex_initialize "" 1
multiplex_set db main 32768 16
+forcedelete test.x
do_test multiplex-2.1.2 {
- sqlite3 db test.db
+ sqlite3 db test.x
execsql {
PRAGMA page_size=1024;
PRAGMA auto_vacuum=OFF;
@@ -159,7 +159,7 @@ do_test multiplex-2.1.2 {
INSERT INTO t1 VALUES(2, randomblob(1100));
}
} {}
-do_test multiplex-2.1.3 { file size [multiplex_name test.db 0] } {4096}
+do_test multiplex-2.1.3 { file size [multiplex_name test.x 0] } {4096}
do_test multiplex-2.1.4 {
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
@@ -167,10 +167,10 @@ do_test multiplex-2.1.4 {
do_test multiplex-2.2.1 {
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
-do_test multiplex-2.2.3 { file size [multiplex_name test.db 0] } {6144}
+do_test multiplex-2.2.3 { file size [multiplex_name test.x 0] } {6144}
do_test multiplex-2.3.1 {
- sqlite3 db2 test2.db
+ sqlite3 db2 test2.x
db2 close
} {}
@@ -181,7 +181,7 @@ do_test multiplex-2.4.1 {
do_test multiplex-2.4.2 {
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
-do_test multiplex-2.4.4 { file size [multiplex_name test.db 0] } {7168}
+do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168}
do_test multiplex-2.4.99 {
db close
sqlite3_multiplex_shutdown
@@ -189,9 +189,9 @@ do_test multiplex-2.4.99 {
do_test multiplex-2.5.1 {
- multiplex_delete test.db
+ multiplex_delete test.x
sqlite3_multiplex_initialize "" 1
- sqlite3 db test.db
+ sqlite3 db test.x
multiplex_set db main 4096 16
} {SQLITE_OK}
@@ -236,8 +236,8 @@ do_test multiplex-2.5.8 {
db eval {SELECT a,length(b) FROM t1 WHERE a=4}
} {4 4000}
-do_test multiplex-2.5.9 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
-do_test multiplex-2.5.10 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
+do_test multiplex-2.5.9 { file size [multiplex_name test.x 0] } [list $g_chunk_size]
+do_test multiplex-2.5.10 { file size [multiplex_name test.x 1] } [list $g_chunk_size]
do_test multiplex-2.5.99 {
db close
@@ -514,7 +514,7 @@ do_test multiplex-5.4.1 {
file mkdir test.db
list [catch { sqlite3 db test.db } msg] $msg
} {1 {unable to open database file}}
-catch { file delete test.db }
+catch { delete_file test.db }
do_faultsim_test multiplex-5.5 -prep {
catch { sqlite3_multiplex_shutdown }
@@ -523,50 +523,6 @@ do_faultsim_test multiplex-5.5 -prep {
multiplex_set db main 32768 16
}
-# test that mismatch filesize is detected
-#
-# Do not run this test if $::G(perm:presql) is set. If it is set, then the
-# expected IO error will occur within the Tcl [sqlite3] wrapper, not within
-# the first SQL statement executed below. This breaks the test case.
-#
-if {0==[info exists ::G(perm:presql)] || $::G(perm:presql) == ""} {
- set all_journal_modes {delete persist truncate memory off}
- foreach jmode $all_journal_modes {
- do_test multiplex-5.6.1.$jmode {
- sqlite3_multiplex_shutdown
- multiplex_delete test.db
- sqlite3 db test.db
- db eval {
- PRAGMA page_size = 1024;
- PRAGMA auto_vacuum = off;
- }
- db eval "PRAGMA journal_mode = $jmode;"
- } $jmode
- do_test multiplex-5.6.2.$jmode {
- execsql {
- CREATE TABLE t1(a, b);
- INSERT INTO t1 VALUES(1, randomblob(15000));
- INSERT INTO t1 VALUES(2, randomblob(15000));
- INSERT INTO t1 VALUES(3, randomblob(15000));
- INSERT INTO t1 VALUES(4, randomblob(15000));
- INSERT INTO t1 VALUES(5, randomblob(15000));
- }
- db close
- sqlite3_multiplex_initialize "" 1
- sqlite3 db test.db
- multiplex_set db main 4096 16
- } {SQLITE_OK}
- do_test multiplex-5.6.3.$jmode {
- catchsql {
- INSERT INTO t1 VALUES(6, randomblob(15000));
- }
- } {1 {disk I/O error}}
- do_test multiplex-5.6.4.$jmode {
- db close
- } {}
- }
-}
-
#-------------------------------------------------------------------------
# Test that you can vacuum a multiplex'ed DB.
@@ -575,8 +531,9 @@ ifcapable vacuum {
sqlite3_multiplex_shutdown
do_test multiplex-6.0.0 {
multiplex_delete test.db
+ multiplex_delete test.x
sqlite3_multiplex_initialize "" 1
- sqlite3 db test.db
+ sqlite3 db test.x
multiplex_set db main 4096 16
} {SQLITE_OK}
@@ -592,8 +549,8 @@ do_test multiplex-6.1.0 {
INSERT INTO t1 VALUES(2, randomblob($g_chunk_size));
}
} {}
-do_test multiplex-6.2.1 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
-do_test multiplex-6.2.2 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
+do_test multiplex-6.2.1 { file size [multiplex_name test.x 0] } [list $g_chunk_size]
+do_test multiplex-6.2.2 { file size [multiplex_name test.x 1] } [list $g_chunk_size]
do_test multiplex-6.3.0 {
execsql { VACUUM }
@@ -601,7 +558,7 @@ do_test multiplex-6.3.0 {
do_test multiplex-6.99 {
db close
- multiplex_delete test.db
+ multiplex_delete test.x
sqlite3_multiplex_shutdown
} {SQLITE_OK}
diff --git a/test/nan.test b/test/nan.test
index 3257a439..df3f65b8 100644
--- a/test/nan.test
+++ b/test/nan.test
@@ -320,6 +320,52 @@ do_realnum_test nan-4.20 {
db eval {SELECT x, typeof(x) FROM t1}
} {inf real}
+do_realnum_test nan-4.30 {
+ db eval {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES('2.5e+9999');
+ SELECT x, typeof(x) FROM t1;
+ }
+} {inf real}
+do_realnum_test nan-4.31 {
+ db eval {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES('2.5e+10000');
+ SELECT x, typeof(x) FROM t1;
+ }
+} {inf real}
+
+do_realnum_test nan-4.32 {
+ db eval {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES('2.5e-9999');
+ SELECT x, typeof(x) FROM t1;
+ }
+} {0.0 real}
+do_realnum_test nan-4.33 {
+ db eval {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES('2.5e-10000');
+ SELECT x, typeof(x) FROM t1;
+ }
+} {0.0 real}
+do_realnum_test nan-4.34 {
+ db eval {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES('2.5e2147483650');
+ SELECT x, typeof(x) FROM t1;
+ }
+} {inf real}
+do_realnum_test nan-4.35 {
+ db eval {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES('2.5e-2147483650');
+ SELECT x, typeof(x) FROM t1;
+ }
+} {0.0 real}
+
+
+
finish_test
diff --git a/test/notify1.test b/test/notify1.test
index 1cfb36fe..be6a1225 100644
--- a/test/notify1.test
+++ b/test/notify1.test
@@ -140,7 +140,7 @@ do_test notify1-2.2.5 {
do_test notify1-2.3.1 {
db close
db2 close
- file delete -force test.db test2.db test3.db
+ forcedelete test.db test2.db test3.db
foreach con {db db2 db3} {
sqlite3 $con test.db
$con eval { ATTACH 'test2.db' AS aux2 }
@@ -294,7 +294,7 @@ do_malloc_test notify1-5 -tclprep {
#
db close
do_test notify1-6.1.1 {
- file delete -force test.db test2.db
+ forcedelete test.db test2.db
foreach conn {db db2 db3} {
sqlite3 $conn test.db
execsql { ATTACH 'test2.db' AS two } $conn
diff --git a/test/notify2.test b/test/notify2.test
index bfb9af81..4016b6db 100644
--- a/test/notify2.test
+++ b/test/notify2.test
@@ -167,7 +167,7 @@ foreach {iTest xStep xPrepare} {
1 sqlite3_blocking_step sqlite3_blocking_prepare_v2
2 sqlite3_step sqlite3_nonblocking_prepare_v2
} {
- file delete -force test.db test2.db test3.db
+ forcedelete test.db test2.db test3.db
set ThreadSetup "set xStep $xStep;set xPrepare $xPrepare;set nSecond $nSecond"
diff --git a/test/notify3.test b/test/notify3.test
index 0d06ce19..446f0107 100644
--- a/test/notify3.test
+++ b/test/notify3.test
@@ -25,7 +25,7 @@ ifcapable !unlock_notify||!shared_cache {
set esc [sqlite3_enable_shared_cache 1]
sqlite3 db test.db
-file delete -force test.db2 test.db2-journal test.db2-wal
+forcedelete test.db2 test.db2-journal test.db2-wal
sqlite3 db2 test.db2
do_test notify3-1.1 {
diff --git a/test/openv2.test b/test/openv2.test
index 843f8919..2a9e22d6 100644
--- a/test/openv2.test
+++ b/test/openv2.test
@@ -17,7 +17,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
do_test openv2-1.1 {
set rc [catch {sqlite3 db test.db -create 0} msg]
lappend rc $msg
diff --git a/test/oserror.test b/test/oserror.test
index bdeb8684..40d2966b 100644
--- a/test/oserror.test
+++ b/test/oserror.test
@@ -97,23 +97,25 @@ do_re_test 1.4.2 { lindex $::log 0 } {^os_unix.c:\d*: \(\d+\) open\(.*test.db\)
#--------------------------------------------------------------------------
# Tests oserror-1.* test failures in the unlink() system call.
#
-do_test 2.1.1 {
- set ::log [list]
- file mkdir test.db-wal
- forcedelete test.db
- list [catch {
- sqlite3 dbh test.db
- execsql { SELECT * FROM sqlite_master } dbh
- } msg] $msg
-} {1 {disk I/O error}}
-
-do_re_test 2.1.2 {
- lindex $::log 0
-} {^os_unix.c:\d+: \(\d+\) unlink\(.*test.db-wal\) - }
-do_test 2.1.3 {
- catch { dbh close }
- forcedelete test.db-wal
-} {}
+ifcapable wal {
+ do_test 2.1.1 {
+ set ::log [list]
+ file mkdir test.db-wal
+ forcedelete test.db
+ list [catch {
+ sqlite3 dbh test.db
+ execsql { SELECT * FROM sqlite_master } dbh
+ } msg] $msg
+ } {1 {disk I/O error}}
+
+ do_re_test 2.1.2 {
+ lindex $::log 0
+ } {^os_unix.c:\d+: \(\d+\) unlink\(.*test.db-wal\) - }
+ do_test 2.1.3 {
+ catch { dbh close }
+ forcedelete test.db-wal
+ } {}
+}
test_syscall reset
diff --git a/test/pager1.test b/test/pager1.test
index 136ca05f..0226fe49 100644
--- a/test/pager1.test
+++ b/test/pager1.test
@@ -452,7 +452,7 @@ do_test pager1.4.2.2 {
} {4 ok}
do_test pager1.4.2.3 {
faultsim_restore_and_reopen
- foreach f [glob test.db-mj*] { file delete -force $f }
+ foreach f [glob test.db-mj*] { forcedelete $f }
execsql {
SELECT count(*) FROM t1;
PRAGMA integrity_check;
@@ -469,7 +469,7 @@ do_test pager1.4.2.4 {
do_test pager1.4.2.5 {
faultsim_restore_and_reopen
hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
- foreach f [glob test.db-mj*] { file delete -force $f }
+ foreach f [glob test.db-mj*] { forcedelete $f }
execsql {
SELECT count(*) FROM t1;
PRAGMA integrity_check;
@@ -649,7 +649,7 @@ foreach {tn1 tcl} {
#
do_test pager1-4.4.$tn.7 {
faultsim_restore_and_reopen $prefix
- foreach f [glob ${prefix}-mj*] { file delete -force $f }
+ foreach f [glob ${prefix}-mj*] { forcedelete $f }
execsql "ATTACH '${prefix}2' AS aux"
} {}
do_execsql_test pager1-4.4.$tn.8 {
@@ -664,7 +664,7 @@ foreach {tn1 tcl} {
}
db close
tv delete
-file delete -force $dirname
+forcedelete $dirname
# Set up a VFS to make a copy of the file-system just before deleting a
@@ -882,7 +882,7 @@ do_test pager1.4.7.3 {
db close
catch {file attributes test.db-journal -permissions rw-rw-rw-}
catch {file attributes test.db-journal -readonly 0}
- file delete test.db-journal
+ delete_file test.db-journal
file exists test.db-journal
} {0}
@@ -1766,6 +1766,10 @@ do_multiclient_test tn {
# + Page 0,
# + A page with a page number greater than (2^31-1).
#
+# These tests will not work if SQLITE_DIRECT_OVERFLOW_READ is defined. In
+# that case IO errors are sometimes reported instead of SQLITE_CORRUPT.
+#
+ifcapable !direct_read {
do_test pager1-18.1 {
faultsim_delete_and_reopen
db func a_string a_string
@@ -1841,6 +1845,7 @@ do_test pager1-18.6 {
sqlite3 db test.db
catchsql { SELECT length(x) FROM t1 }
} {1 {database disk image is malformed}}
+}
do_test pager1-19.1 {
sqlite3 db ""
@@ -1992,31 +1997,33 @@ ifcapable wal {
# pager1-22.1.*: is a no-op on a non-WAL db, and
# pager1-22.2.*: does not cause xSync calls with a synchronous=off db.
#
-do_test pager1-22.1.1 {
- faultsim_delete_and_reopen
- execsql {
- CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def');
- INSERT INTO ko DEFAULT VALUES;
- }
- execsql { PRAGMA wal_checkpoint }
-} {0 -1 -1}
-do_test pager1-22.2.1 {
- testvfs tv -default 1
- tv filter xSync
- tv script xSyncCb
- proc xSyncCb {args} {incr ::synccount}
- set ::synccount 0
- sqlite3 db test.db
- execsql {
- PRAGMA synchronous = off;
- PRAGMA journal_mode = WAL;
- INSERT INTO ko DEFAULT VALUES;
- }
- execsql { PRAGMA wal_checkpoint }
- set synccount
-} {0}
-db close
-tv delete
+ifcapable wal {
+ do_test pager1-22.1.1 {
+ faultsim_delete_and_reopen
+ execsql {
+ CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def');
+ INSERT INTO ko DEFAULT VALUES;
+ }
+ execsql { PRAGMA wal_checkpoint }
+ } {0 -1 -1}
+ do_test pager1-22.2.1 {
+ testvfs tv -default 1
+ tv filter xSync
+ tv script xSyncCb
+ proc xSyncCb {args} {incr ::synccount}
+ set ::synccount 0
+ sqlite3 db test.db
+ execsql {
+ PRAGMA synchronous = off;
+ PRAGMA journal_mode = WAL;
+ INSERT INTO ko DEFAULT VALUES;
+ }
+ execsql { PRAGMA wal_checkpoint }
+ set synccount
+ } {0}
+ db close
+ tv delete
+}
#-------------------------------------------------------------------------
# Tests for changing journal mode.
@@ -2368,8 +2375,8 @@ do_test pager1-29.2 {
#
do_test pager1-30.1 {
db close
- file delete test.db
- file delete test.db-journal
+ delete_file test.db
+ delete_file test.db-journal
set fd [open test.db-journal w]
seek $fd [expr 512+1032*2]
puts -nonewline $fd x
@@ -2409,8 +2416,8 @@ do_test pager1-31.1 {
BEGIN;
UPDATE t1 SET y = randomblob(1499);
}
- file copy test.db test.db2
- file copy test.db-journal test.db2-journal
+ copy_file test.db test.db2
+ copy_file test.db-journal test.db2-journal
hexio_write test.db2-journal 24 00000000
sqlite3 db2 test.db2
@@ -2418,5 +2425,43 @@ do_test pager1-31.1 {
} {ok}
}
+#-------------------------------------------------------------------------
+# Test that a database file can be "pre-hinted" to a certain size and that
+# subsequent spilling of the pager cache does not result in the database
+# file being shrunk.
+#
+catch {db close}
+forcedelete test.db
+
+do_test pager1-32.1 {
+ sqlite3 db test.db
+ execsql {
+ CREATE TABLE t1(x, y);
+ }
+ db close
+ sqlite3 db test.db
+ execsql {
+ BEGIN;
+ INSERT INTO t1 VALUES(1, randomblob(10000));
+ }
+ file_control_chunksize_test db main 1024
+ file_control_sizehint_test db main 20971520; # 20MB
+ execsql {
+ PRAGMA cache_size = 10;
+ INSERT INTO t1 VALUES(1, randomblob(10000));
+ INSERT INTO t1 VALUES(2, randomblob(10000));
+ INSERT INTO t1 SELECT x+2, randomblob(10000) from t1;
+ INSERT INTO t1 SELECT x+4, randomblob(10000) from t1;
+ INSERT INTO t1 SELECT x+8, randomblob(10000) from t1;
+ INSERT INTO t1 SELECT x+16, randomblob(10000) from t1;
+ SELECT count(*) FROM t1;
+ COMMIT;
+ }
+ db close
+ file size test.db
+} {20971520}
+
+# Cleanup 20MB file left by the previous test.
+forcedelete test.db
finish_test
diff --git a/test/pagerfault.test b/test/pagerfault.test
index ced6da3b..e04e97e4 100644
--- a/test/pagerfault.test
+++ b/test/pagerfault.test
@@ -233,7 +233,7 @@ do_faultsim_test pagerfault-5.2 -prep {
do_faultsim_test pagerfault-5.3 -faults oom-transient -prep {
faultsim_restore_and_reopen
db func a_string a_string
- file delete -force test2.db test2.db-journal test2.db-wal
+ forcedelete test2.db test2.db-journal test2.db-wal
execsql {
PRAGMA journal_mode = PERSIST;
ATTACH 'test2.db' AS aux;
@@ -641,7 +641,7 @@ do_test pagerfault-13-pre1 {
COMMIT;
}
db close
- file delete -force test.db
+ forcedelete test.db
faultsim_save
} {}
do_faultsim_test pagerfault-13 -prep {
@@ -1106,7 +1106,7 @@ do_faultsim_test pagerfault-22 -prep {
#
do_faultsim_test pagerfault-23 -prep {
sqlite3 db :memory:
- foreach f [glob -nocomplain test.db*] { file delete -force $f }
+ foreach f [glob -nocomplain test.db*] { forcedelete $f }
db eval {
ATTACH 'test.db2' AS aux;
CREATE TABLE t1(a, b);
diff --git a/test/pageropt.test b/test/pageropt.test
index 1c634f64..82311965 100644
--- a/test/pageropt.test
+++ b/test/pageropt.test
@@ -17,7 +17,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-ifcapable {!pager_pragmas||secure_delete} {
+ifcapable {!pager_pragmas||secure_delete||direct_read} {
finish_test
return
}
diff --git a/test/pagesize.test b/test/pagesize.test
index af2c017b..0eebbbb7 100644
--- a/test/pagesize.test
+++ b/test/pagesize.test
@@ -42,7 +42,7 @@ do_test pagesize-1.3 {
do_test pagesize-1.4 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql {
PRAGMA page_size=511;
@@ -99,7 +99,7 @@ foreach PGSZ {512 2048 4096 8192} {
}
do_test pagesize-2.$PGSZ.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql "PRAGMA page_size=$PGSZ"
execsql {
@@ -190,7 +190,7 @@ foreach PGSZ {512 2048 4096 8192} {
integrity_check pagesize-2.$PGSZ.17
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
do_test pagesize-2.$PGSZ.30 {
execsql "
@@ -203,7 +203,7 @@ foreach PGSZ {512 2048 4096 8192} {
} [list 1024 $PGSZ]
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
do_test pagesize-2.$PGSZ.40 {
execsql "
diff --git a/test/pcache2.test b/test/pcache2.test
index 14df52eb..77e7a261 100644
--- a/test/pcache2.test
+++ b/test/pcache2.test
@@ -16,7 +16,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-
# Set up a pcache memory pool so that we can easily track how many
# pages are being used for cache.
#
@@ -34,13 +33,13 @@ do_test pcache2-1.1 {
# Open up two database connections to separate files.
#
do_test pcache2-1.2 {
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
db eval {PRAGMA cache_size=10}
lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {2}
do_test pcache2-1.3 {
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
sqlite3 db2 test2.db
db2 eval {PRAGMA cache_size=50}
lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
diff --git a/test/permutations.test b/test/permutations.test
index 22e2189d..7c3b026c 100644
--- a/test/permutations.test
+++ b/test/permutations.test
@@ -111,7 +111,7 @@ set allquicktests [test_set $alltests -exclude {
thread003.test thread004.test thread005.test trans2.test vacuum3.test
incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test
vtab_err.test walslow.test walcrash.test
- walthread.test rtree3.test
+ walthread.test rtree3.test indexfault.test
}]
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
@@ -180,10 +180,12 @@ test_suite "fts3" -prefix "" -description {
fts3defer.test fts3defer2.test fts3e.test fts3expr.test fts3expr2.test
fts3near.test fts3query.test fts3shared.test fts3snippet.test
fts3sort.test
-
fts3fault.test fts3malloc.test fts3matchinfo.test
-
fts3aux1.test fts3comp1.test fts3auto.test
+ fts4aa.test fts4content.test
+ fts3conf.test fts3prefix.test fts3fault2.test fts3corrupt.test
+ fts3corrupt2.test
+ fts3first.test
}
@@ -520,7 +522,7 @@ test_suite "inmemory_journal" -description {
# the number of fsync() calls.
pager.test exclusive.test jrnlmode.test sync.test misc1.test
journal1.test conflict.test crash8.test tkt3457.test io.test
- journal3.test
+ journal3.test 8_3_names.test
pager1.test async4.test corrupt.test filefmt.test pager2.test
corrupt5.test corruptA.test pageropt.test
@@ -529,7 +531,7 @@ test_suite "inmemory_journal" -description {
stmt.test
# WAL mode is different.
- wal* tkt-2d1a5c67d.test
+ wal* tkt-2d1a5c67d.test backcompat.test
}]
ifcapable mem3 {
@@ -726,7 +728,7 @@ test_suite "journaltest" -description {
unregister_jt_vfs
} -files [test_set $::allquicktests -exclude {
wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test
- async4.test bigfile.test
+ async4.test bigfile.test backcompat.test
}]
if {[info commands register_demovfs] != ""} {
@@ -776,6 +778,15 @@ test_suite "no_optimization" -description {
optimization_control $::dbhandle all 0
}
+test_suite "prepare" -description {
+ Run tests with the db connection using sqlite3_prepare() instead of _v2().
+} -dbconfig {
+ db_use_legacy_prepare $::dbhandle 1
+ #$::dbhandle cache size 0
+} -files [
+ test_set $allquicktests -exclude *malloc* *ioerr* *fault*
+]
+
# End of tests
#############################################################################
@@ -856,4 +867,3 @@ if {[info script] == $argv0} {
main $argv
finish_test
}
-
diff --git a/test/pragma.test b/test/pragma.test
index 4b441829..0cad25a3 100644
--- a/test/pragma.test
+++ b/test/pragma.test
@@ -51,8 +51,8 @@ ifcapable !pragma {
# that the "all.test" script does.
#
db close
-file delete test.db test.db-journal
-file delete test3.db test3.db-journal
+delete_file test.db test.db-journal
+delete_file test3.db test3.db-journal
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
@@ -221,8 +221,8 @@ do_test pragma-1.18 {
# Test modifying the safety_level of an attached database.
ifcapable pager_pragmas&&attach {
do_test pragma-2.1 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
ATTACH 'test2.db' AS aux;
}
@@ -255,7 +255,7 @@ ifcapable pager_pragmas&&attach {
#
do_test pragma-3.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql {
PRAGMA auto_vacuum=OFF;
@@ -312,7 +312,7 @@ ifcapable attach {
#
do_test pragma-3.8 {
execsql {DETACH t2}
- file delete -force testerr.db testerr.db-journal
+ forcedelete testerr.db testerr.db-journal
set out [open testerr.db w]
fconfigure $out -translation binary
set in [open test.db r]
@@ -329,6 +329,9 @@ ifcapable attach {
do_test pragma-3.8.1 {
execsql {PRAGMA quick_check}
} {ok}
+ do_test pragma-3.8.2 {
+ execsql {PRAGMA QUICK_CHECK}
+ } {ok}
do_test pragma-3.9 {
execsql {
ATTACH 'testerr.db' AS t2;
@@ -419,7 +422,7 @@ Page 6 is never used} {rowid 1 missing from index i2}}
}
do_test pragma-3.19 {
catch {db close}
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
db eval {PRAGMA integrity_check}
} {ok}
@@ -741,8 +744,8 @@ do_test pragma-8.1.10 {
} SQLITE_SCHEMA
# Make sure the schema-version can be manipulated in an attached database.
-file delete -force test2.db
-file delete -force test2.db-journal
+forcedelete test2.db
+forcedelete test2.db-journal
ifcapable attach {
do_test pragma-8.1.11 {
execsql {
@@ -1205,7 +1208,7 @@ do_test pragma-13.1 {
ifcapable pager_pragmas {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
do_test pragma-14.1 {
@@ -1219,6 +1222,9 @@ ifcapable pager_pragmas {
PRAGMA page_count;
}
} {2}
+ do_test pragma-14.2uc {
+ execsql {pragma PAGE_COUNT}
+ } {2}
do_test pragma-14.3 {
execsql {
@@ -1227,6 +1233,9 @@ ifcapable pager_pragmas {
PRAGMA page_count;
}
} {3}
+ do_test pragma-14.3uc {
+ execsql {pragma PAGE_COUNT}
+ } {3}
do_test pragma-14.4 {
set page_size [db one {pragma page_size}]
@@ -1241,7 +1250,7 @@ ifcapable pager_pragmas {
} {2}
do_test pragma-14.6 {
- file delete -force test2.db
+ forcedelete test2.db
sqlite3 db2 test2.db
execsql {
PRAGMA auto_vacuum = 0;
@@ -1256,6 +1265,9 @@ ifcapable pager_pragmas {
PRAGMA aux.page_count;
}
} {5}
+ do_test pragma-14.6uc {
+ execsql {pragma AUX.PAGE_COUNT}
+ } {5}
}
# Test that the value set using the cache_size pragma is not reset when the
diff --git a/test/pragma2.test b/test/pragma2.test
index 87c3c5d0..1111a984 100644
--- a/test/pragma2.test
+++ b/test/pragma2.test
@@ -33,8 +33,8 @@ ifcapable !pragma||!schema_pragmas {
# that the "all.test" script does.
#
db close
-file delete test.db test.db-journal
-file delete test3.db test3.db-journal
+delete_file test.db test.db-journal
+delete_file test3.db test3.db-journal
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
db eval {PRAGMA auto_vacuum=0}
@@ -61,8 +61,8 @@ do_test pragma2-1.4 {
}
} {1}
-file delete -force test2.db
-file delete -force test2.db-journal
+forcedelete test2.db
+forcedelete test2.db-journal
ifcapable attach {
do_test pragma2-2.1 {
diff --git a/test/printf.test b/test/printf.test
index 100ce96b..73222720 100644
--- a/test/printf.test
+++ b/test/printf.test
@@ -3547,7 +3547,7 @@ do_test printf-4.16 {
do_test printf-5.1 {
set x [sqlite3_mprintf_str {%d %d %100000s} 0 0 {Hello}]
string length $x
-} {344}
+} {100004}
do_test printf-5.2 {
sqlite3_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}
} {-9 -10 (HelloHello) %}
diff --git a/test/quota.test b/test/quota.test
index d7601e0e..49b403f1 100644
--- a/test/quota.test
+++ b/test/quota.test
@@ -123,7 +123,7 @@ proc quota_check {filename limitvar size} {
}
do_test quota-3.1.1 {
- file delete -force test.db
+ forcedelete test.db
sqlite3_quota_initialize "" 1
sqlite3_quota_set *test.db 4096 quota_check
} {SQLITE_OK}
@@ -158,7 +158,7 @@ do_test quota-3.1.6 {
} {SQLITE_OK}
do_test quota-3.2.1 {
- file delete force test.db test2.db
+ delete_file force test.db test2.db
sqlite3_quota_set * 4096 {}
sqlite3 db1a test.db
@@ -223,7 +223,7 @@ do_test quota-3.2.X {
} {SQLITE_OK}
#-------------------------------------------------------------------------
-# Quotas are deleted when unused and when there limit is set to zero
+# Quotas are deleted when unused and when their limit is set to zero
#
# Return a list of all currently defined quotas. Each quota is identified
@@ -235,6 +235,13 @@ proc quota_list {} {
}
return [lsort $allq]
}
+proc quota_size {name} {
+ set allq {}
+ foreach q [sqlite3_quota_dump] {
+ if {[lindex $q 0]==$name} {return [lindex $q 2]}
+ }
+ return 0
+}
do_test quota-4.1.1 {
sqlite3_quota_set *test.db 0 {}
@@ -257,7 +264,7 @@ do_test quota-4.1.5 {
quota_list
} {*test2.db}
do_test quota-4.1.6 {
- file delete -force test2.db test2.db-journal test2.db-wal
+ forcedelete test2.db test2.db-journal test2.db-wal
sqlite3 db test2.db
db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');}
quota_list
@@ -329,11 +336,121 @@ do_test quota-4.3.1 {
quota_list
} {}
+unset -nocomplain quotagroup
+if {$tcl_platform(platform)=="windows"} {
+ set quotagroup *\\quota-test-A?.db
+} else {
+ set quotagroup */quota-test-A?.db
+}
+foreach file [glob -nocomplain quota-test-A*] {
+ forcedelete $file
+}
do_test quota-4.4.1 {
+ set ::quota {}
+ sqlite3_quota_set $::quotagroup 10000 quota_callback
+ file delete -force ./quota-test-A1.db ./quota-test-A2.db
+ sqlite3 db ./quota-test-A1.db
+ db eval {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(randomblob(5000));
+ }
+ quota_list
+} [list $quotagroup]
+do_test quota-4.4.2 {
+ expr {$::quota==""}
+} {1}
+do_test quota-4.4.3 {
+ db close
+ sqlite3 db ./quota-test-A2.db
+ db eval {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(randomblob(5000));
+ }
+ quota_list
+} [list $quotagroup]
+do_test quota-4.4.4 {
+ expr {$::quota!=""}
+} {1}
+do_test quota-4.4.5 {
+ db close
+ sqlite3_quota_set $::quotagroup 0 {}
+ sqlite3_quota_dump
+} {}
+do_test quota-4.4.6 {
+ sqlite3_quota_set $quotagroup 10000 quota_callback
+ sqlite3 db quota-test-A1.db
+ db eval {SELECT count(*) FROM sqlite_master}
+ quota_size $quotagroup
+} [file size quota-test-A1.db]
+do_test quota-4.4.7 {
+ sqlite3_quota_file quota-test-A2.db
+ quota_size $::quotagroup
+} [expr {[file size quota-test-A1.db]+[file size quota-test-A2.db]}]
+
+unset -nocomplain quotagroup
+if {$tcl_platform(platform)=="windows"} {
+ set quotagroup *\\quota-test-B*
+} else {
+ set quotagroup */quota-test-B*
+}
+foreach file [glob -nocomplain quota-test-B*] {
+ forcedelete $file
+}
+do_test quota-4.5.1 {
+ sqlite3_quota_set $::quotagroup 100000 quota_callback
+ quota_size $::quotagroup
+} {0}
+do_test quota-4.5.2 {
+ sqlite3_quota_file quota-test-B1.txt
+ quota_size $::quotagroup
+} {0}
+proc add_to_file {name n} {
+ set out [open $name a]
+ fconfigure $out -translation binary
+ puts -nonewline $out [string repeat x $n]
+ close $out
+}
+do_test quota-4.5.3 {
+ add_to_file quota-test-B1.txt 123
+ sqlite3_quota_file quota-test-B1.txt
+ quota_size $::quotagroup
+} {123}
+do_test quota-4.5.4 {
+ add_to_file quota-test-B2.txt 234
+ sqlite3_quota_file quota-test-B2.txt
+ quota_size $::quotagroup
+} {357}
+do_test quota-4.5.5 {
+ add_to_file quota-test-B1.txt 2000
+ sqlite3_quota_file quota-test-B1.txt
+ quota_size $::quotagroup
+} {2357}
+do_test quota-4.5.6 {
+ forcedelete quota-test-B1.txt
+ sqlite3_quota_file quota-test-B1.txt
+ quota_size $::quotagroup
+} {234}
+do_test quota-4.5.7 {
+ forcedelete quota-test-B2.txt
+ sqlite3_quota_file quota-test-B2.txt
+ quota_size $::quotagroup
+} {0}
+do_test quota-4.5.8 {
+ add_to_file quota-test-B3.txt 1234
+ sqlite3_quota_file quota-test-B3.txt
+ quota_size $::quotagroup
+} {1234}
+do_test quota-4.5.9 {
+ sqlite3_quota_set $quotagroup 0 {}
+ quota_size $::quotagroup
+} {0}
+
+do_test quota-4.9.1 {
+ db close
sqlite3_quota_set A 1000 quota_callback
sqlite3_quota_shutdown
} {SQLITE_OK}
-do_test quota-4.4.2 {
+do_test quota-4.9.2 {
quota_list
} {}
@@ -357,7 +474,7 @@ do_faultsim_test quota-5.2 -prep {
}
catch { db close }
-file delete -force test.db
+forcedelete test.db
do_test quota-5.3.prep {
sqlite3 db test.db
@@ -377,7 +494,7 @@ do_faultsim_test quota-5.3 -prep {
do_test quota-5.4.1 {
catch { db close }
- file delete -force test.db
+ forcedelete test.db
file mkdir test.db
list [catch { sqlite3 db test.db } msg] $msg
} {1 {unable to open database file}}
diff --git a/test/releasetest.tcl b/test/releasetest.tcl
index 84542bb8..77256301 100644
--- a/test/releasetest.tcl
+++ b/test/releasetest.tcl
@@ -155,10 +155,10 @@ array set ::Configs {
array set ::Platforms {
Linux-x86_64 {
+ "Debug-One" "checksymbols test"
"Secure-Delete" test
"Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
"Update-Delete-Limit" test
- "Debug-One" test
"Extra-Robustness" test
"Device-Two" test
"Ftrapv" test
@@ -177,6 +177,7 @@ array set ::Platforms {
}
}
+
# End of configuration section.
#########################################################################
#########################################################################
diff --git a/test/rollback.test b/test/rollback.test
index d462fc48..fc123ab9 100644
--- a/test/rollback.test
+++ b/test/rollback.test
@@ -88,8 +88,8 @@ if {$tcl_platform(platform) == "unix"
BEGIN;
INSERT INTO t3 VALUES('hello world');
}
- file copy -force test.db testA.db
- file copy -force test.db-journal testA.db-journal
+ forcecopy test.db testA.db
+ forcecopy test.db-journal testA.db-journal
execsql {
COMMIT;
}
diff --git a/test/savepoint.test b/test/savepoint.test
index 042c5558..3bbbaaae 100644
--- a/test/savepoint.test
+++ b/test/savepoint.test
@@ -371,7 +371,7 @@ wal_check_journal_mode savepoint-5.5
#
ifcapable {autovacuum && pragma} {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
do_test savepoint-6.1 {
@@ -419,7 +419,7 @@ ifcapable {autovacuum && pragma} {
# surrounding savepoints by growing and shrinking the database file.
#
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
do_test savepoint-7.1 {
@@ -490,7 +490,7 @@ wal_check_journal_mode savepoint-7.3.3
do_test savepoint-7.4.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql { PRAGMA auto_vacuum = incremental }
wal_set_journal_mode
@@ -640,8 +640,8 @@ set templockstate [lindex [db eval {PRAGMA lock_status}] 3]
if {[wal_is_wal_mode]==0} {
do_test savepoint-10.2.1 {
- file delete -force test3.db
- file delete -force test2.db
+ forcedelete test3.db
+ forcedelete test2.db
execsql {
ATTACH 'test2.db' AS aux1;
ATTACH 'test3.db' AS aux2;
@@ -762,7 +762,7 @@ if {[wal_is_wal_mode]==0} {
#
do_test savepoint-11.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql { PRAGMA auto_vacuum = full; }
wal_set_journal_mode
@@ -868,7 +868,7 @@ wal_check_journal_mode savepoint-12.5
if {[wal_is_wal_mode]==0} {
do_test savepoint-13.1 {
db close
- catch {file delete -force test.db}
+ catch {forcedelete test.db}
sqlite3 db test.db
execsql {
BEGIN;
@@ -909,7 +909,7 @@ if {[wal_is_wal_mode]==0} {
}
db close
-file delete test.db
+delete_file test.db
do_multiclient_test tn {
do_test savepoint-14.$tn.1 {
sql1 {
diff --git a/test/savepoint6.test b/test/savepoint6.test
index 60fde4c2..b1d0d46f 100644
--- a/test/savepoint6.test
+++ b/test/savepoint6.test
@@ -246,7 +246,7 @@ foreach zSetup [list {
unset -nocomplain ::aEntry
catch { db close }
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
eval $zSetup
sql $DATABASE_SCHEMA
diff --git a/test/securedel.test b/test/securedel.test
index c965069e..7ff5a628 100644
--- a/test/securedel.test
+++ b/test/securedel.test
@@ -26,7 +26,7 @@ do_test securedel-1.0 {
db eval {PRAGMA secure_delete;}
} $DEFAULT_SECDEL
-file delete -force test2.db test2.db-journal
+forcedelete test2.db test2.db-journal
do_test securedel-1.1 {
db eval {
ATTACH 'test2.db' AS db2;
diff --git a/test/selectB.test b/test/selectB.test
index 3fdf85c0..b9d979ac 100644
--- a/test/selectB.test
+++ b/test/selectB.test
@@ -355,7 +355,7 @@ for {set ii 3} {$ii <= 4} {incr ii} {
SELECT DISTINCT (a/10) FROM t1 UNION ALL SELECT DISTINCT(d%2) FROM t2
)
}
- } {0 1 0 1}
+ } {0 1 1 0}
do_test selectB-$ii.20 {
execsql {
diff --git a/test/server1.test b/test/server1.test
index 134a9f57..90673ef0 100644
--- a/test/server1.test
+++ b/test/server1.test
@@ -29,7 +29,7 @@ if {[llength [info command client_step]]==0 || [sqlite3 -has-codec]} {
# The sample server implementation does not work right when memory
# management is enabled.
#
-ifcapable memorymanage {
+ifcapable (memorymanage||mutex_noop) {
finish_test
return
}
diff --git a/test/shared.test b/test/shared.test
index 35ddf088..37564e69 100644
--- a/test/shared.test
+++ b/test/shared.test
@@ -27,7 +27,7 @@ set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
foreach av [list 0 1] {
# Open the database connection and execute the auto-vacuum pragma
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
ifcapable autovacuum {
@@ -293,9 +293,9 @@ catch {db3 close}
# db2.main -> ./test2.db
# db2.test -> ./test.db
#
-file delete -force test.db
-file delete -force test2.db
-file delete -force test2.db-journal
+forcedelete test.db
+forcedelete test2.db
+forcedelete test2.db-journal
sqlite3 db test.db
sqlite3 db2 test2.db
do_test shared-$av.4.1.1 {
@@ -426,7 +426,7 @@ catch {db close}
# Tests shared-5.*
#
foreach db [list test.db test1.db test2.db test3.db] {
- file delete -force $db ${db}-journal
+ forcedelete $db ${db}-journal
}
do_test shared-$av.5.1.1 {
sqlite3 db1 test.db
@@ -557,7 +557,7 @@ do_test shared-$av.6.1.4 {
catch {db1 close}
catch {db2 close}
foreach f [list test.db test2.db] {
- file delete -force $f ${f}-journal
+ forcedelete $f ${f}-journal
}
#--------------------------------------------------------------------------
@@ -643,7 +643,7 @@ unset -nocomplain contents
# The following tests try to trick the shared-cache code into assuming
# the wrong encoding for a database.
#
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
ifcapable utf16 {
do_test shared-$av.8.1.1 {
sqlite3 db test.db
@@ -675,7 +675,7 @@ ifcapable utf16 {
}
} {UTF-8}
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
do_test shared-$av.8.2.1 {
execsql {
ATTACH 'test2.db' AS aux;
@@ -693,7 +693,7 @@ ifcapable utf16 {
catch {db close}
catch {db2 close}
- file delete -force test.db test2.db
+ forcedelete test.db test2.db
do_test shared-$av.8.3.2 {
sqlite3 db test.db
@@ -732,7 +732,7 @@ if 0 {
catch {db close}
catch {db2 close}
-file delete -force test.db test2.db
+forcedelete test.db test2.db
#---------------------------------------------------------------------------
# The following tests - shared-9.* - test interactions between TEMP triggers
@@ -772,7 +772,7 @@ do_test shared-$av.9.3 {
#
do_test shared-$av.10.1 {
# Create a small sample database with two connections to it (db and db2).
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
sqlite3 db2 test.db
execsql {
@@ -853,7 +853,7 @@ do_test shared-$av.10.11 {
} {}
do_test shared-$av.11.1 {
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
sqlite3 db2 test.db
execsql {
@@ -916,7 +916,7 @@ do_test shared-$av.11.11 {
# This tests that if it is impossible to free any pages, SQLite will
# exceed the limit set by PRAGMA cache_size.
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
ifcapable pager_pragmas {
do_test shared-$av.12.1 {
@@ -963,7 +963,7 @@ do_test shared-$av.12.X {
# database handle. This covers an extra line or two.
#
do_test shared-$av.13.1 {
- file delete -force test2.db test3.db test4.db test5.db
+ forcedelete test2.db test3.db test4.db test5.db
sqlite3 db :memory:
execsql {
ATTACH 'test2.db' AS aux2;
@@ -1026,7 +1026,7 @@ do_test shared-$av.14.3 {
# assert() statements in the C code.
#
do_test shared-$av-15.1 {
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db -fullmutex 1
sqlite3 db2 test.db -fullmutex 1
execsql {
diff --git a/test/shared2.test b/test/shared2.test
index d2a0d1b0..d40c9a27 100644
--- a/test/shared2.test
+++ b/test/shared2.test
@@ -129,7 +129,7 @@ do_test shared2-3.2 {
sqlite3_enable_shared_cache 1
} {1}
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
do_test shared2-4.1 {
diff --git a/test/shared3.test b/test/shared3.test
index 8f9eae9b..783ae6a8 100644
--- a/test/shared3.test
+++ b/test/shared3.test
@@ -24,7 +24,7 @@ set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
# Ticket #1824
#
do_test shared3-1.1 {
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db1 test.db
db1 eval {
PRAGMA encoding=UTF16;
diff --git a/test/shared4.test b/test/shared4.test
index f9f01738..83925b06 100644
--- a/test/shared4.test
+++ b/test/shared4.test
@@ -30,10 +30,10 @@ set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
# Prepare multiple databases in shared cache mode.
#
do_test shared4-1.1 {
- file delete -force test1.db test1.db-journal
- file delete -force test2.db test2.db-journal
- file delete -force test3.db test3.db-journal
- file delete -force test4.db test4.db-journal
+ forcedelete test1.db test1.db-journal
+ forcedelete test2.db test2.db-journal
+ forcedelete test3.db test3.db-journal
+ forcedelete test4.db test4.db-journal
sqlite3 db1 test1.db
sqlite3 db2 test2.db
sqlite3 db3 test3.db
diff --git a/test/shared6.test b/test/shared6.test
index 4d38b22e..499cbb0e 100644
--- a/test/shared6.test
+++ b/test/shared6.test
@@ -235,7 +235,7 @@ do_test shared6-3.X {
} {}
do_test shared6-4.1 {
- #file delete -force test.db test.db-journal
+ #forcedelete test.db test.db-journal
sqlite3 db1 test.db
sqlite3 db2 test.db
diff --git a/test/shared7.test b/test/shared7.test
index d003f0ae..5c4a1da2 100644
--- a/test/shared7.test
+++ b/test/shared7.test
@@ -35,7 +35,7 @@ do_test shared7-1.2 {
} {1 {database is already attached}}
do_test shared7-1.3 {
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
db eval {
ATTACH 'test2.db' AS test2;
CREATE TABLE test2.t2(y);
diff --git a/test/speed3.test b/test/speed3.test
index a99a6245..1beaeb74 100644
--- a/test/speed3.test
+++ b/test/speed3.test
@@ -116,7 +116,7 @@ proc reset_db {} {
}
}
-file delete -force test2.db test2.db-journal
+forcedelete test2.db test2.db-journal
reset_db
# Set up a database in auto-vacuum mode and create a database schema.
diff --git a/test/sqllimits1.test b/test/sqllimits1.test
index bf4a2626..2cbad3ff 100644
--- a/test/sqllimits1.test
+++ b/test/sqllimits1.test
@@ -319,18 +319,22 @@ do_test sqllimits1-5.14.4 {
catch {sqlite3_bind_text $::STMT 1 $::str1 -1} res
set res
} {SQLITE_TOOBIG}
-do_test sqllimits1-5.14.5 {
- catch {sqlite3_bind_text16 $::STMT 1 $::str1 -1} res
- set res
-} {SQLITE_TOOBIG}
+ifcapable utf16 {
+ do_test sqllimits1-5.14.5 {
+ catch {sqlite3_bind_text16 $::STMT 1 $::str1 -1} res
+ set res
+ } {SQLITE_TOOBIG}
+}
do_test sqllimits1-5.14.6 {
catch {sqlite3_bind_text $::STMT 1 $::str1 $np1} res
set res
} {SQLITE_TOOBIG}
-do_test sqllimits1-5.14.7 {
- catch {sqlite3_bind_text16 $::STMT 1 $::str1 $np1} res
- set res
-} {SQLITE_TOOBIG}
+ifcapable utf16 {
+ do_test sqllimits1-5.14.7 {
+ catch {sqlite3_bind_text16 $::STMT 1 $::str1 $np1} res
+ set res
+ } {SQLITE_TOOBIG}
+}
do_test sqllimits1-5.14.8 {
set n [expr {$np1-1}]
catch {sqlite3_bind_text $::STMT 1 $::str1 $n} res
@@ -755,7 +759,7 @@ ifcapable attach {
do_test sqllimits1-12.1 {
set max $::SQLITE_MAX_ATTACHED
for {set i 0} {$i < ($max)} {incr i} {
- file delete -force test${i}.db test${i}.db-journal
+ forcedelete test${i}.db test${i}.db-journal
}
for {set i 0} {$i < ($max)} {incr i} {
execsql "ATTACH 'test${i}.db' AS aux${i}"
diff --git a/test/stat.test b/test/stat.test
index e1aeaa9e..21726eb2 100644
--- a/test/stat.test
+++ b/test/stat.test
@@ -36,7 +36,8 @@ ifcapable wal {
do_execsql_test stat-0.1 {
PRAGMA journal_mode = WAL;
PRAGMA journal_mode = delete;
- SELECT * FROM stat;
+ SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
+ FROM stat;
} {wal delete sqlite_master / 1 leaf 0 0 916 0}
}
@@ -50,17 +51,20 @@ do_test stat-1.0 {
} {}
do_test stat-1.1 {
execsql {
- SELECT * FROM stat WHERE name = 't1';
+ SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
+ FROM stat WHERE name = 't1';
}
} {t1 / 2 leaf 2 10 998 5}
do_test stat-1.2 {
execsql {
- SELECT * FROM stat WHERE name = 'i1';
+ SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
+ FROM stat WHERE name = 'i1';
}
} {i1 / 3 leaf 2 10 1000 5}
do_test stat-1.3 {
execsql {
- SELECT * FROM stat WHERE name = 'sqlite_master';
+ SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
+ FROM stat WHERE name = 'sqlite_master';
}
} {sqlite_master / 1 leaf 2 77 831 40}
do_test stat-1.4 {
@@ -77,7 +81,8 @@ do_execsql_test stat-2.1 {
INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3;
INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3;
INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3;
- SELECT * FROM stat WHERE name != 'sqlite_master';
+ SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
+ FROM stat WHERE name != 'sqlite_master';
} [list \
sqlite_autoindex_t3_1 / 3 internal 3 368 623 125 \
sqlite_autoindex_t3_1 /000/ 8 leaf 8 946 46 123 \
@@ -108,7 +113,8 @@ do_execsql_test stat-3.1 {
CREATE TABLE t4(x);
CREATE INDEX i4 ON t4(x);
INSERT INTO t4(rowid, x) VALUES(2, a_string(7777));
- SELECT * FROM stat WHERE name != 'sqlite_master';
+ SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
+ FROM stat WHERE name != 'sqlite_master';
} [list \
i4 / 3 leaf 1 103 905 7782 \
i4 /000+000000 9 overflow 0 1020 0 0 \
@@ -132,14 +138,15 @@ do_execsql_test stat-3.1 {
do_execsql_test stat-4.1 {
CREATE TABLE t5(x);
CREATE INDEX i5 ON t5(x);
- SELECT * FROM stat WHERE name = 't5' OR name = 'i5';
+ SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
+ FROM stat WHERE name = 't5' OR name = 'i5';
} [list \
i5 / 5 leaf 0 0 1016 0 \
t5 / 4 leaf 0 0 1016 0 \
]
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
register_dbstat_vtab db
breakpoint
@@ -149,7 +156,8 @@ do_execsql_test stat-5.1 {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(zeroblob(1513));
INSERT INTO t1 VALUES(zeroblob(1514));
- SELECT * FROM stat WHERE name = 't1';
+ SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
+ FROM stat WHERE name = 't1';
} [list \
t1 / 2 leaf 2 993 5 1517 \
t1 /000+000000 3 overflow 0 1020 0 0 \
diff --git a/test/subquery2.test b/test/subquery2.test
new file mode 100644
index 00000000..04200046
--- /dev/null
+++ b/test/subquery2.test
@@ -0,0 +1,86 @@
+# 2011 September 16
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#*************************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is testing correlated subqueries
+#
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+ifcapable !subquery {
+ finish_test
+ return
+}
+
+do_test subquery2-1.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,2);
+ INSERT INTO t1 VALUES(3,4);
+ INSERT INTO t1 VALUES(5,6);
+ INSERT INTO t1 VALUES(7,8);
+ CREATE TABLE t2(c,d);
+ INSERT INTO t2 VALUES(1,1);
+ INSERT INTO t2 VALUES(3,9);
+ INSERT INTO t2 VALUES(5,25);
+ INSERT INTO t2 VALUES(7,49);
+ CREATE TABLE t3(e,f);
+ INSERT INTO t3 VALUES(1,1);
+ INSERT INTO t3 VALUES(3,27);
+ INSERT INTO t3 VALUES(5,125);
+ INSERT INTO t3 VALUES(7,343);
+ COMMIT;
+ }
+ execsql {
+ SELECT a FROM t1
+ WHERE b IN (SELECT x+1 FROM (SELECT DISTINCT f/(a*a) AS x FROM t3));
+ }
+} {1 3 5 7}
+do_test subquery2-1.2 {
+ execsql {
+ CREATE INDEX t1b ON t1(b);
+ SELECT a FROM t1
+ WHERE b IN (SELECT x+1 FROM (SELECT DISTINCT f/(a*a) AS x FROM t3));
+ }
+} {1 3 5 7}
+
+do_test subquery2-1.11 {
+ execsql {
+ SELECT a FROM t1
+ WHERE +b=(SELECT x+1 FROM (SELECT DISTINCT f/(a*a) AS x FROM t3));
+ }
+} {1}
+do_test subquery2-1.12 {
+ execsql {
+ SELECT a FROM t1
+ WHERE b=(SELECT x+1 FROM (SELECT DISTINCT f/(a*a) AS x FROM t3));
+ }
+} {1}
+
+do_test subquery2-1.21 {
+ execsql {
+ SELECT a FROM t1
+ WHERE +b=(SELECT x+1 FROM
+ (SELECT DISTINCT f/d AS x FROM t2 JOIN t3 ON d*a=f))
+ }
+} {1 3 5 7}
+do_test subquery2-1.22 {
+ execsql {
+ SELECT a FROM t1
+ WHERE b=(SELECT x+1 FROM
+ (SELECT DISTINCT f/d AS x FROM t2 JOIN t3 ON d*a=f))
+ }
+} {1 3 5 7}
+
+
+finish_test
diff --git a/test/superlock.test b/test/superlock.test
index b12863f7..8155d929 100644
--- a/test/superlock.test
+++ b/test/superlock.test
@@ -48,6 +48,11 @@ do_execsql_test 1.1 {
PRAGMA journal_mode = DELETE;
} {delete}
+ifcapable !wal {
+ finish_test
+ return
+}
+
do_test 1.2 { sqlite3demo_superlock unlock test.db } {unlock}
do_catchsql_test 1.3 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.4 { unlock } {}
diff --git a/test/sync.test b/test/sync.test
index 4b02ad72..14252b5c 100644
--- a/test/sync.test
+++ b/test/sync.test
@@ -42,8 +42,8 @@ proc cond_incr_sync_count {adj} {
do_test sync-1.1 {
set sqlite_sync_count 0
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
PRAGMA fullfsync=OFF;
CREATE TABLE t1(a,b);
diff --git a/test/syscall.test b/test/syscall.test
index 4442612a..201bd636 100644
--- a/test/syscall.test
+++ b/test/syscall.test
@@ -59,7 +59,7 @@ do_test 2.1.2 { test_syscall exists nosuchcall } 0
foreach s {
open close access getcwd stat fstat ftruncate
fcntl read pread write pwrite fchmod fallocate
- pread64 pwrite64
+ pread64 pwrite64 unlink openDirectory
} {
if {[test_syscall exists $s]} {lappend syscall_list $s}
}
diff --git a/test/table.test b/test/table.test
index 5fa91166..4826cb92 100644
--- a/test/table.test
+++ b/test/table.test
@@ -260,6 +260,18 @@ do_test table-5.2 {
catchsql {DROP TABLE IF EXISTS sqlite_master}
} {1 {table sqlite_master may not be dropped}}
+# Dropping sqlite_statN tables is OK.
+#
+do_test table-5.2.1 {
+ db eval {
+ ANALYZE;
+ DROP TABLE IF EXISTS sqlite_stat1;
+ DROP TABLE IF EXISTS sqlite_stat2;
+ DROP TABLE IF EXISTS sqlite_stat3;
+ SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_stat*';
+ }
+} {}
+
# Make sure an EXPLAIN does not really create a new table
#
do_test table-5.3 {
@@ -667,8 +679,8 @@ ifcapable attach {
# Now attach a database and ensure that a table can be created in the
# attached database whilst in a callback from a query on the main database.
do_test table-14.3 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
ATTACH 'test2.db' as aux;
}
diff --git a/test/tclsqlite.test b/test/tclsqlite.test
index 8db04ebf..0ed06024 100644
--- a/test/tclsqlite.test
+++ b/test/tclsqlite.test
@@ -617,5 +617,16 @@ ifcapable tclvar {
} {31323334 blob}
}
+db func xCall xCall
+proc xCall {} { return "value" }
+do_execsql_test tcl-14.1 {
+ CREATE TABLE t6(x);
+ INSERT INTO t6 VALUES(1);
+}
+do_test tcl-14.2 {
+ db one {SELECT x FROM t6 WHERE xCall()!='value'}
+} {}
+
+
finish_test
diff --git a/test/temptable.test b/test/temptable.test
index ad85f7e9..5eeb0f57 100644
--- a/test/temptable.test
+++ b/test/temptable.test
@@ -292,6 +292,7 @@ do_test temptable-5.1 {
execsql {
CREATE TEMP TABLE mask(a,b,c)
} db2
+ if {[permutation]=="prepare"} { db2 cache flush }
execsql {
CREATE INDEX mask ON t2(x);
SELECT * FROM t2;
@@ -403,7 +404,7 @@ do_test temptable-6.8 {
}
} {1 {no such table: t9}}
-file delete -force test2.db test2.db-journal
+forcedelete test2.db test2.db-journal
ifcapable attach {
do_test temptable-7.1 {
catchsql {
@@ -414,14 +415,14 @@ ifcapable attach {
}
# Need to do the following for tcl 8.5 on mac. On that configuration, the
-# -readonly flag is taken so seriously that a subsequent [file delete -force]
+# -readonly flag is taken so seriously that a subsequent [forcedelete]
# (required before the next test file can be executed) will fail.
#
catch {file attributes test.db -readonly 0}
do_test temptable-8.0 {
db close
- catch {file delete -force test.db}
+ catch {forcedelete test.db}
sqlite3 db test.db
} {}
do_test temptable-8.1 {
diff --git a/test/temptrigger.test b/test/temptrigger.test
index ececc4a8..ed1efb91 100644
--- a/test/temptrigger.test
+++ b/test/temptrigger.test
@@ -157,8 +157,8 @@ sqlite3_enable_shared_cache $::enable_shared_cache
# temptrigger-3.4: Check that the temp trigger can be dropped without error.
#
do_test temptrigger-3.1 {
- catch { file delete -force test2.db test2.db-journal }
- catch { file delete -force test.db test.db-journal }
+ catch { forcedelete test2.db test2.db-journal }
+ catch { forcedelete test.db test.db-journal }
sqlite3 db test.db
sqlite3 db2 test2.db
execsql { CREATE TABLE t2(a, b) } db2
diff --git a/test/tester.tcl b/test/tester.tcl
index 8624821a..3c34b45d 100644
--- a/test/tester.tcl
+++ b/test/tester.tcl
@@ -20,7 +20,9 @@
# Commands to manipulate the db and the file-system at a high level:
#
# copy_file FROM TO
-# drop_all_table ?DB?
+# delete_file FILENAME
+# drop_all_tables ?DB?
+# forcecopy FROM TO
# forcedelete FILENAME
#
# Test the capability of the SQLite version built into the interpreter to
@@ -123,6 +125,121 @@ if {[info command sqlite_orig]==""} {
}
}
+proc getFileRetries {} {
+ if {![info exists ::G(file-retries)]} {
+ #
+ # NOTE: Return the default number of retries for [file] operations. A
+ # value of zero or less here means "disabled".
+ #
+ return [expr {$::tcl_platform(platform) eq "windows" ? 10 : 0}]
+ }
+ return $::G(file-retries)
+}
+
+proc getFileRetryDelay {} {
+ if {![info exists ::G(file-retry-delay)]} {
+ #
+ # NOTE: Return the default number of milliseconds to wait when retrying
+ # failed [file] operations. A value of zero or less means "do not
+ # wait".
+ #
+ return 100; # TODO: Good default?
+ }
+ return $::G(file-retry-delay)
+}
+
+# Copy file $from into $to. This is used because some versions of
+# TCL for windows (notably the 8.4.1 binary package shipped with the
+# current mingw release) have a broken "file copy" command.
+#
+proc copy_file {from to} {
+ do_copy_file false $from $to
+}
+
+proc forcecopy {from to} {
+ do_copy_file true $from $to
+}
+
+proc do_copy_file {force from to} {
+ set nRetry [getFileRetries] ;# Maximum number of retries.
+ set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
+
+ # On windows, sometimes even a [file copy -force] can fail. The cause is
+ # usually "tag-alongs" - programs like anti-virus software, automatic backup
+ # tools and various explorer extensions that keep a file open a little longer
+ # than we expect, causing the delete to fail.
+ #
+ # The solution is to wait a short amount of time before retrying the copy.
+ #
+ if {$nRetry > 0} {
+ for {set i 0} {$i<$nRetry} {incr i} {
+ set rc [catch {
+ if {$force} {
+ file copy -force $from $to
+ } else {
+ file copy $from $to
+ }
+ } msg]
+ if {$rc==0} break
+ if {$nDelay > 0} { after $nDelay }
+ }
+ if {$rc} { error $msg }
+ } else {
+ if {$force} {
+ file copy -force $from $to
+ } else {
+ file copy $from $to
+ }
+ }
+}
+
+# Delete a file or directory
+#
+proc delete_file {args} {
+ do_delete_file false {*}$args
+}
+
+proc forcedelete {args} {
+ do_delete_file true {*}$args
+}
+
+proc do_delete_file {force args} {
+ set nRetry [getFileRetries] ;# Maximum number of retries.
+ set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
+
+ foreach filename $args {
+ # On windows, sometimes even a [file delete -force] can fail just after
+ # a file is closed. The cause is usually "tag-alongs" - programs like
+ # anti-virus software, automatic backup tools and various explorer
+ # extensions that keep a file open a little longer than we expect, causing
+ # the delete to fail.
+ #
+ # The solution is to wait a short amount of time before retrying the
+ # delete.
+ #
+ if {$nRetry > 0} {
+ for {set i 0} {$i<$nRetry} {incr i} {
+ set rc [catch {
+ if {$force} {
+ file delete -force $filename
+ } else {
+ file delete $filename
+ }
+ } msg]
+ if {$rc==0} break
+ if {$nDelay > 0} { after $nDelay }
+ }
+ if {$rc} { error $msg }
+ } else {
+ if {$force} {
+ file delete -force $filename
+ } else {
+ file delete $filename
+ }
+ }
+ }
+}
+
proc execpresql {handle args} {
trace remove execution $handle enter [list execpresql $handle]
if {[info exists ::G(perm:presql)]} {
@@ -154,6 +271,8 @@ if {[info exists cmdlinearg]==0} {
# --backtrace=N
# --binarylog=N
# --soak=N
+ # --file-retries=N
+ # --file-retry-delay=N
# --start=[$permutation:]$testfile
#
set cmdlinearg(soft-heap-limit) 0
@@ -162,6 +281,8 @@ if {[info exists cmdlinearg]==0} {
set cmdlinearg(backtrace) 10
set cmdlinearg(binarylog) 0
set cmdlinearg(soak) 0
+ set cmdlinearg(file-retries) 0
+ set cmdlinearg(file-retry-delay) 0
set cmdlinearg(start) ""
set leftover [list]
@@ -197,6 +318,14 @@ if {[info exists cmdlinearg]==0} {
foreach {dummy cmdlinearg(soak)} [split $a =] break
set ::G(issoak) $cmdlinearg(soak)
}
+ {^-+file-retries=.+$} {
+ foreach {dummy cmdlinearg(file-retries)} [split $a =] break
+ set ::G(file-retries) $cmdlinearg(file-retries)
+ }
+ {^-+file-retry-delay=.+$} {
+ foreach {dummy cmdlinearg(file-retry-delay)} [split $a =] break
+ set ::G(file-retry-delay) $cmdlinearg(file-retry-delay)
+ }
{^-+start=.+$} {
foreach {dummy cmdlinearg(start)} [split $a =] break
@@ -246,9 +375,9 @@ sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
#
proc reset_db {} {
catch {db close}
- file delete -force test.db
- file delete -force test.db-journal
- file delete -force test.db-wal
+ forcedelete test.db
+ forcedelete test.db-journal
+ forcedelete test.db-wal
sqlite3 db ./test.db
set ::DB [sqlite3_connection_pointer db]
if {[info exists ::SETUP_SQL]} {
@@ -622,10 +751,10 @@ proc finalize_testing {} {
}
}
foreach f [glob -nocomplain test.db-*-journal] {
- file delete -force $f
+ forcedelete $f
}
foreach f [glob -nocomplain test.db-mj*] {
- file delete -force $f
+ forcedelete $f
}
exit [expr {$nErr>0}]
}
@@ -740,30 +869,6 @@ proc stepsql {dbptr sql} {
return $r
}
-# Delete a file or directory
-#
-proc forcedelete {args} {
- foreach filename $args {
- # On windows, sometimes even a [file delete -force] can fail just after
- # a file is closed. The cause is usually "tag-alongs" - programs like
- # anti-virus software, automatic backup tools and various explorer
- # extensions that keep a file open a little longer than we expect, causing
- # the delete to fail.
- #
- # The solution is to wait a short amount of time before retrying the
- # delete.
- #
- set nRetry 50 ;# Maximum number of retries.
- set nDelay 100 ;# Delay in ms before retrying.
- for {set i 0} {$i<$nRetry} {incr i} {
- set rc [catch {file delete -force $filename} msg]
- if {$rc==0} break
- after $nDelay
- }
- if {$rc} { error $msg }
- }
-}
-
# Do an integrity check of the entire database
#
proc integrity_check {name {db db}} {
@@ -964,10 +1069,10 @@ proc do_ioerr_test {testname args} {
set ::sqlite_io_error_pending 0
catch {db close}
catch {db2 close}
- catch {file delete -force test.db}
- catch {file delete -force test.db-journal}
- catch {file delete -force test2.db}
- catch {file delete -force test2.db-journal}
+ catch {forcedelete test.db}
+ catch {forcedelete test.db-journal}
+ catch {forcedelete test2.db}
+ catch {forcedelete test2.db-journal}
set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
if {[info exists ::ioerropts(-tclprep)]} {
@@ -1241,24 +1346,6 @@ proc memdebug_log_sql {{filename mallocs.sql}} {
close $fd
}
-# Copy file $from into $to. This is used because some versions of
-# TCL for windows (notably the 8.4.1 binary package shipped with the
-# current mingw release) have a broken "file copy" command.
-#
-proc copy_file {from to} {
- if {$::tcl_platform(platform)=="unix"} {
- file copy -force $from $to
- } else {
- set f [open $from]
- fconfigure $f -translation binary
- set t [open $to w]
- fconfigure $t -translation binary
- puts -nonewline $t [read $f [file size $from]]
- close $t
- close $f
- }
-}
-
# Drop all tables in database [db]
proc drop_all_tables {{db db}} {
ifcapable trigger&&foreignkey {
@@ -1440,7 +1527,7 @@ proc db_save {} {
foreach f [glob -nocomplain sv_test.db*] { forcedelete $f }
foreach f [glob -nocomplain test.db*] {
set f2 "sv_$f"
- file copy -force $f $f2
+ forcecopy $f $f2
}
}
proc db_save_and_close {} {
@@ -1452,7 +1539,7 @@ proc db_restore {} {
foreach f [glob -nocomplain test.db*] { forcedelete $f }
foreach f2 [glob -nocomplain sv_test.db*] {
set f [string range $f2 3 end]
- file copy -force $f2 $f
+ forcecopy $f2 $f
}
}
proc db_restore_and_reopen {{dbfile test.db}} {
@@ -1462,7 +1549,7 @@ proc db_restore_and_reopen {{dbfile test.db}} {
}
proc db_delete_and_reopen {{file test.db}} {
catch { db close }
- foreach f [glob -nocomplain test.db*] { file delete -force $f }
+ foreach f [glob -nocomplain test.db*] { forcedelete $f }
sqlite3 db $file
}
diff --git a/test/thread001.test b/test/thread001.test
index 9b788aaf..7e0893f2 100644
--- a/test/thread001.test
+++ b/test/thread001.test
@@ -42,7 +42,7 @@ foreach {tn same_db shared_cache} [list \
sqlite3_enable_shared_cache $shared_cache
sqlite3_enable_shared_cache $shared_cache
} $shared_cache
- sqlite3 db test.db -fullmutex 1
+ sqlite3 db test.db -fullmutex 1 -key xyzzy
set dbconfig ""
if {$same_db} {
@@ -77,7 +77,7 @@ foreach {tn same_db shared_cache} [list \
#sqlthread parent {puts STARTING..}
set needToClose 0
if {![info exists ::DB]} {
- set ::DB [sqlthread open test.db]
+ set ::DB [sqlthread open test.db xyzzy]
#sqlthread parent "puts \"OPEN $::DB\""
set needToClose 1
}
diff --git a/test/thread002.test b/test/thread002.test
index b1e5f636..b39c9ae7 100644
--- a/test/thread002.test
+++ b/test/thread002.test
@@ -16,9 +16,11 @@
set testdir [file dirname $argv0]
+set do_not_use_codec 1
source $testdir/tester.tcl
if {[run_thread_tests]==0} { finish_test ; return }
+
db close
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
@@ -27,7 +29,7 @@ set ::NTHREAD 10
do_test thread002.1 {
# Create 3 databases with identical schemas:
for {set ii 0} {$ii < 3} {incr ii} {
- file delete -force test${ii}.db
+ forcedelete test${ii}.db
sqlite3 db test${ii}.db
execsql {
CREATE TABLE t1(k, v);
diff --git a/test/thread003.test b/test/thread003.test
index 8aa513af..8c7440c8 100644
--- a/test/thread003.test
+++ b/test/thread003.test
@@ -40,7 +40,7 @@ do_test thread003.1.2 {
} {1}
do_test thread003.1.3 {
db close
- file delete -force test2.db
+ forcedelete test2.db
sqlite3 db test2.db
} {}
do_test thread003.1.4 {
@@ -80,7 +80,7 @@ do_test thread003.2 {
foreach zFile {test.db test2.db} {
set SCRIPT [format {
set iEnd [expr {[clock_seconds] + %d}]
- set ::DB [sqlthread open %s]
+ set ::DB [sqlthread open %s xyzzy]
# Set the cache size to 15 pages per cache. 30 available globally.
execsql { PRAGMA cache_size = 15 }
@@ -117,7 +117,7 @@ do_test thread003.3 {
set SCRIPT [format {
set iStart [clock_seconds]
set iEnd [expr {[clock_seconds] + %d}]
- set ::DB [sqlthread open %s]
+ set ::DB [sqlthread open %s xyzzy]
# Set the cache size to 15 pages per cache. 30 available globally.
execsql { PRAGMA cache_size = 15 }
@@ -156,7 +156,7 @@ unset -nocomplain finished(2)
do_test thread003.4 {
thread_spawn finished(1) $thread_procs [format {
set iEnd [expr {[clock_seconds] + %d}]
- set ::DB [sqlthread open test.db]
+ set ::DB [sqlthread open test.db xyzzy]
# Set the cache size to 15 pages per cache. 30 available globally.
execsql { PRAGMA cache_size = 15 }
diff --git a/test/thread005.test b/test/thread005.test
index 9253287d..89cbfe76 100644
--- a/test/thread005.test
+++ b/test/thread005.test
@@ -121,7 +121,7 @@ for {set ii 2} {$ii < 500} {incr ii} {
# switch or something...
#
-file delete -force test.db test2.db
+forcedelete test.db test2.db
unset -nocomplain finished
do_test thread005-2.1 {
diff --git a/test/tkt-2d1a5c67d.test b/test/tkt-2d1a5c67d.test
index 278e1d38..bf9595f0 100644
--- a/test/tkt-2d1a5c67d.test
+++ b/test/tkt-2d1a5c67d.test
@@ -118,8 +118,8 @@ do_test 3.5 {
#
forcedelete test.db2-wal test.db2
do_test 3.6 {
- file copy test.db-wal test.db2-wal
- file copy test.db test.db2
+ copy_file test.db-wal test.db2-wal
+ copy_file test.db test.db2
sqlite3 db2 test.db2
execsql { SELECT * FROM t4 WHERE a = 'xyz' } db2
} {xyz}
diff --git a/test/tkt-31338dca7e.test b/test/tkt-31338dca7e.test
index 3f66816d..9423c684 100644
--- a/test/tkt-31338dca7e.test
+++ b/test/tkt-31338dca7e.test
@@ -74,4 +74,105 @@ do_test tkt-31338-2.2 {
} {111 222 222 333 888 333 444 444 555 888 333 444 444 555 999}
+# Ticket [2c2de252666662f5459904fc33a9f2956cbff23c]
+#
+do_test tkt-31338-3.1 {
+ foreach x [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
+ db eval "DROP TABLE $x"
+ }
+ db eval {
+ CREATE TABLE t1(a,b,c,d);
+ CREATE TABLE t2(e,f);
+ INSERT INTO t1 VALUES(1,2,3,4);
+ INSERT INTO t2 VALUES(10,-8);
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1b ON t1(b);
+ CREATE TABLE t3(g);
+ INSERT INTO t3 VALUES(4);
+ CREATE TABLE t4(h);
+ INSERT INTO t4 VALUES(5);
+
+ SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
+ WHERE (a=1 AND h=4)
+ OR (b IN (
+ SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
+ GROUP BY e
+ ));
+ }
+} {4 1 2 3 4 {}}
+do_test tkt-31338-3.2 {
+ db eval {
+ SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
+ WHERE (a=1 AND h=4)
+ OR (b=2 AND b NOT IN (
+ SELECT x+1 FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
+ GROUP BY e
+ ));
+ }
+} {4 1 2 3 4 {}}
+do_test tkt-31338-3.3 {
+ db eval {
+ SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
+ WHERE (+a=1 AND h=4)
+ OR (b IN (
+ SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
+ GROUP BY e
+ ));
+ }
+} {4 1 2 3 4 {}}
+do_test tkt-31338-3.4 {
+ db eval {
+ SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
+ WHERE (a=1 AND h=4)
+ OR (+b IN (
+ SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
+ GROUP BY e
+ ));
+ }
+} {4 1 2 3 4 {}}
+
+do_test tkt-31338-3.5 {
+ db eval {
+ CREATE TABLE t5(a,b,c,d,e,f);
+ CREATE TABLE t6(g,h);
+ CREATE TRIGGER t6r AFTER INSERT ON t6 BEGIN
+ INSERT INTO t5
+ SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
+ WHERE (a=1 AND h=4)
+ OR (b IN (
+ SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
+ GROUP BY e
+ ));
+ END;
+ INSERT INTO t6 VALUES(88,99);
+ SELECT * FROM t5;
+ }
+} {4 1 2 3 4 {}}
+
+do_test tkt-31338-3.6 {
+ db eval {
+ INSERT INTO t1 VALUES(2,4,3,4);
+ INSERT INTO t1 VALUES(99,101,3,4);
+ INSERT INTO t1 VALUES(98,97,3,4);
+ SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
+ WHERE (a=1 AND h=4)
+ OR (b IN (
+ SELECT x+a FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
+ GROUP BY e
+ ));
+ }
+} {4 2 4 3 4 {} 4 99 101 3 4 {}}
+
+do_test tkt-31338-3.7 {
+ db eval {
+ SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
+ WHERE (a=1 AND h=4)
+ OR (b IN (
+ SELECT x FROM (SELECT e+f+a AS x, e FROM t2 ORDER BY 1 LIMIT 2)
+ GROUP BY e
+ ));
+ }
+} {4 2 4 3 4 {} 4 99 101 3 4 {}}
+
+
finish_test
diff --git a/test/tkt-54844eea3f.test b/test/tkt-54844eea3f.test
new file mode 100644
index 00000000..7b04f693
--- /dev/null
+++ b/test/tkt-54844eea3f.test
@@ -0,0 +1,67 @@
+# 2011 July 8
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing that bug [54844eea3f] has been fixed.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set ::testprefix tkt-54844eea3f
+
+do_test 1.0 {
+ execsql {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY);
+ INSERT INTO t1 VALUES(1);
+ INSERT INTO t1 VALUES(4);
+
+ CREATE TABLE t2(b INTEGER PRIMARY KEY);
+ INSERT INTO t2 VALUES(1);
+ INSERT INTO t2 VALUES(2);
+ INSERT INTO t2 SELECT b+2 FROM t2;
+ INSERT INTO t2 SELECT b+4 FROM t2;
+ INSERT INTO t2 SELECT b+8 FROM t2;
+ INSERT INTO t2 SELECT b+16 FROM t2;
+
+ CREATE TABLE t3(c INTEGER PRIMARY KEY);
+ INSERT INTO t3 VALUES(1);
+ INSERT INTO t3 VALUES(2);
+ INSERT INTO t3 VALUES(3);
+ }
+} {}
+
+do_test 1.1 {
+ execsql {
+ SELECT 'test-2', t3.c, (
+ SELECT count(*)
+ FROM t1 JOIN (SELECT DISTINCT t3.c AS p FROM t2) AS x ON t1.a=x.p
+ )
+ FROM t3;
+ }
+} {test-2 1 1 test-2 2 0 test-2 3 0}
+
+do_test 1.2 {
+ execsql {
+ CREATE TABLE t4(a, b, c);
+ INSERT INTO t4 VALUES('a', 1, 'one');
+ INSERT INTO t4 VALUES('a', 2, 'two');
+ INSERT INTO t4 VALUES('b', 1, 'three');
+ INSERT INTO t4 VALUES('b', 2, 'four');
+ SELECT (
+ SELECT c FROM (
+ SELECT * FROM t4 WHERE a=out.a ORDER BY b LIMIT 10 OFFSET 1
+ ) WHERE b=out.b
+ ) FROM t4 AS out;
+ }
+} {{} two {} four}
+
+
+finish_test
diff --git a/test/tkt-5ee23731f.test b/test/tkt-5ee23731f.test
index 61c99741..761382a4 100644
--- a/test/tkt-5ee23731f.test
+++ b/test/tkt-5ee23731f.test
@@ -19,7 +19,7 @@ source $testdir/tester.tcl
do_test tkt-5ee237-1.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
db eval {
CREATE TABLE t1(x UNIQUE);
diff --git a/test/tkt-b1d3a2e531.test b/test/tkt-b1d3a2e531.test
new file mode 100644
index 00000000..54534b6c
--- /dev/null
+++ b/test/tkt-b1d3a2e531.test
@@ -0,0 +1,109 @@
+# 2011 August 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.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+# This file implements tests for foreign keys. Specifically, it tests
+# that ticket b1d3a2e531 has been fixed.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+ifcapable {!foreignkey||!trigger} {
+ finish_test
+ return
+}
+set testprefix tkt-b1d3a2e531
+
+do_execsql_test 1.0 { PRAGMA foreign_keys = ON }
+
+do_execsql_test 1.1 {
+ CREATE TABLE pp(x PRIMARY KEY);
+ CREATE TABLE cc(y REFERENCES pp DEFERRABLE INITIALLY DEFERRED);
+ INSERT INTO pp VALUES('abc');
+ INSERT INTO cc VALUES('abc');
+}
+do_execsql_test 1.2 {
+ BEGIN;
+ DROP TABLE pp;
+ DROP TABLE cc;
+ COMMIT;
+}
+do_execsql_test 1.3 {
+ CREATE TABLE pp(x PRIMARY KEY);
+ CREATE TABLE cc(y REFERENCES pp DEFERRABLE INITIALLY DEFERRED);
+ INSERT INTO pp VALUES('abc');
+ INSERT INTO cc VALUES('abc');
+}
+do_execsql_test 1.4 {
+ BEGIN;
+ DROP TABLE cc;
+ DROP TABLE pp;
+ COMMIT;
+}
+
+do_execsql_test 2.1 {
+ CREATE TABLE pp(x PRIMARY KEY);
+ CREATE TABLE cc(
+ y INTEGER PRIMARY KEY REFERENCES pp DEFERRABLE INITIALLY DEFERRED
+ );
+ INSERT INTO pp VALUES(5);
+ INSERT INTO cc VALUES(5);
+}
+do_execsql_test 2.2 {
+ BEGIN;
+ DROP TABLE pp;
+ DROP TABLE cc;
+ COMMIT;
+}
+do_execsql_test 2.3 {
+ CREATE TABLE pp(x PRIMARY KEY);
+ CREATE TABLE cc(
+ y INTEGER PRIMARY KEY REFERENCES pp DEFERRABLE INITIALLY DEFERRED
+ );
+ INSERT INTO pp VALUES(5);
+ INSERT INTO cc VALUES(5);
+}
+do_execsql_test 2.4 {
+ BEGIN;
+ DROP TABLE cc;
+ DROP TABLE pp;
+ COMMIT;
+}
+
+do_execsql_test 3.1 {
+ CREATE TABLE pp1(x PRIMARY KEY);
+ CREATE TABLE cc1(y REFERENCES pp1 DEFERRABLE INITIALLY DEFERRED);
+
+ CREATE TABLE pp2(x PRIMARY KEY);
+ CREATE TABLE cc2(y REFERENCES pp1 DEFERRABLE INITIALLY DEFERRED);
+
+ INSERT INTO pp1 VALUES(2200);
+ INSERT INTO cc1 VALUES(NULL);
+
+ INSERT INTO pp2 VALUES(2200);
+ INSERT INTO cc2 VALUES(2200);
+}
+do_catchsql_test 3.2 {
+ BEGIN;
+ DELETE FROM pp2;
+ DROP TABLE pp1;
+ DROP TABLE cc1;
+ COMMIT;
+} {1 {foreign key constraint failed}}
+do_catchsql_test 3.3 {
+ DROP TABLE cc2;
+ COMMIT;
+} {0 {}}
+
+
+
+finish_test
diff --git a/test/tkt-c48d99d690.test b/test/tkt-c48d99d690.test
new file mode 100644
index 00000000..9b405799
--- /dev/null
+++ b/test/tkt-c48d99d690.test
@@ -0,0 +1,26 @@
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set ::testprefix tkt-c48d99d690
+
+do_test 1.0 {
+ execsql {
+ CREATE TABLE t1(a, b);
+ CREATE TABLE t2(a, b);
+ INSERT INTO t1 VALUES('one' , 1);
+ INSERT INTO t1 VALUES('two' , 5);
+ INSERT INTO t1 VALUES('two' , 2);
+ INSERT INTO t1 VALUES('three', 3);
+ PRAGMA count_changes = 1;
+ }
+} {}
+
+do_test 1.1 {
+ execsql { INSERT INTO t2 SELECT * FROM t1 }
+} {4}
+
+do_test 1.2 { execsql VACUUM } {}
+
+finish_test
+
diff --git a/test/tkt-cbd054fa6b.test b/test/tkt-cbd054fa6b.test
index 6e7455b3..180acf56 100644
--- a/test/tkt-cbd054fa6b.test
+++ b/test/tkt-cbd054fa6b.test
@@ -16,7 +16,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-ifcapable !stat2 {
+ifcapable !stat3 {
finish_test
return
}
@@ -46,7 +46,7 @@ do_test tkt-cbd05-1.2 {
do_test tkt-cbd05-1.3 {
execsql {
SELECT tbl,idx,group_concat(sample,' ')
- FROM sqlite_stat2
+ FROM sqlite_stat3
WHERE idx = 't1_x'
GROUP BY tbl,idx
}
@@ -78,7 +78,7 @@ do_test tkt-cbd05-2.2 {
do_test tkt-cbd05-2.3 {
execsql {
SELECT tbl,idx,group_concat(sample,' ')
- FROM sqlite_stat2
+ FROM sqlite_stat3
WHERE idx = 't1_x'
GROUP BY tbl,idx
}
diff --git a/test/tkt-d635236375.test b/test/tkt-d635236375.test
new file mode 100644
index 00000000..3fc78226
--- /dev/null
+++ b/test/tkt-d635236375.test
@@ -0,0 +1,38 @@
+# 2011 August 3
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing that bug [d63523637517386191d634e]
+# has been fixed.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set ::testprefix tkt-d635236375
+
+do_test 1.0 {
+ execsql {
+ CREATE TABLE t1(id1 INTEGER PRIMARY KEY);
+ INSERT INTO t1 VALUES(9999);
+ CREATE TABLE t2(id2 INTEGER PRIMARY KEY);
+ INSERT INTO t2 VALUES(12345);
+ INSERT INTO t2 VALUES(54321);
+ SELECT DISTINCT id1 AS x, id1 AS y FROM t1, t2;
+ }
+} {9999 9999}
+do_test 1.1 {
+ execsql {
+ SELECT count(*) FROM t1, t2 GROUP BY id1, id1;
+ }
+} {2}
+
+
+finish_test
diff --git a/test/tkt-f3e5abed55.test b/test/tkt-f3e5abed55.test
index 241c1612..b3f5d565 100644
--- a/test/tkt-f3e5abed55.test
+++ b/test/tkt-f3e5abed55.test
@@ -14,8 +14,8 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
-foreach f [glob -nocomplain test.db*mj*] { file delete -force $f }
-file delete -force test.db2
+foreach f [glob -nocomplain test.db*mj*] { forcedelete $f }
+forcedelete test.db2
do_test tkt-f3e5abed55-1.1 {
execsql {
@@ -51,7 +51,7 @@ do_test tkt-f3e5abed55-1.5 {
do_test tkt-f3e5abed55-1.6 {
glob -nocomplain test.db*mj*
} {}
-foreach f [glob -nocomplain test.db*mj*] { file delete -force $f }
+foreach f [glob -nocomplain test.db*mj*] { forcedelete $f }
db close
db2 close
diff --git a/test/tkt-fa7bf5ec.test b/test/tkt-fa7bf5ec.test
new file mode 100644
index 00000000..34f12b96
--- /dev/null
+++ b/test/tkt-fa7bf5ec.test
@@ -0,0 +1,39 @@
+# 2011 October 13
+#
+# 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. Specifically,
+# it tests that ticket [fa7bf5ec94801e7e2030e41eefe5d9dd96eaacfd] has
+# been resolved.
+#
+# The problem described by this ticket was that the sqlite3ExprCompare()
+# function was saying that expressions (x='a') and (x='A') were identical
+# because it was using sqlite3StrICmp() instead of strcmp() to compare string
+# literals. That was causing the query optimizer for aggregate queries to
+# believe that both count() operations were identical, and thus only
+# computing the first count() and making a copy of the result for the
+# second count().
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test tkt-fa7bf5ec-1 {
+ execsql {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES ('a');
+ INSERT INTO t1 VALUES ('A');
+ INSERT INTO t1 VALUES ('A');
+ SELECT count(CASE WHEN x='a' THEN 1 END),
+ count(CASE WHEN x='A' THEN 1 END)
+ FROM t1;
+ }
+} {1 2}
+
+finish_test
diff --git a/test/tkt1667.test b/test/tkt1667.test
index 9883a208..63815061 100644
--- a/test/tkt1667.test
+++ b/test/tkt1667.test
@@ -25,7 +25,7 @@ ifcapable !autovacuum||!tclvar {
}
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
# Set the pending byte offset such that the page it is on is
# the first autovacuum pointer map page in the file (assume a page
diff --git a/test/tkt1873.test b/test/tkt1873.test
index 85a52832..9930790c 100644
--- a/test/tkt1873.test
+++ b/test/tkt1873.test
@@ -24,7 +24,7 @@ ifcapable !attach {
return
}
-file delete -force test2.db test2.db-journal
+forcedelete test2.db test2.db-journal
do_test tkt1873-1.1 {
execsql {
diff --git a/test/tkt2686.test b/test/tkt2686.test
index c03c6868..20447bba 100644
--- a/test/tkt2686.test
+++ b/test/tkt2686.test
@@ -49,7 +49,7 @@ for {set i 1} {$i<2000} {incr i} {
}
db close
-file delete -force test.db test.db-journal
+forcedelete test.db test.db-journal
sqlite3 db test.db
db eval {
diff --git a/test/tkt2817.test b/test/tkt2817.test
index 46b7fe36..579cf2f7 100644
--- a/test/tkt2817.test
+++ b/test/tkt2817.test
@@ -48,7 +48,7 @@ integrity_check tkt2817-1.3
# same name. #2817 did not cause a problem with these tests.
#
db close
-file delete -force test.db
+forcedelete test.db
sqlite3 db test.db
do_test tkt2817-2.0 {
execsql {
diff --git a/test/tkt2820.test b/test/tkt2820.test
index 106c1e55..11c4cd3a 100644
--- a/test/tkt2820.test
+++ b/test/tkt2820.test
@@ -25,7 +25,7 @@ source $testdir/tester.tcl
proc test_schema_change {testid init ddl res} {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
execsql $init
do_test tkt2820-$testid.1 {
@@ -70,7 +70,7 @@ test_schema_change 3 {
#
do_test tkt2820-4.1 {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY);
diff --git a/test/tkt2854.test b/test/tkt2854.test
index 862524a7..914ddd1b 100644
--- a/test/tkt2854.test
+++ b/test/tkt2854.test
@@ -128,7 +128,7 @@ do_test tkt2854-1.18 {
# attached db cannot be locked, the internal exclusive flag used by
# shared-cache users is correctly cleared.
do_test tkt2854-1.19 {
- file delete -force test2.db test2.db-journal
+ forcedelete test2.db test2.db-journal
sqlite3 db4 test2.db
execsql { CREATE TABLE def(d, e, f) } db4
execsql { ATTACH 'test2.db' AS aux } db
diff --git a/test/tkt3457.test b/test/tkt3457.test
index 71eb4246..7b9a1b35 100644
--- a/test/tkt3457.test
+++ b/test/tkt3457.test
@@ -46,8 +46,8 @@ do_test tkt3457-1.1 {
INSERT INTO t1 VALUES(4, 5, 6);
}
- file copy -force test.db bak.db
- file copy -force test.db-journal bak.db-journal
+ forcecopy test.db bak.db
+ forcecopy test.db-journal bak.db-journal
# Fix the first journal-header in the journal-file. Because the
# journal file has not yet been synced, the 8-byte magic string at the
@@ -63,23 +63,23 @@ do_test tkt3457-1.1 {
} {}
do_test tkt3457-1.2 {
- file copy -force bak.db-journal test.db-journal
+ forcecopy bak.db-journal test.db-journal
file attributes test.db-journal -permissions ---------
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.3 {
- file copy -force bak.db-journal test.db-journal
+ forcecopy bak.db-journal test.db-journal
file attributes test.db-journal -permissions -w--w--w-
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.4 {
- file copy -force bak.db-journal test.db-journal
+ forcecopy bak.db-journal test.db-journal
file attributes test.db-journal -permissions r--r--r--
catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.5 {
- file copy -force bak.db-journal test.db-journal
+ forcecopy bak.db-journal test.db-journal
file attributes test.db-journal -permissions rw-rw-rw-
catchsql { SELECT * FROM t1 }
} {0 {1 2 3 4 5 6}}
diff --git a/test/tkt35xx.test b/test/tkt35xx.test
index d2a83cde..f9d10c30 100644
--- a/test/tkt35xx.test
+++ b/test/tkt35xx.test
@@ -50,7 +50,7 @@ do_test tkt35xx-1.1 {
# Trigger the problem using statement rollback.
#
db close
-file delete test.db
+delete_file test.db
sqlite3 db test.db
set big [string repeat abcdefghij 22] ;# 220 byte string
do_test tkt35xx-1.2.1 {
diff --git a/test/tkt3793.test b/test/tkt3793.test
index 2b5f2bab..074aab2d 100644
--- a/test/tkt3793.test
+++ b/test/tkt3793.test
@@ -100,16 +100,18 @@ set x 0
# Note: Before the bug was fixed, if [db2] was opened with the "-fullmutex 1"
# option, then this test case would cause an assert() to fail.
#
-set ::busyconnection db1
-db1 eval {SELECT * FROM t2 ORDER BY a LIMIT 20} {
- do_test tkt3793-2.[incr x] { set ::busyconnection } db1
- set ::busyconnection db2
-
- db2 eval { SELECT count(*) FROM t2 }
- do_test tkt3793-2.[incr x] { set ::busyconnection } db2
+ifcapable threadsafe {
set ::busyconnection db1
+ db1 eval {SELECT * FROM t2 ORDER BY a LIMIT 20} {
+ do_test tkt3793-2.[incr x] { set ::busyconnection } db1
+ set ::busyconnection db2
+
+ db2 eval { SELECT count(*) FROM t2 }
+ do_test tkt3793-2.[incr x] { set ::busyconnection } db2
+ set ::busyconnection db1
+ }
}
-
+
do_test tkt3793-3 {
db1 close
db2 close
diff --git a/test/trigger1.test b/test/trigger1.test
index 622aff2d..dc344d4d 100644
--- a/test/trigger1.test
+++ b/test/trigger1.test
@@ -534,8 +534,8 @@ ifcapable conflict {
# example, that you can drop and re-create tables referenced by triggers.
ifcapable tempdb&&attach {
do_test trigger1-10.0 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
ATTACH 'test2.db' AS aux;
}
diff --git a/test/trigger4.test b/test/trigger4.test
index 0e44ce6c..a05a5e73 100644
--- a/test/trigger4.test
+++ b/test/trigger4.test
@@ -130,8 +130,8 @@ do_test trigger4-3.7 {
do_test trigger4-4.1 {
db close
- file delete -force trigtest.db
- file delete -force trigtest.db-journal
+ forcedelete trigtest.db
+ forcedelete trigtest.db-journal
sqlite3 db trigtest.db
catchsql {drop table tbl; drop view vw}
execsql {
@@ -195,6 +195,6 @@ do_test trigger4-7.2 {
integrity_check trigger4-99.9
db close
-file delete -force trigtest.db trigtest.db-journal
+forcedelete trigtest.db trigtest.db-journal
finish_test
diff --git a/test/triggerA.test b/test/triggerA.test
index 9f93db5c..0bc017ff 100644
--- a/test/triggerA.test
+++ b/test/triggerA.test
@@ -205,16 +205,16 @@ source $testdir/malloc_common.tcl
# Save a copy of the current database configuration.
#
db close
-file delete -force test.db-triggerA
-file copy test.db test.db-triggerA
+forcedelete test.db-triggerA
+copy_file test.db test.db-triggerA
sqlite3 db test.db
# Run malloc tests on the INSTEAD OF trigger firing.
#
do_malloc_test triggerA-3 -tclprep {
db close
- file delete -force test.db test.db-journal
- file copy -force test.db-triggerA test.db
+ forcedelete test.db test.db-journal
+ forcecopy test.db-triggerA test.db
sqlite3 db test.db
sqlite3_extended_result_codes db 1
db eval {SELECT * FROM v5; -- warm up the cache}
@@ -225,6 +225,6 @@ do_malloc_test triggerA-3 -tclprep {
# Clean up the saved database copy.
#
-file delete -force test.db-triggerA
+forcedelete test.db-triggerA
finish_test
diff --git a/test/triggerC.test b/test/triggerC.test
index e5a492a4..12a5e4ac 100644
--- a/test/triggerC.test
+++ b/test/triggerC.test
@@ -918,7 +918,7 @@ do_test triggerC-11.4 {
do_test triggerC-12.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql {
diff --git a/test/triggerD.test b/test/triggerD.test
index 08945081..a5dd4bdd 100644
--- a/test/triggerD.test
+++ b/test/triggerD.test
@@ -14,6 +14,12 @@
# the use of these columns in triggers will refer to the column and not
# to the actual ROWID. Ticket [34d2ae1c6d08b5271ba5e5592936d4a1d913ffe3]
#
+# Also, verify that triggers created like this:
+#
+# CREATE TRIGGER attached.trig AFTER INSERT ON attached.tab ...
+#
+# can be reparsed as a main database. Ticket [d6ddba6706353915ceedc56b4e3]
+#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -171,4 +177,43 @@ do_test triggerD-3.2 {
} {10003 20004}
+#############################################################################
+#
+# Ticket [d6ddba6706353915ceedc56b4e3e72ecb4d77ba4]
+#
+# The following syntax really should not be allowed:
+#
+# CREATE TRIGGER xyz.trig BEFORE UPDATE ON xyz.tab BEGIN ...
+#
+# But a long-standing bug does allow it. And the "xyz.tab" slips into
+# the sqlite_master table. We cannot fix the bug simply by disallowing
+# "xyz.tab" since that could break legacy applications. We have to
+# fix the system so that the "xyz." on "xyz.tab" is ignored.
+# Verify that this is the case.
+#
+do_test triggerD-4.1 {
+ db close
+ forcedelete test.db test2.db
+ sqlite3 db test.db
+ db eval {
+ CREATE TABLE t1(x);
+ ATTACH 'test2.db' AS db2;
+ CREATE TABLE db2.t2(y);
+ CREATE TABLE db2.log(z);
+ CREATE TRIGGER db2.trig AFTER INSERT ON db2.t2 BEGIN
+ INSERT INTO log(z) VALUES(new.y);
+ END;
+ INSERT INTO t2 VALUES(123);
+ SELECT * FROM log;
+ }
+} {123}
+do_test triggerD-4.2 {
+ sqlite3 db2 test2.db
+ db2 eval {
+ INSERT INTO t2 VALUES(234);
+ SELECT * FROM log;
+ }
+} {123 234}
+db2 close
+
finish_test
diff --git a/test/unordered.test b/test/unordered.test
index a9c62534..6c7c2bb2 100644
--- a/test/unordered.test
+++ b/test/unordered.test
@@ -31,11 +31,13 @@ do_execsql_test 1.0 {
} {}
foreach idxmode {ordered unordered} {
+ catchsql { DELETE FROM sqlite_stat2 }
+ catchsql { DELETE FROM sqlite_stat3 }
if {$idxmode == "unordered"} {
execsql { UPDATE sqlite_stat1 SET stat = stat || ' unordered' }
- db close
- sqlite3 db test.db
}
+ db close
+ sqlite3 db test.db
foreach {tn sql r(ordered) r(unordered)} {
1 "SELECT * FROM t1 ORDER BY a"
{0 0 0 {SCAN TABLE t1 USING INDEX i1 (~128 rows)}}
diff --git a/test/uri.test b/test/uri.test
index f361e929..90074d0d 100644
--- a/test/uri.test
+++ b/test/uri.test
@@ -219,44 +219,46 @@ do_test 4.3.2 {
# set, where X is the file-name the method is called on. Calls to the above
# methods using "tvfs2" set entries in the global T2 array.
#
-testvfs tvfs1
-tvfs1 filter {xOpen xDelete xAccess xFullPathname}
-tvfs1 script tvfs1_callback
-proc tvfs1_callback {method filename args} {
- set ::T1([file tail $filename]) 1
-}
-testvfs tvfs2
-tvfs2 filter {xOpen xDelete xAccess xFullPathname}
-tvfs2 script tvfs2_callback
-proc tvfs2_callback {method filename args} {
- set ::T2([file tail $filename]) 1
-}
-
-catch {db close}
-eval forcedelete [glob test.db*]
-do_test 5.1.1 {
- sqlite3 db file:test.db1?vfs=tvfs1
- execsql {
- ATTACH 'file:test.db2?vfs=tvfs2' AS aux;
- PRAGMA main.journal_mode = PERSIST;
- PRAGMA aux.journal_mode = PERSIST;
- CREATE TABLE t1(a, b);
- CREATE TABLE aux.t2(a, b);
- PRAGMA main.journal_mode = WAL;
- PRAGMA aux.journal_mode = WAL;
- INSERT INTO t1 VALUES('x', 'y');
- INSERT INTO t2 VALUES('x', 'y');
+ifcapable wal {
+ testvfs tvfs1
+ tvfs1 filter {xOpen xDelete xAccess xFullPathname}
+ tvfs1 script tvfs1_callback
+ proc tvfs1_callback {method filename args} {
+ set ::T1([file tail $filename]) 1
}
- lsort [array names ::T1]
-} {test.db1 test.db1-journal test.db1-wal}
-
-do_test 5.1.2 {
- lsort [array names ::T2]
-} {test.db2 test.db2-journal test.db2-wal}
-
-db close
-tvfs1 delete
-tvfs2 delete
+ testvfs tvfs2
+ tvfs2 filter {xOpen xDelete xAccess xFullPathname}
+ tvfs2 script tvfs2_callback
+ proc tvfs2_callback {method filename args} {
+ set ::T2([file tail $filename]) 1
+ }
+
+ catch {db close}
+ eval forcedelete [glob test.db*]
+ do_test 5.1.1 {
+ sqlite3 db file:test.db1?vfs=tvfs1
+ execsql {
+ ATTACH 'file:test.db2?vfs=tvfs2' AS aux;
+ PRAGMA main.journal_mode = PERSIST;
+ PRAGMA aux.journal_mode = PERSIST;
+ CREATE TABLE t1(a, b);
+ CREATE TABLE aux.t2(a, b);
+ PRAGMA main.journal_mode = WAL;
+ PRAGMA aux.journal_mode = WAL;
+ INSERT INTO t1 VALUES('x', 'y');
+ INSERT INTO t2 VALUES('x', 'y');
+ }
+ lsort [array names ::T1]
+ } {test.db1 test.db1-journal test.db1-wal}
+
+ do_test 5.1.2 {
+ lsort [array names ::T2]
+ } {test.db2 test.db2-journal test.db2-wal}
+ db close
+
+ tvfs1 delete
+ tvfs2 delete
+}
#-------------------------------------------------------------------------
# Check that only "" and "localhost" are acceptable as authorities.
diff --git a/test/vacuum.test b/test/vacuum.test
index 34be57ce..57429c29 100644
--- a/test/vacuum.test
+++ b/test/vacuum.test
@@ -208,7 +208,7 @@ db3 close
do_test vacuum-3.1 {
db close
db2 close
- file delete test.db
+ delete_file test.db
sqlite3 db test.db
execsql {
PRAGMA empty_result_callbacks=on;
@@ -234,7 +234,7 @@ do_test vacuum-4.2 {
ifcapable view {
do_test vacuum-5.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
catchsql {
CREATE TABLE Test (TestID int primary key);
@@ -290,10 +290,10 @@ ifcapable {bloblit} {
}
# Check what happens when an in-memory database is vacuumed. The
-# [file delete] command covers us in case the library was compiled
+# [delete_file] command covers us in case the library was compiled
# without in-memory database support.
#
-file delete -force :memory:
+forcedelete :memory:
do_test vacuum-7.0 {
sqlite3 db2 :memory:
execsql {
@@ -337,8 +337,8 @@ db2 close
# Ticket #873. VACUUM a database that has ' in its name.
#
do_test vacuum-8.1 {
- file delete -force a'z.db
- file delete -force a'z.db-journal
+ forcedelete a'z.db
+ forcedelete a'z.db-journal
sqlite3 db2 a'z.db
execsql {
CREATE TABLE t1(t);
@@ -383,6 +383,22 @@ ifcapable {autoinc} {
} $::cksum
}
-file delete -force {a'z.db}
+forcedelete {a'z.db}
+
+# Test that "PRAGMA count_changes" does not interfere with VACUUM or cause
+# it to return any rows to the user.
+#
+do_test vacuum-10.1 {
+ db close
+ forcedelete test.db
+ sqlite3 db test.db
+ execsql {
+ CREATE TABLE t8(a, b);
+ INSERT INTO t8 VALUES('a', 'b');
+ INSERT INTO t8 VALUES('c', 'd');
+ PRAGMA count_changes = 1;
+ }
+} {}
+do_test vacuum-10.2 { execsql VACUUM } {}
finish_test
diff --git a/test/vacuum2.test b/test/vacuum2.test
index 35524bb2..b3bfab30 100644
--- a/test/vacuum2.test
+++ b/test/vacuum2.test
@@ -135,7 +135,7 @@ db2 close
ifcapable autovacuum {
do_test vacuum2-4.1 {
db close
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql {
pragma auto_vacuum=1;
diff --git a/test/vacuum3.test b/test/vacuum3.test
index f6b75d70..484a7d44 100644
--- a/test/vacuum3.test
+++ b/test/vacuum3.test
@@ -196,7 +196,7 @@ foreach {request actual} [list \
do_test vacuum3-4.1 {
db close
- file delete test.db
+ delete_file test.db
sqlite3 db test.db
execsql {
PRAGMA page_size=1024;
diff --git a/test/view.test b/test/view.test
index a87d2770..b4440905 100644
--- a/test/view.test
+++ b/test/view.test
@@ -458,7 +458,7 @@ do_test view-12.1 {
ifcapable attach {
do_test view-13.1 {
- file delete -force test2.db
+ forcedelete test2.db
catchsql {
ATTACH 'test2.db' AS two;
CREATE TABLE two.t2(x,y);
diff --git a/test/vtab1.test b/test/vtab1.test
index a9aca503..16f1b438 100644
--- a/test/vtab1.test
+++ b/test/vtab1.test
@@ -724,8 +724,8 @@ do_test vtab1-6-8.4 {
} {}
execsql {PRAGMA count_changes=OFF}
-file delete -force test2.db
-file delete -force test2.db-journal
+forcedelete test2.db
+forcedelete test2.db-journal
sqlite3 db2 test2.db
execsql {
CREATE TABLE techo(a PRIMARY KEY, b, c);
@@ -1178,5 +1178,20 @@ do_test vtab1-17.1 {
catchsql { CREATE VIRTUAL TABLE t4 USING echo(t3); }
} {1 {vtable constructor failed: t4}}
+# This test verifies that ticket 48f29963 is fixed.
+#
+do_test vtab1-17.1 {
+ execsql {
+ CREATE TABLE t5(a, b);
+ CREATE VIRTUAL TABLE e5 USING echo_v2(t5);
+ BEGIN;
+ INSERT INTO e5 VALUES(1, 2);
+ DROP TABLE e5;
+ SAVEPOINT one;
+ ROLLBACK TO one;
+ COMMIT;
+ }
+} {}
+
unset -nocomplain echo_module_begin_fail
finish_test
diff --git a/test/vtab7.test b/test/vtab7.test
index d1b1f590..162bab5e 100644
--- a/test/vtab7.test
+++ b/test/vtab7.test
@@ -134,8 +134,8 @@ execsql {DROP TABLE newtab}
# Write to an attached database from xSync().
ifcapable attach {
do_test vtab7-3.1 {
- file delete -force test2.db
- file delete -force test2.db-journal
+ forcedelete test2.db
+ forcedelete test2.db-journal
execsql {
ATTACH 'test2.db' AS db2;
CREATE TABLE db2.stuff(description, shape, color);
diff --git a/test/vtabC.test b/test/vtabC.test
index 824d4ca2..ca78b706 100644
--- a/test/vtabC.test
+++ b/test/vtabC.test
@@ -31,7 +31,7 @@ ifcapable !trigger { finish_test ; return }
unset -nocomplain N
for {set N 1} {$N<=20} {incr N} {
db close
- file delete -force test.db test.db-journal
+ forcedelete test.db test.db-journal
sqlite3 db test.db
register_echo_module [sqlite3_connection_pointer db]
diff --git a/test/vtabF.test b/test/vtabF.test
new file mode 100644
index 00000000..b9341ea5
--- /dev/null
+++ b/test/vtabF.test
@@ -0,0 +1,45 @@
+# 2011 Aug 1
+#
+# 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 checks to make sure IS NOT NULL constraints work on
+# virtual tables.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+ifcapable !vtab||!schema_pragmas { finish_test ; return }
+
+# Register the echo module
+register_echo_module [sqlite3_connection_pointer db]
+
+do_test vtabE-1.1 {
+ execsql {
+ CREATE TABLE t1(a, b);
+ CREATE INDEX i1 ON t1(a);
+ CREATE INDEX i2 ON t1(b);
+ INSERT INTO t1 VALUES(10,110);
+ INSERT INTO t1 VALUES(11,111);
+ INSERT INTO t1 SELECT a+2, b+2 FROM t1;
+ INSERT INTO t1 SELECT null, b+4 FROM t1;
+ INSERT INTO t1 SELECT null, b+8 FROM t1;
+ INSERT INTO t1 SELECT null, b+16 FROM t1;
+ ANALYZE;
+ CREATE VIRTUAL TABLE tv1 USING echo(t1);
+ SELECT b FROM t1 WHERE a IS NOT NULL;
+ }
+} {110 111 112 113}
+do_test vtabE-1.2 {
+ execsql {SELECT b FROM tv1 WHERE a IS NOT NULL}
+} {110 111 112 113}
+
+
+finish_test
diff --git a/test/wal.test b/test/wal.test
index 1aa70e05..056becf7 100644
--- a/test/wal.test
+++ b/test/wal.test
@@ -25,7 +25,7 @@ ifcapable !wal {finish_test ; return }
proc reopen_db {} {
catch { db close }
- file delete -force test.db test.db-wal test.db-wal-summary
+ forcedelete test.db test.db-wal test.db-wal-summary
sqlite3_wal db test.db
}
@@ -211,8 +211,8 @@ do_test wal-4.4.5 {
execsql { SELECT count(*) FROM t2 }
} {1}
do_test wal-4.4.6 {
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
sqlite3 db2 test2.db
execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
} {1 2}
@@ -269,8 +269,8 @@ do_test wal-4.5.5 {
execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 }
} {1 2}
do_test wal-4.5.6 {
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
sqlite3 db2 test2.db
execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
} {1 2}
@@ -334,7 +334,7 @@ db close
foreach sector {512 4096} {
sqlite3_simulate_device -sectorsize $sector
foreach pgsz {512 1024 2048 4096} {
- file delete -force test.db test.db-wal
+ forcedelete test.db test.db-wal
do_test wal-6.$sector.$pgsz.1 {
sqlite3 db test.db -vfs devsym
execsql "
@@ -357,7 +357,7 @@ foreach sector {512 4096} {
}
do_test wal-7.1 {
- file delete -force test.db test.db-wal
+ forcedelete test.db test.db-wal
sqlite3_wal db test.db
execsql {
PRAGMA page_size = 1024;
@@ -377,7 +377,7 @@ do_test wal-7.2 {
do_test wal-8.1 {
reopen_db
catch { db close }
- file delete -force test.db test.db-wal
+ forcedelete test.db test.db-wal
sqlite3 db test.db
db function blob blob
@@ -435,9 +435,9 @@ do_test wal-9.2 {
} {ok}
do_test wal-9.3 {
- file delete -force test2.db test2.db-wal
- file copy test.db test2.db
- file copy test.db-wal test2.db-wal
+ forcedelete test2.db test2.db-wal
+ copy_file test.db test2.db
+ copy_file test.db-wal test2.db-wal
sqlite3_wal db3 test2.db
execsql {PRAGMA integrity_check } db3
} {ok}
@@ -786,8 +786,8 @@ do_test wal-12.3 {
list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
} {3 2}
do_test wal-12.4 {
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
sqlite3_wal db2 test2.db
execsql { SELECT * FROM t2 } db2
} {B 1}
@@ -804,8 +804,8 @@ do_test wal-12.5 {
execsql { SELECT * FROM t2 }
} {B 2}
do_test wal-12.6 {
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
sqlite3_wal db2 test2.db
execsql { SELECT * FROM t2 } db2
} {B 2}
@@ -909,7 +909,7 @@ do_multiclient_test tn {
catch { db close }
catch { db2 close }
catch { db3 close }
-file delete -force test.db test.db-wal
+forcedelete test.db test.db-wal
sqlite3 db test.db
sqlite3 db2 test.db
do_test wal-14 {
@@ -947,7 +947,7 @@ catch { db2 close }
# The following block of tests - wal-15.* - focus on testing the
# implementation of the sqlite3_wal_checkpoint() interface.
#
-file delete -force test.db test.db-wal
+forcedelete test.db test.db-wal
sqlite3 db test.db
do_test wal-15.1 {
execsql {
@@ -1043,8 +1043,8 @@ foreach {tn ckpt_cmd ckpt_res ckpt_main ckpt_aux} {
9 {db eval "PRAGMA temp.wal_checkpoint"} {0 -1 -1} 0 0
} {
do_test wal-16.$tn.1 {
- file delete -force test2.db test2.db-wal test2.db-journal
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test2.db test2.db-wal test2.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
execsql {
@@ -1116,7 +1116,7 @@ foreach {tn sectorsize logsize} "
6 4096 [wal_file_size 176 512]
7 8192 [wal_file_size 184 512]
" {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3_simulate_device -sectorsize $sectorsize
sqlite3 db test.db -vfs devsym
@@ -1160,7 +1160,7 @@ sqlite3_test_control_pending_byte $old_pending_byte
# wal-18.2.* When the page-size field that occurs at the start of a log
# file is a power of 2 greater than 16384 or smaller than 512.
#
-file delete -force test.db test.db-wal test.db-journal
+forcedelete test.db test.db-wal test.db-journal
do_test wal-18.0 {
sqlite3 db test.db
execsql {
@@ -1178,8 +1178,8 @@ do_test wal-18.0 {
INSERT INTO t1 VALUES(5, 6); -- frames 5 and 6
}
- file copy -force test.db testX.db
- file copy -force test.db-wal testX.db-wal
+ forcecopy test.db testX.db
+ forcecopy test.db-wal testX.db-wal
db close
list [file size testX.db] [file size testX.db-wal]
} [list [expr 3*1024] [wal_file_size 6 1024]]
@@ -1195,8 +1195,8 @@ foreach {nFrame result} {
6 {0 0 1 2 3 4 5 6}
} {
do_test wal-18.1.$nFrame {
- file copy -force testX.db test.db
- file copy -force testX.db-wal test.db-wal
+ forcecopy testX.db test.db
+ forcecopy testX.db-wal test.db-wal
hexio_write test.db-wal [expr 24 + $nFrame*(24+1024) + 20] 00000000
@@ -1232,7 +1232,7 @@ proc logcksum {ckv1 ckv2 blob} {
}
}
-file copy -force test.db testX.db
+forcecopy test.db testX.db
foreach {tn pgsz works} {
1 128 0
2 256 0
@@ -1253,8 +1253,8 @@ foreach {tn pgsz works} {
}
for {set pg 1} {$pg <= 3} {incr pg} {
- file copy -force testX.db test.db
- file delete -force test.db-wal
+ forcecopy testX.db test.db
+ forcedelete test.db-wal
# Check that the database now exists and consists of three pages. And
# that there is no associated wal file.
@@ -1321,7 +1321,7 @@ foreach {tn pgsz works} {
# snapshot.
#
do_test wal-19.1 {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
sqlite3 db2 test.db
execsql {
@@ -1370,7 +1370,7 @@ do_test wal-19.4 {
#
do_test wal-20.1 {
catch {db close}
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
execsql {
PRAGMA journal_mode = WAL;
@@ -1476,7 +1476,7 @@ foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} {
#
set walfile [file nativename [file join [pwd] test.db-wal]]
catch {db close}
-file delete -force test.db
+forcedelete test.db
do_test wal-23.1 {
faultsim_delete_and_reopen
execsql {
diff --git a/test/wal2.test b/test/wal2.test
index 97966cd9..f4887065 100644
--- a/test/wal2.test
+++ b/test/wal2.test
@@ -164,7 +164,7 @@ foreach {tn iInsert res wal_index_hdr_mod wal_locks} "
db close
db2 close
tvfs delete
-file delete -force test.db test.db-wal test.db-journal
+forcedelete test.db test.db-wal test.db-journal
#-------------------------------------------------------------------------
# This test case is very similar to the previous one, except, after
@@ -271,7 +271,7 @@ foreach {tn iInsert res0 res1 wal_index_hdr_mod} {
db close
db2 close
tvfs delete
-file delete -force test.db test.db-wal test.db-journal
+forcedelete test.db test.db-wal test.db-journal
if 0 {
@@ -344,7 +344,7 @@ do_test wal2-3.5 {
} {0 0}
db close
tvfs delete
-file delete -force test.db test.db-wal test.db-journal
+forcedelete test.db test.db-wal test.db-journal
}
@@ -441,7 +441,7 @@ tvfs delete
# connection silently remains in exclusive mode.
#
do_test wal2-6.1.1 {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
execsql {
Pragma Journal_Mode = Wal;
@@ -484,7 +484,7 @@ do_test wal2-6.1.6 {
db close
do_test wal2-6.2.1 {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
execsql {
Pragma Locking_Mode = Exclusive;
@@ -552,7 +552,7 @@ do_test wal2-6.2.9 {
db close
do_test wal2-6.3.1 {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
execsql {
PRAGMA journal_mode = WAL;
@@ -597,7 +597,7 @@ db close
# as expected when a WAL database is used with locking_mode=exclusive.
#
do_test wal2-6.4.1 {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
proc tvfs_cb {method args} {
set ::shm_file [lindex $args 0]
if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] }
@@ -606,6 +606,7 @@ do_test wal2-6.4.1 {
testvfs tvfs
tvfs script tvfs_cb
sqlite3 db test.db -vfs tvfs
+ set {} {}
} {}
set RECOVERY {
@@ -792,7 +793,7 @@ T delete
# Test a theory about the checksum algorithm. Theory was false and this
# test did not provoke a bug.
#
-file delete -force test.db test.db-wal test.db-journal
+forcedelete test.db test.db-wal test.db-journal
do_test wal2-7.1.1 {
sqlite3 db test.db
execsql {
@@ -803,8 +804,8 @@ do_test wal2-7.1.1 {
file size test.db
} {4096}
do_test wal2-7.1.2 {
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
hexio_write test2.db-wal 48 FF
} {1}
do_test wal2-7.1.3 {
@@ -814,7 +815,7 @@ do_test wal2-7.1.3 {
} {}
db close
db2 close
-file delete -force test.db test.db-wal test.db-journal
+forcedelete test.db test.db-wal test.db-journal
do_test wal2-8.1.2 {
sqlite3 db test.db
execsql {
@@ -870,7 +871,7 @@ testvfs tvfs
tvfs script get_name
tvfs filter xShmOpen
-file delete -force test.db test.db-wal test.db-journal
+forcedelete test.db test.db-wal test.db-journal
do_test wal2-9.1 {
sqlite3 db test.db -vfs tvfs
execsql {
diff --git a/test/wal3.test b/test/wal3.test
index bd296154..ea5e7057 100644
--- a/test/wal3.test
+++ b/test/wal3.test
@@ -94,9 +94,9 @@ for {set i 1} {$i < 50} {incr i} {
# Check that the file-system in its current state can be recovered.
#
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
- file delete -force test2.db-journal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
+ forcedelete test2.db-journal
sqlite3 db2 test2.db
do_test wal3-1.$i.5 {
execsql { SELECT count(*) FROM t1 } db2
@@ -208,7 +208,7 @@ foreach {tn syncmode synccount} {
lappend ::syncs [file tail $filename] $flags
}
do_test wal3-3.$tn {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
testvfs T
T filter {}
@@ -411,7 +411,7 @@ T delete
catch {db close}
testvfs T -default 1
do_test wal3-6.1.1 {
- file delete -force test.db test.db-journal test.db wal
+ forcedelete test.db test.db-journal test.db wal
sqlite3 db test.db
execsql { PRAGMA auto_vacuum = off }
execsql { PRAGMA journal_mode = WAL }
@@ -492,7 +492,7 @@ db2 close
db close
do_test wal3-6.2.1 {
- file delete -force test.db test.db-journal test.db wal
+ forcedelete test.db test.db-journal test.db wal
sqlite3 db test.db
sqlite3 db2 test.db
execsql { PRAGMA auto_vacuum = off }
@@ -558,7 +558,7 @@ T delete
catch {db close}
testvfs T -default 1
do_test wal3-7.1.1 {
- file delete -force test.db test.db-journal test.db wal
+ forcedelete test.db test.db-journal test.db wal
sqlite3 db test.db
execsql {
PRAGMA journal_mode = WAL;
@@ -615,7 +615,7 @@ T delete
#-------------------------------------------------------------------------
#
do_test wal3-8.1 {
- file delete -force test.db test.db-journal test.db wal
+ forcedelete test.db test.db-journal test.db wal
sqlite3 db test.db
sqlite3 db2 test.db
execsql {
@@ -707,9 +707,9 @@ T delete
# and continues.
#
set nConn 50
-if { [string match *BSD $tcl_platform(os)] } { set nConn 35 }
+if { [string match *BSD $tcl_platform(os)] } { set nConn 25 }
do_test wal3-9.0 {
- file delete -force test.db test.db-journal test.db wal
+ forcedelete test.db test.db-journal test.db wal
sqlite3 db test.db
execsql {
PRAGMA page_size = 1024;
@@ -784,4 +784,3 @@ do_multiclient_test tn {
}
finish_test
-
diff --git a/test/wal4.test b/test/wal4.test
index 22ccfea7..c7a43813 100644
--- a/test/wal4.test
+++ b/test/wal4.test
@@ -31,7 +31,7 @@ do_test wal4-1.2 {
# Save a copy of the file-system containing the wal and wal-index files
# only (no database file).
faultsim_save_and_close
- file delete -force sv_test.db
+ forcedelete sv_test.db
} {}
do_test wal4-1.3 {
diff --git a/test/wal5.test b/test/wal5.test
index 0c700dfc..ad6bcfc7 100644
--- a/test/wal5.test
+++ b/test/wal5.test
@@ -235,14 +235,7 @@ foreach {testprefix do_wal_checkpoint} {
do_test 2.3.$tn.5 { sql1 { INSERT INTO t2 VALUES(3, 4) } } {}
do_test 2.3.$tn.6 { file_page_counts } {1 7 1 7}
do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } {1 7 5}
- if {$tcl_platform(platform) == "windows"} {
- # on unix, the size_hint is a no-op if no chunk size is set.
- # the windows implementation does not have a similar check,
- # and because of this, the db file size has an extra page.
- do_test 2.3.$tn.8 { file_page_counts } {2 7 2 7}
- } {
- do_test 2.3.$tn.8 { file_page_counts } {1 7 2 7}
- }
+ do_test 2.3.$tn.8 { file_page_counts } {1 7 2 7}
}
# Check that checkpoints block on the correct locks. And respond correctly
diff --git a/test/wal6.test b/test/wal6.test
index 6fae48e9..ec31bb8b 100644
--- a/test/wal6.test
+++ b/test/wal6.test
@@ -43,19 +43,11 @@ foreach jmode $all_journal_modes {
} {1 2}
# Under Windows, you'll get an error trying to delete
-# a file this is already opened. For now, make sure
-# we get that error, then close the first connection
+# a file this is already opened. Close the first connection
# so the other tests work.
if {$tcl_platform(platform)=="windows"} {
if {$jmode=="persist" || $jmode=="truncate"} {
- do_test wal6-1.2.$jmode.win {
- sqlite3 db2 test.db
- catchsql {
- PRAGMA journal_mode=WAL;
- } db2
- } {1 {disk I/O error}}
- db2 close
- db close
+ db close
}
}
@@ -87,4 +79,3 @@ if {$tcl_platform(platform)=="windows"} {
}
finish_test
-
diff --git a/test/walbak.test b/test/walbak.test
index fe5b99e1..303a628a 100644
--- a/test/walbak.test
+++ b/test/walbak.test
@@ -48,7 +48,7 @@ do_test walbak-1.0 {
}
} {wal}
do_test walbak-1.1 {
- file delete -force bak.db bak.db-journal bak.db-wal
+ forcedelete bak.db bak.db-journal bak.db-wal
db backup bak.db
file size bak.db
} [expr 3*1024]
@@ -79,6 +79,9 @@ do_test walbak-1.6 {
execsql { PRAGMA wal_checkpoint }
list [file size test.db] [file size test.db-wal]
} [list [expr 3*1024] [wal_file_size 6 1024]]
+do_test walbak-1.6.1 {
+ hexio_read test.db 18 2
+} {0202}
do_test walbak-1.7 {
execsql {
CREATE TABLE t2(a, b);
@@ -106,7 +109,7 @@ proc sig {{db db}} {
}
}
db close
-file delete test.db
+delete_file test.db
sqlite3 db test.db
do_test walbak-2.1 {
execsql { PRAGMA journal_mode = WAL }
@@ -236,7 +239,7 @@ foreach {tn setup} {
}
} {
- foreach f [glob -nocomplain test.db*] { file delete -force $f }
+ foreach f [glob -nocomplain test.db*] { forcedelete $f }
eval $setup
@@ -271,9 +274,84 @@ foreach {tn setup} {
execsql { SELECT * FROM t1 }
} {1 2 3 4 5 6 7 8}
+ # Check that [db] is still in WAL mode.
+ do_test walbak-3.$tn.5 {
+ execsql { PRAGMA journal_mode }
+ } {wal}
+ do_test walbak-3.$tn.6 {
+ execsql { PRAGMA wal_checkpoint }
+ hexio_read test.db 18 2
+ } {0202}
+
+ # If it was not an in-memory database, check that [db2] is still in
+ # rollback mode.
+ if {[file exists test.db2]} {
+ do_test walbak-3.$tn.7 {
+ execsql { PRAGMA journal_mode } db2
+ } {wal}
+ do_test walbak-3.$tn.8 {
+ execsql { PRAGMA wal_checkpoint }
+ hexio_read test.db 18 2
+ } {0202}
+ }
+
db close
db2 close
}
+#-------------------------------------------------------------------------
+# Test that the following holds when a backup operation is run:
+#
+# Source | Destination inital | Destination final
+# ---------------------------------------------------
+# Rollback Rollback Rollback
+# Rollback WAL WAL
+# WAL Rollback WAL
+# WAL WAL WAL
+#
+foreach {tn src dest dest_final} {
+ 1 delete delete delete
+ 2 delete wal wal
+ 3 wal delete wal
+ 4 wal wal wal
+} {
+ catch { db close }
+ catch { db2 close }
+ forcedelete test.db test.db2
+
+ do_test walbak-4.$tn.1 {
+ sqlite3 db test.db
+ db eval "PRAGMA journal_mode = $src"
+ db eval {
+ CREATE TABLE t1(a, b);
+ INSERT INTO t1 VALUES('I', 'II');
+ INSERT INTO t1 VALUES('III', 'IV');
+ }
+
+ sqlite3 db2 test.db2
+ db2 eval "PRAGMA journal_mode = $dest"
+ db2 eval {
+ CREATE TABLE t2(x, y);
+ INSERT INTO t2 VALUES('1', '2');
+ INSERT INTO t2 VALUES('3', '4');
+ }
+ } {}
+
+ do_test walbak-4.$tn.2 { execsql { PRAGMA journal_mode } db } $src
+ do_test walbak-4.$tn.3 { execsql { PRAGMA journal_mode } db2 } $dest
+
+ do_test walbak-4.$tn.4 { db backup test.db2 } {}
+ do_test walbak-4.$tn.5 {
+ execsql { SELECT * FROM t1 } db2
+ } {I II III IV}
+ do_test walbak-4.$tn.5 { execsql { PRAGMA journal_mode } db2 } $dest_final
+
+
+ db2 close
+ do_test walbak-4.$tn.6 { file exists test.db2-wal } 0
+ sqlite3 db2 test.db2
+ do_test walbak-4.$tn.7 { execsql { PRAGMA journal_mode } db2 } $dest_final
+}
+
finish_test
diff --git a/test/walbig.test b/test/walbig.test
index 9ceb8ede..092db238 100644
--- a/test/walbig.test
+++ b/test/walbig.test
@@ -17,6 +17,11 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+ifcapable !wal {
+ finish_test
+ return
+}
+
# Do not use a codec for this file, as the database is manipulated using
# external methods (the [fake_big_file] and [hexio_write] commands).
#
diff --git a/test/walcksum.test b/test/walcksum.test
index b2c4a905..08278dd0 100644
--- a/test/walcksum.test
+++ b/test/walcksum.test
@@ -153,7 +153,7 @@ foreach endian {big little} {
#
do_test walcksum-1.$endian.1 {
catch { db close }
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
execsql {
PRAGMA page_size = 1024;
@@ -172,8 +172,8 @@ foreach endian {big little} {
INSERT INTO t1 VALUES(21, 'twentyone');
}
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
db close
list [file size test2.db] [file size test2.db-wal]
@@ -199,8 +199,8 @@ foreach endian {big little} {
} {1}
}
do_test walcksum-1.$endian.4.1 {
- file copy -force test2.db test.db
- file copy -force test2.db-wal test.db-wal
+ forcecopy test2.db test.db
+ forcecopy test2.db-wal test.db-wal
sqlite3 db test.db
execsql { SELECT a FROM t1 }
} {1 2 3 5 8 13 21}
@@ -248,8 +248,8 @@ foreach endian {big little} {
# Now that both the recoverer and non-recoverer have added frames to the
# log file, check that it can still be recovered.
#
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
do_test walcksum-1.$endian.7.11 {
sqlite3 db3 test2.db
execsql {
@@ -294,7 +294,7 @@ foreach endian {big little} {
# formatted (and can be recovered by a second process if required).
#
do_test walcksum-2.1 {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
execsql {
PRAGMA synchronous = NORMAL;
@@ -322,8 +322,8 @@ do_test walcksum-2.1 {
COMMIT;
}
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
sqlite3 db2 test2.db
execsql {
@@ -340,7 +340,7 @@ catch { db2 close }
# invalid as a result.
#
do_test walcksum-3.1 {
- file delete -force test.db test.db-wal test.db-journal
+ forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
execsql {
@@ -356,13 +356,13 @@ do_test walcksum-3.1 {
file size test.db-wal
} [wal_file_size 1 1024]
do_test walcksum-3.2 {
- file copy -force test.db-wal test2.db-wal
- file copy -force test.db test2.db
+ forcecopy test.db-wal test2.db-wal
+ forcecopy test.db test2.db
sqlite3 db2 test2.db
execsql { SELECT a FROM t1 } db2
} {1 2 3}
db2 close
-file copy -force test.db test2.db
+forcecopy test.db test2.db
foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} {
@@ -370,7 +370,7 @@ foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} {
set FAIL 0
for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} {
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db-wal test2.db-wal
set fd [open test2.db-wal r+]
fconfigure $fd -encoding binary
fconfigure $fd -translation binary
diff --git a/test/walcrash.test b/test/walcrash.test
index 0ef21fff..cfce5fed 100644
--- a/test/walcrash.test
+++ b/test/walcrash.test
@@ -37,7 +37,7 @@ set REPEATS 100
# walcrash-1.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
- file delete -force test.db test.db-wal
+ forcedelete test.db test.db-wal
do_test walcrash-1.$i.1 {
crashsql -delay 4 -file test.db-wal -seed [incr seed] {
PRAGMA journal_mode = WAL;
@@ -74,7 +74,7 @@ for {set i 1} {$i < $REPEATS} {incr i} {
# walcrash-2.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
- file delete -force test.db test.db-wal
+ forcedelete test.db test.db-wal
do_test walcrash-2.$i.1 {
crashsql -delay 4 -file test.db-wal -seed [incr seed] {
PRAGMA journal_mode = WAL;
@@ -111,8 +111,8 @@ for {set i 1} {$i < $REPEATS} {incr i} {
# walcrash-3.*
#
# for {set i 1} {$i < $REPEATS} {incr i} {
-# file delete -force test.db test.db-wal
-# file delete -force test2.db test2.db-wal
+# forcedelete test.db test.db-wal
+# forcedelete test2.db test2.db-wal
#
# do_test walcrash-3.$i.1 {
# crashsql -delay 2 -file test2.db-wal -seed [incr seed] {
@@ -143,8 +143,8 @@ for {set i 1} {$i < $REPEATS} {incr i} {
# walcrash-4.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
- file delete -force test.db test.db-wal
- file delete -force test2.db test2.db-wal
+ forcedelete test.db test.db-wal
+ forcedelete test2.db test2.db-wal
do_test walcrash-4.$i.1 {
crashsql -delay 3 -file test.db-wal -seed [incr seed] -blocksize 4096 {
@@ -171,8 +171,8 @@ for {set i 1} {$i < $REPEATS} {incr i} {
# walcrash-5.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
- file delete -force test.db test.db-wal
- file delete -force test2.db test2.db-wal
+ forcedelete test.db test.db-wal
+ forcedelete test2.db test2.db-wal
do_test walcrash-5.$i.1 {
crashsql -delay 11 -file test.db-wal -seed [incr seed] -blocksize 4096 {
@@ -212,8 +212,8 @@ for {set i 1} {$i < $REPEATS} {incr i} {
# walcrash-6.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
- file delete -force test.db test.db-wal
- file delete -force test2.db test2.db-wal
+ forcedelete test.db test.db-wal
+ forcedelete test2.db test2.db-wal
do_test walcrash-6.$i.1 {
crashsql -delay 12 -file test.db-wal -seed [incr seed] -blocksize 512 {
@@ -262,7 +262,7 @@ for {set i 1} {$i < $REPEATS} {incr i} {
# based on the log file.
#
for {set i 1} {$i < $REPEATS} {incr i} {
- file delete -force test.db test.db-wal
+ forcedelete test.db test.db-wal
# Select a page-size for this test.
#
diff --git a/test/walfault.test b/test/walfault.test
index 3a90f9c6..1b71d78a 100644
--- a/test/walfault.test
+++ b/test/walfault.test
@@ -465,7 +465,7 @@ do_test walfault-13-pre-1 {
COMMIT;
}
faultsim_save_and_close
- file delete sv_test.db-shm
+ delete_file sv_test.db-shm
} {}
do_faultsim_test walfault-13.1 -prep {
diff --git a/test/walmode.test b/test/walmode.test
index 11113c6b..4e14d54d 100644
--- a/test/walmode.test
+++ b/test/walmode.test
@@ -295,7 +295,7 @@ db close
# loaded when sqlite3_prepare_v2() is called to compile the statement.
#
do_test walmode-7.0 {
- file delete -force test.db
+ forcedelete test.db
sqlite3 db test.db
execsql {
PRAGMA journal_mode = WAL;
diff --git a/test/walnoshm.test b/test/walnoshm.test
index de059dd5..d4082178 100644
--- a/test/walnoshm.test
+++ b/test/walnoshm.test
@@ -87,8 +87,8 @@ do_execsql_test 2.1.2 {
} {exclusive wal}
do_test 2.1.3 {
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
sqlite3 db2 test2.db
catchsql { SELECT * FROM t2 } db2
} {1 {unable to open database file}}
@@ -104,8 +104,8 @@ do_test 2.1.5 {
} {exclusive delete a b c d e f g h}
do_test 2.2.1 {
- file copy -force test.db test2.db
- file copy -force test.db-wal test2.db-wal
+ forcecopy test.db test2.db
+ forcecopy test.db-wal test2.db-wal
sqlite3 db3 test2.db -vfs tvfsshm
sqlite3 db2 test2.db
execsql { SELECT * FROM t2 } db3
diff --git a/test/walpersist.test b/test/walpersist.test
new file mode 100644
index 00000000..175dcbf8
--- /dev/null
+++ b/test/walpersist.test
@@ -0,0 +1,73 @@
+# 2011 July 26
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file contains tests for using WAL with persistent WAL file mode.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+set ::testprefix walpersist
+
+ifcapable !wal {
+ finish_test
+ return
+}
+
+do_test walpersist-1.0 {
+ db eval {
+ PRAGMA journal_mode=WAL;
+ CREATE TABLE t1(a);
+ INSERT INTO t1 VALUES(randomblob(5000));
+ }
+ file exists test.db-wal
+} {1}
+do_test walpersist-1.1 {
+ file exists test.db-shm
+} {1}
+do_test walpersist-1.2 {
+ db close
+ list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
+} {1 0 0}
+do_test walpersist-1.3 {
+ sqlite3 db test.db
+ db eval {SELECT length(a) FROM t1}
+} {5000}
+do_test walpersist-1.4 {
+ list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
+} {1 1 1}
+do_test walpersist-1.5 {
+ file_control_persist_wal db -1
+} {0 0}
+do_test walpersist-1.6 {
+ file_control_persist_wal db 1
+} {0 1}
+do_test walpersist-1.7 {
+ file_control_persist_wal db -1
+} {0 1}
+do_test walpersist-1.8 {
+ file_control_persist_wal db 0
+} {0 0}
+do_test walpersist-1.9 {
+ file_control_persist_wal db -1
+} {0 0}
+do_test walpersist-1.10 {
+ file_control_persist_wal db 1
+} {0 1}
+do_test walpersist-1.11 {
+ db close
+ list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm]
+} {1 1 1}
+
+
+
+
+finish_test
diff --git a/test/walro.test b/test/walro.test
index 60bdce9e..3ae7d53c 100644
--- a/test/walro.test
+++ b/test/walro.test
@@ -24,6 +24,13 @@ if {$::tcl_platform(platform) != "unix"} {
return
}
+# And only if the build is WAL-capable.
+#
+ifcapable !wal {
+ finish_test
+ return
+}
+
do_multiclient_test tn {
# Do not run tests with the connections in the same process.
#
@@ -136,7 +143,7 @@ do_multiclient_test tn {
} {1 {unable to open database file}}
# Also test that if the -shm file can be opened for read/write access,
- # it is, even if readonly_shm=1 is present in the URI.
+ # it is not if readonly_shm=1 is present in the URI.
do_test 1.3.2.1 {
code1 { db close }
code2 { db2 close }
@@ -144,8 +151,8 @@ do_multiclient_test tn {
} {0}
do_test 1.3.2.2 {
code1 { sqlite3 db file:test.db?readonly_shm=1 }
- sql1 { SELECT * FROM t1 }
- } {a b c d e f g h i j k l}
+ csql1 { SELECT * FROM sqlite_master }
+ } {1 {unable to open database file}}
do_test 1.3.2.3 {
code1 { db close }
close [open test.db-shm w]
diff --git a/test/walslow.test b/test/walslow.test
index d7269528..83f29228 100644
--- a/test/walslow.test
+++ b/test/walslow.test
@@ -21,7 +21,7 @@ ifcapable !wal {finish_test ; return }
proc reopen_db {} {
catch { db close }
- file delete -force test.db test.db-wal
+ forcedelete test.db test.db-wal
sqlite3 db test.db
execsql { PRAGMA journal_mode = wal }
}
@@ -53,9 +53,9 @@ for {set seed 1} {$seed<10} {incr seed} {
} {ok}
do_test walslow-1.seed=$seed.$iTest.3 {
- file delete -force testX.db testX.db-wal
- file copy test.db testX.db
- file copy test.db-wal testX.db-wal
+ forcedelete testX.db testX.db-wal
+ copy_file test.db testX.db
+ copy_file test.db-wal testX.db-wal
sqlite3 db2 testX.db
execsql { PRAGMA journal_mode = WAL } db2
diff --git a/test/walthread.test b/test/walthread.test
index 9817c0e0..cbd63718 100644
--- a/test/walthread.test
+++ b/test/walthread.test
@@ -129,7 +129,7 @@ proc do_thread_test {args} {
puts "Running $P(testname) for $P(seconds) seconds..."
catch { db close }
- file delete -force test.db test.db-journal test.db-wal
+ forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
eval $P(init)
@@ -508,12 +508,12 @@ do_thread_test walthread-5 -seconds $seconds(walthread-5) -init {
COMMIT;
}
- file copy -force test.db-wal bak.db-wal
- file copy -force test.db bak.db
+ forcecopy test.db-wal bak.db-wal
+ forcecopy test.db bak.db
db close
- file copy -force bak.db-wal test.db-wal
- file copy -force bak.db test.db
+ forcecopy bak.db-wal test.db-wal
+ forcecopy bak.db test.db
if {[file size test.db-wal] < [log_file_size [expr 64*1024] 1024]} {
error "Somehow failed to create a large log file"
diff --git a/test/where3.test b/test/where3.test
index ab75fdec..e08f9051 100644
--- a/test/where3.test
+++ b/test/where3.test
@@ -342,4 +342,87 @@ do_execsql_test where3-5.3 {
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
+# Name resolution with NATURAL JOIN and USING
+#
+do_test where3-6.setup {
+ db eval {
+ CREATE TABLE t6w(a, w);
+ INSERT INTO t6w VALUES(1, 'w-one');
+ INSERT INTO t6w VALUES(2, 'w-two');
+ INSERT INTO t6w VALUES(9, 'w-nine');
+ CREATE TABLE t6x(a, x);
+ INSERT INTO t6x VALUES(1, 'x-one');
+ INSERT INTO t6x VALUES(3, 'x-three');
+ INSERT INTO t6x VALUES(9, 'x-nine');
+ CREATE TABLE t6y(a, y);
+ INSERT INTO t6y VALUES(1, 'y-one');
+ INSERT INTO t6y VALUES(4, 'y-four');
+ INSERT INTO t6y VALUES(9, 'y-nine');
+ CREATE TABLE t6z(a, z);
+ INSERT INTO t6z VALUES(1, 'z-one');
+ INSERT INTO t6z VALUES(5, 'z-five');
+ INSERT INTO t6z VALUES(9, 'z-nine');
+ }
+} {}
+set cnt 0
+foreach predicate {
+ {}
+ {ORDER BY a}
+ {ORDER BY t6w.a}
+ {WHERE a>0}
+ {WHERE t6y.a>0}
+ {WHERE a>0 ORDER BY a}
+} {
+ incr cnt
+ do_test where3-6.$cnt.1 {
+ set sql "SELECT * FROM t6w NATURAL JOIN t6x NATURAL JOIN t6y"
+ append sql " NATURAL JOIN t6z "
+ append sql $::predicate
+ db eval $sql
+ } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine}
+ do_test where3-6.$cnt.2 {
+ set sql "SELECT * FROM t6w JOIN t6x USING(a) JOIN t6y USING(a)"
+ append sql " JOIN t6z USING(a) "
+ append sql $::predicate
+ db eval $sql
+ } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine}
+ do_test where3-6.$cnt.3 {
+ set sql "SELECT * FROM t6w NATURAL JOIN t6x JOIN t6y USING(a)"
+ append sql " JOIN t6z USING(a) "
+ append sql $::predicate
+ db eval $sql
+ } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine}
+ do_test where3-6.$cnt.4 {
+ set sql "SELECT * FROM t6w JOIN t6x USING(a) NATURAL JOIN t6y"
+ append sql " JOIN t6z USING(a) "
+ append sql $::predicate
+ db eval $sql
+ } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine}
+ do_test where3-6.$cnt.5 {
+ set sql "SELECT * FROM t6w JOIN t6x USING(a) JOIN t6y USING(a)"
+ append sql " NATURAL JOIN t6z "
+ append sql $::predicate
+ db eval $sql
+ } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine}
+ do_test where3-6.$cnt.6 {
+ set sql "SELECT * FROM t6w JOIN t6x USING(a) NATURAL JOIN t6y"
+ append sql " NATURAL JOIN t6z "
+ append sql $::predicate
+ db eval $sql
+ } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine}
+ do_test where3-6.$cnt.7 {
+ set sql "SELECT * FROM t6w NATURAL JOIN t6x JOIN t6y USING(a)"
+ append sql " NATURAL JOIN t6z "
+ append sql $::predicate
+ db eval $sql
+ } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine}
+ do_test where3-6.$cnt.8 {
+ set sql "SELECT * FROM t6w NATURAL JOIN t6x NATURAL JOIN t6y"
+ append sql " JOIN t6z USING(a) "
+ append sql $::predicate
+ db eval $sql
+ } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine}
+}
+
+
finish_test
diff --git a/test/where7.test b/test/where7.test
index e34778c7..ffb7173d 100644
--- a/test/where7.test
+++ b/test/where7.test
@@ -10,8 +10,6 @@
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the multi-index OR clause optimizer.
-#
-# $Id: where7.test,v 1.9 2009/06/07 23:45:11 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -23341,7 +23339,7 @@ do_execsql_test where7-3.1 {
OR t301.c8 = 1407424651264000)
ORDER BY t302.c5 LIMIT 200;
} {
- 0 0 1 {SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?) (~10 rows)}
+ 0 0 1 {SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?) (~5 rows)}
0 0 1 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}
0 1 0 {SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?) (~2 rows)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
diff --git a/test/where9.test b/test/where9.test
index 9a180116..b4a2d8d1 100644
--- a/test/where9.test
+++ b/test/where9.test
@@ -11,7 +11,6 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the multi-index OR clause optimizer.
#
-# $Id: where9.test,v 1.9 2009/06/05 17:09:12 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -365,7 +364,7 @@ ifcapable explain {
} {
0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}
0 1 1 {SEARCH TABLE t2 USING INDEX t2d (d=?) (~2 rows)}
- 0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) (~10 rows)}
+ 0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) (~5 rows)}
}
do_execsql_test where9-3.2 {
EXPLAIN QUERY PLAN
@@ -375,7 +374,7 @@ ifcapable explain {
} {
0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}
0 1 1 {SEARCH TABLE t2 USING INDEX t2d (d=?) (~2 rows)}
- 0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) (~10 rows)}
+ 0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?) (~5 rows)}
}
}
@@ -454,8 +453,8 @@ ifcapable explain {
do_execsql_test where9-5.1 {
EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL)
} {
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?) (~10 rows)}
- 0 0 0 {SEARCH TABLE t1 USING INDEX t1d (d=?) (~10 rows)}
+ 0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?) (~2 rows)}
+ 0 0 0 {SEARCH TABLE t1 USING INDEX t1d (d=?) (~2 rows)}
}
# In contrast, b=1000 is preferred over any OR-clause.
@@ -783,4 +782,79 @@ do_test where9-6.8.2 {
}
} {1 {cannot use index: t1b}}
+############################################################################
+# Test cases where terms inside an OR series are combined with AND terms
+# external to the OR clause. In other words, cases where
+#
+# x AND (y OR z)
+#
+# is able to use indices on x,y and x,z, or indices y,x and z,x.
+#
+do_test where9-7.0 {
+ execsql {
+ CREATE TABLE t5(a, b, c, d, e, f, g, x, y);
+ INSERT INTO t5
+ SELECT a, b, c, e, d, f, g,
+ CASE WHEN (a&1)!=0 THEN 'y' ELSE 'n' END,
+ CASE WHEN (a&2)!=0 THEN 'y' ELSE 'n' END
+ FROM t1;
+ CREATE INDEX t5xb ON t5(x, b);
+ CREATE INDEX t5xc ON t5(x, c);
+ CREATE INDEX t5xd ON t5(x, d);
+ CREATE INDEX t5xe ON t5(x, e);
+ CREATE INDEX t5xf ON t5(x, f);
+ CREATE INDEX t5xg ON t5(x, g);
+ CREATE INDEX t5yb ON t5(y, b);
+ CREATE INDEX t5yc ON t5(y, c);
+ CREATE INDEX t5yd ON t5(y, d);
+ CREATE INDEX t5ye ON t5(y, e);
+ CREATE INDEX t5yf ON t5(y, f);
+ CREATE INDEX t5yg ON t5(y, g);
+ CREATE TABLE t6(a, b, c, e, d, f, g, x, y);
+ INSERT INTO t6 SELECT * FROM t5;
+ ANALYZE t5;
+ }
+} {}
+do_test where9-7.1.1 {
+ count_steps {
+ SELECT a FROM t5 WHERE x='y' AND (b=913 OR c=27027) ORDER BY a;
+ }
+} {79 81 83 scan 0 sort 1}
+do_test where9-7.1.2 {
+ execsql {
+ SELECT a FROM t6 WHERE x='y' AND (b=913 OR c=27027) ORDER BY a;
+ }
+} {79 81 83}
+do_test where9-7.1.3 {
+ count_steps {
+ SELECT a FROM t5 WHERE x='n' AND (b=913 OR c=27027) ORDER BY a;
+ }
+} {80 scan 0 sort 1}
+do_test where9-7.1.4 {
+ execsql {
+ SELECT a FROM t6 WHERE x='n' AND (b=913 OR c=27027) ORDER BY a;
+ }
+} {80}
+do_test where9-7.2.1 {
+ count_steps {
+ SELECT a FROM t5 WHERE (x='y' OR y='y') AND b=913 ORDER BY a;
+ }
+} {83 scan 0 sort 1}
+do_test where9-7.2.2 {
+ execsql {
+ SELECT a FROM t6 WHERE (x='y' OR y='y') AND b=913 ORDER BY a;
+ }
+} {83}
+do_test where9-7.3.1 {
+ count_steps {
+ SELECT a FROM t5 WHERE (x='y' OR y='y') AND c=27027 ORDER BY a;
+ }
+} {79 81 scan 0 sort 1}
+do_test where9-7.3.2 {
+ execsql {
+ SELECT a FROM t6 WHERE (x='y' OR y='y') AND c=27027 ORDER BY a;
+ }
+} {79 81}
+
+
finish_test
diff --git a/test/win32lock.test b/test/win32lock.test
new file mode 100644
index 00000000..d014be4d
--- /dev/null
+++ b/test/win32lock.test
@@ -0,0 +1,133 @@
+# 2011 July 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 regression tests for SQLite library. The
+# focus of this script is recovery from transient manditory locks
+# that sometimes appear on database files due to anti-virus software.
+#
+
+if {$tcl_platform(platform)!="windows"} return
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set testprefix win32lock
+
+db close
+sqlite3_shutdown
+test_sqlite3_log xLog
+proc xLog {error_code msg} {
+ lappend ::log $msg
+}
+sqlite3 db test.db
+
+do_test win32lock-1.1 {
+ db eval {
+ PRAGMA cache_size=10;
+ CREATE TABLE t1(x,y);
+ INSERT INTO t1 VALUES(1,randomblob(100000));
+ INSERT INTO t1 VALUES(2,randomblob(50000));
+ INSERT INTO t1 VALUES(3,randomblob(25000));
+ INSERT INTO t1 VALUES(4,randomblob(12500));
+ SELECT x, length(y) FROM t1 ORDER BY rowid;
+ }
+} {1 100000 2 50000 3 25000 4 12500}
+
+unset -nocomplain delay1 rc msg
+set old_pending_byte [sqlite3_test_control_pending_byte 0x40000000]
+
+set win32_lock_ok [list]
+set win32_lock_error [list]
+set delay1 25
+while {1} {
+ lock_win32_file test.db 0 $::delay1
+ set ::log {}
+ set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
+ if {$rc} {
+ lappend win32_lock_error $::delay1
+ do_test win32lock-1.2-$delay1-error {
+ set ::msg
+ } {disk I/O error}
+ } else {
+ lappend win32_lock_ok $::delay1
+ do_test win32lock-1.2-$delay1-ok {
+ set ::msg
+ } {1 100000 2 50000 3 25000 4 12500}
+ if {[info exists ::log] && $::log!=""} {
+ do_test win32lock-1.2-$delay1-log1 {
+ regsub {\d+} $::log # x
+ set x
+ } {{delayed #ms for lock/sharing conflict}}
+ }
+ }
+ if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
+ incr delay1 25
+ if {$delay1 > 12500} {
+ puts "Timed out waiting for \"ok\" and \"error\" results."
+ break
+ }
+ sqlite3_sleep 10
+}
+
+do_test win32lock-2.0 {
+ file_control_win32_av_retry db -1 -1
+} {0 10 25}
+do_test win32lock-2.1 {
+ file_control_win32_av_retry db 1 1
+} {0 1 1}
+
+#
+# NOTE: It is known that the win32lock-2.2-* tests may fail if the system is
+# experiencing heavy load (i.e. they are very timing sensitive). This is
+# primarily due to the AV retry delay being set to 1 millisecond in the
+# win32lock-2.1 test (above). While it is important to test this corner
+# case for the AV retry logic, a failure of this test should probably not
+# be interpreted as a bug in SQLite or these test cases.
+#
+set win32_lock_ok [list]
+set win32_lock_error [list]
+set delay1 1
+while {1} {
+ lock_win32_file test.db 0 $::delay1
+ set ::log {}
+ set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
+ if {$rc} {
+ lappend win32_lock_error $::delay1
+ do_test win32lock-2.2-$delay1-error {
+ set ::msg
+ } {disk I/O error}
+ } else {
+ lappend win32_lock_ok $::delay1
+ do_test win32lock-2.2-$delay1-ok {
+ set ::msg
+ } {1 100000 2 50000 3 25000 4 12500}
+ if {[info exists ::log] && $::log!=""} {
+ do_test win32lock-2.2-$delay1-log1 {
+ regsub {\d+} $::log # x
+ set x
+ } {{delayed #ms for lock/sharing conflict}}
+ }
+ }
+ if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
+ incr delay1 1
+ if {$delay1 > 500} {
+ puts "Timed out waiting for \"ok\" and \"error\" results."
+ break
+ }
+ sqlite3_sleep 10
+}
+
+file_control_win32_av_retry db 10 25
+sqlite3_test_control_pending_byte $old_pending_byte
+db close
+sqlite3_shutdown
+test_sqlite3_log
+sqlite3_initialize
+finish_test
diff --git a/tool/extract.c b/tool/extract.c
new file mode 100644
index 00000000..5bf5caa3
--- /dev/null
+++ b/tool/extract.c
@@ -0,0 +1,46 @@
+/*
+** Extract a range of bytes from a file.
+**
+** Usage:
+**
+** extract FILENAME OFFSET AMOUNT
+**
+** The bytes are written to standard output.
+*/
+#include
+#include
+
+int main(int argc, char **argv){
+ FILE *f;
+ char *zBuf;
+ int ofst;
+ int n;
+ size_t got;
+
+ if( argc!=4 ){
+ fprintf(stderr, "Usage: %s FILENAME OFFSET AMOUNT\n", *argv);
+ return 1;
+ }
+ f = fopen(argv[1], "rb");
+ if( f==0 ){
+ fprintf(stderr, "cannot open \"%s\"\n", argv[1]);
+ return 1;
+ }
+ ofst = atoi(argv[2]);
+ n = atoi(argv[3]);
+ zBuf = malloc( n );
+ if( zBuf==0 ){
+ fprintf(stderr, "out of memory\n");
+ return 1;
+ }
+ fseek(f, ofst, SEEK_SET);
+ got = fread(zBuf, 1, n, f);
+ fclose(f);
+ if( goterrorcnt++;
+ fclose(fp);
return;
}
if( fread(filebuf,1,filesize,fp)!=filesize ){
@@ -2529,6 +2530,7 @@ void Parse(struct lemon *gp)
filesize);
free(filebuf);
gp->errorcnt++;
+ fclose(fp);
return;
}
fclose(fp);
diff --git a/tool/mksqlite3c-noext.tcl b/tool/mksqlite3c-noext.tcl
new file mode 100644
index 00000000..6ad30237
--- /dev/null
+++ b/tool/mksqlite3c-noext.tcl
@@ -0,0 +1,308 @@
+#!/usr/bin/tclsh
+#
+# To build a single huge source file holding all of SQLite (or at
+# least the core components - the test harness, shell, and TCL
+# interface are omitted.) first do
+#
+# make target_source
+#
+# The make target above moves all of the source code files into
+# a subdirectory named "tsrc". (This script expects to find the files
+# there and will not work if they are not found.) There are a few
+# generated C code files that are also added to the tsrc directory.
+# For example, the "parse.c" and "parse.h" files to implement the
+# the parser are derived from "parse.y" using lemon. And the
+# "keywordhash.h" files is generated by a program named "mkkeywordhash".
+#
+# After the "tsrc" directory has been created and populated, run
+# this script:
+#
+# tclsh mksqlite3c.tcl
+#
+# The amalgamated SQLite code will be written into sqlite3.c
+#
+
+# Begin by reading the "sqlite3.h" header file. Extract the version number
+# from in this file. The versioon number is needed to generate the header
+# comment of the amalgamation.
+#
+if {[lsearch $argv --nostatic]>=0} {
+ set addstatic 0
+} else {
+ set addstatic 1
+}
+if {[lsearch $argv --linemacros]>=0} {
+ set linemacros 1
+} else {
+ set linemacros 0
+}
+set in [open tsrc/sqlite3.h]
+set cnt 0
+set VERSION ?????
+while {![eof $in]} {
+ set line [gets $in]
+ if {$line=="" && [eof $in]} break
+ incr cnt
+ regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
+}
+close $in
+
+# Open the output file and write a header comment at the beginning
+# of the file.
+#
+set out [open sqlite3.c w]
+# Force the output to use unix line endings, even on Windows.
+fconfigure $out -translation lf
+set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
+puts $out [subst \
+{/******************************************************************************
+** This file is an amalgamation of many separate C source files from SQLite
+** version $VERSION. By combining all the individual C code files into this
+** single large file, the entire code can be compiled as a single translation
+** unit. This allows many compilers to do optimizations that would not be
+** possible if the files were compiled separately. Performance improvements
+** of 5% or more are commonly seen when SQLite is compiled as a single
+** translation unit.
+**
+** This file is all you need to compile SQLite. To use SQLite in other
+** programs, you need this file and the "sqlite3.h" header file that defines
+** the programming interface to the SQLite library. (If you do not have
+** the "sqlite3.h" header file at hand, you will find a copy embedded within
+** the text of this file. Search for "Begin file sqlite3.h" to find the start
+** of the embedded sqlite3.h header file.) Additional code files may be needed
+** if you want a wrapper to interface SQLite with your choice of programming
+** language. The code for the "sqlite3" command-line shell is also in a
+** separate file. This file contains only code for the core SQLite library.
+*/
+#define SQLITE_CORE 1
+#define SQLITE_AMALGAMATION 1}]
+if {$addstatic} {
+ puts $out \
+{#ifndef SQLITE_PRIVATE
+# define SQLITE_PRIVATE static
+#endif
+#ifndef SQLITE_API
+# define SQLITE_API
+#endif}
+}
+
+# These are the header files used by SQLite. The first time any of these
+# files are seen in a #include statement in the C code, include the complete
+# text of the file in-line. The file only needs to be included once.
+#
+foreach hdr {
+ btree.h
+ btreeInt.h
+ hash.h
+ hwtime.h
+ keywordhash.h
+ mutex.h
+ opcodes.h
+ os_common.h
+ os.h
+ os_os2.h
+ pager.h
+ parse.h
+ pcache.h
+ sqlite3ext.h
+ sqlite3.h
+ sqliteicu.h
+ sqliteInt.h
+ sqliteLimit.h
+ vdbe.h
+ vdbeInt.h
+ wal.h
+} {
+ set available_hdr($hdr) 1
+}
+set available_hdr(sqliteInt.h) 0
+
+# 78 stars used for comment formatting.
+set s78 \
+{*****************************************************************************}
+
+# Insert a comment into the code
+#
+proc section_comment {text} {
+ global out s78
+ set n [string length $text]
+ set nstar [expr {60 - $n}]
+ set stars [string range $s78 0 $nstar]
+ puts $out "/************** $text $stars/"
+}
+
+# Read the source file named $filename and write it into the
+# sqlite3.c output file. If any #include statements are seen,
+# process them approprately.
+#
+proc copy_file {filename} {
+ global seen_hdr available_hdr out addstatic linemacros
+ set ln 0
+ set tail [file tail $filename]
+ section_comment "Begin file $tail"
+ if {$linemacros} {puts $out "#line 1 \"$filename\""}
+ set in [open $filename r]
+ set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
+ set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(}
+ if {[file extension $filename]==".h"} {
+ set declpattern " *$declpattern"
+ }
+ set declpattern ^$declpattern
+ while {![eof $in]} {
+ set line [gets $in]
+ incr ln
+ if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
+ if {[info exists available_hdr($hdr)]} {
+ if {$available_hdr($hdr)} {
+ if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
+ set available_hdr($hdr) 0
+ }
+ section_comment "Include $hdr in the middle of $tail"
+ copy_file tsrc/$hdr
+ section_comment "Continuing where we left off in $tail"
+ if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
+ }
+ } elseif {![info exists seen_hdr($hdr)]} {
+ set seen_hdr($hdr) 1
+ puts $out $line
+ } else {
+ puts $out "/* $line */"
+ }
+ } elseif {[regexp {^#ifdef __cplusplus} $line]} {
+ puts $out "#if 0"
+ } elseif {!$linemacros && [regexp {^#line} $line]} {
+ # Skip #line directives.
+ } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
+ regsub {^SQLITE_API } $line {} line
+ if {[regexp $declpattern $line all funcname]} {
+ # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
+ # so that linkage can be modified at compile-time.
+ if {[regexp {^sqlite3_} $funcname]} {
+ puts $out "SQLITE_API $line"
+ } else {
+ puts $out "SQLITE_PRIVATE $line"
+ }
+ } elseif {[regexp $varpattern $line all varname]} {
+ # Add the SQLITE_PRIVATE before variable declarations or
+ # definitions for internal use
+ if {![regexp {^sqlite3_} $varname]} {
+ regsub {^extern } $line {} line
+ puts $out "SQLITE_PRIVATE $line"
+ } else {
+ if {[regexp {const char sqlite3_version\[\];} $line]} {
+ set line {const char sqlite3_version[] = SQLITE_VERSION;}
+ }
+ regsub {^SQLITE_EXTERN } $line {} line
+ puts $out "SQLITE_API $line"
+ }
+ } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
+ regsub {^SQLITE_EXTERN } $line {} line
+ puts $out "SQLITE_PRIVATE $line"
+ } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
+ puts $out "SQLITE_PRIVATE $line"
+ } else {
+ puts $out $line
+ }
+ } else {
+ puts $out $line
+ }
+ }
+ close $in
+ section_comment "End of $tail"
+}
+
+
+# Process the source files. Process files containing commonly
+# used subroutines first in order to help the compiler find
+# inlining opportunities.
+#
+foreach file {
+ sqliteInt.h
+
+ global.c
+ ctime.c
+ status.c
+ date.c
+ os.c
+
+ fault.c
+ mem0.c
+ mem1.c
+ mem2.c
+ mem3.c
+ mem5.c
+ mutex.c
+ mutex_noop.c
+ mutex_os2.c
+ mutex_unix.c
+ mutex_w32.c
+ malloc.c
+ printf.c
+ random.c
+ utf.c
+ util.c
+ hash.c
+ opcodes.c
+
+ os_os2.c
+ os_unix.c
+ os_win.c
+
+ bitvec.c
+ pcache.c
+ pcache1.c
+ rowset.c
+ pager.c
+ wal.c
+
+ btmutex.c
+ btree.c
+ backup.c
+
+ vdbemem.c
+ vdbeaux.c
+ vdbeapi.c
+ vdbetrace.c
+ vdbe.c
+ vdbeblob.c
+ vdbesort.c
+ journal.c
+ memjournal.c
+
+ walker.c
+ resolve.c
+ expr.c
+ alter.c
+ analyze.c
+ attach.c
+ auth.c
+ build.c
+ callback.c
+ delete.c
+ func.c
+ fkey.c
+ insert.c
+ legacy.c
+ loadext.c
+ pragma.c
+ prepare.c
+ select.c
+ table.c
+ trigger.c
+ update.c
+ vacuum.c
+ vtab.c
+ where.c
+
+ parse.c
+
+ tokenize.c
+ complete.c
+
+ main.c
+ notify.c
+} {
+ copy_file tsrc/$file
+}
+
+close $out
diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl
index a834cab2..d0c7a560 100644
--- a/tool/mksqlite3c.tcl
+++ b/tool/mksqlite3c.tcl
@@ -31,6 +31,11 @@ if {[lsearch $argv --nostatic]>=0} {
} else {
set addstatic 1
}
+if {[lsearch $argv --linemacros]>=0} {
+ set linemacros 1
+} else {
+ set linemacros 0
+}
set in [open tsrc/sqlite3.h]
set cnt 0
set VERSION ?????
@@ -136,9 +141,11 @@ proc section_comment {text} {
# process them approprately.
#
proc copy_file {filename} {
- global seen_hdr available_hdr out addstatic
+ global seen_hdr available_hdr out addstatic linemacros
+ set ln 0
set tail [file tail $filename]
section_comment "Begin file $tail"
+ if {$linemacros} {puts $out "#line 1 \"$filename\""}
set in [open $filename r]
set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(}
@@ -148,6 +155,7 @@ proc copy_file {filename} {
set declpattern ^$declpattern
while {![eof $in]} {
set line [gets $in]
+ incr ln
if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
if {[info exists available_hdr($hdr)]} {
if {$available_hdr($hdr)} {
@@ -157,14 +165,17 @@ proc copy_file {filename} {
section_comment "Include $hdr in the middle of $tail"
copy_file tsrc/$hdr
section_comment "Continuing where we left off in $tail"
+ if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
}
} elseif {![info exists seen_hdr($hdr)]} {
set seen_hdr($hdr) 1
puts $out $line
+ } else {
+ puts $out "/* $line */"
}
} elseif {[regexp {^#ifdef __cplusplus} $line]} {
puts $out "#if 0"
- } elseif {[regexp {^#line} $line]} {
+ } elseif {!$linemacros && [regexp {^#line} $line]} {
# Skip #line directives.
} elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
regsub {^SQLITE_API } $line {} line
@@ -259,6 +270,7 @@ foreach file {
vdbetrace.c
vdbe.c
vdbeblob.c
+ vdbesort.c
journal.c
memjournal.c
diff --git a/tool/offsets.c b/tool/offsets.c
new file mode 100644
index 00000000..8e098e71
--- /dev/null
+++ b/tool/offsets.c
@@ -0,0 +1,329 @@
+/*
+** This program searches an SQLite database file for the lengths and
+** offsets for all TEXT or BLOB entries for a particular column of a
+** particular table. The rowid, size and offset for the column are
+** written to standard output. There are three arguments, which are the
+** name of the database file, the table, and the column.
+*/
+#include "sqlite3.h"
+#include
+#include
+#include
+#include
+
+typedef unsigned char u8;
+typedef struct GState GState;
+
+#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
+
+/*
+** Global state information for this program.
+*/
+struct GState {
+ char *zErr; /* Error message text */
+ FILE *f; /* Open database file */
+ int szPg; /* Page size for the database file */
+ int iRoot; /* Root page of the table */
+ int iCol; /* Column number for the column */
+ int pgno; /* Current page number */
+ u8 *aPage; /* Current page content */
+ u8 *aStack[20]; /* Page stack */
+ int aPgno[20]; /* Page number stack */
+ int nStack; /* Depth of stack */
+ int bTrace; /* True for tracing output */
+};
+
+/*
+** Write an error.
+*/
+static void ofstError(GState *p, const char *zFormat, ...){
+ va_list ap;
+ sqlite3_free(p->zErr);
+ va_start(ap, zFormat);
+ p->zErr = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+}
+
+/*
+** Write a trace message
+*/
+static void ofstTrace(GState *p, const char *zFormat, ...){
+ va_list ap;
+ if( p->bTrace ){
+ va_start(ap, zFormat);
+ vprintf(zFormat, ap);
+ va_end(ap);
+ }
+}
+
+/*
+** Find the root page of the table and the column number of the column.
+*/
+static void ofstRootAndColumn(
+ GState *p, /* Global state */
+ const char *zFile, /* Name of the database file */
+ const char *zTable, /* Name of the table */
+ const char *zColumn /* Name of the column */
+){
+ sqlite3 *db = 0;
+ sqlite3_stmt *pStmt = 0;
+ char *zSql = 0;
+ int rc;
+ if( p->zErr ) return;
+ rc = sqlite3_open(zFile, &db);
+ if( rc ){
+ ofstError(p, "cannot open database file \"%s\"", zFile);
+ goto rootAndColumn_exit;
+ }
+ zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master WHERE name=%Q",
+ zTable);
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql);
+ sqlite3_free(zSql);
+ if( p->zErr ) goto rootAndColumn_exit;
+ if( sqlite3_step(pStmt)!=SQLITE_ROW ){
+ ofstError(p, "cannot find table [%s]\n", zTable);
+ sqlite3_finalize(pStmt);
+ goto rootAndColumn_exit;
+ }
+ p->iRoot = sqlite3_column_int(pStmt , 0);
+ sqlite3_finalize(pStmt);
+
+ p->iCol = -1;
+ zSql = sqlite3_mprintf("PRAGMA table_info(%Q)", zTable);
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc ) ofstError(p, "%s: [%s}", sqlite3_errmsg(db), zSql);
+ sqlite3_free(zSql);
+ if( p->zErr ) goto rootAndColumn_exit;
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ const char *zCol = sqlite3_column_text(pStmt, 1);
+ if( strlen(zCol)==strlen(zColumn)
+ && sqlite3_strnicmp(zCol, zColumn, strlen(zCol))==0
+ ){
+ p->iCol = sqlite3_column_int(pStmt, 0);
+ break;
+ }
+ }
+ sqlite3_finalize(pStmt);
+ if( p->iCol<0 ){
+ ofstError(p, "no such column: %s.%s", zTable, zColumn);
+ goto rootAndColumn_exit;
+ }
+
+ zSql = sqlite3_mprintf("PRAGMA page_size");
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql);
+ sqlite3_free(zSql);
+ if( p->zErr ) goto rootAndColumn_exit;
+ if( sqlite3_step(pStmt)!=SQLITE_ROW ){
+ ofstError(p, "cannot find page size");
+ }else{
+ p->szPg = sqlite3_column_int(pStmt, 0);
+ }
+ sqlite3_finalize(pStmt);
+
+rootAndColumn_exit:
+ sqlite3_close(db);
+ return;
+}
+
+/*
+** Pop a page from the stack
+*/
+static void ofstPopPage(GState *p){
+ if( p->nStack<=0 ) return;
+ p->nStack--;
+ sqlite3_free(p->aStack[p->nStack]);
+ p->pgno = p->aPgno[p->nStack-1];
+ p->aPage = p->aStack[p->nStack-1];
+}
+
+
+/*
+** Push a new page onto the stack.
+*/
+static void ofstPushPage(GState *p, int pgno){
+ u8 *pPage;
+ size_t got;
+ if( p->zErr ) return;
+ if( p->nStack >= ArraySize(p->aStack) ){
+ ofstError(p, "page stack overflow");
+ return;
+ }
+ p->aPgno[p->nStack] = pgno;
+ p->aStack[p->nStack] = pPage = sqlite3_malloc( p->szPg );
+ if( pPage==0 ){
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ p->nStack++;
+ p->aPage = pPage;
+ p->pgno = pgno;
+ fseek(p->f, (pgno-1)*p->szPg, SEEK_SET);
+ got = fread(pPage, 1, p->szPg, p->f);
+ if( got!=p->szPg ){
+ ofstError(p, "unable to read page %d", pgno);
+ ofstPopPage(p);
+ }
+}
+
+/* Read a two-byte integer at the given offset into the current page */
+static int ofst2byte(GState *p, int ofst){
+ int x = p->aPage[ofst];
+ return (x<<8) + p->aPage[ofst+1];
+}
+
+/* Read a four-byte integer at the given offset into the current page */
+static int ofst4byte(GState *p, int ofst){
+ int x = p->aPage[ofst];
+ x = (x<<8) + p->aPage[ofst+1];
+ x = (x<<8) + p->aPage[ofst+2];
+ x = (x<<8) + p->aPage[ofst+3];
+ return x;
+}
+
+/* Read a variable-length integer. Update the offset */
+static sqlite3_int64 ofstVarint(GState *p, int *pOfst){
+ sqlite3_int64 x = 0;
+ u8 *a = &p->aPage[*pOfst];
+ int n = 0;
+ while( n<8 && (a[0] & 0x80)!=0 ){
+ x = (x<<7) + (a[0] & 0x7f);
+ n++;
+ a++;
+ }
+ if( n==8 ){
+ x = (x<<8) + a[0];
+ }else{
+ x = (x<<7) + a[0];
+ }
+ *pOfst += (n+1);
+ return x;
+}
+
+/* Return the absolute offset into a file for the given offset
+** into the current page */
+static int ofstInFile(GState *p, int ofst){
+ return p->szPg*(p->pgno-1) + ofst;
+}
+
+/* Return the size (in bytes) of the data corresponding to the
+** given serial code */
+static int ofstSerialSize(int scode){
+ if( scode<5 ) return scode;
+ if( scode==5 ) return 6;
+ if( scode<8 ) return 8;
+ if( scode<12 ) return 0;
+ return (scode-12)/2;
+}
+
+/* Forward reference */
+static void ofstWalkPage(GState*, int);
+
+/* Walk an interior btree page */
+static void ofstWalkInteriorPage(GState *p){
+ int nCell;
+ int i;
+ int ofst;
+ int iChild;
+
+ nCell = ofst2byte(p, 3);
+ for(i=0; izErr ) return;
+ }
+ ofstWalkPage(p, ofst4byte(p, 8));
+}
+
+/* Walk a leaf btree page */
+static void ofstWalkLeafPage(GState *p){
+ int nCell;
+ int i;
+ int ofst;
+ int nPayload;
+ sqlite3_int64 rowid;
+ int nHdr;
+ int j;
+ int scode;
+ int sz;
+ int dataOfst;
+ char zMsg[200];
+
+ nCell = ofst2byte(p, 3);
+ for(i=0; i p->szPg-35 ){
+ sqlite3_snprintf(sizeof(zMsg), zMsg,
+ "# overflow rowid %lld", rowid);
+ printf("%s\n", zMsg);
+ continue;
+ }
+ dataOfst = ofst;
+ nHdr = ofstVarint(p, &ofst);
+ dataOfst += nHdr;
+ for(j=0; jiCol; j++){
+ scode = ofstVarint(p, &ofst);
+ dataOfst += ofstSerialSize(scode);
+ }
+ scode = ofstVarint(p, &ofst);
+ sz = ofstSerialSize(scode);
+ sqlite3_snprintf(sizeof(zMsg), zMsg,
+ "rowid %12lld size %5d offset %8d",
+ rowid, sz, ofstInFile(p, dataOfst));
+ printf("%s\n", zMsg);
+ }
+}
+
+/*
+** Output results from a single page.
+*/
+static void ofstWalkPage(GState *p, int pgno){
+ if( p->zErr ) return;
+ ofstPushPage(p, pgno);
+ if( p->zErr ) return;
+ if( p->aPage[0]==5 ){
+ ofstWalkInteriorPage(p);
+ }else if( p->aPage[0]==13 ){
+ ofstWalkLeafPage(p);
+ }else{
+ ofstError(p, "page %d has a faulty type byte: %d", pgno, p->aPage[0]);
+ }
+ ofstPopPage(p);
+}
+
+int main(int argc, char **argv){
+ GState g;
+ memset(&g, 0, sizeof(g));
+ if( argc>2 && strcmp(argv[1],"--trace")==0 ){
+ g.bTrace = 1;
+ argc--;
+ argv++;
+ }
+ if( argc!=4 ){
+ fprintf(stderr, "Usage: %s DATABASE TABLE COLUMN\n", *argv);
+ exit(1);
+ }
+ ofstRootAndColumn(&g, argv[1], argv[2], argv[3]);
+ if( g.zErr ){
+ fprintf(stderr, "%s\n", g.zErr);
+ exit(1);
+ }
+ ofstTrace(&g, "# szPg = %d\n", g.szPg);
+ ofstTrace(&g, "# iRoot = %d\n", g.iRoot);
+ ofstTrace(&g, "# iCol = %d\n", g.iCol);
+ g.f = fopen(argv[1], "rb");
+ if( g.f==0 ){
+ fprintf(stderr, "cannot open \"%s\"\n", argv[1]);
+ exit(1);
+ }
+ ofstWalkPage(&g, g.iRoot);
+ if( g.zErr ){
+ fprintf(stderr, "%s\n", g.zErr);
+ exit(1);
+ }
+ return 0;
+}
diff --git a/tool/omittest.tcl b/tool/omittest.tcl
index 33a71cee..7f13a4cb 100644
--- a/tool/omittest.tcl
+++ b/tool/omittest.tcl
@@ -48,19 +48,18 @@ they do not respect the OPTS variable.
#
#
proc run_quick_test {dir omit_symbol_list} {
- set target "testfixture"
# Compile the value of the OPTS Makefile variable.
- set opts "-DSQLITE_MEMDEBUG -DSQLITE_DEBUG -DSQLITE_NO_SYNC"
+ set opts ""
if {$::tcl_platform(platform)=="windows"} {
- append opts " -DSQLITE_OS_WIN=1"
+ append opts "OPTS += -DSQLITE_OS_WIN=1\n"
set target "testfixture.exe"
} elseif {$::tcl_platform(platform)=="os2"} {
- append opts " -DSQLITE_OS_OS2=1"
+ append opts "OPTS += -DSQLITE_OS_OS2=1\n"
} else {
- append opts " -DSQLITE_OS_UNIX=1"
+ append opts "OPTS += -DSQLITE_OS_UNIX=1\n"
}
foreach sym $omit_symbol_list {
- append opts " -D${sym}=1"
+ append opts "OPTS += -D${sym}=1\n"
}
# Create the directory and do the build. If an error occurs return
@@ -68,12 +67,20 @@ proc run_quick_test {dir omit_symbol_list} {
file mkdir $dir
puts -nonewline "Building $dir..."
flush stdout
-catch {
- file copy -force ./config.h $dir
- file copy -force ./libtool $dir
-}
+ catch {
+ file copy -force ./config.h $dir
+ file copy -force ./libtool $dir
+ }
+ set fd [open $::MAKEFILE]
+ set mkfile [read $fd]
+ close $fd
+ regsub {\ninclude} $mkfile "\n$opts\ninclude" mkfile
+ set fd [open $dir/makefile w]
+ puts $fd $mkfile
+ close $fd
+
set rc [catch {
- exec $::MAKEBIN -C $dir -f $::MAKEFILE clean $target OPTS=$opts >& $dir/build.log
+ exec $::MAKEBIN -C $dir -f makefile clean $::TARGET >& $dir/build.log
}]
if {$rc} {
puts "No good. See $dir/build.log."
@@ -102,7 +109,7 @@ catch {
puts -nonewline "Testing $dir..."
flush stdout
set rc [catch {
- exec $::MAKEBIN -C $dir -f $::MAKEFILE test OPTS=$opts >& $dir/test.log
+ exec $::MAKEBIN -C $dir -f makefile test >& $dir/test.log
}]
if {$rc} {
puts "No good. See $dir/test.log."
@@ -126,6 +133,7 @@ proc process_options {argv} {
set ::MAKEFILE ./Makefile.linux-gcc ;# Default value
}
set ::SKIP_RUN 0 ;# Default to attempt test
+ set ::TARGET testfixture ;# Default thing to build
for {set i 0} {$i < [llength $argv]} {incr i} {
switch -- [lindex $argv $i] {
@@ -139,6 +147,11 @@ proc process_options {argv} {
set ::MAKEFILE ./Makefile.msc
}
+ -target {
+ incr i
+ set ::TARGET [lindex $argv $i]
+ }
+
-skip_run {
set ::SKIP_RUN 1
}
@@ -182,7 +195,6 @@ proc main {argv} {
SQLITE_OMIT_DATETIME_FUNCS \
SQLITE_OMIT_DECLTYPE \
SQLITE_OMIT_DEPRECATED \
- xxxSQLITE_OMIT_DISKIO \
SQLITE_OMIT_EXPLAIN \
SQLITE_OMIT_FLAG_PRAGMAS \
SQLITE_OMIT_FLOATING_POINT \
@@ -224,15 +236,11 @@ proc main {argv} {
SQLITE_DISABLE_DIRSYNC \
SQLITE_DISABLE_LFS \
SQLITE_ENABLE_ATOMIC_WRITE \
- xxxSQLITE_ENABLE_CEROD \
SQLITE_ENABLE_COLUMN_METADATA \
SQLITE_ENABLE_EXPENSIVE_ASSERT \
- xxxSQLITE_ENABLE_FTS1 \
- xxxSQLITE_ENABLE_FTS2 \
SQLITE_ENABLE_FTS3 \
SQLITE_ENABLE_FTS3_PARENTHESIS \
SQLITE_ENABLE_FTS4 \
- xxxSQLITE_ENABLE_ICU \
SQLITE_ENABLE_IOTRACE \
SQLITE_ENABLE_LOAD_EXTENSION \
SQLITE_ENABLE_LOCKING_STYLE \
@@ -241,7 +249,7 @@ proc main {argv} {
SQLITE_ENABLE_MEMSYS5 \
SQLITE_ENABLE_OVERSIZE_CELL_CHECK \
SQLITE_ENABLE_RTREE \
- SQLITE_ENABLE_STAT2 \
+ SQLITE_ENABLE_STAT3 \
SQLITE_ENABLE_UNLOCK_NOTIFY \
SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
]
diff --git a/tool/spaceanal.tcl b/tool/spaceanal.tcl
index bf6244e8..3dddfe42 100644
--- a/tool/spaceanal.tcl
+++ b/tool/spaceanal.tcl
@@ -4,15 +4,32 @@
#
if {[catch {
-
# Get the name of the database to analyze
#
-#set argv $argv0
-if {[llength $argv]!=1} {
+proc usage {} {
+ set argv0 [file rootname [file tail [info nameofexecutable]]]
puts stderr "Usage: $argv0 database-name"
exit 1
}
-set file_to_analyze [lindex $argv 0]
+set file_to_analyze {}
+set flags(-pageinfo) 0
+set flags(-stats) 0
+append argv {}
+foreach arg $argv {
+ if {[regexp {^-+pageinfo$} $arg]} {
+ set flags(-pageinfo) 1
+ } elseif {[regexp {^-+stats$} $arg]} {
+ set flags(-stats) 1
+ } elseif {[regexp {^-} $arg]} {
+ puts stderr "Unknown option: $arg"
+ usage
+ } elseif {$file_to_analyze!=""} {
+ usage
+ } else {
+ set file_to_analyze $arg
+ }
+}
+if {$file_to_analyze==""} usage
if {![file exists $file_to_analyze]} {
puts stderr "No such file: $file_to_analyze"
exit 1
@@ -21,19 +38,76 @@ if {![file readable $file_to_analyze]} {
puts stderr "File is not readable: $file_to_analyze"
exit 1
}
-if {[file size $file_to_analyze]<512} {
+set true_file_size [file size $file_to_analyze]
+if {$true_file_size<512} {
puts stderr "Empty or malformed database: $file_to_analyze"
exit 1
}
+# Compute the total file size assuming test_multiplexor is being used.
+# Assume that SQLITE_ENABLE_8_3_NAMES might be enabled
+#
+set extension [file extension $file_to_analyze]
+set pattern $file_to_analyze
+append pattern {[0-9][0-9]}
+foreach f [glob -nocomplain $pattern] {
+ incr true_file_size [file size $f]
+ set extension {}
+}
+if {[string length $extension]>=2 && [string length $extension]<=4} {
+ set pattern [file rootname $file_to_analyze]
+ append pattern [string range $extension 0 1]
+ append pattern {[0-9][0-9]}
+ foreach f [glob -nocomplain $pattern] {
+ incr true_file_size [file size $f]
+ }
+}
+
# Open the database
#
-sqlite3 db [lindex $argv 0]
+sqlite3 db $file_to_analyze
register_dbstat_vtab db
-set pageSize [db one {PRAGMA page_size}]
+db eval {SELECT count(*) FROM sqlite_master}
+set pageSize [expr {wide([db one {PRAGMA page_size}])}]
-#set DB [btree_open [lindex $argv 0] 1000 0]
+if {$flags(-pageinfo)} {
+ db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
+ db eval {SELECT name, path, pageno FROM temp.stat ORDER BY pageno} {
+ puts "$pageno $name $path"
+ }
+ exit 0
+}
+if {$flags(-stats)} {
+ db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
+ puts "BEGIN;"
+ puts "CREATE TABLE stats("
+ puts " name STRING, /* Name of table or index */"
+ puts " path INTEGER, /* Path to page from root */"
+ puts " pageno INTEGER, /* Page number */"
+ puts " pagetype STRING, /* 'internal', 'leaf' or 'overflow' */"
+ puts " ncell INTEGER, /* Cells on page (0 for overflow) */"
+ puts " payload INTEGER, /* Bytes of payload on this page */"
+ puts " unused INTEGER, /* Bytes of unused space on this page */"
+ puts " mx_payload INTEGER, /* Largest payload size of all cells */"
+ puts " pgoffset INTEGER, /* Offset of page in file */"
+ puts " pgsize INTEGER /* Size of the page */"
+ puts ");"
+ db eval {SELECT quote(name) || ',' ||
+ quote(path) || ',' ||
+ quote(pageno) || ',' ||
+ quote(pagetype) || ',' ||
+ quote(ncell) || ',' ||
+ quote(payload) || ',' ||
+ quote(unused) || ',' ||
+ quote(mx_payload) || ',' ||
+ quote(pgoffset) || ',' ||
+ quote(pgsize) AS x FROM stat} {
+ puts "INSERT INTO stats VALUES($x);"
+ }
+ puts "COMMIT;"
+ exit 0
+}
# In-memory database for collecting statistics. This script loops through
# the tables and indices in the database being analyzed, adding a row for each
@@ -41,8 +115,7 @@ set pageSize [db one {PRAGMA page_size}]
# queries the in-memory db to produce the space-analysis report.
#
sqlite3 mem :memory:
-set tabledef\
-{CREATE TABLE space_used(
+set tabledef {CREATE TABLE space_used(
name clob, -- Name of a table or index in the database file
tblname clob, -- Name of associated table
is_index boolean, -- TRUE if it is an index, false for a table
@@ -58,17 +131,17 @@ set tabledef\
int_unused int, -- Number of unused bytes on interior pages
leaf_unused int, -- Number of unused bytes on primary pages
ovfl_unused int, -- Number of unused bytes on overflow pages
- gap_cnt int -- Number of gaps in the page layout
+ gap_cnt int, -- Number of gaps in the page layout
+ compressed_size int -- Total bytes stored on disk
);}
mem eval $tabledef
# Create a temporary "dbstat" virtual table.
#
-db eval {
- CREATE VIRTUAL TABLE temp.stat USING dbstat;
- CREATE TEMP TABLE dbstat AS SELECT * FROM temp.stat ORDER BY name, path;
- DROP TABLE temp.stat;
-}
+db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
+db eval {CREATE TEMP TABLE dbstat AS SELECT * FROM temp.stat
+ ORDER BY name, path}
+db eval {DROP TABLE temp.stat}
proc isleaf {pagetype is_index} {
return [expr {$pagetype == "leaf" || ($pagetype == "internal" && $is_index)}]
@@ -84,6 +157,8 @@ db func isleaf isleaf
db func isinternal isinternal
db func isoverflow isoverflow
+set isCompressed 0
+set compressOverhead 0
set sql { SELECT name, tbl_name FROM sqlite_master WHERE rootpage>0 }
foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] {
@@ -101,10 +176,18 @@ foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] {
sum(isoverflow(pagetype, $is_index)) AS ovfl_pages,
sum(isinternal(pagetype, $is_index) * unused) AS int_unused,
sum(isleaf(pagetype, $is_index) * unused) AS leaf_unused,
- sum(isoverflow(pagetype, $is_index) * unused) AS ovfl_unused
+ sum(isoverflow(pagetype, $is_index) * unused) AS ovfl_unused,
+ sum(pgsize) AS compressed_size
FROM temp.dbstat WHERE name = $name
} break
+ set total_pages [expr {$leaf_pages+$int_pages+$ovfl_pages}]
+ set storage [expr {$total_pages*$pageSize}]
+ if {!$isCompressed && $storage>$compressed_size} {
+ set isCompressed 1
+ set compressOverhead 14
+ }
+
# Column 'gap_cnt' is set to the number of non-contiguous entries in the
# list of pages visited if the b-tree structure is traversed in a top-down
# fashion (each node visited before its child-tree is passed). Any overflow
@@ -138,14 +221,15 @@ foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] {
$int_unused,
$leaf_unused,
$ovfl_unused,
- $gap_cnt
+ $gap_cnt,
+ $compressed_size
);
}
}
proc integerify {real} {
if {[string is double -strict $real]} {
- return [expr {int($real)}]
+ return [expr {wide($real)}]
} else {
return 0
}
@@ -200,7 +284,7 @@ proc divide {num denom} {
# the $where clause determines which subset to analyze.
#
proc subreport {title where} {
- global pageSize file_pgcnt
+ global pageSize file_pgcnt compressOverhead
# Query the in-memory database for the sum of various statistics
# for the subset of tables/indices identified by the WHERE clause in
@@ -224,7 +308,8 @@ proc subreport {title where} {
int(sum(leaf_unused)) AS leaf_unused,
int(sum(int_unused)) AS int_unused,
int(sum(ovfl_unused)) AS ovfl_unused,
- int(sum(gap_cnt)) AS gap_cnt
+ int(sum(gap_cnt)) AS gap_cnt,
+ int(sum(compressed_size)) AS compressed_size
FROM space_used WHERE $where" {} {}
# Output the sub-report title, nicely decorated with * characters.
@@ -274,6 +359,12 @@ proc subreport {title where} {
statline {Percentage of total database} $total_pages_percent
statline {Number of entries} $nleaf
statline {Bytes of storage consumed} $storage
+ if {$compressed_size!=$storage} {
+ set compressed_size [expr {$compressed_size+$compressOverhead*$total_pages}]
+ set pct [expr {$compressed_size*100.0/$storage}]
+ set pct [format {%5.1f%%} $pct]
+ statline {Bytes used after compression} $compressed_size $pct
+ }
statline {Bytes of payload} $payload $payload_percent
statline {Average payload per entry} $avg_payload
statline {Average unused bytes per entry} $avg_unused
@@ -293,16 +384,16 @@ proc subreport {title where} {
statline {Overflow pages used} $ovfl_pages
statline {Total pages used} $total_pages
if {$int_unused>0} {
- set int_unused_percent \
- [percent $int_unused [expr {$int_pages*$pageSize}] {of index space}]
+ set int_unused_percent [
+ percent $int_unused [expr {$int_pages*$pageSize}] {of index space}]
statline "Unused bytes on index pages" $int_unused $int_unused_percent
}
- statline "Unused bytes on primary pages" $leaf_unused \
- [percent $leaf_unused [expr {$leaf_pages*$pageSize}] {of primary space}]
- statline "Unused bytes on overflow pages" $ovfl_unused \
- [percent $ovfl_unused [expr {$ovfl_pages*$pageSize}] {of overflow space}]
- statline "Unused bytes on all pages" $total_unused \
- [percent $total_unused $storage {of all space}]
+ statline "Unused bytes on primary pages" $leaf_unused [
+ percent $leaf_unused [expr {$leaf_pages*$pageSize}] {of primary space}]
+ statline "Unused bytes on overflow pages" $ovfl_unused [
+ percent $ovfl_unused [expr {$ovfl_pages*$pageSize}] {of overflow space}]
+ statline "Unused bytes on all pages" $total_unused [
+ percent $total_unused $storage {of all space}]
return 1
}
@@ -330,7 +421,7 @@ proc autovacuum_overhead {filePages pageSize} {
set ptrsPerPage [expr double($pageSize/5)]
# Return the number of pointer map pages in the database.
- return [expr int(ceil( ($filePages-1.0)/($ptrsPerPage+1.0) ))]
+ return [expr wide(ceil( ($filePages-1.0)/($ptrsPerPage+1.0) ))]
}
@@ -357,17 +448,24 @@ proc autovacuum_overhead {filePages pageSize} {
# (not including sqlite_master)
# user_percent: $user_payload as a percentage of total file size.
-set file_bytes [file size $file_to_analyze]
-set file_pgcnt [expr {$file_bytes/$pageSize}]
+### The following, setting $file_bytes based on the actual size of the file
+### on disk, causes this tool to choke on zipvfs databases. So set it based
+### on the return of [PRAGMA page_count] instead.
+if 0 {
+ set file_bytes [file size $file_to_analyze]
+ set file_pgcnt [expr {$file_bytes/$pageSize}]
+}
+set file_pgcnt [db one {PRAGMA page_count}]
+set file_bytes [expr {$file_pgcnt * $pageSize}]
set av_pgcnt [autovacuum_overhead $file_pgcnt $pageSize]
set av_percent [percent $av_pgcnt $file_pgcnt]
set sql {SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM space_used}
-set inuse_pgcnt [expr int([mem eval $sql])]
+set inuse_pgcnt [expr wide([mem eval $sql])]
set inuse_percent [percent $inuse_pgcnt $file_pgcnt]
-set free_pgcnt [expr $file_pgcnt-$inuse_pgcnt-$av_pgcnt]
+set free_pgcnt [expr {$file_pgcnt-$inuse_pgcnt-$av_pgcnt}]
set free_percent [percent $free_pgcnt $file_pgcnt]
set free_pgcnt2 [db one {PRAGMA freelist_count}]
set free_percent2 [percent $free_pgcnt2 $file_pgcnt]
@@ -403,7 +501,13 @@ statline {Number of tables in the database} $ntable
statline {Number of indices} $nindex
statline {Number of named indices} $nmanindex
statline {Automatically generated indices} $nautoindex
-statline {Size of the file in bytes} $file_bytes
+if {$isCompressed} {
+ statline {Size of uncompressed content in bytes} $file_bytes
+ set efficiency [percent $true_file_size $file_bytes]
+ statline {Size of compressed file on disk} $true_file_size $efficiency
+} else {
+ statline {Size of the file in bytes} $file_bytes
+}
statline {Bytes of user payload stored} $user_payload $user_percent
# Output table rankings
@@ -416,6 +520,24 @@ mem eval {SELECT tblname, count(*) AS cnt,
FROM space_used GROUP BY tblname ORDER BY size+0 DESC, tblname} {} {
statline [string toupper $tblname] $size [percent $size $file_pgcnt]
}
+if {$isCompressed} {
+ puts ""
+ puts "*** Bytes of disk space used after compression ***********************"
+ puts ""
+ set csum 0
+ mem eval {SELECT tblname,
+ int(sum(compressed_size)) +
+ $compressOverhead*sum(int_pages+leaf_pages+ovfl_pages)
+ AS csize
+ FROM space_used GROUP BY tblname ORDER BY csize+0 DESC, tblname} {} {
+ incr csum $csize
+ statline [string toupper $tblname] $csize [percent $csize $true_file_size]
+ }
+ set overhead [expr {$true_file_size - $csum}]
+ if {$overhead>0} {
+ statline {Header and free space} $overhead [percent $overhead $true_file_size]
+ }
+}
# Output subreports
#
@@ -452,11 +574,9 @@ Page size in bytes
Number of pages in the whole file
}
-puts \
-" The number of $pageSize-byte pages that go into forming the complete
+puts " The number of $pageSize-byte pages that go into forming the complete
database"
-puts \
-{
+puts {
Pages that store data
The number of pages that store data, either as primary B*Tree pages or
diff --git a/tool/symbols-mingw.sh b/tool/symbols-mingw.sh
new file mode 100644
index 00000000..bf93eec7
--- /dev/null
+++ b/tool/symbols-mingw.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Run this script in a directory that contains a valid SQLite makefile in
+# order to verify that unintentionally exported symbols.
+#
+make sqlite3.c
+
+echo '****** Exported symbols from a build including RTREE && FTS4 ******'
+gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
+ -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
+ -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
+ sqlite3.c
+nm sqlite3.o | grep " [TD] "
+
+echo '****** Surplus symbols from a build including RTREE & FTS4 ******'
+nm sqlite3.o | grep " [TD] " | grep -v " .*sqlite3_"
+
+echo '****** Dependencies of the core. No extensions. No OS interface *******'
+gcc -c -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
+ -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
+ -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
+ -DSQLITE_OS_OTHER -DSQLITE_THREADSAFE=0 \
+ sqlite3.c
+nm sqlite3.o | grep " U "
+
+echo '****** Dependencies including RTREE & FTS4 *******'
+gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
+ -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
+ -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
+ sqlite3.c
+nm sqlite3.o | grep " U "
diff --git a/tool/symbols.sh b/tool/symbols.sh
index 8aec0056..befffce5 100644
--- a/tool/symbols.sh
+++ b/tool/symbols.sh
@@ -7,18 +7,18 @@ make sqlite3.c
echo '****** Exported symbols from a build including RTREE, FTS4 & ICU ******'
gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT2 \
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
-DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
-DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
-DSQLITE_ENABLE_ICU \
sqlite3.c
-nm sqlite3.o | grep ' T ' | sort -k 3
+nm sqlite3.o | grep ' [TD] ' | sort -k 3
echo '****** Surplus symbols from a build including RTREE, FTS4 & ICU ******'
-nm sqlite3.o | grep ' T ' | grep -v ' sqlite3_'
+nm sqlite3.o | grep ' [TD] ' | grep -v ' .*sqlite3_'
echo '****** Dependencies of the core. No extensions. No OS interface *******'
-gcc -c -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT2 \
+gcc -c -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
-DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
-DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
-DSQLITE_OS_OTHER -DSQLITE_THREADSAFE=0 \
@@ -27,7 +27,7 @@ nm sqlite3.o | grep ' U ' | sort -k 3
echo '****** Dependencies including RTREE & FTS4 *******'
gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
- -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT2 \
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
-DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
-DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
sqlite3.c
diff --git a/tool/tostr.awk b/tool/tostr.awk
index 83c6cc1a..b4f48d3d 100644
--- a/tool/tostr.awk
+++ b/tool/tostr.awk
@@ -3,7 +3,6 @@
# Convert input text into a C string
#
{
- gsub(/\\/,"\\\\");
gsub(/\"/,"\\\"");
print "\"" $0 "\\n\"";
}
diff --git a/tool/warnings-clang.sh b/tool/warnings-clang.sh
new file mode 100644
index 00000000..51084f31
--- /dev/null
+++ b/tool/warnings-clang.sh
@@ -0,0 +1,13 @@
+#/bin/sh
+#
+# Run this script in a directory with a working makefile to check for
+# compiler warnings in SQLite.
+#
+rm -f sqlite3.c
+make sqlite3.c
+echo '************* FTS4 and RTREE ****************'
+scan-build gcc -c -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
+ -DSQLITE_DEBUG sqlite3.c 2>&1 | grep -v 'ANALYZE:'
+echo '********** ENABLE_STAT3. THREADSAFE=0 *******'
+scan-build gcc -c -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \
+ -DSQLITE_DEBUG sqlite3.c 2>&1 | grep -v 'ANALYZE:'
diff --git a/tool/warnings.sh b/tool/warnings.sh
index e1fa2b2d..78cfb55d 100644
--- a/tool/warnings.sh
+++ b/tool/warnings.sh
@@ -3,12 +3,17 @@
# Run this script in a directory with a working makefile to check for
# compiler warnings in SQLite.
#
-make sqlite3.c
+rm -f sqlite3.c
+make sqlite3.c-debug
echo '********** No optimizations. Includes FTS4 and RTREE *********'
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
sqlite3.c
-echo '********** Optimized -O3. Includes FTS4 and RTREE *********'
+echo '********** No optimizations. ENABLE_STAT3. THREADSAFE=0 *******'
+gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
+ -ansi -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \
+ sqlite3.c
+echo '********** Optimized -O3. Includes FTS4 and RTREE ************'
gcc -O3 -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
sqlite3.c