Compare commits

..

1 Commits

Author SHA1 Message Date
drh 656ba691e5 An experimental virtual tables for showing the content of internal schema
objects.

FossilOrigin-Name: d1fbc6ca18383b97befd597aeb7ff84c6a04d243
2013-11-14 15:35:43 +00:00
107 changed files with 1987 additions and 4002 deletions
+1 -4
View File
@@ -534,7 +534,7 @@ mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
mkdir tsrc
cp -f $(SRC) tsrc
rm tsrc/sqlite.h.in tsrc/parse.y
$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new
mv vdbe.new tsrc/vdbe.c
touch .target_source
@@ -940,9 +940,6 @@ showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.c
wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.c
$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.c $(TLIBS)
speedtest1$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)
# Standard install and cleanup targets
#
lib_install: libsqlite3.la
+6 -10
View File
@@ -162,7 +162,7 @@ RC = rc.exe
!IFDEF NCC
NCC = $(NCC:\\=\)
!ELSEIF $(XCOMPILE)!=0
NCC = "$(VCINSTALLDIR)\bin\$(CC)"
NCC = "$(VCINSTALLDIR)\bin\cl.exe"
NCC = $(NCC:\\=\)
!ELSE
NCC = $(CC)
@@ -911,7 +911,7 @@ mptester.exe: $(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
-mkdir tsrc
for %i in ($(SRC)) do copy /Y %i tsrc
del /Q tsrc\sqlite.h.in tsrc\parse.y
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new
move vdbe.new tsrc\vdbe.c
echo > .target_source
@@ -1334,17 +1334,13 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
showdb.exe: $(TOP)\tool\showdb.c sqlite3.c
showdb.exe: $(TOP)/tool/showdb.c sqlite3.c
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
$(TOP)\tool\showdb.c sqlite3.c
$(TOP)/tool/showdb.c sqlite3.c
wordcount.exe: $(TOP)\test\wordcount.c sqlite3.c
wordcount.exe: $(TOP)/test/wordcount.c sqlite3.c
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
$(TOP)\test\wordcount.c sqlite3.c
speedtest1.exe: $(TOP)\test\speedtest1.c sqlite3.c
$(LTLINK) -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
$(TOP)\test\speedtest1.c sqlite3.c
$(TOP)/test/wordcount.c sqlite3.c
clean:
del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
+1 -1
View File
@@ -1 +1 @@
3.8.3
3.8.2
+1
View File
@@ -28,6 +28,7 @@ END {
printf "#define TK_%-29s %4d\n", "COLUMN", ++max
printf "#define TK_%-29s %4d\n", "AGG_FUNCTION", ++max
printf "#define TK_%-29s %4d\n", "AGG_COLUMN", ++max
printf "#define TK_%-29s %4d\n", "CONST_FUNC", ++max
printf "#define TK_%-29s %4d\n", "UMINUS", ++max
printf "#define TK_%-29s %4d\n", "UPLUS", ++max
}
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.62 for sqlite 3.8.3.
# Generated by GNU Autoconf 2.62 for sqlite 3.8.2.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
@@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.8.3'
PACKAGE_STRING='sqlite 3.8.3'
PACKAGE_VERSION='3.8.2'
PACKAGE_STRING='sqlite 3.8.2'
PACKAGE_BUGREPORT=''
# Factoring default headers for most tests.
@@ -1483,7 +1483,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.8.3 to adapt to many kinds of systems.
\`configure' configures sqlite 3.8.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1548,7 +1548,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.8.3:";;
short | recursive ) echo "Configuration of sqlite 3.8.2:";;
esac
cat <<\_ACEOF
@@ -1664,7 +1664,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.8.3
sqlite configure 3.8.2
generated by GNU Autoconf 2.62
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1678,7 +1678,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.8.3, which was
It was created by sqlite $as_me 3.8.2, which was
generated by GNU Autoconf 2.62. Invocation command line was
$ $0 $@
@@ -14021,7 +14021,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.8.3, which was
This file was extended by sqlite $as_me 3.8.2, which was
generated by GNU Autoconf 2.62. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14074,7 +14074,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
sqlite config.status 3.8.3
sqlite config.status 3.8.2
configured by $0, generated by GNU Autoconf 2.62,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+3 -6
View File
@@ -333,9 +333,6 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
v = (v & mask1) | ( (*ptr++) << shift ); \
if( (v & mask2)==0 ){ var = v; return ret; }
#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
v = (*ptr++); \
if( (v & mask2)==0 ){ var = v; return ret; }
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
@@ -348,7 +345,7 @@ int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
u64 b;
int shift;
GETVARINT_INIT(a, p, 0, 0x00, 0x80, *v, 1);
GETVARINT_STEP(a, p, 0, 0x00, 0x80, *v, 1);
GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *v, 2);
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *v, 3);
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4);
@@ -360,7 +357,7 @@ int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
if( (c & 0x80)==0 ) break;
}
*v = b;
return (int)(p - pStart);
return p - pStart;
}
/*
@@ -371,7 +368,7 @@ int sqlite3Fts3GetVarint32(const char *p, int *pi){
u32 a;
#ifndef fts3GetVarint32
GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
GETVARINT_STEP(a, p, 0, 0x00, 0x80, *pi, 1);
#else
a = (*p++);
assert( a & 0x80 );
+3 -6
View File
@@ -379,9 +379,9 @@ libsqlite3.a: $(LIBOBJ)
$(AR) libsqlite3.a $(LIBOBJ)
$(RANLIB) libsqlite3.a
sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h
sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(TOP)/src/test_schema2.c
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) \
$(TOP)/src/shell.c \
-I$(TOP)/src $(TOP)/src/shell.c \
libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
@@ -402,7 +402,7 @@ target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl
mkdir tsrc
cp -f $(SRC) tsrc
rm tsrc/sqlite.h.in tsrc/parse.y
tclsh $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
tclsh $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new
mv vdbe.new tsrc/vdbe.c
touch target_source
@@ -630,9 +630,6 @@ wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \
$(TOP)/test/wordcount.c sqlite3.c
speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o
$(TCC) -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
# releasetest.tcl script.
+105 -109
View File
@@ -1,14 +1,14 @@
C Fix\sthe\sformatting\sof\s%c\sin\sthe\sprintf()\sSQL\sfunction.
D 2013-12-17T15:58:42.950
C An\sexperimental\svirtual\stables\sfor\sshowing\sthe\scontent\sof\sinternal\sschema\nobjects.
D 2013-11-14T15:35:43.564
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 4d4ead6b71d1bf03028fbd61da0ba0ec5e1556e1
F Makefile.msc 19243469fcd1073319ea5b7db97609c1cfb3b1c0
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION 8ed548d87d0a27fd7d7620476f9e25f9fa742d73
F VERSION 52f7e22bfcec71a462e34194b4ae1671380fde59
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 87ca612393d0f439550634bd2c156ea9ff6195ae
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
@@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 1673bc402f8fc95015f72c279adc5a9a668ee237 x
F configure f97b17cd80fa428e5df4e70a36ed5b4ed21100c2 x
F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
@@ -78,7 +78,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 1e667eacb3fe4b4ad6f863920da4286f071f6e07
F ext/fts3/fts3.c dceaa5079833caa2e7945433e1eb93bb22f623a3
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h eb5f8029589f3d8f1dc7fd50c773326a640388b1
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
@@ -142,12 +142,12 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff
F main.mk 9f091ea7920f8b15e48c7b6e5b6fb0182577ab2e
F main.mk fc7620245363d451c167095df5fab8b13e6e61d6
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh d2a981497b404d6498f5ff3e3b1f3816bdfcb338
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkopcodeh.awk 987ee588ff3bb4043bed2185c1ee2bdc39b1e526
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -163,38 +163,38 @@ F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
F src/analyze.c 581d5c18ce89c6f45d4dca65914d0de5b4dad41f
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 11e29ef8cf16a42925fde036bcffbeffd9cc82df
F src/btree.h a61ddebc78c66795a2b93181321a116746302cc9
F src/btree.c 260dedc13119e6fb7930380bd3d294b98362bf5a
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
F src/build.c 47ef8209e56d840d2b35b8a243c6ee567ad52bda
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
F src/build.c 2baeed38bdaa9f1199f101c63db41fdcc4b39ba5
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c b36db1f79ee50eaca979660c9dd36437f5410b93
F src/expr.c 31a2b65339f6c3795d4cfa5e99798cd72f9fdfdf
F src/delete.c ddb92f44595366c4817e576b5f11cad5a915c3ef
F src/expr.c e7bbe3c6916e141f27a28655d3cf325b817695e4
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
F src/func.c 6325ac2ec10833ccf4d5c36d323709221d37ea19
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/fkey.c 78364daed38e26269c53ddb94c515bceac1063c6
F src/func.c 96caa9dfd1febf9a4b720de4c43ccfb392a52b73
F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 3cf8012325857d162f74389420b14be7976a538d
F src/insert.c 63003c569c55793c3278ad7634bdd0c49d755a47
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
F src/main.c 45e08d8ca4808625c4512a14898e9c61553e3d2a
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
F src/main.c 32bf1e6e164a6fa0ddf1bf2616c6eafbefd6e9b0
F src/malloc.c 543a8eb5508eaf4cadf55a9b503379eba2088128
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c 19d9271cb936742707b6118ed44d779657c7c511
F src/mem5.c 0025308a93838022bd5696cf9627ff4e40b19918
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
@@ -205,36 +205,36 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c b4ad71336fd96f97776f75587cd9e8218288f5be
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_unix.c 60a7b3b23e6fcf83a50d1e320b280b551724e11f
F src/os_win.c 16eac0961603182ffc10c02b39fe830126538e07
F src/pager.c efa923693e958696eee69b205a20bfbc402c8480
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y acee1a9958539e21263362b194594c5255ad2fca
F src/os_unix.c 143624d9eabb3b997c59cf594e0d06c56edd43e9
F src/os_win.c ef091b347d682cb24fc575ac9a6290341af62e2b
F src/pager.c 2aa4444ffe86e9282d03bc349a4a5e49bd77c0e8
F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c
F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b
F src/pragma.c 5ab7279d132143feb77f773688a24ab05da75fd7
F src/prepare.c 359d1a1e9c9bd4488e4dd3a1aaaf2d2ebb9bb768
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
F src/pragma.c c8d70c47ec8d8ba93575d92e34d30ddff8e9b517
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
F src/resolve.c fc4673cc49b116e51e7f12de074c0acf8f2388f9
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c d41381d80a22d3a83352aeca274cccf264ac277a
F src/shell.c 18924f6ccfa70da98bf9e388bab512c0fd1e792e
F src/sqlite.h.in 4ef56464aeaa3785a2c5ca37fb3a0fb229d68b2e
F src/select.c 7317406831ecced390edba972818f3c5f82238c0
F src/shell.c 044a79639c420ed293510cd560b358f75dae9472
F src/sqlite.h.in 4dedcab5b32358bf7a596badffe7363be1f1a82d
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h b7e9da87740488671cfe4c70038a8eef3a1d317e
F src/sqliteInt.h 2ec1d71220307fa5ee85a918a6240cf0b4635b0e
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 651b10698c87bbc3ae5772e2491e3444c5bbf153
F src/test1.c 633e5e6a116acf4473b9289240bcceb5320a9d93
F src/tclsqlite.c 3b5f3716e320480659239abe887164521c575d83
F src/test1.c 5757066e503a8ed51313cb3a5d9bcdcced2991a9
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
F src/test6.c 4f958b71334695e65746d357dac77709732b28db
F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2
F src/test8.c c7aab1d9fbbf54fc33d43b73aa24aa55f9eaf534
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
@@ -242,7 +242,7 @@ F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
F src/test_config.c 10d0e00dd6315879a6d9fac20bd063c7bbbfb8f8
F src/test_config.c e825cd6a4a8f498be246fc5934fe5fd702b9441f
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
@@ -253,7 +253,7 @@ F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61
F src/test_intarray.h 2ece66438cfd177b78d1bfda7a4180cd3a10844d
F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
F src/test_malloc.c 1ff5b1243d96124c9a180f3b89424820a1f337f3
F src/test_malloc.c eba4e1c5847cc98e7edc98f62265cd2abafba7a6
F src/test_multiplex.c 9f304bf04170c91c0318238d512df2da039eb1c8
F src/test_multiplex.h 110a8c4d356e0aa464ca8730375608a9a0b61ae1
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
@@ -264,6 +264,7 @@ F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0
F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
F src/test_rtree.c f3d1d12538dccb75fd916e3fa58f250edbdd3b47
F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6
F src/test_schema2.c c07c0826c77659ff37da580f8d8bc30e26849e3b
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e
F src/test_stat.c 9898687a6c2beca733b0dd6fe19163d987826d31
@@ -272,28 +273,28 @@ F src/test_syscall.c 16dbe79fb320fadb5acd7a0a59f49e52ab2d2091
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78
F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4
F src/trigger.c d84e1f3669e9a217731a14a9d472b1c7b87c87ba
F src/update.c d1c2477dcf14d90999d1935af4efb4806553250b
F src/trigger.c 53d6b5d50b3b23d4fcd0a36504feb5cff9aed716
F src/update.c 3de7e657b98ac67338d775c114a4068faf732402
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c e71f19b272f05c8695cf747b4bac1732685f9e5c
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c 919422843c859a1db08db0c88189912dbf625fc7
F src/vdbe.c f9a4e08114f97e453a5f13a62c31a357301137cc
F src/vdbe.h c06f0813f853566457ce9cfb1a4a4bc39a5da644
F src/vdbeInt.h a7bc268f844d75be48bb7ae16f77b418fd3c641c
F src/vdbeapi.c ce4e68ea4842cc6081046f533d088dcf01d247ad
F src/vdbeaux.c a22cbd91b24503b82690cb03324ffec9f4ef63f6
F src/vdbeblob.c 8cd05a5630e6d5563ad017bf82edaf812b28acde
F src/vdbemem.c 0e69351b2c6ff7d8b638688c0ae336a26befa6b2
F src/vdbeInt.h 62eb680327011f3a4b0336642b0ca9d6ecc6eb91
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
F src/vdbeaux.c dd0f6ab9dc159911facfc0a7a2164af44779bdda
F src/vdbeblob.c ff60adf2953e0ffc1d59541b3101c9886b03a3de
F src/vdbemem.c cc529bbf4f13e4e181bdb446bf6e6962ab030b4b
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
F src/where.c b8f3aab1e5843012895b89a183dcdd6cef0708db
F src/where.c 2eb88f96a73d77bd61d6afd50c33ec5d63c15dd5
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -313,7 +314,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
F test/analyze6.test d31defa011a561b938b4608d3538c1b4e0b5e92c
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
F test/analyze9.test 339e87723cd4dc158dc5e9095acd8df9e87faf79
F test/analyze9.test 1b9b7e9a096d1536f03d9ad7b72f638ef5669347
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
@@ -321,7 +322,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
F test/atof1.test 08a61df9365c341f334a65f4348897312d8f3db7
F test/atof1.test 9bf1d25180a2e05fc12ce3940cc8003033642f68
F test/attach.test 0d112b7713611fdf0340260192749737135fda5f
F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
F test/attach3.test d89ccfe4fe6e2b5e368d480fcdfe4b496c54cf4e
@@ -330,7 +331,7 @@ F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
F test/auth.test 9bea29041871807d9f289ee679d05d3ed103642f
F test/auth2.test c3b415b76c033bedb81292118fb7c01f5f10cbcd
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
F test/autoinc.test bd30d372d00045252f6c2e41b5f41455e1975acf
F test/autoindex1.test d4dfe14001dfcb74cfbd7107f45a79fc1ab6183e
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
@@ -364,7 +365,7 @@ F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
F test/capi3.test f5eab498a0927d498e6d75c14567addb995ceccb
F test/capi3.test 56ab450125ead38846cbae7e5b6a216686c3cffa
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test 93d24621c9ff84da9da060f30431e0453db1cdb0
F test/capi3d.test 6d0fc0a86d73f42dd19a7d8b7761ab9bc02277d0
@@ -387,25 +388,25 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/colmeta.test 087c42997754b8c648819832241daf724f813322
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
F test/conflict.test 841bcf7cabbfca39c577eb8411ea8601843b46a8
F test/conflict2.test 0d3af4fb534fa1bd020c79960bb56e4d52655f09
F test/conflict2.test 3ed0b6ec3c2cb8acebbc89677ea0e58c01aaa1ff
F test/conflict3.test dec0634c0f31dec9a4b01c63063e939f0cd21b6b
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97
F test/corrupt2.test f2064e0bf934124cc38868fd8badb8f0dd67b552
F test/corrupt3.test 4b548d0bbe2933bc81d3f54099a05fc4d28aff18
F test/corrupt4.test b99652079d542b21f4965f6248703b983e40fe80
F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107
F test/corrupt6.test 269548d19427ac554c830763b1c5ea54a0252f80
F test/corrupt7.test 22cc644c2e76c9804bc844121267aa6f8f7c0ded
F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test c150f156dace653c00a121ad0f5772a0568c41ba
F test/corrupt.test 4aabd06cff3fe759e3e658bcc17b71789710665e
F test/corrupt2.test 9c0ab4becd50e9050bc1ebb8675456a4e5587bf0
F test/corrupt3.test 889d7cdb811800303aa722d7813fe8a4299cf726
F test/corrupt4.test b963f9e01e0f92d15c76fb0747876fd4b96dc30a
F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff
F test/corrupt6.test 4e4161aef1f30b9f34582bb4142334b7f47eacae
F test/corrupt7.test a90caf89c7d7cb7893ea4d92529bd0c129317ee4
F test/corrupt8.test 48eb37ffb9a03bceada62219e2bd4c92f4b0cb75
F test/corrupt9.test 959179e68dc0b7b99f424cf3e0381c86dcdd0112
F test/corruptA.test fafa652aa585753be4f6b62ff0bb250266eaf7ce
F test/corruptB.test 20d4a20cbed23958888c3e8995b424a47223d647
F test/corruptC.test 62a767fe64acb1975f58cc6171192839c783edbb
F test/corruptD.test 3b09903a2e2fe07ecafe775fea94177f8a4bb34f
F test/corruptE.test d3a3d7e864a95978195741744dda4abfd8286018
F test/corruptF.test 1c7b6f77cf3f237fb7fbb5b61d6c921fd4c7b993
F test/corruptG.test c67fd860e9e3943bc90b856a3049c9a28827167e
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
@@ -423,7 +424,7 @@ F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test 42973251b9429f2c41b77eb98a7b0b0ba2d3b2c0
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
F test/default.test 792c3c70836f1901e2a8cb34fa0880ed71e2c1a9
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
@@ -433,11 +434,11 @@ F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test 44028aaf161a5e80a2f229622b3a174d3b352810
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_createtable.test ee95d48664503d40f6cc9ef4a7d03216188e2ada
F test/e_createtable.test 3b453432cd14a12732ee9467597d2274ca37ce36
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
F test/e_expr.test 5c71d183fbf519a4769fd2e2124afdc70b5b1f42
F test/e_expr.test d5cdda0e4ffb17760858ed4c7c4ece07efc40f71
F test/e_fkey.test d83a04478bb9c02d2c513518548a69f818869f41
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test 1e44f84d2abe44d66e4fbf198be4b20e3cc724a0
@@ -470,7 +471,7 @@ F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 8a1fde4e7721ae00b05b3178888833726ca2df8d
F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48
F test/fkey7.test e31d0e71a41c1d29349a16448d6c420e2c53a8fc
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
F test/fkey_malloc.test bb74c9cb8f8fceed03b58f8a7ef2df98520bbd51
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
@@ -559,7 +560,7 @@ F test/fts3snippet.test d524af6bcef4714e059ef559113dbdc924cd33d1
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test b10d0a12a0ab5f905cea1200b745de233f37443f
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
F test/fts3varint.test 23e79002ebebd6fbb1235504f7acb087b0fea741
F test/fts4aa.test 0c3152322c7f0b548cc942ad763eaba0da87ccca
F test/fts4check.test 66fa274cab2b615f2fb338b257713aba8fad88a8
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
@@ -573,21 +574,20 @@ F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
F test/fts4unicode.test e28ba1a14181e709dcdf47455f207adf14c7cfe0
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test 00667bbeac044d007f6f021af1b9f6150f0c7ff8
F test/func.test c7e80a44eebac8604397eb2ad83d0d5d9d541237
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
F test/hook.test 45cb22b940c3cc0af616ba7430f666e245711a48
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
@@ -624,7 +624,7 @@ F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
F test/intpkey.test 7506090fc08e028712a8bf47e5f54111947e3844
F test/io.test 3a7abcef18727cc0f2399e04b0e8903eccae50f8
F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d
F test/ioerr.test 40bb2cfcab63fb6aa7424cd97812a84bc16b5fb8
F test/ioerr2.test 9d71166f8466eda510f1af6137bdabaa82b5408d
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
@@ -643,7 +643,7 @@ F test/jrnlmode.test 9ee3a78f53d52cca737db69293d15dc41c0cbd36
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test 935fb4f608e3ea126891496a6e99b9468372bf5c
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
@@ -698,7 +698,7 @@ F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test 1265eb98c2e22a446a13fdef754118b272716684
F test/misc7.test 50c02c35ef7924c246eb3d8d71dfbf90ba352f8f
F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054
F test/mmap1.test 93d167b328255cbe6679fe1e1a23be1b1197d07b
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
@@ -726,7 +726,6 @@ F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pager4.test b40ecb4cc7dff957ee7916e41ab21d1ed702a642
F test/pagerfault.test 7285379906ab2f1108b8e82bbdf2d386cc8ff3ff
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
@@ -739,7 +738,6 @@ F test/permutations.test af3278cbea3a19e025d5169be8193ff48dc3f862
F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/printf2.test 2f0978059768bb039d3ee09466bdcd06fc7a6a86
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
@@ -758,9 +756,8 @@ F test/releasetest.tcl 06d289d8255794073a58d2850742f627924545ce
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
F test/rollback.test e9504a009a202c3ed711da2e6879ff60c5a4669c
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test b78b30afb9537a73788ca1233a23a32190a3bb1f
F test/rowid.test f777404492adb0e00868fd706a3721328fd3af48
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
F test/savepoint.test 6c53f76dffe5df0dd87646efe3e7aa159c36e07b
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
@@ -805,12 +802,11 @@ F test/shell1.test e7c0b9ebda25d5e78f0a3ea0dc4e31bb6d8098c0
F test/shell2.test e1d3790f064e50b2f973502f45750012667486df
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
F test/shell5.test cee83b4385f842fec1f2a0bec9ea811f35386edf
F test/shell5.test 46c8c18d62732415c4fe084816c13d559831705e
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
F test/skipscan1.test 6bb4891c2cc5efd5690a9da9e7508e53d4a68e10
F test/skipscan2.test 5a4db0799c338ddbacb154aaa5589c0254b36a8d
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
@@ -822,7 +818,6 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c bb3a4cc62b6cf29f5bc72c85d2bee5991e207be7
F test/spellfix.test 8c40b169b104086d8795781f670ba3c786d6d8be
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/stat.test c8eccfe8fcd3f3cfc864ce22d5b9e803a3c69940
@@ -841,8 +836,8 @@ F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl 08e9f317afe60d398fa900993503ecaef3295bad
F test/temptrigger.test 0a48d94222d50e6e50d72ac103606c4f8e7cbb81
F test/tester.tcl bce6b929932498383ce92431da6a96432c690bf7
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -991,7 +986,7 @@ F test/tpch01.test 8f4ac52f62f3e9f6bce0889105aecdf0275e331b
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
F test/trace2.test e7a988fdd982cdec62f1f1f34b0360e6476d01a0
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22
F test/trans3.test 373ac5183cc56be69f48ae44090e7f672939f732
F test/transitive1.test 03f532954f46cdf5608f7766bff0b0c52bf2a7cd
F test/trigger1.test dc47573ac79ffe0ee3eecaa517d70d8dacbccd03
@@ -1087,18 +1082,16 @@ F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
F test/whereG.test 2a3d5181decc801b36600fa1c40b0dad2ccc267f
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32longpath.test e2aafc07e6990fe86c69be22a3d1a0e210cd329b
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test b4a639a367f04d382d20e8f44fc1be4f2d57d107
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
F test/wordcount.c 2c2cc1119de42e6730ca8bd149666f0e0095108a
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test 209d7ed441f44cc5299e4ebffbef06fd5aabfefd
F tool/build-all-msvc.bat e0917e787df675b020d250d60a00de8abaa4e30a x
F tool/build-all-msvc.bat 1bac6adc3fdb4d9204f21d17b14be25778370e48 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
@@ -1143,11 +1136,14 @@ F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 6db7052eeefafdbf26b3153bc38600fecfb53ae6
R 2f73ea36e182ebaad881490b3d78bb71
P 24ef16548eebcdb9d8b40308f6a16dabf8f8d474
R d7a0355ea8d187cc731421105334e976
T *branch * schema2-vtab
T *sym-schema2-vtab *
T -sym-trunk *
U drh
Z 671b11d5131d6faea51d8a864c8026f9
Z ad6b62ac80e7bb705f75b7062e44d1db
+1 -1
View File
@@ -1 +1 @@
3375571a5e267744c19a7c310840256cec57a242
d1fbc6ca18383b97befd597aeb7ff84c6a04d243
-2
View File
@@ -136,10 +136,8 @@ END {
|| name=="OP_VUpdate" \
|| name=="OP_VFilter" \
|| name=="OP_Next" \
|| name=="OP_NextIfOpen" \
|| name=="OP_SorterNext" \
|| name=="OP_Prev" \
|| name=="OP_PrevIfOpen" \
){
cnt++
while( used[cnt] ) cnt++
+4 -5
View File
@@ -96,7 +96,6 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
rc = SQLITE_ERROR;
}
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
sqlite3ParserReset(pParse);
sqlite3StackFree(pErrorDb, pParse);
}
if( rc ){
@@ -526,7 +525,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Sync the database file to disk. */
if( rc==SQLITE_OK ){
rc = sqlite3PagerSync(pDestPager, 0);
rc = sqlite3PagerSync(pDestPager);
}
}else{
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
@@ -601,10 +600,10 @@ int sqlite3_backup_finish(sqlite3_backup *p){
/* Set the error code of the destination database handle. */
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
if( p->pDestDb ){
sqlite3Error(p->pDestDb, rc, 0);
sqlite3Error(p->pDestDb, rc, 0);
/* Exit the mutexes and free the backup context structure. */
/* Exit the mutexes and free the backup context structure. */
if( p->pDestDb ){
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
}
sqlite3BtreeLeave(p->pSrc);
+133 -92
View File
@@ -694,10 +694,6 @@ static int btreeMoveto(
);
if( pIdxKey==0 ) return SQLITE_NOMEM;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 ){
sqlite3DbFree(pCur->pKeyInfo->db, pFree);
return SQLITE_CORRUPT_BKPT;
}
}else{
pIdxKey = 0;
}
@@ -1652,7 +1648,7 @@ static int getAndInitPage(
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeGetPage(pBt, pgno, ppPage, bReadonly);
if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
if( rc==SQLITE_OK ){
rc = btreeInitPage(*ppPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
@@ -1673,11 +1669,10 @@ static void releasePage(MemPage *pPage){
if( pPage ){
assert( pPage->aData );
assert( pPage->pBt );
assert( pPage->pDbPage!=0 );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
sqlite3PagerUnrefNotNull(pPage->pDbPage);
sqlite3PagerUnref(pPage->pDbPage);
}
}
@@ -4193,10 +4188,10 @@ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
/*
** Return a pointer to payload information from the entry that the
** pCur cursor is pointing to. The pointer is to the beginning of
** the key if index btrees (pPage->intKey==0) and is the data for
** table btrees (pPage->intKey==1). The number of bytes of available
** key/data is written into *pAmt. If *pAmt==0, then the value
** returned will not be a valid pointer.
** the key if skipKey==0 and it points to the beginning of data if
** skipKey==1. The number of bytes of available key/data is written
** into *pAmt. If *pAmt==0, then the value returned will not be
** a valid pointer.
**
** This routine is an optimization. It is common for the entire key
** and data to fit on the local page and for there to be no overflow
@@ -4209,21 +4204,41 @@ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
** page of the database. The data might change or move the next time
** any btree routine is called.
*/
static const void *fetchPayload(
static const unsigned char *fetchPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 *pAmt /* Write the number of available bytes here */
int *pAmt, /* Write the number of available bytes here */
int skipKey /* read beginning at data if this is true */
){
unsigned char *aPayload;
MemPage *pPage;
u32 nKey;
u32 nLocal;
assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
if( pCur->info.nSize==0 ){
pPage = pCur->apPage[pCur->iPage];
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
if( NEVER(pCur->info.nSize==0) ){
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
&pCur->info);
}
*pAmt = pCur->info.nLocal;
return (void*)(pCur->info.pCell + pCur->info.nHeader);
aPayload = pCur->info.pCell;
aPayload += pCur->info.nHeader;
if( pPage->intKey ){
nKey = 0;
}else{
nKey = (int)pCur->info.nKey;
}
if( skipKey ){
aPayload += nKey;
nLocal = pCur->info.nLocal - nKey;
}else{
nLocal = pCur->info.nLocal;
assert( nLocal<=nKey );
}
*pAmt = nLocal;
return aPayload;
}
@@ -4241,11 +4256,23 @@ static const void *fetchPayload(
** These routines is used to get quick access to key and data
** in the common case where no overflow pages are used.
*/
const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){
return fetchPayload(pCur, pAmt);
const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){
const void *p = 0;
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) );
if( ALWAYS(pCur->eState==CURSOR_VALID) ){
p = (const void*)fetchPayload(pCur, pAmt, 0);
}
return p;
}
const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){
return fetchPayload(pCur, pAmt);
const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){
const void *p = 0;
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) );
if( ALWAYS(pCur->eState==CURSOR_VALID) ){
p = (const void*)fetchPayload(pCur, pAmt, 1);
}
return p;
}
@@ -4364,6 +4391,8 @@ static void moveToParent(BtCursor *pCur){
static int moveToRoot(BtCursor *pCur){
MemPage *pRoot;
int rc = SQLITE_OK;
Btree *p = pCur->pBtree;
BtShared *pBt = p->pBt;
assert( cursorHoldsMutex(pCur) );
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
@@ -4378,12 +4407,16 @@ static int moveToRoot(BtCursor *pCur){
}
if( pCur->iPage>=0 ){
while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]);
int i;
for(i=1; i<=pCur->iPage; i++){
releasePage(pCur->apPage[i]);
}
pCur->iPage = 0;
}else if( pCur->pgnoRoot==0 ){
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}else{
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0],
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
@@ -4416,16 +4449,14 @@ static int moveToRoot(BtCursor *pCur){
pCur->atLast = 0;
pCur->validNKey = 0;
if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID;
}else if( !pRoot->leaf ){
if( pRoot->nCell==0 && !pRoot->leaf ){
Pgno subpage;
if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
pCur->eState = CURSOR_VALID;
rc = moveToChild(pCur, subpage);
}else{
pCur->eState = CURSOR_INVALID;
pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
}
return rc;
}
@@ -4616,10 +4647,10 @@ int sqlite3BtreeMovetoUnpacked(
}
assert( pCur->apPage[0]->intKey || pIdxKey );
for(;;){
int lwr, upr, idx, c;
int lwr, upr, idx;
Pgno chldPg;
MemPage *pPage = pCur->apPage[pCur->iPage];
u8 *pCell; /* Pointer to current cell in pPage */
int c;
/* pPage->nCell must be greater than zero. If this is the root-page
** the cursor would have been INVALID above and this for(;;) loop
@@ -4631,47 +4662,35 @@ int sqlite3BtreeMovetoUnpacked(
assert( pPage->intKey==(pIdxKey==0) );
lwr = 0;
upr = pPage->nCell-1;
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( pPage->intKey ){
for(;;){
if( biasRight ){
pCur->aiIdx[pCur->iPage] = (u16)(idx = upr);
}else{
pCur->aiIdx[pCur->iPage] = (u16)(idx = (upr+lwr)/2);
}
for(;;){
u8 *pCell; /* Pointer to current cell in pPage */
assert( idx==pCur->aiIdx[pCur->iPage] );
pCur->info.nSize = 0;
pCell = findCell(pPage, idx) + pPage->childPtrSize;
if( pPage->intKey ){
i64 nCellKey;
pCell = findCell(pPage, idx) + pPage->childPtrSize;
if( pPage->hasData ){
while( 0x80 <= *(pCell++) ){
if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
}
u32 dummy;
pCell += getVarint32(pCell, dummy);
}
getVarint(pCell, (u64*)&nCellKey);
if( nCellKey<intKey ){
lwr = idx+1;
if( lwr>upr ){ c = -1; break; }
}else if( nCellKey>intKey ){
upr = idx-1;
if( lwr>upr ){ c = +1; break; }
if( nCellKey==intKey ){
c = 0;
}else if( nCellKey<intKey ){
c = -1;
}else{
assert( nCellKey==intKey );
pCur->validNKey = 1;
pCur->info.nKey = nCellKey;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( !pPage->leaf ){
lwr = idx;
goto moveto_next_layer;
}else{
*pRes = 0;
rc = SQLITE_OK;
goto moveto_finish;
}
assert( nCellKey>intKey );
c = +1;
}
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
}
}else{
for(;;){
int nCell;
pCell = findCell(pPage, idx) + pPage->childPtrSize;
pCur->validNKey = 1;
pCur->info.nKey = nCellKey;
}else{
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is less than 16384 bytes and may be stored as a 2-byte
@@ -4680,8 +4699,10 @@ int sqlite3BtreeMovetoUnpacked(
** stored entirely within the b-tree page by inspecting the first
** 2 bytes of the cell.
*/
nCell = pCell[0];
if( nCell<=pPage->max1bytePayload ){
int nCell = pCell[0];
if( nCell<=pPage->max1bytePayload
/* && (pCell+nCell)<pPage->aDataEnd */
){
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
@@ -4689,6 +4710,7 @@ int sqlite3BtreeMovetoUnpacked(
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
/* && (pCell+nCell+2)<=pPage->aDataEnd */
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
@@ -4708,7 +4730,6 @@ int sqlite3BtreeMovetoUnpacked(
rc = SQLITE_NOMEM;
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
if( rc ){
sqlite3_free(pCellKey);
@@ -4717,44 +4738,49 @@ int sqlite3BtreeMovetoUnpacked(
c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
}
if( c<0 ){
lwr = idx+1;
}else if( c>0 ){
upr = idx-1;
}
if( c==0 ){
if( pPage->intKey && !pPage->leaf ){
lwr = idx;
break;
}else{
assert( c==0 );
*pRes = 0;
rc = SQLITE_OK;
pCur->aiIdx[pCur->iPage] = (u16)idx;
goto moveto_finish;
}
if( lwr>upr ) break;
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
}
if( c<0 ){
lwr = idx+1;
}else{
upr = idx-1;
}
if( lwr>upr ){
break;
}
pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2);
}
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
pCur->aiIdx[pCur->iPage] = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto moveto_finish;
}
moveto_next_layer:
if( lwr>=pPage->nCell ){
chldPg = 0;
}else if( lwr>=pPage->nCell ){
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
if( chldPg==0 ){
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
*pRes = c;
rc = SQLITE_OK;
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)lwr;
pCur->info.nSize = 0;
pCur->validNKey = 0;
rc = moveToChild(pCur, chldPg);
if( rc ) break;
if( rc ) goto moveto_finish;
}
moveto_finish:
pCur->info.nSize = 0;
pCur->validNKey = 0;
return rc;
}
@@ -5512,7 +5538,7 @@ static int fillInCell(
nHeader += 4;
}
if( pPage->hasData ){
nHeader += putVarint32(&pCell[nHeader], nData+nZero);
nHeader += putVarint(&pCell[nHeader], nData+nZero);
}else{
nData = nZero = 0;
}
@@ -5640,6 +5666,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
u32 pc; /* Offset to cell content of cell being deleted */
u8 *data; /* pPage->aData */
u8 *ptr; /* Used to move bytes around within data[] */
u8 *endPtr; /* End of loop */
int rc; /* The return code */
int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
@@ -5664,8 +5691,13 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
*pRC = rc;
return;
}
endPtr = &pPage->aCellIdx[2*pPage->nCell - 2];
assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
while( ptr<endPtr ){
*(u16*)ptr = *(u16*)&ptr[2];
ptr += 2;
}
pPage->nCell--;
memmove(ptr, ptr+2, 2*(pPage->nCell - idx));
put2byte(&data[hdr+3], pPage->nCell);
pPage->nFree += 2;
}
@@ -5702,6 +5734,9 @@ static void insertCell(
int ins; /* Index in data[] where new cell pointer is inserted */
int cellOffset; /* Address of first cell pointer in data[] */
u8 *data; /* The content of the whole page */
u8 *ptr; /* Used for moving information around in data[] */
u8 *endPtr; /* End of the loop */
int nSkip = (iChild ? 4 : 0);
if( *pRC ) return;
@@ -5752,7 +5787,13 @@ static void insertCell(
if( iChild ){
put4byte(&data[idx], iChild);
}
memmove(&data[ins+2], &data[ins], end-ins);
ptr = &data[end];
endPtr = &data[ins];
assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
while( ptr>endPtr ){
*(u16*)ptr = *(u16*)&ptr[-2];
ptr -= 2;
}
put2byte(&data[ins], idx);
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -7714,7 +7755,7 @@ static void checkAppendMsg(
sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
}
if( zMsg1 ){
sqlite3StrAccumAppendAll(&pCheck->errMsg, zMsg1);
sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1);
}
sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
va_end(ap);
+2 -2
View File
@@ -178,8 +178,8 @@ int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int *pRes);
int sqlite3BtreeKeySize(BtCursor*, i64 *pSize);
int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt);
const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt);
const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt);
const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64);
+14 -22
View File
@@ -150,7 +150,7 @@ void sqlite3FinishCoding(Parse *pParse){
*/
if( pParse->cookieGoto>0 ){
yDbMask mask;
int iDb, i, addr;
int iDb;
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
if( (mask & pParse->cookieMask)==0 ) continue;
@@ -164,11 +164,14 @@ void sqlite3FinishCoding(Parse *pParse){
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=0; i<pParse->nVtabLock; i++){
char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
{
int i;
for(i=0; i<pParse->nVtabLock; i++){
char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
}
pParse->nVtabLock = 0;
}
pParse->nVtabLock = 0;
#endif
/* Once all the cookies have been verified and transactions opened,
@@ -181,18 +184,8 @@ void sqlite3FinishCoding(Parse *pParse){
*/
sqlite3AutoincrementBegin(pParse);
/* Code constant expressions that where factored out of inner loops */
addr = pParse->cookieGoto;
if( pParse->pConstExpr ){
ExprList *pEL = pParse->pConstExpr;
pParse->cookieGoto = 0;
for(i=0; i<pEL->nExpr; i++){
sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
}
}
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto);
}
}
@@ -2790,7 +2783,7 @@ Index *sqlite3CreateIndex(
const Column *pTabCol; /* A column in the table */
int nExtra = 0; /* Space allocated for zExtra[] */
int nExtraCol; /* Number of extra columns needed */
char *zExtra = 0; /* Extra space after the Index object */
char *zExtra; /* Extra space after the Index object */
Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
assert( pParse->nErr==0 ); /* Never called with prior errors */
@@ -3989,9 +3982,9 @@ void sqlite3UniqueConstraint(
for(j=0; j<pIdx->nKeyCol; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
sqlite3StrAccumAppendAll(&errMsg, pTab->zName);
sqlite3StrAccumAppend(&errMsg, pTab->zName, -1);
sqlite3StrAccumAppend(&errMsg, ".", 1);
sqlite3StrAccumAppendAll(&errMsg, zCol);
sqlite3StrAccumAppend(&errMsg, zCol, -1);
}
zErr = sqlite3StrAccumFinish(&errMsg);
sqlite3HaltConstraint(pParse,
@@ -4183,9 +4176,8 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
assert( sqlite3KeyInfoIsWriteable(pKey) );
for(i=0; i<nCol; i++){
char *zColl = pIdx->azColl[i];
assert( zColl!=0 );
pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
sqlite3LocateCollSeq(pParse, zColl);
if( NEVER(zColl==0) ) zColl = "BINARY";
pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl);
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
}
if( pParse->nErr ){
+1
View File
@@ -357,6 +357,7 @@ FuncDef *sqlite3FindFunction(
assert( nArg>=(-2) );
assert( nArg>=(-1) || createFlag==0 );
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
/* First search for a match amongst the application-defined functions.
-6
View File
@@ -347,9 +347,6 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_SOUNDEX
"SOUNDEX",
#endif
#ifdef SQLITE_SYSTEM_MALLOC
"SYSTEM_MALLOC",
#endif
#ifdef SQLITE_TCL
"TCL",
#endif
@@ -365,9 +362,6 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
#ifdef SQLITE_WIN32_MALLOC
"WIN32_MALLOC",
#endif
#ifdef SQLITE_ZERO_MALLOC
"ZERO_MALLOC"
#endif
+99 -149
View File
@@ -227,34 +227,20 @@ void sqlite3DeleteFrom(
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
const char *zDb; /* Name of database holding pTab */
int end, addr = 0; /* A couple addresses of generated code */
int i; /* Loop counter */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Index *pIdx; /* For looping over indices of the table */
int iTabCur; /* Cursor number for the table */
int iDataCur; /* VDBE cursor for the canonical data source */
int iIdxCur; /* Cursor number of the first index */
int nIdx; /* Number of indices */
sqlite3 *db; /* Main database structure */
AuthContext sContext; /* Authorization context */
NameContext sNC; /* Name context to resolve expressions in */
int iDb; /* Database number */
int memCnt = -1; /* Memory cell used for change counting */
int rcauth; /* Value returned by authorization callback */
int okOnePass; /* True for one-pass algorithm without the FIFO */
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
Index *pPk; /* The PRIMARY KEY index on the table */
int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */
i16 nPk = 1; /* Number of columns in the PRIMARY KEY */
int iKey; /* Memory cell holding key of row to be deleted */
i16 nKey; /* Number of memory cells in the row key */
int iEphCur = 0; /* Ephemeral table holding all primary key values */
int iRowSet = 0; /* Register for rowset of rows to delete */
int addrBypass = 0; /* Address of jump over the delete logic */
int addrLoop = 0; /* Top of the delete loop */
int addrDelete = 0; /* Jump directly to the delete logic */
int addrEphOpen = 0; /* Instruction to open the Ephermeral table */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
Trigger *pTrigger; /* List of table triggers, if required */
@@ -309,11 +295,11 @@ void sqlite3DeleteFrom(
}
assert(!isView || pTrigger);
/* Assign cursor numbers to the table and all its indices.
/* Assign cursor number to the table and all its indices.
*/
assert( pTabList->nSrc==1 );
iTabCur = pTabList->a[0].iCursor = pParse->nTab++;
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
pParse->nTab++;
}
@@ -379,129 +365,106 @@ void sqlite3DeleteFrom(
}
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
{
if( HasRowid(pTab) ){
/* For a rowid table, initialize the RowSet to an empty set */
pPk = 0;
nPk = 1;
iRowSet = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
}else{
/* For a WITHOUT ROWID table, create an ephermeral table used to
** hold all primary keys for rows to be deleted. */
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
nPk = pPk->nKeyCol;
iPk = pParse->nMem+1;
pParse->nMem += nPk;
iEphCur = pParse->nTab++;
addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
}
/* Construct a query to find the rowid or primary key for every row
** to be deleted, based on the WHERE clause.
if( !HasRowid(pTab) ){
/* There is a WHERE clause on a WITHOUT ROWID table.
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK,
iTabCur+1);
Index *pPk; /* The PRIMARY KEY index on the table */
int iPk; /* First of nPk memory cells holding PRIMARY KEY value */
int iEph; /* Ephemeral table holding all primary key values */
int iKey; /* Key value inserting into iEph */
i16 nPk; /* Number of components of the PRIMARY KEY */
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
nPk = pPk->nKeyCol;
iPk = pParse->nMem+1;
pParse->nMem += nPk;
iKey = ++pParse->nMem;
iEph = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 0, 0);
if( pWInfo==0 ) goto delete_from_cleanup;
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
/* Keep track of the number of rows to be deleted */
for(i=0; i<nPk; i++){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pPk->aiColumn[i],iPk+i);
}
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, iKey);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
}
/* Extract the rowid or primary key for the current row */
if( pPk ){
for(i=0; i<nPk; i++){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
pPk->aiColumn[i], iPk+i);
}
iKey = iPk;
}else{
iKey = pParse->nMem + 1;
iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
if( iKey>pParse->nMem ) pParse->nMem = iKey;
}
if( okOnePass ){
/* For ONEPASS, no need to store the rowid/primary-key. There is only
** one, so just keep it in its register(s) and fall through to the
** delete code.
*/
nKey = nPk; /* OP_Found will use an unpacked key */
aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
if( aToOpen==0 ){
sqlite3WhereEnd(pWInfo);
goto delete_from_cleanup;
}
memset(aToOpen, 1, nIdx+1);
aToOpen[nIdx+1] = 0;
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
addrDelete = sqlite3VdbeAddOp0(v, OP_Goto); /* Jump to DELETE logic */
}else if( pPk ){
/* Construct a composite key for the row to be deleted and remember it */
iKey = ++pParse->nMem;
nKey = 0; /* Zero tells OP_Found to use a composite key */
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
}else{
/* Get the rowid of the row to be deleted and remember it in the RowSet */
nKey = 1; /* OP_Seek always uses a single rowid */
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
}
/* End of the WHERE loop */
sqlite3WhereEnd(pWInfo);
if( okOnePass ){
/* Bypass the delete logic below if the WHERE loop found zero rows */
addrBypass = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBypass);
sqlite3VdbeJumpHere(v, addrDelete);
/* Open cursors for all indices of the table.
*/
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite,
iTabCur, &iDataCur, &iIdxCur);
/* Loop over the primary keys to be deleted. */
addr = sqlite3VdbeAddOp1(v, OP_Rewind, iEph);
sqlite3VdbeAddOp2(v, OP_RowKey, iEph, iPk);
/* Delete the row */
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
iPk, 0, 1, OE_Default, 0);
/* End of the delete loop */
sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1);
sqlite3VdbeJumpHere(v, addr);
/* Close the cursors open on the table and its indexes. */
assert( iDataCur>=iIdxCur );
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur+i);
}
}else{
/* There is a WHERE clause on a rowid table. Run a loop that extracts
** all rowids to be deleted into a RowSet.
*/
int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
int regRowid; /* Actual register containing rowids */
/* Collect rowids of every row to be deleted.
*/
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
pWInfo = sqlite3WhereBegin(
pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
);
if( pWInfo==0 ) goto delete_from_cleanup;
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iRowid, 0);
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
}
sqlite3WhereEnd(pWInfo);
/* Delete every item whose key was written to the list during the
** database scan. We have to delete items after the scan is complete
** because deleting an item can change the scan order. */
end = sqlite3VdbeMakeLabel(v);
/* Unless this is a view, open cursors for the table we are
** deleting from and all its indices. If this is a view, then the
** only effect this statement has is to fire the INSTEAD OF
** triggers.
*/
** triggers. */
if( !isView ){
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur,
&iDataCur, &iIdxCur);
assert( pPk || iDataCur==iTabCur );
assert( pPk || iIdxCur==iDataCur+1 );
assert( iDataCur==iTabCur );
assert( iIdxCur==iDataCur+1 );
}
/* Set up a loop over the rowids/primary-keys that were found in the
** where-clause loop above.
*/
if( okOnePass ){
/* Just one row. Hence the top-of-loop is a no-op */
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
if( aToOpen[iDataCur-iTabCur] ){
assert( pPk!=0 );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
}
}else if( pPk ){
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur);
sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
assert( nKey==0 ); /* OP_Found will use a composite key */
}else{
addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
assert( nKey==1 );
}
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
/* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, OE_Abort);
sqlite3MayAbort(pParse);
}else
@@ -509,28 +472,21 @@ void sqlite3DeleteFrom(
{
int count = (pParse->nested==0); /* True to count changes */
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
iKey, nKey, count, OE_Default, okOnePass);
iRowid, 1, count, OE_Default, 0);
}
/* End of the loop over all rowids/primary-keys. */
if( okOnePass ){
sqlite3VdbeResolveLabel(v, addrBypass);
}else if( pPk ){
sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1);
sqlite3VdbeJumpHere(v, addrLoop);
}else{
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop);
sqlite3VdbeJumpHere(v, addrLoop);
}
/* End of the delete loop */
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
sqlite3VdbeResolveLabel(v, end);
/* Close the cursors open on the table and its indexes. */
if( !isView && !IsVirtual(pTab) ){
if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i);
}
}
} /* End non-truncate path */
}
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
@@ -554,7 +510,6 @@ delete_from_cleanup:
sqlite3AuthContextPop(&sContext);
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprDelete(db, pWhere);
sqlite3DbFree(db, aToOpen);
return;
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
@@ -621,7 +576,6 @@ void sqlite3GenerateRowDelete(
if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
u32 mask; /* Mask of OLD.* columns in use */
int iCol; /* Iterator used while populating OLD.* */
int addrStart; /* Start of BEFORE trigger programs */
/* TODO: Could use temporary registers here. Also could attempt to
** avoid copying the contents of the rowid register. */
@@ -642,19 +596,15 @@ void sqlite3GenerateRowDelete(
}
/* Invoke BEFORE DELETE trigger programs. */
addrStart = sqlite3VdbeCurrentAddr(v);
sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
);
/* If any BEFORE triggers were coded, then seek the cursor to the
** row to be deleted again. It may be that the BEFORE triggers moved
** the cursor or of already deleted the row that the cursor was
** pointing to.
*/
if( addrStart<sqlite3VdbeCurrentAddr(v) ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
}
/* Seek the cursor to the row to be deleted again. It may be that
** the BEFORE triggers coded above have already removed the row
** being deleted. Do not attempt to delete the row a second time, and
** do not fire AFTER triggers. */
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
/* Do FK processing. This call checks that any FK constraints that
** refer to this table (i.e. constraints attached to other tables)
+200 -131
View File
@@ -930,7 +930,8 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pItem->sortOrder = pOldItem->sortOrder;
pItem->done = 0;
pItem->bSpanIsTab = pOldItem->bSpanIsTab;
pItem->u = pOldItem->u;
pItem->iOrderByCol = pOldItem->iOrderByCol;
pItem->iAlias = pOldItem->iAlias;
}
return pNew;
}
@@ -1191,12 +1192,9 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
** and either pWalker->u.i==2 or the function as the SQLITE_FUNC_CONST
** flag. */
** and pWalker->u.i==2 */
case TK_FUNCTION:
if( pWalker->u.i==2 || ExprHasProperty(pExpr,EP_Constant) ){
return WRC_Continue;
}
if( pWalker->u.i==2 ) return 0;
/* Fall through */
case TK_ID:
case TK_COLUMN:
@@ -2358,7 +2356,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
int regFree2 = 0; /* If non-zero free this temporary register */
int r1, r2, r3, r4; /* Various register numbers */
sqlite3 *db = pParse->db; /* The database connection */
Expr tempX; /* Temporary expression node */
assert( target>0 && target<=pParse->nMem );
if( v==0 ){
@@ -2578,10 +2575,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
codeReal(v, pLeft->u.zToken, 1, target);
#endif
}else{
tempX.op = TK_INTEGER;
tempX.flags = EP_IntValue|EP_TokenOnly;
tempX.u.iValue = 0;
r1 = sqlite3ExprCodeTemp(pParse, &tempX, &regFree1);
regFree1 = r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
testcase( regFree2==0 );
@@ -2626,6 +2621,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}
break;
}
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
int nFarg; /* Number of function arguments */
@@ -2638,6 +2634,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
CollSeq *pColl = 0; /* A collating sequence */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
testcase( op==TK_CONST_FUNC );
testcase( op==TK_FUNCTION );
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
@@ -2681,21 +2679,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
break;
}
for(i=0; i<nFarg; i++){
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
constMask |= (1<<i);
}
if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
}
}
if( pFarg ){
if( constMask ){
r1 = pParse->nMem+1;
pParse->nMem += nFarg;
}else{
r1 = sqlite3GetTempRange(pParse, nFarg);
}
r1 = sqlite3GetTempRange(pParse, nFarg);
/* For length() and typeof() functions with a column argument,
** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
@@ -2710,15 +2695,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
pFarg->a[0].pExpr->op2 =
pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
testcase( (pDef->funcFlags&~SQLITE_FUNC_ENCMASK)
==SQLITE_FUNC_LENGTH );
pFarg->a[0].pExpr->op2 = pDef->funcFlags&~SQLITE_FUNC_ENCMASK;
}
}
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
sqlite3ExprCodeExprList(pParse, pFarg, r1,
SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
}else{
r1 = 0;
@@ -2742,6 +2726,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
}
#endif
for(i=0; i<nFarg; i++){
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
constMask |= (1<<i);
}
if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
}
}
if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
@@ -2749,7 +2741,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
(char*)pDef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nFarg);
if( nFarg && constMask==0 ){
if( nFarg ){
sqlite3ReleaseTempRange(pParse, r1, nFarg);
}
break;
@@ -2900,6 +2892,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
ExprList *pEList; /* List of WHEN terms */
struct ExprList_item *aListelem; /* Array of WHEN terms */
Expr opCompare; /* The X==Ei expression */
Expr cacheX; /* Cached expression X */
Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
@@ -2911,12 +2904,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
nExpr = pEList->nExpr;
endLabel = sqlite3VdbeMakeLabel(v);
if( (pX = pExpr->pLeft)!=0 ){
tempX = *pX;
cacheX = *pX;
testcase( pX->op==TK_COLUMN );
exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, &regFree1));
testcase( pX->op==TK_REGISTER );
exprToRegister(&cacheX, sqlite3ExprCodeTemp(pParse, pX, &regFree1));
testcase( regFree1==0 );
opCompare.op = TK_EQ;
opCompare.pLeft = &tempX;
opCompare.pLeft = &cacheX;
pTest = &opCompare;
/* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
** The value in regFree1 might get SCopy-ed into the file result.
@@ -2936,6 +2930,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
testcase( pTest->op==TK_COLUMN );
sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
testcase( aListelem[i+1].pExpr->op==TK_REGISTER );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
sqlite3ExprCachePop(pParse, 1);
@@ -2986,28 +2981,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
return inReg;
}
/*
** Factor out the code of the given expression to initialization time.
*/
void sqlite3ExprCodeAtInit(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The expression to code when the VDBE initializes */
int regDest, /* Store the value in this register */
u8 reusable /* True if this expression is reusable */
){
ExprList *p;
assert( ConstFactorOk(pParse) );
p = pParse->pConstExpr;
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
p = sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
pItem->u.iConstExprReg = regDest;
pItem->reusable = reusable;
}
pParse->pConstExpr = p;
}
/*
** Generate code to evaluate an expression and store the results
** into a register. Return the register number where the results
@@ -3016,40 +2989,15 @@ void sqlite3ExprCodeAtInit(
** If the register is a temporary register that can be deallocated,
** then write its number into *pReg. If the result register is not
** a temporary, then set *pReg to zero.
**
** If pExpr is a constant, then this routine might generate this
** code to fill the register in the initialization section of the
** VDBE program, in order to factor it out of the evaluation loop.
*/
int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
int r2;
pExpr = sqlite3ExprSkipCollate(pExpr);
if( ConstFactorOk(pParse)
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
ExprList *p = pParse->pConstExpr;
int i;
*pReg = 0;
if( p ){
struct ExprList_item *pItem;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
return pItem->u.iConstExprReg;
}
}
}
r2 = ++pParse->nMem;
sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1);
int r1 = sqlite3GetTempReg(pParse);
int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
if( r2==r1 ){
*pReg = r1;
}else{
int r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
if( r2==r1 ){
*pReg = r1;
}else{
sqlite3ReleaseTempReg(pParse, r1);
*pReg = 0;
}
sqlite3ReleaseTempReg(pParse, r1);
*pReg = 0;
}
return r2;
}
@@ -3092,13 +3040,12 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
int inReg;
inReg = sqlite3ExprCode(pParse, pExpr, target);
assert( target>0 );
/* The only place, other than this routine, where expressions can be
** converted to TK_REGISTER is internal subexpressions in BETWEEN and
** CASE operators. Neither ever calls this routine. And this routine
** is never called twice on the same expression. Hence it is impossible
** for the input to this routine to already be a register. Nevertheless,
** it seems prudent to keep the ALWAYS() in case the conditions above
** change with future modifications or enhancements. */
/* This routine is called for terms to INSERT or UPDATE. And the only
** other place where expressions can be converted into TK_REGISTER is
** in WHERE clause processing. So as currently implemented, there is
** no way for a TK_REGISTER to exist here. But it seems prudent to
** keep the ALWAYS() in case the conditions above change with future
** modifications or enhancements. */
if( ALWAYS(pExpr->op!=TK_REGISTER) ){
int iMem;
iMem = ++pParse->nMem;
@@ -3230,6 +3177,7 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
}
case TK_AGG_FUNCTION:
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
@@ -3380,41 +3328,164 @@ void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
}
#endif /* SQLITE_DEBUG */
/*
** Return TRUE if pExpr is an constant expression that is appropriate
** for factoring out of a loop. Appropriate expressions are:
**
** * Any expression that evaluates to two or more opcodes.
**
** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
** or OP_Variable that does not need to be placed in a
** specific register.
**
** There is no point in factoring out single-instruction constant
** expressions that need to be placed in a particular register.
** We could factor them out, but then we would end up adding an
** OP_SCopy instruction to move the value into the correct register
** later. We might as well just use the original instruction and
** avoid the OP_SCopy.
*/
static int isAppropriateForFactoring(Expr *p){
if( !sqlite3ExprIsConstantNotJoin(p) ){
return 0; /* Only constant expressions are appropriate for factoring */
}
if( (p->flags & EP_FixedDest)==0 ){
return 1; /* Any constant without a fixed destination is appropriate */
}
while( p->op==TK_UPLUS ) p = p->pLeft;
switch( p->op ){
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB:
#endif
case TK_VARIABLE:
case TK_INTEGER:
case TK_FLOAT:
case TK_NULL:
case TK_STRING: {
testcase( p->op==TK_BLOB );
testcase( p->op==TK_VARIABLE );
testcase( p->op==TK_INTEGER );
testcase( p->op==TK_FLOAT );
testcase( p->op==TK_NULL );
testcase( p->op==TK_STRING );
/* Single-instruction constants with a fixed destination are
** better done in-line. If we factor them, they will just end
** up generating an OP_SCopy to move the value to the destination
** register. */
return 0;
}
case TK_UMINUS: {
if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){
return 0;
}
break;
}
default: {
break;
}
}
return 1;
}
/*
** If pExpr is a constant expression that is appropriate for
** factoring out of a loop, then evaluate the expression
** into a register and convert the expression into a TK_REGISTER
** expression.
*/
static int evalConstExpr(Walker *pWalker, Expr *pExpr){
Parse *pParse = pWalker->pParse;
switch( pExpr->op ){
case TK_IN:
case TK_REGISTER: {
return WRC_Prune;
}
case TK_COLLATE: {
return WRC_Continue;
}
case TK_FUNCTION:
case TK_AGG_FUNCTION:
case TK_CONST_FUNC: {
/* The arguments to a function have a fixed destination.
** Mark them this way to avoid generated unneeded OP_SCopy
** instructions.
*/
ExprList *pList = pExpr->x.pList;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( pList ){
int i = pList->nExpr;
struct ExprList_item *pItem = pList->a;
for(; i>0; i--, pItem++){
if( ALWAYS(pItem->pExpr) ) pItem->pExpr->flags |= EP_FixedDest;
}
}
break;
}
}
if( isAppropriateForFactoring(pExpr) ){
int r1 = ++pParse->nMem;
int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
/* If r2!=r1, it means that register r1 is never used. That is harmless
** but suboptimal, so we want to know about the situation to fix it.
** Hence the following assert: */
assert( r2==r1 );
exprToRegister(pExpr, r2);
return WRC_Prune;
}
return WRC_Continue;
}
/*
** Preevaluate constant subexpressions within pExpr and store the
** results in registers. Modify pExpr so that the constant subexpresions
** are TK_REGISTER opcodes that refer to the precomputed values.
**
** This routine is a no-op if the jump to the cookie-check code has
** already occur. Since the cookie-check jump is generated prior to
** any other serious processing, this check ensures that there is no
** way to accidently bypass the constant initializations.
**
** This routine is also a no-op if the SQLITE_FactorOutConst optimization
** is disabled via the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS)
** interface. This allows test logic to verify that the same answer is
** obtained for queries regardless of whether or not constants are
** precomputed into registers or if they are inserted in-line.
*/
void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
Walker w;
if( pParse->cookieGoto ) return;
if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
memset(&w, 0, sizeof(w));
w.xExprCallback = evalConstExpr;
w.pParse = pParse;
sqlite3WalkExpr(&w, pExpr);
}
/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
** Return the number of elements evaluated.
**
** The SQLITE_ECEL_DUP flag prevents the arguments from being
** filled using OP_SCopy. OP_Copy must be used instead.
**
** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
** factored out into initialization code.
*/
int sqlite3ExprCodeExprList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* The expression list to be coded */
int target, /* Where to write results */
u8 flags /* SQLITE_ECEL_* flags */
int doHardCopy /* Make a hard copy of every element */
){
struct ExprList_item *pItem;
int i, n;
u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
assert( pList!=0 );
assert( target>0 );
assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */
n = pList->nExpr;
if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
Expr *pExpr = pItem->pExpr;
if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
}else{
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
if( inReg!=target+i ){
sqlite3VdbeAddOp2(pParse->pVdbe, copyOp, inReg, target+i);
}
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
if( inReg!=target+i ){
sqlite3VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy,
inReg, target+i);
}
}
return n;
@@ -3768,18 +3839,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
** an incorrect 0 or 1 could lead to a malfunction.
*/
int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
u32 combinedFlags;
if( pA==0 || pB==0 ){
if( pA==0||pB==0 ){
return pB==pA ? 0 : 2;
}
combinedFlags = pA->flags | pB->flags;
if( combinedFlags & EP_IntValue ){
if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
return 0;
}
assert( !ExprHasProperty(pA, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(pB, EP_TokenOnly|EP_Reduced) );
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
return 2;
}
if( pA->op!=pB->op ){
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( pA->op!=pB->op && (pA->op!=TK_REGISTER || pA->op2!=pB->op) ){
if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
return 1;
}
@@ -3788,23 +3857,23 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
}
return 2;
}
if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken ){
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
&& pA->op!=TK_REGISTER
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
if( ExprHasProperty(pA, EP_IntValue) ){
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
return 2;
}
}else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
return pA->op==TK_COLLATE ? 1 : 2;
}
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( combinedFlags & EP_xIsSelect ) return 2;
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
if( ALWAYS((combinedFlags & EP_Reduced)==0) ){
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
}
}
return 0;
}
-2
View File
@@ -548,7 +548,6 @@ static void fkScanChildren(
assert( pIdx==0 || pIdx->pTable==pTab );
assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol );
assert( pIdx!=0 || pFKey->nCol==1 );
assert( pIdx!=0 || HasRowid(pTab) );
if( nIncr<0 ){
iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
@@ -601,7 +600,6 @@ static void fkScanChildren(
}else{
Expr *pEq, *pAll = 0;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pIdx!=0 );
for(i=0; i<pPk->nKeyCol; i++){
i16 iCol = pIdx->aiColumn[i];
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
+7 -34
View File
@@ -218,32 +218,6 @@ static void instrFunc(
sqlite3_result_int(context, N);
}
/*
** Implementation of the printf() function.
*/
static void printfFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
PrintfArguments x;
StrAccum str;
const char *zFormat;
int n;
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, 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,
SQLITE_DYNAMIC);
}
}
/*
** Implementation of the substr() function.
**
@@ -1537,11 +1511,11 @@ static void groupConcatStep(
zSep = ",";
nSep = 1;
}
if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
sqlite3StrAccumAppend(pAccum, zSep, nSep);
}
zVal = (char*)sqlite3_value_text(argv[0]);
nVal = sqlite3_value_bytes(argv[0]);
if( nVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
sqlite3StrAccumAppend(pAccum, zVal, nVal);
}
}
static void groupConcatFinalize(sqlite3_context *context){
@@ -1674,7 +1648,6 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(instr, 2, 0, 0, instrFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
FUNCTION(printf, -1, 0, 0, printfFunc ),
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
FUNCTION(char, -1, 0, 0, charFunc ),
FUNCTION(abs, 1, 0, 0, absFunc ),
@@ -1691,8 +1664,8 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
VFUNCTION(random, 0, 0, 0, randomFunc ),
VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(random, 0, 0, 0, randomFunc ),
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -1702,9 +1675,9 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
FUNCTION(quote, 1, 0, 0, quoteFunc ),
VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
VFUNCTION(changes, 0, 0, 0, changes ),
VFUNCTION(total_changes, 0, 0, 0, total_changes ),
FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
FUNCTION(changes, 0, 0, 0, changes ),
FUNCTION(total_changes, 0, 0, 0, total_changes ),
FUNCTION(replace, 3, 0, 0, replaceFunc ),
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
#ifdef SQLITE_SOUNDEX
+1 -1
View File
@@ -148,7 +148,6 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
128, /* szLookaside */
500, /* nLookaside */
{0,0,0,0,0,0,0,0}, /* m */
@@ -184,6 +183,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
#endif
};
/*
** Hash table for global functions - functions common to all
** database connections. After initialization, this table is
+9 -17
View File
@@ -820,7 +820,7 @@ void sqlite3Insert(
/* If this is not a view, open the table and and all indices */
if( !isView ){
int nIdx;
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1, 0,
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1,
&iDataCur, &iIdxCur);
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
if( aRegIdx==0 ){
@@ -1680,19 +1680,16 @@ int sqlite3OpenTableAndIndices(
Table *pTab, /* Table to be opened */
int op, /* OP_OpenRead or OP_OpenWrite */
int iBase, /* Use this for the table cursor, if there is one */
u8 *aToOpen, /* If not NULL: boolean for each table and index */
int *piDataCur, /* Write the database source cursor number here */
int *piIdxCur /* Write the first index cursor number here */
){
int i;
int iDb;
int iDataCur;
Index *pIdx;
Vdbe *v;
assert( op==OP_OpenRead || op==OP_OpenWrite );
if( IsVirtual(pTab) ){
assert( aToOpen==0 );
*piDataCur = 0;
*piIdxCur = 1;
return 0;
@@ -1701,25 +1698,20 @@ int sqlite3OpenTableAndIndices(
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
if( iBase<0 ) iBase = pParse->nTab;
iDataCur = iBase++;
if( piDataCur ) *piDataCur = iDataCur;
if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){
sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op);
if( HasRowid(pTab) ){
*piDataCur = iBase++;
sqlite3OpenTable(pParse, *piDataCur, iDb, pTab, op);
}else{
sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName);
}
if( piIdxCur ) *piIdxCur = iBase;
*piIdxCur = iBase;
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
int iIdxCur = iBase++;
assert( pIdx->pSchema==pTab->pSchema );
if( pIdx->autoIndex==2 && !HasRowid(pTab) && piDataCur ){
*piDataCur = iIdxCur;
}
if( aToOpen==0 || aToOpen[i+1] ){
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "%s", pIdx->zName));
}
if( pIdx->autoIndex==2 && !HasRowid(pTab) ) *piDataCur = iIdxCur;
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "%s", pIdx->zName));
}
if( iBase>pParse->nTab ) pParse->nTab = iBase;
return i;
+11 -35
View File
@@ -515,13 +515,6 @@ int sqlite3_config(int op, ...){
break;
}
#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC)
case SQLITE_CONFIG_WIN32_HEAPSIZE: {
sqlite3GlobalConfig.nHeap = va_arg(ap, int);
break;
}
#endif
default: {
rc = SQLITE_ERROR;
break;
@@ -588,8 +581,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
db->lookaside.bEnabled = 1;
db->lookaside.bMalloced = pBuf==0 ?1:0;
}else{
db->lookaside.pStart = db;
db->lookaside.pEnd = db;
db->lookaside.pEnd = 0;
db->lookaside.bEnabled = 0;
db->lookaside.bMalloced = 0;
}
@@ -987,7 +979,9 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
#endif
sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
sqlite3ValueFree(db->pErr);
if( db->pErr ){
sqlite3ValueFree(db->pErr);
}
sqlite3CloseExtensions(db);
db->magic = SQLITE_MAGIC_ERROR;
@@ -1085,7 +1079,6 @@ const char *sqlite3ErrName(int rc){
case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break;
case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break;
case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break;
case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break;
case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break;
@@ -1370,7 +1363,6 @@ int sqlite3CreateFunc(
){
FuncDef *p;
int nName;
int extraFlags;
assert( sqlite3_mutex_held(db->mutex) );
if( zFunctionName==0 ||
@@ -1381,10 +1373,6 @@ int sqlite3CreateFunc(
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
return SQLITE_MISUSE_BKPT;
}
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
extraFlags = enc & SQLITE_DETERMINISTIC;
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
#ifndef SQLITE_OMIT_UTF16
/* If SQLITE_UTF16 is specified as the encoding type, transform this
@@ -1398,10 +1386,10 @@ int sqlite3CreateFunc(
enc = SQLITE_UTF16NATIVE;
}else if( enc==SQLITE_ANY ){
int rc;
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags,
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8,
pUserData, xFunc, xStep, xFinal, pDestructor);
if( rc==SQLITE_OK ){
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags,
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE,
pUserData, xFunc, xStep, xFinal, pDestructor);
}
if( rc!=SQLITE_OK ){
@@ -1444,8 +1432,7 @@ int sqlite3CreateFunc(
pDestructor->nRef++;
}
p->pDestructor = pDestructor;
p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
testcase( p->funcFlags & SQLITE_DETERMINISTIC );
p->funcFlags &= SQLITE_FUNC_ENCMASK;
p->xFunc = xFunc;
p->xStep = xStep;
p->xFinalize = xFinal;
@@ -1875,7 +1862,6 @@ const char *sqlite3_errmsg(sqlite3 *db){
if( db->mallocFailed ){
z = sqlite3ErrStr(SQLITE_NOMEM);
}else{
testcase( db->pErr==0 );
z = (char*)sqlite3_value_text(db->pErr);
assert( !db->mallocFailed );
if( z==0 ){
@@ -1917,7 +1903,8 @@ const void *sqlite3_errmsg16(sqlite3 *db){
}else{
z = sqlite3_value_text16(db->pErr);
if( z==0 ){
sqlite3Error(db, db->errCode, sqlite3ErrStr(db->errCode));
sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode),
SQLITE_UTF8, SQLITE_STATIC);
z = sqlite3_value_text16(db->pErr);
}
/* A malloc() may have failed within the call to sqlite3_value_text16()
@@ -2631,6 +2618,8 @@ static int openDatabase(
}
#endif
sqlite3Error(db, rc, 0);
/* -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.
@@ -3300,19 +3289,6 @@ int sqlite3_test_control(int op, ...){
}
#endif
/* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
**
** Set or clear a flag that indicates that the database file is always well-
** formed and never corrupt. This flag is clear by default, indicating that
** database files might have arbitrary corruption. Setting the flag during
** testing causes certain assert() statements in the code to be activated
** that demonstrat invariants on well-formed database files.
*/
case SQLITE_TESTCTRL_NEVER_CORRUPT: {
sqlite3Config.neverCorrupt = va_arg(ap, int);
break;
}
}
va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */
+3 -4
View File
@@ -433,7 +433,7 @@ void sqlite3ScratchFree(void *p){
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, void *p){
return p>=db->lookaside.pStart && p<db->lookaside.pEnd;
return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
}
#else
#define isLookaside(A,B) 0
@@ -449,9 +449,8 @@ int sqlite3MallocSize(void *p){
return sqlite3GlobalConfig.m.xSize(p);
}
int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
if( isLookaside(db, p) ){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
if( db && isLookaside(db, p) ){
return db->lookaside.sz;
}else{
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+22 -4
View File
@@ -202,13 +202,32 @@ static void memsys5Leave(void){
static int memsys5Size(void *p){
int iSize = 0;
if( p ){
int i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom);
int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
assert( i>=0 && i<mem5.nBlock );
iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
}
return iSize;
}
/*
** Find the first entry on the freelist iLogsize. Unlink that
** entry and return its index.
*/
static int memsys5UnlinkFirst(int iLogsize){
int i;
int iFirst;
assert( iLogsize>=0 && iLogsize<=LOGMAX );
i = iFirst = mem5.aiFreelist[iLogsize];
assert( iFirst>=0 );
while( i>0 ){
if( i<iFirst ) iFirst = i;
i = MEM5LINK(i)->next;
}
memsys5Unlink(iFirst, iLogsize);
return iFirst;
}
/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable. Return NULL if nBytes==0.
@@ -254,8 +273,7 @@ static void *memsys5MallocUnsafe(int nByte){
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
return 0;
}
i = mem5.aiFreelist[iBin];
memsys5Unlink(i, iBin);
i = memsys5UnlinkFirst(iBin);
while( iBin>iLogsize ){
int newSize;
@@ -289,7 +307,7 @@ static void memsys5FreeUnsafe(void *pOld){
/* Set iBlock to the index of the block pointed to by pOld in
** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
*/
iBlock = (int)(((u8 *)pOld-mem5.zPool)/mem5.szAtom);
iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
/* Check that the pointer pOld points to a valid, non-free block. */
assert( iBlock>=0 && iBlock<mem5.nBlock );
+5 -15
View File
@@ -1315,15 +1315,6 @@ static int findInodeInfo(
return SQLITE_OK;
}
/*
** Return TRUE if pFile has been renamed or unlinked since it was first opened.
*/
static int fileHasMoved(unixFile *pFile){
struct stat buf;
return pFile->pInode!=0 &&
(osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
}
/*
** Check a unixFile that is a database. Verify the following:
@@ -1358,7 +1349,10 @@ static void verifyDbFile(unixFile *pFile){
pFile->ctrlFlags |= UNIXFILE_WARNED;
return;
}
if( fileHasMoved(pFile) ){
if( pFile->pInode!=0
&& ((rc = osStat(pFile->zPath, &buf))!=0
|| buf.st_ino!=pFile->pInode->fileId.ino)
){
sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
pFile->ctrlFlags |= UNIXFILE_WARNED;
return;
@@ -3807,10 +3801,6 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
return SQLITE_OK;
}
case SQLITE_FCNTL_HAS_MOVED: {
*(int*)pArg = fileHasMoved(pFile);
return SQLITE_OK;
}
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
@@ -4091,7 +4081,7 @@ static int unixShmSystemLock(
#ifdef SQLITE_DEBUG
{ u16 mask;
OSTRACE(("SHM-LOCK "));
mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
mask = (1<<(ofst+n)) - (1<<ofst);
if( rc==SQLITE_OK ){
if( lockType==F_UNLCK ){
OSTRACE(("unlock %d ok", ofst));
+34 -87
View File
@@ -59,34 +59,6 @@
must be defined."
#endif
/*
** Define the required Windows SDK version constants if they are not
** already available.
*/
#ifndef NTDDI_WIN8
# define NTDDI_WIN8 0x06020000
#endif
#ifndef NTDDI_WINBLUE
# define NTDDI_WINBLUE 0x06030000
#endif
/*
** Check if the GetVersionEx[AW] functions should be considered deprecated
** and avoid using them in that case. It should be noted here that if the
** value of the SQLITE_WIN32_GETVERSIONEX pre-processor macro is zero
** (whether via this block or via being manually specified), that implies
** the underlying operating system will always be based on the Windows NT
** Kernel.
*/
#ifndef SQLITE_WIN32_GETVERSIONEX
# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
# define SQLITE_WIN32_GETVERSIONEX 0
# else
# define SQLITE_WIN32_GETVERSIONEX 1
# endif
#endif
/*
** This constant should already be defined (in the "WinDef.h" SDK file).
*/
@@ -722,8 +694,7 @@ static struct win_syscall {
#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \
SQLITE_WIN32_GETVERSIONEX
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
#else
{ "GetVersionExA", (SYSCALL)0, 0 },
@@ -732,8 +703,7 @@ static struct win_syscall {
#define osGetVersionExA ((BOOL(WINAPI*)( \
LPOSVERSIONINFOA))aSyscall[34].pCurrent)
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
#else
{ "GetVersionExW", (SYSCALL)0, 0 },
@@ -1290,10 +1260,11 @@ void sqlite3_win32_sleep(DWORD milliseconds){
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
#ifndef NTDDI_WIN8
# define NTDDI_WIN8 0x06020000
#endif
#if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX
# define osIsNT() (1)
#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
#if SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
# define osIsNT() (1)
#elif !defined(SQLITE_WIN32_HAS_WIDE)
# define osIsNT() (0)
@@ -1430,20 +1401,14 @@ static int winMemInit(void *pAppData){
#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
if( !pWinMemData->hHeap ){
DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE;
DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap;
if( dwMaximumSize==0 ){
dwMaximumSize = SQLITE_WIN32_HEAP_MAX_SIZE;
}else if( dwInitialSize>dwMaximumSize ){
dwInitialSize = dwMaximumSize;
}
pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
dwInitialSize, dwMaximumSize);
SQLITE_WIN32_HEAP_INIT_SIZE,
SQLITE_WIN32_HEAP_MAX_SIZE);
if( !pWinMemData->hHeap ){
sqlite3_log(SQLITE_NOMEM,
"failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu",
osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize,
dwMaximumSize);
"failed to HeapCreate (%lu), flags=%u, initSize=%u, maxSize=%u",
osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
return SQLITE_NOMEM;
}
pWinMemData->bOwned = TRUE;
@@ -3119,7 +3084,7 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
case SQLITE_FCNTL_VFSNAME: {
*(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
*(char**)pArg = sqlite3_mprintf("win32");
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
}
@@ -4103,7 +4068,7 @@ static const sqlite3_io_methods winIoMethod = {
** sqlite3_vfs object.
*/
#if defined(__CYGWIN__)
#if 0
/*
** Convert a filename from whatever the underlying operating system
** supports for filenames into UTF-8. Space to hold the result is
@@ -4279,17 +4244,23 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
** be used. However, we may need to convert the string containing
** its name into UTF-8 (i.e. if it is UTF-16 right now).
*/
char *zUtf8 = winConvertToUtf8Filename(zConverted);
if( !zUtf8 ){
if( osIsNT() ){
char *zUtf8 = winUnicodeToUtf8(zConverted);
if( !zUtf8 ){
sqlite3_free(zConverted);
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
}
sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
sqlite3_free(zUtf8);
sqlite3_free(zConverted);
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
break;
}else{
sqlite3_snprintf(nMax, zBuf, "%s", zConverted);
sqlite3_free(zConverted);
break;
}
sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
sqlite3_free(zUtf8);
sqlite3_free(zConverted);
break;
}
sqlite3_free(zConverted);
}
@@ -4974,43 +4945,19 @@ static int winFullPathname(
if( !zOut ){
return SQLITE_IOERR_NOMEM;
}
if( cygwin_conv_path(
(osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) |
CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){
if( cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
pVfs->mxPathname+1)<0 ){
sqlite3_free(zOut);
return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
"winFullPathname1", zRelative);
}else{
char *zUtf8 = winConvertToUtf8Filename(zOut);
if( !zUtf8 ){
sqlite3_free(zOut);
return SQLITE_IOERR_NOMEM;
}
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
sqlite3_data_directory, winGetDirSep(), zUtf8);
sqlite3_free(zUtf8);
sqlite3_free(zOut);
}
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
sqlite3_data_directory, winGetDirSep(), zOut);
sqlite3_free(zOut);
}else{
char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
if( !zOut ){
return SQLITE_IOERR_NOMEM;
}
if( cygwin_conv_path(
(osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A),
zRelative, zOut, pVfs->mxPathname+1)<0 ){
sqlite3_free(zOut);
if( cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull)<0 ){
return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
"winFullPathname2", zRelative);
}else{
char *zUtf8 = winConvertToUtf8Filename(zOut);
if( !zUtf8 ){
sqlite3_free(zOut);
return SQLITE_IOERR_NOMEM;
}
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
sqlite3_free(zUtf8);
sqlite3_free(zOut);
}
}
return SQLITE_OK;
+62 -95
View File
@@ -1024,12 +1024,15 @@ static char *print_pager_state(Pager *p){
static int subjRequiresPage(PgHdr *pPg){
Pager *pPager = pPg->pPager;
PagerSavepoint *p;
Pgno pgno = pPg->pgno;
Pgno pgno;
int i;
for(i=0; i<pPager->nSavepoint; i++){
p = &pPager->aSavepoint[i];
if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
return 1;
if( pPager->nSavepoint ){
pgno = pPg->pgno;
for(i=0; i<pPager->nSavepoint; i++){
p = &pPager->aSavepoint[i];
if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
return 1;
}
}
}
return 0;
@@ -1038,8 +1041,8 @@ static int subjRequiresPage(PgHdr *pPg){
/*
** Return true if the page is already in the journal file.
*/
static int pageInJournal(Pager *pPager, PgHdr *pPg){
return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno);
static int pageInJournal(PgHdr *pPg){
return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
}
/*
@@ -1246,7 +1249,6 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|| len>=nMaster
|| len==0
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|| memcmp(aMagic, aJournalMagic, 8)
@@ -1987,7 +1989,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
PgHdr *p = pager_lookup(pPager, 1);
if( p ){
p->pageHash = 0;
sqlite3PagerUnrefNotNull(p);
sqlite3PagerUnref(p);
}
}
#endif
@@ -2016,11 +2018,6 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
rc = pager_truncate(pPager, pPager->dbSize);
}
if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
}
if( !pPager->exclusiveMode
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){
@@ -2834,7 +2831,7 @@ end_playback:
if( rc==SQLITE_OK
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
rc = sqlite3PagerSync(pPager, 0);
rc = sqlite3PagerSync(pPager);
}
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
@@ -2980,7 +2977,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){
if( rc==SQLITE_OK ){
pPager->xReiniter(pPg);
}
sqlite3PagerUnrefNotNull(pPg);
sqlite3PagerUnref(pPg);
}
}
@@ -4335,7 +4332,7 @@ static int subjournalPage(PgHdr *pPg){
assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
assert( pagerUseWal(pPager)
|| pageInJournal(pPager, pPg)
|| pageInJournal(pPg)
|| pPg->pgno>pPager->dbOrigSize
);
rc = openSubJournal(pPager);
@@ -4800,30 +4797,6 @@ int sqlite3PagerOpen(
}
/* Verify that the database file has not be deleted or renamed out from
** under the pager. Return SQLITE_OK if the database is still were it ought
** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
** code from sqlite3OsAccess()) if the database has gone missing.
*/
static int databaseIsUnmoved(Pager *pPager){
int bHasMoved = 0;
int rc;
if( pPager->tempFile ) return SQLITE_OK;
if( pPager->dbSize==0 ) return SQLITE_OK;
assert( pPager->zFilename && pPager->zFilename[0] );
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
if( rc==SQLITE_NOTFOUND ){
/* If the HAS_MOVED file-control is unimplemented, assume that the file
** has not been moved. That is the historical behavior of SQLite: prior to
** version 3.8.3, it never checked */
rc = SQLITE_OK;
}else if( rc==SQLITE_OK && bHasMoved ){
rc = SQLITE_READONLY_DBMOVED;
}
return rc;
}
/*
** This function is called after transitioning from PAGER_UNLOCK to
@@ -5295,7 +5268,7 @@ int sqlite3PagerAcquire(
if( rc!=SQLITE_OK ) goto pager_acquire_err;
}
if( bMmapOk && iFrame==0 ){
if( iFrame==0 && bMmapOk ){
void *pData = 0;
rc = sqlite3OsFetch(pPager->fd,
@@ -5436,19 +5409,16 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
** are released, a rollback occurs and the lock on the database is
** removed.
*/
void sqlite3PagerUnrefNotNull(DbPage *pPg){
Pager *pPager;
assert( pPg!=0 );
pPager = pPg->pPager;
if( pPg->flags & PGHDR_MMAP ){
pagerReleaseMapPage(pPg);
}else{
sqlite3PcacheRelease(pPg);
}
pagerUnlockIfUnused(pPager);
}
void sqlite3PagerUnref(DbPage *pPg){
if( pPg ) sqlite3PagerUnrefNotNull(pPg);
if( pPg ){
Pager *pPager = pPg->pPager;
if( pPg->flags & PGHDR_MMAP ){
pagerReleaseMapPage(pPg);
}else{
sqlite3PcacheRelease(pPg);
}
pagerUnlockIfUnused(pPager);
}
}
/*
@@ -5503,19 +5473,13 @@ static int pager_open_journal(Pager *pPager){
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
(SQLITE_OPEN_MAIN_JOURNAL)
);
/* Verify that the database still has the same name as it did when
** it was originally opened. */
rc = databaseIsUnmoved(pPager);
if( rc==SQLITE_OK ){
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
rc = sqlite3JournalOpen(
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
);
#else
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
#endif
}
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
rc = sqlite3JournalOpen(
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
);
#else
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
#endif
}
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
}
@@ -5636,9 +5600,9 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
** of any open savepoints as appropriate.
*/
static int pager_write(PgHdr *pPg){
void *pData = pPg->pData;
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
int inJournal;
/* This routine is not called unless a write-transaction has already
** been started. The journal file may or may not be open at this point.
@@ -5649,8 +5613,14 @@ static int pager_write(PgHdr *pPg){
|| pPager->eState==PAGER_WRITER_DBMOD
);
assert( assert_pager_state(pPager) );
assert( pPager->errCode==0 );
assert( pPager->readOnly==0 );
/* If an error has been previously detected, report the same error
** again. This should not happen, but the check provides robustness. */
if( NEVER(pPager->errCode) ) return pPager->errCode;
/* Higher-level routines never call this function if database is not
** writable. But check anyway, just for robustness. */
if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
CHECK_PAGE(pPg);
@@ -5674,8 +5644,7 @@ static int pager_write(PgHdr *pPg){
** to the journal then we can return right away.
*/
sqlite3PcacheMakeDirty(pPg);
inJournal = pageInJournal(pPager, pPg);
if( inJournal && (pPager->nSavepoint==0 || !subjRequiresPage(pPg)) ){
if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
assert( !pagerUseWal(pPager) );
}else{
@@ -5683,7 +5652,7 @@ static int pager_write(PgHdr *pPg){
** EXCLUSIVE lock on the main database file. Write the current page to
** the transaction journal if it is not there already.
*/
if( !inJournal && !pagerUseWal(pPager) ){
if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
assert( pagerUseWal(pPager)==0 );
if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
u32 cksum;
@@ -5696,7 +5665,7 @@ static int pager_write(PgHdr *pPg){
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
assert( pPager->journalHdr<=pPager->journalOff );
CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
cksum = pager_cksum(pPager, (u8*)pData2);
/* Even if an IO or diskfull error occurs while journalling the
@@ -5748,7 +5717,7 @@ static int pager_write(PgHdr *pPg){
** the statement journal format differs from the standard journal format
** in that it omits the checksums and the header.
*/
if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){
if( subjRequiresPage(pPg) ){
rc = subjournalPage(pPg);
}
}
@@ -5780,19 +5749,19 @@ int sqlite3PagerWrite(DbPage *pDbPage){
PgHdr *pPg = pDbPage;
Pager *pPager = pPg->pPager;
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
assert( (pPg->flags & PGHDR_MMAP)==0 );
assert( pPager->eState>=PAGER_WRITER_LOCKED );
assert( pPager->eState!=PAGER_ERROR );
assert( assert_pager_state(pPager) );
if( pPager->sectorSize > (u32)pPager->pageSize ){
if( nPagePerSector>1 ){
Pgno nPageCount; /* Total number of pages in database file */
Pgno pg1; /* First page of the sector pPg is located on. */
int nPage = 0; /* Number of pages starting at pg1 to journal */
int ii; /* Loop counter */
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
/* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
** a journal header to be written between the pages journaled by
@@ -5831,14 +5800,14 @@ int sqlite3PagerWrite(DbPage *pDbPage){
if( pPage->flags&PGHDR_NEED_SYNC ){
needSync = 1;
}
sqlite3PagerUnrefNotNull(pPage);
sqlite3PagerUnref(pPage);
}
}
}else if( (pPage = pager_lookup(pPager, pg))!=0 ){
if( pPage->flags&PGHDR_NEED_SYNC ){
needSync = 1;
}
sqlite3PagerUnrefNotNull(pPage);
sqlite3PagerUnref(pPage);
}
}
@@ -5854,7 +5823,7 @@ int sqlite3PagerWrite(DbPage *pDbPage){
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
if( pPage ){
pPage->flags |= PGHDR_NEED_SYNC;
sqlite3PagerUnrefNotNull(pPage);
sqlite3PagerUnref(pPage);
}
}
}
@@ -6007,17 +5976,17 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
** If successful, or if called on a pager for which it is a no-op, this
** function returns SQLITE_OK. Otherwise, an IO error code is returned.
*/
int sqlite3PagerSync(Pager *pPager, const char *zMaster){
int sqlite3PagerSync(Pager *pPager){
int rc = SQLITE_OK;
if( isOpen(pPager->fd) ){
void *pArg = (void*)zMaster;
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
}
if( rc==SQLITE_OK && !pPager->noSync ){
if( !pPager->noSync ){
assert( !MEMDB );
rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
}else if( isOpen(pPager->fd) ){
assert( !MEMDB );
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
if( rc==SQLITE_NOTFOUND ){
rc = SQLITE_OK;
}
}
return rc;
}
@@ -6216,7 +6185,7 @@ int sqlite3PagerCommitPhaseOne(
/* Finally, sync the database file. */
if( !noSync ){
rc = sqlite3PagerSync(pPager, zMaster);
rc = sqlite3PagerSync(pPager);
}
IOTRACE(("DBSYNC %p\n", pPager))
}
@@ -6345,9 +6314,7 @@ int sqlite3PagerRollback(Pager *pPager){
assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
|| rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR
|| rc==SQLITE_CANTOPEN
);
|| rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
/* If an error occurs during a ROLLBACK, we can no longer trust the pager
** cache. So call pager_error() on the way out to make any error persistent.
@@ -6750,7 +6717,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
needSyncPgno = pPg->pgno;
assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize );
pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
assert( pPg->flags&PGHDR_DIRTY );
}
@@ -6784,7 +6751,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
if( MEMDB ){
assert( pPgOld );
sqlite3PcacheMove(pPgOld, origPgno);
sqlite3PagerUnrefNotNull(pPgOld);
sqlite3PagerUnref(pPgOld);
}
if( needSyncPgno ){
@@ -6813,7 +6780,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
}
pPgHdr->flags |= PGHDR_NEED_SYNC;
sqlite3PcacheMakeDirty(pPgHdr);
sqlite3PagerUnrefNotNull(pPgHdr);
sqlite3PagerUnref(pPgHdr);
}
return SQLITE_OK;
+1 -2
View File
@@ -136,7 +136,6 @@ int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
void sqlite3PagerRef(DbPage*);
void sqlite3PagerUnref(DbPage*);
void sqlite3PagerUnrefNotNull(DbPage*);
/* Operations on page references. */
int sqlite3PagerWrite(DbPage*);
@@ -151,7 +150,7 @@ void sqlite3PagerPagecount(Pager*, int*);
int sqlite3PagerBegin(Pager*, int exFlag, int);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
int sqlite3PagerExclusiveLock(Pager*);
int sqlite3PagerSync(Pager *pPager, const char *zMaster);
int sqlite3PagerSync(Pager *pPager);
int sqlite3PagerCommitPhaseTwo(Pager*);
int sqlite3PagerRollback(Pager*);
int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
+6 -1
View File
@@ -854,7 +854,12 @@ expr(A) ::= ID(X) LP STAR RP(E). {
spanSet(&A,&X,&E);
}
term(A) ::= CTIME_KW(OP). {
A.pExpr = sqlite3ExprFunction(pParse, 0, &OP);
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
** treated as functions that return constants */
A.pExpr = sqlite3ExprFunction(pParse, 0,&OP);
if( A.pExpr ){
A.pExpr->op = TK_CONST_FUNC;
}
spanSet(&A, &OP, &OP);
}
+22 -31
View File
@@ -96,7 +96,6 @@ struct PCache1 {
struct PgHdr1 {
sqlite3_pcache_page page;
unsigned int iKey; /* Key value (page number) */
u8 isPinned; /* Page in use, not on the LRU list */
PgHdr1 *pNext; /* Next in hash table chain */
PCache1 *pCache; /* Cache that currently owns this page */
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
@@ -425,32 +424,34 @@ static int pcache1ResizeHash(PCache1 *p){
** LRU list, then this function is a no-op.
**
** The PGroup mutex must be held when this function is called.
**
** If pPage is NULL then this routine is a no-op.
*/
static void pcache1PinPage(PgHdr1 *pPage){
PCache1 *pCache;
PGroup *pGroup;
assert( pPage!=0 );
assert( pPage->isPinned==0 );
if( pPage==0 ) return;
pCache = pPage->pCache;
pGroup = pCache->pGroup;
assert( pPage->pLruNext || pPage==pGroup->pLruTail );
assert( pPage->pLruPrev || pPage==pGroup->pLruHead );
assert( sqlite3_mutex_held(pGroup->mutex) );
if( pPage->pLruPrev ){
pPage->pLruPrev->pLruNext = pPage->pLruNext;
}else{
pGroup->pLruHead = pPage->pLruNext;
if( pPage->pLruNext || pPage==pGroup->pLruTail ){
if( pPage->pLruPrev ){
pPage->pLruPrev->pLruNext = pPage->pLruNext;
}
if( pPage->pLruNext ){
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
}
if( pGroup->pLruHead==pPage ){
pGroup->pLruHead = pPage->pLruNext;
}
if( pGroup->pLruTail==pPage ){
pGroup->pLruTail = pPage->pLruPrev;
}
pPage->pLruNext = 0;
pPage->pLruPrev = 0;
pPage->pCache->nRecyclable--;
}
if( pPage->pLruNext ){
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
}else{
pGroup->pLruTail = pPage->pLruPrev;
}
pPage->pLruNext = 0;
pPage->pLruPrev = 0;
pPage->isPinned = 1;
pCache->nRecyclable--;
}
@@ -482,7 +483,6 @@ static void pcache1EnforceMaxPage(PGroup *pGroup){
while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
PgHdr1 *p = pGroup->pLruTail;
assert( p->pCache->pGroup==pGroup );
assert( p->isPinned==0 );
pcache1PinPage(p);
pcache1RemoveFromHash(p);
pcache1FreePage(p);
@@ -510,7 +510,7 @@ static void pcache1TruncateUnsafe(
if( pPage->iKey>=iLimit ){
pCache->nPage--;
*pp = pPage->pNext;
if( !pPage->isPinned ) pcache1PinPage(pPage);
pcache1PinPage(pPage);
pcache1FreePage(pPage);
}else{
pp = &pPage->pNext;
@@ -733,11 +733,8 @@ static sqlite3_pcache_page *pcache1Fetch(
}
/* Step 2: Abort if no existing page is found and createFlag is 0 */
if( pPage ){
if( !pPage->isPinned ) pcache1PinPage(pPage);
goto fetch_out;
}
if( createFlag==0 ){
if( pPage || createFlag==0 ){
pcache1PinPage(pPage);
goto fetch_out;
}
@@ -778,7 +775,6 @@ static sqlite3_pcache_page *pcache1Fetch(
)){
PCache1 *pOther;
pPage = pGroup->pLruTail;
assert( pPage->isPinned==0 );
pcache1RemoveFromHash(pPage);
pcache1PinPage(pPage);
pOther = pPage->pCache;
@@ -815,7 +811,6 @@ static sqlite3_pcache_page *pcache1Fetch(
pPage->pCache = pCache;
pPage->pLruPrev = 0;
pPage->pLruNext = 0;
pPage->isPinned = 1;
*(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage;
}
@@ -851,7 +846,6 @@ static void pcache1Unpin(
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
assert( pPage->isPinned==1 );
if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
pcache1RemoveFromHash(pPage);
@@ -867,7 +861,6 @@ static void pcache1Unpin(
pGroup->pLruHead = pPage;
}
pCache->nRecyclable++;
pPage->isPinned = 0;
}
pcache1LeaveMutex(pCache->pGroup);
@@ -994,7 +987,6 @@ int sqlite3PcacheReleaseMemory(int nReq){
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
nFree += sqlite3MemSize(p);
#endif
assert( p->isPinned==0 );
pcache1PinPage(p);
pcache1RemoveFromHash(p);
pcache1FreePage(p);
@@ -1019,7 +1011,6 @@ void sqlite3PcacheStats(
PgHdr1 *p;
int nRecyclable = 0;
for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
assert( p->isPinned==0 );
nRecyclable++;
}
*pnCurrent = pcache1.grp.nCurrentPage;
+1 -1
View File
@@ -1891,7 +1891,7 @@ void sqlite3Pragma(
sqlite3VdbeJumpHere(v, addr);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead,
1, 0, &iDataCur, &iIdxCur);
1, &iDataCur, &iIdxCur);
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
-8
View File
@@ -524,13 +524,6 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
return i;
}
/*
** Free all memory allocations in the pParse object
*/
void sqlite3ParserReset(Parse *pParse){
if( pParse ) sqlite3ExprListDelete(pParse->db, pParse->pConstExpr);
}
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
@@ -688,7 +681,6 @@ static int sqlite3Prepare(
end_prepare:
sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
+42 -117
View File
@@ -148,31 +148,6 @@ void sqlite3AppendSpace(StrAccum *pAccum, int N){
}
}
/*
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
p->accError = eError;
p->nAlloc = 0;
}
/*
** Extra argument values from a PrintfArguments object
*/
static sqlite3_int64 getIntArg(PrintfArguments *p){
if( p->nArg<=p->nUsed ) return 0;
return sqlite3_value_int64(p->apArg[p->nUsed++]);
}
static double getDoubleArg(PrintfArguments *p){
if( p->nArg<=p->nUsed ) return 0.0;
return sqlite3_value_double(p->apArg[p->nUsed++]);
}
static char *getTextArg(PrintfArguments *p){
if( p->nArg<=p->nUsed ) return 0;
return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
}
/*
** On machines with a small stack size, you can redefine the
** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
@@ -186,10 +161,10 @@ static char *getTextArg(PrintfArguments *p){
** Render a string given by "fmt" into the StrAccum object.
*/
void sqlite3VXPrintf(
StrAccum *pAccum, /* Accumulate results here */
u32 bFlags, /* SQLITE_PRINTF_* flags */
const char *fmt, /* Format string */
va_list ap /* arguments */
StrAccum *pAccum, /* Accumulate results here */
int useExtended, /* Allow extended %-conversions */
const char *fmt, /* Format string */
va_list ap /* arguments */
){
int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */
@@ -207,8 +182,6 @@ void sqlite3VXPrintf(
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
etByte xtype = 0; /* Conversion paradigm */
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
u8 useIntern; /* Ok to use internal conversions (ex: %T) */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
sqlite_uint64 longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
@@ -223,18 +196,9 @@ void sqlite3VXPrintf(
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
#endif
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
char buf[etBUFSIZE]; /* Conversion buffer */
bufpt = 0;
if( bFlags ){
if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
pArgList = va_arg(ap, PrintfArguments*);
}
useIntern = bFlags & SQLITE_PRINTF_INTERNAL;
}else{
bArgList = useIntern = 0;
}
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
int amt;
@@ -266,11 +230,7 @@ void sqlite3VXPrintf(
/* Get the field width */
width = 0;
if( c=='*' ){
if( bArgList ){
width = (int)getIntArg(pArgList);
}else{
width = va_arg(ap,int);
}
width = va_arg(ap,int);
if( width<0 ){
flag_leftjustify = 1;
width = -width;
@@ -287,11 +247,7 @@ void sqlite3VXPrintf(
precision = 0;
c = *++fmt;
if( c=='*' ){
if( bArgList ){
precision = (int)getIntArg(pArgList);
}else{
precision = va_arg(ap,int);
}
precision = va_arg(ap,int);
if( precision<0 ) precision = -precision;
c = *++fmt;
}else{
@@ -322,7 +278,7 @@ void sqlite3VXPrintf(
for(idx=0; idx<ArraySize(fmtinfo); idx++){
if( c==fmtinfo[idx].fmttype ){
infop = &fmtinfo[idx];
if( useIntern || (infop->flags & FLAG_INTERN)==0 ){
if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
xtype = infop->type;
}else{
return;
@@ -362,9 +318,7 @@ void sqlite3VXPrintf(
case etRADIX:
if( infop->flags & FLAG_SIGNED ){
i64 v;
if( bArgList ){
v = getIntArg(pArgList);
}else if( flag_longlong ){
if( flag_longlong ){
v = va_arg(ap,i64);
}else if( flag_long ){
v = va_arg(ap,long int);
@@ -385,9 +339,7 @@ void sqlite3VXPrintf(
else prefix = 0;
}
}else{
if( bArgList ){
longvalue = (u64)getIntArg(pArgList);
}else if( flag_longlong ){
if( flag_longlong ){
longvalue = va_arg(ap,u64);
}else if( flag_long ){
longvalue = va_arg(ap,unsigned long int);
@@ -407,7 +359,7 @@ void sqlite3VXPrintf(
nOut = precision + 10;
zOut = zExtra = sqlite3Malloc( nOut );
if( zOut==0 ){
setStrAccumError(pAccum, STRACCUM_NOMEM);
pAccum->accError = STRACCUM_NOMEM;
return;
}
}
@@ -447,11 +399,7 @@ void sqlite3VXPrintf(
case etFLOAT:
case etEXP:
case etGENERIC:
if( bArgList ){
realvalue = getDoubleArg(pArgList);
}else{
realvalue = va_arg(ap,double);
}
realvalue = va_arg(ap,double);
#ifdef SQLITE_OMIT_FLOATING_POINT
length = 0;
#else
@@ -523,7 +471,7 @@ void sqlite3VXPrintf(
if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
if( bufpt==0 ){
setStrAccumError(pAccum, STRACCUM_NOMEM);
pAccum->accError = STRACCUM_NOMEM;
return;
}
}
@@ -606,9 +554,7 @@ void sqlite3VXPrintf(
#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
break;
case etSIZE:
if( !bArgList ){
*(va_arg(ap,int*)) = pAccum->nChar;
}
*(va_arg(ap,int*)) = pAccum->nChar;
length = width = 0;
break;
case etPERCENT:
@@ -617,12 +563,7 @@ void sqlite3VXPrintf(
length = 1;
break;
case etCHARX:
if( bArgList ){
bufpt = getTextArg(pArgList);
c = bufpt ? bufpt[0] : 0;
}else{
c = va_arg(ap,int);
}
c = va_arg(ap,int);
buf[0] = (char)c;
if( precision>=0 ){
for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
@@ -634,14 +575,10 @@ void sqlite3VXPrintf(
break;
case etSTRING:
case etDYNSTRING:
if( bArgList ){
bufpt = getTextArg(pArgList);
}else{
bufpt = va_arg(ap,char*);
}
bufpt = va_arg(ap,char*);
if( bufpt==0 ){
bufpt = "";
}else if( xtype==etDYNSTRING && !bArgList ){
}else if( xtype==etDYNSTRING ){
zExtra = bufpt;
}
if( precision>=0 ){
@@ -657,13 +594,7 @@ void sqlite3VXPrintf(
int needQuote;
char ch;
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg;
if( bArgList ){
escarg = getTextArg(pArgList);
}else{
escarg = va_arg(ap,char*);
}
char *escarg = va_arg(ap,char*);
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
k = precision;
@@ -675,7 +606,7 @@ void sqlite3VXPrintf(
if( n>etBUFSIZE ){
bufpt = zExtra = sqlite3Malloc( n );
if( bufpt==0 ){
setStrAccumError(pAccum, STRACCUM_NOMEM);
pAccum->accError = STRACCUM_NOMEM;
return;
}
}else{
@@ -698,8 +629,7 @@ void sqlite3VXPrintf(
}
case etTOKEN: {
Token *pToken = va_arg(ap, Token*);
assert( bArgList==0 );
if( pToken && pToken->n ){
if( pToken ){
sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
}
length = width = 0;
@@ -709,13 +639,12 @@ void sqlite3VXPrintf(
SrcList *pSrc = va_arg(ap, SrcList*);
int k = va_arg(ap, int);
struct SrcList_item *pItem = &pSrc->a[k];
assert( bArgList==0 );
assert( k>=0 && k<pSrc->nSrc );
if( pItem->zDatabase ){
sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase);
sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
sqlite3StrAccumAppend(pAccum, ".", 1);
}
sqlite3StrAccumAppendAll(pAccum, pItem->zName);
sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
length = width = 0;
break;
}
@@ -746,7 +675,7 @@ void sqlite3VXPrintf(
sqlite3AppendSpace(pAccum, nspace);
}
}
if( zExtra ) sqlite3_free(zExtra);
sqlite3_free(zExtra);
}/* End for loop over the format string */
} /* End of function */
@@ -754,20 +683,22 @@ void sqlite3VXPrintf(
** Append N bytes of text from z to the StrAccum object.
*/
void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( z!=0 );
assert( p->zText!=0 || p->nChar==0 || p->accError );
assert( N>=0 );
assert( p->accError==0 || p->nAlloc==0 );
assert( z!=0 || N==0 );
if( p->accError ){
testcase(p->accError==STRACCUM_TOOBIG);
testcase(p->accError==STRACCUM_NOMEM);
return;
}
assert( p->zText!=0 || p->nChar==0 );
if( N<=0 ){
if( N==0 || z[0]==0 ) return;
N = sqlite3Strlen30(z);
}
if( p->nChar+N >= p->nAlloc ){
char *zNew;
if( p->accError ){
testcase(p->accError==STRACCUM_TOOBIG);
testcase(p->accError==STRACCUM_NOMEM);
return;
}
if( !p->useMalloc ){
p->accError = STRACCUM_TOOBIG;
N = p->nAlloc - p->nChar - 1;
setStrAccumError(p, STRACCUM_TOOBIG);
if( N<=0 ){
return;
}
@@ -777,7 +708,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
szNew += N + 1;
if( szNew > p->mxAlloc ){
sqlite3StrAccumReset(p);
setStrAccumError(p, STRACCUM_TOOBIG);
p->accError = STRACCUM_TOOBIG;
return;
}else{
p->nAlloc = (int)szNew;
@@ -791,8 +722,8 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
p->zText = zNew;
}else{
p->accError = STRACCUM_NOMEM;
sqlite3StrAccumReset(p);
setStrAccumError(p, STRACCUM_NOMEM);
return;
}
}
@@ -802,14 +733,6 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
p->nChar += N;
}
/*
** Append the complete text of zero-terminated string z[] to the p string.
*/
void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z));
}
/*
** Finish off a string by making sure it is zero-terminated.
** Return a pointer to the resulting string. Return a NULL
@@ -827,7 +750,7 @@ char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
setStrAccumError(p, STRACCUM_NOMEM);
p->accError = STRACCUM_NOMEM;
}
}
}
@@ -873,7 +796,7 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
acc.db = db;
sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap);
sqlite3VXPrintf(&acc, 1, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.accError==STRACCUM_NOMEM ){
db->mallocFailed = 1;
@@ -1029,12 +952,14 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
}
#endif
#ifndef SQLITE_OMIT_TRACE
/*
** variable-argument wrapper around sqlite3VXPrintf().
*/
void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){
void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
va_list ap;
va_start(ap,zFormat);
sqlite3VXPrintf(p, bFlags, zFormat, ap);
sqlite3VXPrintf(p, 1, zFormat, ap);
va_end(ap);
}
#endif
+16 -17
View File
@@ -108,10 +108,10 @@ static void resolveAlias(
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
if( pDup==0 ) return;
ExprSetProperty(pDup, EP_Skip);
if( pEList->a[iCol].u.x.iAlias==0 ){
pEList->a[iCol].u.x.iAlias = (u16)(++pParse->nAlias);
if( pEList->a[iCol].iAlias==0 ){
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
}
pDup->iTable = pEList->a[iCol].u.x.iAlias;
pDup->iTable = pEList->a[iCol].iAlias;
}
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
@@ -352,9 +352,7 @@ static int lookupName(
}
}
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
/* IMP: R-24309-18625 */
/* IMP: R-44911-55124 */
iCol = -1;
iCol = -1; /* IMP: R-44911-55124 */
}
if( iCol<pTab->nCol ){
cnt++;
@@ -669,6 +667,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
/* Resolve function names
*/
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pList = pExpr->x.pList; /* The argument list */
int n = pList ? pList->nExpr : 0; /* Number of arguments */
@@ -681,6 +680,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
testcase( pExpr->op==TK_CONST_FUNC );
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
notValidPartIdxWhere(pParse, pNC, "functions");
zId = pExpr->u.zToken;
@@ -725,7 +725,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pExpr->op = TK_NULL;
return WRC_Prune;
}
if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant);
}
#endif
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
@@ -977,7 +976,7 @@ static int resolveCompoundOrderBy(
pItem->pExpr->pLeft = pNew;
}
sqlite3ExprDelete(db, pE);
pItem->u.x.iOrderByCol = (u16)iCol;
pItem->iOrderByCol = (u16)iCol;
pItem->done = 1;
}else{
moreToDo = 1;
@@ -998,8 +997,8 @@ static int resolveCompoundOrderBy(
/*
** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
** the SELECT statement pSelect. If any term is reference to a
** result set expression (as determined by the ExprList.a.u.x.iOrderByCol
** field) then convert that term into a copy of the corresponding result set
** result set expression (as determined by the ExprList.a.iOrderByCol field)
** then convert that term into a copy of the corresponding result set
** column.
**
** If any errors are detected, add an error message to pParse and
@@ -1026,12 +1025,12 @@ int sqlite3ResolveOrderGroupBy(
pEList = pSelect->pEList;
assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
if( pItem->u.x.iOrderByCol ){
if( pItem->u.x.iOrderByCol>pEList->nExpr ){
if( pItem->iOrderByCol ){
if( pItem->iOrderByCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
return 1;
}
resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0);
resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0);
}
}
return 0;
@@ -1080,7 +1079,7 @@ static int resolveOrderGroupBy(
** a copy of the iCol-th result-set column. The subsequent call to
** sqlite3ResolveOrderGroupBy() will convert the expression to a
** copy of the iCol-th result-set expression. */
pItem->u.x.iOrderByCol = (u16)iCol;
pItem->iOrderByCol = (u16)iCol;
continue;
}
}
@@ -1092,18 +1091,18 @@ static int resolveOrderGroupBy(
resolveOutOfRangeError(pParse, zType, i+1, nResult);
return 1;
}
pItem->u.x.iOrderByCol = (u16)iCol;
pItem->iOrderByCol = (u16)iCol;
continue;
}
/* Otherwise, treat the ORDER BY term as an ordinary expression */
pItem->u.x.iOrderByCol = 0;
pItem->iOrderByCol = 0;
if( sqlite3ResolveExprNames(pNC, pE) ){
return 1;
}
for(j=0; j<pSelect->pEList->nExpr; j++){
if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
pItem->u.x.iOrderByCol = j+1;
pItem->iOrderByCol = j+1;
}
}
}
+10 -12
View File
@@ -599,8 +599,7 @@ static void selectInnerLoop(
** values returned by the SELECT are not required.
*/
sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pEList, regResult,
(eDest==SRT_Output)?SQLITE_ECEL_DUP:0);
sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
}
nColumn = nResultCol;
@@ -2373,8 +2372,8 @@ static int multiSelectOrderBy(
for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
struct ExprList_item *pItem;
for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
assert( pItem->u.x.iOrderByCol>0 );
if( pItem->u.x.iOrderByCol==i ) break;
assert( pItem->iOrderByCol>0 );
if( pItem->iOrderByCol==i ) break;
}
if( j==nOrderBy ){
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
@@ -2382,7 +2381,7 @@ static int multiSelectOrderBy(
pNew->flags |= EP_IntValue;
pNew->u.iValue = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i;
if( pOrderBy ) pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i;
}
}
}
@@ -2398,9 +2397,8 @@ static int multiSelectOrderBy(
if( aPermute ){
struct ExprList_item *pItem;
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
assert( pItem->u.x.iOrderByCol>0
&& pItem->u.x.iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->iOrderByCol - 1;
}
pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1);
if( pKeyMerge ){
@@ -2980,7 +2978,7 @@ static int flattenSubquery(
if( p->pOrderBy ){
int ii;
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
if( p->pOrderBy->a[ii].iOrderByCol==0 ) return 0;
}
}
}
@@ -3886,7 +3884,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP);
sqlite3ExprCodeExprList(pParse, pList, regAgg, 1);
}else{
nArg = 0;
regAgg = 0;
@@ -4387,10 +4385,10 @@ int sqlite3Select(
struct ExprList_item *pItem; /* For looping over expression in a list */
for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
pItem->u.x.iAlias = 0;
pItem->iAlias = 0;
}
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
pItem->u.x.iAlias = 0;
pItem->iAlias = 0;
}
if( p->nSelectRow>100 ) p->nSelectRow = 100;
}else{
+25 -30
View File
@@ -466,7 +466,6 @@ struct callback_data {
FILE *pLog; /* Write log output here */
int *aiIndent; /* Array of indents used in MODE_Explain */
int nIndent; /* Size of array aiIndent[] */
int iIndent; /* Index of current op in aiIndent[] */
};
/*
@@ -772,10 +771,10 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
w = strlen30(azArg[i]);
}
if( i==1 && p->aiIndent && p->pStmt ){
if( p->iIndent<p->nIndent ){
fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
int iOp = sqlite3_column_int(p->pStmt, 0);
if( iOp<p->nIndent ){
fprintf(p->out, "%*.s", p->aiIndent[iOp], "");
}
p->iIndent++;
}
if( w<0 ){
fprintf(p->out,"%*.*s%s",-w,-w,
@@ -1174,10 +1173,9 @@ static int str_in_array(const char *zStr, const char **azArray){
** all opcodes that occur between the p2 jump destination and the opcode
** itself by 2 spaces.
**
** * For each "Goto", if the jump destination is earlier in the program
** and ends on one of:
** Yield SeekGt SeekLt RowSetRead
** then indent all opcodes between the earlier instruction
** * For each "Goto", if the jump destination is a "Yield", "SeekGt",
** or "SeekLt" instruction that occurs earlier in the program than
** the Goto itself, indent all opcodes between the earlier instruction
** and "Goto" by 2 spaces.
*/
static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
@@ -1185,10 +1183,10 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
const char *z; /* Used to check if this is an EXPLAIN */
int *abYield = 0; /* True if op is an OP_Yield */
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
int iOp; /* Index of operation in p->aiIndent[] */
int iOp;
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", 0 };
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", 0 };
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", 0 };
const char *azGoto[] = { "Goto", 0 };
/* Try to figure out if this is really an EXPLAIN statement. If this
@@ -1200,16 +1198,8 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
int i;
int iAddr = sqlite3_column_int(pSql, 0);
const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
/* Set p2 to the P2 field of the current opcode. Then, assuming that
** p2 is an instruction address, set variable p2op to the index of that
** instruction in the aiIndent[] array. p2 and p2op may be different if
** the current instruction is part of a sub-program generated by an
** SQL trigger or foreign key. */
int p2 = sqlite3_column_int(pSql, 3);
int p2op = (p2 + (iOp-iAddr));
/* Grow the p->aiIndent array as required */
if( iOp>=nAlloc ){
@@ -1222,14 +1212,13 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
p->nIndent = iOp+1;
if( str_in_array(zOp, azNext) ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
for(i=p2; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
if( str_in_array(zOp, azGoto) && p2<p->nIndent && abYield[p2] ){
for(i=p2+1; i<iOp; i++) p->aiIndent[i] += 2;
}
}
p->iIndent = 0;
sqlite3_free(abYield);
sqlite3_reset(pSql);
}
@@ -1241,7 +1230,6 @@ static void explain_data_delete(struct callback_data *p){
sqlite3_free(p->aiIndent);
p->aiIndent = 0;
p->nIndent = 0;
p->iIndent = 0;
}
/*
@@ -1307,7 +1295,7 @@ static int shell_exec(
/* If the shell is currently in ".explain" mode, gather the extra
** data required to add indents to the output.*/
if( pArg && pArg->mode==MODE_Explain ){
if( pArg->mode==MODE_Explain ){
explain_data_prepare(pArg, pStmt);
}
@@ -1603,6 +1591,11 @@ static char zTimerHelp[] =
/* Forward reference */
static int process_input(struct callback_data *p, FILE *in);
/* Include the source code for various extensions when in debug mode: */
#ifdef SQLITE_DEBUG
# include "test_schema2.c"
#endif
/*
** Make sure the database is open. If it is not, then open it. If
** the database fails to open, print an error message and exit.
@@ -1624,6 +1617,9 @@ static void open_db(struct callback_data *p, int keepAlive){
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
#ifdef SQLITE_DEBUG
sqlite3_schema2_register(p->db);
#endif
}
}
@@ -1836,7 +1832,7 @@ static void csv_append_char(CSVReader *p, int c){
** + Report syntax errors on stderr
*/
static char *csv_read_one_field(CSVReader *p){
int c, pc, ppc;
int c, pc;
int cSep = p->cSeparator;
p->n = 0;
c = fgetc(p->in);
@@ -1847,7 +1843,7 @@ static char *csv_read_one_field(CSVReader *p){
if( c=='"' ){
int startLine = p->nLine;
int cQuote = c;
pc = ppc = 0;
pc = 0;
while( 1 ){
c = fgetc(p->in);
if( c=='\n' ) p->nLine++;
@@ -1859,7 +1855,7 @@ static char *csv_read_one_field(CSVReader *p){
}
if( (c==cSep && pc==cQuote)
|| (c=='\n' && pc==cQuote)
|| (c=='\n' && pc=='\r' && ppc==cQuote)
|| (c=='\n' && pc=='\r' && p->n>=2 && p->z[p->n-2]==cQuote)
|| (c==EOF && pc==cQuote)
){
do{ p->n--; }while( p->z[p->n]!=cQuote );
@@ -1877,7 +1873,6 @@ static char *csv_read_one_field(CSVReader *p){
break;
}
csv_append_char(p, c);
ppc = pc;
pc = c;
}
}else{
@@ -2097,7 +2092,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
*/
p->mode = MODE_Explain;
p->showHeader = 1;
memset(p->colWidth,0,sizeof(p->colWidth));
memset(p->colWidth,0,ArraySize(p->colWidth));
p->colWidth[0] = 4; /* addr */
p->colWidth[1] = 13; /* opcode */
p->colWidth[2] = 4; /* P1 */
+34 -86
View File
@@ -365,7 +365,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** <ul>
** <li> The application must insure that the 1st parameter to sqlite3_exec()
** is a valid and open [database connection].
** <li> The application must not close the [database connection] specified by
** <li> The application must not close [database connection] specified by
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
@@ -442,7 +442,7 @@ int sqlite3_exec(
** [sqlite3_extended_result_codes()] API.
**
** Some of the available extended result codes are listed here.
** One may expect the number of extended result codes will increase
** One may expect the number of extended result codes will be expand
** over time. Software that uses extended result codes should expect
** to see new result codes in future releases of SQLite.
**
@@ -486,7 +486,6 @@ int sqlite3_exec(
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
@@ -554,8 +553,7 @@ int sqlite3_exec(
** after reboot following a crash or power loss, the only bytes in a
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
** flag indicate that a file cannot be deleted when open.
** guaranteed to be unchanged.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -786,29 +784,15 @@ struct sqlite3_io_methods {
** additional information.
**
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
** No longer in use.
**
** <li>[[SQLITE_FCNTL_SYNC]]
** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
** sent to the VFS immediately before the xSync method is invoked on a
** database file descriptor. Or, if the xSync method is not invoked
** because the user has configured SQLite with
** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place
** of the xSync method. In most cases, the pointer argument passed with
** this file-control is NULL. However, if the database file is being synced
** as part of a multi-database commit, the argument points to a nul-terminated
** string containing the transactions master-journal file name. VFSes that
** do not need this signal should silently ignore this opcode. Applications
** should not call [sqlite3_file_control()] with this opcode as doing so may
** disrupt the operation of the specialized VFSes that do require it.
**
** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
** and sent to the VFS after a transaction has been committed immediately
** but before the database is unlocked. VFSes that do not need this signal
** should silently ignore this opcode. Applications should not call
** [sqlite3_file_control()] with this opcode as doing so may disrupt the
** operation of the specialized VFSes that do require it.
** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
** SQLite and sent to all VFSes in place of a call to the xSync method
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.
**
** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
@@ -932,12 +916,6 @@ struct sqlite3_io_methods {
** SQLite stack may generate instances of this file control if
** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
**
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
** pointer to an integer and it writes a boolean into that integer depending
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -958,9 +936,6 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_TEMPFILENAME 16
#define SQLITE_FCNTL_MMAP_SIZE 18
#define SQLITE_FCNTL_TRACE 19
#define SQLITE_FCNTL_HAS_MOVED 20
#define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
/*
** CAPI3REF: Mutex Handle
@@ -1405,7 +1380,7 @@ int sqlite3_db_config(sqlite3*, int op, ...);
** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
** that causes the corresponding memory allocation to fail.
**
** The xInit method initializes the memory allocator. For example,
** The xInit method initializes the memory allocator. (For example,
** it might allocate any require mutexes or initialize internal data
** structures. The xShutdown method is invoked (indirectly) by
** [sqlite3_shutdown()] and should deallocate any resources acquired
@@ -1707,13 +1682,6 @@ struct sqlite3_mem_methods {
** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
** ^If either argument to this option is negative, then that argument is
** changed to its compile-time default.
**
** [[SQLITE_CONFIG_WIN32_HEAPSIZE]]
** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
** <dd>^This option is only available if SQLite is compiled for Windows
** with the [SQLITE_WIN32_MALLOC] pre-processor macro defined.
** SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
** that specifies the maximum size of the created heap.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -1738,7 +1706,6 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -3139,6 +3106,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** the
** </li>
** </ol>
*/
@@ -3800,19 +3768,19 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
**
** <tr><td> NULL <td> INTEGER <td> Result is 0
** <tr><td> NULL <td> FLOAT <td> Result is 0.0
** <tr><td> NULL <td> TEXT <td> Result is a NULL pointer
** <tr><td> NULL <td> BLOB <td> Result is a NULL pointer
** <tr><td> NULL <td> TEXT <td> Result is NULL pointer
** <tr><td> NULL <td> BLOB <td> Result is NULL pointer
** <tr><td> INTEGER <td> FLOAT <td> Convert from integer to float
** <tr><td> INTEGER <td> TEXT <td> ASCII rendering of the integer
** <tr><td> INTEGER <td> BLOB <td> Same as INTEGER->TEXT
** <tr><td> FLOAT <td> INTEGER <td> [CAST] to INTEGER
** <tr><td> FLOAT <td> INTEGER <td> Convert from float to integer
** <tr><td> FLOAT <td> TEXT <td> ASCII rendering of the float
** <tr><td> FLOAT <td> BLOB <td> [CAST] to BLOB
** <tr><td> TEXT <td> INTEGER <td> [CAST] to INTEGER
** <tr><td> TEXT <td> FLOAT <td> [CAST] to REAL
** <tr><td> FLOAT <td> BLOB <td> Same as FLOAT->TEXT
** <tr><td> TEXT <td> INTEGER <td> Use atoi()
** <tr><td> TEXT <td> FLOAT <td> Use atof()
** <tr><td> TEXT <td> BLOB <td> No change
** <tr><td> BLOB <td> INTEGER <td> [CAST] to INTEGER
** <tr><td> BLOB <td> FLOAT <td> [CAST] to REAL
** <tr><td> BLOB <td> INTEGER <td> Convert to TEXT then use atoi()
** <tr><td> BLOB <td> FLOAT <td> Convert to TEXT then use atof()
** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
** </table>
** </blockquote>)^
@@ -3868,7 +3836,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** 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 <b>not</b> pass the pointers returned
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
** ^(If a memory allocation error occurs during the evaluation of any
@@ -3977,24 +3945,15 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
**
** ^The fourth parameter, eTextRep, specifies what
** [SQLITE_UTF8 | text encoding] this SQL function prefers for
** its parameters. The application should set this parameter to
** [SQLITE_UTF16LE] if the function implementation invokes
** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
** implementation invokes [sqlite3_value_text16be()] on an input, or
** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
** otherwise. ^The same SQL function may be registered multiple times using
** different preferred text encodings, with different implementations for
** each encoding.
** its parameters. Every SQL function implementation must be able to work
** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be
** more efficient with one encoding than another. ^An application may
** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
** times with the same function but with different values of eTextRep.
** ^When multiple implementations of the same function are available, SQLite
** will pick the one that involves the least amount of data conversion.
**
** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
** to signal that the function will always return the same result given
** the same inputs within a single SQL statement. Most SQL functions are
** deterministic. The built-in [random()] SQL function is an example of a
** function that is not deterministic. The SQLite query planner is able to
** perform additional optimizations on deterministic functions, so use
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
** If there is only a single implementation which does not care what text
** encoding is used, then the fourth argument should be [SQLITE_ANY].
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -4080,19 +4039,9 @@ int sqlite3_create_function_v2(
#define SQLITE_UTF16LE 2
#define SQLITE_UTF16BE 3
#define SQLITE_UTF16 4 /* Use native byte order */
#define SQLITE_ANY 5 /* Deprecated */
#define SQLITE_ANY 5 /* sqlite3_create_function only */
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
/*
** CAPI3REF: Function Flags
**
** These constants may be ORed together with the
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
** [sqlite3_create_function_v2()].
*/
#define SQLITE_DETERMINISTIC 0x800
/*
** CAPI3REF: Deprecated Functions
** DEPRECATED
@@ -4965,8 +4914,8 @@ int sqlite3_release_memory(int);
**
** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
** memory as possible from database connection D. Unlike the
** [sqlite3_release_memory()] interface, this interface is in effect even
** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
** [sqlite3_release_memory()] interface, this interface is effect even
** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
** omitted.
**
** See also: [sqlite3_release_memory()]
@@ -6113,8 +6062,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_LAST 20
#define SQLITE_TESTCTRL_LAST 19
/*
** CAPI3REF: SQLite Runtime Status
+13 -71
View File
@@ -742,7 +742,6 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct PrintfArguments PrintfArguments;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
@@ -1078,13 +1077,6 @@ struct sqlite3 {
#define OptimizationEnabled(db, mask) 1
#endif
/*
** Return true if it OK to factor constant expressions into the initialization
** code. The argument is a Parse object for the code generator.
*/
#define ConstFactorOk(P) \
((P)->cookieGoto>0 && OptimizationEnabled((P)->db,SQLITE_FactorOutConst))
/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
@@ -1151,7 +1143,6 @@ struct FuncDestructor {
#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */
#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -1164,9 +1155,6 @@ struct FuncDestructor {
** as the user-data (sqlite3_user_data()) for the function. If
** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
**
** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
** Used to create an aggregate function definition implemented by
** the C functions xStep and xFinal. The first four parameters
@@ -1182,20 +1170,16 @@ struct FuncDestructor {
** parameter.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
{nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
pArg, 0, xFunc, 0, 0, #zName, 0, 0}
#define LIKEFUNC(zName, nArg, arg, flags) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
(void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0}
{nArg, SQLITE_UTF8|flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0}
#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}
@@ -1845,7 +1829,7 @@ struct Expr {
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE opeartor */
/* unused 0x000200 */
#define EP_FixedDest 0x000200 /* Result needed in a specific register */
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
@@ -1855,7 +1839,6 @@ struct Expr {
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_Constant 0x080000 /* Node is a constant */
/*
** These macros can be used to test, set, or clear bits in the
@@ -1917,14 +1900,8 @@ struct ExprList {
u8 sortOrder; /* 1 for DESC or 0 for ASC */
unsigned done :1; /* A flag to indicate when processing is finished */
unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
unsigned reusable :1; /* Constant expression is reusable */
union {
struct {
u16 iOrderByCol; /* For ORDER BY, column number in result set */
u16 iAlias; /* Index into Parse.aAlias[] for zName */
} x;
int iConstExprReg; /* Register in which Expr value is cached */
} u;
u16 iOrderByCol; /* For ORDER BY, column number in result set */
u16 iAlias; /* Index into Parse.aAlias[] for zName */
} *a; /* Alloc a power of two greater or equal to nExpr */
};
@@ -2301,7 +2278,6 @@ struct Parse {
int iReg; /* Reg with value of this column. 0 means none. */
int lru; /* Least recently used entry has the smallest value */
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
ExprList *pConstExpr;/* Constant expressions */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
@@ -2539,7 +2515,6 @@ struct Sqlite3Config {
int bOpenUri; /* True to interpret filenames as URIs */
int bUseCis; /* Use covering indices for full-scans */
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
int nLookaside; /* Default lookaside buffer count */
sqlite3_mem_methods m; /* Low-level memory allocation interface */
@@ -2576,24 +2551,6 @@ struct Sqlite3Config {
#endif
};
/*
** This macro is used inside of assert() statements to indicate that
** the assert is only valid on a well-formed database. Instead of:
**
** assert( X );
**
** One writes:
**
** assert( X || CORRUPT_DB );
**
** CORRUPT_DB is true during normal operation. CORRUPT_DB does not indicate
** that the database is definitely corrupt, only that it might be corrupt.
** For most test cases, CORRUPT_DB is set to false using a special
** sqlite3_test_control(). This enables assert() statements to prove
** things that are always true for well-formed databases.
*/
#define CORRUPT_DB (sqlite3Config.neverCorrupt==0)
/*
** Context pointer passed down through the tree-walk.
*/
@@ -2765,20 +2722,10 @@ void sqlite3StatusSet(int, int);
# define sqlite3IsNaN(X) 0
#endif
/*
** An instance of the following structure holds information about SQL
** functions arguments that are the parameters to the printf() function.
*/
struct PrintfArguments {
int nArg; /* Total number of arguments */
int nUsed; /* Number of arguments used so far */
sqlite3_value **apArg; /* The argument values */
};
#define SQLITE_PRINTF_INTERNAL 0x01
#define SQLITE_PRINTF_SQLFUNC 0x02
void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list);
void sqlite3XPrintf(StrAccum*, u32, const char*, ...);
void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
#ifndef SQLITE_OMIT_TRACE
void sqlite3XPrintf(StrAccum*, const char*, ...);
#endif
char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
@@ -2941,13 +2888,11 @@ void sqlite3ExprCacheRemove(Parse*, int, int);
void sqlite3ExprCacheClear(Parse*);
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
int sqlite3ExprCode(Parse*, Expr*, int);
void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8);
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
void sqlite3ExprCodeConstants(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int);
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
@@ -2992,7 +2937,7 @@ int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*);
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, int*, int*);
void sqlite3BeginWriteOperation(Parse*, int, int);
void sqlite3MultiWrite(Parse*);
void sqlite3MayAbort(Parse*);
@@ -3168,7 +3113,6 @@ const void *sqlite3ValueText(sqlite3_value*, u8);
int sqlite3ValueBytes(sqlite3_value*, u8);
void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void(*)(void*));
void sqlite3ValueSetNull(sqlite3_value*);
void sqlite3ValueFree(sqlite3_value*);
sqlite3_value *sqlite3ValueNew(sqlite3 *);
char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
@@ -3234,7 +3178,6 @@ int sqlite3OpenTempDatabase(Parse *);
void sqlite3StrAccumInit(StrAccum*, char*, int, int);
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
void sqlite3AppendSpace(StrAccum*,int);
char *sqlite3StrAccumFinish(StrAccum*);
void sqlite3StrAccumReset(StrAccum*);
@@ -3316,7 +3259,6 @@ void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
+6 -6
View File
@@ -424,12 +424,13 @@ static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){
*/
static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
SqlFunc *p, *pNew;
int nName = strlen30(zName);
pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + nName + 1 );
int i;
pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + strlen30(zName) + 1 );
pNew->zName = (char*)&pNew[1];
memcpy(pNew->zName, zName, nName+1);
for(i=0; zName[i]; i++){ pNew->zName[i] = tolower(zName[i]); }
pNew->zName[i] = 0;
for(p=pDb->pFunc; p; p=p->pNext){
if( sqlite3_stricmp(p->zName, pNew->zName)==0 ){
if( strcmp(p->zName, pNew->zName)==0 ){
Tcl_Free((char*)pNew);
return p;
}
@@ -1082,14 +1083,13 @@ static int dbPrepareAndBind(
int nSql; /* Length of zSql in bytes */
int nVar; /* Number of variables in statement */
int iParm = 0; /* Next free entry in apParm */
char c;
int i;
Tcl_Interp *interp = pDb->interp;
*ppPreStmt = 0;
/* Trim spaces from the start of zSql and calculate the remaining length. */
while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; }
while( isspace(zSql[0]) ){ zSql++; }
nSql = strlen30(zSql);
for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){
+6 -64
View File
@@ -942,21 +942,9 @@ static void ptrChngFunction(
sqlite3_result_int(context, p1!=p2);
}
/*
** This SQL function returns a different answer each time it is called, even if
** the arguments are the same.
*/
static void nondeterministicFunction(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
static int cnt = 0;
sqlite3_result_int(context, cnt++);
}
/*
** Usage: sqlite3_create_function DB
** Usage: sqlite_test_create_function DB
**
** Call the sqlite3_create_function API on the given database in order
** to create a function named "x_coalesce". This function does the same thing
@@ -985,16 +973,16 @@ static int test_create_function(
return TCL_ERROR;
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
t1_ifnullFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
0, hex8Func, 0, 0);
rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,
hex8Func, 0, 0);
}
#ifndef SQLITE_OMIT_UTF16
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
0, hex16Func, 0, 0);
rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,
hex16Func, 0, 0);
}
#endif
if( rc==SQLITE_OK ){
@@ -1006,19 +994,6 @@ static int test_create_function(
ptrChngFunction, 0, 0);
}
/* Functions counter1() and counter2() have the same implementation - they
** both return an ascending integer with each call. But counter1() is marked
** as non-deterministic and counter2() is marked as deterministic.
*/
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
0, nondeterministicFunction, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
0, nondeterministicFunction, 0, 0);
}
#ifndef SQLITE_OMIT_UTF16
/* Use the sqlite3_create_function16() API here. Mainly for fun, but also
** because it is not tested anywhere else. */
@@ -5478,37 +5453,6 @@ static int reset_prng_state(
return TCL_OK;
}
/*
** tclcmd: database_may_be_corrupt
**
** Indicate that database files might be corrupt. In other words, set the normal
** state of operation.
*/
static int database_may_be_corrupt(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0);
return TCL_OK;
}
/*
** tclcmd: database_never_corrupt
**
** Indicate that database files are always well-formed. This enables extra assert()
** statements that test conditions that are always true for well-formed databases.
*/
static int database_never_corrupt(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1);
return TCL_OK;
}
/*
** tclcmd: pcache_stats
*/
@@ -6387,8 +6331,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "save_prng_state", save_prng_state, 0 },
{ "restore_prng_state", restore_prng_state, 0 },
{ "reset_prng_state", reset_prng_state, 0 },
{ "database_never_corrupt", database_never_corrupt, 0},
{ "database_may_be_corrupt", database_may_be_corrupt, 0},
{ "optimization_control", optimization_control,0},
#if SQLITE_OS_WIN
{ "lock_win32_file", win32_file_lock, 0 },
+7 -6
View File
@@ -173,6 +173,9 @@ static void *crash_realloc(void *p, int n){
static int writeDbFile(CrashFile *p, u8 *z, i64 iAmt, i64 iOff){
int rc = SQLITE_OK;
int iSkip = 0;
if( iOff==PENDING_BYTE && (p->flags&SQLITE_OPEN_MAIN_DB) ){
iSkip = 512;
}
if( (iAmt-iSkip)>0 ){
rc = sqlite3OsWrite(p->pRealFile, &z[iSkip], (int)(iAmt-iSkip), iOff+iSkip);
}
@@ -406,17 +409,13 @@ static int cfRead(
sqlite_int64 iOfst
){
CrashFile *pCrash = (CrashFile *)pFile;
int nCopy = (int)MIN((i64)iAmt, (pCrash->iSize - iOfst));
if( nCopy>0 ){
memcpy(zBuf, &pCrash->zData[iOfst], nCopy);
}
/* Check the file-size to see if this is a short-read */
if( nCopy<iAmt ){
if( pCrash->iSize<(iOfst+iAmt) ){
return SQLITE_IOERR_SHORT_READ;
}
memcpy(zBuf, &pCrash->zData[iOfst], iAmt);
return SQLITE_OK;
}
@@ -633,12 +632,14 @@ static int cfOpen(
** UPDATE: It also contains an assert() verifying that each call
** to the xRead() method reads less than 128KB of data.
*/
const int isDb = (flags&SQLITE_OPEN_MAIN_DB);
i64 iOff;
memset(pWrapper->zData, 0, pWrapper->nData);
for(iOff=0; iOff<pWrapper->iSize; iOff += 512){
int nRead = (int)(pWrapper->iSize - iOff);
if( nRead>512 ) nRead = 512;
if( isDb && iOff==PENDING_BYTE ) continue;
rc = sqlite3OsRead(pReal, &pWrapper->zData[iOff], nRead, iOff);
}
}else{
-6
View File
@@ -63,12 +63,6 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "curdir", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_WIN32_MALLOC
Tcl_SetVar2(interp, "sqlite_options", "win32malloc", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "win32malloc", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_DEBUG
Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY);
#else
-28
View File
@@ -1130,33 +1130,6 @@ static int test_config_heap(
return TCL_OK;
}
/*
** Usage: sqlite3_config_heap_size NBYTE
*/
static int test_config_heap_size(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
int nByte; /* Size to pass to sqlite3_config() */
int rc; /* Return code of sqlite3_config() */
Tcl_Obj * CONST *aArg = &objv[1];
int nArg = objc-1;
if( nArg!=1 ){
Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
rc = sqlite3_config(SQLITE_CONFIG_WIN32_HEAPSIZE, nByte);
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
return TCL_OK;
}
/*
** Usage: sqlite3_config_error [DB]
**
@@ -1500,7 +1473,6 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
{ "sqlite3_db_status", test_db_status ,0 },
{ "install_malloc_faultsim", test_install_malloc_faultsim ,0 },
{ "sqlite3_config_heap", test_config_heap ,0 },
{ "sqlite3_config_heap_size", test_config_heap_size ,0 },
{ "sqlite3_config_memstatus", test_config_memstatus ,0 },
{ "sqlite3_config_lookaside", test_config_lookaside ,0 },
{ "sqlite3_config_error", test_config_error ,0 },
+398
View File
@@ -0,0 +1,398 @@
/*
** 2013-11-14
**
** 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 an implementation of the "schema2" virtual table
** for displaying the content of various internal objects associated with
** the parsed schema.
*/
#ifndef SQLITE_AMALGAMATION
# include "sqliteInt.h"
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
static const char azSchema2[] =
"CREATE TABLE x("
" dbname STRING," /* Name of attached database */
" tblname STRING," /* Name of the table */
" idxname STRING," /* Index name or NULL if not applicable */
" cnum INT," /* Column number or NULL if not applicable */
" attr STRING," /* Attribute name */
" value STRING " /* Attribute value */
");"
;
typedef struct Schema2Table Schema2Table;
typedef struct Schema2Cursor Schema2Cursor;
typedef struct Schema2Row Schema2Row;
/*
** A single row of the result
*/
struct Schema2Row {
const char *zDb; /* Schema name. db->aDb[].zName */
const char *zTbl; /* Table name. Might be NULL */
const char *zIdx; /* Index name. Might be NULL */
int iCol; /* Column number */
const char *zAttr; /* Attribute */
char *zValue; /* Value of the attribute */
Schema2Row *pNext; /* Next row */
};
/*
** A cursor for iterating through internal schema information
*/
struct Schema2Cursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
int iRowid; /* Current rowid */
Schema2Row *pAll; /* All rows */
Schema2Row *pCurrent; /* Current row */
Schema2Row *pLast; /* Last row */
};
/*
** The complete Schema2 virtual table
*/
struct Schema2Table {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db; /* The database connection that owns this table */
};
/*
** Connect to or create an Schema2 virtual table.
*/
static int schema2Connect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
Schema2Table *pTab;
pTab = (Schema2Table *)sqlite3_malloc(sizeof(Schema2Table));
memset(pTab, 0, sizeof(Schema2Table));
pTab->db = db;
sqlite3_declare_vtab(db, azSchema2);
*ppVtab = &pTab->base;
return SQLITE_OK;
}
/*
** Disconnect from or destroy an Schema2 virtual table.
*/
static int schema2Disconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** There is no "best-index". This virtual table always does a complete
** scan.
*/
static int schema2BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
pIdxInfo->estimatedCost = 10.0;
return SQLITE_OK;
}
/*
** Open a new Schema2 cursor.
*/
static int schema2Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
Schema2Cursor *pCsr;
pCsr = (Schema2Cursor *)sqlite3_malloc(sizeof(Schema2Cursor));
memset(pCsr, 0, sizeof(Schema2Cursor));
pCsr->base.pVtab = pVTab;
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return SQLITE_OK;
}
static void schema2ResetCsr(Schema2Cursor *pCsr){
Schema2Row *pRow, *pNextRow;
for(pRow=pCsr->pAll; pRow; pRow=pNextRow){
pNextRow = pRow->pNext;
sqlite3_free(pRow->zValue);
sqlite3_free(pRow);
}
pCsr->pAll = 0;
pCsr->pCurrent = 0;
pCsr->pLast = 0;
pCsr->iRowid = 0;
}
/*
** Close a statvfs cursor.
*/
static int schema2Close(sqlite3_vtab_cursor *pCursor){
Schema2Cursor *pCsr = (Schema2Cursor *)pCursor;
schema2ResetCsr(pCsr);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** Move a statvfs cursor to the next entry.
*/
static int schema2Next(sqlite3_vtab_cursor *pCursor){
Schema2Cursor *pCsr = (Schema2Cursor *)pCursor;
if( pCsr->pCurrent==0 ){
pCsr->pCurrent = pCsr->pAll;
}else{
pCsr->pCurrent = pCsr->pCurrent->pNext;
}
pCsr->iRowid++;
return SQLITE_OK;
}
static int schema2Eof(sqlite3_vtab_cursor *pCursor){
Schema2Cursor *pCsr = (Schema2Cursor *)pCursor;
return pCsr->pCurrent==0 && pCsr->iRowid>0;
}
/* Append a single to the cursor pCsr */
static void schema2AppendRow(
Schema2Cursor *pCsr,
const char *zDb,
const char *zTbl,
const char *zIdx,
int iCol,
const char *zAttr,
const char *zValue,
...
){
Schema2Row *pRow = sqlite3_malloc( sizeof(*pRow) );
va_list ap;
if( pRow==0 );
pRow->zDb = zDb;
pRow->zTbl = zTbl;
pRow->zIdx = zIdx;
pRow->iCol = iCol;
pRow->zAttr = zAttr;
va_start(ap, zValue);
pRow->zValue = sqlite3_vmprintf(zValue, ap);
va_end(ap);
if( pCsr->pLast==0 ){
pCsr->pAll = pRow;
}else{
pCsr->pLast->pNext = pRow;
}
pCsr->pLast = pRow;
}
/* Append rows for index pIdx of table pTab which is part of the zDb schema */
static void schema2AppendIndex(
Schema2Cursor *pCsr,
const char *zDb,
Table *pTab,
Index *pIdx
){
const char *zTbl = pTab->zName;
const char *zIdx = pIdx->zName;
int i;
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"zColAff","%s",pIdx->zColAff);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"tnum","%d",pIdx->tnum);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"szIdxRow","%d",pIdx->szIdxRow);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"nKeyCol","%d",pIdx->nKeyCol);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"nColumn","%d",pIdx->nColumn);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"onError","%d",pIdx->onError);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"autoIndex","%d",pIdx->autoIndex);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"bUnordered","%d",pIdx->bUnordered);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"uniqNotNull","%d",pIdx->uniqNotNull);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"isResized","%d",pIdx->isResized);
schema2AppendRow(pCsr,zDb,zTbl,zIdx,-1,"isCovering","%d",pIdx->isCovering);
for(i=0; i<pIdx->nColumn; i++){
i16 x = pIdx->aiColumn[i];
schema2AppendRow(pCsr,zDb,zTbl,zIdx,i,"zName","%s",
x>=0?pTab->aCol[x].zName:"rowid");
schema2AppendRow(pCsr,zDb,zTbl,zIdx,i,"aiRowEst","%lld",
(sqlite3_int64)pIdx->aiRowEst[i]);
}
}
/* Append rows for table pTab which is part of the zDb schema */
static void schema2AppendTable(
Schema2Cursor *pCsr,
const char *zDb,
Table *pTab
){
const char *zTbl = pTab->zName;
int i;
Index *pIdx;
schema2AppendRow(pCsr,zDb,zTbl,0,-1,"zColAff","%s",pTab->zColAff);
schema2AppendRow(pCsr,zDb,zTbl,0,-1,"nRowEst",
"%lld",(sqlite3_int64)pTab->nRowEst);
schema2AppendRow(pCsr,zDb,zTbl,0,-1,"tnum","%d",pTab->tnum);
schema2AppendRow(pCsr,zDb,zTbl,0,-1,"iPKey","%d",pTab->iPKey);
schema2AppendRow(pCsr,zDb,zTbl,0,-1,"nCol","%d",pTab->nCol);
schema2AppendRow(pCsr,zDb,zTbl,0,-1,"nRef","%d",pTab->nRef);
schema2AppendRow(pCsr,zDb,zTbl,0,-1,"szTabRow","%d",pTab->szTabRow);
schema2AppendRow(pCsr,zDb,zTbl,0,-1,"tabFlags","%d",pTab->tabFlags);
for(i=0; i<pTab->nCol; i++){
const Column *p = pTab->aCol + i;
schema2AppendRow(pCsr,zDb,zTbl,0,i,"zName","%s",p->zName);
schema2AppendRow(pCsr,zDb,zTbl,0,i,"zDflt","%s",p->zDflt);
schema2AppendRow(pCsr,zDb,zTbl,0,i,"zType","%s",p->zType);
schema2AppendRow(pCsr,zDb,zTbl,0,i,"zColl","%s",p->zColl);
schema2AppendRow(pCsr,zDb,zTbl,0,i,"notNull","%d",p->notNull);
schema2AppendRow(pCsr,zDb,zTbl,0,i,"affinity","%c",p->affinity);
schema2AppendRow(pCsr,zDb,zTbl,0,i,"szEst","%d",p->szEst);
schema2AppendRow(pCsr,zDb,zTbl,0,i,"colFlags","%04x",p->colFlags);
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
schema2AppendIndex(pCsr, zDb, pTab, pIdx);
}
}
/* Append rows for schema object pSchema */
static void schema2AppendSchema(
Schema2Cursor *pCsr,
const char *zDb,
Schema *pSchema
){
HashElem *i;
schema2AppendRow(pCsr,zDb,0,0,-1,"generation","%d", pSchema->iGeneration);
schema2AppendRow(pCsr,zDb,0,0,-1,"file_format","%d", pSchema->file_format);
schema2AppendRow(pCsr,zDb,0,0,-1,"enc","%d", pSchema->enc);
schema2AppendRow(pCsr,zDb,0,0,-1,"flags","%d", pSchema->flags);
schema2AppendRow(pCsr,zDb,0,0,-1,"cache_size","%d", pSchema->cache_size);
for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){
schema2AppendTable(pCsr, zDb, (Table*)sqliteHashData(i));
}
}
static int schema2Filter(
sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
int iDb;
Schema2Cursor *pCsr = (Schema2Cursor*)pCursor;
Schema2Table *pTab = (Schema2Table*)(pCursor->pVtab);
sqlite3 *db = pTab->db;
schema2ResetCsr(pCsr);
for(iDb=0; iDb<db->nDb; iDb++){
const char *zDb = db->aDb[iDb].zName;
Schema *pSchema = db->aDb[iDb].pSchema;
schema2AppendRow(pCsr,zDb,0,0,-1,"safety_level",
"%d", db->aDb[iDb].safety_level);
schema2AppendSchema(pCsr, zDb, pSchema);
}
return schema2Next(pCursor);
}
static int schema2Column(
sqlite3_vtab_cursor *pCursor,
sqlite3_context *ctx,
int i
){
Schema2Cursor *pCsr = (Schema2Cursor *)pCursor;
Schema2Row *pRow = pCsr->pCurrent;
if( pRow==0 ) return SQLITE_OK;
switch( i ){
case 0: /* dbname */
sqlite3_result_text(ctx, pRow->zDb, -1, SQLITE_STATIC);
break;
case 1: /* tblname */
if( pRow->zTbl ) sqlite3_result_text(ctx, pRow->zTbl, -1, SQLITE_STATIC);
break;
case 2: /* idxname */
if( pRow->zIdx ) sqlite3_result_text(ctx, pRow->zIdx, -1, SQLITE_STATIC);
break;
case 3: /* cnum */
if( pRow->iCol>=0 ) sqlite3_result_int(ctx, pRow->iCol);
break;
case 4: /* attr */
sqlite3_result_text(ctx, pRow->zAttr, -1, SQLITE_STATIC);
break;
case 5: /* value */
if( pRow->zValue ) sqlite3_result_text(ctx,pRow->zValue,-1,SQLITE_STATIC);
break;
}
return SQLITE_OK;
}
static int schema2Rowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
Schema2Cursor *pCsr = (Schema2Cursor *)pCursor;
*pRowid = pCsr->iRowid;
return SQLITE_OK;
}
int sqlite3_schema2_register(sqlite3 *db){
static sqlite3_module schema2_module = {
0, /* iVersion */
schema2Connect, /* xCreate */
schema2Connect, /* xConnect */
schema2BestIndex, /* xBestIndex */
schema2Disconnect, /* xDisconnect */
schema2Disconnect, /* xDestroy */
schema2Open, /* xOpen - open a cursor */
schema2Close, /* xClose - close a cursor */
schema2Filter, /* xFilter - configure scan constraints */
schema2Next, /* xNext - advance a cursor */
schema2Eof, /* xEof - check for end of scan */
schema2Column, /* xColumn - read data */
schema2Rowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
};
sqlite3_create_module(db, "schema2", &schema2_module, 0);
return SQLITE_OK;
}
#endif
#if defined(SQLITE_TEST) || TCLSH==2
#include <tcl.h>
static int test_schema2(
void *clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_OMIT_VIRTUALTABLE
Tcl_AppendResult(interp, "schema2 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_schema2_register(db);
}
return TCL_OK;
#endif
}
int SqlitetestSchema2_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "register_schema2_vtab", test_schema2, 0, 0);
return TCL_OK;
}
#endif /* if defined(SQLITE_TEST) || TCLSH==2 */
-5
View File
@@ -258,11 +258,6 @@ static void vfstrace_print_errcode(
case SQLITE_IOERR_SHMOPEN: zVal = "SQLITE_IOERR_SHMOPEN"; break;
case SQLITE_IOERR_SHMSIZE: zVal = "SQLITE_IOERR_SHMSIZE"; break;
case SQLITE_IOERR_SHMLOCK: zVal = "SQLITE_IOERR_SHMLOCK"; break;
case SQLITE_IOERR_SHMMAP: zVal = "SQLITE_IOERR_SHMMAP"; break;
case SQLITE_IOERR_SEEK: zVal = "SQLITE_IOERR_SEEK"; break;
case SQLITE_IOERR_GETTEMPPATH: zVal = "SQLITE_IOERR_GETTEMPPATH"; break;
case SQLITE_IOERR_CONVPATH: zVal = "SQLITE_IOERR_CONVPATH"; break;
case SQLITE_READONLY_DBMOVED: zVal = "SQLITE_READONLY_DBMOVED"; break;
case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break;
case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break;
case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break;
-1
View File
@@ -924,7 +924,6 @@ static TriggerPrg *codeRowTrigger(
assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
sqlite3ParserReset(pSubParse);
sqlite3StackFree(db, pSubParse);
return pPrg;
+44 -37
View File
@@ -101,7 +101,6 @@ void sqlite3Update(
Index *pIdx; /* For looping over indices */
Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
int nIdx; /* Number of indices that need updating */
int iBaseCur; /* Base cursor number */
int iDataCur; /* Cursor for the canonical data btree */
int iIdxCur; /* Cursor for the first index */
sqlite3 *db; /* The database structure */
@@ -109,11 +108,11 @@ void sqlite3Update(
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
u8 *aToOpen; /* 1 for tables and indices to be opened */
u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */
u8 chngRowid; /* Rowid changed in a normal table */
u8 chngKey; /* Either chngPk or chngRowid */
Expr *pRowidExpr = 0; /* Expression defining the new record number */
int openAll = 0; /* True if all indices need to be opened */
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
@@ -177,13 +176,16 @@ void sqlite3Update(
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
goto update_cleanup;
}
aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol );
if( aXRef==0 ) goto update_cleanup;
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
/* Allocate a cursors for the main database table and for all indices.
** The index cursors might not be used, but if they are used they
** need to occur right after the database cursor. So go ahead and
** allocate enough space, just in case.
*/
pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++;
pTabList->a[0].iCursor = iDataCur = pParse->nTab++;
iIdxCur = iDataCur+1;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
@@ -194,17 +196,6 @@ void sqlite3Update(
pParse->nTab++;
}
/* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
** Initialize aXRef[] and aToOpen[] to their default values.
*/
aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
if( aXRef==0 ) goto update_cleanup;
aRegIdx = aXRef+pTab->nCol;
aToOpen = (u8*)(aRegIdx+nIdx);
memset(aToOpen, 1, nIdx+1);
aToOpen[nIdx+1] = 0;
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
/* Initialize the name-context */
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
@@ -263,17 +254,17 @@ void sqlite3Update(
assert( chngPk==0 || chngPk==1 );
chngKey = chngRowid + chngPk;
/* The SET expressions are not actually used inside the WHERE loop.
** So reset the colUsed mask
*/
pTabList->a[0].colUsed = 0;
hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
/* There is one entry in the aRegIdx[] array for each index on the table
** being updated. Fill in aRegIdx[] with a register number that will hold
** the key for accessing each index.
/* Allocate memory for the array aRegIdx[]. There is one entry in the
** array for each index associated with table being updated. Fill in
** the value with a register number for indices that are to be used
** and with zero for unused indices.
*/
if( nIdx>0 ){
aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
if( aRegIdx==0 ) goto update_cleanup;
}
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){
@@ -287,7 +278,6 @@ void sqlite3Update(
}
}
}
if( reg==0 ) aToOpen[j+1] = 0;
aRegIdx[j] = reg;
}
@@ -411,30 +401,42 @@ void sqlite3Update(
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
if( !okOnePass && HasRowid(pTab) ){
sqlite3OpenTable(pParse, iDataCur, iDb, pTab, OP_OpenWrite);
}
sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
if( onError==OE_Replace ){
memset(aToOpen, 1, nIdx+1);
openAll = 1;
}else{
openAll = 0;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->onError==OE_Replace ){
memset(aToOpen, 1, nIdx+1);
openAll = 1;
break;
}
}
}
if( okOnePass ){
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
int iThisCur = iIdxCur+i;
assert( aRegIdx );
if( (openAll || aRegIdx[i]>0)
&& iThisCur!=aiCurOnePass[1]
){
assert( iThisCur!=aiCurOnePass[0] );
sqlite3VdbeAddOp3(v, OP_OpenWrite, iThisCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
assert( pParse->nTab>iThisCur );
VdbeComment((v, "%s", pIdx->zName));
if( okOnePass && pPk && iThisCur==iDataCur ){
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak,
regKey, nKey);
}
}
}
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen,
0, 0);
}
/* Top of the update loop */
if( okOnePass ){
if( aToOpen[iDataCur-iBaseCur] ){
assert( pPk!=0 );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
}
labelContinue = labelBreak;
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
}else if( pPk ){
@@ -579,7 +581,11 @@ void sqlite3Update(
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
}
if( bReplace || chngKey ){
sqlite3VdbeJumpHere(v, j1);
if( sqlite3VdbeCurrentAddr(v)==j1+1 ){
sqlite3VdbeChangeToNoop(v, j1);
}else{
sqlite3VdbeJumpHere(v, j1);
}
}
if( hasFK ){
@@ -623,7 +629,7 @@ void sqlite3Update(
/* Close all tables */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
assert( aRegIdx );
if( aToOpen[i+1] ){
if( openAll || aRegIdx[i]>0 ){
sqlite3VdbeAddOp2(v, OP_Close, iIdxCur+i, 0);
}
}
@@ -650,7 +656,8 @@ void sqlite3Update(
update_cleanup:
sqlite3AuthContextPop(&sContext);
sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */
sqlite3DbFree(db, aRegIdx);
sqlite3DbFree(db, aXRef);
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprListDelete(db, pChanges);
sqlite3ExprDelete(db, pWhere);
+19 -19
View File
@@ -115,17 +115,18 @@ int sqlite3Strlen30(const char *z){
** to NULL.
*/
void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
assert( db!=0 );
db->errCode = err_code;
if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
char *z;
va_list ap;
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
}else if( db->pErr ){
sqlite3ValueSetNull(db->pErr);
if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
db->errCode = err_code;
if( zFormat ){
char *z;
va_list ap;
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
}else{
sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
}
}
}
@@ -464,12 +465,12 @@ static int compare2pow63(const char *zNum, int incr){
** If the zNum value is representable as a 64-bit twos-complement
** integer, then write that value into *pNum and return 0.
**
** If zNum is exactly 9223372036854775808, return 2. This special
** case is broken out because while 9223372036854775808 cannot be a
** signed 64-bit integer, its negative -9223372036854775808 can be.
** If zNum is exactly 9223372036854665808, return 2. This special
** case is broken out because while 9223372036854665808 cannot be a
** signed 64-bit integer, its negative -9223372036854665808 can be.
**
** If zNum is too big for a 64-bit integer and is not
** 9223372036854775808 or if zNum contains any non-numeric text,
** 9223372036854665808 or if zNum contains any non-numeric text,
** then return 1.
**
** length is the number of bytes in the string (bytes, not characters).
@@ -511,7 +512,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
u = u*10 + c - '0';
}
if( u>LARGEST_INT64 ){
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
*pNum = SMALLEST_INT64;
}else if( neg ){
*pNum = -(i64)u;
}else{
@@ -542,6 +543,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
/* zNum is exactly 9223372036854775808. Fits if negative. The
** special case 2 overflow if positive */
assert( u-1==LARGEST_INT64 );
assert( (*pNum)==SMALLEST_INT64 );
return neg ? 0 : 2;
}
}
@@ -1280,8 +1282,6 @@ u64 sqlite3LogEstToInt(LogEst x){
x /= 10;
if( n>=5 ) n -= 2;
else if( n>=1 ) n -= 1;
if( x>=3 ){
return x>60 ? (u64)LARGEST_INT64 : (n+8)<<(x-3);
}
if( x>=3 ) return (n+8)<<(x-3);
return (n+8)>>(3-x);
}
+378 -341
View File
File diff suppressed because it is too large Load Diff
+25 -26
View File
@@ -36,7 +36,7 @@ typedef struct VdbeOp Op;
/*
** Boolean values
*/
typedef unsigned Bool;
typedef unsigned char Bool;
/* Opaque type used by code in vdbesort.c */
typedef struct VdbeSorter VdbeSorter;
@@ -53,9 +53,6 @@ typedef struct AuxData AuxData;
** loop over all entries of the Btree. You can also insert new BTree
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
**
** Cursors can also point to virtual tables, sorters, or "pseudo-tables".
** A pseudo-table is a single-row table implemented by registers.
**
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
@@ -64,24 +61,30 @@ struct VdbeCursor {
BtCursor *pCursor; /* The cursor structure of the backend */
Btree *pBt; /* Separate file holding temporary table */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int seekResult; /* Result of previous sqlite3BtreeMoveto() */
int iDb; /* Index of cursor database in db->aDb[] (or -1) */
int pseudoTableReg; /* Register holding pseudotable content. */
i16 nField; /* Number of fields in the header */
u16 nHdrParsed; /* Number of header fields parsed so far */
i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
u8 nullRow; /* True if pointing to a row with no data */
u8 rowidIsValid; /* True if lastRowid is valid */
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
Bool isTable:1; /* True if a table requiring integer keys */
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
Bool multiPseudo:1; /* Multi-register pseudo-cursor */
int nField; /* Number of fields in the header */
Bool zeroed; /* True if zeroed out and ready for reuse */
Bool rowidIsValid; /* True if lastRowid is valid */
Bool atFirst; /* True if pointing to first entry */
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
Bool nullRow; /* True if pointing to a row with no data */
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
Bool isSorter; /* True if a new-style sorter */
Bool multiPseudo; /* Multi-register pseudo-cursor */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
i64 lastRowid; /* Rowid being deleted by OP_Delete */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
/* Result of last sqlite3BtreeMoveto() done by an OP_NotExists */
int seekResult;
/* Cached information about the header for the data record that the
** cursor is currently pointing to. Only valid if cacheStatus matches
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
@@ -92,14 +95,10 @@ struct VdbeCursor {
** be NULL.
*/
u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
u32 payloadSize; /* Total number of bytes in the record */
u32 szRow; /* Byte available in aRow */
u32 iHdrOffset; /* Offset to next unparsed byte of the header */
const u8 *aRow; /* Data for the current row, if all on one page */
u32 aType[1]; /* Type values for all entries in the record */
/* 2*nField extra array elements allocated for aType[], beyond the one
** static element declared in the structure. nField total array slots for
** aType[] and nField+1 array slots for aOffset[] */
int payloadSize; /* Total number of bytes in the record */
u32 *aType; /* Type values for all entries in the record */
u32 *aOffset; /* Cached offsets to the start of each columns data */
u8 *aRow; /* Data for the current row, if all on one page */
};
typedef struct VdbeCursor VdbeCursor;
@@ -389,7 +388,7 @@ void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
u32 sqlite3VdbeSerialTypeLen(u32);
u32 sqlite3VdbeSerialType(Mem*, int);
u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
@@ -424,7 +423,7 @@ double sqlite3VdbeRealValue(Mem*);
void sqlite3VdbeIntegerAffinity(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemNumerify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemReleaseExternal(Mem *p);
#define VdbeMemRelease(X) \
+1 -2
View File
@@ -486,7 +486,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
v->doingRerun = 1;
assert( v->expired==0 );
}
if( rc2!=SQLITE_OK ){
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
@@ -496,7 +496,6 @@ int sqlite3_step(sqlite3_stmt *pStmt){
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
assert( zErr!=0 || db->mallocFailed );
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
+35 -20
View File
@@ -453,14 +453,12 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
}
#endif
case OP_Next:
case OP_NextIfOpen:
case OP_SorterNext: {
pOp->p4.xAdvance = sqlite3BtreeNext;
pOp->p4type = P4_ADVANCE;
break;
}
case OP_Prev:
case OP_PrevIfOpen: {
case OP_Prev: {
pOp->p4.xAdvance = sqlite3BtreePrevious;
pOp->p4type = P4_ADVANCE;
break;
@@ -1676,7 +1674,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
const sqlite3_module *pModule = pCx->pModule;
p->inVtabMethod = 1;
pModule->xClose(pVtabCursor);
p->inVtabMethod = 0;
@@ -2420,7 +2418,6 @@ int sqlite3VdbeTransferError(Vdbe *p){
if( p->zErrMsg ){
u8 mallocFailed = db->mallocFailed;
sqlite3BeginBenignMalloc();
if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db);
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
sqlite3EndBenignMalloc();
db->mallocFailed = mallocFailed;
@@ -2489,7 +2486,8 @@ int sqlite3VdbeReset(Vdbe *p){
** to sqlite3_step(). For consistency (since sqlite3_step() was
** called), set the database error in this case as well.
*/
sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
sqlite3Error(db, p->rc, 0);
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
@@ -2660,7 +2658,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor *p){
#endif
p->deferredMoveto = 0;
p->cacheStatus = CACHE_STALE;
}else if( p->pCursor ){
}else if( ALWAYS(p->pCursor) ){
int hasMoved;
int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved);
if( rc ) return rc;
@@ -2827,15 +2825,21 @@ static u64 floatSwap(u64 in){
** buf. It is assumed that the caller has allocated sufficient space.
** Return the number of bytes written.
**
** nBuf is the amount of space left in buf[]. The caller is responsible
** for allocating enough space to buf[] to hold the entire field, exclusive
** of the pMem->u.nZero bytes for a MEM_Zero value.
** nBuf is the amount of space left in buf[]. nBuf must always be
** large enough to hold the entire field. Except, if the field is
** a blob with a zero-filled tail, then buf[] might be just the right
** size to hold everything except for the zero-filled tail. If buf[]
** is only big enough to hold the non-zero prefix, then only write that
** prefix into buf[]. But if buf[] is large enough to hold both the
** prefix and the tail then write the prefix and set the tail to all
** zeros.
**
** Return the number of bytes actually written into buf[]. The number
** of bytes in the zero-filled tail is included in the return value only
** if those bytes were zeroed in buf[].
*/
u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
u32 serial_type = sqlite3VdbeSerialType(pMem, file_format);
u32 len;
/* Integer and Real */
@@ -2850,6 +2854,7 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
v = pMem->u.i;
}
len = i = sqlite3VdbeSerialTypeLen(serial_type);
assert( len<=(u32)nBuf );
while( i-- ){
buf[i] = (u8)(v&0xFF);
v >>= 8;
@@ -2861,8 +2866,17 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
if( serial_type>=12 ){
assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
== (int)sqlite3VdbeSerialTypeLen(serial_type) );
assert( pMem->n<=nBuf );
len = pMem->n;
memcpy(buf, pMem->z, len);
if( pMem->flags & MEM_Zero ){
len += pMem->u.nZero;
assert( nBuf>=0 );
if( len > (u32)nBuf ){
len = (u32)nBuf;
}
memset(&buf[pMem->n], 0, len-pMem->n);
}
return len;
}
@@ -2952,12 +2966,15 @@ u32 sqlite3VdbeSerialGet(
return 0;
}
default: {
static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
u32 len = (serial_type-12)/2;
pMem->z = (char *)buf;
pMem->n = len;
pMem->xDel = 0;
pMem->flags = aFlag[serial_type&1];
if( serial_type&0x01 ){
pMem->flags = MEM_Str | MEM_Ephem;
}else{
pMem->flags = MEM_Blob | MEM_Ephem;
}
return len;
}
}
@@ -3096,11 +3113,9 @@ int sqlite3VdbeRecordCompare(
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB );
assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField );
assert( pKeyInfo->aSortOrder!=0 );
assert( pKeyInfo->nField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
while( idx1<szHdr1 && i<pPKey2->nField ){
u32 serial_type1;
/* Read the serial types for the next element in each key. */
@@ -3133,7 +3148,7 @@ int sqlite3VdbeRecordCompare(
return rc;
}
i++;
}while( idx1<szHdr1 && i<pPKey2->nField );
}
/* No memory allocation is ever used on mem1. Prove this using
** the following assert(). If the assert() fails, it indicates a
@@ -3191,7 +3206,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
/* Read in the complete content of the index entry */
memset(&m, 0, sizeof(m));
rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m);
if( rc ){
return rc;
}
@@ -3269,7 +3284,7 @@ int sqlite3VdbeIdxKeyCompare(
return SQLITE_CORRUPT_BKPT;
}
memset(&m, 0, sizeof(m));
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m);
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
if( rc ){
return rc;
}
+3 -5
View File
@@ -64,8 +64,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
rc = sqlite3_step(p->pStmt);
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
u32 type = pC->aType[p->iCol];
u32 type = v->apCsr[0]->aType[p->iCol];
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
@@ -74,9 +73,9 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
sqlite3_finalize(p->pStmt);
p->pStmt = 0;
}else{
p->iOffset = pC->aType[p->iCol + pC->nField];
p->iOffset = v->apCsr[0]->aOffset[p->iCol];
p->nByte = sqlite3VdbeSerialTypeLen(type);
p->pCsr = pC->pCursor;
p->pCsr = v->apCsr[0]->pCursor;
sqlite3BtreeEnterCursor(p->pCsr);
sqlite3BtreeCacheOverflow(p->pCsr);
sqlite3BtreeLeaveCursor(p->pCsr);
@@ -329,7 +328,6 @@ blob_open_out:
}
sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
+73 -46
View File
@@ -59,14 +59,18 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
/*
** Make sure pMem->z points to a writable allocation of at least
** min(n,32) bytes.
** n bytes.
**
** If the bPreserve argument is true, then copy of the content of
** pMem->z into the new allocation. pMem must be either a string or
** blob if bPreserve is true. If bPreserve is false, any prior content
** in pMem->z is discarded.
** If the third argument passed to this function is true, then memory
** cell pMem must contain a string or blob. In this case the content is
** preserved. Otherwise, if the third parameter to this function is false,
** any current string or blob value may be discarded.
**
** This function sets the MEM_Dyn flag and clears any xDel callback.
** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
** not set, Mem.n is zeroed.
*/
int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
assert( 1 >=
((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
(((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
@@ -75,39 +79,37 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
);
assert( (pMem->flags&MEM_RowSet)==0 );
/* If the bPreserve flag is set to true, then the memory cell must already
/* If the preserve flag is set to true, then the memory cell must already
** contain a valid string or blob value. */
assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
testcase( bPreserve && pMem->z==0 );
assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
if( n<32 ) n = 32;
if( bPreserve && pMem->z==pMem->zMalloc ){
if( n<32 ) n = 32;
if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
if( preserve && pMem->z==pMem->zMalloc ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
bPreserve = 0;
preserve = 0;
}else{
sqlite3DbFree(pMem->db, pMem->zMalloc);
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
}
if( pMem->zMalloc==0 ){
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Null;
return SQLITE_NOMEM;
}
}
if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
memcpy(pMem->zMalloc, pMem->z, pMem->n);
}
if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){
if( pMem->flags&MEM_Dyn && pMem->xDel ){
assert( pMem->xDel!=SQLITE_DYNAMIC );
pMem->xDel((void *)(pMem->z));
}
pMem->z = pMem->zMalloc;
pMem->flags &= ~(MEM_Ephem|MEM_Static);
if( pMem->z==0 ){
pMem->flags = MEM_Null;
}else{
pMem->flags &= ~(MEM_Ephem|MEM_Static);
}
pMem->xDel = 0;
return SQLITE_OK;
return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
}
/*
@@ -293,18 +295,23 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
*/
void sqlite3VdbeMemRelease(Mem *p){
VdbeMemRelease(p);
if( p->zMalloc ){
sqlite3DbFree(p->db, p->zMalloc);
p->zMalloc = 0;
}
sqlite3DbFree(p->db, p->zMalloc);
p->z = 0;
assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */
p->zMalloc = 0;
p->xDel = 0;
}
/*
** Convert a 64-bit IEEE double into a 64-bit signed integer.
** If the double is out of range of a 64-bit signed integer then
** return the closest available 64-bit signed integer.
** If the double is too large, return 0x8000000000000000.
**
** Most systems appear to do this simply by assigning
** variables and without the extra range tests. But
** there are reports that windows throws an expection
** if the floating point value is out of range. (See ticket #2880.)
** Because we do not completely understand the problem, we will
** take the conservative approach and always do range tests
** before attempting the conversion.
*/
static i64 doubleToInt64(double r){
#ifdef SQLITE_OMIT_FLOATING_POINT
@@ -321,10 +328,14 @@ static i64 doubleToInt64(double r){
static const i64 maxInt = LARGEST_INT64;
static const i64 minInt = SMALLEST_INT64;
if( r<=(double)minInt ){
if( r<(double)minInt ){
return minInt;
}else if( r>(double)maxInt ){
/* minInt is correct here - not maxInt. It turns out that assigning
** a very large positive number to an integer results in a very large
** negative integer. This makes no sense, but it is what x86 hardware
** does so for compatibility we will do the same in software. */
return minInt;
}else if( r>=(double)maxInt ){
return maxInt;
}else{
return (i64)r;
}
@@ -406,11 +417,17 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
**
** The second and third terms in the following conditional enforces
** the second condition under the assumption that addition overflow causes
** values to wrap around.
** values to wrap around. On x86 hardware, the third term is always
** true and could be omitted. But we leave it in because other
** architectures might behave differently.
*/
if( pMem->r==(double)pMem->u.i
&& pMem->u.i>SMALLEST_INT64
#if defined(__i486__) || defined(__x86_64__)
&& ALWAYS(pMem->u.i<LARGEST_INT64)
#else
&& pMem->u.i<LARGEST_INT64
#endif
){
pMem->flags |= MEM_Int;
}
@@ -482,9 +499,6 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
MemSetTypeFlag(pMem, MEM_Null);
pMem->type = SQLITE_NULL;
}
void sqlite3ValueSetNull(sqlite3_value *p){
sqlite3VdbeMemSetNull((Mem*)p);
}
/*
** Delete any previous value and set the value to be a BLOB of length
@@ -882,13 +896,13 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
*/
int sqlite3VdbeMemFromBtree(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
u32 offset, /* Offset from the start of data to return bytes from. */
u32 amt, /* Number of bytes to return. */
int offset, /* Offset from the start of data to return bytes from. */
int amt, /* Number of bytes to return. */
int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
char *zData; /* Data from the btree layer */
u32 available = 0; /* Number of bytes available on the local btree page */
int available = 0; /* Number of bytes available on the local btree page */
int rc = SQLITE_OK; /* Return code */
assert( sqlite3BtreeCursorIsValid(pCur) );
@@ -903,7 +917,7 @@ int sqlite3VdbeMemFromBtree(
}
assert( zData!=0 );
if( offset+amt<=available ){
if( offset+amt<=available && (pMem->flags&MEM_Dyn)==0 ){
sqlite3VdbeMemRelease(pMem);
pMem->z = &zData[offset];
pMem->flags = MEM_Blob|MEM_Ephem;
@@ -922,7 +936,7 @@ int sqlite3VdbeMemFromBtree(
sqlite3VdbeMemRelease(pMem);
}
}
pMem->n = (int)amt;
pMem->n = amt;
return rc;
}
@@ -1019,7 +1033,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
int i; /* Counter variable */
int nCol = pIdx->nColumn; /* Number of index columns including rowid */
nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord));
nByte = sizeof(Mem) * nCol + sizeof(UnpackedRecord);
pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
if( pRec ){
pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
@@ -1027,7 +1041,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
assert( pRec->pKeyInfo->enc==ENC(db) );
pRec->flags = UNPACKED_PREFIX_MATCH;
pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
pRec->aMem = (Mem *)&pRec[1];
for(i=0; i<nCol; i++){
pRec->aMem[i].flags = MEM_Null;
pRec->aMem[i].type = SQLITE_NULL;
@@ -1081,7 +1095,16 @@ static int valueFromExpr(
return SQLITE_OK;
}
op = pExpr->op;
/* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT4.
** The ifdef here is to enable us to achieve 100% branch test coverage even
** when SQLITE_ENABLE_STAT4 is omitted.
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( op==TK_REGISTER ) op = pExpr->op2;
#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
#endif
/* Handle negative integers in a single step. This is needed in the
** case when the value is -9223372036854775808.
@@ -1222,7 +1245,7 @@ static void recordFunc(
}else{
aRet[0] = nSerial+1;
sqlite3PutVarint(&aRet[1], iSerial);
sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format);
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
sqlite3DbFree(db, aRet);
}
@@ -1300,9 +1323,10 @@ int sqlite3Stat4ProbeSetValue(
pVal = valueNew(db, &alloc);
if( pVal ){
sqlite3VdbeMemSetNull((Mem*)pVal);
*pbOk = 1;
}
}else if( pExpr->op==TK_VARIABLE
|| NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
|| (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
){
Vdbe *v;
int iBindVar = pExpr->iColumn;
@@ -1315,13 +1339,16 @@ int sqlite3Stat4ProbeSetValue(
sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
}
pVal->db = pParse->db;
*pbOk = 1;
sqlite3VdbeMemStoreType((Mem*)pVal);
}
}else{
*pbOk = 0;
}
}else{
rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, &alloc);
*pbOk = (pVal!=0);
}
*pbOk = (pVal!=0);
assert( pVal==0 || pVal->db==db );
return rc;
+8 -13
View File
@@ -92,7 +92,6 @@ char *sqlite3VdbeExpandSql(
const char *zStart = zRawSql;
while( *(zRawSql++)!='\n' && *zRawSql );
sqlite3StrAccumAppend(&out, "-- ", 3);
assert( (zRawSql - zStart) > 0 );
sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
}
}else{
@@ -125,9 +124,9 @@ char *sqlite3VdbeExpandSql(
if( pVar->flags & MEM_Null ){
sqlite3StrAccumAppend(&out, "NULL", 4);
}else if( pVar->flags & MEM_Int ){
sqlite3XPrintf(&out, 0, "%lld", pVar->u.i);
sqlite3XPrintf(&out, "%lld", pVar->u.i);
}else if( pVar->flags & MEM_Real ){
sqlite3XPrintf(&out, 0, "%!.15g", pVar->r);
sqlite3XPrintf(&out, "%!.15g", pVar->r);
}else if( pVar->flags & MEM_Str ){
int nOut; /* Number of bytes of the string text to include in output */
#ifndef SQLITE_OMIT_UTF16
@@ -148,17 +147,15 @@ char *sqlite3VdbeExpandSql(
while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
}
#endif
sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z);
sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
#ifdef SQLITE_TRACE_SIZE_LIMIT
if( nOut<pVar->n ){
sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
}
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
#endif
#ifndef SQLITE_OMIT_UTF16
if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
#endif
}else if( pVar->flags & MEM_Zero ){
sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero);
sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
}else{
int nOut; /* Number of bytes of the blob to include in output */
assert( pVar->flags & MEM_Blob );
@@ -168,13 +165,11 @@ char *sqlite3VdbeExpandSql(
if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
#endif
for(i=0; i<nOut; i++){
sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff);
sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
}
sqlite3StrAccumAppend(&out, "'", 1);
#ifdef SQLITE_TRACE_SIZE_LIMIT
if( nOut<pVar->n ){
sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
}
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
#endif
}
}
@@ -233,7 +228,7 @@ void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
}
va_start(ap, zFormat);
sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap);
sqlite3VXPrintf(&p->str, 1, zFormat, ap);
va_end(ap);
}
}
-1
View File
@@ -738,7 +738,6 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sqlite3VdbeFinalize(pParse->pVdbe);
}
sqlite3DeleteTable(db, pParse->pNewTable);
sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
}
+33 -28
View File
@@ -669,6 +669,9 @@ static int isLikeOrGlob(
pRight = pList->a[0].pExpr;
op = pRight->op;
if( op==TK_REGISTER ){
op = pRight->op2;
}
if( op==TK_VARIABLE ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
@@ -1905,7 +1908,8 @@ static void whereKeyStats(
#ifndef SQLITE_DEBUG
UNUSED_PARAMETER( pParse );
#endif
assert( pRec!=0 );
assert( pRec!=0 || pParse->db->mallocFailed );
if( pRec==0 ) return;
iCol = pRec->nField - 1;
assert( pIdx->nSample>0 );
assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
@@ -2405,7 +2409,7 @@ static int codeEqualityTerm(
}else{
pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
}
pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
}else{
pLevel->u.in.nIn = 0;
@@ -2568,7 +2572,7 @@ static void explainAppendTerm(
const char *zOp /* Name of the operator */
){
if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5);
sqlite3StrAccumAppendAll(pStr, zColumn);
sqlite3StrAccumAppend(pStr, zColumn, -1);
sqlite3StrAccumAppend(pStr, zOp, 1);
sqlite3StrAccumAppend(pStr, "?", 1);
}
@@ -2614,7 +2618,7 @@ static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
}else{
if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5);
sqlite3StrAccumAppend(&txt, "ANY(", 4);
sqlite3StrAccumAppendAll(&txt, z);
sqlite3StrAccumAppend(&txt, z, -1);
sqlite3StrAccumAppend(&txt, ")", 1);
}
}
@@ -2755,7 +2759,7 @@ static Bitmask codeOneLoopStart(
bRev = (pWInfo->revMask>>iLevel)&1;
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
&& (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
VdbeNoopComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
/* Create labels for the "break" and "continue" instructions
** for the current loop. Jump to addrBrk to break out of a loop.
@@ -2983,6 +2987,7 @@ static Bitmask codeOneLoopStart(
OP_IdxLT /* 2: (end_constraints && bRev) */
};
u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */
u16 nSkip = pLoop->u.btree.nSkip; /* Number of left index terms to skip */
int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
int regBase; /* Base register holding constraint values */
int r1; /* Temp register */
@@ -2997,11 +3002,11 @@ static Bitmask codeOneLoopStart(
int nExtraReg = 0; /* Number of extra registers needed */
int op; /* Instruction opcode */
char *zStartAff; /* Affinity for start of range constraint */
char cEndAff = 0; /* Affinity for end of range constraint */
char *zEndAff; /* Affinity for end of range constraint */
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
assert( nEq>=pLoop->u.btree.nSkip );
assert( nEq>=nSkip );
/* If this loop satisfies a sort order (pOrderBy) request that
** was passed to this function to implement a "SELECT min(x) ..."
@@ -3015,7 +3020,7 @@ static Bitmask codeOneLoopStart(
&& (pWInfo->bOBSat!=0)
&& (pIdx->nKeyCol>nEq)
){
assert( pLoop->u.btree.nSkip==0 );
assert( nSkip==0 );
isMinQuery = 1;
nExtraReg = 1;
}
@@ -3038,8 +3043,7 @@ static Bitmask codeOneLoopStart(
** starting at regBase.
*/
regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
if( zStartAff ) cEndAff = zStartAff[nEq];
zEndAff = sqlite3DbStrDup(db, zStartAff);
addrNxt = pLevel->addrNxt;
/* If we are doing a reverse order scan on an ascending index, or
@@ -3109,15 +3113,23 @@ static Bitmask codeOneLoopStart(
if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
}
if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE
&& !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff)
){
codeApplyAffinity(pParse, regBase+nEq, 1, &cEndAff);
}
if( zEndAff ){
if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){
/* Since the comparison is to be performed with no conversions
** applied to the operands, set the affinity to apply to pRight to
** SQLITE_AFF_NONE. */
zEndAff[nEq] = SQLITE_AFF_NONE;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){
zEndAff[nEq] = SQLITE_AFF_NONE;
}
}
codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
nConstraint++;
testcase( pRangeEnd->wtFlags & TERM_VIRTUAL );
}
sqlite3DbFree(db, zStartAff);
sqlite3DbFree(db, zEndAff);
/* Top of the loop body */
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@@ -3142,7 +3154,6 @@ static Bitmask codeOneLoopStart(
if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
&& (j = pIdx->aiColumn[nEq])>=0
&& pIdx->pTable->aCol[j].notNull==0
&& (nEq || (pLoop->wsFlags & WHERE_BTM_LIMIT)==0)
){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
VdbeComment((v, "%s", pIdx->pTable->aCol[j].zName));
@@ -3460,7 +3471,7 @@ static Bitmask codeOneLoopStart(
if( pAlt->wtFlags & (TERM_CODED) ) continue;
testcase( pAlt->eOperator & WO_EQ );
testcase( pAlt->eOperator & WO_IN );
VdbeModuleComment((v, "begin transitive constraint"));
VdbeNoopComment((v, "begin transitive constraint"));
pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
if( pEAlt ){
*pEAlt = *pAlt->pExpr;
@@ -3917,17 +3928,10 @@ static int whereLoopAddBtreeIndex(
saved_nOut = pNew->nOut;
pNew->rSetup = 0;
rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
/* Consider using a skip-scan if there are no WHERE clause constraints
** available for the left-most terms of the index, and if the average
** number of repeats in the left-most terms is at least 18. The magic
** number 18 was found by experimentation to be the payoff point where
** skip-scan become faster than a full-scan.
*/
if( pTerm==0
&& saved_nEq==saved_nSkip
&& saved_nEq+1<pProbe->nKeyCol
&& pProbe->aiRowEst[saved_nEq+1]>=18 /* TUNING: Minimum for skip-scan */
&& pProbe->aiRowEst[saved_nEq+1]>50
){
LogEst nIter;
pNew->u.btree.nEq++;
@@ -5423,6 +5427,7 @@ WhereInfo *sqlite3WhereBegin(
*/
initMaskSet(pMaskSet);
whereClauseInit(&pWInfo->sWC, pWInfo);
sqlite3ExprCodeConstants(pParse, pWhere);
whereSplit(&pWInfo->sWC, pWhere, TK_AND);
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
@@ -5737,7 +5742,7 @@ WhereInfo *sqlite3WhereBegin(
}
/* Done. */
VdbeModuleComment((v, "Begin WHERE-core"));
VdbeNoopComment((v, "Begin WHERE-core"));
return pWInfo;
/* Jump here if malloc fails */
@@ -5764,7 +5769,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Generate loop termination code.
*/
VdbeModuleComment((v, "End WHERE-core"));
VdbeNoopComment((v, "End WHERE-core"));
sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){
int addr;
@@ -5810,7 +5815,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
sqlite3VdbeJumpHere(v, addr);
}
VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
VdbeNoopComment((v, "End WHERE-loop%d: %s", i,
pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
}
+1 -2
View File
@@ -805,9 +805,8 @@ do_test 16.1 {
ANALYZE;
}
set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
puts -nonewline " (nByte=$nByte nByte2=$nByte2)"
expr {$nByte2 > $nByte+900 && $nByte2 < $nByte+1100}
expr {$nByte2 > $nByte+900 && $nByte2 < $nByte+1050}
} {1}
#-------------------------------------------------------------------------
+1 -1
View File
@@ -15,7 +15,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {![info exists __GNUC__] || [regexp arm $tcl_platform(machine)]} {
if {![info exists __GNUC__]} {
finish_test
return
}
+1 -1
View File
@@ -216,7 +216,7 @@ do_test autoinc-2.27 {
} {t1 1238}
do_test autoinc-2.28 {
execsql {
UPDATE sqlite_sequence SET seq='-12345678901234567890'
UPDATE sqlite_sequence SET seq='12345678901234567890'
WHERE name='t1';
INSERT INTO t1 VALUES(NULL,6);
SELECT * FROM t1;
-1
View File
@@ -1191,7 +1191,6 @@ do_test capi3-18.2 {
sqlite3_reset $STMT
sqlite3_errcode db
} {SQLITE_SCHEMA}
breakpoint
do_test capi3-18.3 {
sqlite3_errmsg db
} {database schema has changed}
-5
View File
@@ -305,11 +305,6 @@ foreach {i conf1 cmd t0 t1 t2 t3 t4} {
15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 1
16 {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0 0 0
} {
# When using in-memory journals, no temporary files are required for
# statement journals.
if {[permutation] == "inmemory_journal"} { set t4 0 }
if {$t0} {set t1 {UNIQUE constraint failed: t1.a}}
if {[info exists TEMP_STORE] && $TEMP_STORE==3} {
set t3 0
-4
View File
@@ -25,10 +25,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# Construct a large database for testing.
#
do_test corrupt-1.1 {
-4
View File
@@ -23,10 +23,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
set presql ""
catch { set presql "$::G(perm:presql);" }
unset -nocomplain ::G(perm:presql)
-4
View File
@@ -23,10 +23,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas||direct_read {
-4
View File
@@ -23,10 +23,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas {
-4
View File
@@ -19,10 +19,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# These tests deal with corrupt database files
#
database_may_be_corrupt
# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas {
-4
View File
@@ -24,10 +24,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas {
-4
View File
@@ -24,10 +24,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas {
-4
View File
@@ -24,10 +24,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas||!autovacuum {
-4
View File
@@ -24,10 +24,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# We must have the page_size pragma for these tests to work.
#
ifcapable !pager_pragmas {
-4
View File
@@ -24,10 +24,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# Create a database to work with.
#
-4
View File
@@ -30,10 +30,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
do_test corruptB-1.1 {
execsql {
+1 -9
View File
@@ -27,10 +27,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# Construct a compact, dense database for testing.
#
do_test corruptC-1.1 {
@@ -206,10 +202,6 @@ do_test corruptC-2.8 {
} {1 {database disk image is malformed}}
# corruption (seed 170434)
#
# UPDATE: Prior to 3.8.2, this used to return SQLITE_CORRUPT. It no longer
# does. That is Ok, the point of these tests is to verify that no buffer
# overruns or overreads can be caused by corrupt databases.
do_test corruptC-2.9 {
db close
forcecopy test.bu test.db
@@ -219,7 +211,7 @@ do_test corruptC-2.9 {
sqlite3 db test.db
catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;}
} {0 {}}
} {1 {database disk image is malformed}}
# corruption (seed 186504)
do_test corruptC-2.10 {
-4
View File
@@ -19,10 +19,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
#--------------------------------------------------------------------------
# OVERVIEW
#
-4
View File
@@ -24,10 +24,6 @@ source $testdir/tester.tcl
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# Do not run the tests in this file if ENABLE_OVERSIZE_CELL_CHECK is on.
#
ifcapable oversize_cell_check {
-4
View File
@@ -19,10 +19,6 @@ set testprefix corruptF
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
proc str {i} { format %08d $i }
# Create a 6 page database containing a single table - t1. Table t1
-4
View File
@@ -19,10 +19,6 @@ set testprefix corruptG
#
do_not_use_codec
# These tests deal with corrupt database files
#
database_may_be_corrupt
# Create a simple database with a single entry. Then corrupt the
# header-size varint on the index payload so that it maps into a
# negative number. Try to use the database.
-35
View File
@@ -64,39 +64,4 @@ ifcapable pragma {
} {0 c {} 0 'abc' 0}
}
do_execsql_test default-3.1 {
CREATE TABLE t3(
a INTEGER PRIMARY KEY AUTOINCREMENT,
b INT DEFAULT 12345 UNIQUE NOT NULL CHECK( b>=0 AND b<99999 ),
c VARCHAR(123,456) DEFAULT 'hello' NOT NULL ON CONFLICT REPLACE,
d REAL,
e FLOATING POINT(5,10) DEFAULT 4.36,
f NATIONAL CHARACTER(15) COLLATE RTRIM,
g LONG INTEGER DEFAULT( 3600*12 )
);
INSERT INTO t3 VALUES(null, 5, 'row1', '5.25', 'xyz', 321, '432');
SELECT a, typeof(a), b, typeof(b), c, typeof(c),
d, typeof(d), e, typeof(e), f, typeof(f),
g, typeof(g) FROM t3;
} {1 integer 5 integer row1 text 5.25 real xyz text 321 text 432 integer}
do_execsql_test default-3.2 {
DELETE FROM t3;
INSERT INTO t3 DEFAULT VALUES;
SELECT * FROM t3;
} {2 12345 hello {} 4.36 {} 43200}
do_execsql_test default-3.3 {
CREATE TABLE t300(
a INT DEFAULT 2147483647,
b INT DEFAULT 2147483648,
c INT DEFAULT +9223372036854775807,
d INT DEFAULT -2147483647,
e INT DEFAULT -2147483648,
f INT DEFAULT -9223372036854775808,
g INT DEFAULT (-(-9223372036854775808)),
h INT DEFAULT (-(-9223372036854775807))
);
INSERT INTO t300 DEFAULT VALUES;
SELECT * FROM t300;
} {2147483647 2147483648 9223372036854775807 -2147483647 -2147483648 -9223372036854775808 9.22337203685478e+18 9223372036854775807}
finish_test
+1 -9
View File
@@ -1103,7 +1103,7 @@ do_catchsql_test e_createtable-3.11.5 {
# EVIDENCE-OF: R-52382-54248 Each table in SQLite may have at most one
# PRIMARY KEY.
#
# EVIDENCE-OF: R-31826-01813 An error is raised if more than one PRIMARY
# EVIDENCE-OF: R-62315-57691 An error is rasied if more than one PRIMARY
# KEY clause appears in a CREATE TABLE statement.
#
# To test the two above, show that zero primary keys is Ok, one primary
@@ -1654,10 +1654,6 @@ do_execsql_test 4.19.4 { SELECT * FROM t5 } {}
# of the special case-independent names "rowid", "oid", or "_rowid_" in
# place of a column name.
#
# EVIDENCE-OF: R-06726-07466 A column name can be any of the names
# defined in the CREATE TABLE statement or one of the following special
# identifiers: "ROWID", "OID", or "_ROWID_".
#
drop_all_tables
do_execsql_test 5.1.0 {
CREATE TABLE t1(x, y);
@@ -1682,10 +1678,6 @@ do_createtable_tests 5.1 {
# explicitly declared column and cannot be used to retrieve the integer
# rowid value.
#
# EVIDENCE-OF: R-44615-33286 The special identifiers only refer to the
# row key if the CREATE TABLE statement does not define a real column
# with the same name.
#
do_execsql_test 5.2.0 {
CREATE TABLE t2(oid, b);
CREATE TABLE t3(a, _rowid_);
+14 -57
View File
@@ -1081,9 +1081,9 @@ ifcapable !icu {
# EVIDENCE-OF: R-33693-50180 The REGEXP operator is a special syntax for
# the regexp() user function.
#
# EVIDENCE-OF: R-65524-61849 If an application-defined SQL function
# named "regexp" is added at run-time, then the "X REGEXP Y" operator
# will be implemented as a call to "regexp(Y,X)".
# EVIDENCE-OF: R-57289-13578 If a application-defined SQL function named
# "regexp" is added at run-time, that function will be called in order
# to implement the REGEXP operator.
#
proc regexpfunc {args} {
eval lappend ::regexpargs $args
@@ -1407,12 +1407,10 @@ do_test e_expr-26.1.6 { set ::evalcount } {5}
#-------------------------------------------------------------------------
# Test statements related to CAST expressions.
#
# EVIDENCE-OF: R-20854-17109 A CAST conversion is similar to the
# conversion that takes place when a column affinity is applied to a
# value except that with the CAST operator the conversion always takes
# place even if the conversion lossy and irreversible, whereas column
# affinity only changes the data type of a value if the change is
# lossless and reversible.
# EVIDENCE-OF: R-65079-31758 Application of a CAST expression is
# different to application of a column affinity, as with a CAST
# expression the storage class conversion is forced even if it is lossy
# and irrreversible.
#
do_execsql_test e_expr-27.1.1 {
CREATE TABLE t3(a TEXT, b REAL, c INTEGER);
@@ -1596,29 +1594,26 @@ do_expr_test e_expr-30.4.1 { CAST('' AS INTEGER) } integer 0
do_expr_test e_expr-30.4.2 { CAST('not a number' AS INTEGER) } integer 0
do_expr_test e_expr-30.4.3 { CAST('XXI' AS INTEGER) } integer 0
# EVIDENCE-OF: R-02752-50091 A cast of a REAL value into an INTEGER
# results in the integer between the REAL value and zero that is closest
# to the REAL value.
# EVIDENCE-OF: R-00741-38776 A cast of a REAL value into an INTEGER will
# truncate the fractional part of the REAL.
#
do_expr_test e_expr-31.1.1 { CAST(3.14159 AS INTEGER) } integer 3
do_expr_test e_expr-31.1.2 { CAST(1.99999 AS INTEGER) } integer 1
do_expr_test e_expr-31.1.3 { CAST(-1.99999 AS INTEGER) } integer -1
do_expr_test e_expr-31.1.4 { CAST(-0.99999 AS INTEGER) } integer 0
# EVIDENCE-OF: R-51517-40824 If a REAL is greater than the greatest
# possible signed integer (+9223372036854775807) then the result is the
# greatest possible signed integer and if the REAL is less than the
# least possible signed integer (-9223372036854775808) then the result
# is the least possible signed integer.
# EVIDENCE-OF: R-49503-28105 If a REAL is too large to be represented as
# an INTEGER then the result of the cast is the largest negative
# integer: -9223372036854775808.
#
do_expr_test e_expr-31.2.1 { CAST(2e+50 AS INT) } integer 9223372036854775807
do_expr_test e_expr-31.2.1 { CAST(2e+50 AS INT) } integer -9223372036854775808
do_expr_test e_expr-31.2.2 { CAST(-2e+50 AS INT) } integer -9223372036854775808
do_expr_test e_expr-31.2.3 {
CAST(-9223372036854775809.0 AS INT)
} integer -9223372036854775808
do_expr_test e_expr-31.2.4 {
CAST(9223372036854775809.0 AS INT)
} integer 9223372036854775807
} integer -9223372036854775808
# EVIDENCE-OF: R-09295-61337 Casting a TEXT or BLOB value into NUMERIC
@@ -1852,43 +1847,5 @@ foreach {tn expr} {
do_expr_test e_expr-36.4.$tn $expr null {}
}
# EVIDENCE-OF: R-62477-06476 For example, the values NULL, 0.0, 0,
# 'english' and '0' are all considered to be false.
#
do_execsql_test e_expr-37.1 {
SELECT CASE WHEN NULL THEN 'true' ELSE 'false' END;
} {false}
do_execsql_test e_expr-37.2 {
SELECT CASE WHEN 0.0 THEN 'true' ELSE 'false' END;
} {false}
do_execsql_test e_expr-37.3 {
SELECT CASE WHEN 0 THEN 'true' ELSE 'false' END;
} {false}
do_execsql_test e_expr-37.4 {
SELECT CASE WHEN 'engligh' THEN 'true' ELSE 'false' END;
} {false}
do_execsql_test e_expr-37.5 {
SELECT CASE WHEN '0' THEN 'true' ELSE 'false' END;
} {false}
# EVIDENCE-OF: R-55532-10108 Values 1, 1.0, 0.1, -0.1 and '1english' are
# considered to be true.
#
do_execsql_test e_expr-37.6 {
SELECT CASE WHEN 1 THEN 'true' ELSE 'false' END;
} {true}
do_execsql_test e_expr-37.7 {
SELECT CASE WHEN 1.0 THEN 'true' ELSE 'false' END;
} {true}
do_execsql_test e_expr-37.8 {
SELECT CASE WHEN 0.1 THEN 'true' ELSE 'false' END;
} {true}
do_execsql_test e_expr-37.9 {
SELECT CASE WHEN -0.1 THEN 'true' ELSE 'false' END;
} {true}
do_execsql_test e_expr-37.10 {
SELECT CASE WHEN '1english' THEN 'true' ELSE 'false' END;
} {true}
finish_test
+1 -4
View File
@@ -69,10 +69,7 @@ proc catch_fk_error {zSql} {
if {[string match {*foreign key*} $msg]} {
return ""
}
if {$msg eq "out of memory"
|| $msg eq "FOREIGN KEY constraint failed"
|| $msg eq "constraint failed"
} {
if {$msg eq "out of memory" || $msg eq "constraint failed"} {
error 1
}
error $msg
+1 -1
View File
@@ -10,7 +10,7 @@
# $Id: fts3.test,v 1.2 2008/07/23 18:17:32 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/permutations.test
set testprefix fts3varint
ifcapable !fts3 {
-18
View File
@@ -1319,24 +1319,6 @@ do_test func-29.6 {
set x
} {1}
# The OP_Column opcode has an optimization that avoids loading content
# for fields with content-length=0 when the content offset is on an overflow
# page. Make sure the optimization works.
#
do_execsql_test func-29.10 {
CREATE TABLE t29b(a,b,c,d,e,f,g,h,i);
INSERT INTO t29b
VALUES(1, hex(randomblob(2000)), null, 0, 1, '', zeroblob(0),'x',x'01');
SELECT typeof(c), typeof(d), typeof(e), typeof(f),
typeof(g), typeof(h), typeof(i) FROM t29b;
} {null integer integer text blob text blob}
do_execsql_test func-29.11 {
SELECT length(f), length(g), length(h), length(i) FROM t29b;
} {0 0 1 1}
do_execsql_test func-29.12 {
SELECT quote(f), quote(g), quote(h), quote(i) FROM t29b;
} {'' X'' 'x' X'01'}
# EVIDENCE-OF: R-29701-50711 The unicode(X) function returns the numeric
# unicode code point corresponding to the first character of the string
# X.
-63
View File
@@ -1,63 +0,0 @@
# 2013-11-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.
#
#*************************************************************************
#
# Testing of function factoring and the SQLITE_DETERMINISTIC flag.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Verify that constant string expressions that get factored into initializing
# code are not reused between function parameters and other values in the
# VDBE program, as the function might have changed the encoding.
#
do_execsql_test func5-1.1 {
PRAGMA encoding=UTF16le;
CREATE TABLE t1(x,a,b,c);
INSERT INTO t1 VALUES(1,'ab','cd',1);
INSERT INTO t1 VALUES(2,'gh','ef',5);
INSERT INTO t1 VALUES(3,'pqr','fuzzy',99);
INSERT INTO t1 VALUES(4,'abcdefg','xy',22);
INSERT INTO t1 VALUES(5,'shoe','mayer',2953);
SELECT x FROM t1 WHERE c=instr('abcdefg',b) OR a='abcdefg' ORDER BY +x;
} {2 4}
do_execsql_test func5-1.2 {
SELECT x FROM t1 WHERE a='abcdefg' OR c=instr('abcdefg',b) ORDER BY +x;
} {2 4}
# Verify that SQLITE_DETERMINISTIC functions get factored out of the
# evaluation loop whereas non-deterministic functions do not. counter1()
# is marked as non-deterministic and so is not factored out of the loop,
# and it really is non-deterministic, returning a different result each
# time. But counter2() is marked as deterministic, so it does get factored
# out of the loop. counter2() has the same implementation as counter1(),
# returning a different result on each invocation, but because it is
# only invoked once outside of the loop, it appears to return the same
# result multiple times.
#
do_execsql_test func5-2.1 {
CREATE TABLE t2(x,y);
INSERT INTO t2 VALUES(1,2),(3,4),(5,6),(7,8);
SELECT x, y FROM t2 WHERE x+5=5+x ORDER BY +x;
} {1 2 3 4 5 6 7 8}
sqlite3_create_function db
do_execsql_test func5-2.2 {
SELECT x, y FROM t2
WHERE x+counter1('hello')=counter1('hello')+x
ORDER BY +x;
} {}
do_execsql_test func5-2.3 {
SELECT x, y FROM t2
WHERE x+counter2('hello')=counter2('hello')+x
ORDER BY +x;
} {1 2 3 4 5 6 7 8}
finish_test
-3
View File
@@ -18,9 +18,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# These tests deal with corrupt database files
#
database_may_be_corrupt
expr srand(123)
+2 -50
View File
@@ -127,52 +127,21 @@ db2 close
# depopulation of indices, to make sure the update-hook is not
# invoked incorrectly.
#
# EVIDENCE-OF: R-21999-45122 The sqlite3_update_hook() interface
# registers a callback function with the database connection identified
# by the first argument to be invoked whenever a row is updated,
# inserted or deleted in a rowid table.
# Simple tests
do_test hook-4.1.1a {
do_test hook-4.1.1 {
catchsql {
DROP TABLE t1;
}
unset -nocomplain ::update_hook
set ::update_hook {}
db update_hook [list lappend ::update_hook]
#
# EVIDENCE-OF: R-52223-27275 The update hook is not invoked when
# internal system tables are modified (i.e. sqlite_master and
# sqlite_sequence).
#
execsql {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t1w(a INT PRIMARY KEY, b) WITHOUT ROWID;
}
set ::update_hook
} {}
do_test hook-4.1.1b {
execsql {
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(3, 'three');
INSERT INTO t1w SELECT * FROM t1;
}
db update_hook [list lappend ::update_hook]
} {}
# EVIDENCE-OF: R-15506-57666 The second callback argument is one of
# SQLITE_INSERT, SQLITE_DELETE, or SQLITE_UPDATE, depending on the
# operation that caused the callback to be invoked.
#
# EVIDENCE-OF: R-29213-61195 The third and fourth arguments to the
# callback contain pointers to the database and table name containing
# the affected row.
#
# EVIDENCE-OF: R-30809-57812 The final callback parameter is the rowid
# of the row.
#
do_test hook-4.1.2 {
set ::update_hook {}
execsql {
INSERT INTO t1 VALUES(4, 'four');
DELETE FROM t1 WHERE b = 'two';
@@ -190,23 +159,6 @@ do_test hook-4.1.2 {
DELETE main t1 4 \
]
# EVIDENCE-OF: R-61808-14344 The sqlite3_update_hook() interface does
# not fire callbacks for changes to a WITHOUT ROWID table.
#
# EVIDENCE-OF: R-33257-44249 The update hook is not invoked when WITHOUT
# ROWID tables are modified.
#
do_test hook-4.1.2w {
set ::update_hook {}
execsql {
INSERT INTO t1w VALUES(4, 'four');
DELETE FROM t1w WHERE b = 'two';
UPDATE t1w SET b = '' WHERE a = 1 OR a = 3;
DELETE FROM t1w WHERE 1; -- Avoid the truncate optimization (for now)
}
set ::update_hook
} {}
ifcapable trigger {
# Update hook is not invoked for changes to sqlite_master
#
+1 -1
View File
@@ -258,7 +258,7 @@ do_ioerr_test ioerr-10 -ckrefcount true -tclprep {
INSERT INTO t1 SELECT (a+500)%900, 'good string' FROM t1;
}} msg
if {$msg != "UNIQUE constraint failed: t1.a"} {
if {$msg != "column a is not unique"} {
error $msg
}
}
-11
View File
@@ -36,17 +36,6 @@ do_test lastinsert-1.1 {
}
} {0 3}
# EVIDENCE-OF: R-47220-63683 The sqlite3_last_insert_rowid() function
# does not work for WITHOUT ROWID tables.
#
do_test lastinsert-1.1w {
catchsql {
create table t1w (k integer primary key) WITHOUT ROWID;
insert into t1w values (123456);
select last_insert_rowid(); -- returns 3 from above.
}
} {0 3}
# LIRID unchanged after an update on a table
do_test lastinsert-1.2 {
catchsql {
+1 -1
View File
@@ -355,7 +355,7 @@ do_ioerr_test misc7-16 -sqlprep {
COMMIT;
}} msg]
if {!$rc || ($rc && [string first "UNIQUE" $msg]==0)} {
if {!$rc || ($rc && [string first "columns" $msg]==0)} {
set msg
} else {
error $msg
-94
View File
@@ -1,94 +0,0 @@
# 2013-12-06
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests for the SQLITE_IOERR_NODB error condition: the database file file
# is unlinked or renamed out from under SQLite.
#
if {$tcl_platform(platform)!="unix"} return
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Create a database file for testing
#
do_execsql_test pager4-1.1 {
CREATE TABLE t1(a,b,c);
INSERT INTO t1 VALUES(673,'stone','philips');
SELECT * FROM t1;
} {673 stone philips}
# After renaming the database file while it is open, one can still
# read from the database, but writing returns a READONLY error.
#
file delete -force test-xyz.db
file rename test.db test-xyz.db
do_catchsql_test pager4-1.2 {
SELECT * FROM t1;
} {0 {673 stone philips}}
do_catchsql_test pager4-1.3 {
UPDATE t1 SET a=537;
} {1 {attempt to write a readonly database}}
# Creating a different database file with the same name of the original
# is detected and still leaves the database read-only.
#
sqlite3 db2 test.db
db2 eval {CREATE TABLE t2(x,y,z)}
do_catchsql_test pager4-1.4 {
UPDATE t1 SET a=948;
} {1 {attempt to write a readonly database}}
# Changing the name back clears the READONLY error
#
db2 close
file delete -force test.db
file rename test-xyz.db test.db
do_catchsql_test pager4-1.5 {
SELECT * FROM t1;
} {0 {673 stone philips}}
do_catchsql_test pager4-1.6 {
UPDATE t1 SET a=537;
SELECT * FROM t1;
} {0 {537 stone philips}}
# We can write to a renamed database if journal_mode=OFF or
# journal_mode=MEMORY.
#
file rename test.db test-xyz.db
do_catchsql_test pager4-1.7 {
PRAGMA journal_mode=OFF;
UPDATE t1 SET a=107;
SELECT * FROM t1;
} {0 {off 107 stone philips}}
do_catchsql_test pager4-1.8 {
PRAGMA journal_mode=MEMORY;
UPDATE t1 SET b='magpie';
SELECT * FROM t1;
} {0 {memory 107 magpie philips}}
# Any other journal mode gives a READONLY error
#
do_catchsql_test pager4-1.9 {
PRAGMA journal_mode=DELETE;
UPDATE t1 SET c='jaguar';
} {1 {attempt to write a readonly database}}
do_catchsql_test pager4-1.10 {
PRAGMA journal_mode=TRUNCATE;
UPDATE t1 SET c='jaguar';
} {1 {attempt to write a readonly database}}
do_catchsql_test pager4-1.11 {
PRAGMA journal_mode=PERSIST;
UPDATE t1 SET c='jaguar';
} {1 {attempt to write a readonly database}}
finish_test
-59
View File
@@ -1,59 +0,0 @@
# 2013-12-17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the printf() SQL function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test printf2-1.1 {
SELECT printf();
} {{}}
do_execsql_test printf2-1.2 {
SELECT printf('hello');
} {hello}
do_execsql_test printf2-1.3 {
SELECT printf('%d,%d,%d',55,-11,3421);
} {55,-11,3421}
do_execsql_test printf2-1.4 {
SELECT printf('%d,%d,%d',55,'-11',3421);
} {55,-11,3421}
do_execsql_test printf2-1.5 {
SELECT printf('%d,%d,%d,%d',55,'-11',3421);
} {55,-11,3421,0}
do_execsql_test printf2-1.6 {
SELECT printf('%.2f',3.141592653);
} {3.14}
do_execsql_test printf2-1.7 {
SELECT printf('%.*f',2,3.141592653);
} {3.14}
do_execsql_test printf2-1.8 {
SELECT printf('%*.*f',5,2,3.141592653);
} {{ 3.14}}
do_execsql_test printf2-1.9 {
SELECT printf('%d',314159.2653);
} {314159}
do_execsql_test printf2-1.10 {
SELECT printf('%lld',314159.2653);
} {314159}
do_execsql_test printf2-1.11 {
SELECT printf('%lld%n',314159.2653,'hi');
} {314159}
do_execsql_test printf2-1.12 {
SELECT printf('%.*z',5,'abcdefghijklmnop');
} {abcde}
do_execsql_test printf2-1.13 {
SELECT printf('%c','abcdefghijklmnop');
} {a}
finish_test
+1 -3
View File
@@ -12,9 +12,7 @@
# focus of this file is testing the magic ROWID column that is
# found on all tables.
#
# EVIDENCE-OF: R-36924-43758 By default, every row in SQLite has a
# special column, usually called the "rowid", that uniquely identifies
# that row within the table.
# $Id: rowid.test,v 1.21 2009/06/26 15:14:55 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-78
View File
@@ -1,78 +0,0 @@
#!/bin/sh
#
# This script runs the wordcount program in different ways, comparing
# the output from each.
#
# Select the source text to be analyzed.
#
if test "x$1" = "x";
then echo "Usage: $0 FILENAME [ARGS...]"; exit 1;
fi
# Do test runs
#
rm -f wcdb1.db
./wordcount --timer --summary wcdb1.db $* --insert >wc-out.txt
mv wc-out.txt wc-baseline.txt
rm -f wcdb2.db
./wordcount --timer --summary wcdb2.db $* --insert --without-rowid >wc-out.txt
if cmp -s wc-out.txt wc-baseline.txt;
then echo hi >/dev/null;
else echo ERROR:;
diff -u wc-baseline.txt wc-out.txt;
fi
rm -f wcdb1.db
./wordcount --timer --summary wcdb1.db $* --replace >wc-out.txt
if cmp -s wc-out.txt wc-baseline.txt;
then echo hi >/dev/null;
else echo ERROR:;
diff -u wc-baseline.txt wc-out.txt;
fi
rm -f wcdb2.db
./wordcount --timer --summary wcdb2.db $* --replace --without-rowid >wc-out.txt
if cmp -s wc-out.txt wc-baseline.txt;
then echo hi >/dev/null;
else echo ERROR:;
diff -u wc-baseline.txt wc-out.txt;
fi
rm -f wcdb1.db
./wordcount --timer --summary wcdb1.db $* --select >wc-out.txt
if cmp -s wc-out.txt wc-baseline.txt;
then echo hi >/dev/null;
else echo ERROR:;
diff -u wc-baseline.txt wc-out.txt;
fi
rm -f wcdb2.db
./wordcount --timer --summary wcdb2.db $* --select --without-rowid >wc-out.txt
if cmp -s wc-out.txt wc-baseline.txt;
then echo hi >/dev/null;
else echo ERROR:;
diff -u wc-baseline.txt wc-out.txt;
fi
./wordcount --timer --summary wcdb1.db $* --query >wc-out.txt
mv wc-out.txt wc-baseline.txt
./wordcount --timer --summary wcdb2.db $* --query --without-rowid >wc-out.txt
if cmp -s wc-out.txt wc-baseline.txt;
then echo hi >/dev/null;
else echo ERROR:;
diff -u wc-baseline.txt wc-out.txt;
fi
./wordcount --timer --summary wcdb1.db $* --delete >wc-out.txt
mv wc-out.txt wc-baseline.txt
./wordcount --timer --summary wcdb2.db $* --delete --without-rowid >wc-out.txt
if cmp -s wc-out.txt wc-baseline.txt;
then echo hi >/dev/null;
else echo ERROR:;
diff -u wc-baseline.txt wc-out.txt;
fi
# Clean up temporary files created.
#
rm -rf wcdb1.db wcdb2.db wc-out.txt wc-baseline.txt
-19
View File
@@ -268,23 +268,4 @@ do_test shell5-1.9 {
} {1 {} 11 | 2 x 22 | 3 {"} 33 | 4 hello 44 | 5 55 {} | 6 66 x | 7 77 {"} | 8 88 hello | {} 9 99 | x 10 110 | {"} 11 121 | hello 12 132 |}
db close
# Import columns containing quoted strings
do_test shell5-1.10 {
set out [open shell5.csv w]
fconfigure $out -translation lf
puts $out {column1,column2,column3,column4}
puts $out "field1,field2,\"x3 \"\"\r\ndata\"\" 3\",field4"
puts $out "x1,x2,\"x3 \"\"\ndata\"\" 3\",x4"
close $out
forcedelete test.db
catchcmd test.db {.mode csv
CREATE TABLE t1(a,b,c,d);
.import shell5.csv t1
}
sqlite3 db test.db
db eval {SELECT hex(c) FROM t1 ORDER BY rowid}
} {636F6C756D6E33 783320220D0A64617461222033 783320220A64617461222033}
db close
finish_test
-190
View File
@@ -1,190 +0,0 @@
# 2013-11-27
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file implements tests of the "skip-scan" query strategy.
#
# The test cases in this file are derived from the description of
# the skip-scan query strategy in the "optoverview.html" document.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test skipscan2-1.1 {
CREATE TABLE people(
name TEXT PRIMARY KEY,
role TEXT NOT NULL,
height INT NOT NULL, -- in cm
CHECK( role IN ('student','teacher') )
);
CREATE INDEX people_idx1 ON people(role, height);
} {}
do_execsql_test skipscan2-1.2 {
INSERT INTO people VALUES('Alice','student',156);
INSERT INTO people VALUES('Bob','student',161);
INSERT INTO people VALUES('Cindy','student',155);
INSERT INTO people VALUES('David','student',181);
INSERT INTO people VALUES('Emily','teacher',158);
INSERT INTO people VALUES('Fred','student',163);
INSERT INTO people VALUES('Ginny','student',169);
INSERT INTO people VALUES('Harold','student',172);
INSERT INTO people VALUES('Imma','student',179);
INSERT INTO people VALUES('Jack','student',181);
INSERT INTO people VALUES('Karen','student',163);
INSERT INTO people VALUES('Logan','student',177);
INSERT INTO people VALUES('Megan','teacher',159);
INSERT INTO people VALUES('Nathan','student',163);
INSERT INTO people VALUES('Olivia','student',161);
INSERT INTO people VALUES('Patrick','teacher',180);
INSERT INTO people VALUES('Quiana','student',182);
INSERT INTO people VALUES('Robert','student',159);
INSERT INTO people VALUES('Sally','student',166);
INSERT INTO people VALUES('Tom','student',171);
INSERT INTO people VALUES('Ursula','student',170);
INSERT INTO people VALUES('Vance','student',179);
INSERT INTO people VALUES('Willma','student',175);
INSERT INTO people VALUES('Xavier','teacher',185);
INSERT INTO people VALUES('Yvonne','student',149);
INSERT INTO people VALUES('Zach','student',170);
}
# Without ANALYZE, a skip-scan is not used
#
do_execsql_test skipscan2-1.3 {
SELECT name FROM people WHERE height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-1.3eqp {
EXPLAIN QUERY PLAN
SELECT name FROM people WHERE height>=180 ORDER BY +name;
} {~/*INDEX people_idx1 */}
# Now do an ANALYZE. A skip-scan can be used after ANALYZE.
#
do_execsql_test skipscan2-1.4 {
ANALYZE;
-- We do not have enough people above to actually force the use
-- of a skip-scan. So make a manual adjustment to the stat1 table
-- to make it seem like there are many more.
UPDATE sqlite_stat1 SET stat='10000 5000 20' WHERE idx='people_idx1';
ANALYZE sqlite_master;
}
db cache flush
do_execsql_test skipscan2-1.5 {
SELECT name FROM people WHERE height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-1.5eqp {
EXPLAIN QUERY PLAN
SELECT name FROM people WHERE height>=180 ORDER BY +name;
} {/*INDEX people_idx1 */}
# Same answer with other formulations of the same query
#
do_execsql_test skipscan2-1.6 {
SELECT name FROM people
WHERE role IN (SELECT DISTINCT role FROM people)
AND height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-1.7 {
SELECT name FROM people WHERE role='teacher' AND height>=180
UNION ALL
SELECT name FROM people WHERE role='student' AND height>=180
ORDER BY 1;
} {David Jack Patrick Quiana Xavier}
# Add 8 more people, bringing the total to 34. Then the number of
# duplicates in the left-column of the index will be 17 and
# skip-scan should not be used after an (unfudged) ANALYZE.
#
do_execsql_test skipscan2-1.8 {
INSERT INTO people VALUES('Angie','student',166);
INSERT INTO people VALUES('Brad','student',176);
INSERT INTO people VALUES('Claire','student',168);
INSERT INTO people VALUES('Donald','student',162);
INSERT INTO people VALUES('Elaine','student',177);
INSERT INTO people VALUES('Frazier','student',159);
INSERT INTO people VALUES('Grace','student',179);
INSERT INTO people VALUES('Horace','student',166);
ANALYZE;
SELECT stat FROM sqlite_stat1 WHERE idx='people_idx1';
} {{34 17 2}}
db cache flush
do_execsql_test skipscan2-1.9 {
SELECT name FROM people WHERE height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-1.9eqp {
EXPLAIN QUERY PLAN
SELECT name FROM people WHERE height>=180 ORDER BY +name;
} {~/*INDEX people_idx1 */}
# Add 2 more people, bringing the total to 36. Then the number of
# duplicates in the left-column of the index will be 18 and
# skip-scan will be used after an (unfudged) ANALYZE.
#
do_execsql_test skipscan2-1.10 {
INSERT INTO people VALUES('Ingrad','student',155);
INSERT INTO people VALUES('Jacob','student',179);
ANALYZE;
SELECT stat FROM sqlite_stat1 WHERE idx='people_idx1';
} {{36 18 2}}
db cache flush
do_execsql_test skipscan2-1.11 {
SELECT name FROM people WHERE height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-1.11eqp {
EXPLAIN QUERY PLAN
SELECT name FROM people WHERE height>=180 ORDER BY +name;
} {/*INDEX people_idx1 */}
# Repeat using a WITHOUT ROWID table.
#
do_execsql_test skipscan2-2.1 {
CREATE TABLE peoplew(
name TEXT PRIMARY KEY,
role TEXT NOT NULL,
height INT NOT NULL, -- in cm
CHECK( role IN ('student','teacher') )
) WITHOUT ROWID;
CREATE INDEX peoplew_idx1 ON peoplew(role, height);
INSERT INTO peoplew(name,role,height)
SELECT name, role, height FROM people;
ALTER TABLE people RENAME TO old_people;
SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-2.2 {
SELECT name FROM peoplew
WHERE role IN (SELECT DISTINCT role FROM peoplew)
AND height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-2.2 {
SELECT name FROM peoplew WHERE role='teacher' AND height>=180
UNION ALL
SELECT name FROM peoplew WHERE role='student' AND height>=180
ORDER BY 1;
} {David Jack Patrick Quiana Xavier}
# Now do an ANALYZE. A skip-scan can be used after ANALYZE.
#
do_execsql_test skipscan2-2.4 {
ANALYZE;
}
db cache flush
do_execsql_test skipscan2-2.5 {
SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-2.5eqp {
EXPLAIN QUERY PLAN
SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
} {/*INDEX peoplew_idx1 */}
finish_test
-966
View File
@@ -1,966 +0,0 @@
/*
** A program for performance testing.
**
** The available command-line options are described below:
*/
static const char zHelp[] =
"Usage: %s [--options] DATABASE\n"
"Options:\n"
" --autovacuum Enable AUTOVACUUM mode\n"
" --cachesize N Set the cache size to N\n"
" --exclusive Enable locking_mode=EXCLUSIVE\n"
" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
" --incrvacuum Enable incremenatal vacuum mode\n"
" --journalmode M Set the journal_mode to MODE\n"
" --key KEY Set the encryption key to KEY\n"
" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
" --nosync Set PRAGMA synchronous=OFF\n"
" --notnull Add NOT NULL constraints to table columns\n"
" --pagesize N Set the page size to N\n"
" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
" --primarykey Use PRIMARY KEY instead of UNIQUE where appropriate\n"
" --reprepare Reprepare each statement upon every invocation\n"
" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
" --sqlonly No-op. Only show the SQL that would have been run.\n"
" --size N Relative test size. Default=100\n"
" --stats Show statistics at the end\n"
" --testset T Run test-set T\n"
" --trace Turn on SQL tracing\n"
" --utf16be Set text encoding to UTF-16BE\n"
" --utf16le Set text encoding to UTF-16LE\n"
" --without-rowid Use WITHOUT ROWID where appropriate\n"
;
#include "sqlite3.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
/* All global state is held in this structure */
static struct Global {
sqlite3 *db; /* The open database connection */
sqlite3_stmt *pStmt; /* Current SQL statement */
sqlite3_int64 iStart; /* Start-time for the current test */
sqlite3_int64 iTotal; /* Total time */
int bWithoutRowid; /* True for --without-rowid */
int bReprepare; /* True to reprepare the SQL on each rerun */
int bSqlOnly; /* True to print the SQL once only */
int szTest; /* Scale factor for test iterations */
const char *zWR; /* Might be WITHOUT ROWID */
const char *zNN; /* Might be NOT NULL */
const char *zPK; /* Might be UNIQUE or PRIMARY KEY */
unsigned int x, y; /* Pseudo-random number generator state */
int nResult; /* Size of the current result */
char zResult[3000]; /* Text of the current result */
} g;
/* Print an error message and exit */
static void fatal_error(const char *zMsg, ...){
va_list ap;
va_start(ap, zMsg);
vfprintf(stderr, zMsg, ap);
va_end(ap);
exit(1);
}
/*
** Return the value of a hexadecimal digit. Return -1 if the input
** is not a hex digit.
*/
static int hexDigitValue(char c){
if( c>='0' && c<='9' ) return c - '0';
if( c>='a' && c<='f' ) return c - 'a' + 10;
if( c>='A' && c<='F' ) return c - 'A' + 10;
return -1;
}
/* Provide an alternative to sqlite3_stricmp() in older versions of
** SQLite */
#if SQLITE_VERSION_NUMBER<3007011
# define sqlite3_stricmp strcmp
#endif
/*
** Interpret zArg as an integer value, possibly with suffixes.
*/
static int integerValue(const char *zArg){
sqlite3_int64 v = 0;
static const struct { char *zSuffix; int iMult; } aMult[] = {
{ "KiB", 1024 },
{ "MiB", 1024*1024 },
{ "GiB", 1024*1024*1024 },
{ "KB", 1000 },
{ "MB", 1000000 },
{ "GB", 1000000000 },
{ "K", 1000 },
{ "M", 1000000 },
{ "G", 1000000000 },
};
int i;
int isNeg = 0;
if( zArg[0]=='-' ){
isNeg = 1;
zArg++;
}else if( zArg[0]=='+' ){
zArg++;
}
if( zArg[0]=='0' && zArg[1]=='x' ){
int x;
zArg += 2;
while( (x = hexDigitValue(zArg[0]))>=0 ){
v = (v<<4) + x;
zArg++;
}
}else{
while( isdigit(zArg[0]) ){
v = v*10 + zArg[0] - '0';
zArg++;
}
}
for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
v *= aMult[i].iMult;
break;
}
}
if( v>0x7fffffff ) fatal_error("parameter too large - max 2147483648");
return (int)(isNeg? -v : v);
}
/* Return the current wall-clock time, in milliseconds */
sqlite3_int64 speedtest1_timestamp(void){
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
#if SQLITE_VERSION_NUMBER>=3007000
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
clockVfs->xCurrentTimeInt64(clockVfs, &t);
}else
#endif
{
double r;
clockVfs->xCurrentTime(clockVfs, &r);
t = (sqlite3_int64)(r*86400000.0);
}
return t;
}
/* Return a pseudo-random unsigned integer */
unsigned int speedtest1_random(void){
g.x = (g.x>>1) ^ ((1+~(g.x&1)) & 0xd0000001);
g.y = g.y*1103515245 + 12345;
return g.x ^ g.y;
}
/* Map the value in within the range of 1...limit into another
** number in a way that is chatic and invertable.
*/
unsigned swizzle(unsigned in, unsigned limit){
unsigned out = 0;
while( limit ){
out = (out<<1) | (in&1);
in >>= 1;
limit >>= 1;
}
return out;
}
/* Round up a number so that it is a power of two minus one
*/
unsigned roundup_allones(unsigned limit){
unsigned m = 1;
while( m<limit ) m = (m<<1)+1;
return m;
}
/* The speedtest1_numbername procedure below converts its argment (an integer)
** into a string which is the English-language name for that number.
** The returned string should be freed with sqlite3_free().
**
** Example:
**
** speedtest1_numbername(123) -> "one hundred twenty three"
*/
int speedtest1_numbername(unsigned int n, char *zOut, int nOut){
static const char *ones[] = { "zero", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine", "ten", "eleven", "twelve",
"thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
"eighteen", "nineteen" };
static const char *tens[] = { "", "ten", "twenty", "thirty", "forty",
"fifty", "sixty", "seventy", "eighty", "ninety" };
int i = 0;
if( n>=1000000000 ){
i += speedtest1_numbername(n/1000000000, zOut+i, nOut-i);
sqlite3_snprintf(nOut-i, zOut+i, " billion");
i += (int)strlen(zOut+i);
n = n % 1000000000;
}
if( n>=1000000 ){
if( i && i<nOut-1 ) zOut[i++] = ' ';
i += speedtest1_numbername(n/1000000, zOut+i, nOut-i);
sqlite3_snprintf(nOut-i, zOut+i, " million");
i += (int)strlen(zOut+i);
n = n % 1000000;
}
if( n>=1000 ){
if( i && i<nOut-1 ) zOut[i++] = ' ';
i += speedtest1_numbername(n/1000, zOut+i, nOut-i);
sqlite3_snprintf(nOut-i, zOut+i, " thousand");
i += (int)strlen(zOut+i);
n = n % 1000;
}
if( n>=100 ){
if( i && i<nOut-1 ) zOut[i++] = ' ';
sqlite3_snprintf(nOut-i, zOut+i, "%s hundred", ones[n/100]);
i += (int)strlen(zOut+i);
n = n % 100;
}
if( n>=20 ){
if( i && i<nOut-1 ) zOut[i++] = ' ';
sqlite3_snprintf(nOut-i, zOut+i, "%s", tens[n/10]);
i += (int)strlen(zOut+i);
n = n % 10;
}
if( n>0 ){
if( i && i<nOut-1 ) zOut[i++] = ' ';
sqlite3_snprintf(nOut-i, zOut+i, "%s", ones[n]);
i += (int)strlen(zOut+i);
}
if( i==0 ){
sqlite3_snprintf(nOut-i, zOut+i, "zero");
i += (int)strlen(zOut+i);
}
return i;
}
/* Start a new test case */
#define NAMEWIDTH 60
static const char zDots[] =
".......................................................................";
void speedtest1_begin_test(int iTestNum, const char *zTestName, ...){
int n = (int)strlen(zTestName);
char *zName;
va_list ap;
va_start(ap, zTestName);
zName = sqlite3_vmprintf(zTestName, ap);
va_end(ap);
n = (int)strlen(zName);
if( n>NAMEWIDTH ){
zName[NAMEWIDTH] = 0;
n = NAMEWIDTH;
}
if( g.bSqlOnly ){
printf("/* %4d - %s%.*s */\n", iTestNum, zName, NAMEWIDTH-n, zDots);
}else{
printf("%4d - %s%.*s ", iTestNum, zName, NAMEWIDTH-n, zDots);
fflush(stdout);
}
sqlite3_free(zName);
g.nResult = 0;
g.iStart = speedtest1_timestamp();
g.x = 0xad131d0b;
g.y = 0x44f9eac8;
}
/* Complete a test case */
void speedtest1_end_test(void){
sqlite3_int64 iElapseTime = speedtest1_timestamp() - g.iStart;
if( !g.bSqlOnly ){
g.iTotal += iElapseTime;
printf("%4d.%03ds\n", (int)(iElapseTime/1000), (int)(iElapseTime%1000));
}
if( g.pStmt ){
sqlite3_finalize(g.pStmt);
g.pStmt = 0;
}
}
/* Report end of testing */
void speedtest1_final(void){
if( !g.bSqlOnly ){
printf(" TOTAL%.*s %4d.%03ds\n", NAMEWIDTH-5, zDots,
(int)(g.iTotal/1000), (int)(g.iTotal%1000));
}
}
/* Run SQL */
void speedtest1_exec(const char *zFormat, ...){
va_list ap;
char *zSql;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( g.bSqlOnly ){
int n = (int)strlen(zSql);
while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; }
printf("%.*s;\n", n, zSql);
}else{
char *zErrMsg = 0;
int rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
if( zErrMsg ) fatal_error("SQL error: %s\n%s\n", zErrMsg, zSql);
if( rc!=SQLITE_OK ) fatal_error("exec error: %s\n", sqlite3_errmsg(g.db));
}
sqlite3_free(zSql);
}
/* Prepare an SQL statement */
void speedtest1_prepare(const char *zFormat, ...){
va_list ap;
char *zSql;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( g.bSqlOnly ){
int n = (int)strlen(zSql);
while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; }
printf("%.*s;\n", n, zSql);
}else{
int rc;
if( g.pStmt ) sqlite3_finalize(g.pStmt);
rc = sqlite3_prepare_v2(g.db, zSql, -1, &g.pStmt, 0);
if( rc ){
fatal_error("SQL error: %s\n", sqlite3_errmsg(g.db));
}
}
sqlite3_free(zSql);
}
/* Run an SQL statement previously prepared */
void speedtest1_run(void){
int i, n, len;
if( g.bSqlOnly ) return;
assert( g.pStmt );
g.nResult = 0;
while( sqlite3_step(g.pStmt)==SQLITE_ROW ){
n = sqlite3_column_count(g.pStmt);
for(i=0; i<n; i++){
const char *z = (const char*)sqlite3_column_text(g.pStmt, i);
if( z==0 ) z = "nil";
len = (int)strlen(z);
if( g.nResult+len<sizeof(g.zResult)-2 ){
if( g.nResult>0 ) g.zResult[g.nResult++] = ' ';
memcpy(g.zResult + g.nResult, z, len+1);
g.nResult += len;
}
}
}
if( g.bReprepare ){
sqlite3_stmt *pNew;
sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0);
sqlite3_finalize(g.pStmt);
g.pStmt = pNew;
}else{
sqlite3_reset(g.pStmt);
}
}
/* The sqlite3_trace() callback function */
static void traceCallback(void *NotUsed, const char *zSql){
int n = (int)strlen(zSql);
while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ) n--;
fprintf(stderr,"%.*s;\n", n, zSql);
}
/* Substitute random() function that gives the same random
** sequence on each run, for repeatability. */
static void randomFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3_result_int64(context, (sqlite3_int64)speedtest1_random());
}
/*
** The main and default testset
*/
void testset_main(void){
int i; /* Loop counter */
int n; /* iteration count */
int sz; /* Size of the tables */
int maxb; /* Maximum swizzled value */
unsigned x1, x2; /* Parameters */
int len; /* Length of the zNum[] string */
char zNum[2000]; /* A number name */
sz = n = g.szTest*500;
maxb = roundup_allones(sz);
speedtest1_begin_test(100, "%d INSERTs into table with no index", n);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE TABLE t1(a INTEGER %s, b INTEGER %s, c TEXT %s);",
g.zNN, g.zNN, g.zNN);
speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2,?3); -- %d times", n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
speedtest1_numbername(x1, zNum, sizeof(zNum));
sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1);
sqlite3_bind_int(g.pStmt, 2, i);
sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz;
speedtest1_begin_test(110, "%d ordered INSERTS with one index/PK", n);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE TABLE t2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
speedtest1_prepare("INSERT INTO t2 VALUES(?1,?2,?3); -- %d times", n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
speedtest1_numbername(x1, zNum, sizeof(zNum));
sqlite3_bind_int(g.pStmt, 1, i);
sqlite3_bind_int64(g.pStmt, 2, (sqlite3_int64)x1);
sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz;
speedtest1_begin_test(120, "%d unordered INSERTS with one index/PK", n);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE TABLE t3(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
speedtest1_prepare("INSERT INTO t3 VALUES(?1,?2,?3); -- %d times", n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
speedtest1_numbername(x1, zNum, sizeof(zNum));
sqlite3_bind_int(g.pStmt, 2, i);
sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1);
sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = g.szTest/2;
speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
" WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%maxb;
x2 = speedtest1_random()%10 + sz/5000 + x1;
sqlite3_bind_int(g.pStmt, 1, x1);
sqlite3_bind_int(g.pStmt, 2, x2);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = g.szTest/5;
speedtest1_begin_test(140, "%d SELECTS, LIKE, unindexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
" WHERE c LIKE ?1; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%maxb;
zNum[0] = '%';
len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2);
zNum[len] = '%';
zNum[len+1] = 0;
sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
speedtest1_begin_test(150, "CREATE INDEX five times");
speedtest1_exec(
"BEGIN;\n"
"CREATE UNIQUE INDEX t1b ON t1(b);\n"
"CREATE INDEX t1c ON t1(c);\n"
"CREATE UNIQUE INDEX t2b ON t2(b);\n"
"CREATE INDEX t2c ON t2(c DESC);\n"
"CREATE INDEX t3bc ON t3(b,c);\n"
"COMMIT;\n"
);
speedtest1_end_test();
n = sz/5;
speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
" WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%maxb;
x2 = speedtest1_random()%10 + sz/5000 + x1;
sqlite3_bind_int(g.pStmt, 1, x1);
sqlite3_bind_int(g.pStmt, 2, x2);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz/5;
speedtest1_begin_test(161, "%d SELECTS, numeric BETWEEN, PK", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t2\n"
" WHERE a BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%maxb;
x2 = speedtest1_random()%10 + sz/5000 + x1;
sqlite3_bind_int(g.pStmt, 1, x1);
sqlite3_bind_int(g.pStmt, 2, x2);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz/5;
speedtest1_begin_test(170, "%d SELECTS, text BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
" WHERE c BETWEEN ?1 AND (?1||'~'); -- %d times", n
);
for(i=1; i<=n; i++){
x1 = swizzle(i, maxb);
len = speedtest1_numbername(x1, zNum, sizeof(zNum)-1);
sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz;
speedtest1_begin_test(180, "%d INSERTS with three indexes", n);
speedtest1_exec("BEGIN");
speedtest1_exec(
"CREATE TABLE t4(\n"
" a INTEGER %s %s,\n"
" b INTEGER %s,\n"
" c TEXT %s\n"
") %s",
g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
speedtest1_exec("CREATE INDEX t4b ON t4(b)");
speedtest1_exec("CREATE INDEX t4c ON t4(c)");
speedtest1_exec("INSERT INTO t4 SELECT * FROM t1");
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz;
speedtest1_begin_test(190, "DELETE and REFILL one table", n);
speedtest1_exec(
"DELETE FROM t2;"
"INSERT INTO t2 SELECT * FROM t1;"
);
speedtest1_end_test();
speedtest1_begin_test(200, "VACUUM");
speedtest1_exec("VACUUM");
speedtest1_end_test();
speedtest1_begin_test(210, "ALTER TABLE ADD COLUMN, and query");
speedtest1_exec("ALTER TABLE t2 ADD COLUMN d DEFAULT 123");
speedtest1_exec("SELECT sum(d) FROM t2");
speedtest1_end_test();
n = sz/5;
speedtest1_begin_test(230, "%d UPDATES, numeric BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"UPDATE t2 SET d=b*2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%maxb;
x2 = speedtest1_random()%10 + sz/5000 + x1;
sqlite3_bind_int(g.pStmt, 1, x1);
sqlite3_bind_int(g.pStmt, 2, x2);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz;
speedtest1_begin_test(240, "%d UPDATES of individual rows", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"UPDATE t2 SET d=b*3 WHERE a=?1; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%sz + 1;
sqlite3_bind_int(g.pStmt, 1, x1);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
speedtest1_begin_test(250, "One big UPDATE of the whole %d-row table", sz);
speedtest1_exec("UPDATE t2 SET d=b*4");
speedtest1_end_test();
speedtest1_begin_test(260, "Query added column after filling");
speedtest1_exec("SELECT sum(d) FROM t2");
speedtest1_end_test();
n = sz/5;
speedtest1_begin_test(270, "%d DELETEs, numeric BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"DELETE FROM t2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%maxb + 1;
x2 = speedtest1_random()%10 + sz/5000 + x1;
sqlite3_bind_int(g.pStmt, 1, x1);
sqlite3_bind_int(g.pStmt, 2, x2);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz;
speedtest1_begin_test(280, "%d DELETEs of individual rows", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"DELETE FROM t3 WHERE a=?1; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%sz + 1;
sqlite3_bind_int(g.pStmt, 1, x1);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
speedtest1_begin_test(290, "Refill two %d-row tables using REPLACE", sz);
speedtest1_exec("REPLACE INTO t2(a,b,c) SELECT a,b,c FROM t1");
speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM t1");
speedtest1_end_test();
n = sz/5;
speedtest1_begin_test(300, "%d four-ways joins", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT t1.c FROM t1, t2, t3, t4\n"
" WHERE t4.a BETWEEN ?1 AND ?2\n"
" AND t3.a=t4.b\n"
" AND t2.a=t3.b\n"
" AND t1.c=t2.c"
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%sz + 1;
x2 = speedtest1_random()%10 + x1 + 4;
sqlite3_bind_int(g.pStmt, 1, x1);
sqlite3_bind_int(g.pStmt, 2, x2);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
speedtest1_begin_test(980, "PRAGMA integrity_check");
speedtest1_exec("PRAGMA integrity_check");
speedtest1_end_test();
speedtest1_begin_test(990, "ANALYZE");
speedtest1_exec("ANALYZE");
speedtest1_end_test();
}
/*
** A testset used for debugging speedtest1 itself.
*/
void testset_debug1(void){
unsigned i, n;
unsigned x1, x2;
char zNum[2000]; /* A number name */
n = g.szTest;
for(i=1; i<=n; i++){
x1 = swizzle(i, n);
x2 = swizzle(x1, n);
speedtest1_numbername(x1, zNum, sizeof(zNum));
printf("%5d %5d %5d %s\n", i, x1, x2, zNum);
}
}
int main(int argc, char **argv){
int doAutovac = 0; /* True for --autovacuum */
int cacheSize = 0; /* Desired cache size. 0 means default */
int doExclusive = 0; /* True for --exclusive */
int nHeap = 0, mnHeap = 0; /* Heap size from --heap */
int doIncrvac = 0; /* True for --incrvacuum */
const char *zJMode = 0; /* Journal mode */
const char *zKey = 0; /* Encryption key */
int nLook = 0, szLook = 0; /* --lookaside configuration */
int noSync = 0; /* True for --nosync */
int pageSize = 0; /* Desired page size. 0 means default */
int nPCache = 0, szPCache = 0;/* --pcache configuration */
int nScratch = 0, szScratch=0;/* --scratch configuration */
int showStats = 0; /* True for --stats */
const char *zTSet = "main"; /* Which --testset torun */
int doTrace = 0; /* True for --trace */
const char *zEncoding = 0; /* --utf16be or --utf16le */
const char *zDbName = 0; /* Name of the test database */
void *pHeap = 0; /* Allocated heap space */
void *pLook = 0; /* Allocated lookaside space */
void *pPCache = 0; /* Allocated storage for pcache */
void *pScratch = 0; /* Allocated storage for scratch */
int iCur, iHi; /* Stats values, current and "highwater" */
int i; /* Loop counter */
int rc; /* API return code */
/* Process command-line arguments */
g.zWR = "";
g.zNN = "";
g.zPK = "UNIQUE";
g.szTest = 100;
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' ){
do{ z++; }while( z[0]=='-' );
if( strcmp(z,"autovacuum")==0 ){
doAutovac = 1;
}else if( strcmp(z,"cachesize")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
i++;
cacheSize = integerValue(argv[i]);
}else if( strcmp(z,"exclusive")==0 ){
doExclusive = 1;
}else if( strcmp(z,"heap")==0 ){
if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
nHeap = integerValue(argv[i+1]);
mnHeap = integerValue(argv[i+2]);
i += 2;
}else if( strcmp(z,"incrvacuum")==0 ){
doIncrvac = 1;
}else if( strcmp(z,"journal")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
zJMode = argv[++i];
}else if( strcmp(z,"key")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
zKey = argv[++i];
}else if( strcmp(z,"lookaside")==0 ){
if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
nLook = integerValue(argv[i+1]);
szLook = integerValue(argv[i+2]);
i += 2;
}else if( strcmp(z,"nosync")==0 ){
noSync = 1;
}else if( strcmp(z,"notnull")==0 ){
g.zNN = "NOT NULL";
}else if( strcmp(z,"pagesize")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
pageSize = integerValue(argv[++i]);
}else if( strcmp(z,"pcache")==0 ){
if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
nPCache = integerValue(argv[i+1]);
szPCache = integerValue(argv[i+2]);
i += 2;
}else if( strcmp(z,"primarykey")==0 ){
g.zPK = "PRIMARY KEY";
}else if( strcmp(z,"reprepare")==0 ){
g.bReprepare = 1;
}else if( strcmp(z,"scratch")==0 ){
if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
nScratch = integerValue(argv[i+1]);
szScratch = integerValue(argv[i+2]);
i += 2;
}else if( strcmp(z,"sqlonly")==0 ){
g.bSqlOnly = 1;
}else if( strcmp(z,"size")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
g.szTest = integerValue(argv[++i]);
}else if( strcmp(z,"stats")==0 ){
showStats = 1;
}else if( strcmp(z,"testset")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
zTSet = argv[++i];
}else if( strcmp(z,"trace")==0 ){
doTrace = 1;
}else if( strcmp(z,"utf16le")==0 ){
zEncoding = "utf16le";
}else if( strcmp(z,"utf16be")==0 ){
zEncoding = "utf16be";
}else if( strcmp(z,"without-rowid")==0 ){
g.zWR = "WITHOUT ROWID";
g.zPK = "PRIMARY KEY";
}else if( strcmp(z, "help")==0 || strcmp(z,"?")==0 ){
printf(zHelp, argv[0]);
exit(0);
}else{
fatal_error("unknown option: %s\nUse \"%s -?\" for help\n",
argv[i], argv[0]);
}
}else if( zDbName==0 ){
zDbName = argv[i];
}else{
fatal_error("surplus argument: %s\nUse \"%s -?\" for help\n",
argv[i], argv[0]);
}
}
#if 0
if( zDbName==0 ){
fatal_error(zHelp, argv[0]);
}
#endif
if( nHeap>0 ){
pHeap = malloc( nHeap );
if( pHeap==0 ) fatal_error("cannot allocate %d-byte heap\n", nHeap);
rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
if( rc ) fatal_error("heap configuration failed: %d\n", rc);
}
if( nPCache>0 && szPCache>0 ){
pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
if( pPCache==0 ) fatal_error("cannot allocate %lld-byte pcache\n",
nPCache*(sqlite3_int64)szPCache);
rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
if( rc ) fatal_error("pcache configuration failed: %d\n", rc);
}
if( nScratch>0 && szScratch>0 ){
pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
if( pScratch==0 ) fatal_error("cannot allocate %lld-byte scratch\n",
nScratch*(sqlite3_int64)szScratch);
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
if( rc ) fatal_error("scratch configuration failed: %d\n", rc);
}
if( nLook>0 ){
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
}
/* Open the database and the input file */
if( sqlite3_open(zDbName, &g.db) ){
fatal_error("Cannot open database file: %s\n", zDbName);
}
if( nLook>0 && szLook>0 ){
pLook = malloc( nLook*szLook );
rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook,nLook);
if( rc ) fatal_error("lookaside configuration failed: %d\n", rc);
}
/* Set database connection options */
sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0);
if( doTrace ) sqlite3_trace(g.db, traceCallback, 0);
if( zKey ){
speedtest1_exec("PRAGMA key('%s')", zKey);
}
if( zEncoding ){
speedtest1_exec("PRAGMA encoding=%s", zEncoding);
}
if( doAutovac ){
speedtest1_exec("PRAGMA auto_vacuum=FULL");
}else if( doIncrvac ){
speedtest1_exec("PRAGMA auto_vacuum=INCREMENTAL");
}
if( pageSize ){
speedtest1_exec("PRAGMA page_size=%d", pageSize);
}
if( cacheSize ){
speedtest1_exec("PRAGMA cache_size=%d", cacheSize);
}
if( noSync ) speedtest1_exec("PRAGMA synchronous=OFF");
if( doExclusive ){
speedtest1_exec("PRAGMA locking_mode=EXCLUSIVE");
}
if( zJMode ){
speedtest1_exec("PRAGMA journal_mode=%s", zJMode);
}
if( strcmp(zTSet,"main")==0 ){
testset_main();
}else if( strcmp(zTSet,"debug1")==0 ){
testset_debug1();
}else{
fatal_error("unknown testset: \"%s\"\n", zTSet);
}
speedtest1_final();
/* Database connection statistics printed after both prepared statements
** have been finalized */
#if SQLITE_VERSION_NUMBER>=3007009
if( showStats ){
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHi, 0);
printf("-- Lookaside Slots Used: %d (max %d)\n", iCur,iHi);
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHi, 0);
printf("-- Successful lookasides: %d\n", iHi);
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHi,0);
printf("-- Lookaside size faults: %d\n", iHi);
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHi,0);
printf("-- Lookaside OOM faults: %d\n", iHi);
sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHi, 0);
printf("-- Pager Heap Usage: %d bytes\n", iCur);
sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHi, 1);
printf("-- Page cache hits: %d\n", iCur);
sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHi, 1);
printf("-- Page cache misses: %d\n", iCur);
#if SQLITE_VERSION_NUMBER>=3007012
sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHi, 1);
printf("-- Page cache writes: %d\n", iCur);
#endif
sqlite3_db_status(g.db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHi, 0);
printf("-- Schema Heap Usage: %d bytes\n", iCur);
sqlite3_db_status(g.db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHi, 0);
printf("-- Statement Heap Usage: %d bytes\n", iCur);
}
#endif
sqlite3_close(g.db);
/* Global memory usage statistics printed after the database connection
** has closed. Memory usage should be zero at this point. */
if( showStats ){
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHi, 0);
printf("-- Memory Used (bytes): %d (max %d)\n", iCur,iHi);
#if SQLITE_VERSION_NUMBER>=3007000
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHi, 0);
printf("-- Outstanding Allocations: %d (max %d)\n", iCur,iHi);
#endif
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0);
printf("-- Pcache Overflow Bytes: %d (max %d)\n", iCur,iHi);
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHi, 0);
printf("-- Scratch Overflow Bytes: %d (max %d)\n", iCur,iHi);
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0);
printf("-- Largest Allocation: %d bytes\n",iHi);
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0);
printf("-- Largest Pcache Allocation: %d bytes\n",iHi);
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHi, 0);
printf("-- Largest Scratch Allocation: %d bytes\n", iHi);
}
/* Release memory */
free( pLook );
free( pPCache );
free( pScratch );
free( pHeap );
return 0;
}
+2 -2
View File
@@ -265,10 +265,10 @@ do_test 6.1 {
} {}
do_execsql_test 6.2 {
SELECT type,name,tbl_name,sql FROM aux.sqlite_master;
SELECT * FROM aux.sqlite_master;
INSERT INTO aux.t1 VALUES(1,2,3);
} {
table t1 t1 {CREATE TABLE t1(a, b, c)}
table t1 t1 2 {CREATE TABLE t1(a, b, c)}
}
do_catchsql_test 6.3 {
+1 -10
View File
@@ -1251,7 +1251,6 @@ proc crashsql {args} {
set blocksize ""
set crashdelay 1
set prngseed 0
set opendb { sqlite3 db test.db -vfs crash }
set tclbody {}
set crashfile ""
set dc ""
@@ -1263,7 +1262,6 @@ proc crashsql {args} {
set z2 [lindex $args [expr $ii+1]]
if {$n>1 && [string first $z -delay]==0} {set crashdelay $z2} \
elseif {$n>1 && [string first $z -opendb]==0} {set opendb $z2} \
elseif {$n>1 && [string first $z -seed]==0} {set prngseed $z2} \
elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \
elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \
@@ -1285,7 +1283,7 @@ proc crashsql {args} {
puts $f "sqlite3_crash_enable 1"
puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile"
puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
puts $f $opendb
puts $f "sqlite3 db test.db -vfs crash"
# This block sets the cache size of the main database to 10
# pages. This is done in case the build is configured to omit
@@ -1293,7 +1291,6 @@ proc crashsql {args} {
puts $f {db eval {SELECT * FROM sqlite_master;}}
puts $f {set bt [btree_from_db db]}
puts $f {btree_set_cache_size $bt 10}
if {$prngseed} {
set seed [expr {$prngseed%10007+1}]
# puts seed=$seed
@@ -1889,11 +1886,5 @@ set AUTOVACUUM $sqlite_options(default_autovacuum)
# Make sure the FTS enhanced query syntax is disabled.
set sqlite_fts3_enable_parentheses 0
# During testing, assume that all database files are well-formed. The
# few test cases that deliberately corrupt database files should rescind
# this setting by invoking "database_can_be_corrupt"
#
database_never_corrupt
source $testdir/thread_common.tcl
source $testdir/malloc_common.tcl

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