Compare commits

..

1 Commits

Author SHA1 Message Date
drh 9336a521e8 Prototype for an sqlite3_db_log() interface.
FossilOrigin-Name: 658e20f55467a90bcebe5e01cf9f252dbe8bd690
2015-04-22 14:41:19 +00:00
150 changed files with 9123 additions and 17915 deletions
+29 -90
View File
@@ -167,7 +167,7 @@ USE_AMALGAMATION = @USE_AMALGAMATION@
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
callback.lo complete.lo ctime.lo date.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@@ -181,11 +181,10 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
table.lo threads.lo tokenize.lo trigger.lo \
update.lo util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
utf.lo vtab.lo
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
# Object files for the amalgamation.
#
@@ -214,7 +213,6 @@ SRC = \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
$(TOP)/src/fault.c \
@@ -274,7 +272,6 @@ SRC = \
$(TOP)/src/threads.c \
$(TOP)/src/tclsqlite.c \
$(TOP)/src/tokenize.c \
$(TOP)/src/treeview.c \
$(TOP)/src/trigger.c \
$(TOP)/src/utf.c \
$(TOP)/src/update.c \
@@ -295,8 +292,6 @@ SRC = \
$(TOP)/src/wal.h \
$(TOP)/src/walker.c \
$(TOP)/src/where.c \
$(TOP)/src/wherecode.c \
$(TOP)/src/whereexpr.c \
$(TOP)/src/whereInt.h
# Source code for extensions
@@ -343,9 +338,6 @@ SRC += \
SRC += \
$(TOP)/ext/rtree/rtree.h \
$(TOP)/ext/rtree/rtree.c
SRC += \
$(TOP)/ext/ota/sqlite3ota.h \
$(TOP)/ext/ota/sqlite3ota.c
# Generated source code files
@@ -397,13 +389,13 @@ TESTSRC = \
$(TOP)/src/test_server.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
$(TOP)/src/test_stat.c \
$(TOP)/src/test_tclvar.c \
$(TOP)/src/test_thread.c \
$(TOP)/src/test_vfs.c \
$(TOP)/src/test_wsd.c \
$(TOP)/ext/fts3/fts3_term.c \
$(TOP)/ext/fts3/fts3_test.c \
$(TOP)/ext/ota/test_ota.c
$(TOP)/ext/fts3/fts3_test.c
# Statically linked extensions
#
@@ -431,7 +423,6 @@ TESTSRC2 = \
$(TOP)/src/build.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
$(TOP)/src/insert.c \
@@ -458,8 +449,6 @@ TESTSRC2 = \
$(TOP)/src/vdbemem.c \
$(TOP)/src/vdbetrace.c \
$(TOP)/src/where.c \
$(TOP)/src/wherecode.c \
$(TOP)/src/whereexpr.c \
parse.c \
$(TOP)/ext/fts3/fts3.c \
$(TOP)/ext/fts3/fts3_aux.c \
@@ -520,25 +509,6 @@ EXTHDR += \
EXTHDR += \
$(TOP)/ext/rtree/sqlite3rtree.h
# executables needed for testing
#
TESTPROGS = \
testfixture$(TEXE) \
sqlite3$(TEXE) \
sqlite3_analyzer$(TEXE) \
sqldiff$(TEXE)
# Databases containing fuzzer test cases
#
FUZZDATA = \
$(TOP)/test/fuzzdata1.db \
$(TOP)/test/fuzzdata2.db \
$(TOP)/test/fuzzdata3.db
# Standard options to testfixture
#
TESTOPTS = --verbose=file --output=test-out.txt
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
@@ -566,22 +536,19 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h
-o $@ $(TOP)/src/shell.c libsqlite3.la \
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS)
mptester$(TEXE): sqlite3.c $(TOP)/mptest/mptest.c
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
$(TLIBS) -rpath "$(libdir)"
MPTEST1=./mptester$(TEXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
MPTEST2=./mptester$(TEXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
mptest: mptester$(TEXE)
MPTEST1=./mptester$(EXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
MPTEST2=./mptester$(EXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
mptest: mptester$(EXE)
rm -f mptest.db
$(MPTEST1) --journalmode DELETE
$(MPTEST2) --journalmode WAL
@@ -685,9 +652,6 @@ ctime.lo: $(TOP)/src/ctime.c $(HDR)
date.lo: $(TOP)/src/date.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/date.c
dbstat.lo: $(TOP)/src/dbstat.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbstat.c
delete.lo: $(TOP)/src/delete.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/delete.c
@@ -811,9 +775,6 @@ threads.lo: $(TOP)/src/threads.c $(HDR)
tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c
treeview.lo: $(TOP)/src/treeview.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/treeview.c
trigger.lo: $(TOP)/src/trigger.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/trigger.c
@@ -862,12 +823,6 @@ walker.lo: $(TOP)/src/walker.c $(HDR)
where.lo: $(TOP)/src/where.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/where.c
wherecode.lo: $(TOP)/src/wherecode.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wherecode.c
whereexpr.lo: $(TOP)/src/whereexpr.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/whereexpr.c
tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c
@@ -996,52 +951,39 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC)
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
# A very detailed test running most or all test cases
fulltest: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS)
fulltest: testfixture$(TEXE) sqlite3$(TEXE)
./testfixture$(TEXE) $(TOP)/test/all.test
# Really really long testing
soaktest: $(TESTPROGS)
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)
soaktest: testfixture$(TEXE) sqlite3$(TEXE)
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1
# Do extra testing but not everything.
fulltestonly: $(TESTPROGS)
# Do extra testing but not aeverything.
fulltestonly: testfixture$(TEXE) sqlite3$(TEXE)
./testfixture$(TEXE) $(TOP)/test/full.test
# Fuzz testing
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
./fuzzcheck$(TEXE) $(FUZZDATA)
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
valgrind ./fuzzcheck$(TEXE) --cell-size-check --quiet $(FUZZDATA)
# Minimal testing that runs in less than 3 minutes
# This is the common case. Run many tests but not those that take
# a really long time.
#
quicktest: ./testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
test: testfixture$(TEXE) sqlite3$(TEXE)
./testfixture$(TEXE) $(TOP)/test/veryquick.test
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest: $(TESTPROGS) valgrindfuzz
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)
valgrindtest: testfixture$(TEXE) sqlite3$(TEXE)
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind
# A very fast test that checks basic sanity. The name comes from
# the 60s-era electronics testing: "Turn it on and see if smoke
# comes out."
#
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
smoketest: testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
echo "#define TCLSH 2" > $@
echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
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 >> $@
@@ -1151,9 +1093,6 @@ clean:
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f fuzzershell fuzzershell.exe
rm -f fuzzcheck fuzzcheck.exe
rm -f sqldiff sqldiff.exe
distclean: clean
rm -f config.log config.status libtool Makefile sqlite3.pc
+35 -107
View File
@@ -36,13 +36,6 @@ USE_STDCALL = 0
DYNAMIC_SHELL = 0
!ENDIF
# Set this non-0 to enable extra code that attempts to detect misuse of the
# SQLite API.
#
!IFNDEF API_ARMOR
API_ARMOR = 0
!ENDIF
# If necessary, create a list of harmless compiler warnings to disable when
# compiling the various tools. For the SQLite source code itself, warnings,
# if any, will be disabled from within it.
@@ -155,13 +148,6 @@ MEMDEBUG = 0
WIN32HEAP = 0
!ENDIF
# Set this to non-0 to enable OSTRACE() macros, which can be useful when
# debugging.
#
!IFNDEF OSTRACE
OSTRACE = 0
!ENDIF
# Set this to one of the following values to enable various debugging
# features. Each level includes the debugging options from the previous
# levels. Currently, the recognized values for DEBUG are:
@@ -498,24 +484,24 @@ BCC = $(BCC) -DNDEBUG
RCC = $(RCC) -DNDEBUG
!ENDIF
!IF $(DEBUG)>0 || $(API_ARMOR)!=0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!IF $(DEBUG)>0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR
!ENDIF
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG=1
RCC = $(RCC) -DSQLITE_DEBUG=1
TCC = $(TCC) -DSQLITE_DEBUG
RCC = $(RCC) -DSQLITE_DEBUG
!ENDIF
!IF $(DEBUG)>4 || $(OSTRACE)!=0
TCC = $(TCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
!IF $(DEBUG)>4
TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1
!ENDIF
!IF $(DEBUG)>5
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
!ENDIF
# Prevent warnings about "insecure" MSVC runtime library functions
@@ -822,7 +808,7 @@ NAWK = gawk.exe
#
LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
callback.lo complete.lo ctime.lo date.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@@ -835,11 +821,10 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
table.lo threads.lo tokenize.lo trigger.lo \
update.lo util.lo vacuum.lo \
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
utf.lo vtab.lo
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
# Object files for the amalgamation.
#
@@ -879,7 +864,6 @@ SRC1 = \
$(TOP)\src\complete.c \
$(TOP)\src\ctime.c \
$(TOP)\src\date.c \
$(TOP)\src\dbstat.c \
$(TOP)\src\delete.c \
$(TOP)\src\expr.c \
$(TOP)\src\fault.c \
@@ -940,7 +924,6 @@ SRC2 = \
$(TOP)\src\threads.c \
$(TOP)\src\tclsqlite.c \
$(TOP)\src\tokenize.c \
$(TOP)\src\treeview.c \
$(TOP)\src\trigger.c \
$(TOP)\src\utf.c \
$(TOP)\src\update.c \
@@ -961,8 +944,6 @@ SRC2 = \
$(TOP)\src\wal.h \
$(TOP)\src\walker.c \
$(TOP)\src\where.c \
$(TOP)\src\wherecode.c \
$(TOP)\src\whereexpr.c \
$(TOP)\src\whereInt.h
# Source code for extensions
@@ -1005,9 +986,7 @@ SRC4 = \
$(TOP)\ext\icu\sqliteicu.h \
$(TOP)\ext\icu\icu.c \
$(TOP)\ext\rtree\rtree.h \
$(TOP)\ext\rtree\rtree.c \
$(TOP)\ext\ota\sqlite3ota.h \
$(TOP)\ext\ota\sqlite3ota.c
$(TOP)\ext\rtree\rtree.c
# Generated source code files
@@ -1062,13 +1041,13 @@ TESTSRC = \
$(TOP)\src\test_server.c \
$(TOP)\src\test_superlock.c \
$(TOP)\src\test_syscall.c \
$(TOP)\src\test_stat.c \
$(TOP)\src\test_tclvar.c \
$(TOP)\src\test_thread.c \
$(TOP)\src\test_vfs.c \
$(TOP)\src\test_wsd.c \
$(TOP)\ext\fts3\fts3_term.c \
$(TOP)\ext\fts3\fts3_test.c \
$(TOP)\ext\ota\test_ota.c
$(TOP)\ext\fts3\fts3_test.c
# Statically linked extensions
#
@@ -1097,7 +1076,6 @@ TESTSRC2 = \
$(TOP)\src\build.c \
$(TOP)\src\ctime.c \
$(TOP)\src\date.c \
$(TOP)\src\dbstat.c \
$(TOP)\src\expr.c \
$(TOP)\src\func.c \
$(TOP)\src\insert.c \
@@ -1125,8 +1103,6 @@ TESTSRC2 = \
$(TOP)\src\vdbesort.c \
$(TOP)\src\vdbetrace.c \
$(TOP)\src\where.c \
$(TOP)\src\wherecode.c \
$(TOP)\src\whereexpr.c \
parse.c \
$(TOP)\ext\fts3\fts3.c \
$(TOP)\ext\fts3\fts3_aux.c \
@@ -1188,25 +1164,6 @@ EXTHDR = $(EXTHDR) \
EXTHDR = $(EXTHDR) \
$(TOP)\ext\rtree\sqlite3rtree.h
# executables needed for testing
#
TESTPROGS = \
testfixture.exe \
sqlite3.exe \
sqlite3_analyzer.exe \
sqldiff.exe
# Databases containing fuzzer test cases
#
FUZZDATA = \
$(TOP)\test\fuzzdata1.db \
$(TOP)\test\fuzzdata2.db \
$(TOP)\test\fuzzdata3.db
# Standard options to testfixture
#
TESTOPTS = --verbose=file --output=test-out.txt
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
@@ -1223,16 +1180,13 @@ sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
/link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c sqlite3.c
$(LTLINK) $(TOP)\tool\sqldiff.c sqlite3.c
fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h
$(LTLINK) $(NO_WARN) $(TOP)\tool\fuzzershell.c sqlite3.c
fuzzcheck.exe: $(TOP)\test\fuzzcheck.c sqlite3.c sqlite3.h
$(LTLINK) $(NO_WARN) $(TOP)\test\fuzzcheck.c sqlite3.c
$(LTLINK) $(TOP)\tool\fuzzershell.c sqlite3.c
mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
$(LTLINK) $(NO_WARN) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
$(LTLINK) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
/link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20
@@ -1365,9 +1319,6 @@ ctime.lo: $(TOP)\src\ctime.c $(HDR)
date.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
dbstat.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbstat.c
delete.lo: $(TOP)\src\delete.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\delete.c
@@ -1491,9 +1442,6 @@ threads.lo: $(TOP)\src\threads.c $(HDR)
tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\tokenize.c
treeview.lo: $(TOP)\src\treeview.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\treeview.c
trigger.lo: $(TOP)\src\trigger.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c
@@ -1542,12 +1490,6 @@ walker.lo: $(TOP)\src\walker.c $(HDR)
where.lo: $(TOP)\src\where.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\where.c
wherecode.lo: $(TOP)\src\wherecode.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wherecode.c
whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
$(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
@@ -1680,48 +1622,35 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR)
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
extensiontest: testfixture.exe testloadext.dll
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
.\testfixture.exe $(TOP)\test\loadext.test
fulltest: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)
fulltest: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\all.test
soaktest: $(TESTPROGS)
.\testfixture.exe $(TOP)\test\all.test -soak=1 $(TESTOPTS)
soaktest: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\all.test -soak=1
fulltestonly: $(TESTPROGS) fuzztest
fulltestonly: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\full.test
queryplantest: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS)
.\testfixture.exe $(TOP)\test\permutations.test queryplanner
fuzztest: fuzzcheck.exe
.\fuzzcheck.exe $(FUZZDATA)
test: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\veryquick.test
# Minimal testing that runs in less than 3 minutes (on a fast machine)
#
quicktest: testfixture.exe
.\testfixture.exe $(TOP)\test\extraquick.test $(TESTOPTS)
smoketest: testfixture.exe
.\testfixture.exe $(TOP)\test\main.test
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
smoketest: $(TESTPROGS)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
echo #define TCLSH 2 > $@
echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@
copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
copy $(SQLITE3C) + $(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 $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
testloadext.lo: $(TOP)\src\test_loadext.c
@@ -1766,8 +1695,8 @@ speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C)
$(TOP)\test\speedtest1.c $(SQLITE3C)
clean:
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
del /Q *.bsc *.cod *.da *.bb *.bbg gmon.out 2>NUL
del /Q *.exp *.lo *.ilk *.lib *.obj *.pdb 2>NUL
del /Q *.cod *.da *.bb *.bbg gmon.out 2>NUL
del /Q sqlite3.h opcodes.c opcodes.h 2>NUL
del /Q lemon.* lempar.c parse.* 2>NUL
del /Q mkkeywordhash.* keywordhash.h 2>NUL
@@ -1791,7 +1720,6 @@ clean:
del /Q shell.c sqlite3ext.h 2>NUL
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL
# Dynamic link library section.
#
+2 -17
View File
@@ -4,10 +4,6 @@ This repository contains the complete source code for the SQLite database
engine. Some test scripts are also include. However, many other test scripts
and most of the documentation are managed separately.
If you are reading this on a Git mirror someplace, you are doing it wrong.
The [official repository](https://www.sqlite.org/src/) is better. Go there
now.
## Compiling
First create a directory in which to place
@@ -178,7 +174,7 @@ complex code. So there is a lot of complexity in the SQLite implementation.
Key files:
* **sqlite.h.in** - This file defines the public interface to the SQLite
* **sqlite3.h** - This file defines the public interface to the SQLite
library. Readers will need to be familiar with this interface before
trying to understand how the library works internally.
@@ -186,7 +182,7 @@ Key files:
used internally by SQLite.
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
to parse SQL statements, and the actions that are taken at each step
to parse SQL statements, and the actions that are taken at each stop
in the parsing process.
* **vdbe.c** - This file implements the virtual machine that runs
@@ -210,17 +206,6 @@ Key files:
between SQLite and the underlying operating system using the run-time
pluggable VFS interface.
* **shell.c** - This file is not part of the core SQLite library. This
is the file that, when linked against sqlite3.a, generates the
"sqlite3.exe" command-line shell.
* **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It
is not part of the core SQLite library. But as most of the tests in this
repository are written in Tcl, the Tcl language bindings are important.
There are many other source files. Each has a suscinct header comment that
describes its purpose and role within the larger system.
## Contacts
+1 -1
View File
@@ -1 +1 @@
3.8.11
3.8.10
+3 -3
View File
@@ -6,9 +6,9 @@ libsqlite3_la_SOURCES = sqlite3.c
libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
bin_PROGRAMS = sqlite3
sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h
sqlite3_LDADD = @READLINE_LIBS@
sqlite3_CFLAGS = $(AM_CFLAGS)
sqlite3_SOURCES = shell.c sqlite3.h
sqlite3_LDADD = $(top_builddir)/libsqlite3.la @READLINE_LIBS@
sqlite3_DEPENDENCIES = $(top_builddir)/libsqlite3.la
include_HEADERS = sqlite3.h sqlite3ext.h
Vendored
+4439 -2252
View File
File diff suppressed because it is too large Load Diff
-14
View File
@@ -320,20 +320,6 @@ if test "${use_tcl}" = "yes" ; then
fi
fi
# On ubuntu 14.10, $auto_path on tclsh is not quite correct.
# So try again after applying corrections.
if test x"${ac_cv_c_tclconfig}" = x ; then
if test x"$cross_compiling" = xno; then
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'`
do
if test -f "$i/tclConfig.sh" ; then
ac_cv_c_tclconfig="$i"
break
fi
done
fi
fi
# then check for a private Tcl installation
if test x"${ac_cv_c_tclconfig}" = x ; then
for i in \
+16 -26
View File
@@ -508,17 +508,6 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
return SQLITE_OK;
}
/*
** Write an error message into *pzErr
*/
void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){
va_list ap;
sqlite3_free(*pzErr);
va_start(ap, zFormat);
*pzErr = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
}
/*
** Construct one or more SQL statements from the format string given
** and then evaluate those statements. The success code is written
@@ -1050,7 +1039,7 @@ static int fts3ContentColumns(
}else{
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db));
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
}
sqlite3_free(zSql);
@@ -1218,13 +1207,13 @@ static int fts3InitVtab(
}
}
if( iOpt==SizeofArray(aFts4Opt) ){
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
*pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
rc = SQLITE_ERROR;
}else{
switch( iOpt ){
case 0: /* MATCHINFO */
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
*pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
rc = SQLITE_ERROR;
}
bNoDocsize = 1;
@@ -1252,7 +1241,7 @@ static int fts3InitVtab(
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
){
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
*pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
rc = SQLITE_ERROR;
}
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
@@ -1338,7 +1327,7 @@ static int fts3InitVtab(
rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
if( rc==SQLITE_ERROR ){
assert( zPrefix );
sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix);
*pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
}
if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -1420,7 +1409,7 @@ static int fts3InitVtab(
}
for(i=0; i<nNotindexed; i++){
if( azNotindexed[i] ){
sqlite3Fts3ErrMsg(pzErr, "no such column: %s", azNotindexed[i]);
*pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]);
rc = SQLITE_ERROR;
}
}
@@ -1428,7 +1417,7 @@ static int fts3InitVtab(
if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){
char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
rc = SQLITE_ERROR;
sqlite3Fts3ErrMsg(pzErr, "missing %s parameter in fts4 constructor", zMiss);
*pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss);
}
p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc);
p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc);
@@ -1675,7 +1664,7 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
sqlite3Fts3ExprFree(pCsr->pExpr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3_free(pCsr->aMatchinfo);
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
sqlite3_free(pCsr);
return SQLITE_OK;
@@ -2821,7 +2810,7 @@ static int fts3SegReaderCursor(
** calls out here. */
if( iLevel<0 && p->aIndex ){
Fts3SegReader *pSeg = 0;
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
if( rc==SQLITE_OK && pSeg ){
rc = fts3SegReaderCursorAppend(pCsr, pSeg);
}
@@ -3176,7 +3165,7 @@ static int fts3FilterMethod(
/* In case the cursor has been used before, clear it now. */
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3_free(pCsr->aMatchinfo);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
@@ -5074,7 +5063,7 @@ static int fts3EvalNearTrim(
** 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 sqlite3Fts3EvalTestDeferred() for details on testing if a row is
** See fts3EvalTestDeferredAndNear() for details on testing if a row is
** really a match, taking into account deferred tokens and NEAR operators.
*/
static void fts3EvalNextRow(
@@ -5294,7 +5283,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
}
/*
** This function is a helper function for sqlite3Fts3EvalTestDeferred().
** 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.
@@ -5415,7 +5404,7 @@ static int fts3EvalTestExpr(
** Or, if no error occurs and it seems the current row does match the FTS
** query, return 0.
*/
int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){
static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
int rc = *pRc;
int bMiss = 0;
if( rc==SQLITE_OK ){
@@ -5462,7 +5451,7 @@ static int fts3EvalNext(Fts3Cursor *pCsr){
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
pCsr->iPrevId = pExpr->iDocid;
}while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) );
}while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
}
/* Check if the cursor is past the end of the docid range specified
@@ -5623,7 +5612,7 @@ static int fts3EvalGatherStats(
pCsr->iPrevId = pRoot->iDocid;
}while( pCsr->isEof==0
&& pRoot->eType==FTSQUERY_NEAR
&& sqlite3Fts3EvalTestDeferred(pCsr, &rc)
&& fts3EvalTestDeferredAndNear(pCsr, &rc)
);
if( rc==SQLITE_OK && pCsr->isEof==0 ){
@@ -5648,6 +5637,7 @@ static int fts3EvalGatherStats(
fts3EvalNextRow(pCsr, pRoot, &rc);
assert( pRoot->bEof==0 );
}while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
fts3EvalTestDeferredAndNear(pCsr, &rc);
}
}
return rc;
+4 -9
View File
@@ -197,8 +197,6 @@ typedef struct Fts3DeferredToken Fts3DeferredToken;
typedef struct Fts3SegReader Fts3SegReader;
typedef struct Fts3MultiSegReader Fts3MultiSegReader;
typedef struct MatchinfoBuffer MatchinfoBuffer;
/*
** A connection to a fulltext index is an instance of the following
** structure. The xCreate and xConnect methods create an instance
@@ -308,7 +306,9 @@ struct Fts3Cursor {
i64 iMinDocid; /* Minimum docid to return */
i64 iMaxDocid; /* Maximum docid to return */
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */
u32 *aMatchinfo; /* Information about most recent match */
int nMatchinfo; /* Number of elements in aMatchinfo[] */
char *zMatchinfo; /* Matchinfo specification */
};
#define FTS3_EVAL_FILTER 0
@@ -428,9 +428,7 @@ struct Fts3Expr {
u8 bStart; /* True if iDocid is valid */
u8 bDeferred; /* True if this expression is entirely deferred */
/* The following are used by the fts3_snippet.c module. */
int iPhrase; /* Index of this phrase in matchinfo() results */
u32 *aMI; /* See above */
u32 *aMI;
};
/*
@@ -541,7 +539,6 @@ int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
)
/* fts3.c */
void sqlite3Fts3ErrMsg(char**,const char*,...);
int sqlite3Fts3PutVarint(char *, sqlite3_int64);
int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
int sqlite3Fts3GetVarint32(const char *, int *);
@@ -551,7 +548,6 @@ void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
/* fts3_tokenizer.c */
const char *sqlite3Fts3NextToken(const char *, int *);
@@ -567,7 +563,6 @@ void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
const char *, const char *, int, int
);
void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p);
/* fts3_expr.c */
int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
+1 -1
View File
@@ -116,7 +116,7 @@ static int fts3auxConnectMethod(
return SQLITE_OK;
bad_args:
sqlite3Fts3ErrMsg(pzErr, "invalid arguments to fts4aux constructor");
*pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor");
return SQLITE_ERROR;
}
+2 -2
View File
@@ -1022,13 +1022,13 @@ int sqlite3Fts3ExprParse(
sqlite3Fts3ExprFree(*ppExpr);
*ppExpr = 0;
if( rc==SQLITE_TOOBIG ){
sqlite3Fts3ErrMsg(pzErr,
*pzErr = sqlite3_mprintf(
"FTS expression tree is too large (maximum depth %d)",
SQLITE_FTS3_MAX_EXPR_DEPTH
);
rc = SQLITE_ERROR;
}else if( rc==SQLITE_ERROR ){
sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z);
*pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z);
}
}
+48 -227
View File
@@ -27,8 +27,6 @@
#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */
#define FTS3_MATCHINFO_LCS 's' /* nCol values */
#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */
#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */
#define FTS3_MATCHINFO_LHITS_BM 'b' /* nCol*nPhrase values */
/*
** The default value for the second argument to matchinfo().
@@ -90,22 +88,9 @@ struct MatchInfo {
int nCol; /* Number of columns in table */
int nPhrase; /* Number of matchable phrases in query */
sqlite3_int64 nDoc; /* Number of docs in database */
char flag;
u32 *aMatchinfo; /* Pre-allocated buffer */
};
/*
** An instance of this structure is used to manage a pair of buffers, each
** (nElem * sizeof(u32)) bytes in size. See the MatchinfoBuffer code below
** for details.
*/
struct MatchinfoBuffer {
u8 aRef[3];
int nElem;
int bGlobal; /* Set if global data is loaded */
char *zMatchinfo;
u32 aMatchinfo[1];
};
/*
@@ -121,97 +106,6 @@ struct StrBuffer {
};
/*************************************************************************
** Start of MatchinfoBuffer code.
*/
/*
** Allocate a two-slot MatchinfoBuffer object.
*/
static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){
MatchinfoBuffer *pRet;
int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer);
int nStr = (int)strlen(zMatchinfo);
pRet = sqlite3_malloc(nByte + nStr+1);
if( pRet ){
memset(pRet, 0, nByte);
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1);
pRet->nElem = nElem;
pRet->zMatchinfo = ((char*)pRet) + nByte;
memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
pRet->aRef[0] = 1;
}
return pRet;
}
static void fts3MIBufferFree(void *p){
MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
assert( (u32*)p==&pBuf->aMatchinfo[1]
|| (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
);
if( (u32*)p==&pBuf->aMatchinfo[1] ){
pBuf->aRef[1] = 0;
}else{
pBuf->aRef[2] = 0;
}
if( pBuf->aRef[0]==0 && pBuf->aRef[1]==0 && pBuf->aRef[2]==0 ){
sqlite3_free(pBuf);
}
}
static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
void (*xRet)(void*) = 0;
u32 *aOut = 0;
if( p->aRef[1]==0 ){
p->aRef[1] = 1;
aOut = &p->aMatchinfo[1];
xRet = fts3MIBufferFree;
}
else if( p->aRef[2]==0 ){
p->aRef[2] = 1;
aOut = &p->aMatchinfo[p->nElem+2];
xRet = fts3MIBufferFree;
}else{
aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32));
if( aOut ){
xRet = sqlite3_free;
if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
}
}
*paOut = aOut;
return xRet;
}
static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
p->bGlobal = 1;
memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
}
/*
** Free a MatchinfoBuffer object allocated using fts3MIBufferNew()
*/
void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){
if( p ){
assert( p->aRef[0]==1 );
p->aRef[0] = 0;
if( p->aRef[0]==0 && p->aRef[1]==0 && p->aRef[2]==0 ){
sqlite3_free(p);
}
}
}
/*
** End of MatchinfoBuffer code.
*************************************************************************/
/*
** This function is used to help iterate through a position-list. A position
** list is a list of unique integers, sorted from smallest to largest. Each
@@ -248,7 +142,7 @@ static int fts3ExprIterate2(
void *pCtx /* Second argument to pass to callback */
){
int rc; /* Return code */
int eType = pExpr->eType; /* Type of expression node pExpr */
int eType = pExpr->eType; /* Type of expression node pExpr */
if( eType!=FTSQUERY_PHRASE ){
assert( pExpr->pLeft && pExpr->pRight );
@@ -282,7 +176,6 @@ static int fts3ExprIterate(
return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
}
/*
** This is an fts3ExprIterate() callback used while loading the doclists
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
@@ -327,7 +220,8 @@ static int fts3ExprLoadDoclists(
static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
(*(int *)ctx)++;
pExpr->iPhrase = iPhrase;
UNUSED_PARAMETER(pExpr);
UNUSED_PARAMETER(iPhrase);
return SQLITE_OK;
}
static int fts3ExprPhraseCount(Fts3Expr *pExpr){
@@ -548,7 +442,7 @@ static int fts3BestSnippet(
sIter.nSnippet = nSnippet;
sIter.nPhrase = nList;
sIter.iCurrent = -1;
rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter);
rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter);
if( rc==SQLITE_OK ){
/* Set the *pmSeen output variable. */
@@ -849,60 +743,6 @@ static int fts3ColumnlistCount(char **ppCollist){
return nEntry;
}
/*
** This function gathers 'y' or 'b' data for a single phrase.
*/
static void fts3ExprLHits(
Fts3Expr *pExpr, /* Phrase expression node */
MatchInfo *p /* Matchinfo context */
){
Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab;
int iStart;
Fts3Phrase *pPhrase = pExpr->pPhrase;
char *pIter = pPhrase->doclist.pList;
int iCol = 0;
assert( p->flag==FTS3_MATCHINFO_LHITS_BM || p->flag==FTS3_MATCHINFO_LHITS );
if( p->flag==FTS3_MATCHINFO_LHITS ){
iStart = pExpr->iPhrase * p->nCol;
}else{
iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
}
while( 1 ){
int nHit = fts3ColumnlistCount(&pIter);
if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
if( p->flag==FTS3_MATCHINFO_LHITS ){
p->aMatchinfo[iStart + iCol] = (u32)nHit;
}else if( nHit ){
p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
}
}
assert( *pIter==0x00 || *pIter==0x01 );
if( *pIter!=0x01 ) break;
pIter++;
pIter += fts3GetVarint32(pIter, &iCol);
}
}
/*
** Gather the results for matchinfo directives 'y' and 'b'.
*/
static void fts3ExprLHitGather(
Fts3Expr *pExpr,
MatchInfo *p
){
assert( (pExpr->pLeft==0)==(pExpr->pRight==0) );
if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
if( pExpr->pLeft ){
fts3ExprLHitGather(pExpr->pLeft, p);
fts3ExprLHitGather(pExpr->pRight, p);
}else{
fts3ExprLHits(pExpr, p);
}
}
}
/*
** fts3ExprIterate() callback used to collect the "global" matchinfo stats
** for a single query.
@@ -981,12 +821,10 @@ static int fts3MatchinfoCheck(
|| (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize)
|| (cArg==FTS3_MATCHINFO_LCS)
|| (cArg==FTS3_MATCHINFO_HITS)
|| (cArg==FTS3_MATCHINFO_LHITS)
|| (cArg==FTS3_MATCHINFO_LHITS_BM)
){
return SQLITE_OK;
}
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg);
*pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg);
return SQLITE_ERROR;
}
@@ -1006,14 +844,6 @@ static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
nVal = pInfo->nCol;
break;
case FTS3_MATCHINFO_LHITS:
nVal = pInfo->nCol * pInfo->nPhrase;
break;
case FTS3_MATCHINFO_LHITS_BM:
nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
break;
default:
assert( cArg==FTS3_MATCHINFO_HITS );
nVal = pInfo->nCol * pInfo->nPhrase * 3;
@@ -1208,7 +1038,7 @@ static int fts3MatchinfoValues(
sqlite3_stmt *pSelect = 0;
for(i=0; rc==SQLITE_OK && zArg[i]; i++){
pInfo->flag = zArg[i];
switch( zArg[i] ){
case FTS3_MATCHINFO_NPHRASE:
if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase;
@@ -1268,14 +1098,6 @@ static int fts3MatchinfoValues(
}
break;
case FTS3_MATCHINFO_LHITS_BM:
case FTS3_MATCHINFO_LHITS: {
int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
memset(pInfo->aMatchinfo, 0, nZero);
fts3ExprLHitGather(pCsr->pExpr, pInfo);
break;
}
default: {
Fts3Expr *pExpr;
assert( zArg[i]==FTS3_MATCHINFO_HITS );
@@ -1288,7 +1110,6 @@ static int fts3MatchinfoValues(
if( rc!=SQLITE_OK ) break;
}
rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
sqlite3Fts3EvalTestDeferred(pCsr, &rc);
if( rc!=SQLITE_OK ) break;
}
(void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo);
@@ -1308,8 +1129,7 @@ static int fts3MatchinfoValues(
** Populate pCsr->aMatchinfo[] with data for the current row. The
** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32).
*/
static void fts3GetMatchinfo(
sqlite3_context *pCtx, /* Return results here */
static int fts3GetMatchinfo(
Fts3Cursor *pCsr, /* FTS3 Cursor object */
const char *zArg /* Second argument to matchinfo() function */
){
@@ -1318,9 +1138,6 @@ static void fts3GetMatchinfo(
int rc = SQLITE_OK;
int bGlobal = 0; /* Collect 'global' stats as well as local */
u32 *aOut = 0;
void (*xDestroyOut)(void*) = 0;
memset(&sInfo, 0, sizeof(MatchInfo));
sInfo.pCursor = pCsr;
sInfo.nCol = pTab->nColumn;
@@ -1328,18 +1145,21 @@ static void fts3GetMatchinfo(
/* If there is cached matchinfo() data, but the format string for the
** cache does not match the format string for this request, discard
** the cached data. */
if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
pCsr->pMIBuffer = 0;
if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){
assert( pCsr->aMatchinfo );
sqlite3_free(pCsr->aMatchinfo);
pCsr->zMatchinfo = 0;
pCsr->aMatchinfo = 0;
}
/* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the
/* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the
** matchinfo function has been called for this query. In this case
** allocate the array used to accumulate the matchinfo data and
** initialize those elements that are constant for every row.
*/
if( pCsr->pMIBuffer==0 ){
if( pCsr->aMatchinfo==0 ){
int nMatchinfo = 0; /* Number of u32 elements in match-info */
int nArg; /* Bytes in zArg */
int i; /* Used to iterate through zArg */
/* Determine the number of phrases in the query */
@@ -1348,46 +1168,30 @@ static void fts3GetMatchinfo(
/* Determine the number of integers in the buffer returned by this call. */
for(i=0; zArg[i]; i++){
char *zErr = 0;
if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){
sqlite3_result_error(pCtx, zErr, -1);
sqlite3_free(zErr);
return;
}
nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]);
}
/* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */
pCsr->pMIBuffer = fts3MIBufferNew(nMatchinfo, zArg);
if( !pCsr->pMIBuffer ) rc = SQLITE_NOMEM;
nArg = (int)strlen(zArg);
pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1);
if( !pCsr->aMatchinfo ) return SQLITE_NOMEM;
pCsr->zMatchinfo = (char *)&pCsr->aMatchinfo[nMatchinfo];
pCsr->nMatchinfo = nMatchinfo;
memcpy(pCsr->zMatchinfo, zArg, nArg+1);
memset(pCsr->aMatchinfo, 0, sizeof(u32)*nMatchinfo);
pCsr->isMatchinfoNeeded = 1;
bGlobal = 1;
}
if( rc==SQLITE_OK ){
xDestroyOut = fts3MIBufferAlloc(pCsr->pMIBuffer, &aOut);
if( xDestroyOut==0 ){
rc = SQLITE_NOMEM;
}
}
if( rc==SQLITE_OK ){
sInfo.aMatchinfo = aOut;
sInfo.nPhrase = pCsr->nPhrase;
sInfo.aMatchinfo = pCsr->aMatchinfo;
sInfo.nPhrase = pCsr->nPhrase;
if( pCsr->isMatchinfoNeeded ){
rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg);
if( bGlobal ){
fts3MIBufferSetGlobal(pCsr->pMIBuffer);
}
pCsr->isMatchinfoNeeded = 0;
}
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pCtx, rc);
if( xDestroyOut ) xDestroyOut(aOut);
}else{
int n = pCsr->pMIBuffer->nElem * sizeof(u32);
sqlite3_result_blob(pCtx, aOut, n, xDestroyOut);
}
return rc;
}
/*
@@ -1593,7 +1397,7 @@ void sqlite3Fts3Offsets(
*/
sCtx.iCol = iCol;
sCtx.iTerm = 0;
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx);
/* Retreive the text stored in column iCol. If an SQL NULL is stored
** in column iCol, jump immediately to the next iteration of the loop.
@@ -1685,9 +1489,19 @@ void sqlite3Fts3Matchinfo(
const char *zArg /* Second arg to matchinfo() function */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc;
int i;
const char *zFormat;
if( zArg ){
for(i=0; zArg[i]; i++){
char *zErr = 0;
if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){
sqlite3_result_error(pContext, zErr, -1);
sqlite3_free(zErr);
return;
}
}
zFormat = zArg;
}else{
zFormat = FTS3_MATCHINFO_DEFAULT;
@@ -1696,10 +1510,17 @@ void sqlite3Fts3Matchinfo(
if( !pCsr->pExpr ){
sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC);
return;
}
/* Retrieve matchinfo() data. */
rc = fts3GetMatchinfo(pCsr, zFormat);
sqlite3Fts3SegmentsClose(pTab);
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pContext, rc);
}else{
/* Retrieve matchinfo() data. */
fts3GetMatchinfo(pContext, pCsr, zFormat);
sqlite3Fts3SegmentsClose(pTab);
int n = pCsr->nMatchinfo * sizeof(u32);
sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT);
}
}
+1 -1
View File
@@ -81,7 +81,7 @@ static int fts3termConnectMethod(
/* The user should specify a single argument - the name of an fts3 table. */
if( argc!=4 ){
sqlite3Fts3ErrMsg(pzErr,
*pzErr = sqlite3_mprintf(
"wrong number of arguments to fts4term constructor"
);
return SQLITE_ERROR;
+1 -1
View File
@@ -85,7 +85,7 @@ static int fts3tokQueryTokenizer(
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
if( !p ){
sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName);
*pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
return SQLITE_ERROR;
}
+2 -2
View File
@@ -172,7 +172,7 @@ int sqlite3Fts3InitTokenizer(
m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1);
if( !m ){
sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z);
*pzErr = sqlite3_mprintf("unknown tokenizer: %s", z);
rc = SQLITE_ERROR;
}else{
char const **aArg = 0;
@@ -195,7 +195,7 @@ int sqlite3Fts3InitTokenizer(
rc = m->xCreate(iArg, aArg, ppTok);
assert( rc!=SQLITE_OK || *ppTok );
if( rc!=SQLITE_OK ){
sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer");
*pzErr = sqlite3_mprintf("unknown tokenizer");
}else{
(*ppTok)->pModule = m;
}
+6 -7
View File
@@ -326,7 +326,7 @@ static int fts3SqlStmt(
/* 25 */ "",
/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'",
/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'",
/* This statement is used to determine which level to read the input from
** when performing an incremental merge. It returns the absolute level number
@@ -3444,8 +3444,7 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
if( rc==SQLITE_OK ){
int rc2;
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
sqlite3_bind_int(pAllLangid, 2, p->nIndex);
sqlite3_bind_int(pAllLangid, 1, p->nIndex);
while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
int i;
int iLangid = sqlite3_column_int(pAllLangid, 0);
@@ -4777,7 +4776,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
pHint->n = i;
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
i += fts3GetVarint32(&pHint->a[i], pnInput);
if( i!=nHint ) return FTS_CORRUPT_VTAB;
if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
return SQLITE_OK;
}
@@ -5145,8 +5144,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
if( rc==SQLITE_OK ){
int rc2;
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
sqlite3_bind_int(pAllLangid, 2, p->nIndex);
sqlite3_bind_int(pAllLangid, 1, p->nIndex);
while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
int iLangid = sqlite3_column_int(pAllLangid, 0);
int i;
@@ -5159,6 +5157,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
}
/* This block calculates the checksum according to the %_content table */
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
if( rc==SQLITE_OK ){
sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
sqlite3_stmt *pStmt = 0;
@@ -5255,7 +5254,7 @@ static int fts3DoIntegrityCheck(
int rc;
int bOk = 0;
rc = fts3IntegrityCheck(p, &bOk);
if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB;
return rc;
}
-122
View File
@@ -1,122 +0,0 @@
/*
** 2014 August 30
**
** 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 a command-line application that uses the OTA
** extension. See the usage() function below for an explanation.
*/
#include "sqlite3ota.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
** Print a usage message and exit.
*/
void usage(const char *zArgv0){
fprintf(stderr,
"Usage: %s [-step NSTEP] TARGET-DB OTA-DB\n"
"\n"
" Argument OTA-DB must be an OTA database containing an update suitable for\n"
" target database TARGET-DB. If NSTEP is set to less than or equal to zero\n"
" (the default value), this program attempts to apply the entire update to\n"
" the target database.\n"
"\n"
" If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n"
" to sqlite3ota_step(). If the OTA update has not been completely applied\n"
" after the NSTEP'th call is made, the state is saved in the database OTA-DB\n"
" and the program exits. Subsequent invocations of this (or any other OTA)\n"
" application will use this state to resume applying the OTA update to the\n"
" target db.\n"
"\n"
, zArgv0);
exit(1);
}
void report_default_vfs(){
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName);
}
void report_ota_vfs(sqlite3ota *pOta){
sqlite3 *db = sqlite3ota_db(pOta, 0);
if( db ){
char *zName = 0;
sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName);
if( zName ){
fprintf(stdout, "using vfs \"%s\"\n", zName);
}else{
fprintf(stdout, "vfs name not available\n");
}
sqlite3_free(zName);
}
}
int main(int argc, char **argv){
int i;
const char *zTarget; /* Target database to apply OTA to */
const char *zOta; /* Database containing OTA */
char *zErrmsg; /* Error message, if any */
sqlite3ota *pOta; /* OTA handle */
int nStep = 0; /* Maximum number of step() calls */
int rc;
sqlite3_int64 nProgress = 0;
/* Process command line arguments. Following this block local variables
** zTarget, zOta and nStep are all set. */
if( argc==5 ){
int nArg1 = strlen(argv[1]);
if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]);
nStep = atoi(argv[2]);
}else if( argc!=3 ){
usage(argv[0]);
}
zTarget = argv[argc-2];
zOta = argv[argc-1];
report_default_vfs();
/* Open an OTA handle. If nStep is less than or equal to zero, call
** sqlite3ota_step() until either the OTA has been completely applied
** or an error occurs. Or, if nStep is greater than zero, call
** sqlite3ota_step() a maximum of nStep times. */
pOta = sqlite3ota_open(zTarget, zOta);
report_ota_vfs(pOta);
for(i=0; (nStep<=0 || i<nStep) && sqlite3ota_step(pOta)==SQLITE_OK; i++);
nProgress = sqlite3ota_progress(pOta);
rc = sqlite3ota_close(pOta, &zErrmsg);
/* Let the user know what happened. */
switch( rc ){
case SQLITE_OK:
fprintf(stdout,
"SQLITE_OK: ota update incomplete (%lld operations so far)\n",
nProgress
);
break;
case SQLITE_DONE:
fprintf(stdout,
"SQLITE_DONE: ota update completed (%lld operations)\n",
nProgress
);
break;
default:
fprintf(stderr, "error=%d: %s\n", rc, zErrmsg);
break;
}
sqlite3_free(zErrmsg);
return (rc==SQLITE_OK || rc==SQLITE_DONE) ? 0 : 1;
}
-680
View File
@@ -1,680 +0,0 @@
# 2014 August 30
#
# 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota1
db close
sqlite3_shutdown
sqlite3_config_uri 1
# Create a simple OTA database. That expects to write to a table:
#
# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
#
proc create_ota1 {filename} {
forcedelete $filename
sqlite3 ota1 $filename
ota1 eval {
CREATE TABLE data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t1 VALUES(2, 'two', 'three', 0);
INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0);
}
ota1 close
return $filename
}
# Create a simple OTA database. That expects to write to a table:
#
# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
#
# This OTA includes both insert and delete operations.
#
proc create_ota4 {filename} {
forcedelete $filename
sqlite3 ota1 $filename
ota1 eval {
CREATE TABLE data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t1 VALUES(2, NULL, 5, 1);
INSERT INTO data_t1 VALUES(3, 8, 9, 0);
INSERT INTO data_t1 VALUES(4, NULL, 11, 1);
}
ota1 close
return $filename
}
#
# Create a simple OTA database. That expects to write to a table:
#
# CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY);
#
# This OTA includes both insert and delete operations.
#
proc create_ota4b {filename} {
forcedelete $filename
sqlite3 ota1 $filename
ota1 eval {
CREATE TABLE data_t1(c, b, '(a)', ota_control);
INSERT INTO data_t1 VALUES(3, 2, 1, 0);
INSERT INTO data_t1 VALUES(5, NULL, 2, 1);
INSERT INTO data_t1 VALUES(9, 8, 3, 0);
INSERT INTO data_t1 VALUES(11, NULL, 4, 1);
}
ota1 close
return $filename
}
# Create a simple OTA database. That expects to write to a table:
#
# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
#
# This OTA includes update statements.
#
proc create_ota5 {filename} {
forcedelete $filename
sqlite3 ota5 $filename
ota5 eval {
CREATE TABLE data_t1(a, b, c, d, ota_control);
INSERT INTO data_t1 VALUES(1, NULL, NULL, 5, '...x'); -- SET d = 5
INSERT INTO data_t1 VALUES(2, NULL, 10, 5, '..xx'); -- SET c=10, d = 5
INSERT INTO data_t1 VALUES(3, 11, NULL, NULL, '.x..'); -- SET b=11
}
ota5 close
return $filename
}
# Run the OTA in file $ota on target database $target until completion.
#
proc run_ota {target ota} {
sqlite3ota ota $target $ota
while 1 {
set rc [ota step]
if {$rc!="SQLITE_OK"} break
}
ota close
}
proc step_ota {target ota} {
while 1 {
sqlite3ota ota $target $ota
set rc [ota step]
ota close
if {$rc != "SQLITE_OK"} break
}
set rc
}
# Same as [step_ota], except using a URI to open the target db.
#
proc step_ota_uri {target ota} {
while 1 {
sqlite3ota ota file:$target?xyz=&abc=123 $ota
set rc [ota step]
ota close
if {$rc != "SQLITE_OK"} break
}
set rc
}
# Same as [step_ota], except using an external state database - "state.db"
#
proc step_ota_state {target ota} {
while 1 {
sqlite3ota ota $target $ota state.db
set rc [ota step]
ota close
if {$rc != "SQLITE_OK"} break
}
set rc
}
proc dbfilecksum {file} {
sqlite3 ck $file
set cksum [dbcksum ck main]
ck close
set cksum
}
foreach {tn3 create_vfs destroy_vfs} {
1 {} {}
2 {
sqlite3ota_create_vfs -default myota ""
} {
sqlite3ota_destroy_vfs myota
}
} {
eval $create_vfs
foreach {tn2 cmd} {
1 run_ota
2 step_ota 3 step_ota_uri 4 step_ota_state
} {
foreach {tn schema} {
1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
}
2 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b);
}
3 {
CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
}
4 {
CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
CREATE INDEX i1 ON t1(b);
}
5 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)) WITHOUT ROWID;
CREATE INDEX i1 ON t1(b);
}
6 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(c)) WITHOUT ROWID;
CREATE INDEX i1 ON t1(b, a);
}
7 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b, c);
CREATE INDEX i2 ON t1(c, b);
CREATE INDEX i3 ON t1(a, b, c, a, b, c);
}
8 {
CREATE TABLE t1(a PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b, c);
CREATE INDEX i2 ON t1(c, b);
CREATE INDEX i3 ON t1(a, b, c, a, b, c);
}
9 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c));
CREATE INDEX i1 ON t1(b);
}
10 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b DESC);
}
11 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b DESC, a ASC, c DESC);
}
12 {
CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID;
}
13 {
CREATE TABLE t1(a INT, b, c, PRIMARY KEY(a DESC)) WITHOUT ROWID;
}
14 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a DESC, c)) WITHOUT ROWID;
CREATE INDEX i1 ON t1(b);
}
15 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c DESC)) WITHOUT ROWID;
CREATE INDEX i1 ON t1(b);
}
16 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(c DESC, a)) WITHOUT ROWID;
CREATE INDEX i1 ON t1(b DESC, c, a);
}
} {
reset_db
execsql $schema
create_ota1 ota.db
set check [dbfilecksum ota.db]
forcedelete state.db
do_test $tn3.1.$tn2.$tn.1 {
$cmd test.db ota.db
} {SQLITE_DONE}
do_execsql_test $tn3.1.$tn2.$tn.2 { SELECT * FROM t1 ORDER BY a ASC } {
1 2 3
2 two three
3 {} 8.2
}
do_execsql_test $tn3.1.$tn2.$tn.3 { SELECT * FROM t1 ORDER BY b ASC } {
3 {} 8.2
1 2 3
2 two three
}
do_execsql_test $tn3.1.$tn2.$tn.4 { SELECT * FROM t1 ORDER BY c ASC } {
1 2 3
3 {} 8.2
2 two three
}
do_execsql_test $tn3.1.$tn2.$tn.5 { PRAGMA integrity_check } ok
if {$cmd=="step_ota_state"} {
do_test $tn3.1.$tn2.$tn.6 { file exists state.db } 1
do_test $tn3.1.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 1
} else {
do_test $tn3.1.$tn2.$tn.8 { file exists state.db } 0
do_test $tn3.1.$tn2.$tn.9 { expr {$check == [dbfilecksum ota.db]} } 0
}
}
}
#-------------------------------------------------------------------------
# Check that an OTA cannot be applied to a table that has no PK.
#
# UPDATE: At one point OTA required that all tables featured either
# explicit IPK columns or were declared WITHOUT ROWID. This has been
# relaxed so that external PRIMARY KEYs on tables with automatic rowids
# are now allowed.
#
# UPDATE 2: Tables without any PRIMARY KEY declaration are now allowed.
# However the input table must feature an "ota_rowid" column.
#
reset_db
create_ota1 ota.db
do_execsql_test $tn3.2.1 { CREATE TABLE t1(a, b, c) }
do_test $tn3.2.2 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_ERROR}
do_test $tn3.2.3 {
list [catch { ota close } msg] $msg
} {1 {SQLITE_ERROR - table data_t1 requires ota_rowid column}}
reset_db
do_execsql_test $tn3.2.4 { CREATE TABLE t1(a PRIMARY KEY, b, c) }
do_test $tn3.2.5 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_OK}
do_test $tn3.2.6 {
list [catch { ota close } msg] $msg
} {0 SQLITE_OK}
#-------------------------------------------------------------------------
# Check that if a UNIQUE constraint is violated the current and all
# subsequent [ota step] calls return SQLITE_CONSTRAINT. And that the OTA
# transaction is rolled back by the [ota close] that deletes the ota
# handle.
#
foreach {tn errcode errmsg schema} {
1 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.a" {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
INSERT INTO t1 VALUES(3, 2, 1);
}
2 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.c" {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE);
INSERT INTO t1 VALUES(4, 2, 'three');
}
3 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.a" {
CREATE TABLE t1(a PRIMARY KEY, b, c);
INSERT INTO t1 VALUES(3, 2, 1);
}
4 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.c" {
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
INSERT INTO t1 VALUES(4, 2, 'three');
}
} {
reset_db
execsql $schema
set cksum [dbcksum db main]
do_test $tn3.3.$tn.1 {
create_ota1 ota.db
sqlite3ota ota test.db ota.db
while {[set res [ota step]]=="SQLITE_OK"} {}
set res
} $errcode
do_test $tn3.3.$tn.2 { ota step } $errcode
do_test $tn3.3.$tn.3 {
list [catch { ota close } msg] $msg
} [list 1 "$errcode - $errmsg"]
do_test $tn3.3.$tn.4 { dbcksum db main } $cksum
}
#-------------------------------------------------------------------------
#
foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state } {
foreach {tn schema} {
1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
}
2 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b);
}
3 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b);
CREATE INDEX i2 ON t1(c, b);
CREATE INDEX i3 ON t1(c, b, c);
}
4 {
CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID;
CREATE INDEX i1 ON t1(b);
CREATE INDEX i2 ON t1(c, b);
CREATE INDEX i3 ON t1(c, b, c);
}
5 {
CREATE TABLE t1(a INT PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b);
CREATE INDEX i2 ON t1(c, b);
CREATE INDEX i3 ON t1(c, b, c);
}
6 {
CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c);
CREATE INDEX i1 ON t1(b DESC);
CREATE INDEX i2 ON t1(c, b);
CREATE INDEX i3 ON t1(c DESC, b, c);
}
7 {
CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID;
CREATE INDEX i1 ON t1(b);
CREATE INDEX i2 ON t1(c, b);
CREATE INDEX i3 ON t1(c, b, c);
}
} {
reset_db
execsql $schema
execsql {
INSERT INTO t1 VALUES(2, 'hello', 'world');
INSERT INTO t1 VALUES(4, 'hello', 'planet');
INSERT INTO t1 VALUES(6, 'hello', 'xyz');
}
create_ota4 ota.db
set check [dbfilecksum ota.db]
forcedelete state.db
do_test $tn3.4.$tn2.$tn.1 {
$cmd test.db ota.db
} {SQLITE_DONE}
do_execsql_test $tn3.4.$tn2.$tn.2 {
SELECT * FROM t1 ORDER BY a ASC;
} {
1 2 3
3 8 9
6 hello xyz
}
do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok
if {$cmd=="step_ota_state"} {
do_test $tn3.4.$tn2.$tn.4 { file exists state.db } 1
do_test $tn3.4.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1
} else {
do_test $tn3.4.$tn2.$tn.6 { file exists state.db } 0
do_test $tn3.4.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0
}
}
}
foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state} {
foreach {tn schema} {
1 {
CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY);
CREATE INDEX i1 ON t1(c, b);
}
2 {
CREATE TABLE t1(c, b, '(a)' PRIMARY KEY);
}
3 {
CREATE TABLE t1(c, b, '(a)' PRIMARY KEY) WITHOUT ROWID;
}
} {
reset_db
execsql $schema
execsql {
INSERT INTO t1('(a)', b, c) VALUES(2, 'hello', 'world');
INSERT INTO t1('(a)', b, c) VALUES(4, 'hello', 'planet');
INSERT INTO t1('(a)', b, c) VALUES(6, 'hello', 'xyz');
}
create_ota4b ota.db
set check [dbfilecksum ota.db]
forcedelete state.db
do_test $tn3.5.$tn2.$tn.1 {
$cmd test.db ota.db
} {SQLITE_DONE}
do_execsql_test $tn3.5.$tn2.$tn.2 {
SELECT * FROM t1 ORDER BY "(a)" ASC;
} {
3 2 1
9 8 3
xyz hello 6
}
do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok
if {$cmd=="step_ota_state"} {
do_test $tn3.5.$tn2.$tn.4 { file exists state.db } 1
do_test $tn3.5.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1
} else {
do_test $tn3.5.$tn2.$tn.6 { file exists state.db } 0
do_test $tn3.5.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0
}
}
}
#-------------------------------------------------------------------------
#
foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state} {
foreach {tn schema} {
1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
}
2 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
CREATE INDEX i1 ON t1(d);
CREATE INDEX i2 ON t1(d, c);
CREATE INDEX i3 ON t1(d, c, b);
CREATE INDEX i4 ON t1(b);
CREATE INDEX i5 ON t1(c);
CREATE INDEX i6 ON t1(c, b);
}
3 {
CREATE TABLE t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID;
CREATE INDEX i1 ON t1(d);
CREATE INDEX i2 ON t1(d, c);
CREATE INDEX i3 ON t1(d, c, b);
CREATE INDEX i4 ON t1(b);
CREATE INDEX i5 ON t1(c);
CREATE INDEX i6 ON t1(c, b);
}
4 {
CREATE TABLE t1(a PRIMARY KEY, b, c, d);
CREATE INDEX i1 ON t1(d);
CREATE INDEX i2 ON t1(d, c);
CREATE INDEX i3 ON t1(d, c, b);
CREATE INDEX i4 ON t1(b);
CREATE INDEX i5 ON t1(c);
CREATE INDEX i6 ON t1(c, b);
}
} {
reset_db
execsql $schema
execsql {
INSERT INTO t1 VALUES(1, 2, 3, 4);
INSERT INTO t1 VALUES(2, 5, 6, 7);
INSERT INTO t1 VALUES(3, 8, 9, 10);
}
create_ota5 ota.db
set check [dbfilecksum ota.db]
forcedelete state.db
do_test $tn3.5.$tn2.$tn.1 {
$cmd test.db ota.db
} {SQLITE_DONE}
do_execsql_test $tn3.5.$tn2.$tn.2 {
SELECT * FROM t1 ORDER BY a ASC;
} {
1 2 3 5
2 5 10 5
3 11 9 10
}
do_execsql_test $tn3.6.$tn2.$tn.3 { PRAGMA integrity_check } ok
if {$cmd=="step_ota_state"} {
do_test $tn3.6.$tn2.$tn.4 { file exists state.db } 1
do_test $tn3.6.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1
} else {
do_test $tn3.6.$tn2.$tn.6 { file exists state.db } 0
do_test $tn3.6.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0
}
}
}
#-------------------------------------------------------------------------
# Test some error cases:
#
# * A virtual table with no ota_rowid column.
# * A no-PK table with no ota_rowid column.
# * A PK table with an ota_rowid column.
#
# 6: An update string of the wrong length
#
ifcapable fts3 {
foreach {tn schema error} {
1 {
CREATE TABLE t1(a, b);
CREATE TABLE ota.data_t1(a, b, ota_control);
} {SQLITE_ERROR - table data_t1 requires ota_rowid column}
2 {
CREATE VIRTUAL TABLE t1 USING fts4(a, b);
CREATE TABLE ota.data_t1(a, b, ota_control);
} {SQLITE_ERROR - table data_t1 requires ota_rowid column}
3 {
CREATE TABLE t1(a PRIMARY KEY, b);
CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control);
} {SQLITE_ERROR - table data_t1 may not have ota_rowid column}
4 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control);
} {SQLITE_ERROR - table data_t1 may not have ota_rowid column}
5 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control);
} {SQLITE_ERROR - table data_t1 may not have ota_rowid column}
6 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_control);
INSERT INTO ota.data_t1 VALUES(1, 2, 'x.x');
} {SQLITE_ERROR - invalid ota_control value}
7 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_control);
INSERT INTO ota.data_t1 VALUES(1, 2, NULL);
} {SQLITE_ERROR - invalid ota_control value}
8 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_control);
INSERT INTO ota.data_t1 VALUES(1, 2, 4);
} {SQLITE_ERROR - invalid ota_control value}
9 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_control);
INSERT INTO ota.data_t1 VALUES(1, 2, 2);
} {SQLITE_ERROR - invalid ota_control value}
10 {
CREATE TABLE t2(a, b);
CREATE TABLE ota.data_t1(a, b, ota_control);
INSERT INTO ota.data_t1 VALUES(1, 2, 2);
} {SQLITE_ERROR - no such table: t1}
11 {
CREATE TABLE ota.data_t2(a, b, ota_control);
INSERT INTO ota.data_t2 VALUES(1, 2, 2);
} {SQLITE_ERROR - no such table: t2}
} {
reset_db
forcedelete ota.db
execsql { ATTACH 'ota.db' AS ota }
execsql $schema
do_test $tn3.7.$tn {
list [catch { run_ota test.db ota.db } msg] $msg
} [list 1 $error]
}
}
# Test that an OTA database containing no input tables is handled
# correctly.
reset_db
forcedelete ota.db
do_test $tn3.8 {
list [catch { run_ota test.db ota.db } msg] $msg
} {0 SQLITE_DONE}
# Test that OTA can update indexes containing NULL values.
#
reset_db
forcedelete ota.db
do_execsql_test $tn3.9.1 {
CREATE TABLE t1(a PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b, c);
INSERT INTO t1 VALUES(1, 1, NULL);
INSERT INTO t1 VALUES(2, NULL, 2);
INSERT INTO t1 VALUES(3, NULL, NULL);
ATTACH 'ota.db' AS ota;
CREATE TABLE ota.data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(1, NULL, NULL, 1);
INSERT INTO data_t1 VALUES(3, NULL, NULL, 1);
} {}
do_test $tn3.9.2 {
list [catch { run_ota test.db ota.db } msg] $msg
} {0 SQLITE_DONE}
do_execsql_test $tn3.9.3 {
SELECT * FROM t1
} {2 {} 2}
do_execsql_test $tn3.9.4 { PRAGMA integrity_check } {ok}
catch { db close }
eval $destroy_vfs
}
finish_test
-188
View File
@@ -1,188 +0,0 @@
# 2014 August 30
#
# 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota10
#--------------------------------------------------------------------
# Test that UPDATE commands work even if the input columns are in a
# different order to the output columns.
#
do_execsql_test 1.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
INSERT INTO t1 VALUES(1, 'b', 'c');
}
proc apply_ota {sql} {
forcedelete ota.db
sqlite3 db2 ota.db
db2 eval $sql
db2 close
sqlite3ota ota test.db ota.db
while { [ota step]=="SQLITE_OK" } {}
ota close
}
do_test 1.1 {
apply_ota {
CREATE TABLE data_t1(a, c, b, ota_control);
INSERT INTO data_t1 VALUES(1, 'xxx', NULL, '.x.');
}
db eval { SELECT * FROM t1 }
} {1 b xxx}
#--------------------------------------------------------------------
# Test that the hidden languageid column of an fts4 table can be
# written.
#
ifcapable fts3 {
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE ft USING fts4(a, b, languageid='langid');
}
do_test 2.1 {
apply_ota {
CREATE TABLE data_ft(a, b, ota_rowid, langid, ota_control);
INSERT INTO data_ft VALUES('a', 'b', 22, 1, 0); -- insert
INSERT INTO data_ft VALUES('a', 'b', 23, 10, 0); -- insert
INSERT INTO data_ft VALUES('a', 'b', 24, 100, 0); -- insert
}
db eval { SELECT a, b, rowid, langid FROM ft }
} [list {*}{
a b 22 1
a b 23 10
a b 24 100
}]
# Or not - this data_xxx table has no langid column, so langid
# defaults to 0.
#
do_test 2.2 {
apply_ota {
CREATE TABLE data_ft(a, b, ota_rowid, ota_control);
INSERT INTO data_ft VALUES('a', 'b', 25, 0); -- insert
}
db eval { SELECT a, b, rowid, langid FROM ft }
} [list {*}{
a b 22 1
a b 23 10
a b 24 100
a b 25 0
}]
# Update langid.
#
do_test 2.3 {
apply_ota {
CREATE TABLE data_ft(a, b, ota_rowid, langid, ota_control);
INSERT INTO data_ft VALUES(NULL, NULL, 23, 50, '..x');
INSERT INTO data_ft VALUES(NULL, NULL, 25, 500, '..x');
}
db eval { SELECT a, b, rowid, langid FROM ft }
} [list {*}{
a b 22 1
a b 23 50
a b 24 100
a b 25 500
}]
}
#--------------------------------------------------------------------
# Test that if writing a hidden virtual table column is an error,
# attempting to do so via ota is also an error.
#
ifcapable fts3 {
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE xt USING fts4(a);
}
do_test 3.1 {
list [catch {
apply_ota {
CREATE TABLE data_xt(a, xt, ota_rowid, ota_control);
INSERT INTO data_xt VALUES('a', 'b', 1, 0);
}
} msg] $msg
} {1 {SQLITE_ERROR - SQL logic error or missing database}}
}
#--------------------------------------------------------------------
# Test that it is not possible to violate a NOT NULL constraint by
# applying an OTA update.
#
do_execsql_test 4.1 {
CREATE TABLE t2(a INTEGER NOT NULL, b TEXT NOT NULL, c PRIMARY KEY);
CREATE TABLE t3(a INTEGER NOT NULL, b TEXT NOT NULL, c INTEGER PRIMARY KEY);
CREATE TABLE t4(a, b, PRIMARY KEY(a, b)) WITHOUT ROWID;
INSERT INTO t2 VALUES(10, 10, 10);
INSERT INTO t3 VALUES(10, 10, 10);
INSERT INTO t4 VALUES(10, 10);
}
foreach {tn error ota} {
2 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.a} {
INSERT INTO data_t2 VALUES(NULL, 'abc', 1, 0);
}
3 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.b} {
INSERT INTO data_t2 VALUES(2, NULL, 1, 0);
}
4 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.c} {
INSERT INTO data_t2 VALUES(1, 'abc', NULL, 0);
}
5 {SQLITE_MISMATCH - datatype mismatch} {
INSERT INTO data_t3 VALUES(1, 'abc', NULL, 0);
}
6 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t4.b} {
INSERT INTO data_t4 VALUES('a', NULL, 0);
}
7 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t4.a} {
INSERT INTO data_t4 VALUES(NULL, 'a', 0);
}
8 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.a} {
INSERT INTO data_t2 VALUES(NULL, 0, 10, 'x..');
}
9 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t3.b} {
INSERT INTO data_t3 VALUES(10, NULL, 10, '.x.');
}
10 {SQLITE_MISMATCH - datatype mismatch} {
INSERT INTO data_t3 VALUES(1, 'abc', 'text', 0);
}
} {
set ota "
CREATE TABLE data_t2(a, b, c, ota_control);
CREATE TABLE data_t3(a, b, c, ota_control);
CREATE TABLE data_t4(a, b, ota_control);
$ota
"
do_test 4.2.$tn {
list [catch { apply_ota $ota } msg] $msg
} [list 1 $error]
}
do_test 4.3 {
set ota {
CREATE TABLE data_t3(a, b, c, ota_control);
INSERT INTO data_t3 VALUES(1, 'abc', '5', 0);
INSERT INTO data_t3 VALUES(1, 'abc', '-6.0', 0);
}
list [catch { apply_ota $ota } msg] $msg
} {0 SQLITE_DONE}
finish_test
-198
View File
@@ -1,198 +0,0 @@
# 2015 February 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota11
#--------------------------------------------------------------------
# Test that the xAccess() method of an ota vfs handles queries other
# than SQLITE_ACCESS_EXISTS correctly. The test code below causes
# SQLite to call xAccess(SQLITE_ACCESS_READWRITE) on the directory
# path argument passed to "PRAGMA temp_store_directory".
#
do_test 1.1 {
sqlite3ota_create_vfs -default ota ""
reset_db
catchsql { PRAGMA temp_store_directory = '/no/such/directory' }
} {1 {not a writable directory}}
do_test 1.2 {
catchsql " PRAGMA temp_store_directory = '[pwd]' "
} {0 {}}
do_test 1.3 {
catchsql " PRAGMA temp_store_directory = '' "
} {0 {}}
do_test 1.4 {
db close
sqlite3ota_destroy_vfs ota
} {}
#--------------------------------------------------------------------
# Try to trick ota into operating on a database opened in wal mode.
#
reset_db
do_execsql_test 2.1 {
CREATE TABLE t1(a PRIMARY KEY, b, c);
INSERT INTO t1 VALUES(1, 2, 3);
PRAGMA journal_mode = 'wal';
CREATE TABLE t2(d PRIMARY KEY, e, f);
} {wal}
do_test 2.2 {
db_save
db close
forcedelete ota.db
sqlite3 dbo ota.db
dbo eval {
CREATE TABLE data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(4, 5, 6, 0);
INSERT INTO data_t1 VALUES(7, 8, 9, 0);
}
dbo close
db_restore
hexio_write test.db 18 0101
file exists test.db-wal
} {1}
do_test 2.3 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_ERROR}
do_test 2.4 {
list [catch {ota close} msg] $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}}
#--------------------------------------------------------------------
# Test a constraint violation message with an unusual table name.
# Specifically, one for which the first character is a codepoint
# smaller than 30 (character '0').
#
reset_db
do_execsql_test 3.1 {
CREATE TABLE "(t1)"(a PRIMARY KEY, b, c);
INSERT INTO "(t1)" VALUES(1, 2, 3);
INSERT INTO "(t1)" VALUES(4, 5, 6);
}
db close
do_test 3.2 {
forcedelete ota.db
sqlite3 dbo ota.db
dbo eval {
CREATE TABLE "data_(t1)"(a, b, c, ota_control);
INSERT INTO "data_(t1)" VALUES(4, 8, 9, 0);
}
dbo close
sqlite3ota ota test.db ota.db
ota step
ota step
} {SQLITE_CONSTRAINT}
do_test 3.3 {
list [catch {ota close} msg] $msg
} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: (t1).a}}
#--------------------------------------------------------------------
# Check that once an OTA update has been applied, attempting to apply
# it a second time is a no-op (as the state stored in the OTA database is
# "all steps completed").
#
reset_db
do_execsql_test 4.1 {
CREATE TABLE "(t1)"(a, b, c, PRIMARY KEY(c, b, a));
INSERT INTO "(t1)" VALUES(1, 2, 3);
INSERT INTO "(t1)" VALUES(4, 5, 6);
}
db close
do_test 4.2 {
forcedelete ota.db
sqlite3 dbo ota.db
dbo eval {
CREATE TABLE "data_(t1)"(a, b, c, ota_control);
INSERT INTO "data_(t1)" VALUES(7, 8, 9, 0);
INSERT INTO "data_(t1)" VALUES(1, 2, 3, 1);
}
dbo close
sqlite3ota ota test.db ota.db
while {[ota step]=="SQLITE_OK"} { }
ota close
} {SQLITE_DONE}
do_test 4.3 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_DONE}
do_test 4.4 {
ota close
} {SQLITE_DONE}
do_test 4.5.1 {
sqlite3 dbo ota.db
dbo eval { INSERT INTO ota_state VALUES(100, 100) }
dbo close
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_CORRUPT}
do_test 4.5.2 {
list [catch {ota close} msg] $msg
} {1 SQLITE_CORRUPT}
do_test 4.5.3 {
sqlite3 dbo ota.db
dbo eval { DELETE FROM ota_state WHERE k = 100 }
dbo close
} {}
# Also, check that an invalid state value in the ota_state table is
# detected and reported as corruption.
do_test 4.6.1 {
sqlite3 dbo ota.db
dbo eval { UPDATE ota_state SET v = v*-1 WHERE k = 1 }
dbo close
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_CORRUPT}
do_test 4.6.2 {
list [catch {ota close} msg] $msg
} {1 SQLITE_CORRUPT}
do_test 4.6.3 {
sqlite3 dbo ota.db
dbo eval { UPDATE ota_state SET v = v*-1 WHERE k = 1 }
dbo close
} {}
do_test 4.7.1 {
sqlite3 dbo ota.db
dbo eval { UPDATE ota_state SET v = 1 WHERE k = 1 }
dbo eval { UPDATE ota_state SET v = 'nosuchtable' WHERE k = 2 }
dbo close
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_ERROR}
do_test 4.7.2 {
list [catch {ota close} msg] $msg
} {1 {SQLITE_ERROR - ota_state mismatch error}}
finish_test
-172
View File
@@ -1,172 +0,0 @@
# 2015 February 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set ::testprefix ota12
set setup_sql {
DROP TABLE IF EXISTS xx;
DROP TABLE IF EXISTS xy;
CREATE TABLE xx(a, b, c PRIMARY KEY);
INSERT INTO xx VALUES(1, 2, 3);
CREATE TABLE xy(a, b, c PRIMARY KEY);
ATTACH 'ota.db' AS ota;
DROP TABLE IF EXISTS data_xx;
CREATE TABLE ota.data_xx(a, b, c, ota_control);
INSERT INTO data_xx VALUES(4, 5, 6, 0);
INSERT INTO data_xx VALUES(7, 8, 9, 0);
CREATE TABLE ota.data_xy(a, b, c, ota_control);
INSERT INTO data_xy VALUES(10, 11, 12, 0);
DETACH ota;
}
do_multiclient_test tn {
# Initialize a target (test.db) and ota (ota.db) database.
#
forcedelete ota.db
sql1 $setup_sql
# Using connection 2, open a read transaction on the target database.
# OTA will still be able to generate "test.db-oal", but it will not be
# able to rename it to "test.db-wal".
#
do_test 1.$tn.1 {
sql2 { BEGIN; SELECT * FROM xx; }
} {1 2 3}
do_test 1.$tn.2 {
sqlite3ota ota test.db ota.db
while 1 {
set res [ota step]
if {$res!="SQLITE_OK"} break
}
set res
} {SQLITE_BUSY}
do_test 1.$tn.3 { sql2 { SELECT * FROM xx; } } {1 2 3}
do_test 1.$tn.4 { sql2 { SELECT * FROM xy; } } {}
do_test 1.$tn.5 {
list [file exists test.db-wal] [file exists test.db-oal]
} {0 1}
do_test 1.$tn.6 { sql2 COMMIT } {}
# The ota object that hit the SQLITE_BUSY error above cannot be reused.
# It is stuck in a permanent SQLITE_BUSY state at this point.
#
do_test 1.$tn.7 { ota step } {SQLITE_BUSY}
do_test 1.$tn.8 {
list [catch { ota close } msg] $msg
} {1 SQLITE_BUSY}
do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {}
do_test 1.$tn.9.2 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_BUSY}
do_test 1.$tn.9.3 {
list [catch { ota close } msg] $msg
} {1 {SQLITE_BUSY - database is locked}}
do_test 1.$tn.9.4 { sql2 COMMIT } {}
sqlite3ota ota test.db ota.db
do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {}
do_test 1.$tn.10.2 {
ota step
} {SQLITE_BUSY}
do_test 1.$tn.10.3 {
list [catch { ota close } msg] $msg
} {1 SQLITE_BUSY}
do_test 1.$tn.10.4 { sql2 COMMIT } {}
# A new ota object can finish the work though.
#
do_test 1.$tn.11 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_OK}
do_test 1.$tn.12 {
list [file exists test.db-wal] [file exists test.db-oal]
} {1 0}
do_test 1.$tn.13 {
while 1 {
set res [ota step]
if {$res!="SQLITE_OK"} break
}
set res
} {SQLITE_DONE}
do_test 1.$tn.14 {
ota close
} {SQLITE_DONE}
}
do_multiclient_test tn {
# Initialize a target (test.db) and ota (ota.db) database.
#
forcedelete ota.db
sql1 $setup_sql
do_test 2.$tn.1 {
sqlite3ota ota test.db ota.db
while {[file exists test.db-wal]==0} {
if {[ota step]!="SQLITE_OK"} {error "problem here...."}
}
ota close
} {SQLITE_OK}
do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {}
do_test 2.$tn.3 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_BUSY}
do_test 2.$tn.4 { list [catch { ota close } msg] $msg } {1 SQLITE_BUSY}
do_test 2.$tn.5 {
sql2 { SELECT * FROM xx ; COMMIT }
} {1 2 3 4 5 6 7 8 9}
do_test 2.$tn.6 {
sqlite3ota ota test.db ota.db
ota step
ota close
} {SQLITE_OK}
do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {}
do_test 2.$tn.8 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_BUSY}
do_test 2.$tn.9 { list [catch { ota close } msg] $msg } {1 SQLITE_BUSY}
do_test 2.$tn.10 {
sql2 { SELECT * FROM xx ; COMMIT }
} {1 2 3 4 5 6 7 8 9}
do_test 2.$tn.11 {
sqlite3ota ota test.db ota.db
while {[ota step]=="SQLITE_OK"} {}
ota close
} {SQLITE_DONE}
}
finish_test
-65
View File
@@ -1,65 +0,0 @@
# 2015 February 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.
#
#***********************************************************************
#
# Test an OTA update that features lots of different ota_control strings
# for UPDATE statements. This tests OTA's internal UPDATE statement cache.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set ::testprefix ota13
do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b, c, d, e, f, g, h);
WITH ii(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM ii WHERE i<127)
INSERT INTO t1 SELECT i, 0, 0, 0, 0, 0, 0, 0 FROM ii;
}
forcedelete ota.db
do_execsql_test 1.1 {
ATTACH 'ota.db' AS ota;
CREATE TABLE ota.data_t1(a, b, c, d, e, f, g, h, ota_control);
}
do_test 1.2 {
for {set i 0} {$i<128} {incr i} {
set control "."
for {set bit 6} {$bit>=0} {incr bit -1} {
if { $i & (1<<$bit) } {
append control "x"
} else {
append control "."
}
}
execsql { INSERT INTO data_t1 VALUES($i, 1, 1, 1, 1, 1, 1, 1, $control) }
}
} {}
do_test 1.3 {
sqlite3ota ota test.db ota.db
while 1 {
set rc [ota step]
if {$rc!="SQLITE_OK"} break
}
ota close
} {SQLITE_DONE}
do_execsql_test 1.4 {
SELECT count(*) FROM t1 WHERE
a == ( (b<<6) + (c<<5) + (d<<4) + (e<<3) + (f<<2) + (g<<1) + (h<<0) )
} {128}
finish_test
-207
View File
@@ -1,207 +0,0 @@
# 2014 August 30
#
# 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota3
# Run the OTA in file $ota on target database $target until completion.
#
proc run_ota {target ota} {
sqlite3ota ota $target $ota
while { [ota step]=="SQLITE_OK" } {}
ota close
}
forcedelete test.db-oal ota.db
db close
sqlite3_shutdown
sqlite3_config_uri 1
reset_db
#--------------------------------------------------------------------
# Test that for an OTA to be applied, no corruption results if the
# affinities on the source and target table do not match.
#
do_execsql_test 1.0 {
CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL);
CREATE INDEX i1 ON x1(b, c);
} {}
do_test 1.1 {
sqlite3 db2 ota.db
db2 eval {
CREATE TABLE data_x1(a, b, c, ota_control);
INSERT INTO data_x1 VALUES(1, '123', '123', 0);
INSERT INTO data_x1 VALUES(2, 123, 123, 0);
}
db2 close
run_ota test.db ota.db
} {SQLITE_DONE}
do_execsql_test 1.2 {
PRAGMA integrity_check;
} {ok}
#--------------------------------------------------------------------
# Test that NULL values may not be inserted into INTEGER PRIMARY KEY
# columns.
#
forcedelete ota.db
reset_db
do_execsql_test 2.0 {
CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL);
CREATE INDEX i1 ON x1(b, c);
} {}
foreach {tn otadb} {
1 {
CREATE TABLE data_x1(a, b, c, ota_control);
INSERT INTO data_x1 VALUES(NULL, 'a', 'b', 0);
}
2 {
CREATE TABLE data_x1(c, b, a, ota_control);
INSERT INTO data_x1 VALUES('b', 'a', NULL, 0);
}
} {
do_test 2.$tn.1 {
forcedelete ota.db
sqlite3 db2 ota.db
db2 eval $otadb
db2 close
list [catch { run_ota test.db ota.db } msg] $msg
} {1 {SQLITE_MISMATCH - datatype mismatch}}
do_execsql_test 2.1.2 {
PRAGMA integrity_check;
} {ok}
}
#--------------------------------------------------------------------
# Test that missing columns are detected.
#
forcedelete ota.db
reset_db
do_execsql_test 2.0 {
CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON x1(b, c);
} {}
do_test 2.1 {
sqlite3 db2 ota.db
db2 eval {
CREATE TABLE data_x1(a, b, ota_control);
INSERT INTO data_x1 VALUES(1, 'a', 0);
}
db2 close
list [catch { run_ota test.db ota.db } msg] $msg
} {1 {SQLITE_ERROR - column missing from data_x1: c}}
do_execsql_test 2.2 {
PRAGMA integrity_check;
} {ok}
# Also extra columns.
#
do_execsql_test 2.3 {
CREATE TABLE x2(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i2 ON x2(b, c);
} {}
do_test 2.4 {
forcedelete ota.db
sqlite3 db2 ota.db
db2 eval {
CREATE TABLE data_x2(a, b, c, d, ota_control);
INSERT INTO data_x2 VALUES(1, 'a', 2, 3, 0);
}
db2 close
list [catch { run_ota test.db ota.db } msg] $msg
} {1 SQLITE_ERROR}
do_execsql_test 2.5 {
PRAGMA integrity_check;
} {ok}
#-------------------------------------------------------------------------
# Test that sqlite3ota_create_vfs() returns an error if the requested
# parent VFS is unknown.
#
# And that nothing disasterous happens if a VFS name passed to
# sqlite3ota_destroy_vfs() is unknown or not an OTA vfs.
#
do_test 3.1 {
list [catch {sqlite3ota_create_vfs xyz nosuchparent} msg] $msg
} {1 SQLITE_NOTFOUND}
do_test 3.2 {
sqlite3ota_destroy_vfs nosuchvfs
sqlite3ota_destroy_vfs unix
sqlite3ota_destroy_vfs win32
} {}
#-------------------------------------------------------------------------
# Test that it is an error to specify an explicit VFS that does not
# include ota VFS functionality.
#
do_test 4.1 {
testvfs tvfs
sqlite3ota ota file:test.db?vfs=tvfs ota.db
list [catch { ota step } msg] $msg
} {0 SQLITE_ERROR}
do_test 4.2 {
list [catch { ota close } msg] $msg
} {1 {SQLITE_ERROR - ota vfs not found}}
tvfs delete
#-------------------------------------------------------------------------
# Test a large ota update to ensure that wal_autocheckpoint does not get
# in the way.
#
forcedelete ota.db
reset_db
do_execsql_test 5.1 {
CREATE TABLE x1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
CREATE INDEX i1 ON x1(a);
ATTACH 'ota.db' AS ota;
CREATE TABLE ota.data_x1(a, b, c, ota_control);
WITH s(a, b, c) AS (
SELECT randomblob(300), randomblob(300), 1
UNION ALL
SELECT randomblob(300), randomblob(300), c+1 FROM s WHERE c<2000
)
INSERT INTO data_x1 SELECT a, b, c, 0 FROM s;
}
do_test 5.2 {
sqlite3ota ota test.db ota.db
while {[ota step]=="SQLITE_OK" && [file exists test.db-wal]==0} {}
ota close
} {SQLITE_OK}
do_test 5.3 {
expr {[file size test.db-wal] > (1024 * 1200)}
} 1
do_test 6.1 { sqlite3ota_internal_test } {}
finish_test
-331
View File
@@ -1,331 +0,0 @@
# 2014 August 30
#
# 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 some properties of the pager_ota_mode and ota_mode pragmas.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota5
# Run the OTA in file $ota on target database $target until completion.
#
proc run_ota {target ota} {
sqlite3ota ota $target $ota
while { [ota step]=="SQLITE_OK" } {}
ota close
}
# Run the OTA in file $ota on target database $target one step at a
# time until completion.
#
proc step_ota {target ota} {
while 1 {
sqlite3ota ota $target $ota
set rc [ota step]
ota close
if {$rc != "SQLITE_OK"} break
}
set rc
}
# Return a list of the primary key columns for table $tbl in the database
# opened by database handle $db.
#
proc pkcols {db tbl} {
set ret [list]
$db eval "PRAGMA table_info = '$tbl'" {
if {$pk} { lappend ret $name }
}
return $ret
}
# Return a list of all columns for table $tbl in the database opened by
# database handle $db.
#
proc allcols {db tbl} {
set ret [list]
$db eval "PRAGMA table_info = '$tbl'" {
lappend ret $name
}
return $ret
}
# Return a checksum on all tables and data in the main database attached
# to database handle $db. It is possible to add indexes without changing
# the checksum.
#
proc datacksum {db} {
$db eval { SELECT name FROM sqlite_master WHERE type='table' } {
append txt $name
set cols [list]
set order [list]
set cnt 0
$db eval "PRAGMA table_info = $name" x {
lappend cols "quote($x(name))"
lappend order [incr cnt]
}
set cols [join $cols ,]
set order [join $order ,]
append txt [$db eval "SELECT $cols FROM $name ORDER BY $order"]
}
return "[string length $txt]-[md5 $txt]"
}
proc ucontrol {args} {
set ret ""
foreach a $args {
if {$a} {
append ret .
} else {
append ret x
}
}
return $ret
}
# Argument $target is the name of an SQLite database file. $sql is an SQL
# script containing INSERT, UPDATE and DELETE statements to execute against
# it. This command creates an OTA update database in file $ota that has
# the same effect as the script. The target database is not modified by
# this command.
#
proc generate_ota_db {target ota sql} {
forcedelete $ota
forcecopy $target copy.db
# Evaluate the SQL script to modify the contents of copy.db.
#
sqlite3 dbOta copy.db
dbOta eval $sql
dbOta function ucontrol ucontrol
# Evaluate the SQL script to modify the contents of copy.db.
set ret [datacksum dbOta]
dbOta eval { ATTACH $ota AS ota }
dbOta eval { ATTACH $target AS orig }
dbOta eval { SELECT name AS tbl FROM sqlite_master WHERE type = 'table' } {
set pk [pkcols dbOta $tbl]
set cols [allcols dbOta $tbl]
# A WHERE clause to test that the PK columns match.
#
set where [list]
foreach c $pk { lappend where "main.$tbl.$c IS orig.$tbl.$c" }
set where [join $where " AND "]
# A WHERE clause to test that all columns match.
#
set where2 [list]
foreach c $cols { lappend where2 "main.$tbl.$c IS orig.$tbl.$c" }
set ucontrol "ucontrol([join $where2 ,])"
set where2 [join $where2 " AND "]
# Create a data_xxx table in the OTA update database.
dbOta eval "
CREATE TABLE ota.data_$tbl AS SELECT *, '' AS ota_control
FROM main.$tbl LIMIT 0
"
# Find all new rows INSERTed by the script.
dbOta eval "
INSERT INTO ota.data_$tbl
SELECT *, 0 AS ota_control FROM main.$tbl
WHERE NOT EXISTS (
SELECT 1 FROM orig.$tbl WHERE $where
)
"
# Find all old rows DELETEd by the script.
dbOta eval "
INSERT INTO ota.data_$tbl
SELECT *, 1 AS ota_control FROM orig.$tbl
WHERE NOT EXISTS (
SELECT 1 FROM main.$tbl WHERE $where
)
"
# Find all rows UPDATEd by the script.
set origcols [list]
foreach c $cols { lappend origcols "main.$tbl.$c" }
set origcols [join $origcols ,]
dbOta eval "
INSERT INTO ota.data_$tbl
SELECT $origcols, $ucontrol AS ota_control
FROM orig.$tbl, main.$tbl
WHERE $where AND NOT ($where2)
"
}
dbOta close
forcedelete copy.db
return $ret
}
#-------------------------------------------------------------------------
#
do_execsql_test 1.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE TABLE t2(x, y, z, PRIMARY KEY(y, z)) WITHOUT ROWID;
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(2, 4, 6);
INSERT INTO t1 VALUES(3, 6, 9);
INSERT INTO t2 VALUES(1, 2, 3);
INSERT INTO t2 VALUES(2, 4, 6);
INSERT INTO t2 VALUES(3, 6, 9);
}
db close
set cksum [generate_ota_db test.db ota.db {
INSERT INTO t1 VALUES(4, 8, 12);
DELETE FROM t1 WHERE a = 2;
UPDATE t1 SET c = 15 WHERE a=3;
INSERT INTO t2 VALUES(4, 8, 12);
DELETE FROM t2 WHERE x = 2;
UPDATE t2 SET x = 15 WHERE z=9;
}]
foreach {tn idx} {
1 {
}
2 {
CREATE INDEX i1 ON t1(a, b, c);
CREATE INDEX i2 ON t2(x, y, z);
}
} {
foreach cmd {run step} {
forcecopy test.db test.db2
forcecopy ota.db ota.db2
sqlite3 db test.db2
db eval $idx
do_test 1.$tn.$cmd.1 {
${cmd}_ota test.db2 ota.db2
datacksum db
} $cksum
do_test 1.$tn.$cmd.2 {
db eval { PRAGMA integrity_check }
} {ok}
db close
}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e);
INSERT INTO t1 VALUES(-750250,'fyetckfaagjkzqjx',-185831,X'FEAD',444258.29);
INSERT INTO t1 VALUES(649081,NULL,X'7DF25BF78778',-342324.63,'akvspktocwozo');
INSERT INTO t1 VALUES(-133045,-44822.31,X'',287935,NULL);
INSERT INTO t1 VALUES(202132,NULL,X'5399','cujsjtspryqeyovcdpz','m');
INSERT INTO t1 VALUES(302910,NULL,'dvdhivtfkaedzhdcnn',-717113.41,688487);
INSERT INTO t1 VALUES(-582327,X'7A267A',X'7E6B3CFE5CB9','zacuzilrok',-196478);
INSERT INTO t1 VALUES(-190462,X'D1A087E7D68D9578','lsmleti',NULL,-928094);
INSERT INTO t1 VALUES(-467665,176344.57,-536684.23,828876.22,X'903E');
INSERT INTO t1 VALUES(-629138,632630.29,X'28D6',-774501,X'819BBBFC65');
INSERT INTO t1 VALUES(-828110,-54379.24,-881121.44,X'',X'8D5A894F0D');
CREATE TABLE t2(a PRIMARY KEY, b, c, d, e) WITHOUT ROWID;
INSERT INTO t2 VALUES(-65174,X'AC1DBFFE27310F',-194471.08,347988,X'84041BA6F9BDDE86A8');
INSERT INTO t2 VALUES('bzbpi',-952693.69,811628.25,NULL,-817434);
INSERT INTO t2 VALUES(-643830,NULL,'n',NULL,'dio');
INSERT INTO t2 VALUES('rovoenxxj',NULL,'owupbtdcoxxnvg',-119676,X'55431DFA');
INSERT INTO t2 VALUES(899770,'jlygdl',X'DBCA4D1A',NULL,-631773);
INSERT INTO t2 VALUES(334698.80,NULL,-697585.58,-89277,-817352);
INSERT INTO t2 VALUES(X'1A9EB7547A4AAF38','aiprdhkpzdz','anw','szvjbwdvzucybpwwqjt',X'53');
INSERT INTO t2 VALUES(713220,NULL,'hfcqhqzjuqplvkum',X'20B076075649DE','fthgpvqdyy');
INSERT INTO t2 VALUES(763908,NULL,'xgslzcpvwfknbr',X'75',X'668146');
INSERT INTO t2 VALUES(X'E1BA2B6BA27278','wjbpd',NULL,139341,-290086.15);
}
db close
set cksum [generate_ota_db test.db ota.db {
INSERT INTO t2 VALUES(222916.23,'idh',X'472C517405',X'E3',X'7C4F31824669');
INSERT INTO t2 VALUES('xcndjwafcoxwxizoktd',-319567.21,NULL,-720906.43,-577170);
INSERT INTO t2 VALUES(376369.99,-536058,'yoaiurfqupdscwc',X'29EC8A2542EC3953E9',-740485.22);
INSERT INTO t2 VALUES(X'0EFB4DC50693',-175590.83,X'1779E253CAB5B1789E',X'BC6903',NULL);
INSERT INTO t2 VALUES(-288299,'hfrp',NULL,528477,730676.77);
DELETE FROM t2 WHERE a < -60000;
UPDATE t2 SET b = 'pgnnaaoflnw' WHERE a = 'bzbpi';
UPDATE t2 SET c = -675583 WHERE a = 'rovoenxxj';
UPDATE t2 SET d = X'09CDF2B2C241' WHERE a = 713220;
INSERT INTO t1 VALUES(224938,'bmruycvfznhhnfmgqys','fr',854381,789143);
INSERT INTO t1 VALUES(-863931,-1386.26,X'2A058540C2FB5C',NULL,X'F9D5990A');
INSERT INTO t1 VALUES(673696,X'97301F0AC5735F44B5',X'440C',227999.92,-709599.79);
INSERT INTO t1 VALUES(-243640,NULL,-71718.11,X'1EEFEB38',X'8CC7C55D95E142FBA5');
INSERT INTO t1 VALUES(275893,X'',375606.30,X'0AF9EC334711FB',-468194);
DELETE FROM t1 WHERE a > 200000;
UPDATE t1 SET b = 'pgnnaaoflnw' WHERE a = -190462;
UPDATE t1 SET c = -675583 WHERE a = -467665;
UPDATE t1 SET d = X'09CDF2B2C241' WHERE a = -133045;
}]
foreach {tn idx} {
1 {
}
2 {
CREATE UNIQUE INDEX i1 ON t1(b, c, d);
CREATE UNIQUE INDEX i2 ON t1(d, e, a);
CREATE UNIQUE INDEX i3 ON t1(e, d, c, b);
CREATE UNIQUE INDEX i4 ON t2(b, c, d);
CREATE UNIQUE INDEX i5 ON t2(d, e, a);
CREATE UNIQUE INDEX i6 ON t2(e, d, c, b);
}
} {
foreach cmd {run step} {
forcecopy test.db test.db2
forcecopy ota.db ota.db2
sqlite3 db test.db2
db eval $idx
do_test 2.$tn.$cmd.1 {
${cmd}_ota test.db2 ota.db2
datacksum db
} $cksum
do_test 2.$tn.$cmd.2 {
db eval { PRAGMA integrity_check }
} {ok}
db close
}
}
finish_test
-103
View File
@@ -1,103 +0,0 @@
# 2014 October 21
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for the OTA module. Specifically, it tests the
# outcome of some other client writing to the database while an OTA update
# is being applied.
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota6
proc setup_test {} {
reset_db
execsql {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b UNIQUE);
CREATE TABLE t3(a INTEGER PRIMARY KEY, b UNIQUE);
}
db close
forcedelete ota.db
sqlite3 ota ota.db
ota eval {
CREATE TABLE data_t1(a, b, ota_control);
CREATE TABLE data_t2(a, b, ota_control);
CREATE TABLE data_t3(a, b, ota_control);
INSERT INTO data_t1 VALUES(1, 't1', 0);
INSERT INTO data_t2 VALUES(2, 't2', 0);
INSERT INTO data_t3 VALUES(3, 't3', 0);
}
ota close
}
# Test the outcome of some other client writing the db while the *-oal
# file is being generated. Once this has happened, the update cannot be
# progressed.
#
for {set nStep 1} {$nStep < 8} {incr nStep} {
do_test 1.$nStep.1 {
setup_test
sqlite3ota ota test.db ota.db
for {set i 0} {$i<$nStep} {incr i} {ota step}
ota close
sqlite3 db test.db
execsql { INSERT INTO t1 VALUES(5, 'hello') }
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_BUSY}
do_test 1.$nStep.2 {
ota step
} {SQLITE_BUSY}
do_test 1.$nStep.3 {
list [file exists test.db-oal] [file exists test.db-wal]
} {1 0}
do_test 1.$nStep.4 {
list [catch { ota close } msg] $msg
} {1 {SQLITE_BUSY - database modified during ota update}}
}
# Test the outcome of some other client writing the db after the *-oal
# file has been copied to the *-wal path. Once this has happened, any
# other client writing to the db causes OTA to consider its job finished.
#
for {set nStep 8} {$nStep < 20} {incr nStep} {
do_test 1.$nStep.1 {
setup_test
sqlite3ota ota test.db ota.db
for {set i 0} {$i<$nStep} {incr i} {ota step}
ota close
sqlite3 db test.db
execsql { INSERT INTO t1 VALUES(5, 'hello') }
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_DONE}
do_test 1.$nStep.2 {
ota step
} {SQLITE_DONE}
do_test 1.$nStep.3 {
file exists test.db-oal
} {0}
do_test 1.$nStep.4 {
list [catch { ota close } msg] $msg
} {0 SQLITE_DONE}
do_execsql_test 1.$nStep.5 {
SELECT * FROM t1;
} {1 t1 5 hello}
}
finish_test
-110
View File
@@ -1,110 +0,0 @@
# 2014 October 21
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for the OTA module.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota7
# Test index:
#
# 1.*: That affinities are correctly applied to values within the
# OTA database.
#
# 2.*: Tests for multi-column primary keys.
#
do_test 1.0 {
execsql {
CREATE TABLE t1(a INT PRIMARY KEY, b) WITHOUT ROWID;
INSERT INTO t1 VALUES(1, 'abc');
INSERT INTO t1 VALUES(2, 'def');
}
forcedelete ota.db
sqlite3 ota ota.db
ota eval {
CREATE TABLE data_t1(a, b, ota_control);
INSERT INTO data_t1 VALUES('1', NULL, 1);
}
ota close
} {}
do_test 1.1 {
sqlite3ota ota test.db ota.db
while { [ota step]=="SQLITE_OK" } {}
ota close
} {SQLITE_DONE}
sqlite3 db test.db
do_execsql_test 1.2 {
SELECT * FROM t1
} {2 def}
#-------------------------------------------------------------------------
#
foreach {tn tbl} {
1 { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID }
2 { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)) }
} {
reset_db
execsql $tbl
do_execsql_test 2.$tn.1 {
CREATE INDEX t1c ON t1(c);
INSERT INTO t1 VALUES(1, 1, 'a');
INSERT INTO t1 VALUES(1, 2, 'b');
INSERT INTO t1 VALUES(2, 1, 'c');
INSERT INTO t1 VALUES(2, 2, 'd');
}
do_test 2.$tn.2 {
forcedelete ota.db
sqlite3 ota ota.db
execsql {
CREATE TABLE data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(3, 1, 'e', 0);
INSERT INTO data_t1 VALUES(3, 2, 'f', 0);
INSERT INTO data_t1 VALUES(1, 2, NULL, 1);
INSERT INTO data_t1 VALUES(2, 1, 'X', '..x');
} ota
ota close
} {}
do_test 2.$tn.3 {
set rc "SQLITE_OK"
while {$rc == "SQLITE_OK"} {
sqlite3ota ota test.db ota.db
ota step
set rc [ota close]
}
set rc
} {SQLITE_DONE}
do_execsql_test 2.$tn.1 {
SELECT * FROM t1 ORDER BY a, b
} {
1 1 a
2 1 X
2 2 d
3 1 e
3 2 f
}
}
finish_test
-75
View File
@@ -1,75 +0,0 @@
# 2014 November 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.
#
#***********************************************************************
#
# Test the ota_delta() feature.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota8
do_execsql_test 1.0 {
CREATE TABLE t1(x, y PRIMARY KEY, z);
INSERT INTO t1 VALUES(NULL, 1, 'one');
INSERT INTO t1 VALUES(NULL, 2, 'two');
INSERT INTO t1 VALUES(NULL, 3, 'three');
CREATE INDEX i1z ON t1(z, x);
}
do_test 1.1 {
forcedelete ota.db
sqlite3 db2 ota.db
db2 eval {
CREATE TABLE data_t1(x, y, z, ota_control);
INSERT INTO data_t1 VALUES('a', 1, '_i' , 'x.d');
INSERT INTO data_t1 VALUES('b', 2, 2 , '..x');
INSERT INTO data_t1 VALUES('_iii', 3, '-III' , 'd.d');
}
db2 close
} {}
do_test 1.2.1 {
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_ERROR}
do_test 1.2.2 {
list [catch {ota close} msg] $msg
} {1 {SQLITE_ERROR - no such function: ota_delta}}
proc ota_delta {orig new} {
return "${orig}${new}"
}
do_test 1.3.1 {
while 1 {
sqlite3ota ota test.db ota.db
ota create_ota_delta
set rc [ota step]
if {$rc != "SQLITE_OK"} break
ota close
}
ota close
} {SQLITE_DONE}
do_execsql_test 1.3.2 {
SELECT * FROM t1
} {
a 1 one_i
{} 2 2
_iii 3 three-III
}
integrity_check 1.3.3
finish_test
-128
View File
@@ -1,128 +0,0 @@
# 2014 November 21
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test OTA with virtual tables. And tables with no PRIMARY KEY declarations.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix ota9
ifcapable !fts3 {
finish_test
return
}
do_execsql_test 1.1 {
CREATE VIRTUAL TABLE f1 USING fts4(a, b, c);
INSERT INTO f1(rowid, a, b, c) VALUES(11, 'a', 'b', 'c');
INSERT INTO f1(rowid, a, b, c) VALUES(12, 'd', 'e', 'f');
INSERT INTO f1(rowid, a, b, c) VALUES(13, 'g', 'h', 'i');
}
do_test 1.1 {
forcedelete ota.db
sqlite3 db2 ota.db
db2 eval {
CREATE TABLE data_f1(ota_rowid, a, b, c, ota_control);
INSERT INTO data_f1 VALUES(14, 'x', 'y', 'z', 0); -- INSERT
INSERT INTO data_f1 VALUES(11, NULL, NULL, NULL, 1); -- DELETE
INSERT INTO data_f1 VALUES(13, NULL, NULL, 'X', '..x'); -- UPDATE
}
db2 close
} {}
do_test 1.2.1 {
while 1 {
sqlite3ota ota test.db ota.db
set rc [ota step]
if {$rc != "SQLITE_OK"} break
ota close
}
ota close
} {SQLITE_DONE}
do_execsql_test 1.2.2 { SELECT rowid, * FROM f1 } {
12 d e f
13 g h X
14 x y z
}
do_execsql_test 1.2.3 { INSERT INTO f1(f1) VALUES('integrity-check') }
integrity_check 1.2.4
#-------------------------------------------------------------------------
# Tables with no PK declaration.
#
# Run the OTA in file $ota on target database $target until completion.
#
proc run_ota {target ota} {
sqlite3ota ota $target $ota
while { [ota step]=="SQLITE_OK" } {}
ota close
}
foreach {tn idx} {
1 { }
2 {
CREATE INDEX i1 ON t1(a);
}
3 {
CREATE INDEX i1 ON t1(b, c);
CREATE INDEX i2 ON t1(c, b);
CREATE INDEX i3 ON t1(a, a, a, b, b, b, c, c, c);
}
} {
reset_db
do_execsql_test 2.$tn.1 {
CREATE TABLE t1(a, b, c);
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
INSERT INTO t1(rowid, a, b, c) VALUES(-1, 'a', 'b', 'c');
INSERT INTO t1(rowid, a, b, c) VALUES(-2, 'd', 'e', 'f');
}
db eval $idx
do_test 2.$tn.2 {
forcedelete ota.db
sqlite3 db2 ota.db
db2 eval {
CREATE TABLE data_t1(ota_rowid, a, b, c, ota_control);
INSERT INTO data_t1 VALUES(3, 'x', 'y', 'z', 0);
INSERT INTO data_t1 VALUES(NULL, 'X', 'Y', 'Z', 0);
INSERT INTO data_t1 VALUES('1', NULL, NULL, NULL, 1);
INSERT INTO data_t1 VALUES(-2, NULL, NULL, 'fff', '..x');
}
db2 close
} {}
run_ota test.db ota.db
do_execsql_test 2.$tn.3 {
SELECT rowid, a, b, c FROM t1 ORDER BY rowid;
} {
-2 d e fff
-1 a b c
2 4 5 6
3 x y z
4 X Y Z
}
integrity_check 2.$tn.4
}
finish_test
-84
View File
@@ -1,84 +0,0 @@
# 2014 August 30
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for the OTA module. More specifically, it
# contains tests to ensure that it is an error to attempt to update
# a wal mode database via OTA.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix otaA
set db_sql {
CREATE TABLE t1(a PRIMARY KEY, b, c);
}
set ota_sql {
CREATE TABLE data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t1 VALUES(4, 5, 6, 0);
INSERT INTO data_t1 VALUES(7, 8, 9, 0);
}
do_test 1.0 {
db close
forcedelete test.db ota.db
sqlite3 db test.db
db eval $db_sql
db eval { PRAGMA journal_mode = wal }
db close
sqlite3 db ota.db
db eval $ota_sql
db close
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_ERROR}
do_test 1.1 {
list [catch { ota close } msg] $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}}
do_test 2.0 {
forcedelete test.db ota.db
sqlite3 db test.db
db eval $db_sql
db close
sqlite3 db ota.db
db eval $ota_sql
db close
sqlite3ota ota test.db ota.db
ota step
ota close
} {SQLITE_OK}
do_test 2.1 {
sqlite3 db test.db
db eval {PRAGMA journal_mode = wal}
db close
breakpoint
sqlite3ota ota test.db ota.db
ota step
} {SQLITE_ERROR}
do_test 2.2 {
list [catch { ota close } msg] $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}}
finish_test
-149
View File
@@ -1,149 +0,0 @@
# 2014 October 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix otacrash
db close
forcedelete test.db-oal ota.db
sqlite3_shutdown
sqlite3_config_uri 1
reset_db
# Set up a target database and an ota update database. The target
# db is the usual "test.db", the ota db is "test.db2".
#
forcedelete test.db2
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a), UNIQUE(b));
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
INSERT INTO t1 VALUES(7, 8, 9);
ATTACH 'test.db2' AS ota;
CREATE TABLE ota.data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(10, 11, 12, 0);
INSERT INTO data_t1 VALUES(13, 14, 15, 0);
INSERT INTO data_t1 VALUES(4, NULL, NULL, 1);
INSERT INTO data_t1 VALUES(1, NULL, 100, '..x');
}
db_save_and_close
# Determine the number of steps in applying the ota update to the test
# target database created above. Set $::ota_num_steps accordingly
#
# Check that the same number of steps are required to apply the ota
# update using many calls to sqlite3ota_step() on a single ota handle
# as required to apply it using a series of ota handles, on each of
# which sqlite3ota_step() is called once.
#
do_test 1.1 {
db_restore
sqlite3ota ota test.db test.db2
breakpoint
set nStep 0
while {[ota step]=="SQLITE_OK"} { incr nStep }
ota close
} {SQLITE_DONE}
set ota_num_steps $nStep
do_test 1.2 {
db_restore
set nStep 0
while {1} {
sqlite3ota ota test.db test.db2
ota step
if {[ota close]=="SQLITE_DONE"} break
incr nStep
}
set nStep
} $ota_num_steps
# Run one or more tests using the target (test.db) and ota (test.db2)
# databases created above. As follows:
#
# 1. This process starts the ota update and calls sqlite3ota_step()
# $nPre times. Then closes the ota update handle.
#
# 2. A second process resumes the ota update and attempts to call
# sqlite3ota_step() $nStep times before closing the handle. A
# crash is simulated during each xSync() of file test.db2.
#
# 3. This process attempts to resume the ota update from whatever
# state it was left in by step (2). Test that it is successful
# in doing so and that the final target database is as expected.
#
# In total (nSync+1) tests are run, where nSync is the number of times
# xSync() is called on test.db2.
#
proc do_ota_crash_test {tn nPre nStep} {
set script [subst -nocommands {
sqlite3ota ota test.db file:test.db2?vfs=crash
set i 0
while {[set i] < $nStep} {
if {[ota step]!="SQLITE_OK"} break
incr i
}
ota close
}]
set bDone 0
for {set iDelay 1} {$bDone==0} {incr iDelay} {
forcedelete test.db2 test.db2-journal test.db test.db-oal test.db-wal
db_restore
if {$nPre>0} {
sqlite3ota ota test.db file:test.db2
set i 0
for {set i 0} {$i < $nPre} {incr i} {
if {[ota step]!="SQLITE_OK"} break
}
ota close
}
set res [
crashsql -file test.db2 -delay $iDelay -tclbody $script -opendb {} {}
]
set bDone 1
if {$res == "1 {child process exited abnormally}"} {
set bDone 0
} elseif {$res != "0 {}"} {
error "unexected catchsql result: $res"
}
sqlite3ota ota test.db test.db2
while {[ota step]=="SQLITE_OK"} {}
ota close
sqlite3 db test.db
do_execsql_test $tn.delay=$iDelay {
SELECT * FROM t1;
PRAGMA integrity_check;
} {1 2 100 7 8 9 10 11 12 13 14 15 ok}
db close
}
}
for {set nPre 0} {$nPre < $ota_num_steps} {incr nPre} {
for {set is 1} {$is <= ($ota_num_steps - $nPre)} {incr is} {
do_ota_crash_test 2.pre=$nPre.step=$is $nPre $is
}
}
finish_test
-237
View File
@@ -1,237 +0,0 @@
# 2014 October 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set ::testprefix otafault
proc copy_if_exists {src target} {
if {[file exists $src]} {
forcecopy $src $target
} else {
forcedelete $target
}
}
foreach {tn2 setup sql expect} {
1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX t1cb ON t1(c, b);
INSERT INTO t1 VALUES(1, 1, 1);
INSERT INTO t1 VALUES(2, 2, 2);
INSERT INTO t1 VALUES(3, 3, 3);
CREATE TABLE ota.data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.');
INSERT INTO data_t1 VALUES(4, 4, 4, 0);
} {
SELECT * FROM t1
} {1 1 1 3 three 3 4 4 4}
2 {
CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
CREATE INDEX t2cb ON t2(c, b);
INSERT INTO t2 VALUES('a', 'a', 'a');
INSERT INTO t2 VALUES('b', 'b', 'b');
INSERT INTO t2 VALUES('c', 'c', 'c');
CREATE TABLE ota.data_t2(a, b, c, ota_control);
INSERT INTO data_t2 VALUES('b', NULL, NULL, 1);
INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.');
INSERT INTO data_t2 VALUES('d', 'd', 'd', 0);
} {
SELECT * FROM t2
} {a a a c see c d d d}
3 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
CREATE INDEX t1cb ON t1(c, b);
CREATE INDEX t2cb ON t2(c, b);
CREATE TABLE ota.data_t1(a, b, c, ota_control);
CREATE TABLE ota.data_t2(a, b, c, ota_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t2 VALUES(4, 5, 6, 0);
} {
SELECT * FROM t1 UNION ALL SELECT * FROM t2
} {1 2 3 4 5 6}
4 {
CREATE TABLE t1(a PRIMARY KEY, b, c);
CREATE INDEX t1c ON t1(c);
INSERT INTO t1 VALUES('A', 'B', 'C');
INSERT INTO t1 VALUES('D', 'E', 'F');
CREATE TABLE ota.data_t1(a, b, c, ota_control);
INSERT INTO data_t1 VALUES('D', NULL, NULL, 1);
INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.');
INSERT INTO data_t1 VALUES('G', 'H', 'I', 0);
} {
SELECT * FROM t1 ORDER BY a;
} {A Z C G H I}
5 {
CREATE TABLE t1(a, b, c);
CREATE INDEX t1c ON t1(c, b);
CREATE TABLE ota.data_t1(a, b, c, ota_rowid, ota_control);
INSERT INTO data_t1 VALUES('a', 'b', 'c', 1, 0);
INSERT INTO data_t1 VALUES('d', 'e', 'f', '2', 0);
} {
SELECT * FROM t1 ORDER BY a;
} {a b c d e f}
} {
catch {db close}
forcedelete ota.db test.db
sqlite3 db test.db
execsql {
PRAGMA encoding = utf16;
ATTACH 'ota.db' AS ota;
}
execsql $setup
db close
forcecopy test.db test.db.bak
forcecopy ota.db ota.db.bak
foreach {tn f reslist} {
1 oom-tra* {
{0 SQLITE_DONE}
{1 {SQLITE_NOMEM - out of memory}}
{1 SQLITE_NOMEM}
{1 SQLITE_IOERR_NOMEM}
{1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}}
}
2 ioerr-* {
{0 SQLITE_DONE}
{1 {SQLITE_IOERR - disk I/O error}}
{1 SQLITE_IOERR}
{1 SQLITE_IOERR_WRITE}
{1 SQLITE_IOERR_READ}
{1 SQLITE_IOERR_FSYNC}
{1 {SQLITE_ERROR - SQL logic error or missing database}}
{1 {SQLITE_ERROR - unable to open database: ota.db}}
{1 {SQLITE_IOERR - unable to open database: ota.db}}
}
3 shmerr-* {
{0 SQLITE_DONE}
{1 {SQLITE_IOERR - disk I/O error}}
{1 SQLITE_IOERR}
}
} {
catch {db close}
sqlite3_shutdown
set lookaside_config [sqlite3_config_lookaside 0 0]
sqlite3_initialize
autoinstall_test_functions
do_faultsim_test 2.$tn2 -faults $::f -prep {
catch { db close }
forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal
forcecopy test.db.bak test.db
forcecopy ota.db.bak ota.db
} -body {
sqlite3ota ota test.db ota.db
while {[ota step]=="SQLITE_OK"} {}
ota close
} -test {
faultsim_test_result {*}$::reslist
if {$testrc==0} {
sqlite3 db test.db
faultsim_integrity_check
set res [db eval $::sql]
if {$res != [list {*}$::expect]} {
puts ""
puts "res: $res"
puts "exp: $expect"
error "data not as expected!"
}
}
}
catch {db close}
sqlite3_shutdown
sqlite3_config_lookaside {*}$lookaside_config
sqlite3_initialize
autoinstall_test_functions
for {set iStep 0} {$iStep<=21} {incr iStep} {
forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal
copy_if_exists test.db.bak test.db
copy_if_exists ota.db.bak ota.db
sqlite3ota ota test.db ota.db
for {set x 0} {$x < $::iStep} {incr x} { ota step }
ota close
# sqlite3 x ota.db ; puts "XYZ [x eval { SELECT * FROM ota_state } ]" ; x close
copy_if_exists test.db test.db.bak.2
copy_if_exists test.db-wal test.db.bak.2-wal
copy_if_exists test.db-oal test.db.bak.2-oal
copy_if_exists ota.db ota.db.bak.2
do_faultsim_test 3.$tn.$iStep -faults $::f -prep {
catch { db close }
forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal
copy_if_exists test.db.bak.2 test.db
copy_if_exists test.db.bak.2-wal test.db-wal
copy_if_exists test.db.bak.2-oal test.db-oal
copy_if_exists ota.db.bak.2 ota.db
} -body {
sqlite3ota ota test.db ota.db
ota step
ota close
} -test {
if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"}
faultsim_test_result {*}$::reslist
if {$testrc==0} {
# No error occurred. If the OTA has not already been fully applied,
# apply the rest of it now. Then ensure that the final state of the
# target db is as expected. And that "PRAGMA integrity_check"
# passes.
sqlite3ota ota test.db ota.db
while {[ota step] == "SQLITE_OK"} {}
ota close
sqlite3 db test.db
faultsim_integrity_check
set res [db eval $::sql]
if {$res != [list {*}$::expect]} {
puts ""
puts "res: $res"
puts "exp: $::expect"
error "data not as expected!"
}
}
}
}
}
}
finish_test
-58
View File
@@ -1,58 +0,0 @@
# 2014 October 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set ::testprefix otafault2
forcedelete ota.db
do_execsql_test 1.0 {
CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y));
INSERT INTO target VALUES(1, 2, 3);
INSERT INTO target VALUES(4, 5, 6);
ATTACH 'ota.db' AS ota;
CREATE TABLE ota.data_target(x, y, z, ota_control);
INSERT INTO data_target VALUES(7, 8, 9, 0);
INSERT INTO data_target VALUES(1, 11, 12, 0);
DETACH ota;
}
db close
forcecopy test.db test.db-bak
forcecopy ota.db ota.db-bak
do_faultsim_test 1 -faults oom* -prep {
forcecopy test.db-bak test.db
forcecopy ota.db-bak ota.db
forcedelete test.db-oal test.db-wal ota.db-journal
sqlite3ota ota test.db ota.db
} -body {
while {[ota step]=="SQLITE_OK"} { }
ota close
} -test {
faultsim_test_result \
{1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: target.x}} \
{1 SQLITE_CONSTRAINT} \
{1 SQLITE_NOMEM} \
{1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}} \
{1 {SQLITE_NOMEM - out of memory}}
}
finish_test
-3661
View File
File diff suppressed because it is too large Load Diff
-419
View File
@@ -1,419 +0,0 @@
/*
** 2014 August 30
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains the public interface for the OTA extension.
*/
/*
** SUMMARY
**
** Writing a transaction containing a large number of operations on
** b-tree indexes that are collectively larger than the available cache
** memory can be very inefficient.
**
** The problem is that in order to update a b-tree, the leaf page (at least)
** containing the entry being inserted or deleted must be modified. If the
** working set of leaves is larger than the available cache memory, then a
** single leaf that is modified more than once as part of the transaction
** may be loaded from or written to the persistent media multiple times.
** Additionally, because the index updates are likely to be applied in
** random order, access to pages within the database is also likely to be in
** random order, which is itself quite inefficient.
**
** One way to improve the situation is to sort the operations on each index
** by index key before applying them to the b-tree. This leads to an IO
** pattern that resembles a single linear scan through the index b-tree,
** and all but guarantees each modified leaf page is loaded and stored
** exactly once. SQLite uses this trick to improve the performance of
** CREATE INDEX commands. This extension allows it to be used to improve
** the performance of large transactions on existing databases.
**
** Additionally, this extension allows the work involved in writing the
** large transaction to be broken down into sub-transactions performed
** sequentially by separate processes. This is useful if the system cannot
** guarantee that a single update process will run for long enough to apply
** the entire update, for example because the update is being applied on a
** mobile device that is frequently rebooted. Even after the writer process
** has committed one or more sub-transactions, other database clients continue
** to read from the original database snapshot. In other words, partially
** applied transactions are not visible to other clients.
**
** "OTA" stands for "Over The Air" update. As in a large database update
** transmitted via a wireless network to a mobile device. A transaction
** applied using this extension is hence refered to as an "OTA update".
**
**
** LIMITATIONS
**
** An "OTA update" transaction is subject to the following limitations:
**
** * The transaction must consist of INSERT, UPDATE and DELETE operations
** only.
**
** * INSERT statements may not use any default values.
**
** * UPDATE and DELETE statements must identify their target rows by
** non-NULL PRIMARY KEY values. Rows with NULL values stored in PRIMARY
** KEY fields may not be updated or deleted. If the table being written
** has no PRIMARY KEY, affected rows must be identified by rowid.
**
** * UPDATE statements may not modify PRIMARY KEY columns.
**
** * No triggers will be fired.
**
** * No foreign key violations are detected or reported.
**
** * CHECK constraints are not enforced.
**
** * No constraint handling mode except for "OR ROLLBACK" is supported.
**
**
** PREPARATION
**
** An "OTA update" is stored as a separate SQLite database. A database
** containing an OTA update is an "OTA database". For each table in the
** target database to be updated, the OTA database should contain a table
** named "data_<target name>" containing the same set of columns as the
** target table, and one more - "ota_control". The data_% table should
** have no PRIMARY KEY or UNIQUE constraints, but each column should have
** the same type as the corresponding column in the target database.
** The "ota_control" column should have no type at all. For example, if
** the target database contains:
**
** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE);
**
** Then the OTA database should contain:
**
** CREATE TABLE data_t1(a INTEGER, b TEXT, c, ota_control);
**
** The order of the columns in the data_% table does not matter.
**
** If the target database table is a virtual table or a table that has no
** PRIMARY KEY declaration, the data_% table must also contain a column
** named "ota_rowid". This column is mapped to the tables implicit primary
** key column - "rowid". Virtual tables for which the "rowid" column does
** not function like a primary key value cannot be updated using OTA. For
** example, if the target db contains either of the following:
**
** CREATE VIRTUAL TABLE x1 USING fts3(a, b);
** CREATE TABLE x1(a, b)
**
** then the OTA database should contain:
**
** CREATE TABLE data_x1(a, b, ota_rowid, ota_control);
**
** All non-hidden columns (i.e. all columns matched by "SELECT *") of the
** target table must be present in the input table. For virtual tables,
** hidden columns are optional - they are updated by OTA if present in
** the input table, or not otherwise. For example, to write to an fts4
** table with a hidden languageid column such as:
**
** CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid');
**
** Either of the following input table schemas may be used:
**
** CREATE TABLE data_ft1(a, b, langid, ota_rowid, ota_control);
** CREATE TABLE data_ft1(a, b, ota_rowid, ota_control);
**
** For each row to INSERT into the target database as part of the OTA
** update, the corresponding data_% table should contain a single record
** with the "ota_control" column set to contain integer value 0. The
** other columns should be set to the values that make up the new record
** to insert.
**
** If the target database table has an INTEGER PRIMARY KEY, it is not
** possible to insert a NULL value into the IPK column. Attempting to
** do so results in an SQLITE_MISMATCH error.
**
** For each row to DELETE from the target database as part of the OTA
** update, the corresponding data_% table should contain a single record
** with the "ota_control" column set to contain integer value 1. The
** real primary key values of the row to delete should be stored in the
** corresponding columns of the data_% table. The values stored in the
** other columns are not used.
**
** For each row to UPDATE from the target database as part of the OTA
** update, the corresponding data_% table should contain a single record
** with the "ota_control" column set to contain a value of type text.
** The real primary key values identifying the row to update should be
** stored in the corresponding columns of the data_% table row, as should
** the new values of all columns being update. The text value in the
** "ota_control" column must contain the same number of characters as
** there are columns in the target database table, and must consist entirely
** of 'x' and '.' characters (or in some special cases 'd' - see below). For
** each column that is being updated, the corresponding character is set to
** 'x'. For those that remain as they are, the corresponding character of the
** ota_control value should be set to '.'. For example, given the tables
** above, the update statement:
**
** UPDATE t1 SET c = 'usa' WHERE a = 4;
**
** is represented by the data_t1 row created by:
**
** INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..x');
**
** Instead of an 'x' character, characters of the ota_control value specified
** for UPDATEs may also be set to 'd'. In this case, instead of updating the
** target table with the value stored in the corresponding data_% column, the
** user-defined SQL function "ota_delta()" is invoked and the result stored in
** the target table column. ota_delta() is invoked with two arguments - the
** original value currently stored in the target table column and the
** value specified in the data_xxx table.
**
** For example, this row:
**
** INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..d');
**
** is similar to an UPDATE statement such as:
**
** UPDATE t1 SET c = ota_delta(c, 'usa') WHERE a = 4;
**
** If the target database table is a virtual table or a table with no PRIMARY
** KEY, the ota_control value should not include a character corresponding
** to the ota_rowid value. For example, this:
**
** INSERT INTO data_ft1(a, b, ota_rowid, ota_control)
** VALUES(NULL, 'usa', 12, '.x');
**
** causes a result similar to:
**
** UPDATE ft1 SET b = 'usa' WHERE rowid = 12;
**
** The data_xxx tables themselves should have no PRIMARY KEY declarations.
** However, OTA is more efficient if reading the rows in from each data_xxx
** table in "rowid" order is roughly the same as reading them sorted by
** the PRIMARY KEY of the corresponding target database table. In other
** words, rows should be sorted using the destination table PRIMARY KEY
** fields before they are inserted into the data_xxx tables.
**
** USAGE
**
** The API declared below allows an application to apply an OTA update
** stored on disk to an existing target database. Essentially, the
** application:
**
** 1) Opens an OTA handle using the sqlite3ota_open() function.
**
** 2) Registers any required virtual table modules with the database
** handle returned by sqlite3ota_db(). Also, if required, register
** the ota_delta() implementation.
**
** 3) Calls the sqlite3ota_step() function one or more times on
** the new handle. Each call to sqlite3ota_step() performs a single
** b-tree operation, so thousands of calls may be required to apply
** a complete update.
**
** 4) Calls sqlite3ota_close() to close the OTA update handle. If
** sqlite3ota_step() has been called enough times to completely
** apply the update to the target database, then the OTA database
** is marked as fully applied. Otherwise, the state of the OTA
** update application is saved in the OTA database for later
** resumption.
**
** See comments below for more detail on APIs.
**
** If an update is only partially applied to the target database by the
** time sqlite3ota_close() is called, various state information is saved
** within the OTA database. This allows subsequent processes to automatically
** resume the OTA update from where it left off.
**
** To remove all OTA extension state information, returning an OTA database
** to its original contents, it is sufficient to drop all tables that begin
** with the prefix "ota_"
**
** DATABASE LOCKING
**
** An OTA update may not be applied to a database in WAL mode. Attempting
** to do so is an error (SQLITE_ERROR).
**
** While an OTA handle is open, a SHARED lock may be held on the target
** database file. This means it is possible for other clients to read the
** database, but not to write it.
**
** If an OTA update is started and then suspended before it is completed,
** then an external client writes to the database, then attempting to resume
** the suspended OTA update is also an error (SQLITE_BUSY).
*/
#ifndef _SQLITE3OTA_H
#define _SQLITE3OTA_H
#include "sqlite3.h" /* Required for error code definitions */
typedef struct sqlite3ota sqlite3ota;
/*
** Open an OTA handle.
**
** Argument zTarget is the path to the target database. Argument zOta is
** the path to the OTA database. Each call to this function must be matched
** by a call to sqlite3ota_close(). When opening the databases, OTA passes
** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget
** or zOta begin with "file:", it will be interpreted as an SQLite
** database URI, not a regular file name.
**
** If the zState argument is passed a NULL value, the OTA extension stores
** the current state of the update (how many rows have been updated, which
** indexes are yet to be updated etc.) within the OTA database itself. This
** can be convenient, as it means that the OTA application does not need to
** organize removing a separate state file after the update is concluded.
** Or, if zState is non-NULL, it must be a path to a database file in which
** the OTA extension can store the state of the update.
**
** When resuming an OTA update, the zState argument must be passed the same
** value as when the OTA update was started.
**
** Once the OTA update is finished, the OTA extension does not
** automatically remove any zState database file, even if it created it.
**
** By default, OTA uses the default VFS to access the files on disk. To
** use a VFS other than the default, an SQLite "file:" URI containing a
** "vfs=..." option may be passed as the zTarget option.
**
** IMPORTANT NOTE FOR ZIPVFS USERS: The OTA extension works with all of
** SQLite's built-in VFSs, including the multiplexor VFS. However it does
** not work out of the box with zipvfs. Refer to the comment describing
** the zipvfs_create_vfs() API below for details on using OTA with zipvfs.
*/
sqlite3ota *sqlite3ota_open(
const char *zTarget,
const char *zOta,
const char *zState
);
/*
** Internally, each OTA connection uses a separate SQLite database
** connection to access the target and ota update databases. This
** API allows the application direct access to these database handles.
**
** The first argument passed to this function must be a valid, open, OTA
** handle. The second argument should be passed zero to access the target
** database handle, or non-zero to access the ota update database handle.
** Accessing the underlying database handles may be useful in the
** following scenarios:
**
** * If any target tables are virtual tables, it may be necessary to
** call sqlite3_create_module() on the target database handle to
** register the required virtual table implementations.
**
** * If the data_xxx tables in the OTA source database are virtual
** tables, the application may need to call sqlite3_create_module() on
** the ota update db handle to any required virtual table
** implementations.
**
** * If the application uses the "ota_delta()" feature described above,
** it must use sqlite3_create_function() or similar to register the
** ota_delta() implementation with the target database handle.
**
** If an error has occurred, either while opening or stepping the OTA object,
** this function may return NULL. The error code and message may be collected
** when sqlite3ota_close() is called.
*/
sqlite3 *sqlite3ota_db(sqlite3ota*, int bOta);
/*
** Do some work towards applying the OTA update to the target db.
**
** Return SQLITE_DONE if the update has been completely applied, or
** SQLITE_OK if no error occurs but there remains work to do to apply
** the OTA update. If an error does occur, some other error code is
** returned.
**
** Once a call to sqlite3ota_step() has returned a value other than
** SQLITE_OK, all subsequent calls on the same OTA handle are no-ops
** that immediately return the same value.
*/
int sqlite3ota_step(sqlite3ota *pOta);
/*
** Close an OTA handle.
**
** If the OTA update has been completely applied, mark the OTA database
** as fully applied. Otherwise, assuming no error has occurred, save the
** current state of the OTA update appliation to the OTA database.
**
** If an error has already occurred as part of an sqlite3ota_step()
** or sqlite3ota_open() call, or if one occurs within this function, an
** SQLite error code is returned. Additionally, *pzErrmsg may be set to
** point to a buffer containing a utf-8 formatted English language error
** message. It is the responsibility of the caller to eventually free any
** such buffer using sqlite3_free().
**
** Otherwise, if no error occurs, this function returns SQLITE_OK if the
** update has been partially applied, or SQLITE_DONE if it has been
** completely applied.
*/
int sqlite3ota_close(sqlite3ota *pOta, char **pzErrmsg);
/*
** Return the total number of key-value operations (inserts, deletes or
** updates) that have been performed on the target database since the
** current OTA update was started.
*/
sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta);
/*
** Create an OTA VFS named zName that accesses the underlying file-system
** via existing VFS zParent. Or, if the zParent parameter is passed NULL,
** then the new OTA VFS uses the default system VFS to access the file-system.
** The new object is registered as a non-default VFS with SQLite before
** returning.
**
** Part of the OTA implementation uses a custom VFS object. Usually, this
** object is created and deleted automatically by OTA.
**
** The exception is for applications that also use zipvfs. In this case,
** the custom VFS must be explicitly created by the user before the OTA
** handle is opened. The OTA VFS should be installed so that the zipvfs
** VFS uses the OTA VFS, which in turn uses any other VFS layers in use
** (for example multiplexor) to access the file-system. For example,
** to assemble an OTA enabled VFS stack that uses both zipvfs and
** multiplexor (error checking omitted):
**
** // Create a VFS named "multiplex" (not the default).
** sqlite3_multiplex_initialize(0, 0);
**
** // Create an ota VFS named "ota" that uses multiplexor. If the
** // second argument were replaced with NULL, the "ota" VFS would
** // access the file-system via the system default VFS, bypassing the
** // multiplexor.
** sqlite3ota_create_vfs("ota", "multiplex");
**
** // Create a zipvfs VFS named "zipvfs" that uses ota.
** zipvfs_create_vfs_v3("zipvfs", "ota", 0, xCompressorAlgorithmDetector);
**
** // Make zipvfs the default VFS.
** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1);
**
** Because the default VFS created above includes a OTA functionality, it
** may be used by OTA clients. Attempting to use OTA with a zipvfs VFS stack
** that does not include the OTA layer results in an error.
**
** The overhead of adding the "ota" VFS to the system is negligible for
** non-OTA users. There is no harm in an application accessing the
** file-system via "ota" all the time, even if it only uses OTA functionality
** occasionally.
*/
int sqlite3ota_create_vfs(const char *zName, const char *zParent);
/*
** Deregister and destroy an OTA vfs created by an earlier call to
** sqlite3ota_create_vfs().
**
** VFS objects are not reference counted. If a VFS object is destroyed
** before all database handles that use it have been closed, the results
** are undefined.
*/
void sqlite3ota_destroy_vfs(const char *zName);
#endif /* _SQLITE3OTA_H */
-247
View File
@@ -1,247 +0,0 @@
/*
** 2015 February 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.
**
*************************************************************************
*/
#include "sqlite3.h"
#if defined(SQLITE_TEST)
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA)
#include "sqlite3ota.h"
#include <tcl.h>
#include <assert.h>
/* From main.c (apparently...) */
extern const char *sqlite3ErrName(int);
void test_ota_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
Tcl_Obj *pScript;
int i;
pScript = Tcl_NewObj();
Tcl_IncrRefCount(pScript);
Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("ota_delta", -1));
for(i=0; i<nArg; i++){
sqlite3_value *pIn = apVal[i];
const char *z = (const char*)sqlite3_value_text(pIn);
Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1));
}
if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){
const char *z = Tcl_GetStringResult(interp);
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
}else{
Tcl_BackgroundError(interp);
}
Tcl_DecrRefCount(pScript);
}
static int test_sqlite3ota_cmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
int ret = TCL_OK;
sqlite3ota *pOta = (sqlite3ota*)clientData;
const char *azMethod[] = { "step", "close", "create_ota_delta", 0 };
int iMethod;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
return TCL_ERROR;
}
if( Tcl_GetIndexFromObj(interp, objv[1], azMethod, "method", 0, &iMethod) ){
return TCL_ERROR;
}
switch( iMethod ){
case 0: /* step */ {
int rc = sqlite3ota_step(pOta);
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
break;
}
case 1: /* close */ {
char *zErrmsg = 0;
int rc;
Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
rc = sqlite3ota_close(pOta, &zErrmsg);
if( rc==SQLITE_OK || rc==SQLITE_DONE ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
assert( zErrmsg==0 );
}else{
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
if( zErrmsg ){
Tcl_AppendResult(interp, " - ", zErrmsg, 0);
sqlite3_free(zErrmsg);
}
ret = TCL_ERROR;
}
break;
}
case 2: /* create_ota_delta */ {
sqlite3 *db = sqlite3ota_db(pOta, 0);
int rc = sqlite3_create_function(
db, "ota_delta", -1, SQLITE_UTF8, (void*)interp, test_ota_delta, 0, 0
);
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
break;
}
default: /* seems unlikely */
assert( !"cannot happen" );
break;
}
return ret;
}
/*
** Tclcmd: sqlite3ota CMD <target-db> <ota-db> ?<state-db>?
*/
static int test_sqlite3ota(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3ota *pOta = 0;
const char *zCmd;
const char *zTarget;
const char *zOta;
const char *zStateDb = 0;
if( objc!=4 && objc!=5 ){
Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB OTA-DB ?STATE-DB?");
return TCL_ERROR;
}
zCmd = Tcl_GetString(objv[1]);
zTarget = Tcl_GetString(objv[2]);
zOta = Tcl_GetString(objv[3]);
if( objc==5 ) zStateDb = Tcl_GetString(objv[4]);
pOta = sqlite3ota_open(zTarget, zOta, zStateDb);
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3ota_cmd, (ClientData)pOta, 0);
Tcl_SetObjResult(interp, objv[1]);
return TCL_OK;
}
/*
** Tclcmd: sqlite3ota_create_vfs ?-default? NAME PARENT
*/
static int test_sqlite3ota_create_vfs(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
const char *zName;
const char *zParent;
int rc;
if( objc!=3 && objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT");
return TCL_ERROR;
}
zName = Tcl_GetString(objv[objc-2]);
zParent = Tcl_GetString(objv[objc-1]);
if( zParent[0]=='\0' ) zParent = 0;
rc = sqlite3ota_create_vfs(zName, zParent);
if( rc!=SQLITE_OK ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
return TCL_ERROR;
}else if( objc==4 ){
sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
sqlite3_vfs_register(pVfs, 1);
}
Tcl_ResetResult(interp);
return TCL_OK;
}
/*
** Tclcmd: sqlite3ota_destroy_vfs NAME
*/
static int test_sqlite3ota_destroy_vfs(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
const char *zName;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "NAME");
return TCL_ERROR;
}
zName = Tcl_GetString(objv[1]);
sqlite3ota_destroy_vfs(zName);
return TCL_OK;
}
/*
** Tclcmd: sqlite3ota_internal_test
*/
static int test_sqlite3ota_internal_test(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db;
if( objc!=1 ){
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
db = sqlite3ota_db(0, 0);
if( db!=0 ){
Tcl_AppendResult(interp, "sqlite3ota_db(0, 0)!=0", 0);
return TCL_ERROR;
}
return TCL_OK;
}
int SqliteOta_Init(Tcl_Interp *interp){
static struct {
char *zName;
Tcl_ObjCmdProc *xProc;
} aObjCmd[] = {
{ "sqlite3ota", test_sqlite3ota },
{ "sqlite3ota_create_vfs", test_sqlite3ota_create_vfs },
{ "sqlite3ota_destroy_vfs", test_sqlite3ota_destroy_vfs },
{ "sqlite3ota_internal_test", test_sqlite3ota_internal_test },
};
int i;
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
}
return TCL_OK;
}
#else
#include <tcl.h>
int SqliteOta_Init(Tcl_Interp *interp){ return TCL_OK; }
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) */
#endif /* defined(SQLITE_TEST) */
+10 -54
View File
@@ -351,7 +351,6 @@ struct RtreeMatchArg {
u32 magic; /* Always RTREE_GEOMETRY_MAGIC */
RtreeGeomCallback cb; /* Info about the callback functions */
int nParam; /* Number of parameters to the SQL function */
sqlite3_value **apSqlParam; /* Original SQL parameter values */
RtreeDValue aParam[1]; /* Values for parameters to the SQL function */
};
@@ -1483,7 +1482,9 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
/* Check that the blob is roughly the right size. */
nBlob = sqlite3_value_bytes(pValue);
if( nBlob<(int)sizeof(RtreeMatchArg) ){
if( nBlob<(int)sizeof(RtreeMatchArg)
|| ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0
){
return SQLITE_ERROR;
}
@@ -1494,7 +1495,6 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
memcpy(pBlob, sqlite3_value_blob(pValue), nBlob);
nExpected = (int)(sizeof(RtreeMatchArg) +
pBlob->nParam*sizeof(sqlite3_value*) +
(pBlob->nParam-1)*sizeof(RtreeDValue));
if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){
sqlite3_free(pInfo);
@@ -1503,7 +1503,6 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
pInfo->pContext = pBlob->cb.pContext;
pInfo->nParam = pBlob->nParam;
pInfo->aParam = pBlob->aParam;
pInfo->apSqlParam = pBlob->apSqlParam;
if( pBlob->cb.xGeom ){
pCons->u.xGeom = pBlob->cb.xGeom;
@@ -1670,30 +1669,17 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
Rtree *pRtree = (Rtree*)tab;
int rc = SQLITE_OK;
int ii;
int bMatch = 0; /* True if there exists a MATCH constraint */
i64 nRow; /* Estimated rows returned by this scan */
int iIdx = 0;
char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];
memset(zIdxStr, 0, sizeof(zIdxStr));
/* Check if there exists a MATCH constraint - even an unusable one. If there
** is, do not consider the lookup-by-rowid plan as using such a plan would
** require the VDBE to evaluate the MATCH constraint, which is not currently
** possible. */
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){
bMatch = 1;
}
}
assert( pIdxInfo->idxStr==0 );
for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
if( bMatch==0 && p->usable
&& p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
){
if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
/* We have an equality constraint on the rowid. Use strategy 1. */
int jj;
for(jj=0; jj<ii; jj++){
@@ -2834,19 +2820,11 @@ static int rtreeUpdate(
if( nData>1 ){
int ii;
/* Populate the cell.aCoord[] array. The first coordinate is azData[3].
**
** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
** with "column" that are interpreted as table constraints.
** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
** This problem was discovered after years of use, so we silently ignore
** these kinds of misdeclared tables to avoid breaking any legacy.
*/
assert( nData<=(pRtree->nDim*2 + 3) );
/* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
assert( nData==(pRtree->nDim*2 + 3) );
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
for(ii=0; ii<nData-4; ii+=2){
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
@@ -2857,7 +2835,7 @@ static int rtreeUpdate(
}else
#endif
{
for(ii=0; ii<nData-4; ii+=2){
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
@@ -3386,18 +3364,6 @@ static void rtreeFreeCallback(void *p){
sqlite3_free(p);
}
/*
** This routine frees the BLOB that is returned by geomCallback().
*/
static void rtreeMatchArgFree(void *pArg){
int i;
RtreeMatchArg *p = (RtreeMatchArg*)pArg;
for(i=0; i<p->nParam; i++){
sqlite3_value_free(p->apSqlParam[i]);
}
sqlite3_free(p);
}
/*
** Each call to sqlite3_rtree_geometry_callback() or
** sqlite3_rtree_query_callback() creates an ordinary SQLite
@@ -3416,10 +3382,8 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
RtreeMatchArg *pBlob;
int nBlob;
int memErr = 0;
nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
+ nArg*sizeof(sqlite3_value*);
nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue);
pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
if( !pBlob ){
sqlite3_result_error_nomem(ctx);
@@ -3427,23 +3391,15 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
int i;
pBlob->magic = RTREE_GEOMETRY_MAGIC;
pBlob->cb = pGeomCtx[0];
pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg];
pBlob->nParam = nArg;
for(i=0; i<nArg; i++){
pBlob->apSqlParam[i] = sqlite3_value_dup(aArg[i]);
if( pBlob->apSqlParam[i]==0 ) memErr = 1;
#ifdef SQLITE_RTREE_INT_ONLY
pBlob->aParam[i] = sqlite3_value_int64(aArg[i]);
#else
pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
#endif
}
if( memErr ){
sqlite3_result_error_nomem(ctx);
rtreeMatchArgFree(pBlob);
}else{
sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree);
}
sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free);
}
}
+1
View File
@@ -87,6 +87,7 @@ do_catchsql_test rtree9-4.3 {
#
register_circle_geom db
breakpoint
do_execsql_test rtree9-5.1 {
CREATE VIRTUAL TABLE rt2 USING rtree(id, xmin, xmax, ymin, ymax);
-83
View File
@@ -269,88 +269,5 @@ ifcapable rtree {
db close
}
#--------------------------------------------------------------------
# Test that queries featuring LEFT or CROSS JOINS are handled correctly.
# Handled correctly in this case means:
#
# * Terms with prereqs that appear to the left of a LEFT JOIN against
# the virtual table are always available to xBestIndex.
#
# * Terms with prereqs that appear to the right of a LEFT JOIN against
# the virtual table are never available to xBestIndex.
#
# And the same behaviour for CROSS joins.
#
reset_db
do_execsql_test 7.0 {
CREATE TABLE xdir(x1);
CREATE TABLE ydir(y1);
CREATE VIRTUAL TABLE rt USING rtree_i32(id, xmin, xmax, ymin, ymax);
INSERT INTO xdir VALUES(5);
INSERT INTO ydir VALUES(10);
INSERT INTO rt VALUES(1, 2, 7, 12, 14); -- Not a hit
INSERT INTO rt VALUES(2, 2, 7, 8, 12); -- A hit!
INSERT INTO rt VALUES(3, 7, 11, 8, 12); -- Not a hit!
INSERT INTO rt VALUES(4, 5, 5, 10, 10); -- A hit!
}
proc do_eqp_execsql_test {tn sql res} {
set query "EXPLAIN QUERY PLAN $sql ; $sql "
uplevel [list do_execsql_test $tn $query $res]
}
do_eqp_execsql_test 7.1 {
SELECT id FROM xdir, rt, ydir
ON (y1 BETWEEN ymin AND ymax)
WHERE (x1 BETWEEN xmin AND xmax);
} {
0 0 0 {SCAN TABLE xdir}
0 1 2 {SCAN TABLE ydir}
0 2 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1}
2 4
}
do_eqp_execsql_test 7.2 {
SELECT * FROM xdir, rt LEFT JOIN ydir
ON (y1 BETWEEN ymin AND ymax)
WHERE (x1 BETWEEN xmin AND xmax);
} {
0 0 0 {SCAN TABLE xdir}
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
0 2 2 {SCAN TABLE ydir}
5 1 2 7 12 14 {}
5 2 2 7 8 12 10
5 4 5 5 10 10 10
}
do_eqp_execsql_test 7.3 {
SELECT id FROM xdir, rt CROSS JOIN ydir
ON (y1 BETWEEN ymin AND ymax)
WHERE (x1 BETWEEN xmin AND xmax);
} {
0 0 0 {SCAN TABLE xdir}
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
0 2 2 {SCAN TABLE ydir}
2 4
}
do_eqp_execsql_test 7.4 {
SELECT id FROM rt, xdir CROSS JOIN ydir
ON (y1 BETWEEN ymin AND ymax)
WHERE (x1 BETWEEN xmin AND xmax);
} {
0 0 1 {SCAN TABLE xdir}
0 1 0 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
0 2 2 {SCAN TABLE ydir}
2 4
}
finish_test
finish_test
+2 -13
View File
@@ -52,9 +52,6 @@ do_execsql_test rtreeE-1.1 {
do_execsql_test rtreeE-1.1 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 0.0, 50.0, 3) ORDER BY id;
} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24}
do_execsql_test rtreeE-1.1x {
SELECT id FROM rt1 WHERE id MATCH Qcircle('x:0 y:0 r:50.0 e:3') ORDER BY id;
} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24}
do_execsql_test rtreeE-1.2 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(100.0, 0.0, 50.0, 3) ORDER BY id;
} {100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124}
@@ -67,12 +64,12 @@ do_execsql_test rtreeE-1.3 {
# last.
#
do_execsql_test rtreeE-1.4 {
SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:3') AND id%100==0
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,3) AND id%100==0
} {200 100 0}
# Exclude odd rowids on a depth-first search
do_execsql_test rtreeE-1.5 {
SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:4') ORDER BY +id
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,4) ORDER BY +id
} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224}
# Exclude odd rowids on a breadth-first search.
@@ -80,13 +77,6 @@ do_execsql_test rtreeE-1.6 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id
} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224}
# Test that rtree prefers MATCH to lookup-by-rowid.
#
do_execsql_test rtreeE-1.7 {
SELECT id FROM rt1 WHERE id=18 AND id MATCH Qcircle(0,0,1000,5)
} {18}
# Construct a large 2-D RTree with thousands of random entries.
#
do_test rtreeE-2.1 {
@@ -136,5 +126,4 @@ do_execsql_test rtreeE-2.4 {
SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id
} $ans
finish_test
-2
View File
@@ -98,8 +98,6 @@ struct sqlite3_rtree_query_info {
int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visiblity */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
};
/*
+20 -94
View File
@@ -53,7 +53,7 @@ TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth
LIBOBJ+= vdbe.o parse.o \
alter.o analyze.o attach.o auth.o \
backup.o bitvec.o btmutex.o btree.o build.o \
callback.o complete.o ctime.o date.o dbstat.o delete.o expr.o fault.o fkey.o \
callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
fts3_tokenize_vtab.o \
@@ -65,12 +65,11 @@ LIBOBJ+= vdbe.o parse.o \
mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
notify.o opcodes.o os.o os_unix.o os_win.o \
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
random.o resolve.o rowset.o rtree.o select.o sqlite3ota.o status.o \
table.o threads.o tokenize.o treeview.o trigger.o \
random.o resolve.o rowset.o rtree.o select.o status.o \
table.o threads.o tokenize.o trigger.o \
update.o userauth.o util.o vacuum.o \
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \
utf.o vtab.o
vdbetrace.o wal.o walker.o where.o utf.o vtab.o
@@ -92,7 +91,6 @@ SRC = \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
$(TOP)/src/fault.c \
@@ -152,7 +150,6 @@ SRC = \
$(TOP)/src/tclsqlite.c \
$(TOP)/src/threads.c \
$(TOP)/src/tokenize.c \
$(TOP)/src/treeview.c \
$(TOP)/src/trigger.c \
$(TOP)/src/utf.c \
$(TOP)/src/update.c \
@@ -173,8 +170,6 @@ SRC = \
$(TOP)/src/wal.h \
$(TOP)/src/walker.c \
$(TOP)/src/where.c \
$(TOP)/src/wherecode.c \
$(TOP)/src/whereexpr.c \
$(TOP)/src/whereInt.h
# Source code for extensions
@@ -225,9 +220,6 @@ SRC += \
SRC += \
$(TOP)/ext/userauth/userauth.c \
$(TOP)/ext/userauth/sqlite3userauth.h
SRC += \
$(TOP)/ext/ota/sqlite3ota.c \
$(TOP)/ext/ota/sqlite3ota.h
# Generated source code files
#
@@ -245,7 +237,6 @@ SRC += \
TESTSRC = \
$(TOP)/ext/fts3/fts3_term.c \
$(TOP)/ext/fts3/fts3_test.c \
$(TOP)/ext/ota/test_ota.c \
$(TOP)/src/test1.c \
$(TOP)/src/test2.c \
$(TOP)/src/test3.c \
@@ -279,6 +270,7 @@ TESTSRC = \
$(TOP)/src/test_rtree.c \
$(TOP)/src/test_schema.c \
$(TOP)/src/test_server.c \
$(TOP)/src/test_stat.c \
$(TOP)/src/test_sqllog.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
@@ -314,7 +306,6 @@ TESTSRC2 = \
$(TOP)/src/btree.c \
$(TOP)/src/build.c \
$(TOP)/src/date.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
$(TOP)/src/insert.c \
@@ -341,15 +332,13 @@ TESTSRC2 = \
$(TOP)/src/vdbe.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/where.c \
$(TOP)/src/wherecode.c \
$(TOP)/src/whereexpr.c \
parse.c \
$(TOP)/ext/fts3/fts3.c \
$(TOP)/ext/fts3/fts3_aux.c \
$(TOP)/ext/fts3/fts3_expr.c \
$(TOP)/ext/fts3/fts3_tokenizer.c \
$(TOP)/ext/fts3/fts3_write.c \
$(TOP)/ext/async/sqlite3async.c
$(TOP)/ext/async/sqlite3async.c
# Header files used by all library source files.
#
@@ -401,25 +390,6 @@ EXTHDR += \
EXTHDR += \
$(TOP)/ext/userauth/sqlite3userauth.h
# executables needed for testing
#
TESTPROGS = \
testfixture$(EXE) \
sqlite3$(EXE) \
sqlite3_analyzer$(EXE) \
sqldiff$(EXE)
# Databases containing fuzzer test cases
#
FUZZDATA = \
$(TOP)/test/fuzzdata1.db \
$(TOP)/test/fuzzdata2.db \
$(TOP)/test/fuzzdata3.db
# Standard options to testfixture
#
TESTOPTS = --verbose=file --output=test-out.txt
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
@@ -436,15 +406,11 @@ sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) $(THREADLIB)
fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\
$(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB)
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) $(THREADLIB)
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
@@ -628,9 +594,6 @@ rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
userauth.o: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
sqlite3ota.o: $(TOP)/ext/ota/sqlite3ota.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/ota/sqlite3ota.c
# Rules for building test programs and for running tests
#
@@ -638,10 +601,9 @@ 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/tclsqlite.c $(TOP)/tool/spaceanal.tcl
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
echo "#define TCLSH 2" > $@
echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
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 >> $@
@@ -671,49 +633,20 @@ fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
fulltest: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/all.test $(TESTOPTS)
fulltest: testfixture$(EXE) sqlite3$(EXE)
./testfixture$(EXE) $(TOP)/test/all.test
soaktest: $(TESTPROGS)
./testfixture$(EXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)
soaktest: testfixture$(EXE) sqlite3$(EXE)
./testfixture$(EXE) $(TOP)/test/all.test -soak=1
fulltestonly: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/full.test $(TESTOPTS)
fulltestonly: testfixture$(EXE) sqlite3$(EXE)
./testfixture$(EXE) $(TOP)/test/full.test
queryplantest: testfixture$(EXE) sqlite3$(EXE)
./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner $(TESTOPTS)
./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner
fuzztest: fuzzcheck$(EXE) $(FUZZDATA)
./fuzzcheck$(EXE) $(FUZZDATA)
valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA)
valgrind ./fuzzcheck$(EXE) --cell-size-check --quiet $(FUZZDATA)
# A very quick test using only testfixture and omitting all the slower
# tests. Designed to run in under 3 minutes on a workstation.
#
quicktest: ./testfixture$(EXE)
./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)
# The default test case. Runs most of the faster standard TCL tests,
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
#
test: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS)
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest: $(TESTPROGS) valgrindfuzz
OMIT_MISUSE=1 valgrind -v \
./testfixture$(EXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)
# A very fast test that checks basic sanity. The name comes from
# the 60s-era electronics testing: "Turn it on and see if smoke
# comes out."
#
smoketest: $(TESTPROGS) fuzzcheck$(EXE)
./testfixture$(EXE) $(TOP)/test/main.test $(TESTOPTS)
test: testfixture$(EXE) sqlite3$(EXE)
./testfixture$(EXE) $(TOP)/test/veryquick.test
# The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This
@@ -771,11 +704,7 @@ wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c
$(TOP)/test/wordcount.c sqlite3.c
speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o
$(TCC) -I. $(OTAFLAGS) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB)
ota$(EXE): $(TOP)/ext/ota/ota.c $(TOP)/ext/ota/sqlite3ota.c sqlite3.o
$(TCC) -I. -o ota$(EXE) $(TOP)/ext/ota/ota.c sqlite3.o \
$(THREADLIB)
$(TCC) -I. -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB)
# 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
@@ -825,6 +754,3 @@ clean:
rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f fuzzershell fuzzershell.exe
rm -f fuzzcheck fuzzcheck.exe
rm -f sqldiff sqldiff.exe
+123 -153
View File
@@ -1,19 +1,19 @@
C More\stest\soutput\srefinements.
D 2015-06-10T23:02:38.561
C Prototype\sfor\san\ssqlite3_db_log()\sinterface.
D 2015-04-22T14:41:19.758
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 1063c58075b7400d93326b0eb332b48a54f53025
F Makefile.in faaf75b89840659d74501bea269c7e33414761c1
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc b7db9ccbbad1c495b98e5326a06cac03aa206127
F Makefile.msc 32d8fe89ac5c130f9f14293fb4a59b120895c943
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
F VERSION 2e244662b71e6e68a5c29b014ebc5b7564f4cc5a
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am 27de1af382c82e81f1fe36a7f38528fba004eb1a
F autoconf/Makefile.am 8fc2972d92769cf20ab8e4a73ea901b84d69bf44
F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x
@@ -38,8 +38,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 17bd8dc3e35c718df68d04f53bf7dacf2b639732 x
F configure.ac 713de38000413e469188db2cb85bed759b56f322
F configure 2ea5f5b58dd106da449ab598ab6e515339d7fa2a x
F configure.ac 0b775d383c536bbaafc1e46dd3cbb81a7ea11aeb
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
@@ -78,25 +78,25 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c a95de5190cf52f4fa9d5952890399cab63e632b9
F ext/fts3/fts3.c 1b198ddb76cd706722dacbbaeb17a2fde6fca2cc
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 601743955ac43a0e82e6828a931c07bb3b0c95ff
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb
F ext/fts3/fts3Int.h 3626655d6ba903a3919bb44e1c38e5f0f9d6be82
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F ext/fts3/fts3_expr.c 40123785eaa3ebd4c45c9b23407cc44ac0c49905
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
F ext/fts3/fts3_snippet.c 52c2dcf410b1f9af5a44d81a2cf8c68ed1cb5283
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
F ext/fts3/fts3_tokenizer.c 50e7a69a549ac5882cc1971ee43f66aaabc11395
F ext/fts3/fts3_tokenize_vtab.c becc661223db7898b213f9e8a23d75bac02408c9
F ext/fts3/fts3_tokenizer.c 9afd223b07740b14dd589edd3116acacf951fd78
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
F ext/fts3/fts3_write.c 4f005f78592a1447ca96c8475ef5342ab7dbe02a
F ext/fts3/fts3_write.c 7104ec015474ee61a8a570349b925f35c6b0a294
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d
@@ -123,27 +123,8 @@ F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/ota/ota.c c47352838b967384a81eda5de75c352922a0dd6e
F ext/ota/ota1.test abdcbe746db4c7f7b51e842b576cacb33eef28f5
F ext/ota/ota10.test 85e0f6e7964db5007590c1b299e75211ed4240d4
F ext/ota/ota11.test 2f606cd2b4af260a86b549e91b9f395450fc75cb
F ext/ota/ota12.test 0dff44474de448fb4b0b28c20da63273a4149abb
F ext/ota/ota13.test f7a3d73fa5d3fabf2755b569f125fce7390a874c
F ext/ota/ota3.test 3fe3521fbdce32d0e4e116a60999c3cba47712c5
F ext/ota/ota5.test ad0799daf8923ddebffe75ae8c5504ca90b7fadb
F ext/ota/ota6.test 3bde7f69a894748b27206b6753462ec3b75b6bb6
F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a
F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda
F ext/ota/ota9.test d3eee95dd836824d07a22e5efcdb7bf6e869358b
F ext/ota/otaA.test ab67f7f53670b81c750dcc946c5b704f51c429a4
F ext/ota/otacrash.test 8346192b2d46cbe7787d5d65904d81d3262a3cbf
F ext/ota/otafault.test 8c43586c2b96ca16bbce00b5d7e7d67316126db8
F ext/ota/otafault2.test fa202a98ca221faec318f3e5c5f39485b1256561
F ext/ota/sqlite3ota.c 2246b779f46ab20d5e7876f5b96c378c601d20f4
F ext/ota/sqlite3ota.h 00028de37eede471ff1947d455cc3f33d3a911c6
F ext/ota/test_ota.c a876f88550d7d59a3ef62d4c1a5c04c4c2f1ebe1
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 0f9b595bd0debcbedf1d7a63d0e0678d619e6c9c
F ext/rtree/rtree.c 14e6239434d4e3f65d3e90320713f26aa24e167f
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 541bbcab74613907fea08b2ecdcdd5b7aa724cc9
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -153,16 +134,16 @@ F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
F ext/rtree/rtree9.test b5eb13849545dfd271a54ff16784cb00d8792aea
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
F ext/rtree/rtreeC.test 90aaaffe2fd4f0dcd12289cad5515f6d41f45ffd
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
F ext/rtree/rtreeE.test 45a147a64a76306172819562309681d8e90f94bb
F ext/rtree/rtreeE.test 388c1c8602c3ce55c15f03b509e9cf545fb7c41f
F ext/rtree/rtreeF.test 66deb9fd1611c7ca2e374adba63debdc2dbb12b4
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
@@ -171,7 +152,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 68f86c21505d6b66765a13c193f00a53dde6a212
F main.mk 60aba7d38b9bd73e249693344dd8405aa24ac02a
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -185,38 +166,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 48e14b8aea28dc58baafe3cfcb8889c086b7744a
F src/alter.c d23d6b6991f66b383934f137fd4384d93fb98c81
F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b
F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 5166c27883c24768c2f7f53479714f03ef34c612
F src/btree.c 127aceb71ba93f59bc9c6ba810e992a04299e98a
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
F src/build.c 6770b74ccb51cb485e81057c625f77455d5ddc06
F src/build.c e246c2cea69c8f6fc825a156ea2de9dd4a17f18b
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
F src/expr.c 0550baeca8dd7472e298d9e881e5e3484f7666f8
F src/expr.c 5555f768c05d7d4a7840c6c2e72ad7aecbe0fe54
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
F src/func.c 5b8b8e77a0fb644eaf8947d413804622e32692b6
F src/func.c e6b4680d0b6c901365e1ea5a6e75710e9479b70d
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c d6e1623a97ce33e9af2f1a0c1f0085a2f63327ef
F src/insert.c 8176ba5bad8fcef643558ca5708f33ed05a4035a
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c 29255bbe1cfb2ce9bbff2526a5ecfddcb49b9271
F src/main.c 3a610587018485d9a12e38899dd8b8129b04d836
F src/malloc.c 908c780fdddd472163c2d1b1820ae4081f01ad20
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
F src/main.c 453ae1a35c044cb5baa6b11697d722766d3f1569
F src/malloc.c 6a370b83d54e4bbf6f94021221c2a311cff26a18
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -232,35 +212,35 @@ F src/mutex_w32.c 61660ada28d8308ad190f444c2170c4f2a590c2f
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc
F src/os_win.c 27cc135e2d0b8b1e2e4944db1e2669a6a18fa0f8
F src/os_unix.c 5ed7e2e453c2980909a6b2c80dc55764b50819a8
F src/os_win.c 03d27be3a20048ef52a648d5f0a15f5edda9f2a3
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 9bc918a009285f96ec6dac62dd764c7063552455
F src/pager.c 5283581c8ce8950ff483a0b3a3cab9cb4d25a21e
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
F src/parse.y c4e0387bc88c8e21e5ba653e2578959a1f3cdbc7
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
F src/pragma.h b8632d7cdda7b25323fa580e3e558a4f0d4502cc
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/printf.c db11b5960105ee661dcac690f2ae6276e49bf251
F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f
F src/prepare.c 1fffbdcd6f8a0173a8f70d71f22528f4c0e1e3d3
F src/printf.c 9753790eed39d7863a3e33567199f382d980fc28
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 84c571794e3ee5806274d95158a4c0177c6c4708
F src/resolve.c 53486a98c17b7ae09b8c2b398013e973ce4c1aae
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 45a814a755f90c1a6345164d2da4a8ef293da53d
F src/shell.c 07dda7cd692911d2f22269953418d049f2e2c0ee
F src/sqlite.h.in d165beeceb6b40af60f352a4d4e37e02d9af7df0
F src/select.c 35433ea8894ac42594ddc31eb0165a6d6401cfe5
F src/shell.c 78eabce4c16c45e36fea2368f95118116399ba8a
F src/sqlite.h.in 3fb08b501d0155b4ba3ae8ef99c6f08491135dcb
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 2ebeb634e751a61a6f0eebfa0f4669f46a42f6cd
F src/sqliteInt.h 4c6731ce49b90582ea7d77c67b8792a4df8da237
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h 823549bbcb0131e09c4a324080309d049a80e258
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tclsqlite.c 555f6467706905ab02a9df6cf1a84b1774a4754a
F src/test1.c a8e09b811f70184ce65012f27f30cfee7e54f268
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
F src/tclsqlite.c 14f1992dd6100bfeb1a3dec7e7f449e1c814b8ee
F src/test1.c 94efc685eb2e3dda4eb476670eeffaeaf05bead9
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
@@ -272,21 +252,21 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803
F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07
F src/test_blob.c 1f2e3e25255b731c4fcf15ee7990d06347cb6c09
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c 7d28ede476189eefd75252fa9acaadc6ba93a733
F src/test_config.c c2d3ff6c129d50183900c7eff14158ff7e9b3f03
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
F src/test_func.c f1ac201465472e76a73e2f3695c3553c63e7322a
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
F src/test_malloc.c 208f09a4e21defa496bc1094fcfadea19385a112
F src/test_multiplex.c 9fefd23f6cc3fa9bf0748a5e453167e7b9f193ce
F src/test_multiplex.c 4dfb159e5c280c0ebdbf8b5ab9d95bf2765061f9
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10
@@ -294,10 +274,11 @@ F src/test_osinst.c 5423dc1d355f594371f27dd292ca54bd320b8196
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 180813f43683be5725458fc1ff13ac455d8e722d
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c 43fff4c5a01576d6d213f27472598801a247890c
F src/test_rtree.c bfe6f4386517f70054311109f3528adffec34485
F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c b690c12933f50ff46491e0d56a251f84ae16e914
F src/test_stat.c ffc8177f6e69de32a8a89fa6bca73facb6c5face
F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
@@ -306,38 +287,34 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
F src/tokenize.c baa0e550dfa76a8d781732a7bfb1f0aa094942f2
F src/treeview.c 84aa2d2ed26627ccc8dd3a2becfa18dc86ee4607
F src/tokenize.c 8fa8a62632f6f3916bfb6f7b10e1ffbd36de71f0
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c a6431c92803b975b7322724a7b433e538d243539
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c 0a6a1df5c31415a0e974e74e7bd412616889453d
F src/vdbe.c 4f4af7239261189393ca2752a3bf9977c14cb024
F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d
F src/vdbeInt.h f0ccddac48583d5f762dc554a9f79e85ea8807e0
F src/vdbeapi.c 6a0d7757987018ff6b1b81bc5293219cd26bb299
F src/vdbeaux.c 46f9bc4b32866082eb87a36b461e487a0bbdbe8e
F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0
F src/vdbeapi.c d4c9945b2a53b0b71d2a16843bb8d054ce513276
F src/vdbeaux.c aa9b179cc9e6e3e75f8f28e366bb0aafab9d710e
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
F src/vdbemem.c 67b302dc6df64b4d6785881c5d22bd4f9b17739d
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c c535e80259ebe616467181a83a4263555b97c694
F src/vdbemem.c b5256445b318b0f2b3bc429028469cfbb08f19a5
F src/vdbesort.c 2e7f683464fd5db3be4beaa1ff2d39e24fcb64b8
F src/vdbetrace.c f95c2dff9041fcf07f871789c22ebb0648ea0b7c
F src/vtab.c 5f81f8a59c1f5ddb94c918f25ed5d83578fcc633
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
F src/wal.c 753995db83247f20361a8e8a874990b21a75abd9
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c 95c0fbfff7aef890b5da7293f6d85cd9a5f99af8
F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047
F src/wherecode.c 0669481cabaf5caf934b6bb825df15bc57f60d40
F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652
F src/where.c ba0839e75f989dba622809716daabeb9c7fbd3c5
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
F test/alter.test 2facdddf08d0d48e75dc6cc312cd2b030f4835dd
F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec
@@ -357,7 +334,6 @@ F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2
F test/analyzer1.test 498e2ff4b62740c2751c3a2f8b744fe26689fae9
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@@ -377,7 +353,6 @@ F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
F test/autoindex5.test 6f487290ce2a667c24517191651bfb8c7d86b6dc
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
@@ -457,7 +432,7 @@ F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
F test/corruptI.test ddf8c7146db0bc6080eedced67453b4cc69b5340
F test/corruptI.test 221ad8b7f0a9ac6b80fc577e73b5ad8cdea31243
F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91
F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
@@ -510,7 +485,7 @@ F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567
F test/e_walauto.test 6544af03423abc61b53cfb976839385ddc2a0a70
F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608
F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
@@ -518,6 +493,7 @@ F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
F test/errlog01.test 112ea4cd0f2974a63d60fe96d322af0f383045d4
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
@@ -526,9 +502,8 @@ F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
@@ -603,9 +578,9 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708
F test/fts3d.test 95c17d1b67b33a5eac0bf5a0d11116a0c0ac7a3a
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468
F test/fts3defer2.test e880e3b65bdf999f4746cdaefa65f14a98b9b724
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
@@ -619,11 +594,11 @@ F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test 07009313ad6c082f94d8c9c3228eb8940c93ac71
F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170
F test/fts3query.test c838b18f2b859e15fd31c64be3d79ef1556803ca
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 63dbd687d5bf5191f1b8e6a0977aa9c1e28a7004
@@ -632,12 +607,12 @@ F test/fts3tok1.test 178c050199af8c05299b1ad572514ce1c54b7827
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
F test/fts4check.test 9d9e818fd6cb29c0e007cd6d00447739d4fde430
F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a
F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
F test/fts4incr.test 361960ed3550e781f3f313e17e2182ef9cefc0e9
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
@@ -657,10 +632,6 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzcheck.c a60f926e3fa86c8d33908406d75eec868c22b9ca
F test/fuzzdata1.db b60254eeb6bc11474071b883059662a73c48da7f
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
F test/fuzzdata3.db a6e9bf75b8bfad0b7e60e57038908f4237b9c5d2
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -688,7 +659,7 @@ F test/index.test 4d990005a67a36984e4f1a5f1bdccea8d08da4ee
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test b6ec456cf3b81d9a32123fe7e449bde434db338b
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e
F test/index6.test 3ae54e53c53f2adcacda269237d8e52bdb05a481
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
@@ -710,7 +681,7 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/join.test f9d4a28dec81c6e9dc21b73518e024d73b5ebf57
F test/join.test 52d4d49f86d0cf46926672878c4eaf0da399104a
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -719,7 +690,7 @@ F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode.test 9ee3a78f53d52cca737db69293d15dc41c0cbd36
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
@@ -742,7 +713,7 @@ F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
F test/main.test 16131264ea0c2b93b95201f0c92958e85f2ba11a
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
F test/malloc.test 96939d2d1a6f39667bbebe5bc27c6525f2ab614e
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
F test/malloc5.test 79182b8bffd6d62f77b1a5a8ba8e6bf0e5053b8e
@@ -774,10 +745,10 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
F test/misc1.test 3f1c479c5a093a6280f378c0fbff1c2701486660
F test/misc1.test 783ba75743b2cf71e0f646bf540a6cef57264811
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
F test/misc5.test f96428ea95b3820aafc6f1c50cf48a09e4597ee1
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
@@ -811,7 +782,6 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7
F test/ota.test 3a8d97cbf8f7210dc6a638797c4e4cd674036927
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@@ -821,17 +791,17 @@ F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 6b0f339a4d5f00041555a986dde8fbe8f54c25bc
F test/permutations.test f9cc1dd987986c9d4949211c7a4ed55ec9aecba1
F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
@@ -844,12 +814,11 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl 2aaffa548a8f8d10053b20bcf68a1b5a01081e51
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/releasetest.tcl a37cd82092c8be438255d65804b5951d6e3ecdae
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
F test/rollbackfault.test 6a004f71087cc399296cffbb5429ea6da655ae65
F test/rowallock.test f7f834125f11ff62f6e1ae7d0b07fd9228f2d5a2
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test 742b5741584a8a44fd83e856cc2896688401d645
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
@@ -872,11 +841,11 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 6d5bc6d178a367e8b48fa1c1d3ea12cae9c2d650
F test/select4.test 48e14766d98b744b2202cca6d4679bf7ef3784c8
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
@@ -889,7 +858,7 @@ F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F test/shared3.test fcd65cb11d189eff5f5c85cc4fad246fb0933108
F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
F test/shared4.test 72d90821e8d2fc918a08f16d32880868d8ee8e9d
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
@@ -898,7 +867,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test ce5e744870387164703bf2dee2cc9753e4a71513
F test/shell1.test ca88b14a8fc8b1f3543a24e519d019585ac9c903
F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
F test/shell4.test ddf0a99044e2245a87fc17423e3aaa1445b3243b
@@ -928,12 +897,10 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 9f1b745c24886cced3f70ffc666300152a39013c
F test/speedtest1.c 2b416dca3a155fcaa849540b2e7fc1df12896c23
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f
@@ -950,7 +917,7 @@ F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl b3a41e20f98a029a76e930b33d0711c5854267bb
F test/tester.tcl ed77454e6c7b40eb501db7e79d1c6fbfd3eebbff
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1106,12 +1073,12 @@ F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4
F test/trace.test 73a5508100f7fccfbc3f8018d5f6963ed478eea0
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
F test/trigger1.test ea9624cc1dae05645469df6119fa815f9e6f1e8c
F test/transitive1.test 03f532954f46cdf5608f7766bff0b0c52bf2a7cd
F test/trigger1.test dc47573ac79ffe0ee3eecaa517d70d8dacbccd03
F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
@@ -1148,12 +1115,12 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
F test/vtab1.test d1e5ec7a818f1d3f0402382b6a1d0c06071b770f
F test/vtab2.test 3644649aa8d1daac57fd541f6a5f914cac59203e
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
F test/vtab6.test d2986cf418dc51e7fb81d12366bea2caa8b812df
F test/vtab6.test 5f5380c425e52993560ab4763db4f826d2ba7b09
F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
@@ -1193,10 +1160,10 @@ F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
F test/where.test 1ff3d9f8da0a6c0dc5ccfd38d9225b2cdb5b6afb
F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b
F test/where2.test 23fdb5d8e756554aad4ca7ae03de9dd8367a2c6e
F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
F test/where4.test 68aa5ad796e33816db2078bc0f6de719c7a0e21f
F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
@@ -1205,7 +1172,7 @@ F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
@@ -1219,10 +1186,10 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/with1.test e99845d4f4bf7863b61f104de554c61739d65764
F test/with1.test a86bf7f9288ba759a25ee57221d3bffaca36032a
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701
F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test 1081aabf60a1e1123b7f9a8f6ae19954351843b0
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
@@ -1238,7 +1205,7 @@ F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/fuzzershell.c f2fc86dd22df654b28851b85019d3bd007361751
F tool/fuzzershell.c bcdca60b54654c8fc25fd215953d9b6bb55fd7d4
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
@@ -1248,10 +1215,10 @@ F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 40c287d3f929ece67da6e9e7c49885789960accf
F tool/mkpragmatab.tcl 94f196c9961e0ca3513e29f57125a3197808be2d
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e
F tool/mksqlite3c.tcl d79e450048b0bbf04d53677e01c249a012981182
F tool/mksqlite3c.tcl 52a3352f7aa15f1db851e45ac3a5e2173d6fe93c
F tool/mksqlite3h.tcl 44730d586c9031638cdd2eb443b801c0d2dbd9f8
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1
@@ -1268,14 +1235,14 @@ F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
F tool/spaceanal.tcl 713c587a057334de42c41ad9566f10e255d3ad27
F tool/spaceanal.tcl d5a09620c66a6c144576cb9d2bdfa9a6fbe362a5
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/sqldiff.c 0748c0daed08f31e5a8eab6de98ca57500e61ecf
F tool/sqldiff.c 393b0f5b17ef29341664563a90d40ee63a0a18f7
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
@@ -1286,7 +1253,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P f38e0be56fc086a3ce08134ade83ab61c9fca106
R 27c776937a2faf6a3c6ca0150fe1d26e
U mistachkin
Z 4bdc8fbc12892afab86b92929a73ad3a
P 025e8370dde2918b66683f8d7fa9c7d23d03c9b4
R 065b478bd5e153421f77ec0bbb390aae
T *branch * sqlite3_db_log
T *sym-sqlite3_db_log *
T -sym-trunk *
U drh
Z cb2dffa7a83d63dde4f8c28d3e4ea48d
+1 -1
View File
@@ -1 +1 @@
e64a5681793238fa04fe3636f48d34b2dd36cdfa
658e20f55467a90bcebe5e01cf9f252dbe8bd690
+1 -2
View File
@@ -126,7 +126,6 @@ static void renameParentFunc(
n = sqlite3GetToken(z, &token);
}while( token==TK_SPACE );
if( token==TK_ILLEGAL ) break;
zParent = sqlite3DbStrNDup(db, (const char *)z, n);
if( zParent==0 ) break;
sqlite3Dequote(zParent);
@@ -692,7 +691,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
if( pDflt ){
sqlite3_value *pVal = 0;
int rc;
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
if( rc!=SQLITE_OK ){
db->mallocFailed = 1;
+1 -1
View File
@@ -341,7 +341,7 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
** bits to act as the reference */
pBitvec = sqlite3BitvecCreate( sz );
pV = sqlite3MallocZero( (sz+7)/8 + 1 );
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
pTmpSpace = sqlite3_malloc(BITVEC_SZ);
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
/* NULL pBitvec tests */
+68 -114
View File
@@ -1196,18 +1196,26 @@ static int defragmentPage(MemPage *pPage){
pc = get2byte(pAddr);
testcase( pc==iCellFirst );
testcase( pc==iCellLast );
#if !defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
/* These conditions have already been verified in btreeInitPage()
** if PRAGMA cell_size_check=ON.
** if SQLITE_ENABLE_OVERSIZE_CELL_CHECK is defined
*/
if( pc<iCellFirst || pc>iCellLast ){
return SQLITE_CORRUPT_BKPT;
}
#endif
assert( pc>=iCellFirst && pc<=iCellLast );
size = cellSizePtr(pPage, &src[pc]);
cbrk -= size;
#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
if( cbrk<iCellFirst ){
return SQLITE_CORRUPT_BKPT;
}
#else
if( cbrk<iCellFirst || pc+size>usableSize ){
return SQLITE_CORRUPT_BKPT;
}
#endif
assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
testcase( cbrk+size==usableSize );
testcase( pc+size==usableSize );
@@ -1272,10 +1280,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc, int *pbDefrag){
int x = size - nByte;
testcase( x==4 );
testcase( x==3 );
if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
*pRc = SQLITE_CORRUPT_BKPT;
return 0;
}else if( x<4 ){
if( x<4 ){
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
** number of bytes in fragments may not exceed 60. */
if( aData[hdr+7]>=60 ){
@@ -1286,6 +1291,9 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc, int *pbDefrag){
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
}else if( size+pc > usableSize ){
*pRc = SQLITE_CORRUPT_BKPT;
return 0;
}else{
/* The slot remains on the free-list. Reduce its size to account
** for the portion used by the new allocation. */
@@ -1335,11 +1343,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** However, that integer is too large to be stored in a 2-byte unsigned
** integer, so a value of 0 is used in its place. */
top = get2byteNotZero(&data[hdr+5]);
if( gap>top || NEVER((u32)top>pPage->pBt->usableSize) ){
/* The NEVER() is because a oversize "top" value will be blocked from
** reaching this point by btreeInitPage() or btreeGetUnusedPage() */
return SQLITE_CORRUPT_BKPT;
}
if( gap>top ) return SQLITE_CORRUPT_BKPT;
/* If there is enough space between gap and top for one more cell pointer
** array entry offset, and if the freelist is not empty, then search the
@@ -1412,7 +1416,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
assert( pPage->pBt!=0 );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize );
assert( iStart>=pPage->hdrOffset+6+pPage->childPtrSize );
assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( iSize>=4 ); /* Minimum cell size is 4 */
@@ -1552,7 +1556,6 @@ static int decodeFlags(MemPage *pPage, int flagByte){
static int btreeInitPage(MemPage *pPage){
assert( pPage->pBt!=0 );
assert( pPage->pBt->db!=0 );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
@@ -1611,7 +1614,8 @@ static int btreeInitPage(MemPage *pPage){
*/
iCellFirst = cellOffset + 2*pPage->nCell;
iCellLast = usableSize - 4;
if( pBt->db->flags & SQLITE_CellSizeCk ){
#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
{
int i; /* Index into the cell pointer array */
int sz; /* Size of a cell */
@@ -1631,6 +1635,7 @@ static int btreeInitPage(MemPage *pPage){
}
if( !pPage->leaf ) iCellLast++;
}
#endif
/* Compute the total free space on the page
** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
@@ -1727,10 +1732,10 @@ static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
/*
** Get a page from the pager. Initialize the MemPage.pBt and
** MemPage.aData elements if needed. See also: btreeGetUnusedPage().
** MemPage.aData elements if needed.
**
** If the PAGER_GET_NOCONTENT flag is set, it means that we do not care
** about the content of the page at this time. So do not go to the disk
** If the noContent flag is set, it means that we do not care about
** the content of the page at this time. So do not go to the disk
** to fetch the content. Just fill in the content with zeros for now.
** If in the future we call sqlite3PagerWrite() on this page, that
** means we have started to be concerned about content and the disk
@@ -1832,36 +1837,6 @@ static void releasePage(MemPage *pPage){
}
}
/*
** Get an unused page.
**
** This works just like btreeGetPage() with the addition:
**
** * If the page is already in use for some other purpose, immediately
** release it and return an SQLITE_CURRUPT error.
** * Make sure the isInit flag is clear
*/
static int btreeGetUnusedPage(
BtShared *pBt, /* The btree */
Pgno pgno, /* Number of the page to fetch */
MemPage **ppPage, /* Return the page in this parameter */
int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */
){
int rc = btreeGetPage(pBt, pgno, ppPage, flags);
if( rc==SQLITE_OK ){
if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
releasePage(*ppPage);
*ppPage = 0;
return SQLITE_CORRUPT_BKPT;
}
(*ppPage)->isInit = 0;
}else{
*ppPage = 0;
}
return rc;
}
/*
** During a rollback, when the pager reloads information into the cache
** so that the cache is restored to its original state at the start of
@@ -2454,7 +2429,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pCursor );
assert( !pBt->pPage1 && !pBt->pCursor );
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
@@ -3109,10 +3084,8 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
u8 isInitOrig = pPage->isInit;
int i;
int nCell;
int rc;
rc = btreeInitPage(pPage);
if( rc ) return rc;
btreeInitPage(pPage);
nCell = pPage->nCell;
for(i=0; i<nCell; i++){
@@ -3913,13 +3886,9 @@ int sqlite3BtreeCursor(
BtCursor *pCur /* Write new cursor here */
){
int rc;
if( iTable<1 ){
rc = SQLITE_CORRUPT_BKPT;
}else{
sqlite3BtreeEnter(p);
rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
sqlite3BtreeLeave(p);
}
sqlite3BtreeEnter(p);
rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
sqlite3BtreeLeave(p);
return rc;
}
@@ -4947,7 +4916,7 @@ int sqlite3BtreeMovetoUnpacked(
}
}else{
for(;;){
int nCell; /* Size of the pCell cell in bytes */
int nCell;
pCell = findCell(pPage, idx) + pPage->childPtrSize;
/* The maximum supported page-size is 65536 bytes. This means that
@@ -4976,25 +4945,12 @@ int sqlite3BtreeMovetoUnpacked(
/* The record flows over onto one or more overflow pages. In
** this case the whole cell needs to be parsed, a buffer allocated
** and accessPayload() used to retrieve the record into the
** buffer before VdbeRecordCompare() can be called.
**
** If the record is corrupt, the xRecordCompare routine may read
** up to two varints past the end of the buffer. An extra 18
** bytes of padding is allocated at the end of the buffer in
** case this happens. */
** buffer before VdbeRecordCompare() can be called. */
void *pCellKey;
u8 * const pCellBody = pCell - pPage->childPtrSize;
btreeParseCellPtr(pPage, pCellBody, &pCur->info);
nCell = (int)pCur->info.nKey;
testcase( nCell<0 ); /* True if key size is 2^32 or more */
testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
if( nCell<2 ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
pCellKey = sqlite3Malloc( nCell+18 );
pCellKey = sqlite3Malloc( nCell );
if( pCellKey==0 ){
rc = SQLITE_NOMEM;
goto moveto_finish;
@@ -5287,7 +5243,8 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
** sqlite3PagerUnref() on the new page when it is done.
**
** SQLITE_OK is returned on success. Any other return value indicates
** an error. *ppPage is set to NULL in the event of an error.
** an error. *ppPage and *pPgno are undefined in the event of an error.
** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
**
** If the "nearby" parameter is not 0, then an effort is made to
** locate a page close to the page number "nearby". This can be used in an
@@ -5381,7 +5338,7 @@ static int allocateBtreePage(
if( iTrunk>mxPage ){
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0);
rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
}
if( rc ){
pTrunk = 0;
@@ -5446,7 +5403,7 @@ static int allocateBtreePage(
goto end_allocate_page;
}
testcase( iNewTrunk==mxPage );
rc = btreeGetUnusedPage(pBt, iNewTrunk, &pNewTrunk, 0);
rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
if( rc!=SQLITE_OK ){
goto end_allocate_page;
}
@@ -5526,12 +5483,11 @@ static int allocateBtreePage(
}
put4byte(&aData[4], k-1);
noContent = !btreeGetHasContent(pBt, *pPgno)? PAGER_GET_NOCONTENT : 0;
rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, noContent);
rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
*ppPage = 0;
}
}
searchList = 0;
@@ -5575,7 +5531,7 @@ static int allocateBtreePage(
MemPage *pPg = 0;
TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent);
rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pPg->pDbPage);
releasePage(pPg);
@@ -5589,12 +5545,11 @@ static int allocateBtreePage(
*pPgno = pBt->nPage;
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent);
rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
if( rc ) return rc;
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
*ppPage = 0;
}
TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
}
@@ -5604,8 +5559,17 @@ static int allocateBtreePage(
end_allocate_page:
releasePage(pTrunk);
releasePage(pPrevTrunk);
assert( rc!=SQLITE_OK || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 );
assert( rc!=SQLITE_OK || (*ppPage)->isInit==0 );
if( rc==SQLITE_OK ){
if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
releasePage(*ppPage);
*ppPage = 0;
return SQLITE_CORRUPT_BKPT;
}
(*ppPage)->isInit = 0;
}else{
*ppPage = 0;
}
assert( rc!=SQLITE_OK || sqlite3PagerIswriteable((*ppPage)->pDbPage) );
return rc;
}
@@ -5630,10 +5594,9 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
int nFree; /* Initial number of pages on free-list */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( CORRUPT_DB || iPage>1 );
assert( iPage>1 );
assert( !pMemPage || pMemPage->pgno==iPage );
if( iPage<2 ) return SQLITE_CORRUPT_BKPT;
if( pMemPage ){
pPage = pMemPage;
sqlite3PagerRef(pPage->pDbPage);
@@ -5785,9 +5748,7 @@ static int clearCell(
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
assert( nOvfl>0 ||
(CORRUPT_DB && (info.nPayload + ovflPageSize)<ovflPageSize)
);
assert( ovflPgno==0 || nOvfl>0 );
while( nOvfl-- ){
Pgno iNext = 0;
MemPage *pOvfl = 0;
@@ -6042,7 +6003,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
if( *pRC ) return;
assert( idx>=0 && idx<pPage->nCell );
assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
assert( sz==cellSize(pPage, idx) );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
data = pPage->aData;
@@ -6141,9 +6102,9 @@ static void insertCell(
ins = cellOffset + 2*i;
rc = allocateSpace(pPage, sz, &idx);
if( rc ){ *pRC = rc; return; }
/* The allocateSpace() routine guarantees the following properties
** if it returns successfully */
assert( idx >= 0 && (idx >= end+2 || CORRUPT_DB) );
/* The allocateSpace() routine guarantees the following two properties
** if it returns success */
assert( idx >= end+2 );
assert( idx+sz <= (int)pPage->pBt->usableSize );
pPage->nCell++;
pPage->nFree -= (u16)(2 + sz);
@@ -6206,8 +6167,7 @@ static void rebuildPage(
memcpy(pData, pCell, szCell[i]);
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
assert( szCell[i]==cellSizePtr(pPg, pCell) || CORRUPT_DB );
testcase( szCell[i]==cellSizePtr(pPg,pCell) );
assert( szCell[i]==cellSizePtr(pPg, pCell) );
}
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
@@ -6885,14 +6845,6 @@ static int balance_nonroot(
int limit;
MemPage *pOld = apOld[i];
/* Verify that all sibling pages are of the same "type" (table-leaf,
** table-interior, index-leaf, or index-interior).
*/
if( pOld->aData[0]!=apOld[0]->aData[0] ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
limit = pOld->nCell+pOld->nOverflow;
if( pOld->nOverflow>0 ){
for(j=0; j<limit; j++){
@@ -6934,13 +6886,13 @@ static int balance_nonroot(
memcpy(apCell[nCell], &pOld->aData[8], 4);
}else{
assert( leafCorrection==4 );
while( szCell[nCell]<4 ){
if( szCell[nCell]<4 ){
/* Do not allow any cells smaller than 4 bytes. If a smaller cell
** does exist, pad it with 0x00 bytes. */
assert( szCell[nCell]==3 || CORRUPT_DB );
assert( apCell[nCell]==&aSpace1[iSpace1-3] || CORRUPT_DB );
assert( szCell[nCell]==3 );
assert( apCell[nCell]==&aSpace1[iSpace1-3] );
aSpace1[iSpace1++] = 0x00;
szCell[nCell]++;
szCell[nCell] = 4;
}
}
nCell++;
@@ -7031,6 +6983,10 @@ static int balance_nonroot(
/*
** Allocate k new pages. Reuse old pages where possible.
*/
if( apOld[0]->pgno<=1 ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
pageFlags = apOld[0]->aData[0];
for(i=0; i<k; i++){
MemPage *pNew;
@@ -7812,7 +7768,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){
unsigned char *pTmp;
pCell = findCell(pLeaf, pLeaf->nCell-1);
if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
nCell = cellSizePtr(pLeaf, pCell);
assert( MX_CELL_SIZE(pBt) >= nCell );
pTmp = pBt->pTmpSpace;
@@ -7905,8 +7860,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
pgnoRoot++;
}
assert( pgnoRoot>=3 || CORRUPT_DB );
testcase( pgnoRoot<3 );
assert( pgnoRoot>=3 );
/* Allocate a page. The page that currently resides at pgnoRoot will
** be moved to the allocated page (unless the allocated page happens
@@ -8056,8 +8010,7 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}else if( pnChange ){
assert( pPage->intKey || CORRUPT_DB );
testcase( !pPage->intKey );
assert( pPage->intKey );
*pnChange += pPage->nCell;
}
if( freePageFlag ){
@@ -8584,12 +8537,12 @@ static void checkList(
**
** The heap property is this: Every node is less than or equal to both
** of its daughter nodes. A consequence of the heap property is that the
** root node aHeap[1] is always the minimum value currently in the heap.
** root node aHeap[1] is always the minimum value current in the heap.
**
** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto
** the heap, preserving the heap property. The btreeHeapPull() routine
** removes the root element from the heap (the minimum value in the heap)
** and then moves other nodes around as necessary to preserve the heap
** and then move other nodes around as necessary to preserve the heap
** property.
**
** This heap is used for cell overlap and coverage testing. Each u32
@@ -8946,7 +8899,8 @@ char *sqlite3BtreeIntegrityCheck(
}
i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
sCheck.errMsg.useMalloc = 2;
/* Check the integrity of the freelist
*/
+43 -67
View File
@@ -1092,10 +1092,10 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
pCol->zName = z;
/* If there is no type specified, columns have the default affinity
** 'BLOB'. If there is a type specified, then sqlite3AddColumnType() will
** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
** be called next to set pCol->affinity correctly.
*/
pCol->affinity = SQLITE_AFF_BLOB;
pCol->affinity = SQLITE_AFF_NONE;
pCol->szEst = 1;
p->nCol++;
}
@@ -1130,7 +1130,7 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
** 'CHAR' | SQLITE_AFF_TEXT
** 'CLOB' | SQLITE_AFF_TEXT
** 'TEXT' | SQLITE_AFF_TEXT
** 'BLOB' | SQLITE_AFF_BLOB
** 'BLOB' | SQLITE_AFF_NONE
** 'REAL' | SQLITE_AFF_REAL
** 'FLOA' | SQLITE_AFF_REAL
** 'DOUB' | SQLITE_AFF_REAL
@@ -1156,7 +1156,7 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){
aff = SQLITE_AFF_TEXT;
}else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
&& (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
aff = SQLITE_AFF_BLOB;
aff = SQLITE_AFF_NONE;
if( zIn[0]=='(' ) zChar = zIn;
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
@@ -1325,11 +1325,14 @@ void sqlite3AddPrimaryKey(
"INTEGER PRIMARY KEY");
#endif
}else{
Vdbe *v = pParse->pVdbe;
Index *p;
if( v ) pParse->addrSkipPK = sqlite3VdbeAddOp0(v, OP_Noop);
p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
0, sortOrder, 0);
if( p ){
p->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
}
pList = 0;
}
@@ -1548,7 +1551,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
zStmt[k++] = '(';
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
static const char * const azType[] = {
/* SQLITE_AFF_BLOB */ "",
/* SQLITE_AFF_NONE */ "",
/* SQLITE_AFF_TEXT */ " TEXT",
/* SQLITE_AFF_NUMERIC */ " NUM",
/* SQLITE_AFF_INTEGER */ " INT",
@@ -1561,17 +1564,17 @@ static char *createTableStmt(sqlite3 *db, Table *p){
k += sqlite3Strlen30(&zStmt[k]);
zSep = zSep2;
identPut(zStmt, &k, pCol->zName);
assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_BLOB );
assert( pCol->affinity-SQLITE_AFF_NONE >= 0 );
assert( pCol->affinity-SQLITE_AFF_NONE < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_NONE );
testcase( pCol->affinity==SQLITE_AFF_TEXT );
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
testcase( pCol->affinity==SQLITE_AFF_REAL );
zType = azType[pCol->affinity - SQLITE_AFF_BLOB];
zType = azType[pCol->affinity - SQLITE_AFF_NONE];
len = sqlite3Strlen30(zType);
assert( pCol->affinity==SQLITE_AFF_BLOB
assert( pCol->affinity==SQLITE_AFF_NONE
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
memcpy(&zStmt[k], zType, len);
k += len;
@@ -1682,6 +1685,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
sqlite3VdbeGetOp(v, pParse->addrCrTab)->opcode = OP_CreateIndex;
}
/* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
** table entry.
*/
if( pParse->addrSkipPK ){
assert( v );
sqlite3VdbeGetOp(v, pParse->addrSkipPK)->opcode = OP_Goto;
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
*/
@@ -1699,16 +1710,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pTab->iPKey = -1;
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
/* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
** table entry. This is only required if currently generating VDBE
** code for a CREATE TABLE (not when parsing one as part of reading
** a database schema). */
if( v ){
assert( db->init.busy==0 );
sqlite3VdbeGetOp(v, pPk->tnum)->opcode = OP_Goto;
}
/*
** Remove all redundant columns from the PRIMARY KEY. For example, change
** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
@@ -1844,7 +1845,7 @@ void sqlite3EndTable(
if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
}else{
p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
p->tabFlags |= TF_WithoutRowid;
convertToWithoutRowidTable(pParse, p);
}
}
@@ -1912,45 +1913,26 @@ void sqlite3EndTable(
** be redundant.
*/
if( pSelect ){
SelectDest dest; /* Where the SELECT should store results */
int regYield; /* Register holding co-routine entry-point */
int addrTop; /* Top of the co-routine */
int regRec; /* A record to be insert into the new table */
int regRowid; /* Rowid of the next row to insert */
int addrInsLoop; /* Top of the loop for inserting rows */
Table *pSelTab; /* A table that describes the SELECT results */
SelectDest dest;
Table *pSelTab;
regYield = ++pParse->nMem;
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
assert(pParse->nTab==1);
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
pParse->nTab = 2;
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
sqlite3SelectDestInit(&dest, SRT_Table, 1);
sqlite3Select(pParse, pSelect, &dest);
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield);
sqlite3VdbeJumpHere(v, addrTop - 1);
if( pParse->nErr ) return;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqlite3DeleteTable(db, pSelTab);
addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec);
sqlite3TableAffinity(v, p, 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrInsLoop);
sqlite3VdbeJumpHere(v, addrInsLoop);
sqlite3VdbeAddOp1(v, OP_Close, 1);
if( pParse->nErr==0 ){
pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqlite3DeleteTable(db, pSelTab);
}
}
/* Compute the complete text of the CREATE statement */
@@ -3249,15 +3231,10 @@ Index *sqlite3CreateIndex(
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto exit_create_index;
sqlite3BeginWriteOperation(pParse, 1, iDb);
/* Create the rootpage for the index using CreateIndex. But before
** doing so, code a Noop instruction and store its address in
** Index.tnum. This is required in case this index is actually a
** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In
** that case the convertToWithoutRowidTable() routine will replace
** the Noop with a Goto to jump over the VDBE code generated below. */
pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
/* Create the rootpage for the index
*/
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);
/* Gather the complete text of the CREATE INDEX statement into
@@ -3297,8 +3274,6 @@ Index *sqlite3CreateIndex(
sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
sqlite3VdbeAddOp1(v, OP_Expire, 0);
}
sqlite3VdbeJumpHere(v, pIndex->tnum);
}
/* When adding an index to the list of indices for a table, make
@@ -3701,7 +3676,7 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3DbFree(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
sqlite3DbFree(db, pItem->zAlias);
sqlite3DbFree(db, pItem->zIndexedBy);
sqlite3DbFree(db, pItem->zIndex);
sqlite3DeleteTable(db, pItem->pTab);
sqlite3SelectDelete(db, pItem->pSelect);
sqlite3ExprDelete(db, pItem->pOn);
@@ -3774,13 +3749,13 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
assert( pIndexedBy!=0 );
if( p && ALWAYS(p->nSrc>0) ){
struct SrcList_item *pItem = &p->a[p->nSrc-1];
assert( pItem->notIndexed==0 && pItem->zIndexedBy==0 );
assert( pItem->notIndexed==0 && pItem->zIndex==0 );
if( pIndexedBy->n==1 && !pIndexedBy->z ){
/* A "NOT INDEXED" clause was supplied. See parse.y
** construct "indexed_opt" for details. */
pItem->notIndexed = 1;
}else{
pItem->zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
pItem->zIndex = sqlite3NameFromToken(pParse->db, pIndexedBy);
}
}
}
@@ -4049,7 +4024,8 @@ void sqlite3UniqueConstraint(
StrAccum errMsg;
Table *pTab = pIdx->pTable;
sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200);
sqlite3StrAccumInit(&errMsg, 0, 0, 200);
errMsg.db = pParse->db;
for(j=0; j<pIdx->nKeyCol; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
-3
View File
@@ -75,9 +75,6 @@ static const char * const azCompileOpt[] = {
#if SQLITE_ENABLE_COLUMN_METADATA
"ENABLE_COLUMN_METADATA",
#endif
#if SQLITE_ENABLE_DBSTAT_VTAB
"ENABLE_DBSTAT_VTAB",
#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
"ENABLE_EXPENSIVE_ASSERT",
#endif
+272 -10
View File
@@ -191,13 +191,13 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
return SQLITE_AFF_NUMERIC;
}else{
return SQLITE_AFF_BLOB;
return SQLITE_AFF_NONE;
}
}else if( !aff1 && !aff2 ){
/* Neither side of the comparison is a column. Compare the
** results directly.
*/
return SQLITE_AFF_BLOB;
return SQLITE_AFF_NONE;
}else{
/* One side is a column, the other is not. Use the columns affinity. */
assert( aff1==0 || aff2==0 );
@@ -221,7 +221,7 @@ static char comparisonAffinity(Expr *pExpr){
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( !aff ){
aff = SQLITE_AFF_BLOB;
aff = SQLITE_AFF_NONE;
}
return aff;
}
@@ -235,7 +235,7 @@ static char comparisonAffinity(Expr *pExpr){
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
char aff = comparisonAffinity(pExpr);
switch( aff ){
case SQLITE_AFF_BLOB:
case SQLITE_AFF_NONE:
return 1;
case SQLITE_AFF_TEXT:
return idx_affinity==SQLITE_AFF_TEXT;
@@ -1041,7 +1041,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
pNewItem->isCorrelated = pOldItem->isCorrelated;
pNewItem->viaCoroutine = pOldItem->viaCoroutine;
pNewItem->isRecursive = pOldItem->isRecursive;
pNewItem->zIndexedBy = sqlite3DbStrDup(db, pOldItem->zIndexedBy);
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
pNewItem->notIndexed = pOldItem->notIndexed;
pNewItem->pIndex = pOldItem->pIndex;
pTab = pNewItem->pTab = pOldItem->pTab;
@@ -1252,7 +1252,7 @@ u32 sqlite3ExprListFlags(const ExprList *pList){
if( pList ){
for(i=0; i<pList->nExpr; i++){
Expr *pExpr = pList->a[i].pExpr;
if( ALWAYS(pExpr) ) m |= pExpr->flags;
if( ALWAYS(pExpr) ) m |= pList->a[i].pExpr->flags;
}
}
return m;
@@ -1268,7 +1268,7 @@ u32 sqlite3ExprListFlags(const ExprList *pList){
**
** sqlite3ExprIsConstant() pWalker->eCode==1
** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
** sqlite3ExprIsTableConstant() pWalker->eCode==3
** sqlite3ExprRefOneTableOnly() pWalker->eCode==3
** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
**
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
@@ -1376,7 +1376,7 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){
}
/*
** Walk an expression tree. Return non-zero if the expression is constant
** Walk an expression tree. Return non-zero if the expression constant
** for any single row of the table with cursor iCur. In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
@@ -1482,7 +1482,7 @@ int sqlite3ExprCanBeNull(const Expr *p){
*/
int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
u8 op;
if( aff==SQLITE_AFF_BLOB ) return 1;
if( aff==SQLITE_AFF_NONE ) return 1;
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
@@ -1933,7 +1933,7 @@ int sqlite3CodeSubselect(
int r1, r2, r3;
if( !affinity ){
affinity = SQLITE_AFF_BLOB;
affinity = SQLITE_AFF_NONE;
}
if( pKeyInfo ){
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
@@ -3311,6 +3311,268 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
exprToRegister(pExpr, iMem);
}
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable explanation of an expression tree.
*/
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(pView);
return;
}
switch( pExpr->op ){
case TK_AGG_COLUMN: {
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
pExpr->iTable, pExpr->iColumn);
break;
}
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
}else{
sqlite3TreeViewLine(pView, "{%d:%d}",
pExpr->iTable, pExpr->iColumn);
}
break;
}
case TK_INTEGER: {
if( pExpr->flags & EP_IntValue ){
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
}else{
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
case TK_NULL: {
sqlite3TreeViewLine(pView,"NULL");
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
}
case TK_REGISTER: {
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_AS: {
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_ID: {
sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT: zBinOp = "LT"; break;
case TK_LE: zBinOp = "LE"; break;
case TK_GT: zBinOp = "GT"; break;
case TK_GE: zBinOp = "GE"; break;
case TK_NE: zBinOp = "NE"; break;
case TK_EQ: zBinOp = "EQ"; break;
case TK_IS: zBinOp = "IS"; break;
case TK_ISNOT: zBinOp = "ISNOT"; break;
case TK_AND: zBinOp = "AND"; break;
case TK_OR: zBinOp = "OR"; break;
case TK_PLUS: zBinOp = "ADD"; break;
case TK_STAR: zBinOp = "MUL"; break;
case TK_MINUS: zBinOp = "SUB"; break;
case TK_REM: zBinOp = "REM"; break;
case TK_BITAND: zBinOp = "BITAND"; break;
case TK_BITOR: zBinOp = "BITOR"; break;
case TK_SLASH: zBinOp = "DIV"; break;
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_DOT: zBinOp = "DOT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break;
case TK_BITNOT: zUniOp = "BITNOT"; break;
case TK_NOT: zUniOp = "NOT"; break;
case TK_ISNULL: zUniOp = "ISNULL"; break;
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
case TK_COLLATE: {
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_AGG_FUNCTION:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
pExpr->op2, pExpr->u.zToken);
}else{
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
}
if( pFarg ){
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
sqlite3TreeViewLine(pView, "EXISTS-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
sqlite3TreeViewLine(pView, "SELECT-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3TreeViewLine(pView, "IN");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
}
break;
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** x BETWEEN y AND z
**
** This is equivalent to
**
** x>=y AND x<=z
**
** X is stored in pExpr->pLeft.
** Y is stored in pExpr->pList->a[0].pExpr.
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
Expr *pX = pExpr->pLeft;
Expr *pY = pExpr->x.pList->a[0].pExpr;
Expr *pZ = pExpr->x.pList->a[1].pExpr;
sqlite3TreeViewLine(pView, "BETWEEN");
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
break;
}
case TK_TRIGGER: {
/* If the opcode is TK_TRIGGER, then the expression is a reference
** to a column in the new.* or old.* pseudo-tables available to
** trigger programs. In this case Expr.iTable is set to 1 for the
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
** is set to the column of the pseudo-table to read, or to -1 to
** read the rowid field.
*/
sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
case TK_CASE: {
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
switch( pExpr->affinity ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
#endif
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
}
}
if( zBinOp ){
sqlite3TreeViewLine(pView, "%s", zBinOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s", zUniOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable explanation of an expression list.
*/
void sqlite3TreeViewExprList(
TreeView *pView,
const ExprList *pList,
u8 moreToFollow,
const char *zLabel
){
int i;
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
if( pList==0 ){
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
}else{
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
#if 0
if( pList->a[i].zName ){
sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
}
if( pList->a[i].bSpanIsTab ){
sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
}
#endif
}
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
+12 -9
View File
@@ -232,13 +232,13 @@ static void printfFunc(
StrAccum str;
const char *zFormat;
int n;
sqlite3 *db = sqlite3_context_db_handle(context);
if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
x.nArg = argc-1;
x.nUsed = 0;
x.apArg = argv+1;
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH);
str.db = sqlite3_context_db_handle(context);
sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x);
n = str.nChar;
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
@@ -388,7 +388,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
#endif
/*
** Allocate nByte bytes of space using sqlite3Malloc(). If the
** Allocate nByte bytes of space using sqlite3_malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed and return NULL.
** If nByte is larger than the maximum string or blob length, then
@@ -886,8 +886,8 @@ static void sourceidFunc(
/*
** Implementation of the sqlite_log() function. This is a wrapper around
** sqlite3_log(). The return value is NULL. The function exists purely for
** its side-effects.
** sqlite3_db_log(). The return value is NULL. The function exists purely
** for its side-effects.
*/
static void errlogFunc(
sqlite3_context *context,
@@ -896,7 +896,9 @@ static void errlogFunc(
){
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(context);
sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1]));
sqlite3_db_log(sqlite3_context_db_handle(context),
sqlite3_value_int(argv[0]),
"%s", sqlite3_value_text(argv[1]));
}
/*
@@ -1057,7 +1059,7 @@ static void charFunc(
){
unsigned char *z, *zOut;
int i;
zOut = z = sqlite3_malloc64( argc*4+1 );
zOut = z = sqlite3_malloc( argc*4+1 );
if( z==0 ){
sqlite3_result_error_nomem(context);
return;
@@ -1205,7 +1207,7 @@ static void replaceFunc(
return;
}
zOld = zOut;
zOut = sqlite3_realloc64(zOut, (int)nOut);
zOut = sqlite3_realloc(zOut, (int)nOut);
if( zOut==0 ){
sqlite3_result_error_nomem(context);
sqlite3_free(zOld);
@@ -1567,7 +1569,8 @@ static void groupConcatStep(
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
int firstTerm = pAccum->mxAlloc==0;
int firstTerm = pAccum->useMalloc==0;
pAccum->useMalloc = 2;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( !firstTerm ){
if( argc==2 ){
+6 -6
View File
@@ -42,7 +42,7 @@ void sqlite3OpenTable(
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
assert( pPk->tnum==pTab->tnum );
assert( pPk->tnum=pTab->tnum );
sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
VdbeComment((v, "%s", pTab->zName));
@@ -56,7 +56,7 @@ void sqlite3OpenTable(
**
** Character Column affinity
** ------------------------------
** 'A' BLOB
** 'A' NONE
** 'B' TEXT
** 'C' NUMERIC
** 'D' INTEGER
@@ -99,9 +99,9 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
/*
** Compute the affinity string for table pTab, if it has not already been
** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities.
**
** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and
** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
** for register iReg and following. Or if affinities exists and iReg==0,
** then just set the P4 operand of the previous opcode (which should be
@@ -111,7 +111,7 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
**
** Character Column affinity
** ------------------------------
** 'A' BLOB
** 'A' NONE
** 'B' TEXT
** 'C' NUMERIC
** 'D' INTEGER
@@ -133,7 +133,7 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
}
do{
zColAff[i--] = 0;
}while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
}while( i>=0 && zColAff[i]==SQLITE_AFF_NONE );
pTab->zColAff = zColAff;
}
i = sqlite3Strlen30(zColAff);
+10 -10
View File
@@ -430,7 +430,7 @@ static int sqlite3LoadExtension(
const char *zEntry;
char *zAltEntry = 0;
void **aHandle;
u64 nMsg = 300 + sqlite3Strlen30(zFile);
int nMsg = 300 + sqlite3Strlen30(zFile);
int ii;
/* Shared library endings to try if zFile cannot be loaded as written */
@@ -473,7 +473,7 @@ static int sqlite3LoadExtension(
#endif
if( handle==0 ){
if( pzErrMsg ){
*pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
*pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
"unable to open shared library [%s]", zFile);
@@ -499,7 +499,7 @@ static int sqlite3LoadExtension(
if( xInit==0 && zProc==0 ){
int iFile, iEntry, c;
int ncFile = sqlite3Strlen30(zFile);
zAltEntry = sqlite3_malloc64(ncFile+30);
zAltEntry = sqlite3_malloc(ncFile+30);
if( zAltEntry==0 ){
sqlite3OsDlClose(pVfs, handle);
return SQLITE_NOMEM;
@@ -521,7 +521,7 @@ static int sqlite3LoadExtension(
if( xInit==0 ){
if( pzErrMsg ){
nMsg += sqlite3Strlen30(zEntry);
*pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
*pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
"no entry point [%s] in shared library [%s]", zEntry, zFile);
@@ -620,7 +620,7 @@ static const sqlite3_api_routines sqlite3Apis = { 0 };
*/
typedef struct sqlite3AutoExtList sqlite3AutoExtList;
static SQLITE_WSD struct sqlite3AutoExtList {
u32 nExt; /* Number of entries in aExt[] */
int nExt; /* Number of entries in aExt[] */
void (**aExt)(void); /* Pointers to the extension init functions */
} sqlite3Autoext = { 0, 0 };
@@ -653,7 +653,7 @@ int sqlite3_auto_extension(void (*xInit)(void)){
}else
#endif
{
u32 i;
int i;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
@@ -663,9 +663,9 @@ int sqlite3_auto_extension(void (*xInit)(void)){
if( wsdAutoext.aExt[i]==xInit ) break;
}
if( i==wsdAutoext.nExt ){
u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
void (**aNew)(void);
aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte);
aNew = sqlite3_realloc(wsdAutoext.aExt, nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -697,7 +697,7 @@ int sqlite3_cancel_auto_extension(void (*xInit)(void)){
int n = 0;
wsdAutoextInit;
sqlite3_mutex_enter(mutex);
for(i=(int)wsdAutoext.nExt-1; i>=0; i--){
for(i=wsdAutoext.nExt-1; i>=0; i--){
if( wsdAutoext.aExt[i]==xInit ){
wsdAutoext.nExt--;
wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
@@ -735,7 +735,7 @@ void sqlite3_reset_auto_extension(void){
** If anything goes wrong, set an error in the database connection.
*/
void sqlite3AutoLoadExtensions(sqlite3 *db){
u32 i;
int i;
int go = 1;
int rc;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
+12 -25
View File
@@ -55,18 +55,6 @@ int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
*/
int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
/*
** When compiling the test fixture or with debugging enabled (on Win32),
** this variable being set to non-zero will cause OSTRACE macros to emit
** extra diagnostic information.
*/
#ifdef SQLITE_HAVE_OS_TRACE
# ifndef SQLITE_DEBUG_OS_TRACE
# define SQLITE_DEBUG_OS_TRACE 0
# endif
int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
#endif
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
/*
** If the following function pointer is not NULL and if
@@ -747,6 +735,14 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
rc = setupLookaside(db, pBuf, sz, cnt);
break;
}
case SQLITE_DBCONFIG_LOG: {
/* MSVC is picky about pulling func ptrs from va lists.
** http://support.microsoft.com/kb/47961 */
typedef void(*LOGFUNC_t)(void*,int,const char*);
db->xLog = va_arg(ap, LOGFUNC_t);
db->pLogArg = va_arg(ap, void*);
break;
}
default: {
static const struct {
int op; /* The opcode */
@@ -1206,7 +1202,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
** Return a static string containing the name corresponding to the error code
** specified in the argument.
*/
#if defined(SQLITE_NEED_ERR_NAME)
#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST)
const char *sqlite3ErrName(int rc){
const char *zName = 0;
int i, origRc = rc;
@@ -2431,14 +2427,14 @@ int sqlite3ParseUri(
int eState; /* Parser state when parsing URI */
int iIn; /* Input character index */
int iOut = 0; /* Output character index */
u64 nByte = nUri+2; /* Bytes of space to allocate */
int nByte = nUri+2; /* Bytes of space to allocate */
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
** method that there may be extra parameters following the file-name. */
flags |= SQLITE_OPEN_URI;
for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
zFile = sqlite3_malloc64(nByte);
zFile = sqlite3_malloc(nByte);
if( !zFile ) return SQLITE_NOMEM;
iIn = 5;
@@ -2604,7 +2600,7 @@ int sqlite3ParseUri(
}
}else{
zFile = sqlite3_malloc64(nUri+2);
zFile = sqlite3_malloc(nUri+2);
if( !zFile ) return SQLITE_NOMEM;
memcpy(zFile, zUri, nUri);
zFile[nUri] = '\0';
@@ -2758,9 +2754,6 @@ static int openDatabase(
#endif
#if defined(SQLITE_REVERSE_UNORDERED_SELECTS)
| SQLITE_ReverseOrder
#endif
#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
| SQLITE_CellSizeCk
#endif
;
sqlite3HashInit(&db->aCollSeq);
@@ -2879,12 +2872,6 @@ static int openDatabase(
}
#endif
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
if( !db->mallocFailed && rc==SQLITE_OK){
rc = sqlite3DbstatRegister(db);
}
#endif
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
** mode. Doing nothing at all also makes NORMAL the default.
+20 -8
View File
@@ -226,8 +226,10 @@ void sqlite3MallocEnd(void){
** Return the amount of memory currently checked out.
*/
sqlite3_int64 sqlite3_memory_used(void){
sqlite3_int64 res, mx;
sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, 0);
int n, mx;
sqlite3_int64 res;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);
res = (sqlite3_int64)n; /* Work around bug in Borland C. Ticket #3216 */
return res;
}
@@ -237,9 +239,11 @@ sqlite3_int64 sqlite3_memory_used(void){
** or since the most recent reset.
*/
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
sqlite3_int64 res, mx;
sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag);
return mx;
int n, mx;
sqlite3_int64 res;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag);
res = (sqlite3_int64)mx; /* Work around bug in Borland C. Ticket #3216 */
return res;
}
/*
@@ -771,11 +775,19 @@ char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
}
/*
** Free any prior content in *pz and replace it with a copy of zNew.
** Create a string from the zFromat argument and the va_list that follows.
** Store the string in memory obtained from sqliteMalloc() and make *pz
** point to that string.
*/
void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){
va_list ap;
char *z;
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
sqlite3DbFree(db, *pz);
*pz = sqlite3DbStrDup(db, zNew);
*pz = z;
}
/*
+10
View File
@@ -29,6 +29,16 @@
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
#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)
#endif
/*
** Macros for performance tracing. Normally turned off. Only works
** on i486 hardware.
+16 -16
View File
@@ -641,7 +641,7 @@ static int unixMutexHeld(void) {
#endif
#ifdef SQLITE_HAVE_OS_TRACE
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
/*
** Helper function for printing out trace information from debugging
** binaries. This returns the string representation of the supplied
@@ -904,7 +904,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
assert( zAbsoluteName[0]=='/' );
n = (int)strlen(zAbsoluteName);
pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) );
pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
if( pNew==0 ) return 0;
pNew->zCanonicalName = (char*)&pNew[1];
memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
@@ -1308,7 +1308,7 @@ static int findInodeInfo(
pInode = pInode->pNext;
}
if( pInode==0 ){
pInode = sqlite3_malloc64( sizeof(*pInode) );
pInode = sqlite3_malloc( sizeof(*pInode) );
if( pInode==0 ){
return SQLITE_NOMEM;
}
@@ -3829,7 +3829,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname );
char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
if( zTFile ){
unixGetTempname(pFile->pVfs->mxPathname, zTFile);
*(char**)pArg = zTFile;
@@ -4270,7 +4270,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
int nShmFilename; /* Size of the SHM filename in bytes */
/* Allocate space for the new unixShm object. */
p = sqlite3_malloc64( sizeof(*p) );
p = sqlite3_malloc( sizeof(*p) );
if( p==0 ) return SQLITE_NOMEM;
memset(p, 0, sizeof(*p));
assert( pDbFd->pShm==0 );
@@ -4301,7 +4301,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
#else
nShmFilename = 6 + (int)strlen(zBasePath);
#endif
pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename );
pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
if( pShmNode==0 ){
rc = SQLITE_NOMEM;
goto shm_open_err;
@@ -4511,7 +4511,7 @@ static int unixShmMap(
goto shmpage_out;
}
}else{
pMem = sqlite3_malloc64(szRegion);
pMem = sqlite3_malloc(szRegion);
if( pMem==0 ){
rc = SQLITE_NOMEM;
goto shmpage_out;
@@ -5348,7 +5348,7 @@ static int fillInUnixFile(
** the afpLockingContext.
*/
afpLockingContext *pCtx;
pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) );
pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
if( pCtx==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -5378,7 +5378,7 @@ static int fillInUnixFile(
int nFilename;
assert( zFilename!=0 );
nFilename = (int)strlen(zFilename) + 6;
zLockFile = (char *)sqlite3_malloc64(nFilename);
zLockFile = (char *)sqlite3_malloc(nFilename);
if( zLockFile==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -5755,7 +5755,7 @@ static int unixOpen(
if( pUnused ){
fd = pUnused->fd;
}else{
pUnused = sqlite3_malloc64(sizeof(*pUnused));
pUnused = sqlite3_malloc(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM;
}
@@ -6135,7 +6135,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
*/
memset(zBuf, 0, nBuf);
randomnessPid = osGetpid(0);
#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
#if !defined(SQLITE_TEST)
{
int fd, got;
fd = robust_open("/dev/urandom", O_RDONLY, 0);
@@ -6547,7 +6547,7 @@ static int proxyCreateUnixFile(
if( pUnused ){
fd = pUnused->fd;
}else{
pUnused = sqlite3_malloc64(sizeof(*pUnused));
pUnused = sqlite3_malloc(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM;
}
@@ -6580,7 +6580,7 @@ static int proxyCreateUnixFile(
}
}
pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew));
pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
if( pNew==NULL ){
rc = SQLITE_NOMEM;
goto end_create_proxy;
@@ -7042,7 +7042,7 @@ static int proxyReleaseConch(unixFile *pFile){
/*
** Given the name of a database file, compute the name of its conch file.
** Store the conch filename in memory obtained from sqlite3_malloc64().
** Store the conch filename in memory obtained from sqlite3_malloc().
** Make *pConchPath point to the new name. Return SQLITE_OK on success
** or SQLITE_NOMEM if unable to obtain memory.
**
@@ -7058,7 +7058,7 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
/* Allocate space for the conch filename and initialize the name to
** the name of the original database file. */
*pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8);
*pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
if( conchPath==0 ){
return SQLITE_NOMEM;
}
@@ -7174,7 +7174,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
(lockPath ? lockPath : ":auto:"), osGetpid(0)));
pCtx = sqlite3_malloc64( sizeof(*pCtx) );
pCtx = sqlite3_malloc( sizeof(*pCtx) );
if( pCtx==0 ){
return SQLITE_NOMEM;
}
+9 -15
View File
@@ -2757,7 +2757,7 @@ static int winSync(sqlite3_file *id, int flags){
BOOL rc;
#endif
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
defined(SQLITE_HAVE_OS_TRACE)
(defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
/*
** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
** OSTRACE() macros.
@@ -3015,12 +3015,6 @@ static int winLock(sqlite3_file *id, int locktype){
return SQLITE_OK;
}
/* Do not allow any kind of write-lock on a read-only database
*/
if( (pFile->ctrlFlags & WINFILE_RDONLY)!=0 && locktype>=RESERVED_LOCK ){
return SQLITE_IOERR_LOCK;
}
/* Make sure the locking sequence is correct
*/
assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
@@ -3440,7 +3434,7 @@ struct winShmNode {
int nRef; /* Number of winShm objects pointing to this */
winShm *pFirst; /* All winShm objects pointing to this */
winShmNode *pNext; /* Next in list of all winShmNode objects */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
#ifdef SQLITE_DEBUG
u8 nextShmId; /* Next available winShm.id value */
#endif
};
@@ -3471,7 +3465,7 @@ struct winShm {
u8 hasMutex; /* True if holding the winShmNode mutex */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
#ifdef SQLITE_DEBUG
u8 id; /* Id of this connection with its winShmNode */
#endif
};
@@ -3662,7 +3656,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
/* Make the new connection a child of the winShmNode */
p->pShmNode = pShmNode;
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
#ifdef SQLITE_DEBUG
p->id = pShmNode->nextShmId++;
#endif
pShmNode->nRef++;
@@ -3931,7 +3925,7 @@ static int winShmMap(
}
/* Map the requested memory region into this processes address space. */
apNew = (struct ShmRegion *)sqlite3_realloc64(
apNew = (struct ShmRegion *)sqlite3_realloc(
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
@@ -5378,7 +5372,7 @@ static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
int n = 0;
UNUSED_PARAMETER(pVfs);
#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS)
#if defined(SQLITE_TEST)
n = nBuf;
memset(zBuf, 0, nBuf);
#else
@@ -5412,23 +5406,23 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
memcpy(&zBuf[n], &i, sizeof(i));
n += sizeof(i);
}
#endif
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
if( sizeof(UUID)<=nBuf-n ){
UUID id;
memset(&id, 0, sizeof(UUID));
osUuidCreate(&id);
memcpy(&zBuf[n], &id, sizeof(UUID));
memcpy(zBuf, &id, sizeof(UUID));
n += sizeof(UUID);
}
if( sizeof(UUID)<=nBuf-n ){
UUID id;
memset(&id, 0, sizeof(UUID));
osUuidCreateSequential(&id);
memcpy(&zBuf[n], &id, sizeof(UUID));
memcpy(zBuf, &id, sizeof(UUID));
n += sizeof(UUID);
}
#endif
#endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */
return n;
}
+5 -6
View File
@@ -3149,10 +3149,11 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
assert( pPager->eLock>=SHARED_LOCK );
nPage = sqlite3WalDbsize(pPager->pWal);
/* If the number of pages in the database is not available from the
** WAL sub-system, determine the page counte based on the size of
** the database file. If the size of the database file is not an
** integer multiple of the page-size, round up the result.
/* If the database size was not available from the WAL sub-system,
** determine it based on the size of the database file. If the size
** of the database file is not an integer multiple of the page-size,
** round down to the nearest page. Except, any file larger than 0
** bytes in size is considered to contain at least one page.
*/
if( nPage==0 ){
i64 n = 0; /* Size of db file in bytes */
@@ -7009,8 +7010,6 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
}
assert( state==pPager->eState );
}
}else if( eMode==PAGER_JOURNALMODE_OFF ){
sqlite3OsClose(pPager->jfd);
}
}
+5 -7
View File
@@ -166,7 +166,7 @@ create_table_args ::= AS select(S). {
table_options(A) ::= . {A = 0;}
table_options(A) ::= WITHOUT nm(X). {
if( X.n==5 && sqlite3_strnicmp(X.z,"rowid",5)==0 ){
A = TF_WithoutRowid | TF_NoVisibleRowid;
A = TF_WithoutRowid;
}else{
A = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", X.n, X.z);
@@ -448,7 +448,6 @@ selectnowith(A) ::= oneselect(X). {A = X;}
%ifndef SQLITE_OMIT_COMPOUND_SELECT
selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). {
Select *pRhs = Z;
Select *pLhs = X;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
@@ -459,12 +458,11 @@ selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). {
}
if( pRhs ){
pRhs->op = (u8)Y;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
pRhs->pPrior = X;
pRhs->selFlags &= ~SF_MultiValue;
if( Y!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
sqlite3SelectDelete(pParse->db, X);
}
A = pRhs;
}
@@ -527,7 +525,7 @@ values(A) ::= values(X) COMMA LP exprlist(Y) RP. {
//
%type distinct {u16}
distinct(A) ::= DISTINCT. {A = SF_Distinct;}
distinct(A) ::= ALL. {A = SF_All;}
distinct(A) ::= ALL. {A = 0;}
distinct(A) ::= . {A = 0;}
// selcollist is a list of expressions that are to become the return
@@ -890,7 +888,7 @@ expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). {
}
A.pExpr = sqlite3ExprFunction(pParse, Y, &X);
spanSet(&A,&X,&E);
if( D==SF_Distinct && A.pExpr ){
if( D && A.pExpr ){
A.pExpr->flags |= EP_Distinct;
}
}
+1 -5
View File
@@ -99,10 +99,6 @@ static const struct sPragmaNames {
/* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
/* ePragFlag: */ 0,
/* iArg: */ 0 },
{ /* zName: */ "cell_size_check",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_CellSizeCk },
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{ /* zName: */ "checkpoint_fullfsync",
/* ePragTyp: */ PragTyp_FLAG,
@@ -460,4 +456,4 @@ static const struct sPragmaNames {
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 60 on by default, 73 total. */
/* Number of pragmas: 59 on by default, 72 total. */
+7 -7
View File
@@ -26,13 +26,13 @@ static void corruptSchema(
){
sqlite3 *db = pData->db;
if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
char *z;
if( zObj==0 ) zObj = "?";
z = sqlite3_mprintf("malformed database schema (%s)", zObj);
if( z && zExtra ) z = sqlite3_mprintf("%z - %s", z, zExtra);
sqlite3DbFree(db, *pData->pzErrMsg);
*pData->pzErrMsg = z;
if( z==0 ) db->mallocFailed = 1;
sqlite3SetString(pData->pzErrMsg, db,
"malformed database schema (%s)", zObj);
if( zExtra ){
*pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg,
"%s - %s", *pData->pzErrMsg, zExtra);
}
}
pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT;
}
@@ -224,7 +224,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0);
if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
goto initone_error_out;
}
openedTransaction = 1;
+139 -33
View File
@@ -1,13 +1,16 @@
/*
** The "printf" code that follows dates from the 1980's. It is in
** the public domain.
** the public domain. The original comments are included here for
** completeness. They are very out-of-date but might be useful as
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
**************************************************************************
**
** 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
** SQLite.
** SQLlite.
*/
#include "sqliteInt.h"
@@ -135,7 +138,6 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG );
p->accError = eError;
p->nAlloc = 0;
}
@@ -250,6 +252,7 @@ void sqlite3VXPrintf(
}
}while( !done && (c=(*++fmt))!=0 );
/* Get the field width */
width = 0;
if( c=='*' ){
if( bArgList ){
width = (int)getIntArg(pArgList);
@@ -273,6 +276,7 @@ void sqlite3VXPrintf(
/* Get the precision */
if( c=='.' ){
precision = 0;
c = *++fmt;
if( c=='*' ){
if( bArgList ){
@@ -751,7 +755,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
testcase(p->accError==STRACCUM_NOMEM);
return 0;
}
if( p->mxAlloc==0 ){
if( !p->useMalloc ){
N = p->nAlloc - p->nChar - 1;
setStrAccumError(p, STRACCUM_TOOBIG);
return N;
@@ -771,10 +775,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}else{
p->nAlloc = (int)szNew;
}
if( p->db ){
if( p->useMalloc==1 ){
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
}else{
zNew = sqlite3_realloc64(zOld, p->nAlloc);
zNew = sqlite3_realloc(zOld, p->nAlloc);
}
if( zNew ){
assert( p->zText!=0 || p->nChar==0 );
@@ -851,8 +855,12 @@ void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
p->zText[p->nChar] = 0;
if( p->mxAlloc>0 && p->zText==p->zBase ){
p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
if( p->useMalloc && p->zText==p->zBase ){
if( p->useMalloc==1 ){
p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
}else{
p->zText = sqlite3_malloc(p->nChar+1);
}
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
@@ -868,31 +876,25 @@ char *sqlite3StrAccumFinish(StrAccum *p){
*/
void sqlite3StrAccumReset(StrAccum *p){
if( p->zText!=p->zBase ){
sqlite3DbFree(p->db, p->zText);
if( p->useMalloc==1 ){
sqlite3DbFree(p->db, p->zText);
}else{
sqlite3_free(p->zText);
}
}
p->zText = 0;
}
/*
** Initialize a string accumulator.
**
** p: The accumulator to be initialized.
** db: Pointer to a database connection. May be NULL. Lookaside
** memory is used if not NULL. db->mallocFailed is set appropriately
** when not NULL.
** zBase: An initial buffer. May be NULL in which case the initial buffer
** is malloced.
** n: Size of zBase in bytes. If total space requirements never exceed
** n then no memory allocations ever occur.
** mx: Maximum number of bytes to accumulate. If mx==0 then no memory
** allocations will ever occur.
** Initialize a string accumulator
*/
void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
p->zText = p->zBase = zBase;
p->db = db;
p->db = 0;
p->nChar = 0;
p->nAlloc = n;
p->mxAlloc = mx;
p->useMalloc = 1;
p->accError = 0;
}
@@ -905,8 +907,9 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
assert( db!=0 );
sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase),
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
acc.db = db;
sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.accError==STRACCUM_NOMEM ){
@@ -928,6 +931,24 @@ char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
return z;
}
/*
** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
** the string and before returning. This routine is intended to be used
** to modify an existing string. For example:
**
** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
**
*/
char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
va_list ap;
char *z;
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
sqlite3DbFree(db, zStr);
return z;
}
/*
** Print into memory obtained from sqlite3_malloc(). Omit the internal
** %-conversion extensions.
@@ -946,7 +967,8 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
acc.useMalloc = 2;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
return z;
@@ -991,7 +1013,8 @@ char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
return zBuf;
}
#endif
sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
sqlite3StrAccumInit(&acc, zBuf, n, 0);
acc.useMalloc = 0;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
return sqlite3StrAccumFinish(&acc);
}
@@ -1013,14 +1036,20 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
** allocate memory because it might be called while the memory allocator
** mutex is held.
*/
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
static void renderLogMsg(
void (*xLog)(void*,int,const char*), /* Logging function */
void *pArg, /* First argument to xLog */
int iErrCode, /* Error code */
const char *zFormat, /* Format string for error message */
va_list ap /* Arguments to format string */
){
StrAccum acc; /* String accumulator */
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
acc.useMalloc = 0;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
sqlite3StrAccumFinish(&acc));
xLog(pArg, iErrCode, sqlite3StrAccumFinish(&acc));
}
/*
@@ -1030,12 +1059,26 @@ void sqlite3_log(int iErrCode, const char *zFormat, ...){
va_list ap; /* Vararg list */
if( sqlite3GlobalConfig.xLog ){
va_start(ap, zFormat);
renderLogMsg(iErrCode, zFormat, ap);
renderLogMsg(sqlite3GlobalConfig.xLog, sqlite3GlobalConfig.pLogArg,
iErrCode, zFormat, ap);
va_end(ap);
}
}
void sqlite3_db_log(sqlite3 *db, int iErrCode, const char *zFormat, ...){
va_list ap; /* Vararg list */
if( db && db->xLog ){
va_start(ap, zFormat);
renderLogMsg(db->xLog, db->pLogArg, iErrCode, zFormat, ap);
va_end(ap);
}else if( sqlite3GlobalConfig.xLog ){
va_start(ap, zFormat);
renderLogMsg(sqlite3GlobalConfig.xLog, sqlite3GlobalConfig.pLogArg,
iErrCode, zFormat, ap);
va_end(ap);
}
}
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
#if defined(SQLITE_DEBUG)
/*
** A version of printf() that understands %lld. Used for debugging.
** The printf() built into some versions of windows does not understand %lld
@@ -1045,7 +1088,8 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
va_list ap;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
acc.useMalloc = 0;
va_start(ap,zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
@@ -1055,6 +1099,68 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
}
#endif
#ifdef SQLITE_DEBUG
/*************************************************************************
** Routines for implementing the "TreeView" display of hierarchical
** data structures for debugging.
**
** The main entry points (coded elsewhere) are:
** sqlite3TreeViewExpr(0, pExpr, 0);
** sqlite3TreeViewExprList(0, pList, 0, 0);
** sqlite3TreeViewSelect(0, pSelect, 0);
** Insert calls to those routines while debugging in order to display
** a diagram of Expr, ExprList, and Select objects.
**
*/
/* Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree. */
TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
if( p==0 ){
p = sqlite3_malloc( sizeof(*p) );
if( p==0 ) return 0;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
return p;
}
/* Finished with one layer of the tree */
void sqlite3TreeViewPop(TreeView *p){
if( p==0 ) return;
p->iLevel--;
if( p->iLevel<0 ) sqlite3_free(p);
}
/* Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines */
void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
acc.useMalloc = 0;
if( p ){
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
}
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
}
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
/* Shorthand for starting a new tree item that consists of a single label */
void sqlite3TreeViewItem(TreeView *p, const char *zLabel, u8 moreToFollow){
p = sqlite3TreeViewPush(p, moreToFollow);
sqlite3TreeViewLine(p, "%s", zLabel);
}
#endif /* SQLITE_DEBUG */
/*
** variable-argument wrapper around sqlite3VXPrintf().
+4 -3
View File
@@ -79,7 +79,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
**
** The nSubquery parameter specifies how many levels of subquery the
** alias is removed from the original expression. The usual value is
** alias is removed from the original expression. The usually value is
** zero but it might be more if the alias is contained within a subquery
** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
** structures must be increased by the nSubquery amount.
@@ -99,6 +99,7 @@ static void resolveAlias(
assert( iCol>=0 && iCol<pEList->nExpr );
pOrig = pEList->a[iCol].pExpr;
assert( pOrig!=0 );
assert( pOrig->flags & EP_Resolved );
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( pDup==0 ) return;
@@ -358,7 +359,7 @@ static int lookupName(
break;
}
}
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
/* IMP: R-51414-32910 */
/* IMP: R-44911-55124 */
iCol = -1;
@@ -388,7 +389,7 @@ static int lookupName(
** Perhaps the name is a reference to the ROWID
*/
if( cnt==0 && cntTab==1 && pMatch && sqlite3IsRowid(zCol)
&& VisibleRowid(pMatch->pTab) ){
&& HasRowid(pMatch->pTab) ){
cnt = 1;
pExpr->iColumn = -1; /* IMP: R-44911-55124 */
pExpr->affinity = SQLITE_AFF_INTEGER;
+201 -200
View File
@@ -21,8 +21,7 @@
/***/ int sqlite3SelectTrace = 0;
# define SELECTTRACE(K,P,S,X) \
if(sqlite3SelectTrace&(K)) \
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\
(S)->zSelName,(S)),\
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",(S)->zSelName,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
@@ -714,13 +713,8 @@ static void selectInnerLoop(
/* If the destination is an EXISTS(...) expression, the actual
** values returned by the SELECT are not required.
*/
u8 ecelFlags;
if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){
ecelFlags = SQLITE_ECEL_DUP;
}else{
ecelFlags = 0;
}
sqlite3ExprCodeExprList(pParse, pEList, regResult, ecelFlags);
sqlite3ExprCodeExprList(pParse, pEList, regResult,
(eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0);
}
/* If the DISTINCT keyword was present on the SELECT statement
@@ -775,8 +769,7 @@ static void selectInnerLoop(
default: {
assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol,
regResult);
codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult);
break;
}
}
@@ -818,8 +811,6 @@ static void selectInnerLoop(
int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1);
testcase( eDest==SRT_Table );
testcase( eDest==SRT_EphemTab );
testcase( eDest==SRT_Fifo );
testcase( eDest==SRT_DistFifo );
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
#ifndef SQLITE_OMIT_CTE
if( eDest==SRT_DistFifo ){
@@ -829,8 +820,7 @@ static void selectInnerLoop(
** current row to the index and proceed with writing it to the
** output table as well. */
int addr = sqlite3VdbeCurrentAddr(v) + 4;
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
VdbeCoverage(v);
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
assert( pSort==0 );
}
@@ -1236,7 +1226,10 @@ static void generateSortTail(
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
switch( eDest ){
case SRT_Table:
case SRT_EphemTab: {
testcase( eDest==SRT_Table );
testcase( eDest==SRT_EphemTab );
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
@@ -1313,27 +1306,28 @@ static void generateSortTail(
*/
#ifdef SQLITE_ENABLE_COLUMN_METADATA
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
#endif
static const char *columnTypeImpl(
NameContext *pNC,
Expr *pExpr,
#ifdef SQLITE_ENABLE_COLUMN_METADATA
const char **pzOrigDb,
const char **pzOrigTab,
const char **pzOrigCol,
#endif
u8 *pEstWidth
){
char const *zType = 0;
int j;
u8 estWidth = 1;
#ifdef SQLITE_ENABLE_COLUMN_METADATA
char const *zOrigDb = 0;
char const *zOrigTab = 0;
char const *zOrigCol = 0;
#endif
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
static const char *columnTypeImpl(
NameContext *pNC,
Expr *pExpr,
u8 *pEstWidth
){
#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
char const *zType = 0;
int j;
u8 estWidth = 1;
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
switch( pExpr->op ){
@@ -1707,12 +1701,11 @@ static void selectAddColumnTypeAndCollation(
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
p = a[i].pExpr;
if( pCol->zType==0 ){
pCol->zType = sqlite3DbStrDup(db,
columnType(&sNC, p,0,0,0, &pCol->szEst));
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
}
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl && pCol->zColl==0 ){
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
@@ -2585,14 +2578,15 @@ static int generateOutputSubroutine(
*/
codeOffset(v, p->iOffset, iContinue);
assert( pDest->eDest!=SRT_Exists );
assert( pDest->eDest!=SRT_Table );
switch( pDest->eDest ){
/* Store the result as data using a unique key.
*/
case SRT_Table:
case SRT_EphemTab: {
int r1 = sqlite3GetTempReg(pParse);
int r2 = sqlite3GetTempReg(pParse);
testcase( pDest->eDest==SRT_Table );
testcase( pDest->eDest==SRT_EphemTab );
sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
@@ -2609,7 +2603,7 @@ static int generateOutputSubroutine(
*/
case SRT_Set: {
int r1;
assert( pIn->nSdst==1 || pParse->nErr>0 );
assert( pIn->nSdst==1 );
pDest->affSdst =
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
r1 = sqlite3GetTempReg(pParse);
@@ -2620,6 +2614,16 @@ static int generateOutputSubroutine(
break;
}
#if 0 /* Never occurs on an ORDER BY query */
/* If any row exist in the result set, record that fact and abort.
*/
case SRT_Exists: {
sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
/* The LIMIT clause will terminate the loop for us */
break;
}
#endif
/* If this is a scalar select that is part of an expression, then
** store the results in the appropriate memory cell and break out
** of the scan loop.
@@ -3218,8 +3222,8 @@ static void substSelect(
**
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
** accidently carried the comment forward until 2014-09-15. Original
** text: "The subquery does not use aggregates or the outer query
** does not use LIMIT."
** text: "The subquery does not use aggregates or the outer query does not
** use LIMIT."
**
** (11) The subquery and the outer query do not both have ORDER BY clauses.
**
@@ -3712,7 +3716,7 @@ static int flattenSubquery(
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
sqlite3DebugPrintf("After flattening:\n");
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -3721,73 +3725,6 @@ static int flattenSubquery(
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Make copies of relevant WHERE clause terms of the outer query into
** the WHERE clause of subquery. Example:
**
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10;
**
** Transformed into:
**
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
** WHERE x=5 AND y=10;
**
** The hope is that the terms added to the inner query will make it more
** efficient.
**
** Do not attempt this optimization if:
**
** (1) The inner query is an aggregate. (In that case, we'd really want
** to copy the outer WHERE-clause terms onto the HAVING clause of the
** inner query. But they probably won't help there so do not bother.)
**
** (2) The inner query is the recursive part of a common table expression.
**
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
** close would change the meaning of the LIMIT).
**
** (4) The inner query is the right operand of a LEFT JOIN. (The caller
** enforces this restriction since this routine does not have enough
** information to know.)
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
static int pushDownWhereTerms(
sqlite3 *db, /* The database connection (for malloc()) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
int iCursor /* Cursor number of the subquery */
){
Expr *pNew;
int nChng = 0;
if( pWhere==0 ) return 0;
if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
return 0; /* restrictions (1) and (2) */
}
if( pSubq->pLimit!=0 ){
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
pWhere = pWhere->pLeft;
}
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
while( pSubq ){
pNew = sqlite3ExprDup(db, pWhere, 0);
pNew = substExpr(db, pNew, iCursor, pSubq->pEList);
pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew);
pSubq = pSubq->pPrior;
}
}
return nChng;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
** Based on the contents of the AggInfo structure indicated by the first
** argument, this function checks if the following are true:
@@ -3871,16 +3808,16 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** pFrom->pIndex and return SQLITE_OK.
*/
int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
if( pFrom->pTab && pFrom->zIndexedBy ){
if( pFrom->pTab && pFrom->zIndex ){
Table *pTab = pFrom->pTab;
char *zIndexedBy = pFrom->zIndexedBy;
char *zIndex = pFrom->zIndex;
Index *pIdx;
for(pIdx=pTab->pIndex;
pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
pIdx=pIdx->pNext
);
if( !pIdx ){
sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0);
pParse->checkSchema = 1;
return SQLITE_ERROR;
}
@@ -4061,7 +3998,7 @@ static int withExpand(
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
pTab->tabFlags |= TF_Ephemeral;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
if( db->mallocFailed ) return SQLITE_NOMEM;
assert( pFrom->pSelect );
@@ -4306,6 +4243,13 @@ static int selectExpander(Walker *pWalker, Select *p){
int longNames = (flags & SQLITE_FullColNames)!=0
&& (flags & SQLITE_ShortColNames)==0;
/* When processing FROM-clause subqueries, it is always the case
** that full_column_names=OFF and short_column_names=ON. The
** sqlite3ResultSetOfSelect() routine makes it so. */
assert( (p->selFlags & SF_NestedFrom)==0
|| ((flags & SQLITE_FullColNames)==0 &&
(flags & SQLITE_ShortColNames)!=0) );
for(k=0; k<pEList->nExpr; k++){
pE = a[k].pExpr;
pRight = pE->pRight;
@@ -4817,11 +4761,12 @@ int sqlite3Select(
memset(&sSort, 0, sizeof(sSort));
sSort.pOrderBy = p->pOrderBy;
pTabList = p->pSrc;
pEList = p->pEList;
if( pParse->nErr || db->mallocFailed ){
goto select_end;
}
assert( p->pEList!=0 );
isAgg = (p->selFlags & SF_Aggregate)!=0;
assert( pEList!=0 );
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p, ("after name resolution:\n"));
@@ -4830,67 +4775,29 @@ int sqlite3Select(
#endif
/* Begin generating code.
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto select_end;
/* If writing to memory or generating a set
** only a single column may be output.
*/
#ifndef SQLITE_OMIT_SUBQUERY
if( checkForMultiColumnSelectError(pParse, pDest, p->pEList->nExpr) ){
if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
goto select_end;
}
#endif
/* Try to flatten subqueries in the FROM clause up into the main query
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
struct SrcList_item *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
int isAggSub;
if( pSub==0 ) continue;
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;
}
pTabList = p->pSrc;
if( db->mallocFailed ) goto select_end;
if( !IgnorableOrderby(pDest) ){
sSort.pOrderBy = p->pOrderBy;
}
}
#endif
/* Get a pointer the VDBE under construction, allocating a new VDBE if one
** does not already exist */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto select_end;
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Handle compound SELECT statements using the separate multiSelect()
** procedure.
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
pParse->nSelectIndent--;
#endif
return rc;
}
#endif
/* Generate code for all sub-queries in the FROM clause
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; i<pTabList->nSrc; i++){
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
struct SrcList_item *pItem = &pTabList->a[i];
SelectDest dest;
Select *pSub = pItem->pSelect;
int isAggSub;
if( pSub==0 ) continue;
/* Sometimes the code for a subquery will be generated more than
@@ -4915,25 +4822,16 @@ int sqlite3Select(
*/
pParse->nHeight += sqlite3SelectExprHeight(p);
/* Make copies of constant WHERE-clause terms in the outer query down
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( (pItem->jointype & JT_OUTER)==0
&& pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
sqlite3TreeViewSelect(0, p, 0);
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;
}
#endif
}
/* Generate code to implement the subquery
*/
if( pTabList->nSrc==1
&& (p->selFlags & SF_All)==0
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
i = -1;
}else if( pTabList->nSrc==1
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
@@ -4984,23 +4882,33 @@ int sqlite3Select(
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
}
if( db->mallocFailed ) goto select_end;
if( /*pParse->nErr ||*/ db->mallocFailed ){
goto select_end;
}
pParse->nHeight -= sqlite3SelectExprHeight(p);
pTabList = p->pSrc;
if( !IgnorableOrderby(pDest) ){
sSort.pOrderBy = p->pOrderBy;
}
}
#endif
/* Various elements of the SELECT copied into local variables for
** convenience */
pEList = p->pEList;
#endif
pWhere = p->pWhere;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* If there is are a sequence of queries, do the earlier ones first.
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
sqlite3TreeViewSelect(0, p, 0);
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
pParse->nSelectIndent--;
#endif
return rc;
}
#endif
@@ -5020,23 +4928,23 @@ int sqlite3Select(
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
&& sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0
){
p->selFlags &= ~SF_Distinct;
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
assert( sDistinct.isTnct );
}
/* If there is an ORDER BY clause, then create an ephemeral index to
** do the sorting. But this sorting ephemeral index might end up
** being unused if the data can be extracted in pre-sorted order.
** If that is the case, then the OP_OpenEphemeral instruction will be
** changed to an OP_Noop once we figure out that the sorting index is
** not needed. The sSort.addrSortIndex variable is used to facilitate
** that change.
/* 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
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
** we figure out that the sorting index is not needed. The addrSortIndex
** variable is used to facilitate that change.
*/
if( sSort.pOrderBy ){
KeyInfo *pKeyInfo;
@@ -5067,14 +4975,14 @@ int sqlite3Select(
sSort.sortFlags |= SORTFLAG_UseSorter;
}
/* Open an ephemeral index to use for the distinct set.
/* Open a virtual index to use for the distinct set.
*/
if( p->selFlags & SF_Distinct ){
sDistinct.tabTnct = pParse->nTab++;
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
sDistinct.tabTnct, 0, 0,
(char*)keyInfoFromExprList(pParse, p->pEList,0,0),
P4_KEYINFO);
sDistinct.tabTnct, 0, 0,
(char*)keyInfoFromExprList(pParse, p->pEList,0,0),
P4_KEYINFO);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
}else{
@@ -5152,10 +5060,11 @@ int sqlite3Select(
p->nSelectRow = 1;
}
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then it may be possible to disable the ORDER BY clause
** on the grounds that the GROUP BY will cause elements to come out
** in the correct order. It also may not - the GROUP BY might use a
** in the correct order. It also may not - the GROUP BY may use a
** database index that causes rows to be grouped together as required
** but not actually sorted. Either way, record the fact that the
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
@@ -5333,8 +5242,7 @@ int sqlite3Select(
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3ExprCacheClear(pParse);
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
sortOut, sortPTab);
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut,sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
if( groupBySort ){
@@ -5406,8 +5314,7 @@ int sqlite3Select(
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
sqlite3VdbeResolveLabel(v, addrOutputRow);
addrOutputRow = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v);
VdbeComment((v, "Groupby result generator entry point"));
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
finalizeAggFunctions(pParse, &sAggInfo);
@@ -5571,8 +5478,7 @@ int sqlite3Select(
** and send them to the callback one by one.
*/
if( sSort.pOrderBy ){
explainTempTable(pParse,
sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
}
@@ -5604,3 +5510,98 @@ select_end:
#endif
return rc;
}
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable description of a the Select object.
*/
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p)",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p
);
if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
if( p->pOffset ) n++;
if( p->pPrior ) n++;
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){
int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
for(i=0; i<p->pSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0);
x.useMalloc = 0;
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
}else if( pItem->zName ){
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
}
if( pItem->pTab ){
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
}
if( pItem->zAlias ){
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
}
if( pItem->jointype & JT_LEFT ){
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
}
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
if( pItem->pSelect ){
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
}
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, p->pWhere, 0);
sqlite3TreeViewPop(pView);
}
if( p->pGroupBy ){
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
}
if( p->pHaving ){
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlite3TreeViewExpr(pView, p->pHaving, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOrderBy ){
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOffset ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pOffset, 0);
sqlite3TreeViewPop(pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
switch( p->op ){
case TK_ALL: zOp = "UNION ALL"; break;
case TK_INTERSECT: zOp = "INTERSECT"; break;
case TK_EXCEPT: zOp = "EXCEPT"; break;
}
sqlite3TreeViewItem(pView, zOp, (n--)>0);
sqlite3TreeViewSelect(pView, p->pPrior, 0);
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
+15 -115
View File
@@ -990,16 +990,7 @@ static int shell_callback(
case MODE_Insert: {
p->cnt++;
if( azArg==0 ) break;
fprintf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
fprintf(p->out,"(");
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
fprintf(p->out, "%s%s", zSep, azCol[i]);
}
fprintf(p->out,")");
}
fprintf(p->out," VALUES(");
fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
@@ -1200,7 +1191,7 @@ static char *save_err_msg(
sqlite3 *db /* Database to query */
){
int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
char *zErrMsg = sqlite3_malloc64(nErrMsg);
char *zErrMsg = sqlite3_malloc(nErrMsg);
if( zErrMsg ){
memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
}
@@ -1437,8 +1428,8 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
/* Grow the p->aiIndent array as required */
if( iOp>=nAlloc ){
nAlloc += 100;
p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int));
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
@@ -1555,7 +1546,7 @@ static int shell_exec(
if( xCallback ){
/* allocate space for col name ptr, value ptr, and type */
int nCol = sqlite3_column_count(pStmt);
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1);
if( !pData ){
rc = SQLITE_NOMEM;
}else{
@@ -1781,7 +1772,6 @@ static int run_schema_dump_query(
static char zHelp[] =
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
".bail on|off Stop after hitting an error. Default OFF\n"
".binary on|off Turn binary output on or off. Default OFF\n"
".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
".dbinfo ?DB? Show status information about the database\n"
@@ -1803,7 +1793,6 @@ static char zHelp[] =
#ifdef SQLITE_ENABLE_IOTRACE
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
#endif
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
#ifndef SQLITE_OMIT_LOAD_EXTENSION
".load FILE ?ENTRY? Load an extension library\n"
#endif
@@ -1873,7 +1862,7 @@ static void readfileFunc(
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc64( nIn );
pBuf = sqlite3_malloc( nIn );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
}else{
@@ -1944,18 +1933,12 @@ static void open_db(ShellState *p, int keepAlive){
/*
** Do C-language style dequoting.
**
** \a -> alarm
** \b -> backspace
** \t -> tab
** \n -> newline
** \v -> vertical tab
** \f -> form feed
** \r -> carriage return
** \s -> space
** \" -> "
** \' -> '
** \\ -> backslash
** \NNN -> ascii character NNN in octal
** \\ -> backslash
*/
static void resolve_backslashes(char *z){
int i, j;
@@ -1964,24 +1947,12 @@ static void resolve_backslashes(char *z){
for(i=j=0; (c = z[i])!=0; i++, j++){
if( c=='\\' && z[i+1]!=0 ){
c = z[++i];
if( c=='a' ){
c = '\a';
}else if( c=='b' ){
c = '\b';
if( c=='n' ){
c = '\n';
}else if( c=='t' ){
c = '\t';
}else if( c=='n' ){
c = '\n';
}else if( c=='v' ){
c = '\v';
}else if( c=='f' ){
c = '\f';
}else if( c=='r' ){
c = '\r';
}else if( c=='"' ){
c = '"';
}else if( c=='\'' ){
c = '\'';
}else if( c=='\\' ){
c = '\\';
}else if( c>='0' && c<='7' ){
@@ -2151,7 +2122,7 @@ struct ImportCtx {
static void import_append_char(ImportCtx *p, int c){
if( p->n+1>=p->nAlloc ){
p->nAlloc += p->nAlloc + 100;
p->z = sqlite3_realloc64(p->z, p->nAlloc);
p->z = sqlite3_realloc(p->z, p->nAlloc);
if( p->z==0 ){
fprintf(stderr, "out of memory\n");
exit(1);
@@ -2165,7 +2136,7 @@ static void import_append_char(ImportCtx *p, int c){
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc64().
** from sqlite3_malloc().
** + Use p->cSep as the column separator. The default is ",".
** + Use p->rSep as the row separator. The default is "\n".
** + Keep track of the line number in p->nLine.
@@ -2239,7 +2210,7 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc64().
** from sqlite3_malloc().
** + Use p->cSep as the column separator. The default is "\x1F".
** + Use p->rSep as the row separator. The default is "\x1E".
** + Keep track of the row number in p->nLine.
@@ -2299,7 +2270,7 @@ static void tryToCloneData(
goto end_data_xfer;
}
n = sqlite3_column_count(pQuery);
zInsert = sqlite3_malloc64(200 + nTable + n*3);
zInsert = sqlite3_malloc(200 + nTable + n*3);
if( zInsert==0 ){
fprintf(stderr, "out of memory\n");
goto end_data_xfer;
@@ -2715,19 +2686,6 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
setBinaryMode(p->out);
}else{
setTextMode(p->out);
}
}else{
fprintf(stderr, "Usage: .binary on|off\n");
rc = 1;
}
}else
/* The undocumented ".breakpoint" command causes a call to the no-op
** routine named test_breakpoint().
*/
@@ -3067,7 +3025,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_finalize(pStmt);
pStmt = 0;
if( nCol==0 ) return 0; /* no columns, no error */
zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 );
if( zSql==0 ){
fprintf(stderr, "Error: out of memory\n");
xCloser(sCtx.in);
@@ -3207,64 +3165,6 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#endif
if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
static const struct {
const char *zLimitName; /* Name of a limit */
int limitCode; /* Integer code for that limit */
} aLimit[] = {
{ "length", SQLITE_LIMIT_LENGTH },
{ "sql_length", SQLITE_LIMIT_SQL_LENGTH },
{ "column", SQLITE_LIMIT_COLUMN },
{ "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
{ "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
{ "vdbe_op", SQLITE_LIMIT_VDBE_OP },
{ "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
{ "attached", SQLITE_LIMIT_ATTACHED },
{ "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
{ "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
{ "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
};
int i, n2;
open_db(p, 0);
if( nArg==1 ){
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
printf("%20s %d\n", aLimit[i].zLimitName,
sqlite3_limit(p->db, aLimit[i].limitCode, -1));
}
}else if( nArg>3 ){
fprintf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
rc = 1;
goto meta_command_exit;
}else{
int iLimit = -1;
n2 = strlen30(azArg[1]);
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
if( iLimit<0 ){
iLimit = i;
}else{
fprintf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
rc = 1;
goto meta_command_exit;
}
}
}
if( iLimit<0 ){
fprintf(stderr, "unknown limit: \"%s\"\n"
"enter \".limits\" with no arguments for a list.\n",
azArg[1]);
rc = 1;
goto meta_command_exit;
}
if( nArg==3 ){
sqlite3_limit(p->db, aLimit[iLimit].limitCode,
(int)integerValue(azArg[2]));
}
printf("%20s %d\n", aLimit[iLimit].zLimitName,
sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
}
}else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
@@ -3750,7 +3650,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( nRow>=nAlloc ){
char **azNew;
int n2 = nAlloc*2 + 10;
azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n2);
if( azNew==0 ){
fprintf(stderr, "Error: out of memory\n");
break;
+57 -44
View File
@@ -963,14 +963,6 @@ struct sqlite3_io_methods {
** circumstances in order to fix a problem with priority inversion.
** Applications should <em>not</em> use this file-control.
**
** <li>[[SQLITE_FCNTL_ZIPVFS]]
** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
** VFS should return SQLITE_NOTFOUND for this opcode.
**
** <li>[[SQLITE_FCNTL_OTA]]
** The [SQLITE_FCNTL_OTA] opcode is implemented by the special VFS used by
** the OTA extension only. All other VFS should return SQLITE_NOTFOUND for
** this opcode.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -996,8 +988,6 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
#define SQLITE_FCNTL_WAL_BLOCK 24
#define SQLITE_FCNTL_ZIPVFS 25
#define SQLITE_FCNTL_OTA 26
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1879,11 +1869,36 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_LOG]] <dt>SQLITE_DBCONFIG_LOG</dt>
** <dd> The SQLITE_DBCONFIG_LOG option is used to configure the SQLite
** [error log] for a specific database connection. See also the
** [SQLITE_CONFIG_LOG] option to [sqlite3_config()] for the global log
** callback.
** (^The SQLITE_DBCONFIG_LOG option takes two arguments: a pointer to a
** function with a call signature of void(*)(void*,int,const char*),
** and a pointer to void. ^If the function pointer is not NULL, it is
** invoked by [sqlite3_db_log()] to process each logging event. ^If the
** function pointer is NULL, then calls to [sqlite3_db_log()] interface try
** to use the [SQLITE_CONFIG_LOG|global error log]. If both the connection
** and global error log callbacks are NULL then [sqlite3_db_log()] is a
** harmless no-op.
** ^The void pointer that is the second argument to SQLITE_DBCONFIG_LOG is
** passed through as the first parameter to the application-defined logger
** function whenever that function is invoked. ^The second parameter to
** the logger function is a copy of the second parameter to the corresponding
** [sqlite3_db_log()] call and is intended to be a [result code] or an
** [extended result code]. ^The third parameter passed to the logger is
** log message after formatting via [sqlite3_snprintf()].
** The SQLite logging interface is not reentrant; the logger function
** supplied by the application must not invoke any SQLite interface.
** </dd>
**
** </dl>
*/
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_LOG 1004 /* xFunc, void* */
/*
@@ -3400,9 +3415,7 @@ int sqlite3_stmt_busy(sqlite3_stmt*);
** Some interfaces require a protected sqlite3_value. Other interfaces
** will accept either a protected or an unprotected sqlite3_value.
** Every interface that accepts sqlite3_value arguments specifies
** whether or not it requires a protected sqlite3_value. The
** [sqlite3_value_dup()] interface can be used to construct a new
** protected sqlite3_value from an unprotected sqlite3_value.
** whether or not it requires a protected sqlite3_value.
**
** The terms "protected" and "unprotected" refer to whether or not
** a mutex is held. An internal mutex is held for a protected
@@ -3905,6 +3918,8 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** KEYWORDS: {column access functions}
** METHOD: sqlite3_stmt
**
** These routines form the "result set" interface.
**
** ^These routines return information about a single column of the current
** result row of a query. ^In every case the first argument is a pointer
** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
@@ -3964,14 +3979,13 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** even empty strings, are always zero-terminated. ^The return
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
**
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object. In a multithreaded environment,
** an unprotected sqlite3_value object may only be used safely with
** [sqlite3_bind_value()] and [sqlite3_result_value()].
** ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object. An unprotected sqlite3_value object
** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
** If the [unprotected sqlite3_value] object returned by
** [sqlite3_column_value()] is used in any other way, including calls
** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
** or [sqlite3_value_bytes()], the behavior is not threadsafe.
** or [sqlite3_value_bytes()], then the behavior is undefined.
**
** These routines attempt to convert the value where appropriate. ^For
** example, if the internal representation is FLOAT and a text result
@@ -4002,6 +4016,12 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** </table>
** </blockquote>)^
**
** The table above makes reference to standard C library functions atoi()
** and atof(). SQLite does not really use these functions. It has its
** own equivalent internal routines. The atoi() and atof() names are
** used in the table for brevity and because they are familiar to most
** C programmers.
**
** Note that when type conversions occur, pointers returned by prior
** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
** sqlite3_column_text16() may be invalidated.
@@ -4026,7 +4046,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** of conversion are done in place when it is possible, but sometimes they
** are not possible and in those cases prior pointers are invalidated.
**
** The safest policy is to invoke these routines
** The safest and easiest to remember policy is to invoke these routines
** in one of the following ways:
**
** <ul>
@@ -4046,7 +4066,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** ^The pointers returned are valid until a type conversion occurs as
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
** [sqlite3_finalize()] is called. ^The memory space used to hold strings
** and BLOBs is freed automatically. Do <em>not</em> pass the pointers returned
** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
@@ -4296,12 +4316,12 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
#endif
/*
** CAPI3REF: Obtaining SQL Values
** CAPI3REF: Obtaining SQL Function Parameter Values
** METHOD: sqlite3_value
**
** The C-language implementation of SQL functions and aggregates uses
** this set of interface routines to access the parameter values on
** the function or aggregate.
** the function or aggregate.
**
** The xFunc (for scalar functions) or xStep (for aggregates) parameters
** to [sqlite3_create_function()] and [sqlite3_create_function16()]
@@ -4354,23 +4374,6 @@ const void *sqlite3_value_text16be(sqlite3_value*);
int sqlite3_value_type(sqlite3_value*);
int sqlite3_value_numeric_type(sqlite3_value*);
/*
** CAPI3REF: Copy And Free SQL Values
** METHOD: sqlite3_value
**
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
** is a [protected sqlite3_value] object even if the input is not.
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
** memory allocation fails.
**
** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object
** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
** then sqlite3_value_free(V) is a harmless no-op.
*/
SQLITE_EXPERIMENTAL sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
SQLITE_EXPERIMENTAL void sqlite3_value_free(sqlite3_value*);
/*
** CAPI3REF: Obtain Aggregate Function Context
** METHOD: sqlite3_context
@@ -4618,7 +4621,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** from [sqlite3_malloc()] before it returns.
**
** ^The sqlite3_result_value() interface sets the result of
** the application-defined function to be a copy of the
** the application-defined function to be a copy the
** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
** so that the [sqlite3_value] specified in the parameter may change or
@@ -5894,7 +5897,7 @@ int sqlite3_blob_open(
**
** ^This function sets the database handle error code and message.
*/
int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
/*
** CAPI3REF: Close A BLOB Handle
@@ -7307,10 +7310,19 @@ int sqlite3_strglob(const char *zGlob, const char *zStr);
**
** ^The [sqlite3_log()] interface writes a message into the [error log]
** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
** ^The [sqlite3_db_log()] interface writes a message into the [error log]
** established by the [SQLITE_DBCONFIG_LOG] option to [sqlite3_db_config()].
** ^If logging is enabled, the zFormat string and subsequent arguments are
** used with [sqlite3_snprintf()] to generate the final output string.
**
** The sqlite3_log() interface is intended for use by extensions such as
** ^The [sqlite3_db_log()] interface writes error and warning information
** to the callback identified by the [SQLITE_DBCONFIG_LOG] option if that
** callback is not NULL, falling back to the [SQLITE_CONFIG_LOG] callback
** if the first parameter to [sqlite3_db_log()] is NULL or if the
** [SQLITE_DBCONFIG_LOG] callback is NULL.
**
** The sqlite3_log() and sqlite3_db_log() interfaces are intended for
** use by extensions such as
** virtual tables, collating functions, and SQL functions. While there is
** nothing to prevent an application from calling sqlite3_log(), doing so
** is considered bad form.
@@ -7324,6 +7336,7 @@ int sqlite3_strglob(const char *zGlob, const char *zStr);
** buffer.
*/
void sqlite3_log(int iErrCode, const char *zFormat, ...);
void sqlite3_db_log(sqlite3*, int iErrCode, const char *zFormat, ...);
/*
** CAPI3REF: Write-Ahead Log Commit Hook
@@ -7704,7 +7717,7 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
**
** See also: [sqlite3_stmt_scanstatus_reset()]
*/
int sqlite3_stmt_scanstatus(
SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
@@ -7720,7 +7733,7 @@ int sqlite3_stmt_scanstatus(
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
-5
View File
@@ -267,8 +267,6 @@ struct sqlite3_api_routines {
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
sqlite3_value (*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
};
/*
@@ -499,9 +497,6 @@ struct sqlite3_api_routines {
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup sqlite3_api->value_dup
#define sqlite3_value_free sqlite3_api->value_free
#endif /* SQLITE_CORE */
#ifndef SQLITE_CORE
+62 -69
View File
@@ -362,32 +362,6 @@
# define NEVER(X) (X)
#endif
/*
** Declarations used for tracing the operating system interfaces.
*/
#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \
(defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
extern int sqlite3OSTrace;
# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
# define SQLITE_HAVE_OS_TRACE
#else
# define OSTRACE(X)
# undef SQLITE_HAVE_OS_TRACE
#endif
/*
** Is the sqlite3ErrName() function needed in the build? Currently,
** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when
** OSTRACE is enabled), and by several "test*.c" files (which are
** compiled using SQLITE_TEST).
*/
#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \
(defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
# define SQLITE_NEED_ERR_NAME
#else
# undef SQLITE_NEED_ERR_NAME
#endif
/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits. This macro is used inside of various testcase()
@@ -1164,6 +1138,8 @@ struct sqlite3 {
double notUsed1; /* Spacer */
} u1;
Lookaside lookaside; /* Lookaside malloc configuration */
void (*xLog)(void*,int,const char*); /* Function for logging */
void *pLogArg; /* First argument to xLog() */
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth; /* Access authorization function */
void *pAuthArg; /* 1st argument to the access auth function */
@@ -1253,7 +1229,6 @@ struct sqlite3 {
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */
#define SQLITE_CellSizeCk 0x10000000 /* Check btree cell sizes on load */
/*
@@ -1501,9 +1476,9 @@ struct CollSeq {
** used as the P4 operand, they will be more readable.
**
** Note also that the numeric types are grouped together so that testing
** for a numeric type is a single comparison. And the BLOB type is first.
** for a numeric type is a single comparison. And the NONE type is first.
*/
#define SQLITE_AFF_BLOB 'A'
#define SQLITE_AFF_NONE 'A'
#define SQLITE_AFF_TEXT 'B'
#define SQLITE_AFF_NUMERIC 'C'
#define SQLITE_AFF_INTEGER 'D'
@@ -1584,8 +1559,34 @@ struct VTable {
};
/*
** The schema for each SQL table and view is represented in memory
** by an instance of the following structure.
** Each SQL table is represented in memory by an instance of the
** following structure.
**
** Table.zName is the name of the table. The case of the original
** CREATE TABLE statement is stored, but case is not significant for
** comparisons.
**
** Table.nCol is the number of columns in this table. Table.aCol is a
** pointer to an array of Column structures, one for each column.
**
** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of
** the column that is that key. Otherwise Table.iPKey is negative. Note
** that the datatype of the PRIMARY KEY must be INTEGER for this field to
** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
** is generated for each row of the table. TF_HasPrimaryKey is set if
** the table has any PRIMARY KEY, INTEGER or otherwise.
**
** Table.tnum is the page number for the root BTree page of the table in the
** database file. If Table.iDb is the index of the database table backend
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
** holds temporary tables and indices. If TF_Ephemeral is set
** then the table is stored in a file that is automatically deleted
** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
** page number. Transient tables are used to hold the results of a
** sub-query that appears instead of a real table name in the FROM clause
** of a SELECT statement.
*/
struct Table {
char *zName; /* Name of the table or view */
@@ -1597,11 +1598,11 @@ struct Table {
#ifndef SQLITE_OMIT_CHECK
ExprList *pCheck; /* All CHECK constraints */
#endif
int tnum; /* Root BTree page for this table */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
int tnum; /* Root BTree node for this table (see note above) */
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
i16 nCol; /* Number of columns in this table */
u16 nRef; /* Number of pointers to this Table */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
LogEst costMult; /* Cost multiplier for using this table */
@@ -1635,9 +1636,8 @@ struct Table {
#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
#define TF_Virtual 0x10 /* Is a virtual table */
#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */
#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */
#define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */
#define TF_OOOHidden 0x40 /* Out-of-Order hidden columns */
/*
@@ -1655,7 +1655,6 @@ struct Table {
/* Does the table have a rowid */
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
/*
** Each foreign key constraint is an instance of the following structure.
@@ -1814,14 +1813,6 @@ struct UnpackedRecord {
** and the value of Index.onError indicate the which conflict resolution
** algorithm to employ whenever an attempt is made to insert a non-unique
** element.
**
** While parsing a CREATE TABLE or CREATE INDEX statement in order to
** generate VDBE code (as opposed to parsing one read from an sqlite_master
** table as part of parsing an existing database schema), transient instances
** of this structure may be created. In this case the Index.tnum variable is
** used to store the address of a VDBE instruction, not a database page
** number (it cannot - the database page is not allocated until the VDBE
** program is executed). See convertToWithoutRowidTable() for details.
*/
struct Index {
char *zName; /* Name of this index */
@@ -2260,7 +2251,7 @@ struct SrcList {
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
char *zIndex; /* Identifier from "INDEXED BY <zIndex>" clause */
Index *pIndex; /* Index structure corresponding to zIndex, if any */
} a[1]; /* One entry for each identifier on the list */
};
@@ -2396,20 +2387,19 @@ struct Select {
** "Select Flag".
*/
#define SF_Distinct 0x0001 /* Output should be DISTINCT */
#define SF_All 0x0002 /* Includes the ALL keyword */
#define SF_Resolved 0x0004 /* Identifiers have been resolved */
#define SF_Aggregate 0x0008 /* Contains aggregate functions */
#define SF_UsesEphemeral 0x0010 /* Uses the OpenEphemeral opcode */
#define SF_Expanded 0x0020 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo 0x0040 /* FROM subqueries have Table metadata */
#define SF_Compound 0x0080 /* Part of a compound query */
#define SF_Values 0x0100 /* Synthesized from VALUES clause */
#define SF_MultiValue 0x0200 /* Single VALUES term with multiple rows */
#define SF_NestedFrom 0x0400 /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert 0x0800 /* Need convertCompoundSelectToSubquery() */
#define SF_Resolved 0x0002 /* Identifiers have been resolved */
#define SF_Aggregate 0x0004 /* Contains aggregate functions */
#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_Compound 0x0040 /* Part of a compound query */
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
#define SF_MultiValue 0x0100 /* Single VALUES term with multiple rows */
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */
#define SF_Recursive 0x2000 /* The recursive part of a recursive CTE */
#define SF_Converted 0x4000 /* By convertCompoundSelectToSubquery() */
#define SF_Converted 0x2000 /* By convertCompoundSelectToSubquery() */
/*
@@ -2651,6 +2641,7 @@ struct Parse {
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */
int addrSkipPK; /* Address of instruction to skip PRIMARY KEY index */
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
@@ -2846,7 +2837,8 @@ struct StrAccum {
char *zText; /* The string collected so far */
int nChar; /* Length of the string so far */
int nAlloc; /* Amount of space allocated in zText */
int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
int mxAlloc; /* Maximum allowed string length */
u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */
u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
};
#define STRACCUM_NOMEM 1
@@ -3162,7 +3154,8 @@ void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list);
void sqlite3XPrintf(StrAccum*, u32, const char*, ...);
char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
void sqlite3DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE_TEST)
@@ -3170,13 +3163,17 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#endif
#if defined(SQLITE_DEBUG)
TreeView *sqlite3TreeViewPush(TreeView*,u8);
void sqlite3TreeViewPop(TreeView*);
void sqlite3TreeViewLine(TreeView*, const char*, ...);
void sqlite3TreeViewItem(TreeView*, const char*, u8);
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
#endif
void sqlite3SetString(char **, sqlite3*, const char*);
void sqlite3SetString(char **, sqlite3*, const char*, ...);
void sqlite3ErrorMsg(Parse*, const char*, ...);
int sqlite3Dequote(char*);
int sqlite3KeywordCode(const unsigned char*, int);
@@ -3505,7 +3502,7 @@ void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
u8 sqlite3HexToInt(int h);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
#if defined(SQLITE_NEED_ERR_NAME)
#if defined(SQLITE_TEST)
const char *sqlite3ErrName(int);
#endif
@@ -3599,7 +3596,7 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3OpenTempDatabase(Parse *);
void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
void sqlite3StrAccumInit(StrAccum*, char*, int, int);
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
void sqlite3AppendChar(StrAccum*,int,char);
@@ -3873,8 +3870,4 @@ int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
int sqlite3ThreadJoin(SQLiteThread*, void**);
#endif
#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)
int sqlite3DbstatRegister(sqlite3*);
#endif
#endif /* _SQLITEINT_H_ */
+3 -3
View File
@@ -90,7 +90,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
z = 0;
}else{
int n = sqlite3Strlen30(argv[i])+1;
z = sqlite3_malloc64( n );
z = sqlite3_malloc( n );
if( z==0 ) goto malloc_failed;
memcpy(z, argv[i], n);
}
@@ -139,7 +139,7 @@ int sqlite3_get_table(
res.nData = 1;
res.nAlloc = 20;
res.rc = SQLITE_OK;
res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc );
res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc );
if( res.azResult==0 ){
db->errCode = SQLITE_NOMEM;
return SQLITE_NOMEM;
@@ -167,7 +167,7 @@ int sqlite3_get_table(
}
if( res.nAlloc>res.nData ){
char **azNew;
azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData );
if( azNew==0 ){
sqlite3_free_table(&res.azResult[1]);
db->errCode = SQLITE_NOMEM;
+12 -3
View File
@@ -3704,7 +3704,7 @@ static int db_last_stmt_ptr(
return TCL_OK;
}
#endif /* SQLITE_TEST */
#endif
/*
** Configure the interpreter passed as the first argument to have access
@@ -3724,6 +3724,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*);
@@ -3760,7 +3771,6 @@ static void init_all(Tcl_Interp *interp){
extern int Sqlitemultiplex_Init(Tcl_Interp*);
extern int SqliteSuperlock_Init(Tcl_Interp*);
extern int SqlitetestSyscall_Init(Tcl_Interp*);
extern int SqliteOta_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
@@ -3804,7 +3814,6 @@ static void init_all(Tcl_Interp *interp){
Sqlitemultiplex_Init(interp);
SqliteSuperlock_Init(interp);
SqlitetestSyscall_Init(interp);
SqliteOta_Init(interp);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
Sqlitetestfts3_Init(interp);
+29 -36
View File
@@ -5797,7 +5797,7 @@ static int test_sqlite3_log(
logcallback.pInterp = 0;
sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
}
if( objc>1 ){
if( objc==2 ){
logcallback.pObj = objv[1];
Tcl_IncrRefCount(logcallback.pObj);
logcallback.pInterp = interp;
@@ -5805,6 +5805,32 @@ static int test_sqlite3_log(
}
return TCL_OK;
}
static int test_sqlite3_db_log(
ClientData clientData,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
sqlite3 *db;
if( objc<1 || objc>3 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
if( logcallback.pObj ){
Tcl_DecrRefCount(logcallback.pObj);
logcallback.pObj = 0;
logcallback.pInterp = 0;
sqlite3_db_config(db, SQLITE_DBCONFIG_LOG, 0, 0);
}
if( objc==3 ){
logcallback.pObj = objv[2];
Tcl_IncrRefCount(logcallback.pObj);
logcallback.pInterp = interp;
sqlite3_db_config(db, SQLITE_DBCONFIG_LOG, xLogcallback, 0);
}
return TCL_OK;
}
/*
** tcl_objproc COMMANDNAME ARGS...
@@ -6680,40 +6706,7 @@ static int test_bad_behavior(
}
return TCL_OK;
}
/*
** tclcmd: register_dbstat_vtab DB
**
** Cause the dbstat virtual table to be available on the connection DB
*/
static int test_register_dbstat_vtab(
void *clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_OMIT_VIRTUALTABLE
Tcl_AppendResult(interp, "dbstat not available because of "
"SQLITE_OMIT_VIRTUALTABLE", (void*)0);
return TCL_ERROR;
#else
struct SqliteDb { sqlite3 *db; };
char *zDb;
Tcl_CmdInfo cmdInfo;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
zDb = Tcl_GetString(objv[1]);
if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
sqlite3DbstatRegister(db);
}
return TCL_OK;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}
/*
** Register commands with the TCL interpreter.
@@ -6785,7 +6778,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
void *clientData;
} aObjCmd[] = {
{ "bad_behavior", test_bad_behavior, (void*)&iZero },
{ "register_dbstat_vtab", test_register_dbstat_vtab },
{ "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
{ "sqlite3_bind_int", test_bind_int, 0 },
{ "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
@@ -6940,6 +6932,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
{ "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 },
{ "test_sqlite3_log", test_sqlite3_log, 0 },
{ "test_sqlite3_db_log", test_sqlite3_db_log, 0 },
#ifndef SQLITE_OMIT_EXPLAIN
{ "print_explain_query_plan", test_print_eqp, 0 },
#endif
+1 -4
View File
@@ -16,7 +16,6 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifndef SQLITE_OMIT_INCRBLOB
/* These functions are implemented in main.c. */
extern const char *sqlite3ErrName(int);
@@ -296,13 +295,12 @@ static int test_blob_write(
return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
}
#endif /* SQLITE_OMIT_INCRBLOB */
/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_blob_Init(Tcl_Interp *interp){
#ifndef SQLITE_OMIT_INCRBLOB
static struct {
char *zName;
Tcl_ObjCmdProc *xProc;
@@ -317,6 +315,5 @@ int Sqlitetest_blob_Init(Tcl_Interp *interp){
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
}
#endif /* SQLITE_OMIT_INCRBLOB */
return TCL_OK;
}
-6
View File
@@ -430,12 +430,6 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_OTA
Tcl_SetVar2(interp, "sqlite_options", "ota", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "ota", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
#else
+4 -4
View File
@@ -85,7 +85,7 @@ static int intarrayCreate(
char **pzErr /* Put error message text here */
){
int rc = SQLITE_NOMEM;
intarray_vtab *pVtab = sqlite3_malloc64(sizeof(intarray_vtab));
intarray_vtab *pVtab = sqlite3_malloc(sizeof(intarray_vtab));
if( pVtab ){
memset(pVtab, 0, sizeof(intarray_vtab));
@@ -102,7 +102,7 @@ static int intarrayCreate(
static int intarrayOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
int rc = SQLITE_NOMEM;
intarray_cursor *pCur;
pCur = sqlite3_malloc64(sizeof(intarray_cursor));
pCur = sqlite3_malloc(sizeof(intarray_cursor));
if( pCur ){
memset(pCur, 0, sizeof(intarray_cursor));
*ppCursor = (sqlite3_vtab_cursor *)pCur;
@@ -225,7 +225,7 @@ SQLITE_API int sqlite3_intarray_create(
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_intarray *p;
*ppReturn = p = sqlite3_malloc64( sizeof(*p) );
*ppReturn = p = sqlite3_malloc( sizeof(*p) );
if( p==0 ){
return SQLITE_NOMEM;
}
@@ -340,7 +340,7 @@ static int test_intarray_bind(
pArray = (sqlite3_intarray*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
n = objc - 2;
#ifndef SQLITE_OMIT_VIRTUALTABLE
a = sqlite3_malloc64( sizeof(a[0])*n );
a = sqlite3_malloc( sizeof(a[0])*n );
if( a==0 ){
Tcl_AppendResult(interp, "SQLITE_NOMEM", (char*)0);
return TCL_ERROR;
+5 -5
View File
@@ -286,7 +286,7 @@ static void multiplexFilename(
static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
if( iChunk>=pGroup->nReal ){
struct multiplexReal *p;
p = sqlite3_realloc64(pGroup->aReal, (iChunk+1)*sizeof(*p));
p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p));
if( p==0 ){
return SQLITE_NOMEM;
}
@@ -297,7 +297,7 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
char *z;
int n = pGroup->nName;
pGroup->aReal[iChunk].z = z = sqlite3_malloc64( n+5 );
pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+5 );
if( z==0 ){
return SQLITE_NOMEM;
}
@@ -357,7 +357,7 @@ static sqlite3_file *multiplexSubOpen(
}
flags &= ~SQLITE_OPEN_CREATE;
}
pSubOpen = sqlite3_malloc64( pOrigVfs->szOsFile );
pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
if( pSubOpen==0 ){
*rc = SQLITE_IOERR_NOMEM;
return 0;
@@ -524,7 +524,7 @@ static int multiplexOpen(
nName = zName ? multiplexStrlen30(zName) : 0;
sz = sizeof(multiplexGroup) /* multiplexGroup */
+ nName + 1; /* zName */
pGroup = sqlite3_malloc64( sz );
pGroup = sqlite3_malloc( sz );
if( pGroup==0 ){
rc = SQLITE_NOMEM;
}
@@ -655,7 +655,7 @@ static int multiplexDelete(
*/
int nName = (int)strlen(zName);
char *z;
z = sqlite3_malloc64(nName + 5);
z = sqlite3_malloc(nName + 5);
if( z==0 ){
rc = SQLITE_IOERR_NOMEM;
}else{
+8 -40
View File
@@ -155,11 +155,6 @@ static int circle_geom(
/*
** Implementation of "circle" r-tree geometry callback using the
** 2nd-generation interface that allows scoring.
**
** Two calling forms:
**
** Qcircle(X,Y,Radius,eType) -- All values are doubles
** Qcircle('x:X y:Y r:R e:ETYPE') -- Single string parameter
*/
static int circle_query_func(sqlite3_rtree_query_info *p){
int i; /* Iterator variable */
@@ -181,9 +176,10 @@ static int circle_query_func(sqlite3_rtree_query_info *p){
** Return an error if the table does not have exactly 2 dimensions. */
if( p->nCoord!=4 ) return SQLITE_ERROR;
/* Test that the correct number of parameters (1 or 4) have been supplied.
*/
if( p->nParam!=4 && p->nParam!=1 ) return SQLITE_ERROR;
/* Test that the correct number of parameters (4) have been supplied,
** and that the parameters are in range (that the radius of the circle
** radius is greater than zero). */
if( p->nParam!=4 || p->aParam[2]<0.0 ) return SQLITE_ERROR;
/* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM
** if the allocation fails. */
@@ -195,38 +191,10 @@ static int circle_query_func(sqlite3_rtree_query_info *p){
** tested bounding boxes that intersect the circular region are detected
** is by testing if each corner of the bounding box lies within radius
** units of the center of the circle. */
if( p->nParam==4 ){
pCircle->centerx = p->aParam[0];
pCircle->centery = p->aParam[1];
pCircle->radius = p->aParam[2];
pCircle->eScoreType = (int)p->aParam[3];
}else{
const char *z = (const char*)sqlite3_value_text(p->apSqlParam[0]);
pCircle->centerx = 0.0;
pCircle->centery = 0.0;
pCircle->radius = 0.0;
pCircle->eScoreType = 0;
while( z && z[0] ){
if( z[0]=='r' && z[1]==':' ){
pCircle->radius = atof(&z[2]);
}else if( z[0]=='x' && z[1]==':' ){
pCircle->centerx = atof(&z[2]);
}else if( z[0]=='y' && z[1]==':' ){
pCircle->centery = atof(&z[2]);
}else if( z[0]=='e' && z[1]==':' ){
pCircle->eScoreType = (int)atof(&z[2]);
}else if( z[0]==' ' ){
z++;
continue;
}
while( z[0]!=0 && z[0]!=' ' ) z++;
while( z[0]==' ' ) z++;
}
}
if( pCircle->radius<0.0 ){
sqlite3_free(pCircle);
return SQLITE_NOMEM;
}
pCircle->centerx = p->aParam[0];
pCircle->centery = p->aParam[1];
pCircle->radius = p->aParam[2];
pCircle->eScoreType = (int)p->aParam[3];
/* Define two bounding box regions. The first, aBox[0], extends to
** infinity in the X dimension. It covers the same range of the Y dimension
+106 -110
View File
@@ -18,9 +18,11 @@
** for an example implementation.
*/
#include "sqliteInt.h" /* Requires access to internal data structures */
#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
#ifndef SQLITE_AMALGAMATION
# include "sqliteInt.h"
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Page paths:
@@ -122,7 +124,6 @@ struct StatCursor {
struct StatTable {
sqlite3_vtab base;
sqlite3 *db;
int iDb; /* Index of database to analyze */
};
#ifndef get2byte
@@ -139,34 +140,15 @@ static int statConnect(
sqlite3_vtab **ppVtab,
char **pzErr
){
StatTable *pTab = 0;
int rc = SQLITE_OK;
int iDb;
StatTable *pTab;
if( argc>=4 ){
iDb = sqlite3FindDbName(db, argv[3]);
if( iDb<0 ){
*pzErr = sqlite3_mprintf("no such database: %s", argv[3]);
return SQLITE_ERROR;
}
}else{
iDb = 0;
}
rc = sqlite3_declare_vtab(db, VTAB_SCHEMA);
if( rc==SQLITE_OK ){
pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable));
if( pTab==0 ) rc = SQLITE_NOMEM;
}
pTab = (StatTable *)sqlite3_malloc(sizeof(StatTable));
memset(pTab, 0, sizeof(StatTable));
pTab->db = db;
assert( rc==SQLITE_OK || pTab==0 );
if( rc==SQLITE_OK ){
memset(pTab, 0, sizeof(StatTable));
pTab->db = db;
pTab->iDb = iDb;
}
*ppVtab = (sqlite3_vtab*)pTab;
return rc;
sqlite3_declare_vtab(db, VTAB_SCHEMA);
*ppVtab = &pTab->base;
return SQLITE_OK;
}
/*
@@ -213,45 +195,33 @@ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
StatCursor *pCsr;
int rc;
pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor));
if( pCsr==0 ){
rc = SQLITE_NOMEM;
}else{
char *zSql;
memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab;
pCsr = (StatCursor *)sqlite3_malloc(sizeof(StatCursor));
memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab;
zSql = sqlite3_mprintf(
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type"
" FROM \"%w\".sqlite_master WHERE rootpage!=0"
" ORDER BY name", pTab->db->aDb[pTab->iDb].zName);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc!=SQLITE_OK ){
sqlite3_free(pCsr);
pCsr = 0;
}
rc = sqlite3_prepare_v2(pTab->db,
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0"
" ORDER BY name", -1,
&pCsr->pStmt, 0
);
if( rc!=SQLITE_OK ){
sqlite3_free(pCsr);
return rc;
}
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return rc;
return SQLITE_OK;
}
static void statClearPage(StatPage *p){
int i;
if( p->aCell ){
for(i=0; i<p->nCell; i++){
sqlite3_free(p->aCell[i].aOvfl);
}
sqlite3_free(p->aCell);
for(i=0; i<p->nCell; i++){
sqlite3_free(p->aCell[i].aOvfl);
}
sqlite3PagerUnref(p->pPg);
sqlite3_free(p->aCell);
sqlite3_free(p->zPath);
memset(p, 0, sizeof(StatPage));
}
@@ -336,8 +306,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
sqlite3BtreeEnter(pBt);
nUsable = szPage - sqlite3BtreeGetReserveNoMutex(pBt);
sqlite3BtreeLeave(pBt);
p->aCell = sqlite3_malloc64((p->nCell+1) * sizeof(StatCell));
if( p->aCell==0 ) return SQLITE_NOMEM;
p->aCell = sqlite3_malloc((p->nCell+1) * sizeof(StatCell));
memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell));
for(i=0; i<p->nCell; i++){
@@ -369,8 +338,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
pCell->nOvfl = nOvfl;
pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
if( pCell->aOvfl==0 ) return SQLITE_NOMEM;
pCell->aOvfl = sqlite3_malloc(sizeof(u32)*nOvfl);
pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]);
for(j=1; j<nOvfl; j++){
int rc;
@@ -398,7 +366,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
*/
static void statSizeAndOffset(StatCursor *pCsr){
StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab;
Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
Btree *pBt = pTab->db->aDb[0].pBt;
Pager *pPager = sqlite3BtreePager(pBt);
sqlite3_file *fd;
sqlite3_int64 x[2];
@@ -412,7 +380,7 @@ static void statSizeAndOffset(StatCursor *pCsr){
*/
fd = sqlite3PagerFile(pPager);
x[0] = pCsr->iPageno;
if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
pCsr->iOffset = x[0];
pCsr->szPage = (int)x[1];
}
@@ -424,10 +392,9 @@ static void statSizeAndOffset(StatCursor *pCsr){
static int statNext(sqlite3_vtab_cursor *pCursor){
int rc;
int nPayload;
char *z;
StatCursor *pCsr = (StatCursor *)pCursor;
StatTable *pTab = (StatTable *)pCursor->pVtab;
Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
Btree *pBt = pTab->db->aDb[0].pBt;
Pager *pPager = sqlite3BtreePager(pBt);
sqlite3_free(pCsr->zPath);
@@ -447,9 +414,8 @@ statNextRestart:
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
pCsr->aPage[0].iPgno = iRoot;
pCsr->aPage[0].iCell = 0;
pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
pCsr->aPage[0].zPath = sqlite3_mprintf("/");
pCsr->iPage = 0;
if( z==0 ) rc = SQLITE_NOMEM;
}else{
pCsr->isEof = 1;
return sqlite3_reset(pCsr->pStmt);
@@ -472,7 +438,7 @@ statNextRestart:
pCsr->zPagetype = "overflow";
pCsr->nCell = 0;
pCsr->nMxPayload = 0;
pCsr->zPath = z = sqlite3_mprintf(
pCsr->zPath = sqlite3_mprintf(
"%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl
);
if( pCell->iOvfl<pCell->nOvfl-1 ){
@@ -484,7 +450,7 @@ statNextRestart:
}
pCell->iOvfl++;
statSizeAndOffset(pCsr);
return z==0 ? SQLITE_NOMEM : SQLITE_OK;
return SQLITE_OK;
}
if( p->iRightChildPg ) break;
p->iCell++;
@@ -506,9 +472,8 @@ statNextRestart:
}
rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg);
p[1].iCell = 0;
p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
p[1].zPath = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
p->iCell++;
if( z==0 ) rc = SQLITE_NOMEM;
}
@@ -521,34 +486,31 @@ statNextRestart:
pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
pCsr->iPageno = p->iPgno;
rc = statDecodePage(pBt, p);
if( rc==SQLITE_OK ){
statSizeAndOffset(pCsr);
statDecodePage(pBt, p);
statSizeAndOffset(pCsr);
switch( p->flags ){
case 0x05: /* table internal */
case 0x02: /* index internal */
pCsr->zPagetype = "internal";
break;
case 0x0D: /* table leaf */
case 0x0A: /* index leaf */
pCsr->zPagetype = "leaf";
break;
default:
pCsr->zPagetype = "corrupted";
break;
}
pCsr->nCell = p->nCell;
pCsr->nUnused = p->nUnused;
pCsr->nMxPayload = p->nMxPayload;
pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
if( z==0 ) rc = SQLITE_NOMEM;
nPayload = 0;
for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal;
}
pCsr->nPayload = nPayload;
switch( p->flags ){
case 0x05: /* table internal */
case 0x02: /* index internal */
pCsr->zPagetype = "internal";
break;
case 0x0D: /* table leaf */
case 0x0A: /* index leaf */
pCsr->zPagetype = "leaf";
break;
default:
pCsr->zPagetype = "corrupted";
break;
}
pCsr->nCell = p->nCell;
pCsr->nUnused = p->nUnused;
pCsr->nMxPayload = p->nMxPayload;
pCsr->zPath = sqlite3_mprintf("%s", p->zPath);
nPayload = 0;
for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal;
}
pCsr->nPayload = nPayload;
}
return rc;
@@ -578,7 +540,7 @@ static int statColumn(
StatCursor *pCsr = (StatCursor *)pCursor;
switch( i ){
case 0: /* name */
sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_STATIC);
break;
case 1: /* path */
sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
@@ -604,8 +566,7 @@ static int statColumn(
case 8: /* pgoffset */
sqlite3_result_int64(ctx, pCsr->iOffset);
break;
default: /* pgsize */
assert( i==9 );
case 9: /* pgsize */
sqlite3_result_int(ctx, pCsr->szPage);
break;
}
@@ -618,10 +579,7 @@ static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
return SQLITE_OK;
}
/*
** Invoke this routine to register the "dbstat" virtual table module
*/
int sqlite3DbstatRegister(sqlite3 *db){
int sqlite3_dbstat_register(sqlite3 *db){
static sqlite3_module dbstat_module = {
0, /* iVersion */
statConnect, /* xCreate */
@@ -644,8 +602,46 @@ int sqlite3DbstatRegister(sqlite3 *db){
0, /* xFindMethod */
0, /* xRename */
};
return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
return SQLITE_OK;
}
#elif defined(SQLITE_ENABLE_DBSTAT_VTAB)
int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; }
#endif /* SQLITE_ENABLE_DBSTAT_VTAB */
#endif
#if defined(SQLITE_TEST) || TCLSH==2
#include <tcl.h>
static int test_dbstat(
void *clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_OMIT_VIRTUALTABLE
Tcl_AppendResult(interp, "dbstat not available because of "
"SQLITE_OMIT_VIRTUALTABLE", (void*)0);
return TCL_ERROR;
#else
struct SqliteDb { sqlite3 *db; };
char *zDb;
Tcl_CmdInfo cmdInfo;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
zDb = Tcl_GetString(objv[1]);
if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
sqlite3_dbstat_register(db);
}
return TCL_OK;
#endif
}
int SqlitetestStat_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "register_dbstat_vtab", test_dbstat, 0, 0);
return TCL_OK;
}
#endif /* if defined(SQLITE_TEST) || TCLSH==2 */
+4 -7
View File
@@ -450,15 +450,12 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
}
abort_parse:
assert( nErr==0 );
if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
assert( zSql[i]==0 );
if( zSql[i]==0 && pParse->rc==SQLITE_OK ){
if( lastTokenParsed!=TK_SEMI ){
sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
pParse->zTail = &zSql[i];
}
if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
#ifdef YYTRACKMAXSTACKDEPTH
sqlite3_mutex_enter(sqlite3MallocMutex());
@@ -473,12 +470,12 @@ abort_parse:
pParse->rc = SQLITE_NOMEM;
}
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc));
}
assert( pzErrMsg!=0 );
if( pParse->zErrMsg ){
*pzErrMsg = pParse->zErrMsg;
sqlite3_log(pParse->rc, "%s", *pzErrMsg);
sqlite3_db_log(db, pParse->rc, "%s", *pzErrMsg);
pParse->zErrMsg = 0;
nErr++;
}
-425
View File
@@ -1,425 +0,0 @@
/*
** 2015-06-08
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains C code to implement the TreeView debugging routines.
** These routines print a parse tree to standard output for debugging and
** analysis.
**
** The interfaces in this file is only available when compiling
** with SQLITE_DEBUG.
*/
#include "sqliteInt.h"
#ifdef SQLITE_DEBUG
/*
** Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree.
*/
static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
if( p==0 ){
p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) return 0;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
return p;
}
/*
** Finished with one layer of the tree
*/
static void sqlite3TreeViewPop(TreeView *p){
if( p==0 ) return;
p->iLevel--;
if( p->iLevel<0 ) sqlite3_free(p);
}
/*
** Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines
*/
static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
}
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
}
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
/*
** Shorthand for starting a new tree item that consists of a single label
*/
static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
p = sqlite3TreeViewPush(p, moreFollows);
sqlite3TreeViewLine(p, "%s", zLabel);
}
/*
** Generate a human-readable description of a the Select object.
*/
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags
);
if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
if( p->pOffset ) n++;
if( p->pPrior ) n++;
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){
int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
for(i=0; i<p->pSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
}else if( pItem->zName ){
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
}
if( pItem->pTab ){
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
}
if( pItem->zAlias ){
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
}
if( pItem->jointype & JT_LEFT ){
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
}
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
if( pItem->pSelect ){
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
}
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, p->pWhere, 0);
sqlite3TreeViewPop(pView);
}
if( p->pGroupBy ){
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
}
if( p->pHaving ){
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlite3TreeViewExpr(pView, p->pHaving, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOrderBy ){
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOffset ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pOffset, 0);
sqlite3TreeViewPop(pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
switch( p->op ){
case TK_ALL: zOp = "UNION ALL"; break;
case TK_INTERSECT: zOp = "INTERSECT"; break;
case TK_EXCEPT: zOp = "EXCEPT"; break;
}
sqlite3TreeViewItem(pView, zOp, (n--)>0);
sqlite3TreeViewSelect(pView, p->pPrior, 0);
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
/*
** Generate a human-readable explanation of an expression tree.
*/
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(pView);
return;
}
switch( pExpr->op ){
case TK_AGG_COLUMN: {
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
pExpr->iTable, pExpr->iColumn);
break;
}
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
}else{
sqlite3TreeViewLine(pView, "{%d:%d}",
pExpr->iTable, pExpr->iColumn);
}
break;
}
case TK_INTEGER: {
if( pExpr->flags & EP_IntValue ){
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
}else{
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
case TK_NULL: {
sqlite3TreeViewLine(pView,"NULL");
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
}
case TK_REGISTER: {
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_AS: {
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_ID: {
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT: zBinOp = "LT"; break;
case TK_LE: zBinOp = "LE"; break;
case TK_GT: zBinOp = "GT"; break;
case TK_GE: zBinOp = "GE"; break;
case TK_NE: zBinOp = "NE"; break;
case TK_EQ: zBinOp = "EQ"; break;
case TK_IS: zBinOp = "IS"; break;
case TK_ISNOT: zBinOp = "ISNOT"; break;
case TK_AND: zBinOp = "AND"; break;
case TK_OR: zBinOp = "OR"; break;
case TK_PLUS: zBinOp = "ADD"; break;
case TK_STAR: zBinOp = "MUL"; break;
case TK_MINUS: zBinOp = "SUB"; break;
case TK_REM: zBinOp = "REM"; break;
case TK_BITAND: zBinOp = "BITAND"; break;
case TK_BITOR: zBinOp = "BITOR"; break;
case TK_SLASH: zBinOp = "DIV"; break;
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_DOT: zBinOp = "DOT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break;
case TK_BITNOT: zUniOp = "BITNOT"; break;
case TK_NOT: zUniOp = "NOT"; break;
case TK_ISNULL: zUniOp = "ISNULL"; break;
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
case TK_COLLATE: {
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_AGG_FUNCTION:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
pExpr->op2, pExpr->u.zToken);
}else{
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
}
if( pFarg ){
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
sqlite3TreeViewLine(pView, "EXISTS-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
sqlite3TreeViewLine(pView, "SELECT-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3TreeViewLine(pView, "IN");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
}
break;
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** x BETWEEN y AND z
**
** This is equivalent to
**
** x>=y AND x<=z
**
** X is stored in pExpr->pLeft.
** Y is stored in pExpr->pList->a[0].pExpr.
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
Expr *pX = pExpr->pLeft;
Expr *pY = pExpr->x.pList->a[0].pExpr;
Expr *pZ = pExpr->x.pList->a[1].pExpr;
sqlite3TreeViewLine(pView, "BETWEEN");
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
break;
}
case TK_TRIGGER: {
/* If the opcode is TK_TRIGGER, then the expression is a reference
** to a column in the new.* or old.* pseudo-tables available to
** trigger programs. In this case Expr.iTable is set to 1 for the
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
** is set to the column of the pseudo-table to read, or to -1 to
** read the rowid field.
*/
sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
case TK_CASE: {
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
switch( pExpr->affinity ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
#endif
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
}
}
if( zBinOp ){
sqlite3TreeViewLine(pView, "%s", zBinOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s", zUniOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(pView);
}
/*
** Generate a human-readable explanation of an expression list.
*/
void sqlite3TreeViewExprList(
TreeView *pView,
const ExprList *pList,
u8 moreToFollow,
const char *zLabel
){
int i;
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
if( pList==0 ){
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
}else{
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
}
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
+3 -1
View File
@@ -743,10 +743,12 @@ static void updateVirtualTable(
*/
assert( v );
ephemTab = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
/* fill the ephemeral table
*/
sqlite3SelectDestInit(&dest, SRT_EphemTab, ephemTab);
sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
sqlite3Select(pParse, pSelect, &dest);
/* Generate code to scan the ephemeral table and call VUpdate. */
+46 -33
View File
@@ -270,7 +270,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
** SQLITE_AFF_TEXT:
** Convert pRec to a text representation.
**
** SQLITE_AFF_BLOB:
** SQLITE_AFF_NONE:
** No-op. pRec is unchanged.
*/
static void applyAffinity(
@@ -296,7 +296,6 @@ static void applyAffinity(
if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
sqlite3VdbeMemStringify(pRec, enc, 1);
}
pRec->flags &= ~(MEM_Real|MEM_Int);
}
}
@@ -968,13 +967,14 @@ case OP_Halt: {
assert( zType!=0 || pOp->p4.z!=0 );
zLogFmt = "abort at %d in [%s]: %s";
if( zType && pOp->p4.z ){
sqlite3VdbeError(p, "%s constraint failed: %s", zType, pOp->p4.z);
sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s",
zType, pOp->p4.z);
}else if( pOp->p4.z ){
sqlite3VdbeError(p, "%s", pOp->p4.z);
sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
}else{
sqlite3VdbeError(p, "%s constraint failed", zType);
sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType);
}
sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg);
sqlite3_db_log(db, pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -985,6 +985,7 @@ case OP_Halt: {
assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
pOp = &aOp[pcx];
goto vdbe_return;
}
@@ -1204,11 +1205,10 @@ case OP_Move: {
memAboutToChange(p, pOut);
sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<pOut ){
pOut->pScopyFrom += pOp->p2 - p1;
if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
pOut->pScopyFrom += p1 - pOp->p2;
}
#endif
Deephemeralize(pOut);
REGISTER_TRACE(p2++, pOut);
pIn1++;
pOut++;
@@ -1604,7 +1604,7 @@ case OP_Function: {
/* If the function returned an error, throw an exception */
if( ctx.fErrorOrAux ){
if( ctx.isError ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(ctx.pOut));
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(ctx.pOut));
rc = ctx.isError;
}
sqlite3VdbeDeleteAuxData(p, (int)(pOp - aOp), pOp->p1);
@@ -1780,9 +1780,9 @@ case OP_RealAffinity: { /* in1 */
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_Cast: { /* in1 */
assert( pOp->p2>=SQLITE_AFF_BLOB && pOp->p2<=SQLITE_AFF_REAL );
assert( pOp->p2>=SQLITE_AFF_NONE && pOp->p2<=SQLITE_AFF_REAL );
testcase( pOp->p2==SQLITE_AFF_TEXT );
testcase( pOp->p2==SQLITE_AFF_BLOB );
testcase( pOp->p2==SQLITE_AFF_NONE );
testcase( pOp->p2==SQLITE_AFF_NUMERIC );
testcase( pOp->p2==SQLITE_AFF_INTEGER );
testcase( pOp->p2==SQLITE_AFF_REAL );
@@ -2477,7 +2477,7 @@ case OP_Column: {
}
}
/* If after trying to extract new entries from the header, nHdrParsed is
/* If after trying to extra new entries from the header, nHdrParsed is
** still not up to p2, that means that the record has fewer than p2
** columns. So the result will be either the default value or a NULL.
*/
@@ -2593,7 +2593,7 @@ case OP_Affinity: {
** The mapping from character to affinity is given by the SQLITE_AFF_
** macros defined in sqliteInt.h.
**
** If P4 is NULL then all index fields have the affinity BLOB.
** If P4 is NULL then all index fields have the affinity NONE.
*/
case OP_MakeRecord: {
u8 *zNewRecord; /* A buffer to hold the data for the new record */
@@ -2791,7 +2791,8 @@ case OP_Savepoint: {
/* A new savepoint cannot be created if there are active write
** statements (i.e. open read/write incremental blob handles).
*/
sqlite3VdbeError(p, "cannot open savepoint - SQL statements in progress");
sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - "
"SQL statements in progress");
rc = SQLITE_BUSY;
}else{
nName = sqlite3Strlen30(zName);
@@ -2842,14 +2843,15 @@ case OP_Savepoint: {
iSavepoint++;
}
if( !pSavepoint ){
sqlite3VdbeError(p, "no such savepoint: %s", zName);
sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName);
rc = SQLITE_ERROR;
}else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){
/* It is not possible to release (commit) a savepoint if there are
** active write statements.
*/
sqlite3VdbeError(p, "cannot release savepoint - "
"SQL statements in progress");
sqlite3SetString(&p->zErrMsg, db,
"cannot release savepoint - SQL statements in progress"
);
rc = SQLITE_BUSY;
}else{
@@ -2955,12 +2957,23 @@ case OP_AutoCommit: {
assert( db->nVdbeActive>0 ); /* At least this one VM is active */
assert( p->bIsReader );
#if 0
if( turnOnAC && iRollback && db->nVdbeActive>1 ){
/* If this instruction implements a ROLLBACK and other VMs are
** still running, and a transaction is active, return an error indicating
** that the other VMs must complete first.
*/
sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
"SQL statements in progress");
rc = SQLITE_BUSY;
}else
#endif
if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){
/* If this instruction implements a COMMIT and other VMs are writing
** return an error indicating that the other VMs must complete first.
*/
sqlite3VdbeError(p, "cannot commit transaction - "
"SQL statements in progress");
sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
"SQL statements in progress");
rc = SQLITE_BUSY;
}else if( desiredAutoCommit!=db->autoCommit ){
if( iRollback ){
@@ -2987,7 +3000,7 @@ case OP_AutoCommit: {
}
goto vdbe_return;
}else{
sqlite3VdbeError(p,
sqlite3SetString(&p->zErrMsg, db,
(!desiredAutoCommit)?"cannot start a transaction within a transaction":(
(iRollback)?"cannot rollback - no transaction is active":
"cannot commit - no transaction is active"));
@@ -5420,7 +5433,7 @@ case OP_Program: { /* jump */
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
rc = SQLITE_ERROR;
sqlite3VdbeError(p, "too many levels of trigger recursion");
sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
break;
}
@@ -5723,7 +5736,7 @@ case OP_AggStep: {
ctx.skipFlag = 0;
(ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */
if( ctx.isError ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(&t));
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&t));
rc = ctx.isError;
}
if( ctx.skipFlag ){
@@ -5755,7 +5768,7 @@ case OP_AggFinal: {
assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
if( rc ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(pMem));
}
sqlite3VdbeChangeEncoding(pMem, encoding);
UPDATE_MAX_BLOBSIZE(pMem);
@@ -5860,7 +5873,7 @@ case OP_JournalMode: { /* out2 */
){
if( !db->autoCommit || db->nVdbeRead>1 ){
rc = SQLITE_ERROR;
sqlite3VdbeError(p,
sqlite3SetString(&p->zErrMsg, db,
"cannot change %s wal mode from within a transaction",
(eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
);
@@ -5899,6 +5912,7 @@ case OP_JournalMode: { /* out2 */
}
eNew = sqlite3PagerSetJournalMode(pPager, eNew);
pOut = &aMem[pOp->p2];
pOut->flags = MEM_Str|MEM_Static|MEM_Term;
pOut->z = (char *)sqlite3JournalModename(eNew);
pOut->n = sqlite3Strlen30(pOut->z);
@@ -5991,7 +6005,7 @@ case OP_TableLock: {
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
if( (rc&0xFF)==SQLITE_LOCKED ){
const char *z = pOp->p4.z;
sqlite3VdbeError(p, "database table is locked: %s", z);
sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
}
}
break;
@@ -6093,9 +6107,8 @@ case OP_VOpen: {
pCur->pVtabCursor = pVtabCursor;
pVtab->nRef++;
}else{
assert( db->mallocFailed );
db->mallocFailed = 1;
pModule->xClose(pVtabCursor);
goto no_mem;
}
}
break;
@@ -6516,7 +6529,7 @@ vdbe_error_halt:
assert( rc );
p->rc = rc;
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
sqlite3_db_log(db, rc, "statement aborts at %d: [%s] %s",
(int)(pOp - aOp), p->zSql, p->zErrMsg);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
@@ -6539,7 +6552,7 @@ vdbe_return:
** is encountered.
*/
too_big:
sqlite3VdbeError(p, "string or blob too big");
sqlite3SetString(&p->zErrMsg, db, "string or blob too big");
rc = SQLITE_TOOBIG;
goto vdbe_error_halt;
@@ -6547,7 +6560,7 @@ too_big:
*/
no_mem:
db->mallocFailed = 1;
sqlite3VdbeError(p, "out of memory");
sqlite3SetString(&p->zErrMsg, db, "out of memory");
rc = SQLITE_NOMEM;
goto vdbe_error_halt;
@@ -6558,7 +6571,7 @@ abort_due_to_error:
assert( p->zErrMsg==0 );
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc!=SQLITE_IOERR_NOMEM ){
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc));
}
goto vdbe_error_halt;
@@ -6569,6 +6582,6 @@ abort_due_to_interrupt:
assert( db->u1.isInterrupted );
rc = SQLITE_INTERRUPT;
p->rc = rc;
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc));
goto vdbe_error_halt;
}
-7
View File
@@ -186,12 +186,6 @@ struct Mem {
#endif
};
/*
** Size of struct Mem not including the Mem.zMalloc member or anything that
** follows.
*/
#define MEMCELLSIZE offsetof(Mem,zMalloc)
/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
@@ -397,7 +391,6 @@ struct Vdbe {
/*
** Function prototypes
*/
void sqlite3VdbeError(Vdbe*, const char *, ...);
void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
int sqlite3VdbeCursorMoveto(VdbeCursor*);
+2 -32
View File
@@ -212,36 +212,6 @@ int sqlite3_value_type(sqlite3_value* pVal){
return aType[pVal->flags&MEM_AffMask];
}
/* Make a copy of an sqlite3_value object
*/
sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
sqlite3_value *pNew;
if( pOrig==0 ) return 0;
pNew = sqlite3_malloc( sizeof(*pNew) );
if( pNew==0 ) return 0;
memset(pNew, 0, sizeof(*pNew));
memcpy(pNew, pOrig, MEMCELLSIZE);
pNew->flags &= ~MEM_Dyn;
pNew->db = 0;
if( pNew->flags&(MEM_Str|MEM_Blob) ){
pNew->flags &= ~(MEM_Static|MEM_Dyn);
pNew->flags |= MEM_Ephem;
if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){
sqlite3ValueFree(pNew);
pNew = 0;
}
}
return pNew;
}
/* Destroy an sqlite3_value object previously obtained from
** sqlite3_value_dup().
*/
void sqlite3_value_free(sqlite3_value *pOld){
sqlite3ValueFree(pOld);
}
/**************************** sqlite3_result_ *******************************
** The following routines are used by user-defined functions to specify
** the function result.
@@ -1175,9 +1145,9 @@ static int vdbeUnbind(Vdbe *p, int i){
sqlite3_mutex_enter(p->db->mutex);
if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE);
sqlite3_mutex_leave(p->db->mutex);
sqlite3_log(SQLITE_MISUSE,
sqlite3_db_log(p->db, SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
sqlite3_mutex_leave(p->db->mutex);
return SQLITE_MISUSE_BKPT;
}
if( i<1 || i>p->nVar ){
+6 -21
View File
@@ -38,17 +38,6 @@ Vdbe *sqlite3VdbeCreate(Parse *pParse){
return p;
}
/*
** Change the error string stored in Vdbe.zErrMsg
*/
void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
va_list ap;
sqlite3DbFree(p->db, p->zErrMsg);
va_start(ap, zFormat);
p->zErrMsg = sqlite3VMPrintf(p->db, zFormat, ap);
va_end(ap);
}
/*
** Remember the SQL string for a prepared statement.
*/
@@ -1405,7 +1394,7 @@ int sqlite3VdbeList(
}else if( db->u1.isInterrupted ){
p->rc = SQLITE_INTERRUPT;
rc = SQLITE_ERROR;
sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc));
}else{
char *zP4;
Op *pOp;
@@ -2064,11 +2053,11 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
u32 iRandom;
if( retryCount ){
if( retryCount>100 ){
sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
sqlite3_db_log(db, SQLITE_FULL, "MJ delete: %s", zMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
break;
}else if( retryCount==1 ){
sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster);
sqlite3_db_log(db, SQLITE_FULL, "MJ collide: %s", zMaster);
}
}
retryCount++;
@@ -2308,7 +2297,7 @@ int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
){
p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
sqlite3SetString(&p->zErrMsg, db, "FOREIGN KEY constraint failed");
return SQLITE_ERROR;
}
return SQLITE_OK;
@@ -3651,7 +3640,7 @@ int sqlite3VdbeRecordCompareWithSkip(
if( pRhs->flags & MEM_Int ){
serial_type = aKey1[idx1];
testcase( serial_type==12 );
if( serial_type>=10 ){
if( serial_type>=12 ){
rc = +1;
}else if( serial_type==0 ){
rc = -1;
@@ -3677,11 +3666,7 @@ int sqlite3VdbeRecordCompareWithSkip(
/* RHS is real */
else if( pRhs->flags & MEM_Real ){
serial_type = aKey1[idx1];
if( serial_type>=10 ){
/* Serial types 12 or greater are strings and blobs (greater than
** numbers). Types 10 and 11 are currently "reserved for future
** use", so it doesn't really matter what the results of comparing
** them to numberic values are. */
if( serial_type>=12 ){
rc = +1;
}else if( serial_type==0 ){
rc = -1;
+9 -9
View File
@@ -200,11 +200,10 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
pMem->z[pMem->n] = 0;
pMem->z[pMem->n+1] = 0;
pMem->flags |= MEM_Term;
}
pMem->flags &= ~MEM_Ephem;
#ifdef SQLITE_DEBUG
pMem->pScopyFrom = 0;
pMem->pScopyFrom = 0;
#endif
}
return SQLITE_OK;
}
@@ -588,7 +587,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
if( pMem->flags & MEM_Null ) return;
switch( aff ){
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
case SQLITE_AFF_NONE: { /* Really a cast to BLOB */
if( (pMem->flags & MEM_Blob)==0 ){
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
@@ -770,6 +769,10 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
}
#endif /* SQLITE_DEBUG */
/*
** Size of struct Mem not including the Mem.zMalloc member.
*/
#define MEMCELLSIZE offsetof(Mem,zMalloc)
/*
** Make an shallow copy of pFrom into pTo. Prior contents of
@@ -796,10 +799,7 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
int rc = SQLITE_OK;
/* The pFrom==0 case in the following assert() is when an sqlite3_value
** from sqlite3_value_dup() is used as the argument
** to sqlite3_result_value(). */
assert( pTo->db==pFrom->db || pFrom->db==0 );
assert( pTo->db==pFrom->db );
assert( (pFrom->flags & MEM_RowSet)==0 );
if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
@@ -1311,7 +1311,7 @@ static int valueFromExpr(
if( zVal==0 ) goto no_mem;
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
}
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
}else{
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
+71 -95
View File
@@ -2063,12 +2063,11 @@ static void vdbeMergeEngineCompare(
#define INCRINIT_TASK 1
#define INCRINIT_ROOT 2
/*
** Forward reference required as the vdbeIncrMergeInit() and
** vdbePmaReaderIncrInit() routines are called mutually recursively when
** building a merge tree.
/* Forward reference.
** The vdbeIncrMergeInit() and vdbePmaReaderIncrMergeInit() routines call each
** other (when building a merge tree).
*/
static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode);
static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode);
/*
** Initialize the MergeEngine object passed as the second argument. Once this
@@ -2115,7 +2114,7 @@ static int vdbeMergeEngineInit(
** better advantage of multi-processor hardware. */
rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]);
}else{
rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL);
rc = vdbePmaReaderIncrMergeInit(&pMerger->aReadr[i], INCRINIT_NORMAL);
}
if( rc!=SQLITE_OK ) return rc;
}
@@ -2127,15 +2126,17 @@ static int vdbeMergeEngineInit(
}
/*
** The PmaReader passed as the first argument is guaranteed to be an
** incremental-reader (pReadr->pIncr!=0). This function serves to open
** and/or initialize the temp file related fields of the IncrMerge
** Initialize the IncrMerge field of a PmaReader.
**
** If the PmaReader passed as the first argument is not an incremental-reader
** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it serves
** to open and/or initialize the temp file related fields of the IncrMerge
** object at (pReadr->pIncr).
**
** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders
** in the sub-tree headed by pReadr are also initialized. Data is then
** loaded into the buffers belonging to pReadr and it is set to point to
** the first key in its range.
** in the sub-tree headed by pReadr are also initialized. Data is then loaded
** into the buffers belonging to pReadr and it is set to
** point to the first key in its range.
**
** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed
** to be a multi-threaded PmaReader and this function is being called in a
@@ -2162,62 +2163,59 @@ static int vdbeMergeEngineInit(
static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){
int rc = SQLITE_OK;
IncrMerger *pIncr = pReadr->pIncr;
SortSubtask *pTask = pIncr->pTask;
sqlite3 *db = pTask->pSorter->db;
/* eMode is always INCRINIT_NORMAL in single-threaded mode */
assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL );
rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
if( pIncr ){
SortSubtask *pTask = pIncr->pTask;
sqlite3 *db = pTask->pSorter->db;
/* Set up the required files for pIncr. A multi-theaded IncrMerge object
** requires two temp files to itself, whereas a single-threaded object
** only requires a region of pTask->file2. */
if( rc==SQLITE_OK ){
int mxSz = pIncr->mxSz;
rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
/* Set up the required files for pIncr. A multi-theaded IncrMerge object
** requires two temp files to itself, whereas a single-threaded object
** only requires a region of pTask->file2. */
if( rc==SQLITE_OK ){
int mxSz = pIncr->mxSz;
#if SQLITE_MAX_WORKER_THREADS>0
if( pIncr->bUseThread ){
rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd);
if( rc==SQLITE_OK ){
rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd);
}
}else
if( pIncr->bUseThread ){
rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd);
if( rc==SQLITE_OK ){
rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd);
}
}else
#endif
/*if( !pIncr->bUseThread )*/{
if( pTask->file2.pFd==0 ){
assert( pTask->file2.iEof>0 );
rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd);
pTask->file2.iEof = 0;
}
if( rc==SQLITE_OK ){
pIncr->aFile[1].pFd = pTask->file2.pFd;
pIncr->iStartOff = pTask->file2.iEof;
pTask->file2.iEof += mxSz;
/*if( !pIncr->bUseThread )*/{
if( pTask->file2.pFd==0 ){
assert( pTask->file2.iEof>0 );
rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd);
pTask->file2.iEof = 0;
}
if( rc==SQLITE_OK ){
pIncr->aFile[1].pFd = pTask->file2.pFd;
pIncr->iStartOff = pTask->file2.iEof;
pTask->file2.iEof += mxSz;
}
}
}
}
#if SQLITE_MAX_WORKER_THREADS>0
if( rc==SQLITE_OK && pIncr->bUseThread ){
/* Use the current thread to populate aFile[1], even though this
** PmaReader is multi-threaded. If this is an INCRINIT_TASK object,
** then this function is already running in background thread
** pIncr->pTask->thread.
**
** If this is the INCRINIT_ROOT object, then it is running in the
** main VDBE thread. But that is Ok, as that thread cannot return
** control to the VDBE or proceed with anything useful until the
** first results are ready from this merger object anyway.
*/
assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK );
rc = vdbeIncrPopulate(pIncr);
}
if( rc==SQLITE_OK && pIncr->bUseThread ){
/* Use the current thread to populate aFile[1], even though this
** PmaReader is multi-threaded. The reason being that this function
** is already running in background thread pIncr->pTask->thread. */
assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK );
rc = vdbeIncrPopulate(pIncr);
}
#endif
if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){
rc = vdbePmaReaderNext(pReadr);
if( rc==SQLITE_OK
&& (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK)
){
rc = vdbePmaReaderNext(pReadr);
}
}
return rc;
}
@@ -2226,7 +2224,7 @@ static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){
** The main routine for vdbePmaReaderIncrMergeInit() operations run in
** background threads.
*/
static void *vdbePmaReaderBgIncrInit(void *pCtx){
static void *vdbePmaReaderBgInit(void *pCtx){
PmaReader *pReader = (PmaReader*)pCtx;
void *pRet = SQLITE_INT_TO_PTR(
vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK)
@@ -2234,36 +2232,20 @@ static void *vdbePmaReaderBgIncrInit(void *pCtx){
pReader->pIncr->pTask->bDone = 1;
return pRet;
}
#endif
/*
** If the PmaReader passed as the first argument is not an incremental-reader
** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes
** the vdbePmaReaderIncrMergeInit() function with the parameters passed to
** this routine to initialize the incremental merge.
**
** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1),
** then a background thread is launched to call vdbePmaReaderIncrMergeInit().
** Or, if the IncrMerger is single threaded, the same function is called
** using the current thread.
** Use a background thread to invoke vdbePmaReaderIncrMergeInit(INCRINIT_TASK)
** on the PmaReader object passed as the first argument.
**
** This call will initialize the various fields of the pReadr->pIncr
** structure and, if it is a multi-threaded IncrMerger, launch a
** background thread to populate aFile[1].
*/
static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){
IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */
int rc = SQLITE_OK; /* Return code */
if( pIncr ){
#if SQLITE_MAX_WORKER_THREADS>0
assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK );
if( pIncr->bUseThread ){
void *pCtx = (void*)pReadr;
rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx);
}else
#endif
{
rc = vdbePmaReaderIncrMergeInit(pReadr, eMode);
}
}
return rc;
static int vdbePmaReaderBgIncrInit(PmaReader *pReadr){
void *pCtx = (void*)pReadr;
return vdbeSorterCreateThread(pReadr->pIncr->pTask, vdbePmaReaderBgInit, pCtx);
}
#endif
/*
** Allocate a new MergeEngine object to merge the contents of nPMA level-0
@@ -2508,21 +2490,15 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){
}
}
for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
/* Check that:
**
** a) The incremental merge object is configured to use the
** right task, and
** b) If it is using task (nTask-1), it is configured to run
** in single-threaded mode. This is important, as the
** root merge (INCRINIT_ROOT) will be using the same task
** object.
*/
PmaReader *p = &pMain->aReadr[iTask];
assert( p->pIncr==0 || (
(p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */
&& (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */
));
rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK);
assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] );
if( p->pIncr ){
if( iTask==pSorter->nTask-1 ){
rc = vdbePmaReaderIncrMergeInit(p, INCRINIT_TASK);
}else{
rc = vdbePmaReaderBgIncrInit(p);
}
}
}
}
pMain = 0;
+2 -1
View File
@@ -84,8 +84,9 @@ char *sqlite3VdbeExpandSql(
char zBase[100]; /* Initial working space */
db = p->db;
sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase),
sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
out.db = db;
if( db->nVdbeExec>1 ){
while( *zRawSql ){
const char *zStart = zRawSql;
+1 -1
View File
@@ -1082,7 +1082,7 @@ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
if( pTab==pToplevel->apVtabLock[i] ) return;
}
n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n);
if( apVtabLock ){
pToplevel->apVtabLock = apVtabLock;
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
+4 -4
View File
@@ -522,7 +522,7 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
if( pWal->nWiData<=iPage ){
int nByte = sizeof(u32*)*(iPage+1);
volatile u32 **apNew;
apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
if( !apNew ){
*ppPage = 0;
return SQLITE_NOMEM;
@@ -1147,7 +1147,7 @@ static int walIndexRecover(Wal *pWal){
/* Malloc a buffer to read frames into. */
szFrame = szPage + WAL_FRAME_HDRSIZE;
aFrame = (u8 *)sqlite3_malloc64(szFrame);
aFrame = (u8 *)sqlite3_malloc(szFrame);
if( !aFrame ){
rc = SQLITE_NOMEM;
goto recovery_error;
@@ -1540,7 +1540,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
nByte = sizeof(WalIterator)
+ (nSegment-1)*sizeof(struct WalSegment)
+ iLast*sizeof(ht_slot);
p = (WalIterator *)sqlite3_malloc64(nByte);
p = (WalIterator *)sqlite3_malloc(nByte);
if( !p ){
return SQLITE_NOMEM;
}
@@ -1550,7 +1550,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
/* Allocate temporary space used by the merge-sort routine. This block
** of memory will be freed before this function returns.
*/
aTmp = (ht_slot *)sqlite3_malloc64(
aTmp = (ht_slot *)sqlite3_malloc(
sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
);
if( !aTmp ){
+2758 -192
View File
File diff suppressed because it is too large Load Diff
+15 -74
View File
@@ -19,7 +19,7 @@
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/***/ int sqlite3WhereTrace;
/***/ int sqlite3WhereTrace = 0;
#endif
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
@@ -161,6 +161,10 @@ struct WhereOrSet {
WhereOrCost a[N_OR_COST]; /* Set of best costs */
};
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
/*
** Each instance of this object holds a sequence of WhereLoop objects
** that implement some or all of a query plan.
@@ -276,7 +280,6 @@ struct WhereTerm {
#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x400 /* The original LIKE operator */
#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
/*
** An instance of the WhereScan object is used as an iterator for locating
@@ -368,11 +371,6 @@ struct WhereMaskSet {
int ix[BMS]; /* Cursor assigned to each bit */
};
/*
** Initialize a WhereMaskSet object
*/
#define initMaskSet(P) (P)->n=0
/*
** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query.
@@ -424,84 +422,27 @@ struct WhereInfo {
WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
/*
** Private interfaces - callable only by other where.c routines.
**
** where.c:
*/
Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
WhereTerm *sqlite3WhereFindTerm(
WhereClause *pWC, /* The WHERE clause to be searched */
int iCur, /* Cursor number of LHS */
int iColumn, /* Column number of LHS */
Bitmask notReady, /* RHS must not overlap with this mask */
u32 op, /* Mask of WO_xx values describing operator */
Index *pIdx /* Must be compatible with this index, if not NULL */
);
/* wherecode.c: */
#ifndef SQLITE_OMIT_EXPLAIN
int sqlite3WhereExplainOneScan(
Parse *pParse, /* Parse context */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
int iLevel, /* Value for "level" column of output */
int iFrom, /* Value for "from" column of output */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
);
#else
# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
void sqlite3WhereAddScanStatus(
Vdbe *v, /* Vdbe to add scanstatus entry to */
SrcList *pSrclist, /* FROM clause pLvl reads data from */
WhereLevel *pLvl, /* Level to add scanstatus() entry for */
int addrExplain /* Address of OP_Explain (or 0) */
);
#else
# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d)
#endif
Bitmask sqlite3WhereCodeOneLoopStart(
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
Bitmask notReady /* Which tables are currently available */
);
/* whereexpr.c: */
void sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
void sqlite3WhereClauseClear(WhereClause*);
void sqlite3WhereSplit(WhereClause*,Expr*,u8);
Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
/*
** Bitmasks for the operators on WhereTerm objects. These are all
** operators that are of interest to the query planner. An
** OR-ed combination of these values can be used when searching for
** particular WhereTerms within a WhereClause.
*/
#define WO_IN 0x0001
#define WO_EQ 0x0002
#define WO_IN 0x001
#define WO_EQ 0x002
#define WO_LT (WO_EQ<<(TK_LT-TK_EQ))
#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
#define WO_MATCH 0x0040
#define WO_IS 0x0080
#define WO_ISNULL 0x0100
#define WO_OR 0x0200 /* Two or more OR-connected terms */
#define WO_AND 0x0400 /* Two or more AND-connected terms */
#define WO_EQUIV 0x0800 /* Of the form A==B, both columns */
#define WO_NOOP 0x1000 /* This term does not restrict search space */
#define WO_MATCH 0x040
#define WO_ISNULL 0x080
#define WO_OR 0x100 /* Two or more OR-connected terms */
#define WO_AND 0x200 /* Two or more AND-connected terms */
#define WO_EQUIV 0x400 /* Of the form A==B, both columns */
#define WO_NOOP 0x800 /* This term does not restrict search space */
#define WO_ALL 0x1fff /* Mask of all possible WO_* values */
#define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */
#define WO_ALL 0xfff /* Mask of all possible WO_* values */
#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
/*
** These are definitions of bits in the WhereLoop.wsFlags field.
-1501
View File
File diff suppressed because it is too large Load Diff
-1249
View File
File diff suppressed because it is too large Load Diff
-61
View File
@@ -1,61 +0,0 @@
# 2015-06-02
#
# 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 type affinity in comparison operations.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test affinity2-100 {
CREATE TABLE t1(
xi INTEGER,
xr REAL,
xb BLOB,
xn NUMERIC,
xt TEXT
);
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(1,1,1,1,1,1);
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(2,'2','2','2','2','2');
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(3,'03','03','03','03','03');
} {}
do_execsql_test affinity2-110 {
SELECT xi, typeof(xi) FROM t1 ORDER BY rowid;
} {1 integer 2 integer 3 integer}
do_execsql_test affinity2-120 {
SELECT xr, typeof(xr) FROM t1 ORDER BY rowid;
} {1.0 real 2.0 real 3.0 real}
do_execsql_test affinity2-130 {
SELECT xb, typeof(xb) FROM t1 ORDER BY rowid;
} {1 integer 2 text 03 text}
do_execsql_test affinity2-140 {
SELECT xn, typeof(xn) FROM t1 ORDER BY rowid;
} {1 integer 2 integer 3 integer}
do_execsql_test affinity2-150 {
SELECT xt, typeof(xt) FROM t1 ORDER BY rowid;
} {1 text 2 text 03 text}
do_execsql_test affinity2-200 {
SELECT rowid, xi==xt, xi==xb, xi==+xt FROM t1 ORDER BY rowid;
} {1 1 1 1 2 1 1 1 3 1 1 1}
do_execsql_test affinity2-210 {
SELECT rowid, xr==xt, xr==xb, xr==+xt FROM t1 ORDER BY rowid;
} {1 1 1 1 2 1 1 1 3 1 1 1}
do_execsql_test affinity2-220 {
SELECT rowid, xn==xt, xn==xb, xn==+xt FROM t1 ORDER BY rowid;
} {1 1 1 1 2 1 1 1 3 1 1 1}
do_execsql_test affinity2-300 {
SELECT rowid, xt==+xi, xt==xi, xt==xb FROM t1 ORDER BY rowid;
} {1 1 1 0 2 1 1 1 3 0 1 1}
finish_test
-9
View File
@@ -912,14 +912,5 @@ do_execsql_test alter-17.9 {
do_execsql_test alter-17.10 {
SELECT sqlite_rename_parent(NULL,'abc','xyz');
} {{}}
do_execsql_test alter-17.11 {
SELECT sqlite_rename_parent('create references ''','abc','xyz');
} {{create references '}}
do_execsql_test alter-17.12 {
SELECT sqlite_rename_parent('create references "abc"123" ','abc','xyz');
} {{create references "xyz"123" }}
do_execsql_test alter-17.13 {
SELECT sqlite_rename_parent("references '''",'abc','xyz');
} {{references '''}}
finish_test
-52
View File
@@ -1,52 +0,0 @@
# 2015-05-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.
#
#***********************************************************************
#
# Quick tests for the sqlite3_analyzer tool
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !vtab {
finish_test
return
}
if {$tcl_platform(platform)=="windows"} {
set PROG "sqlite3_analyzer.exe"
} else {
set PROG "./sqlite3_analyzer"
}
if {![file exe $PROG]} {
puts "analyzer1 cannot run because $PROG is not available"
finish_test
return
}
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
do_test analyzer1-1.0 {
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INT PRIMARY KEY, b) WITHOUT ROWID;
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<250)
INSERT INTO t1(a,b) SELECT x, randomblob(200) FROM c;
INSERT INTO t2(a,b) SELECT a, b FROM t1;
}
set line "exec $PROG test.db"
unset -nocomplain ::MSG
catch {eval $line} ::MSG
} {0}
do_test analyzer1-1.1 {
regexp {^/\*\* Disk-Space Utilization.*COMMIT;\W*$} $::MSG
} {1}
finish_test
-108
View File
@@ -1,108 +0,0 @@
# 2014-10-24
#
# 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 automatic index creation logic,
# and specifically ensuring that automatic indexes can be used with
# co-routine subqueries.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Schema is from the Debian security database
#
do_execsql_test autoindex5-1.0 {
CREATE TABLE source_package_status
(bug_name TEXT NOT NULL,
package INTEGER NOT NULL,
vulnerable INTEGER NOT NULL,
urgency TEXT NOT NULL,
PRIMARY KEY (bug_name, package));
CREATE INDEX source_package_status_package
ON source_package_status(package);
CREATE TABLE source_packages
(name TEXT NOT NULL,
release TEXT NOT NULL,
subrelease TEXT NOT NULL,
archive TEXT NOT NULL,
version TEXT NOT NULL,
version_id INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (name, release, subrelease, archive));
CREATE TABLE bugs
(name TEXT NOT NULL PRIMARY KEY,
cve_status TEXT NOT NULL
CHECK (cve_status IN
('', 'CANDIDATE', 'ASSIGNED', 'RESERVED', 'REJECTED')),
not_for_us INTEGER NOT NULL CHECK (not_for_us IN (0, 1)),
description TEXT NOT NULL,
release_date TEXT NOT NULL,
source_file TEXT NOT NULL,
source_line INTEGER NOT NULL);
CREATE TABLE package_notes
(id INTEGER NOT NULL PRIMARY KEY,
bug_name TEXT NOT NULL,
package TEXT NOT NULL,
fixed_version TEXT
CHECK (fixed_version IS NULL OR fixed_version <> ''),
fixed_version_id INTEGER NOT NULL DEFAULT 0,
release TEXT NOT NULL,
package_kind TEXT NOT NULL DEFAULT 'unknown',
urgency TEXT NOT NULL,
bug_origin TEXT NOT NULL DEFAULT '');
CREATE INDEX package_notes_package
ON package_notes(package);
CREATE UNIQUE INDEX package_notes_bug
ON package_notes(bug_name, package, release);
CREATE TABLE debian_bugs
(bug INTEGER NOT NULL,
note INTEGER NOT NULL,
PRIMARY KEY (bug, note));
CREATE VIEW debian_cve AS
SELECT DISTINCT debian_bugs.bug, st.bug_name
FROM package_notes, debian_bugs, source_package_status AS st
WHERE package_notes.bug_name = st.bug_name
AND debian_bugs.note = package_notes.id
ORDER BY debian_bugs.bug;
} {}
# The following query should use an automatic index for the view
# in FROM clause of the subquery of the second result column.
#
do_execsql_test autoindex5-1.1 {
EXPLAIN QUERY PLAN
SELECT
st.bug_name,
(SELECT ALL debian_cve.bug FROM debian_cve
WHERE debian_cve.bug_name = st.bug_name
ORDER BY debian_cve.bug),
sp.release
FROM
source_package_status AS st,
source_packages AS sp,
bugs
WHERE
sp.rowid = st.package
AND st.bug_name = bugs.name
AND ( st.bug_name LIKE 'CVE-%' OR st.bug_name LIKE 'TEMP-%' )
AND ( sp.release = 'sid' OR sp.release = 'stretch' OR sp.release = 'jessie'
OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
} {/SEARCH SUBQUERY 2 USING AUTOMATIC COVERING INDEX .bug_name=/}
finish_test
-155
View File
@@ -105,159 +105,4 @@ if {[db one {SELECT sqlite_compileoption_used('ENABLE_OVERSIZE_CELL_CHECK')}]} {
INSERT INTO t1 VALUES(9, 'klmnopqrst');
} {1 {database disk image is malformed}}
} ;# end-if !defined(ENABLE_OVERSIZE_CELL_CHECK)
#-------------------------------------------------------------------------
# Test that an assert() failure discovered by AFL corrupt database file
# testing has been fixed.
#
reset_db
do_execsql_test 4.0 {
PRAGMA page_size = 65536;
PRAGMA autovacuum = 0;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(-1, 'abcdefghij');
INSERT INTO t1 VALUES(0, 'abcdefghij');
}
set root [db one {SELECT rootpage FROM sqlite_master}]
set offset [expr ($root-1) * 65536]
ifcapable oversize_cell_check {
set res {1 {database disk image is malformed}}
} else {
set res {0 {}}
}
do_test 4.1 {
db close
hexio_write test.db [expr $offset + 8 + 2] 0000
hexio_write test.db [expr $offset + 5] 0000
sqlite3 db test.db
catchsql { DELETE FROM t1 WHERE a=0 }
} $res
#-------------------------------------------------------------------------
# Database properties:
#
# * Incremental vacuum mode.
# * Database root table has a single leaf page.
# * Free list consists of a single trunk page.
#
# The db is then corrupted by adding the root table leaf page as a free-list
# leaf page (so that it is referenced twice).
#
# Then, a new table is created. The new root page is the current free-list
# trunk. This means that the root table leaf page is made into the new
# free list trunk, which corrupts its header. Then, when the new entry is
# inserted into the root table, things would get chaotic.
#
reset_db
do_test 5.0 {
execsql {
PRAGMA page_size = 512;
PRAGMA auto_vacuum = 2;
}
for {set i 3} {1} {incr i} {
execsql "CREATE TABLE t${i}(x)"
if {[db one {PRAGMA page_count}]>$i} break
}
set nPage [db one {PRAGMA page_count}]
execsql {
CREATE TABLE t100(x);
DROP TABLE t100;
}
} {}
do_execsql_test 5.1 {
PRAGMA page_count
} [expr $nPage+1]
do_test 5.2 {
# The last page of the db is now the only leaf of the sqlite_master table.
# Corrupt the db by adding it to the free-list as well (the second last
# page of the db is the free-list trunk).
db close
hexio_write test.db [expr 512*($nPage-1)] [
format "%.8X%.8X%.8X" 0 1 [expr $nPage+1]
]
} {12}
do_test 5.3 {
sqlite3 db test.db
catchsql { CREATE TABLE tx(x); }
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
# Set the payload size of a cell to just less than 2^32 bytes (not
# possible in an uncorrupted db). Then try to delete the cell. At one
# point this led to an integer overflow that caused an assert() to fail.
#
reset_db
do_execsql_test 6.0 {
PRAGMA page_size = 512;
PRAGMA auto_vacuum=0;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(zeroblob(300));
INSERT INTO t1 VALUES(zeroblob(600));
} {}
do_test 6.1 {
db close
hexio_write test.db 616 EAFFFFFF0202
sqlite3 db test.db
breakpoint
execsql { DELETE FROM t1 WHERE rowid=2 }
} {}
#-------------------------------------------------------------------------
# See what happens if the sqlite_master entry associated with a PRIMARY
# KEY or UNIQUE index is removed.
#
reset_db
do_execsql_test 7.0 {
PRAGMA auto_vacuum=0;
CREATE TABLE t1(x PRIMARY KEY, y);
INSERT INTO t1 VALUES('a', 'A');
INSERT INTO t1 VALUES('b', 'A');
INSERT INTO t1 VALUES('c', 'A');
SELECT name FROM sqlite_master;
} {t1 sqlite_autoindex_t1_1}
do_execsql_test 7.1 {
PRAGMA writable_schema = 1;
DELETE FROM sqlite_master WHERE name = 'sqlite_autoindex_t1_1';
}
do_test 7.2 {
db close
sqlite3 db test.db
catchsql { UPDATE t1 SET x='d' AND y='D' WHERE rowid = 2 }
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
# At one point an assert() would fail if attempt was made to free page 1.
#
reset_db
do_execsql_test 8.0 {
PRAGMA auto_vacuum=0;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(zeroblob(300));
INSERT INTO t1 VALUES(zeroblob(300));
INSERT INTO t1 VALUES(zeroblob(300));
INSERT INTO t1 VALUES(zeroblob(300));
} {}
do_test 8.1 {
db close
hexio_write test.db [expr 1024 + 8] 00000001
sqlite3 db test.db
catchsql { DELETE FROM t1 }
} {1 {database disk image is malformed}}
do_test 8.2 {
db close
sqlite3 db test.db
execsql { PRAGMA integrity_check }
} {/.*in database main.*/}
finish_test
+1
View File
@@ -171,6 +171,7 @@ foreach {tn code} {
#
set ::busy_callback_count 0
proc busy_callback {args} {
puts Hello
incr ::busy_callback_count
return 0
}
+37
View File
@@ -0,0 +1,37 @@
# 2015-04-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.
#
#*************************************************************************
# Test cases for the sqlite3_log() and sqlite3_db_log() interfaces.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
unset -nocomplain log
set log {}
do_test errlog01-1.0 {
test_sqlite3_db_log db [list lappend ::log]
db eval {SELECT sqlite_log(7,'simulated error')}
} {{}}
do_test errlog01-1.1 {
set ::log
} {SQLITE_NOMEM {simulated error}}
do_test errlog01-1.2 {
sqlite3 db2 :memory:
set ::log {}
db2 eval {SELECT sqlite_log(7,'simulated error')}
} {{}}
do_test errlog01-1.3 {
set ::log
} {}
finish_test

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