Merge the latest enhancements from trunk.
FossilOrigin-Name: 7d6cfc79e7e5534ebacd980479917bc528a638f7
This commit is contained in:
+2
-2
@@ -652,9 +652,9 @@ sqlite3.lo: sqlite3.c
|
||||
|
||||
# Rules to build the LEMON compiler generator
|
||||
#
|
||||
lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/src/lempar.c
|
||||
lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
|
||||
$(BCC) -o $@ $(TOP)/tool/lemon.c
|
||||
cp $(TOP)/src/lempar.c .
|
||||
cp $(TOP)/tool/lempar.c .
|
||||
|
||||
# Rules to build individual *.o files from generated *.c files. This
|
||||
# applies to:
|
||||
|
||||
+2
-2
@@ -1335,8 +1335,8 @@ sqlite3.lo: $(SQLITE3C)
|
||||
|
||||
# Rules to build the LEMON compiler generator
|
||||
#
|
||||
lempar.c: $(TOP)\src\lempar.c
|
||||
copy $(TOP)\src\lempar.c .
|
||||
lempar.c: $(TOP)\tool\lempar.c
|
||||
copy $(TOP)\tool\lempar.c .
|
||||
|
||||
lemon.exe: $(TOP)\tool\lemon.c lempar.c
|
||||
$(BCC) $(NO_WARN) -Daccess=_access \
|
||||
|
||||
@@ -6,8 +6,10 @@ libsqlite3_la_SOURCES = sqlite3.c
|
||||
libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
|
||||
|
||||
bin_PROGRAMS = sqlite3
|
||||
sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h
|
||||
sqlite3_LDADD = @READLINE_LIBS@
|
||||
sqlite3_SOURCES = shell.c sqlite3.h
|
||||
EXTRA_sqlite3_SOURCES = sqlite3.c
|
||||
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
|
||||
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
|
||||
sqlite3_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#
|
||||
# --enable-threadsafe
|
||||
# --enable-readline
|
||||
# --enable-editline
|
||||
# --enable-static-shell
|
||||
# --enable-dynamic-extensions
|
||||
#
|
||||
|
||||
@@ -117,6 +119,21 @@ fi
|
||||
AC_SUBST(JSON1_FLAGS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-static-shell
|
||||
#
|
||||
AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(
|
||||
[--enable-static-shell],
|
||||
[statically link libsqlite3 into shell tool [default=yes]])],
|
||||
[], [enable_static_shell=yes])
|
||||
if test x"$enable_static_shell" == "xyes"; then
|
||||
EXTRA_SHELL_OBJ=sqlite3.$OBJEXT
|
||||
else
|
||||
EXTRA_SHELL_OBJ=libsqlite3.la
|
||||
fi
|
||||
AC_SUBST(EXTRA_SHELL_OBJ)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_CHECK_FUNCS(posix_fallocate)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
+12
-4
@@ -58,6 +58,18 @@
|
||||
*/
|
||||
#define yytestcase(X) testcase(X)
|
||||
|
||||
/*
|
||||
** Indicate that sqlite3ParserFree() will never be called with a null
|
||||
** pointer.
|
||||
*/
|
||||
#define YYPARSEFREENOTNULL 1
|
||||
|
||||
/*
|
||||
** Alternative datatype for the argument to the malloc() routine passed
|
||||
** into sqlite3ParserAlloc(). The default is size_t.
|
||||
*/
|
||||
#define YYMALLOCARGTYPE u64
|
||||
|
||||
} // end %include
|
||||
|
||||
%left OR.
|
||||
@@ -168,7 +180,3 @@ phrase(A) ::= STRING(Y) star_opt(Z). {
|
||||
|
||||
star_opt(A) ::= STAR. { A = 1; }
|
||||
star_opt(A) ::= . { A = 0; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -563,9 +563,9 @@ fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl
|
||||
|
||||
# Rules to build the LEMON compiler generator
|
||||
#
|
||||
lemon: $(TOP)/tool/lemon.c $(TOP)/src/lempar.c
|
||||
lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
|
||||
$(BCC) -o lemon $(TOP)/tool/lemon.c
|
||||
cp $(TOP)/src/lempar.c .
|
||||
cp $(TOP)/tool/lempar.c .
|
||||
|
||||
# Rules to build individual *.o files from generated *.c files. This
|
||||
# applies to:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
C Merge\srecent\senhancements\sand\sbug\sfixes\sfrom\strunk.
|
||||
D 2015-11-07T01:33:30.741
|
||||
F Makefile.in 7037017983949da7c736ca3de2c3d29611b77d1c
|
||||
C Merge\sthe\slatest\senhancements\sfrom\strunk.
|
||||
D 2015-11-19T19:40:40.385
|
||||
F Makefile.in c9dfc95717a5af63ab90b36f22afd11e865e3559
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 2ed14817d36a6c26cb146e53b9c8a7318ba5bdd4
|
||||
F Makefile.msc 4f04d3dbe993b706c956509b1437559d7f2469b1
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
F VERSION 8b9d3ac6f1962f94e06ba05462422a544f9c4e36
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -10,12 +10,12 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am bd4a90972aa87f079af6624ddea3df3d58f26d2f
|
||||
F autoconf/Makefile.am 089e5ecdb5761e64ea1013ded02feb4d8b29927d
|
||||
F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x
|
||||
F autoconf/config.sub 1efb390a8fb4bfafd74783a15a8fb5311c84300e x
|
||||
F autoconf/configure.ac bec3caf78cf1bdbaad903dcd5c6029292eda3d2d
|
||||
F autoconf/configure.ac 9a65da17e440466f9842288163f16f9b21298129
|
||||
F autoconf/depcomp 0b26f101e3bc9fd1ff0be1da9fb4a82371142f92 x
|
||||
F autoconf/install-sh 06ee6336e63bb845c8439d777c32eb2eccc4fbf1 x
|
||||
F autoconf/ltmain.sh 7a658a24028f02331c1d2446562758083c5eadd1
|
||||
@@ -118,7 +118,7 @@ F ext/fts5/fts5_tokenize.c 12c5d925286491a71bb3dad7c8924ce9cfd18320
|
||||
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
|
||||
F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
|
||||
F ext/fts5/fts5_vocab.c 3742d0abfe8aa8c3cb4a7df56aa38f2e3c3fb1c2
|
||||
F ext/fts5/fts5parse.y e83dca6028e3309178d05b5bd920e372dc295d35
|
||||
F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d
|
||||
F ext/fts5/test/fts5aa.test 2c553eea4dab4bc5a75928f56729277c7bc1d206
|
||||
@@ -283,7 +283,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 2e67604b0dbd7670230ed626b6a2947f05a35ba5
|
||||
F main.mk 4f8d448adb9a7302cd5106f583ddc47067f1017d
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -302,16 +302,16 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc
|
||||
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 9e5d713bf54be8bfcae9b60210173dd53570f56d
|
||||
F src/btree.h 1b8bf2818b5e256c25a5e09126720113b1d783da
|
||||
F src/btree.c d3bdd8462a86492e2ebc9aca4a0168429017de25
|
||||
F src/btree.h 2d76dee44704c47eed323356a758662724b674a0
|
||||
F src/btreeInt.h 3ab435ed27adea54d040584b0bcc488ee7db1e38
|
||||
F src/build.c ca574d33ffb1763cfd2979383f4d507095bfbe19
|
||||
F src/build.c 5a3b71786e2b96d2bb92d40f190eb1fe736f25ca
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
|
||||
F src/ctime.c 509ef9c64d1321f42448f111da86400b1799218a
|
||||
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
|
||||
F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78
|
||||
F src/delete.c 9dddc4434aace0f42f1ed1c5224cdcfc2328ed67
|
||||
F src/delete.c 86e3940d07fe69a40270c2aaf6ca6c7adf19246c
|
||||
F src/expr.c 0080c0f12806eca91e75a23a121a68918e9da357
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0
|
||||
@@ -320,12 +320,11 @@ F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 0dbbde4b667b6e47a45ea98958516e2f30a9f9c4
|
||||
F src/insert.c 8ab83219eb56a103edb73bb0a1e9057c4d3b976b
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
|
||||
F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810
|
||||
F src/main.c cae25642d7f49cd94d833c49726eeb28381349f0
|
||||
F src/main.c 59798e68b7f93eaf243b2b4d054dd4eb6ead907a
|
||||
F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
|
||||
@@ -344,33 +343,33 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
|
||||
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
|
||||
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c cf72e06e15839ebe7121e01d3eebf256c039b0ca
|
||||
F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf
|
||||
F src/os_unix.c eb24e0340fbe3cfd0eabfb15a71476953e54fa73
|
||||
F src/os_win.c 2d77dab5c555a18c0aff379c6a692fc3499044d9
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c ed5cff11793b6a4146582aabb29ed8613a6cf89e
|
||||
F src/pager.h 7fc069c07f3120ee466ff3d48a9d376974ebffa7
|
||||
F src/parse.y 11078cd8e3af00f030505b6a86a06a4536cfdeaa
|
||||
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
|
||||
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
||||
F src/pager.c 18341e2b759b447cbc82fb9215d08d9c5864e92e
|
||||
F src/pager.h 87c4118a71ba3965184148b379a6d93179071091
|
||||
F src/parse.y 23737e649c26ce327603799e57f5c2ff50e5e6ba
|
||||
F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23
|
||||
F src/pcache.h 1ff11adce609ba7de139b6abfabaf9a2bac947b5
|
||||
F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035
|
||||
F src/pragma.c 8fd4c8a12e25f0d916426f160255ebe25415eba7
|
||||
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
|
||||
F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6
|
||||
F src/pragma.h 3d94aebbebd2089899fecc01909bf2608b39507d
|
||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||
F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a
|
||||
F src/printf.c f8fc8f04e75b1e983ef2793c27ec7a43b287e94a
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 167b4e9058bc8e997d18d6b6b20ecbb0c9c457af
|
||||
F src/shell.c 993863f82d764be0c00803056e56b9b744f86f02
|
||||
F src/sqlite.h.in 45821b35edf55ac410c16a3e1de4d6d43aa7ee16
|
||||
F src/select.c 2376d320907a5c28c55290f18fd94aa3400bf97c
|
||||
F src/shell.c 072fc3601b0ac02e50939b469fabeecfe3d66dcd
|
||||
F src/sqlite.h.in eed36953a0b5ce6c099b0cb2cb6b6ba220e6ca77
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
|
||||
F src/sqliteInt.h a02b33a3b68913394c218ec27f24b8fa33518244
|
||||
F src/sqliteInt.h d85782b8b5b2057ac015f7ec20195b7ce869960d
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
F src/tclsqlite.c e2344bee0d192397f555a24ef3fab26f2ed93bcc
|
||||
F src/test1.c a719afff3144f7f01c6dc3f7d118ac31d15e7527
|
||||
F src/test1.c 4004bcc1b3b361a9137acd1d875599ecbdd6f961
|
||||
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
|
||||
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
@@ -384,7 +383,7 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803
|
||||
F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07
|
||||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c e1fc48719655d83ea23513f3c3da32b4c4205899
|
||||
F src/test_config.c a25edf31cc0dbe17f5d1d667b1320cbb4e52b6dd
|
||||
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
@@ -407,7 +406,7 @@ F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
|
||||
F src/test_rtree.c 43fff4c5a01576d6d213f27472598801a247890c
|
||||
F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
|
||||
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
|
||||
F src/test_sqllog.c b690c12933f50ff46491e0d56a251f84ae16e914
|
||||
F src/test_sqllog.c 0d138a8180a312bf996b37fa66da5c5799d4d57b
|
||||
F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
@@ -416,8 +415,8 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0
|
||||
F src/tokenize.c 338bc8f7c9dd103188952cda7964696bacac6d22
|
||||
F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce
|
||||
F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785
|
||||
F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c c2fff3b60bfcabcb0372acbe8cf6f77c2bb515bc
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
@@ -427,7 +426,7 @@ F src/vdbe.c 9539aa0ccf4844b8b59466ef3c15dbffb479a390
|
||||
F src/vdbe.h bfe3f80dba435377cdb64fd917f2529f0f48ab77
|
||||
F src/vdbeInt.h d6ae6e64ad16e213f37306b1735ff72fb98bec69
|
||||
F src/vdbeapi.c f5eda36a5c85ef578957ab4311e8d9b1f51a3552
|
||||
F src/vdbeaux.c 1c5969fa8b04e162a2e893ebb283071bec81a006
|
||||
F src/vdbeaux.c 67db9a1c132207f4d6a8f4e76531cea39539fcaa
|
||||
F src/vdbeblob.c b400c25ac822af3c507ef84b5cd93c1583a70321
|
||||
F src/vdbemem.c 25b6cfd665b5073480452426e84136edd94140c0
|
||||
F src/vdbesort.c 8b23930a1289526f6d2a3a9f2e965bcc963e4a68
|
||||
@@ -774,7 +773,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzcheck.c ee926f1d4090d053ed542899720d4e4d30811bcc
|
||||
F test/fuzzcheck.c 7c61352f20a28429b221f406f3854cf9c912f63b
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -783,6 +782,7 @@ F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test aa41c095d26822b8a51aa4c82904a14347961be6
|
||||
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
|
||||
F test/ieee754.test 118b665a97a8df0e8f2fbdb07d113e596f4a6b53
|
||||
@@ -896,7 +896,7 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
|
||||
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
|
||||
F test/misc1.test 3f1c479c5a093a6280f378c0fbff1c2701486660
|
||||
F test/misc1.test d614a334b777b1aded6873d76a3560329b819fea
|
||||
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
|
||||
@@ -952,7 +952,7 @@ F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 63cb93f915b4056463cef8ad035082e9f1cb524e
|
||||
F test/pragma.test a44253f911e7d50127d4a08f927f47c861a4c772
|
||||
F test/pragma2.test b5e2ce4c892afceb308c6ae6163a9099b2a0d8d7
|
||||
F test/pragma2.test 00065068eeab2d15ea55465ec0f1e0a70e2c369e
|
||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
|
||||
@@ -970,7 +970,7 @@ F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
|
||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl 2d000ceded3115758be96abb9c10a5669fb27862
|
||||
F test/releasetest.tcl 622f2381b217facdf429584a5c292cc1fc47e7c0
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
|
||||
@@ -1060,6 +1060,7 @@ F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
|
||||
F test/sqllimits1.test 89b3d5aad05b99f707ee3786bdd4416dccf83304
|
||||
F test/sqllog.test a8faa2df39610a037dd372ed872d124260d32953
|
||||
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
|
||||
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
@@ -1081,7 +1082,7 @@ F test/tclsqlite.test 7179b4e0bf236ddf0bfa6bfaefa76fbe0a23c28a
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
F test/tester.tcl b1f0870442ca012effbf8659e34f9be428990696
|
||||
F test/tester.tcl 24d971d001a5bb10ef13c27768caed182eb1566e
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1248,7 +1249,7 @@ F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
||||
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
|
||||
F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
|
||||
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
|
||||
F test/trigger7.test 200dd51e728c9cdc20c72d99d9e9d45c667248f8
|
||||
F test/trigger7.test 799c9d2561facef70340cc9e0dee98aee9b5bdfe
|
||||
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
||||
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
|
||||
F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
|
||||
@@ -1299,7 +1300,7 @@ F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772
|
||||
F test/wal.test dbfc482e10c7263298833bb1fc60b3ac9d6340a1
|
||||
F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada
|
||||
F test/wal3.test 2ab8e490afe0164bfc89b185c8b2572e0d821f23
|
||||
F test/wal3.test b1d425f68a1f61d12563f0fa1ee6fca7d5afabf4
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c
|
||||
F test/wal6.test 4421cd5a2fa99d29cc91ef12fb23bed171ed3a4c
|
||||
@@ -1350,8 +1351,9 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/with1.test a1e8660be88e2eb4648f8860f831d1e38b5b5443
|
||||
F test/with1.test 05c8fc7f809f178a8a0519f02c21fe430948c895
|
||||
F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
|
||||
F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98
|
||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||
F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
@@ -1364,9 +1366,10 @@ F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||
F tool/GetTclKit.bat 8606413d3035c05373a0d7fae82ebf59ae9e16c3
|
||||
F tool/addopcodes.tcl 26892c394964c194fe96b9a79b8b9f87347c7151
|
||||
F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633
|
||||
F tool/build-all-msvc.bat e42141ca3c3812315432f9813ef9eb78aa8d99c9 x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
|
||||
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
|
||||
@@ -1376,15 +1379,15 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d
|
||||
F tool/lempar.c 3617143ddb9b176c3605defe6a9c798793280120
|
||||
F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
|
||||
F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa
|
||||
F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
|
||||
F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8
|
||||
F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b
|
||||
F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 84af2b180484323a2ea22a2279e8bd9e3e1e492e
|
||||
F tool/mkpragmatab.tcl e94e55d247d4fe3be34f2a4f4edb03fdcd09ce5b
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835
|
||||
F tool/mksqlite3c.tcl a52d7e8c0888f9384fbfa2c6ddd5f357409758b9
|
||||
@@ -1397,6 +1400,7 @@ F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/run-speed-test.sh 0ae485af4fe9f826e2b494be8c81f8ca9e222a4a
|
||||
F tool/showdb.c d4476e000a64eca9f5e2c2f68741e747b9778e8d
|
||||
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
|
||||
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
@@ -1410,7 +1414,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/sqldiff.c b318efc2eaf7a7fac4d281a0ce736193cb2506df
|
||||
F tool/sqldiff.c db1232df457fdd4cbf2a919a497fc44bb18fb933
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148
|
||||
@@ -1421,7 +1425,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 0546d1cd1a3402890edade7970c269cc3f17bc98 0f5b147d1fe83c34d0fbeacc7422be94d8441bc1
|
||||
R 65016c2c463ac04ecdb2d993caf6bb9d
|
||||
P 78bc42e664e9fa9ee21ad9762c369f291fcdf5db 126b998cf163dcdd5a222634f1e929f04db3c700
|
||||
R d78a5057451ca68f4e40e727fe9ca899
|
||||
U drh
|
||||
Z 6ef4d8405632dbe4f4eb27a0771bc5f1
|
||||
Z 251138aef0997d710e6be89ddc7546bd
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
78bc42e664e9fa9ee21ad9762c369f291fcdf5db
|
||||
7d6cfc79e7e5534ebacd980479917bc528a638f7
|
||||
+25
-13
@@ -2556,19 +2556,11 @@ int sqlite3BtreeClose(Btree *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the limit on the number of pages allowed in the cache.
|
||||
**
|
||||
** The maximum number of cache pages is set to the absolute
|
||||
** value of mxPage. If mxPage is negative, the pager will
|
||||
** operate asynchronously - it will not stop to do fsync()s
|
||||
** to insure data is written to the disk surface before
|
||||
** continuing. Transactions still work if synchronous is off,
|
||||
** and the database cannot be corrupted if this program
|
||||
** crashes. But if the operating system crashes or there is
|
||||
** an abrupt power failure when synchronous is off, the database
|
||||
** could be left in an inconsistent and unrecoverable state.
|
||||
** Synchronous is on by default so database corruption is not
|
||||
** normally a worry.
|
||||
** Change the "soft" limit on the number of pages in the cache.
|
||||
** Unused and unmodified pages will be recycled when the number of
|
||||
** pages in the cache exceeds this soft limit. But the size of the
|
||||
** cache is allowed to grow larger than this limit if it contains
|
||||
** dirty pages or pages still in active use.
|
||||
*/
|
||||
int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
|
||||
BtShared *pBt = p->pBt;
|
||||
@@ -2579,6 +2571,26 @@ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the "spill" limit on the number of pages in the cache.
|
||||
** If the number of pages exceeds this limit during a write transaction,
|
||||
** the pager might attempt to "spill" pages to the journal early in
|
||||
** order to free up memory.
|
||||
**
|
||||
** The value returned is the current spill size. If zero is passed
|
||||
** as an argument, no changes are made to the spill size setting, so
|
||||
** using mxPage of 0 is a way to query the current spill size.
|
||||
*/
|
||||
int sqlite3BtreeSetSpillSize(Btree *p, int mxPage){
|
||||
BtShared *pBt = p->pBt;
|
||||
int res;
|
||||
assert( sqlite3_mutex_held(p->db->mutex) );
|
||||
sqlite3BtreeEnter(p);
|
||||
res = sqlite3PagerSetSpillsize(pBt->pPager, mxPage);
|
||||
sqlite3BtreeLeave(p);
|
||||
return res;
|
||||
}
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
/*
|
||||
** Change the limit on the amount of the database file that may be
|
||||
|
||||
@@ -63,6 +63,7 @@ int sqlite3BtreeOpen(
|
||||
|
||||
int sqlite3BtreeClose(Btree*);
|
||||
int sqlite3BtreeSetCacheSize(Btree*,int);
|
||||
int sqlite3BtreeSetSpillSize(Btree*,int);
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
|
||||
#endif
|
||||
|
||||
+14
-12
@@ -1049,18 +1049,19 @@ begin_table_error:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** This macro is used to compare two strings in a case-insensitive manner.
|
||||
** It is slightly faster than calling sqlite3StrICmp() directly, but
|
||||
** produces larger code.
|
||||
**
|
||||
** WARNING: This macro is not compatible with the strcmp() family. It
|
||||
** returns true if the two strings are equal, otherwise false.
|
||||
/* Set properties of a table column based on the (magical)
|
||||
** name of the column.
|
||||
*/
|
||||
#define STRICMP(x, y) (\
|
||||
sqlite3UpperToLower[*(unsigned char *)(x)]== \
|
||||
sqlite3UpperToLower[*(unsigned char *)(y)] \
|
||||
&& sqlite3StrICmp((x)+1,(y)+1)==0 )
|
||||
void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
|
||||
#if SQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
|
||||
pCol->colFlags |= COLFLAG_HIDDEN;
|
||||
}else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
|
||||
pTab->tabFlags |= TF_OOOHidden;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Add a new column to the table currently being constructed.
|
||||
@@ -1086,7 +1087,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
|
||||
z = sqlite3NameFromToken(db, pName);
|
||||
if( z==0 ) return;
|
||||
for(i=0; i<p->nCol; i++){
|
||||
if( STRICMP(z, p->aCol[i].zName) ){
|
||||
if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
|
||||
sqlite3DbFree(db, z);
|
||||
return;
|
||||
@@ -1104,6 +1105,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
|
||||
pCol = &p->aCol[p->nCol];
|
||||
memset(pCol, 0, sizeof(p->aCol[0]));
|
||||
pCol->zName = z;
|
||||
sqlite3ColumnPropertiesFromName(p, pCol);
|
||||
|
||||
/* If there is no type specified, columns have the default affinity
|
||||
** 'BLOB'. If there is a type specified, then sqlite3AddColumnType() will
|
||||
|
||||
+2
-1
@@ -106,7 +106,8 @@ void sqlite3MaterializeView(
|
||||
assert( pFrom->a[0].pOn==0 );
|
||||
assert( pFrom->a[0].pUsing==0 );
|
||||
}
|
||||
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
|
||||
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0,
|
||||
SF_IncludeHidden, 0, 0);
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
|
||||
sqlite3Select(pParse, pSel, &dest);
|
||||
sqlite3SelectDelete(db, pSel);
|
||||
|
||||
+15
-11
@@ -736,10 +736,8 @@ void sqlite3Insert(
|
||||
/* Make sure the number of columns in the source data matches the number
|
||||
** of columns to be inserted into the table.
|
||||
*/
|
||||
if( IsVirtual(pTab) ){
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
|
||||
}
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
|
||||
}
|
||||
if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
@@ -835,15 +833,14 @@ void sqlite3Insert(
|
||||
|
||||
/* Create the new column data
|
||||
*/
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( pColumn==0 ){
|
||||
j = i;
|
||||
}else{
|
||||
for(i=j=0; i<pTab->nCol; i++){
|
||||
if( pColumn ){
|
||||
for(j=0; j<pColumn->nId; j++){
|
||||
if( pColumn->a[j].idx==i ) break;
|
||||
}
|
||||
}
|
||||
if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){
|
||||
if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId)
|
||||
|| (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){
|
||||
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
|
||||
}else if( useTempTable ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
|
||||
@@ -851,6 +848,7 @@ void sqlite3Insert(
|
||||
assert( pSelect==0 ); /* Otherwise useTempTable is true */
|
||||
sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
|
||||
}
|
||||
if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++;
|
||||
}
|
||||
|
||||
/* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
|
||||
@@ -934,7 +932,6 @@ void sqlite3Insert(
|
||||
}
|
||||
if( pColumn==0 ){
|
||||
if( IsHiddenColumn(&pTab->aCol[i]) ){
|
||||
assert( IsVirtual(pTab) );
|
||||
j = -1;
|
||||
nHidden++;
|
||||
}else{
|
||||
@@ -1885,7 +1882,7 @@ static int xferOptimization(
|
||||
return 0; /* The result set must have exactly one column */
|
||||
}
|
||||
assert( pEList->a[0].pExpr );
|
||||
if( pEList->a[0].pExpr->op!=TK_ALL ){
|
||||
if( pEList->a[0].pExpr->op!=TK_ASTERISK ){
|
||||
return 0; /* The result set must be the special operator "*" */
|
||||
}
|
||||
|
||||
@@ -1921,6 +1918,13 @@ static int xferOptimization(
|
||||
for(i=0; i<pDest->nCol; i++){
|
||||
Column *pDestCol = &pDest->aCol[i];
|
||||
Column *pSrcCol = &pSrc->aCol[i];
|
||||
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
if( (db->flags & SQLITE_Vacuum)==0
|
||||
&& (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN
|
||||
){
|
||||
return 0; /* Neither table may have __hidden__ columns */
|
||||
}
|
||||
#endif
|
||||
if( pDestCol->affinity!=pSrcCol->affinity ){
|
||||
return 0; /* Affinity must be the same on all columns */
|
||||
}
|
||||
|
||||
-895
@@ -1,895 +0,0 @@
|
||||
/* Driver template for the LEMON parser generator.
|
||||
** The author disclaims copyright to this source code.
|
||||
**
|
||||
** This version of "lempar.c" is modified, slightly, for use by SQLite.
|
||||
** The only modifications are the addition of a couple of NEVER()
|
||||
** macros to disable tests that are needed in the case of a general
|
||||
** LALR(1) grammar but which are always false in the
|
||||
** specific grammar used by SQLite.
|
||||
*/
|
||||
/* First off, code is included that follows the "include" declaration
|
||||
** in the input grammar file. */
|
||||
#include <stdio.h>
|
||||
%%
|
||||
/* Next is all token values, in a form suitable for use by makeheaders.
|
||||
** This section will be null unless lemon is run with the -m switch.
|
||||
*/
|
||||
/*
|
||||
** These constants (all generated automatically by the parser generator)
|
||||
** specify the various kinds of tokens (terminals) that the parser
|
||||
** understands.
|
||||
**
|
||||
** Each symbol here is a terminal symbol in the grammar.
|
||||
*/
|
||||
%%
|
||||
/* Make sure the INTERFACE macro is defined.
|
||||
*/
|
||||
#ifndef INTERFACE
|
||||
# define INTERFACE 1
|
||||
#endif
|
||||
/* The next thing included is series of defines which control
|
||||
** various aspects of the generated parser.
|
||||
** YYCODETYPE is the data type used for storing terminal
|
||||
** and nonterminal numbers. "unsigned char" is
|
||||
** used if there are fewer than 250 terminals
|
||||
** and nonterminals. "int" is used otherwise.
|
||||
** YYNOCODE is a number of type YYCODETYPE which corresponds
|
||||
** to no legal terminal or nonterminal number. This
|
||||
** number is used to fill in empty slots of the hash
|
||||
** table.
|
||||
** YYFALLBACK If defined, this indicates that one or more tokens
|
||||
** have fall-back values which should be used if the
|
||||
** original value of the token will not parse.
|
||||
** YYACTIONTYPE is the data type used for storing terminal
|
||||
** and nonterminal numbers. "unsigned char" is
|
||||
** used if there are fewer than 250 rules and
|
||||
** states combined. "int" is used otherwise.
|
||||
** ParseTOKENTYPE is the data type used for minor tokens given
|
||||
** directly to the parser from the tokenizer.
|
||||
** YYMINORTYPE is the data type used for all minor tokens.
|
||||
** This is typically a union of many types, one of
|
||||
** which is ParseTOKENTYPE. The entry in the union
|
||||
** for base tokens is called "yy0".
|
||||
** YYSTACKDEPTH is the maximum depth of the parser's stack. If
|
||||
** zero the stack is dynamically sized using realloc()
|
||||
** ParseARG_SDECL A static variable declaration for the %extra_argument
|
||||
** ParseARG_PDECL A parameter declaration for the %extra_argument
|
||||
** ParseARG_STORE Code to store %extra_argument into yypParser
|
||||
** ParseARG_FETCH Code to extract %extra_argument from yypParser
|
||||
** YYERRORSYMBOL is the code number of the error symbol. If not
|
||||
** defined, then do no error processing.
|
||||
** YYNSTATE the combined number of states.
|
||||
** YYNRULE the number of rules in the grammar
|
||||
** YY_MAX_SHIFT Maximum value for shift actions
|
||||
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
|
||||
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
|
||||
** YY_MIN_REDUCE Maximum value for reduce actions
|
||||
** YY_ERROR_ACTION The yy_action[] code for syntax error
|
||||
** YY_ACCEPT_ACTION The yy_action[] code for accept
|
||||
** YY_NO_ACTION The yy_action[] code for no-op
|
||||
*/
|
||||
%%
|
||||
|
||||
/* The yyzerominor constant is used to initialize instances of
|
||||
** YYMINORTYPE objects to zero. */
|
||||
static const YYMINORTYPE yyzerominor = { 0 };
|
||||
|
||||
/* Define the yytestcase() macro to be a no-op if is not already defined
|
||||
** otherwise.
|
||||
**
|
||||
** Applications can choose to define yytestcase() in the %include section
|
||||
** to a macro that can assist in verifying code coverage. For production
|
||||
** code the yytestcase() macro should be turned off. But it is useful
|
||||
** for testing.
|
||||
*/
|
||||
#ifndef yytestcase
|
||||
# define yytestcase(X)
|
||||
#endif
|
||||
|
||||
|
||||
/* Next are the tables used to determine what action to take based on the
|
||||
** current state and lookahead token. These tables are used to implement
|
||||
** functions that take a state number and lookahead value and return an
|
||||
** action integer.
|
||||
**
|
||||
** Suppose the action integer is N. Then the action is determined as
|
||||
** follows
|
||||
**
|
||||
** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
|
||||
** token onto the stack and goto state N.
|
||||
**
|
||||
** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
|
||||
** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
|
||||
**
|
||||
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
|
||||
** and YY_MAX_REDUCE
|
||||
|
||||
** N == YY_ERROR_ACTION A syntax error has occurred.
|
||||
**
|
||||
** N == YY_ACCEPT_ACTION The parser accepts its input.
|
||||
**
|
||||
** N == YY_NO_ACTION No such action. Denotes unused
|
||||
** slots in the yy_action[] table.
|
||||
**
|
||||
** The action table is constructed as a single large table named yy_action[].
|
||||
** Given state S and lookahead X, the action is computed as
|
||||
**
|
||||
** yy_action[ yy_shift_ofst[S] + X ]
|
||||
**
|
||||
** If the index value yy_shift_ofst[S]+X is out of range or if the value
|
||||
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
|
||||
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
|
||||
** and that yy_default[S] should be used instead.
|
||||
**
|
||||
** The formula above is for computing the action when the lookahead is
|
||||
** a terminal symbol. If the lookahead is a non-terminal (as occurs after
|
||||
** a reduce action) then the yy_reduce_ofst[] array is used in place of
|
||||
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
|
||||
** YY_SHIFT_USE_DFLT.
|
||||
**
|
||||
** The following are the tables generated in this section:
|
||||
**
|
||||
** yy_action[] A single table containing all actions.
|
||||
** yy_lookahead[] A table containing the lookahead for each entry in
|
||||
** yy_action. Used to detect hash collisions.
|
||||
** yy_shift_ofst[] For each state, the offset into yy_action for
|
||||
** shifting terminals.
|
||||
** yy_reduce_ofst[] For each state, the offset into yy_action for
|
||||
** shifting non-terminals after a reduce.
|
||||
** yy_default[] Default action for each state.
|
||||
*/
|
||||
%%
|
||||
|
||||
/* The next table maps tokens into fallback tokens. If a construct
|
||||
** like the following:
|
||||
**
|
||||
** %fallback ID X Y Z.
|
||||
**
|
||||
** appears in the grammar, then ID becomes a fallback token for X, Y,
|
||||
** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
|
||||
** but it does not parse, the type of the token is changed to ID and
|
||||
** the parse is retried before an error is thrown.
|
||||
*/
|
||||
#ifdef YYFALLBACK
|
||||
static const YYCODETYPE yyFallback[] = {
|
||||
%%
|
||||
};
|
||||
#endif /* YYFALLBACK */
|
||||
|
||||
/* The following structure represents a single element of the
|
||||
** parser's stack. Information stored includes:
|
||||
**
|
||||
** + The state number for the parser at this level of the stack.
|
||||
**
|
||||
** + The value of the token stored at this level of the stack.
|
||||
** (In other words, the "major" token.)
|
||||
**
|
||||
** + The semantic value stored at this level of the stack. This is
|
||||
** the information used by the action routines in the grammar.
|
||||
** It is sometimes called the "minor" token.
|
||||
**
|
||||
** After the "shift" half of a SHIFTREDUCE action, the stateno field
|
||||
** actually contains the reduce action for the second half of the
|
||||
** SHIFTREDUCE.
|
||||
*/
|
||||
struct yyStackEntry {
|
||||
YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
|
||||
YYCODETYPE major; /* The major token value. This is the code
|
||||
** number for the token at this stack level */
|
||||
YYMINORTYPE minor; /* The user-supplied minor token value. This
|
||||
** is the value of the token */
|
||||
};
|
||||
typedef struct yyStackEntry yyStackEntry;
|
||||
|
||||
/* The state of the parser is completely contained in an instance of
|
||||
** the following structure */
|
||||
struct yyParser {
|
||||
int yyidx; /* Index of top element in stack */
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
int yyidxMax; /* Maximum value of yyidx */
|
||||
#endif
|
||||
int yyerrcnt; /* Shifts left before out of the error */
|
||||
ParseARG_SDECL /* A place to hold %extra_argument */
|
||||
#if YYSTACKDEPTH<=0
|
||||
int yystksz; /* Current side of the stack */
|
||||
yyStackEntry *yystack; /* The parser's stack */
|
||||
#else
|
||||
yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
|
||||
#endif
|
||||
};
|
||||
typedef struct yyParser yyParser;
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <stdio.h>
|
||||
static FILE *yyTraceFILE = 0;
|
||||
static char *yyTracePrompt = 0;
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
** Turn parser tracing on by giving a stream to which to write the trace
|
||||
** and a prompt to preface each trace message. Tracing is turned off
|
||||
** by making either argument NULL
|
||||
**
|
||||
** Inputs:
|
||||
** <ul>
|
||||
** <li> A FILE* to which trace output should be written.
|
||||
** If NULL, then tracing is turned off.
|
||||
** <li> A prefix string written at the beginning of every
|
||||
** line of trace output. If NULL, then tracing is
|
||||
** turned off.
|
||||
** </ul>
|
||||
**
|
||||
** Outputs:
|
||||
** None.
|
||||
*/
|
||||
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
|
||||
yyTraceFILE = TraceFILE;
|
||||
yyTracePrompt = zTracePrompt;
|
||||
if( yyTraceFILE==0 ) yyTracePrompt = 0;
|
||||
else if( yyTracePrompt==0 ) yyTraceFILE = 0;
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* For tracing shifts, the names of all terminals and nonterminals
|
||||
** are required. The following table supplies these names */
|
||||
static const char *const yyTokenName[] = {
|
||||
%%
|
||||
};
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* For tracing reduce actions, the names of all rules are required.
|
||||
*/
|
||||
static const char *const yyRuleName[] = {
|
||||
%%
|
||||
};
|
||||
#endif /* NDEBUG */
|
||||
|
||||
|
||||
#if YYSTACKDEPTH<=0
|
||||
/*
|
||||
** Try to increase the size of the parser stack.
|
||||
*/
|
||||
static void yyGrowStack(yyParser *p){
|
||||
int newSize;
|
||||
yyStackEntry *pNew;
|
||||
|
||||
newSize = p->yystksz*2 + 100;
|
||||
pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
|
||||
if( pNew ){
|
||||
p->yystack = pNew;
|
||||
p->yystksz = newSize;
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
|
||||
yyTracePrompt, p->yystksz);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function allocates a new parser.
|
||||
** The only argument is a pointer to a function which works like
|
||||
** malloc.
|
||||
**
|
||||
** Inputs:
|
||||
** A pointer to the function used to allocate memory.
|
||||
**
|
||||
** Outputs:
|
||||
** A pointer to a parser. This pointer is used in subsequent calls
|
||||
** to Parse and ParseFree.
|
||||
*/
|
||||
void *ParseAlloc(void *(*mallocProc)(u64)){
|
||||
yyParser *pParser;
|
||||
pParser = (yyParser*)(*mallocProc)( (u64)sizeof(yyParser) );
|
||||
if( pParser ){
|
||||
pParser->yyidx = -1;
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
pParser->yyidxMax = 0;
|
||||
#endif
|
||||
#if YYSTACKDEPTH<=0
|
||||
pParser->yystack = NULL;
|
||||
pParser->yystksz = 0;
|
||||
yyGrowStack(pParser);
|
||||
#endif
|
||||
}
|
||||
return pParser;
|
||||
}
|
||||
|
||||
/* The following function deletes the value associated with a
|
||||
** symbol. The symbol can be either a terminal or nonterminal.
|
||||
** "yymajor" is the symbol code, and "yypminor" is a pointer to
|
||||
** the value.
|
||||
*/
|
||||
static void yy_destructor(
|
||||
yyParser *yypParser, /* The parser */
|
||||
YYCODETYPE yymajor, /* Type code for object to destroy */
|
||||
YYMINORTYPE *yypminor /* The object to be destroyed */
|
||||
){
|
||||
ParseARG_FETCH;
|
||||
switch( yymajor ){
|
||||
/* Here is inserted the actions which take place when a
|
||||
** terminal or non-terminal is destroyed. This can happen
|
||||
** when the symbol is popped from the stack during a
|
||||
** reduce or during error processing or when a parser is
|
||||
** being destroyed before it is finished parsing.
|
||||
**
|
||||
** Note: during a reduce, the only symbols destroyed are those
|
||||
** which appear on the RHS of the rule, but which are not used
|
||||
** inside the C code.
|
||||
*/
|
||||
%%
|
||||
default: break; /* If no destructor action specified: do nothing */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Pop the parser's stack once.
|
||||
**
|
||||
** If there is a destructor routine associated with the token which
|
||||
** is popped from the stack, then call it.
|
||||
**
|
||||
** Return the major token number for the symbol popped.
|
||||
*/
|
||||
static int yy_pop_parser_stack(yyParser *pParser){
|
||||
YYCODETYPE yymajor;
|
||||
yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
|
||||
|
||||
/* There is no mechanism by which the parser stack can be popped below
|
||||
** empty in SQLite. */
|
||||
assert( pParser->yyidx>=0 );
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE && pParser->yyidx>=0 ){
|
||||
fprintf(yyTraceFILE,"%sPopping %s\n",
|
||||
yyTracePrompt,
|
||||
yyTokenName[yytos->major]);
|
||||
}
|
||||
#endif
|
||||
yymajor = yytos->major;
|
||||
yy_destructor(pParser, yymajor, &yytos->minor);
|
||||
pParser->yyidx--;
|
||||
return yymajor;
|
||||
}
|
||||
|
||||
/*
|
||||
** Deallocate and destroy a parser. Destructors are all called for
|
||||
** all stack elements before shutting the parser down.
|
||||
**
|
||||
** Inputs:
|
||||
** <ul>
|
||||
** <li> A pointer to the parser. This should be a pointer
|
||||
** obtained from ParseAlloc.
|
||||
** <li> A pointer to a function used to reclaim memory obtained
|
||||
** from malloc.
|
||||
** </ul>
|
||||
*/
|
||||
void ParseFree(
|
||||
void *p, /* The parser to be deleted */
|
||||
void (*freeProc)(void*) /* Function used to reclaim memory */
|
||||
){
|
||||
yyParser *pParser = (yyParser*)p;
|
||||
/* In SQLite, we never try to destroy a parser that was not successfully
|
||||
** created in the first place. */
|
||||
if( NEVER(pParser==0) ) return;
|
||||
while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
|
||||
#if YYSTACKDEPTH<=0
|
||||
free(pParser->yystack);
|
||||
#endif
|
||||
(*freeProc)((void*)pParser);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the peak depth of the stack for a parser.
|
||||
*/
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
int ParseStackPeak(void *p){
|
||||
yyParser *pParser = (yyParser*)p;
|
||||
return pParser->yyidxMax;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Find the appropriate action for a parser given the terminal
|
||||
** look-ahead token iLookAhead.
|
||||
**
|
||||
** If the look-ahead token is YYNOCODE, then check to see if the action is
|
||||
** independent of the look-ahead. If it is, return the action, otherwise
|
||||
** return YY_NO_ACTION.
|
||||
*/
|
||||
static int yy_find_shift_action(
|
||||
yyParser *pParser, /* The parser */
|
||||
YYCODETYPE iLookAhead /* The look-ahead token */
|
||||
){
|
||||
int i;
|
||||
int stateno = pParser->yystack[pParser->yyidx].stateno;
|
||||
|
||||
if( stateno>=YY_MIN_REDUCE ) return stateno;
|
||||
assert( stateno <= YY_SHIFT_COUNT );
|
||||
i = yy_shift_ofst[stateno];
|
||||
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
|
||||
assert( iLookAhead!=YYNOCODE );
|
||||
i += iLookAhead;
|
||||
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
|
||||
if( iLookAhead>0 ){
|
||||
#ifdef YYFALLBACK
|
||||
YYCODETYPE iFallback; /* Fallback token */
|
||||
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
|
||||
&& (iFallback = yyFallback[iLookAhead])!=0 ){
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
|
||||
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
|
||||
}
|
||||
#endif
|
||||
return yy_find_shift_action(pParser, iFallback);
|
||||
}
|
||||
#endif
|
||||
#ifdef YYWILDCARD
|
||||
{
|
||||
int j = i - iLookAhead + YYWILDCARD;
|
||||
if(
|
||||
#if YY_SHIFT_MIN+YYWILDCARD<0
|
||||
j>=0 &&
|
||||
#endif
|
||||
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
|
||||
j<YY_ACTTAB_COUNT &&
|
||||
#endif
|
||||
yy_lookahead[j]==YYWILDCARD
|
||||
){
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
|
||||
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
return yy_action[j];
|
||||
}
|
||||
}
|
||||
#endif /* YYWILDCARD */
|
||||
}
|
||||
return yy_default[stateno];
|
||||
}else{
|
||||
return yy_action[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Find the appropriate action for a parser given the non-terminal
|
||||
** look-ahead token iLookAhead.
|
||||
**
|
||||
** If the look-ahead token is YYNOCODE, then check to see if the action is
|
||||
** independent of the look-ahead. If it is, return the action, otherwise
|
||||
** return YY_NO_ACTION.
|
||||
*/
|
||||
static int yy_find_reduce_action(
|
||||
int stateno, /* Current state number */
|
||||
YYCODETYPE iLookAhead /* The look-ahead token */
|
||||
){
|
||||
int i;
|
||||
#ifdef YYERRORSYMBOL
|
||||
if( stateno>YY_REDUCE_COUNT ){
|
||||
return yy_default[stateno];
|
||||
}
|
||||
#else
|
||||
assert( stateno<=YY_REDUCE_COUNT );
|
||||
#endif
|
||||
i = yy_reduce_ofst[stateno];
|
||||
assert( i!=YY_REDUCE_USE_DFLT );
|
||||
assert( iLookAhead!=YYNOCODE );
|
||||
i += iLookAhead;
|
||||
#ifdef YYERRORSYMBOL
|
||||
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
|
||||
return yy_default[stateno];
|
||||
}
|
||||
#else
|
||||
assert( i>=0 && i<YY_ACTTAB_COUNT );
|
||||
assert( yy_lookahead[i]==iLookAhead );
|
||||
#endif
|
||||
return yy_action[i];
|
||||
}
|
||||
|
||||
/*
|
||||
** The following routine is called if the stack overflows.
|
||||
*/
|
||||
static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
|
||||
ParseARG_FETCH;
|
||||
yypParser->yyidx--;
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
|
||||
}
|
||||
#endif
|
||||
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
|
||||
/* Here code is inserted which will execute if the parser
|
||||
** stack every overflows */
|
||||
%%
|
||||
ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
|
||||
}
|
||||
|
||||
/*
|
||||
** Print tracing information for a SHIFT action
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
static void yyTraceShift(yyParser *yypParser, int yyNewState){
|
||||
if( yyTraceFILE ){
|
||||
int i;
|
||||
if( yyNewState<YYNSTATE ){
|
||||
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
|
||||
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
|
||||
for(i=1; i<=yypParser->yyidx; i++)
|
||||
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
|
||||
fprintf(yyTraceFILE,"\n");
|
||||
}else{
|
||||
fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define yyTraceShift(X,Y)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Perform a shift action. Return the number of errors.
|
||||
*/
|
||||
static void yy_shift(
|
||||
yyParser *yypParser, /* The parser to be shifted */
|
||||
int yyNewState, /* The new state to shift in */
|
||||
int yyMajor, /* The major token to shift in */
|
||||
YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */
|
||||
){
|
||||
yyStackEntry *yytos;
|
||||
yypParser->yyidx++;
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
if( yypParser->yyidx>yypParser->yyidxMax ){
|
||||
yypParser->yyidxMax = yypParser->yyidx;
|
||||
}
|
||||
#endif
|
||||
#if YYSTACKDEPTH>0
|
||||
if( yypParser->yyidx>=YYSTACKDEPTH ){
|
||||
yyStackOverflow(yypParser, yypMinor);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if( yypParser->yyidx>=yypParser->yystksz ){
|
||||
yyGrowStack(yypParser);
|
||||
if( yypParser->yyidx>=yypParser->yystksz ){
|
||||
yyStackOverflow(yypParser, yypMinor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
yytos = &yypParser->yystack[yypParser->yyidx];
|
||||
yytos->stateno = (YYACTIONTYPE)yyNewState;
|
||||
yytos->major = (YYCODETYPE)yyMajor;
|
||||
yytos->minor = *yypMinor;
|
||||
yyTraceShift(yypParser, yyNewState);
|
||||
}
|
||||
|
||||
/* The following table contains information about every rule that
|
||||
** is used during the reduce.
|
||||
*/
|
||||
static const struct {
|
||||
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
|
||||
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
|
||||
} yyRuleInfo[] = {
|
||||
%%
|
||||
};
|
||||
|
||||
static void yy_accept(yyParser*); /* Forward Declaration */
|
||||
|
||||
/*
|
||||
** Perform a reduce action and the shift that must immediately
|
||||
** follow the reduce.
|
||||
*/
|
||||
static void yy_reduce(
|
||||
yyParser *yypParser, /* The parser */
|
||||
int yyruleno /* Number of the rule by which to reduce */
|
||||
){
|
||||
int yygoto; /* The next state */
|
||||
int yyact; /* The next action */
|
||||
YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
|
||||
yyStackEntry *yymsp; /* The top of the parser's stack */
|
||||
int yysize; /* Amount to pop the stack */
|
||||
ParseARG_FETCH;
|
||||
yymsp = &yypParser->yystack[yypParser->yyidx];
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE && yyruleno>=0
|
||||
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
|
||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||
fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt,
|
||||
yyRuleName[yyruleno], yymsp[-yysize].stateno);
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
/* Silence complaints from purify about yygotominor being uninitialized
|
||||
** in some cases when it is copied into the stack after the following
|
||||
** switch. yygotominor is uninitialized when a rule reduces that does
|
||||
** not set the value of its left-hand side nonterminal. Leaving the
|
||||
** value of the nonterminal uninitialized is utterly harmless as long
|
||||
** as the value is never used. So really the only thing this code
|
||||
** accomplishes is to quieten purify.
|
||||
**
|
||||
** 2007-01-16: The wireshark project (www.wireshark.org) reports that
|
||||
** without this code, their parser segfaults. I'm not sure what there
|
||||
** parser is doing to make this happen. This is the second bug report
|
||||
** from wireshark this week. Clearly they are stressing Lemon in ways
|
||||
** that it has not been previously stressed... (SQLite ticket #2172)
|
||||
*/
|
||||
/*memset(&yygotominor, 0, sizeof(yygotominor));*/
|
||||
yygotominor = yyzerominor;
|
||||
|
||||
|
||||
switch( yyruleno ){
|
||||
/* Beginning here are the reduction cases. A typical example
|
||||
** follows:
|
||||
** case 0:
|
||||
** #line <lineno> <grammarfile>
|
||||
** { ... } // User supplied code
|
||||
** #line <lineno> <thisfile>
|
||||
** break;
|
||||
*/
|
||||
%%
|
||||
};
|
||||
assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
|
||||
yygoto = yyRuleInfo[yyruleno].lhs;
|
||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||
yypParser->yyidx -= yysize;
|
||||
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
|
||||
if( yyact <= YY_MAX_SHIFTREDUCE ){
|
||||
if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
|
||||
/* If the reduce action popped at least
|
||||
** one element off the stack, then we can push the new element back
|
||||
** onto the stack here, and skip the stack overflow test in yy_shift().
|
||||
** That gives a significant speed improvement. */
|
||||
if( yysize ){
|
||||
yypParser->yyidx++;
|
||||
yymsp -= yysize-1;
|
||||
yymsp->stateno = (YYACTIONTYPE)yyact;
|
||||
yymsp->major = (YYCODETYPE)yygoto;
|
||||
yymsp->minor = yygotominor;
|
||||
yyTraceShift(yypParser, yyact);
|
||||
}else{
|
||||
yy_shift(yypParser,yyact,yygoto,&yygotominor);
|
||||
}
|
||||
}else{
|
||||
assert( yyact == YY_ACCEPT_ACTION );
|
||||
yy_accept(yypParser);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The following code executes when the parse fails
|
||||
*/
|
||||
#ifndef YYNOERRORRECOVERY
|
||||
static void yy_parse_failed(
|
||||
yyParser *yypParser /* The parser */
|
||||
){
|
||||
ParseARG_FETCH;
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
|
||||
}
|
||||
#endif
|
||||
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
|
||||
/* Here code is inserted which will be executed whenever the
|
||||
** parser fails */
|
||||
%%
|
||||
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
|
||||
}
|
||||
#endif /* YYNOERRORRECOVERY */
|
||||
|
||||
/*
|
||||
** The following code executes when a syntax error first occurs.
|
||||
*/
|
||||
static void yy_syntax_error(
|
||||
yyParser *yypParser, /* The parser */
|
||||
int yymajor, /* The major type of the error token */
|
||||
YYMINORTYPE yyminor /* The minor type of the error token */
|
||||
){
|
||||
ParseARG_FETCH;
|
||||
#define TOKEN (yyminor.yy0)
|
||||
%%
|
||||
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
|
||||
}
|
||||
|
||||
/*
|
||||
** The following is executed when the parser accepts
|
||||
*/
|
||||
static void yy_accept(
|
||||
yyParser *yypParser /* The parser */
|
||||
){
|
||||
ParseARG_FETCH;
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
|
||||
}
|
||||
#endif
|
||||
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
|
||||
/* Here code is inserted which will be executed whenever the
|
||||
** parser accepts */
|
||||
%%
|
||||
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
|
||||
}
|
||||
|
||||
/* The main parser program.
|
||||
** The first argument is a pointer to a structure obtained from
|
||||
** "ParseAlloc" which describes the current state of the parser.
|
||||
** The second argument is the major token number. The third is
|
||||
** the minor token. The fourth optional argument is whatever the
|
||||
** user wants (and specified in the grammar) and is available for
|
||||
** use by the action routines.
|
||||
**
|
||||
** Inputs:
|
||||
** <ul>
|
||||
** <li> A pointer to the parser (an opaque structure.)
|
||||
** <li> The major token number.
|
||||
** <li> The minor token number.
|
||||
** <li> An option argument of a grammar-specified type.
|
||||
** </ul>
|
||||
**
|
||||
** Outputs:
|
||||
** None.
|
||||
*/
|
||||
void Parse(
|
||||
void *yyp, /* The parser */
|
||||
int yymajor, /* The major token code number */
|
||||
ParseTOKENTYPE yyminor /* The value for the token */
|
||||
ParseARG_PDECL /* Optional %extra_argument parameter */
|
||||
){
|
||||
YYMINORTYPE yyminorunion;
|
||||
int yyact; /* The parser action. */
|
||||
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
|
||||
int yyendofinput; /* True if we are at the end of input */
|
||||
#endif
|
||||
#ifdef YYERRORSYMBOL
|
||||
int yyerrorhit = 0; /* True if yymajor has invoked an error */
|
||||
#endif
|
||||
yyParser *yypParser; /* The parser */
|
||||
|
||||
/* (re)initialize the parser, if necessary */
|
||||
yypParser = (yyParser*)yyp;
|
||||
if( yypParser->yyidx<0 ){
|
||||
#if YYSTACKDEPTH<=0
|
||||
if( yypParser->yystksz <=0 ){
|
||||
/*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
|
||||
yyminorunion = yyzerominor;
|
||||
yyStackOverflow(yypParser, &yyminorunion);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
yypParser->yyidx = 0;
|
||||
yypParser->yyerrcnt = -1;
|
||||
yypParser->yystack[0].stateno = 0;
|
||||
yypParser->yystack[0].major = 0;
|
||||
}
|
||||
yyminorunion.yy0 = yyminor;
|
||||
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
|
||||
yyendofinput = (yymajor==0);
|
||||
#endif
|
||||
ParseARG_STORE;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
|
||||
}
|
||||
#endif
|
||||
|
||||
do{
|
||||
yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
|
||||
if( yyact <= YY_MAX_SHIFTREDUCE ){
|
||||
if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
|
||||
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
|
||||
yypParser->yyerrcnt--;
|
||||
yymajor = YYNOCODE;
|
||||
}else if( yyact <= YY_MAX_REDUCE ){
|
||||
yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
|
||||
}else{
|
||||
assert( yyact == YY_ERROR_ACTION );
|
||||
#ifdef YYERRORSYMBOL
|
||||
int yymx;
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
|
||||
}
|
||||
#endif
|
||||
#ifdef YYERRORSYMBOL
|
||||
/* A syntax error has occurred.
|
||||
** The response to an error depends upon whether or not the
|
||||
** grammar defines an error token "ERROR".
|
||||
**
|
||||
** This is what we do if the grammar does define ERROR:
|
||||
**
|
||||
** * Call the %syntax_error function.
|
||||
**
|
||||
** * Begin popping the stack until we enter a state where
|
||||
** it is legal to shift the error symbol, then shift
|
||||
** the error symbol.
|
||||
**
|
||||
** * Set the error count to three.
|
||||
**
|
||||
** * Begin accepting and shifting new tokens. No new error
|
||||
** processing will occur until three tokens have been
|
||||
** shifted successfully.
|
||||
**
|
||||
*/
|
||||
if( yypParser->yyerrcnt<0 ){
|
||||
yy_syntax_error(yypParser,yymajor,yyminorunion);
|
||||
}
|
||||
yymx = yypParser->yystack[yypParser->yyidx].major;
|
||||
if( yymx==YYERRORSYMBOL || yyerrorhit ){
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sDiscard input token %s\n",
|
||||
yyTracePrompt,yyTokenName[yymajor]);
|
||||
}
|
||||
#endif
|
||||
yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
|
||||
yymajor = YYNOCODE;
|
||||
}else{
|
||||
while(
|
||||
yypParser->yyidx >= 0 &&
|
||||
yymx != YYERRORSYMBOL &&
|
||||
(yyact = yy_find_reduce_action(
|
||||
yypParser->yystack[yypParser->yyidx].stateno,
|
||||
YYERRORSYMBOL)) >= YY_MIN_REDUCE
|
||||
){
|
||||
yy_pop_parser_stack(yypParser);
|
||||
}
|
||||
if( yypParser->yyidx < 0 || yymajor==0 ){
|
||||
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
|
||||
yy_parse_failed(yypParser);
|
||||
yymajor = YYNOCODE;
|
||||
}else if( yymx!=YYERRORSYMBOL ){
|
||||
YYMINORTYPE u2;
|
||||
u2.YYERRSYMDT = 0;
|
||||
yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
|
||||
}
|
||||
}
|
||||
yypParser->yyerrcnt = 3;
|
||||
yyerrorhit = 1;
|
||||
#elif defined(YYNOERRORRECOVERY)
|
||||
/* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
|
||||
** do any kind of error recovery. Instead, simply invoke the syntax
|
||||
** error routine and continue going as if nothing had happened.
|
||||
**
|
||||
** Applications can set this macro (for example inside %include) if
|
||||
** they intend to abandon the parse upon the first syntax error seen.
|
||||
*/
|
||||
yy_syntax_error(yypParser,yymajor,yyminorunion);
|
||||
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
|
||||
yymajor = YYNOCODE;
|
||||
|
||||
#else /* YYERRORSYMBOL is not defined */
|
||||
/* This is what we do if the grammar does not define ERROR:
|
||||
**
|
||||
** * Report an error message, and throw away the input token.
|
||||
**
|
||||
** * If the input token is $, then fail the parse.
|
||||
**
|
||||
** As before, subsequent error messages are suppressed until
|
||||
** three input tokens have been successfully shifted.
|
||||
*/
|
||||
if( yypParser->yyerrcnt<=0 ){
|
||||
yy_syntax_error(yypParser,yymajor,yyminorunion);
|
||||
}
|
||||
yypParser->yyerrcnt = 3;
|
||||
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
|
||||
if( yyendofinput ){
|
||||
yy_parse_failed(yypParser);
|
||||
}
|
||||
yymajor = YYNOCODE;
|
||||
#endif
|
||||
}
|
||||
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -220,6 +220,12 @@ int sqlite3_initialize(void){
|
||||
if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){
|
||||
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
|
||||
sqlite3GlobalConfig.inProgress = 1;
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
{
|
||||
extern void sqlite3_init_sqllog(void);
|
||||
sqlite3_init_sqllog();
|
||||
}
|
||||
#endif
|
||||
memset(pHash, 0, sizeof(sqlite3GlobalFunctions));
|
||||
sqlite3RegisterGlobalFunctions();
|
||||
if( sqlite3GlobalConfig.isPCacheInit==0 ){
|
||||
|
||||
+3
-1
@@ -3349,7 +3349,7 @@ static int unixWrite(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
|
||||
/* Deal with as much of this write request as possible by transfering
|
||||
** data from the memory mapping using memcpy(). */
|
||||
if( offset<pFile->mmapSize ){
|
||||
@@ -4774,7 +4774,9 @@ static void unixRemapfile(
|
||||
assert( pFd->mmapSizeActual>=pFd->mmapSize );
|
||||
assert( MAP_FAILED!=0 );
|
||||
|
||||
#ifdef SQLITE_MMAP_READWRITE
|
||||
if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
|
||||
#endif
|
||||
|
||||
if( pOrig ){
|
||||
#if HAVE_MREMAP
|
||||
|
||||
+3
-1
@@ -2602,7 +2602,7 @@ static int winWrite(
|
||||
"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
|
||||
pFile->h, pBuf, amt, offset, pFile->locktype));
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
|
||||
/* Deal with as much of this write request as possible by transfering
|
||||
** data from the memory mapping using memcpy(). */
|
||||
if( offset<pFile->mmapSize ){
|
||||
@@ -4096,10 +4096,12 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
|
||||
DWORD flags = FILE_MAP_READ;
|
||||
|
||||
winUnmapfile(pFd);
|
||||
#ifdef SQLITE_MMAP_READWRITE
|
||||
if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
|
||||
protect = PAGE_READWRITE;
|
||||
flags |= FILE_MAP_WRITE;
|
||||
}
|
||||
#endif
|
||||
#if SQLITE_OS_WINRT
|
||||
pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
|
||||
#elif defined(SQLITE_WIN32_HAS_WIDE)
|
||||
|
||||
+10
-1
@@ -3392,12 +3392,21 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the maximum number of in-memory pages that are allowed.
|
||||
** Change the maximum number of in-memory pages that are allowed
|
||||
** before attempting to recycle clean and unused pages.
|
||||
*/
|
||||
void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
|
||||
sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the maximum number of in-memory pages that are allowed
|
||||
** before attempting to spill pages to journal.
|
||||
*/
|
||||
int sqlite3PagerSetSpillsize(Pager *pPager, int mxPage){
|
||||
return sqlite3PcacheSetSpillsize(pPager->pPCache, mxPage);
|
||||
}
|
||||
|
||||
/*
|
||||
** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
|
||||
*/
|
||||
|
||||
@@ -123,6 +123,7 @@ void sqlite3PagerAlignReserve(Pager*,Pager*);
|
||||
#endif
|
||||
int sqlite3PagerMaxPageCount(Pager*, int);
|
||||
void sqlite3PagerSetCachesize(Pager*, int);
|
||||
int sqlite3PagerSetSpillsize(Pager*, int);
|
||||
void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
|
||||
void sqlite3PagerShrink(Pager*);
|
||||
void sqlite3PagerSetFlags(Pager*,unsigned);
|
||||
|
||||
+20
-9
@@ -60,6 +60,18 @@
|
||||
*/
|
||||
#define yytestcase(X) testcase(X)
|
||||
|
||||
/*
|
||||
** Indicate that sqlite3ParserFree() will never be called with a null
|
||||
** pointer.
|
||||
*/
|
||||
#define YYPARSEFREENEVERNULL 1
|
||||
|
||||
/*
|
||||
** Alternative datatype for the argument to the malloc() routine passed
|
||||
** into sqlite3ParserAlloc(). The default is size_t.
|
||||
*/
|
||||
#define YYMALLOCARGTYPE u64
|
||||
|
||||
/*
|
||||
** An instance of this structure holds information about the
|
||||
** LIMIT clause of a SELECT statement.
|
||||
@@ -162,7 +174,7 @@ create_table_args ::= AS select(S). {
|
||||
sqlite3EndTable(pParse,0,0,0,S);
|
||||
sqlite3SelectDelete(pParse->db, S);
|
||||
}
|
||||
%type table_options {u8}
|
||||
%type table_options {int}
|
||||
table_options(A) ::= . {A = 0;}
|
||||
table_options(A) ::= WITHOUT nm(X). {
|
||||
if( X.n==5 && sqlite3_strnicmp(X.z,"rowid",5)==0 ){
|
||||
@@ -364,12 +376,12 @@ defer_subclause_opt(A) ::= defer_subclause(X). {A = X;}
|
||||
// default behavior when there is a constraint conflict.
|
||||
//
|
||||
%type onconf {int}
|
||||
%type orconf {u8}
|
||||
%type orconf {int}
|
||||
%type resolvetype {int}
|
||||
onconf(A) ::= . {A = OE_Default;}
|
||||
onconf(A) ::= ON CONFLICT resolvetype(X). {A = X;}
|
||||
orconf(A) ::= . {A = OE_Default;}
|
||||
orconf(A) ::= OR resolvetype(X). {A = (u8)X;}
|
||||
orconf(A) ::= OR resolvetype(X). {A = X;}
|
||||
resolvetype(A) ::= raisetype(X). {A = X;}
|
||||
resolvetype(A) ::= IGNORE. {A = OE_Ignore;}
|
||||
resolvetype(A) ::= REPLACE. {A = OE_Replace;}
|
||||
@@ -526,7 +538,7 @@ values(A) ::= values(X) COMMA LP exprlist(Y) RP. {
|
||||
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
|
||||
// present and false (0) if it is not.
|
||||
//
|
||||
%type distinct {u16}
|
||||
%type distinct {int}
|
||||
distinct(A) ::= DISTINCT. {A = SF_Distinct;}
|
||||
distinct(A) ::= ALL. {A = SF_All;}
|
||||
distinct(A) ::= . {A = 0;}
|
||||
@@ -534,7 +546,7 @@ distinct(A) ::= . {A = 0;}
|
||||
// selcollist is a list of expressions that are to become the return
|
||||
// values of the SELECT statement. The "*" in statements like
|
||||
// "SELECT * FROM ..." is encoded as a special expression with an
|
||||
// opcode of TK_ALL.
|
||||
// opcode of TK_ASTERISK.
|
||||
//
|
||||
%type selcollist {ExprList*}
|
||||
%destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);}
|
||||
@@ -548,11 +560,11 @@ selcollist(A) ::= sclp(P) expr(X) as(Y). {
|
||||
sqlite3ExprListSetSpan(pParse,A,&X);
|
||||
}
|
||||
selcollist(A) ::= sclp(P) STAR. {
|
||||
Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
|
||||
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
|
||||
A = sqlite3ExprListAppend(pParse, P, p);
|
||||
}
|
||||
selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). {
|
||||
Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &Y);
|
||||
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &Y);
|
||||
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
||||
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
|
||||
A = sqlite3ExprListAppend(pParse,P, pDot);
|
||||
@@ -639,7 +651,6 @@ dbnm(A) ::= DOT nm(X). {A = X;}
|
||||
fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);}
|
||||
|
||||
%type joinop {int}
|
||||
%type joinop2 {int}
|
||||
joinop(X) ::= COMMA|JOIN. { X = JT_INNER; }
|
||||
joinop(X) ::= JOIN_KW(A) JOIN. { X = sqlite3JoinType(pParse,&A,0,0); }
|
||||
joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqlite3JoinType(pParse,&A,&B,0); }
|
||||
@@ -800,7 +811,7 @@ cmd ::= with(W) insert_cmd(R) INTO fullname(X) idlist_opt(F) DEFAULT VALUES.
|
||||
sqlite3Insert(pParse, X, 0, F, R);
|
||||
}
|
||||
|
||||
%type insert_cmd {u8}
|
||||
%type insert_cmd {int}
|
||||
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
|
||||
insert_cmd(A) ::= REPLACE. {A = OE_Replace;}
|
||||
|
||||
|
||||
+46
-26
@@ -21,6 +21,7 @@ struct PCache {
|
||||
PgHdr *pSynced; /* Last synced page in dirty page list */
|
||||
int nRefSum; /* Sum of ref counts over all pages */
|
||||
int szCache; /* Configured cache size */
|
||||
int szSpill; /* Size before spilling occurs */
|
||||
int szPage; /* Size of every page in this cache */
|
||||
int szExtra; /* Size of extra space for each page */
|
||||
u8 bPurgeable; /* True if pages are on backing store */
|
||||
@@ -110,10 +111,8 @@ static void pcacheUnpin(PgHdr *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute the number of pages of cache requested. p->szCache is the
|
||||
** Compute the number of pages of cache requested. p->szCache is the
|
||||
** cache size requested by the "PRAGMA cache_size" statement.
|
||||
**
|
||||
**
|
||||
*/
|
||||
static int numberOfCachePages(PCache *p){
|
||||
if( p->szCache>=0 ){
|
||||
@@ -176,6 +175,7 @@ int sqlite3PcacheOpen(
|
||||
p->xStress = xStress;
|
||||
p->pStress = pStress;
|
||||
p->szCache = 100;
|
||||
p->szSpill = 1;
|
||||
return sqlite3PcacheSetPageSize(p, szPage);
|
||||
}
|
||||
|
||||
@@ -271,32 +271,33 @@ int sqlite3PcacheFetchStress(
|
||||
PgHdr *pPg;
|
||||
if( pCache->eCreate==2 ) return 0;
|
||||
|
||||
|
||||
/* Find a dirty page to write-out and recycle. First try to find a
|
||||
** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
|
||||
** cleared), but if that is not possible settle for any other
|
||||
** unreferenced dirty page.
|
||||
*/
|
||||
for(pPg=pCache->pSynced;
|
||||
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
|
||||
pPg=pPg->pDirtyPrev
|
||||
);
|
||||
pCache->pSynced = pPg;
|
||||
if( !pPg ){
|
||||
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
|
||||
}
|
||||
if( pPg ){
|
||||
int rc;
|
||||
if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){
|
||||
/* Find a dirty page to write-out and recycle. First try to find a
|
||||
** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
|
||||
** cleared), but if that is not possible settle for any other
|
||||
** unreferenced dirty page.
|
||||
*/
|
||||
for(pPg=pCache->pSynced;
|
||||
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
|
||||
pPg=pPg->pDirtyPrev
|
||||
);
|
||||
pCache->pSynced = pPg;
|
||||
if( !pPg ){
|
||||
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
|
||||
}
|
||||
if( pPg ){
|
||||
int rc;
|
||||
#ifdef SQLITE_LOG_CACHE_SPILL
|
||||
sqlite3_log(SQLITE_FULL,
|
||||
"spill page %d making room for %d - cache used: %d/%d",
|
||||
pPg->pgno, pgno,
|
||||
sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
|
||||
sqlite3_log(SQLITE_FULL,
|
||||
"spill page %d making room for %d - cache used: %d/%d",
|
||||
pPg->pgno, pgno,
|
||||
sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
|
||||
numberOfCachePages(pCache));
|
||||
#endif
|
||||
rc = pCache->xStress(pCache->pStress, pPg);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
|
||||
return rc;
|
||||
rc = pCache->xStress(pCache->pStress, pPg);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
*ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
|
||||
@@ -641,6 +642,25 @@ void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
|
||||
numberOfCachePages(pCache));
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the suggested cache-spill value. Make no changes if if the
|
||||
** argument is zero. Return the effective cache-spill size, which will
|
||||
** be the larger of the szSpill and szCache.
|
||||
*/
|
||||
int sqlite3PcacheSetSpillsize(PCache *p, int mxPage){
|
||||
int res;
|
||||
assert( p->pCache!=0 );
|
||||
if( mxPage ){
|
||||
if( mxPage<0 ){
|
||||
mxPage = (int)((-1024*(i64)mxPage)/(p->szPage+p->szExtra));
|
||||
}
|
||||
p->szSpill = mxPage;
|
||||
}
|
||||
res = numberOfCachePages(p);
|
||||
if( res<p->szSpill ) res = p->szSpill;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free up as much memory as possible from the page cache.
|
||||
*/
|
||||
|
||||
@@ -146,6 +146,13 @@ void sqlite3PcacheSetCachesize(PCache *, int);
|
||||
int sqlite3PcacheGetCachesize(PCache *);
|
||||
#endif
|
||||
|
||||
/* Set or get the suggested spill-size for the specified pager-cache.
|
||||
**
|
||||
** The spill-size is the minimum number of pages in cache before the cache
|
||||
** will attempt to spill dirty pages by calling xStress.
|
||||
*/
|
||||
int sqlite3PcacheSetSpillsize(PCache *, int);
|
||||
|
||||
/* Free up as much memory as possible from the page cache */
|
||||
void sqlite3PcacheShrink(PCache*);
|
||||
|
||||
|
||||
+81
-40
@@ -279,7 +279,7 @@ const char *sqlite3JournalModename(int eMode){
|
||||
**
|
||||
** Pragmas are of this form:
|
||||
**
|
||||
** PRAGMA [database.]id [= value]
|
||||
** PRAGMA [schema.]id [= value]
|
||||
**
|
||||
** The identifier might also be a string. The value is a string, and
|
||||
** identifier, or a number. If minusFlag is true, then the value is
|
||||
@@ -291,8 +291,8 @@ const char *sqlite3JournalModename(int eMode){
|
||||
*/
|
||||
void sqlite3Pragma(
|
||||
Parse *pParse,
|
||||
Token *pId1, /* First part of [database.]id field */
|
||||
Token *pId2, /* Second part of [database.]id field, or NULL */
|
||||
Token *pId1, /* First part of [schema.]id field */
|
||||
Token *pId2, /* Second part of [schema.]id field, or NULL */
|
||||
Token *pValue, /* Token for <value>, or NULL */
|
||||
int minusFlag /* True if a '-' sign preceded <value> */
|
||||
){
|
||||
@@ -313,7 +313,7 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeRunOnlyOnce(v);
|
||||
pParse->nMem = 2;
|
||||
|
||||
/* Interpret the [database.] part of the pragma statement. iDb is the
|
||||
/* Interpret the [schema.] part of the pragma statement. iDb is the
|
||||
** index of the database this pragma is being applied to in db.aDb[]. */
|
||||
iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId);
|
||||
if( iDb<0 ) return;
|
||||
@@ -402,8 +402,8 @@ void sqlite3Pragma(
|
||||
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
|
||||
/*
|
||||
** PRAGMA [database.]default_cache_size
|
||||
** PRAGMA [database.]default_cache_size=N
|
||||
** PRAGMA [schema.]default_cache_size
|
||||
** PRAGMA [schema.]default_cache_size=N
|
||||
**
|
||||
** The first form reports the current persistent setting for the
|
||||
** page cache size. The value returned is the maximum number of
|
||||
@@ -454,8 +454,8 @@ void sqlite3Pragma(
|
||||
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
/*
|
||||
** PRAGMA [database.]page_size
|
||||
** PRAGMA [database.]page_size=N
|
||||
** PRAGMA [schema.]page_size
|
||||
** PRAGMA [schema.]page_size=N
|
||||
**
|
||||
** The first form reports the current setting for the
|
||||
** database page size in bytes. The second form sets the
|
||||
@@ -481,8 +481,8 @@ void sqlite3Pragma(
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]secure_delete
|
||||
** PRAGMA [database.]secure_delete=ON/OFF
|
||||
** PRAGMA [schema.]secure_delete
|
||||
** PRAGMA [schema.]secure_delete=ON/OFF
|
||||
**
|
||||
** The first form reports the current setting for the
|
||||
** secure_delete flag. The second form changes the secure_delete
|
||||
@@ -507,8 +507,8 @@ void sqlite3Pragma(
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]max_page_count
|
||||
** PRAGMA [database.]max_page_count=N
|
||||
** PRAGMA [schema.]max_page_count
|
||||
** PRAGMA [schema.]max_page_count=N
|
||||
**
|
||||
** The first form reports the current setting for the
|
||||
** maximum number of pages in the database file. The
|
||||
@@ -519,7 +519,7 @@ void sqlite3Pragma(
|
||||
** change. The only purpose is to provide an easy way to test
|
||||
** the sqlite3AbsInt32() function.
|
||||
**
|
||||
** PRAGMA [database.]page_count
|
||||
** PRAGMA [schema.]page_count
|
||||
**
|
||||
** Return the number of pages in the specified database.
|
||||
*/
|
||||
@@ -540,8 +540,8 @@ void sqlite3Pragma(
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]locking_mode
|
||||
** PRAGMA [database.]locking_mode = (normal|exclusive)
|
||||
** PRAGMA [schema.]locking_mode
|
||||
** PRAGMA [schema.]locking_mode = (normal|exclusive)
|
||||
*/
|
||||
case PragTyp_LOCKING_MODE: {
|
||||
const char *zRet = "normal";
|
||||
@@ -586,8 +586,8 @@ void sqlite3Pragma(
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]journal_mode
|
||||
** PRAGMA [database.]journal_mode =
|
||||
** PRAGMA [schema.]journal_mode
|
||||
** PRAGMA [schema.]journal_mode =
|
||||
** (delete|persist|off|truncate|memory|wal|off)
|
||||
*/
|
||||
case PragTyp_JOURNAL_MODE: {
|
||||
@@ -627,8 +627,8 @@ void sqlite3Pragma(
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]journal_size_limit
|
||||
** PRAGMA [database.]journal_size_limit=N
|
||||
** PRAGMA [schema.]journal_size_limit
|
||||
** PRAGMA [schema.]journal_size_limit=N
|
||||
**
|
||||
** Get or set the size limit on rollback journal files.
|
||||
*/
|
||||
@@ -647,8 +647,8 @@ void sqlite3Pragma(
|
||||
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]auto_vacuum
|
||||
** PRAGMA [database.]auto_vacuum=N
|
||||
** PRAGMA [schema.]auto_vacuum
|
||||
** PRAGMA [schema.]auto_vacuum=N
|
||||
**
|
||||
** Get or set the value of the database 'auto-vacuum' parameter.
|
||||
** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL
|
||||
@@ -699,7 +699,7 @@ void sqlite3Pragma(
|
||||
#endif
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]incremental_vacuum(N)
|
||||
** PRAGMA [schema.]incremental_vacuum(N)
|
||||
**
|
||||
** Do N steps of incremental vacuuming on a database.
|
||||
*/
|
||||
@@ -722,8 +722,8 @@ void sqlite3Pragma(
|
||||
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
/*
|
||||
** PRAGMA [database.]cache_size
|
||||
** PRAGMA [database.]cache_size=N
|
||||
** PRAGMA [schema.]cache_size
|
||||
** PRAGMA [schema.]cache_size=N
|
||||
**
|
||||
** The first form reports the current local setting for the
|
||||
** page cache size. The second form sets the local
|
||||
@@ -735,19 +735,60 @@ void sqlite3Pragma(
|
||||
case PragTyp_CACHE_SIZE: {
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
if( !zRight ){
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
returnSingleInt(v, "cache_size", pDb->pSchema->cache_size);
|
||||
}else{
|
||||
int size = sqlite3Atoi(zRight);
|
||||
pDb->pSchema->cache_size = size;
|
||||
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]mmap_size(N)
|
||||
** PRAGMA [schema.]cache_spill
|
||||
** PRAGMA cache_spill=BOOLEAN
|
||||
** PRAGMA [schema.]cache_spill=N
|
||||
**
|
||||
** The first form reports the current local setting for the
|
||||
** page cache spill size. The second form turns cache spill on
|
||||
** or off. When turnning cache spill on, the size is set to the
|
||||
** current cache_size. The third form sets a spill size that
|
||||
** may be different form the cache size.
|
||||
** If N is positive then that is the
|
||||
** number of pages in the cache. If N is negative, then the
|
||||
** number of pages is adjusted so that the cache uses -N kibibytes
|
||||
** of memory.
|
||||
**
|
||||
** If the number of cache_spill pages is less then the number of
|
||||
** cache_size pages, no spilling occurs until the page count exceeds
|
||||
** the number of cache_size pages.
|
||||
**
|
||||
** The cache_spill=BOOLEAN setting applies to all attached schemas,
|
||||
** not just the schema specified.
|
||||
*/
|
||||
case PragTyp_CACHE_SPILL: {
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
if( !zRight ){
|
||||
returnSingleInt(v, "cache_spill",
|
||||
(db->flags & SQLITE_CacheSpill)==0 ? 0 :
|
||||
sqlite3BtreeSetSpillSize(pDb->pBt,0));
|
||||
}else{
|
||||
int size = 1;
|
||||
if( sqlite3GetInt32(zRight, &size) ){
|
||||
sqlite3BtreeSetSpillSize(pDb->pBt, size);
|
||||
}
|
||||
if( sqlite3GetBoolean(zRight, size!=0) ){
|
||||
db->flags |= SQLITE_CacheSpill;
|
||||
}else{
|
||||
db->flags &= ~SQLITE_CacheSpill;
|
||||
}
|
||||
setAllPagerFlags(db);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA [schema.]mmap_size(N)
|
||||
**
|
||||
** Used to set mapping size limit. The mapping size limit is
|
||||
** used to limit the aggregate size of all memory mapped regions of the
|
||||
@@ -891,8 +932,8 @@ void sqlite3Pragma(
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
/*
|
||||
** PRAGMA [database.]lock_proxy_file
|
||||
** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path"
|
||||
** PRAGMA [schema.]lock_proxy_file
|
||||
** PRAGMA [schema.]lock_proxy_file = ":auto:"|"lock_file_path"
|
||||
**
|
||||
** Return or set the value of the lock_proxy_file flag. Changing
|
||||
** the value sets a specific file to be used for database access locks.
|
||||
@@ -927,8 +968,8 @@ void sqlite3Pragma(
|
||||
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]synchronous
|
||||
** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
|
||||
** PRAGMA [schema.]synchronous
|
||||
** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL
|
||||
**
|
||||
** Return or set the local value of the synchronous flag. Changing
|
||||
** the local value does not make changes to the disk file and the
|
||||
@@ -1324,7 +1365,7 @@ void sqlite3Pragma(
|
||||
case PragTyp_PARSER_TRACE: {
|
||||
if( zRight ){
|
||||
if( sqlite3GetBoolean(zRight, 0) ){
|
||||
sqlite3ParserTrace(stderr, "parser: ");
|
||||
sqlite3ParserTrace(stdout, "parser: ");
|
||||
}else{
|
||||
sqlite3ParserTrace(0, 0);
|
||||
}
|
||||
@@ -1644,16 +1685,16 @@ void sqlite3Pragma(
|
||||
|
||||
#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
||||
/*
|
||||
** PRAGMA [database.]schema_version
|
||||
** PRAGMA [database.]schema_version = <integer>
|
||||
** PRAGMA [schema.]schema_version
|
||||
** PRAGMA [schema.]schema_version = <integer>
|
||||
**
|
||||
** PRAGMA [database.]user_version
|
||||
** PRAGMA [database.]user_version = <integer>
|
||||
** PRAGMA [schema.]user_version
|
||||
** PRAGMA [schema.]user_version = <integer>
|
||||
**
|
||||
** PRAGMA [database.]freelist_count = <integer>
|
||||
** PRAGMA [schema.]freelist_count = <integer>
|
||||
**
|
||||
** PRAGMA [database.]application_id
|
||||
** PRAGMA [database.]application_id = <integer>
|
||||
** PRAGMA [schema.]application_id
|
||||
** PRAGMA [schema.]application_id = <integer>
|
||||
**
|
||||
** The pragma's schema_version and user_version are used to set or get
|
||||
** the value of the schema-version and user-version, respectively. Both
|
||||
@@ -1728,7 +1769,7 @@ void sqlite3Pragma(
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/*
|
||||
** PRAGMA [database.]wal_checkpoint = passive|full|restart|truncate
|
||||
** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate
|
||||
**
|
||||
** Checkpoint the database.
|
||||
*/
|
||||
|
||||
+41
-40
@@ -8,43 +8,44 @@
|
||||
#define PragTyp_FLAG 2
|
||||
#define PragTyp_BUSY_TIMEOUT 3
|
||||
#define PragTyp_CACHE_SIZE 4
|
||||
#define PragTyp_CASE_SENSITIVE_LIKE 5
|
||||
#define PragTyp_COLLATION_LIST 6
|
||||
#define PragTyp_COMPILE_OPTIONS 7
|
||||
#define PragTyp_DATA_STORE_DIRECTORY 8
|
||||
#define PragTyp_DATABASE_LIST 9
|
||||
#define PragTyp_DEFAULT_CACHE_SIZE 10
|
||||
#define PragTyp_ENCODING 11
|
||||
#define PragTyp_FOREIGN_KEY_CHECK 12
|
||||
#define PragTyp_FOREIGN_KEY_LIST 13
|
||||
#define PragTyp_INCREMENTAL_VACUUM 14
|
||||
#define PragTyp_INDEX_INFO 15
|
||||
#define PragTyp_INDEX_LIST 16
|
||||
#define PragTyp_INTEGRITY_CHECK 17
|
||||
#define PragTyp_JOURNAL_MODE 18
|
||||
#define PragTyp_JOURNAL_SIZE_LIMIT 19
|
||||
#define PragTyp_LOCK_PROXY_FILE 20
|
||||
#define PragTyp_LOCKING_MODE 21
|
||||
#define PragTyp_PAGE_COUNT 22
|
||||
#define PragTyp_MMAP_SIZE 23
|
||||
#define PragTyp_PAGE_SIZE 24
|
||||
#define PragTyp_SECURE_DELETE 25
|
||||
#define PragTyp_SHRINK_MEMORY 26
|
||||
#define PragTyp_SOFT_HEAP_LIMIT 27
|
||||
#define PragTyp_STATS 28
|
||||
#define PragTyp_SYNCHRONOUS 29
|
||||
#define PragTyp_TABLE_INFO 30
|
||||
#define PragTyp_TEMP_STORE 31
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 32
|
||||
#define PragTyp_THREADS 33
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 34
|
||||
#define PragTyp_WAL_CHECKPOINT 35
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 36
|
||||
#define PragTyp_HEXKEY 37
|
||||
#define PragTyp_KEY 38
|
||||
#define PragTyp_REKEY 39
|
||||
#define PragTyp_LOCK_STATUS 40
|
||||
#define PragTyp_PARSER_TRACE 41
|
||||
#define PragTyp_CACHE_SPILL 5
|
||||
#define PragTyp_CASE_SENSITIVE_LIKE 6
|
||||
#define PragTyp_COLLATION_LIST 7
|
||||
#define PragTyp_COMPILE_OPTIONS 8
|
||||
#define PragTyp_DATA_STORE_DIRECTORY 9
|
||||
#define PragTyp_DATABASE_LIST 10
|
||||
#define PragTyp_DEFAULT_CACHE_SIZE 11
|
||||
#define PragTyp_ENCODING 12
|
||||
#define PragTyp_FOREIGN_KEY_CHECK 13
|
||||
#define PragTyp_FOREIGN_KEY_LIST 14
|
||||
#define PragTyp_INCREMENTAL_VACUUM 15
|
||||
#define PragTyp_INDEX_INFO 16
|
||||
#define PragTyp_INDEX_LIST 17
|
||||
#define PragTyp_INTEGRITY_CHECK 18
|
||||
#define PragTyp_JOURNAL_MODE 19
|
||||
#define PragTyp_JOURNAL_SIZE_LIMIT 20
|
||||
#define PragTyp_LOCK_PROXY_FILE 21
|
||||
#define PragTyp_LOCKING_MODE 22
|
||||
#define PragTyp_PAGE_COUNT 23
|
||||
#define PragTyp_MMAP_SIZE 24
|
||||
#define PragTyp_PAGE_SIZE 25
|
||||
#define PragTyp_SECURE_DELETE 26
|
||||
#define PragTyp_SHRINK_MEMORY 27
|
||||
#define PragTyp_SOFT_HEAP_LIMIT 28
|
||||
#define PragTyp_STATS 29
|
||||
#define PragTyp_SYNCHRONOUS 30
|
||||
#define PragTyp_TABLE_INFO 31
|
||||
#define PragTyp_TEMP_STORE 32
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 33
|
||||
#define PragTyp_THREADS 34
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 35
|
||||
#define PragTyp_WAL_CHECKPOINT 36
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 37
|
||||
#define PragTyp_HEXKEY 38
|
||||
#define PragTyp_KEY 39
|
||||
#define PragTyp_REKEY 40
|
||||
#define PragTyp_LOCK_STATUS 41
|
||||
#define PragTyp_PARSER_TRACE 42
|
||||
#define PragFlag_NeedSchema 0x01
|
||||
#define PragFlag_ReadOnly 0x02
|
||||
static const struct sPragmaNames {
|
||||
@@ -86,14 +87,14 @@ static const struct sPragmaNames {
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
{ /* zName: */ "cache_size",
|
||||
/* ePragTyp: */ PragTyp_CACHE_SIZE,
|
||||
/* ePragFlag: */ 0,
|
||||
/* ePragFlag: */ PragFlag_NeedSchema,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
{ /* zName: */ "cache_spill",
|
||||
/* ePragTyp: */ PragTyp_FLAG,
|
||||
/* ePragTyp: */ PragTyp_CACHE_SPILL,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ SQLITE_CacheSpill },
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
{ /* zName: */ "case_sensitive_like",
|
||||
/* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
|
||||
|
||||
+1
-1
@@ -726,7 +726,7 @@ void sqlite3VXPrintf(
|
||||
if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
|
||||
|
||||
if( zExtra ){
|
||||
sqlite3_free(zExtra);
|
||||
sqlite3DbFree(pAccum->db, zExtra);
|
||||
zExtra = 0;
|
||||
}
|
||||
}/* End for loop over the format string */
|
||||
|
||||
+43
-40
@@ -118,7 +118,7 @@ Select *sqlite3SelectNew(
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
}
|
||||
if( pEList==0 ){
|
||||
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0));
|
||||
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
|
||||
}
|
||||
pNew->pEList = pEList;
|
||||
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
|
||||
@@ -1596,13 +1596,15 @@ int sqlite3ColumnsFromExprList(
|
||||
){
|
||||
sqlite3 *db = pParse->db; /* Database connection */
|
||||
int i, j; /* Loop counters */
|
||||
int cnt; /* Index added to make the name unique */
|
||||
u32 cnt; /* Index added to make the name unique */
|
||||
Column *aCol, *pCol; /* For looping over result columns */
|
||||
int nCol; /* Number of columns in the result set */
|
||||
Expr *p; /* Expression for a single result column */
|
||||
char *zName; /* Column name */
|
||||
int nName; /* Size of name in zName[] */
|
||||
Hash ht; /* Hash table of column names */
|
||||
|
||||
sqlite3HashInit(&ht);
|
||||
if( pEList ){
|
||||
nCol = pEList->nExpr;
|
||||
aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
|
||||
@@ -1614,13 +1616,12 @@ int sqlite3ColumnsFromExprList(
|
||||
*pnCol = nCol;
|
||||
*paCol = aCol;
|
||||
|
||||
for(i=0, pCol=aCol; i<nCol; i++, pCol++){
|
||||
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
|
||||
/* Get an appropriate name for the column
|
||||
*/
|
||||
p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
|
||||
if( (zName = pEList->a[i].zName)!=0 ){
|
||||
/* If the column contains an "AS <name>" phrase, use <name> as the name */
|
||||
zName = sqlite3DbStrDup(db, zName);
|
||||
}else{
|
||||
Expr *pColExpr = p; /* The expression that is the result column name */
|
||||
Table *pTab; /* Table associated with this expression */
|
||||
@@ -1633,41 +1634,37 @@ int sqlite3ColumnsFromExprList(
|
||||
int iCol = pColExpr->iColumn;
|
||||
pTab = pColExpr->pTab;
|
||||
if( iCol<0 ) iCol = pTab->iPKey;
|
||||
zName = sqlite3MPrintf(db, "%s",
|
||||
iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
|
||||
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
|
||||
}else if( pColExpr->op==TK_ID ){
|
||||
assert( !ExprHasProperty(pColExpr, EP_IntValue) );
|
||||
zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken);
|
||||
zName = pColExpr->u.zToken;
|
||||
}else{
|
||||
/* Use the original text of the column expression as its name */
|
||||
zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan);
|
||||
zName = pEList->a[i].zSpan;
|
||||
}
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
sqlite3DbFree(db, zName);
|
||||
break;
|
||||
}
|
||||
zName = sqlite3MPrintf(db, "%s", zName);
|
||||
|
||||
/* Make sure the column name is unique. If the name is not unique,
|
||||
** append an integer to the name so that it becomes unique.
|
||||
*/
|
||||
nName = sqlite3Strlen30(zName);
|
||||
for(j=cnt=0; j<i; j++){
|
||||
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
|
||||
char *zNewName;
|
||||
int k;
|
||||
for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
|
||||
if( k>=0 && zName[k]==':' ) nName = k;
|
||||
zName[nName] = 0;
|
||||
zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
|
||||
sqlite3DbFree(db, zName);
|
||||
zName = zNewName;
|
||||
j = -1;
|
||||
if( zName==0 ) break;
|
||||
cnt = 0;
|
||||
while( zName && sqlite3HashFind(&ht, zName)!=0 ){
|
||||
nName = sqlite3Strlen30(zName);
|
||||
if( nName>0 ){
|
||||
for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){}
|
||||
if( zName[j]==':' ) nName = j;
|
||||
}
|
||||
zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
|
||||
if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
|
||||
}
|
||||
pCol->zName = zName;
|
||||
sqlite3ColumnPropertiesFromName(0, pCol);
|
||||
if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
}
|
||||
sqlite3HashClear(&ht);
|
||||
if( db->mallocFailed ){
|
||||
for(j=0; j<i; j++){
|
||||
sqlite3DbFree(db, aCol[j].zName);
|
||||
@@ -3941,7 +3938,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
|
||||
if( pNewSrc==0 ) return WRC_Abort;
|
||||
*pNew = *p;
|
||||
p->pSrc = pNewSrc;
|
||||
p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ALL, 0));
|
||||
p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0));
|
||||
p->op = TK_SELECT;
|
||||
p->pWhere = 0;
|
||||
pNew->pGroupBy = 0;
|
||||
@@ -3972,7 +3969,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
|
||||
** object that the returned CTE belongs to.
|
||||
*/
|
||||
static struct Cte *searchWith(
|
||||
With *pWith, /* Current outermost WITH clause */
|
||||
With *pWith, /* Current innermost WITH clause */
|
||||
struct SrcList_item *pItem, /* FROM clause element to resolve */
|
||||
With **ppContext /* OUT: WITH clause return value belongs to */
|
||||
){
|
||||
@@ -4003,11 +4000,12 @@ static struct Cte *searchWith(
|
||||
** statement with which it is associated.
|
||||
*/
|
||||
void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
|
||||
assert( bFree==0 || pParse->pWith==0 );
|
||||
assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
|
||||
if( pWith ){
|
||||
assert( pParse->pWith!=pWith );
|
||||
pWith->pOuter = pParse->pWith;
|
||||
pParse->pWith = pWith;
|
||||
pParse->bFreeWith = bFree;
|
||||
if( bFree ) pParse->pWithToFree = pWith;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4100,6 +4098,7 @@ static int withExpand(
|
||||
pSavedWith = pParse->pWith;
|
||||
pParse->pWith = pWith;
|
||||
sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
|
||||
pParse->pWith = pWith;
|
||||
|
||||
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
|
||||
pEList = pLeft->pEList;
|
||||
@@ -4280,19 +4279,20 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
/* For every "*" that occurs in the column list, insert the names of
|
||||
** all columns in all tables. And for every TABLE.* insert the names
|
||||
** of all columns in TABLE. The parser inserted a special expression
|
||||
** with the TK_ALL operator for each "*" that it found in the column list.
|
||||
** The following code just has to locate the TK_ALL expressions and expand
|
||||
** each one to the list of all columns in all tables.
|
||||
** with the TK_ASTERISK operator for each "*" that it found in the column
|
||||
** list. The following code just has to locate the TK_ASTERISK
|
||||
** expressions and expand each one to the list of all columns in
|
||||
** all tables.
|
||||
**
|
||||
** The first loop just checks to see if there are any "*" operators
|
||||
** that need expanding.
|
||||
*/
|
||||
for(k=0; k<pEList->nExpr; k++){
|
||||
pE = pEList->a[k].pExpr;
|
||||
if( pE->op==TK_ALL ) break;
|
||||
if( pE->op==TK_ASTERISK ) break;
|
||||
assert( pE->op!=TK_DOT || pE->pRight!=0 );
|
||||
assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
|
||||
if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
|
||||
if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break;
|
||||
}
|
||||
if( k<pEList->nExpr ){
|
||||
/*
|
||||
@@ -4310,7 +4310,9 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
pE = a[k].pExpr;
|
||||
pRight = pE->pRight;
|
||||
assert( pE->op!=TK_DOT || pRight!=0 );
|
||||
if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
|
||||
if( pE->op!=TK_ASTERISK
|
||||
&& (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
|
||||
){
|
||||
/* This particular expression does not need to be expanded.
|
||||
*/
|
||||
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
|
||||
@@ -4362,12 +4364,13 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If a column is marked as 'hidden' (currently only possible
|
||||
** for virtual tables), do not include it in the expanded
|
||||
** result-set list.
|
||||
/* If a column is marked as 'hidden', omit it from the expanded
|
||||
** result-set list unless the SELECT has the SF_IncludeHidden
|
||||
** bit set.
|
||||
*/
|
||||
if( IsHiddenColumn(&pTab->aCol[j]) ){
|
||||
assert(IsVirtual(pTab));
|
||||
if( (p->selFlags & SF_IncludeHidden)==0
|
||||
&& IsHiddenColumn(&pTab->aCol[j])
|
||||
){
|
||||
continue;
|
||||
}
|
||||
tableSeen = 1;
|
||||
|
||||
+5
-5
@@ -165,7 +165,7 @@ static sqlite3_int64 timeOfDay(void){
|
||||
static sqlite3_vfs *clockVfs = 0;
|
||||
sqlite3_int64 t;
|
||||
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
|
||||
if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
|
||||
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
|
||||
clockVfs->xCurrentTimeInt64(clockVfs, &t);
|
||||
}else{
|
||||
double r;
|
||||
@@ -2649,7 +2649,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
{ "schema size:",
|
||||
"SELECT total(length(sql)) FROM %s" },
|
||||
};
|
||||
sqlite3_file *pFile;
|
||||
sqlite3_file *pFile = 0;
|
||||
int i;
|
||||
char *zSchemaTab;
|
||||
char *zDb = nArg>=2 ? azArg[1] : "main";
|
||||
@@ -4882,10 +4882,10 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
int n, sz;
|
||||
sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
||||
if( sz>70000 ) sz = 70000;
|
||||
if( sz<800 ) sz = 800;
|
||||
if( sz<0 ) sz = 0;
|
||||
n = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
||||
if( n<10 ) n = 10;
|
||||
sqlite3_config(SQLITE_CONFIG_PAGECACHE, malloc(n*sz+1), sz, n);
|
||||
sqlite3_config(SQLITE_CONFIG_PAGECACHE,
|
||||
(n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
|
||||
data.shellFlgs |= SHFLG_Pagecache;
|
||||
}else if( strcmp(z,"-lookaside")==0 ){
|
||||
int n, sz;
|
||||
|
||||
+21
-16
@@ -1599,29 +1599,34 @@ struct sqlite3_mem_methods {
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer
|
||||
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
|
||||
** that SQLite can use for the database page cache with the default page
|
||||
** cache implementation.
|
||||
** This configuration should not be used if an application-define page
|
||||
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]
|
||||
** configuration option.
|
||||
** This configuration option is a no-op if an application-define page
|
||||
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
|
||||
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
|
||||
** 8-byte aligned
|
||||
** memory, the size of each page buffer (sz), and the number of pages (N).
|
||||
** 8-byte aligned memory (pMem), the size of each page cache line (sz),
|
||||
** and the number of cache lines (N).
|
||||
** The sz argument should be the size of the largest database page
|
||||
** (a power of two between 512 and 65536) plus some extra bytes for each
|
||||
** page header. ^The number of extra bytes needed by the page header
|
||||
** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
|
||||
** to [sqlite3_config()].
|
||||
** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ].
|
||||
** ^It is harmless, apart from the wasted memory,
|
||||
** for the sz parameter to be larger than necessary. The first
|
||||
** argument should pointer to an 8-byte aligned block of memory that
|
||||
** is at least sz*N bytes of memory, otherwise subsequent behavior is
|
||||
** undefined.
|
||||
** ^SQLite will use the memory provided by the first argument to satisfy its
|
||||
** memory needs for the first N pages that it adds to cache. ^If additional
|
||||
** page cache memory is needed beyond what is provided by this option, then
|
||||
** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd>
|
||||
** for the sz parameter to be larger than necessary. The pMem
|
||||
** argument must be either a NULL pointer or a pointer to an 8-byte
|
||||
** aligned block of memory of at least sz*N bytes, otherwise
|
||||
** subsequent behavior is undefined.
|
||||
** ^When pMem is not NULL, SQLite will strive to use the memory provided
|
||||
** to satisfy page cache needs, falling back to [sqlite3_malloc()] if
|
||||
** a page cache line is larger than sz bytes or if all of the pMem buffer
|
||||
** is exhausted.
|
||||
** ^If pMem is NULL and N is non-zero, then each database connection
|
||||
** does an initial bulk allocation for page cache memory
|
||||
** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or
|
||||
** of -1024*N bytes if N is negative, . ^If additional
|
||||
** page cache memory is needed beyond what is provided by the initial
|
||||
** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
|
||||
** additional cache line. </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
|
||||
|
||||
+23
-5
@@ -527,7 +527,6 @@
|
||||
# define SQLITE_DEFAULT_PCACHE_INITSZ 100
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** GCC does not define the offsetof() macro so we'll have to do it
|
||||
** ourselves.
|
||||
@@ -1682,7 +1681,7 @@ struct Table {
|
||||
/*
|
||||
** Allowed values for Table.tabFlags.
|
||||
**
|
||||
** TF_OOOHidden applies to virtual tables that have hidden columns that are
|
||||
** TF_OOOHidden applies to tables or view that have hidden columns that are
|
||||
** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
|
||||
** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
|
||||
** the TF_OOOHidden attribute would apply in this case. Such tables require
|
||||
@@ -1705,12 +1704,28 @@ struct Table {
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
|
||||
# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
|
||||
#else
|
||||
# define IsVirtual(X) 0
|
||||
# define IsHiddenColumn(X) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn()
|
||||
** only works for non-virtual tables (ordinary tables and views) and is
|
||||
** always false unless SQLITE_ENABLE_HIDDEN_COLUMNS is defined. The
|
||||
** IsHiddenColumn() macro is general purpose.
|
||||
*/
|
||||
#if defined(SQLITE_ENABLE_HIDDEN_COLUMNS)
|
||||
# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
|
||||
# define IsOrdinaryHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
|
||||
#elif !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
|
||||
# define IsOrdinaryHiddenColumn(X) 0
|
||||
#else
|
||||
# define IsHiddenColumn(X) 0
|
||||
# define IsOrdinaryHiddenColumn(X) 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Does the table have a rowid */
|
||||
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
|
||||
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
|
||||
@@ -2504,6 +2519,7 @@ struct Select {
|
||||
#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */
|
||||
#define SF_Recursive 0x2000 /* The recursive part of a recursive CTE */
|
||||
#define SF_Converted 0x4000 /* By convertCompoundSelectToSubquery() */
|
||||
#define SF_IncludeHidden 0x8000 /* Include hidden columns in output */
|
||||
|
||||
|
||||
/*
|
||||
@@ -2762,7 +2778,6 @@ struct Parse {
|
||||
int nVar; /* Number of '?' variables seen in the SQL so far */
|
||||
int nzVar; /* Number of available slots in azVar[] */
|
||||
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
|
||||
u8 bFreeWith; /* True if pWith should be freed with parser */
|
||||
u8 explain; /* True if the EXPLAIN flag is found on the query */
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
|
||||
@@ -2789,6 +2804,7 @@ struct Parse {
|
||||
Table *pZombieTab; /* List of Table objects to delete after code gen */
|
||||
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
|
||||
With *pWith; /* Current WITH clause, or NULL */
|
||||
With *pWithToFree; /* Free this WITH object at the end of the parse */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3283,6 +3299,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
||||
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
|
||||
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
|
||||
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
|
||||
void sqlite3TreeViewWith(TreeView*, const With*, u8);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3326,6 +3343,7 @@ void sqlite3OpenMasterTable(Parse *, int);
|
||||
Index *sqlite3PrimaryKeyIndex(Table*);
|
||||
i16 sqlite3ColumnOfIndex(Index*, i16);
|
||||
void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
|
||||
void sqlite3ColumnPropertiesFromName(Table*, Column*);
|
||||
void sqlite3AddColumn(Parse*,Token*);
|
||||
void sqlite3AddNotNull(Parse*, int);
|
||||
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
|
||||
|
||||
+47
-1
@@ -2226,6 +2226,49 @@ static int test_stmt_scanstatus_reset(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
/*
|
||||
** Usage: sqlite3_config_sqllog
|
||||
**
|
||||
** Zero the SQLITE_CONFIG_SQLLOG configuration
|
||||
*/
|
||||
static int test_config_sqllog(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
if( objc!=1 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Usage: vfs_current_time_int64
|
||||
**
|
||||
** Return the value returned by the default VFS's xCurrentTimeInt64 method.
|
||||
*/
|
||||
static int vfsCurrentTimeInt64(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
i64 t;
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
||||
if( objc!=1 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pVfs->xCurrentTimeInt64(pVfs, &t);
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_next_stmt DB STMT
|
||||
**
|
||||
@@ -7036,7 +7079,10 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 },
|
||||
{ "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
{ "sqlite3_config_sqllog", test_config_sqllog, 0 },
|
||||
#endif
|
||||
{ "vfs_current_time_int64", vfsCurrentTimeInt64, 0 },
|
||||
};
|
||||
static int bitmask_size = sizeof(Bitmask)*8;
|
||||
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
|
||||
|
||||
@@ -125,6 +125,12 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
@@ -669,6 +675,12 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
Tcl_SetVar2(interp, "sqlite_options", "sqllog", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "sqllog", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#define LINKVAR(x) { \
|
||||
static const int cv_ ## x = SQLITE_ ## x; \
|
||||
Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
|
||||
|
||||
+64
-17
@@ -46,6 +46,12 @@
|
||||
** separate copy is taken each time the database file is opened or attached)
|
||||
** by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0.
|
||||
**
|
||||
** If the environment variable SQLITE_SQLLOG_CONDITIONAL is defined, then
|
||||
** logging is only done for database connections if a file named
|
||||
** "<database>-sqllog" exists in the same directly as the main database
|
||||
** file when it is first opened ("<database>" is replaced by the actual
|
||||
** name of the main database file).
|
||||
**
|
||||
** OUTPUT:
|
||||
**
|
||||
** The SQLITE_SQLLOG_DIR is populated with three types of files:
|
||||
@@ -88,6 +94,7 @@ static int getProcessId(void){
|
||||
/* Names of environment variables to be used */
|
||||
#define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR"
|
||||
#define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES"
|
||||
#define ENVIRONMENT_VARIABLE3_NAME "SQLITE_SQLLOG_CONDITIONAL"
|
||||
|
||||
/* Assume that all database and database file names are shorted than this. */
|
||||
#define SQLLOG_NAMESZ 512
|
||||
@@ -116,6 +123,7 @@ static struct SLGlobal {
|
||||
int nConn; /* Size of aConn[] array */
|
||||
|
||||
/* Protected by SLGlobal.mutex */
|
||||
int bConditional; /* Only trace if *-sqllog file is present */
|
||||
int bReuse; /* True to avoid extra copies of db files */
|
||||
char zPrefix[SQLLOG_NAMESZ]; /* Prefix for all created files */
|
||||
char zIdx[SQLLOG_NAMESZ]; /* Full path to *.idx file */
|
||||
@@ -215,7 +223,7 @@ static char *sqllogFindFile(const char *zFile){
|
||||
}
|
||||
|
||||
static int sqllogFindAttached(
|
||||
struct SLConn *p, /* Database connection */
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zSearch, /* Name to search for (or NULL) */
|
||||
char *zName, /* OUT: Name of attached database */
|
||||
char *zFile /* OUT: Name of attached file */
|
||||
@@ -228,7 +236,7 @@ static int sqllogFindAttached(
|
||||
** described by the last row returned. */
|
||||
assert( sqllogglobal.bRec==0 );
|
||||
sqllogglobal.bRec = 1;
|
||||
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(db, "PRAGMA database_list", -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
const char *zVal1; int nVal1;
|
||||
@@ -236,7 +244,9 @@ static int sqllogFindAttached(
|
||||
|
||||
zVal1 = (const char*)sqlite3_column_text(pStmt, 1);
|
||||
nVal1 = sqlite3_column_bytes(pStmt, 1);
|
||||
memcpy(zName, zVal1, nVal1+1);
|
||||
if( zName ){
|
||||
memcpy(zName, zVal1, nVal1+1);
|
||||
}
|
||||
|
||||
zVal2 = (const char*)sqlite3_column_text(pStmt, 2);
|
||||
nVal2 = sqlite3_column_bytes(pStmt, 2);
|
||||
@@ -285,7 +295,7 @@ static void sqllogCopydb(struct SLConn *p, const char *zSearch, int bLog){
|
||||
char *zInit = 0;
|
||||
int rc;
|
||||
|
||||
rc = sqllogFindAttached(p, zSearch, zName, zFile);
|
||||
rc = sqllogFindAttached(p->db, zSearch, zName, zFile);
|
||||
if( rc!=SQLITE_OK ) return;
|
||||
|
||||
if( zFile[0]=='\0' ){
|
||||
@@ -405,6 +415,35 @@ static void testSqllogStmt(struct SLConn *p, const char *zSql){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The database handle passed as the only argument has just been opened.
|
||||
** Return true if this module should log initial databases and SQL
|
||||
** statements for this connection, or false otherwise.
|
||||
**
|
||||
** If an error occurs, sqlite3_log() is invoked to report it to the user
|
||||
** and zero returned.
|
||||
*/
|
||||
static int sqllogTraceDb(sqlite3 *db){
|
||||
int bRet = 1;
|
||||
if( sqllogglobal.bConditional ){
|
||||
char zFile[SQLLOG_NAMESZ]; /* Attached database name */
|
||||
int rc = sqllogFindAttached(db, "main", 0, zFile);
|
||||
if( rc==SQLITE_OK ){
|
||||
int nFile = strlen(zFile);
|
||||
if( (SQLLOG_NAMESZ-nFile)<8 ){
|
||||
sqlite3_log(SQLITE_IOERR,
|
||||
"sqllogTraceDb(): database name too long (%d bytes)", nFile
|
||||
);
|
||||
bRet = 0;
|
||||
}else{
|
||||
memcpy(&zFile[nFile], "-sqllog", 8);
|
||||
bRet = !access(zFile, F_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog().
|
||||
**
|
||||
@@ -439,15 +478,19 @@ static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
|
||||
if( sqllogglobal.mutex==0 ){
|
||||
sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
|
||||
}
|
||||
p = &sqllogglobal.aConn[sqllogglobal.nConn++];
|
||||
p->fd = 0;
|
||||
p->db = db;
|
||||
p->iLog = sqllogglobal.iNextLog++;
|
||||
sqlite3_mutex_leave(master);
|
||||
|
||||
/* Open the log and take a copy of the main database file */
|
||||
sqlite3_mutex_enter(sqllogglobal.mutex);
|
||||
if( sqllogglobal.bRec==0 ){
|
||||
if( sqllogglobal.bRec==0 && sqllogTraceDb(db) ){
|
||||
|
||||
sqlite3_mutex_enter(master);
|
||||
p = &sqllogglobal.aConn[sqllogglobal.nConn++];
|
||||
p->fd = 0;
|
||||
p->db = db;
|
||||
p->iLog = sqllogglobal.iNextLog++;
|
||||
sqlite3_mutex_leave(master);
|
||||
|
||||
/* Open the log and take a copy of the main database file */
|
||||
sqllogOpenlog(p);
|
||||
if( p->fd ) sqllogCopydb(p, "main", 0);
|
||||
}
|
||||
@@ -461,20 +504,21 @@ static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
|
||||
p = &sqllogglobal.aConn[i];
|
||||
if( p->db==db ) break;
|
||||
}
|
||||
if( i==sqllogglobal.nConn ) return;
|
||||
|
||||
/* A database handle close command */
|
||||
if( eType==2 ){
|
||||
sqlite3_mutex_enter(master);
|
||||
if( p->fd ) fclose(p->fd);
|
||||
p->db = 0;
|
||||
p->fd = 0;
|
||||
if( i<sqllogglobal.nConn ){
|
||||
if( p->fd ) fclose(p->fd);
|
||||
p->db = 0;
|
||||
p->fd = 0;
|
||||
sqllogglobal.nConn--;
|
||||
}
|
||||
|
||||
sqllogglobal.nConn--;
|
||||
if( sqllogglobal.nConn==0 ){
|
||||
sqlite3_mutex_free(sqllogglobal.mutex);
|
||||
sqllogglobal.mutex = 0;
|
||||
}else{
|
||||
}else if( i<sqllogglobal.nConn ){
|
||||
int nShift = &sqllogglobal.aConn[sqllogglobal.nConn] - p;
|
||||
if( nShift>0 ){
|
||||
memmove(p, &p[1], nShift*sizeof(struct SLConn));
|
||||
@@ -483,7 +527,7 @@ static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
|
||||
sqlite3_mutex_leave(master);
|
||||
|
||||
/* An ordinary SQL command. */
|
||||
}else if( p->fd ){
|
||||
}else if( i<sqllogglobal.nConn && p->fd ){
|
||||
sqlite3_mutex_enter(sqllogglobal.mutex);
|
||||
if( sqllogglobal.bRec==0 ){
|
||||
testSqllogStmt(p, zSql);
|
||||
@@ -504,6 +548,9 @@ void sqlite3_init_sqllog(void){
|
||||
if( SQLITE_OK==sqlite3_config(SQLITE_CONFIG_SQLLOG, testSqllog, 0) ){
|
||||
memset(&sqllogglobal, 0, sizeof(sqllogglobal));
|
||||
sqllogglobal.bReuse = 1;
|
||||
if( getenv(ENVIRONMENT_VARIABLE3_NAME) ){
|
||||
sqllogglobal.bConditional = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-25
@@ -369,8 +369,8 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
break;
|
||||
}
|
||||
for(i=1; IdChar(z[i]); i++){}
|
||||
*tokenType = keywordCode((char*)z, i);
|
||||
return i;
|
||||
*tokenType = TK_ID;
|
||||
return keywordCode((char*)z, i, tokenType);
|
||||
}
|
||||
}
|
||||
*tokenType = TK_ILLEGAL;
|
||||
@@ -416,7 +416,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
assert( pParse->azVar==0 );
|
||||
enableLookaside = db->lookaside.bEnabled;
|
||||
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
|
||||
while( !db->mallocFailed && zSql[i]!=0 ){
|
||||
while( zSql[i]!=0 ){
|
||||
assert( i>=0 );
|
||||
pParse->sLastToken.z = &zSql[i];
|
||||
pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
|
||||
@@ -425,35 +425,25 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
pParse->rc = SQLITE_TOOBIG;
|
||||
break;
|
||||
}
|
||||
switch( tokenType ){
|
||||
case TK_SPACE: {
|
||||
if( db->u1.isInterrupted ){
|
||||
sqlite3ErrorMsg(pParse, "interrupt");
|
||||
pParse->rc = SQLITE_INTERRUPT;
|
||||
goto abort_parse;
|
||||
}
|
||||
if( tokenType>=TK_SPACE ){
|
||||
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
|
||||
if( db->u1.isInterrupted ){
|
||||
sqlite3ErrorMsg(pParse, "interrupt");
|
||||
pParse->rc = SQLITE_INTERRUPT;
|
||||
break;
|
||||
}
|
||||
case TK_ILLEGAL: {
|
||||
if( tokenType==TK_ILLEGAL ){
|
||||
sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"",
|
||||
&pParse->sLastToken);
|
||||
goto abort_parse;
|
||||
}
|
||||
case TK_SEMI: {
|
||||
pParse->zTail = &zSql[i];
|
||||
/* Fall thru into the default case */
|
||||
}
|
||||
default: {
|
||||
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
|
||||
lastTokenParsed = tokenType;
|
||||
if( pParse->rc!=SQLITE_OK ){
|
||||
goto abort_parse;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
if( tokenType==TK_SEMI ) pParse->zTail = &zSql[i];
|
||||
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
|
||||
lastTokenParsed = tokenType;
|
||||
if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
|
||||
}
|
||||
}
|
||||
abort_parse:
|
||||
assert( nErr==0 );
|
||||
if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
|
||||
assert( zSql[i]==0 );
|
||||
@@ -510,7 +500,7 @@ abort_parse:
|
||||
sqlite3DeleteTable(db, pParse->pNewTable);
|
||||
}
|
||||
|
||||
if( pParse->bFreeWith ) sqlite3WithDelete(db, pParse->pWith);
|
||||
sqlite3WithDelete(db, pParse->pWithToFree);
|
||||
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
|
||||
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
|
||||
sqlite3DbFree(db, pParse->azVar);
|
||||
|
||||
@@ -79,6 +79,45 @@ static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
|
||||
sqlite3TreeViewLine(p, "%s", zLabel);
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate a human-readable description of a WITH clause.
|
||||
*/
|
||||
void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
|
||||
int i;
|
||||
if( pWith==0 ) return;
|
||||
if( pWith->nCte==0 ) return;
|
||||
if( pWith->pOuter ){
|
||||
sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
|
||||
}else{
|
||||
sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
|
||||
}
|
||||
if( pWith->nCte>0 ){
|
||||
pView = sqlite3TreeViewPush(pView, 1);
|
||||
for(i=0; i<pWith->nCte; i++){
|
||||
StrAccum x;
|
||||
char zLine[1000];
|
||||
const struct Cte *pCte = &pWith->a[i];
|
||||
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
|
||||
sqlite3XPrintf(&x, 0, "%s", pCte->zName);
|
||||
if( pCte->pCols && pCte->pCols->nExpr>0 ){
|
||||
char cSep = '(';
|
||||
int j;
|
||||
for(j=0; j<pCte->pCols->nExpr; j++){
|
||||
sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName);
|
||||
cSep = ',';
|
||||
}
|
||||
sqlite3XPrintf(&x, 0, ")");
|
||||
}
|
||||
sqlite3XPrintf(&x, 0, " AS");
|
||||
sqlite3StrAccumFinish(&x);
|
||||
sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
|
||||
sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Generate a human-readable description of a the Select object.
|
||||
@@ -87,6 +126,11 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
int n = 0;
|
||||
int cnt = 0;
|
||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||
if( p->pWith ){
|
||||
sqlite3TreeViewWith(pView, p->pWith, 1);
|
||||
cnt = 1;
|
||||
sqlite3TreeViewPush(pView, 1);
|
||||
}
|
||||
do{
|
||||
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
|
||||
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
|
||||
|
||||
+7
-3
@@ -158,6 +158,12 @@ static void test_addop_breakpoint(void){
|
||||
** the sqlite3VdbeChangeP4() function to change the value of the P4
|
||||
** operand.
|
||||
*/
|
||||
static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
assert( p->pParse->nOpAlloc<=p->nOp );
|
||||
if( growOpArray(p, 1) ) return 1;
|
||||
assert( p->pParse->nOpAlloc>p->nOp );
|
||||
return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
|
||||
}
|
||||
int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
int i;
|
||||
VdbeOp *pOp;
|
||||
@@ -166,9 +172,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
assert( op>0 && op<0xff );
|
||||
if( p->pParse->nOpAlloc<=i ){
|
||||
if( growOpArray(p, 1) ){
|
||||
return 1;
|
||||
}
|
||||
return growOp3(p, op, p1, p2, p3);
|
||||
}
|
||||
p->nOp++;
|
||||
pOp = &p->aOp[i];
|
||||
|
||||
+2
-1
@@ -838,6 +838,7 @@ int main(int argc, char **argv){
|
||||
int nMem = 0; /* Memory limit */
|
||||
char *zExpDb = 0; /* Write Databases to files in this directory */
|
||||
char *zExpSql = 0; /* Write SQL to files in this directory */
|
||||
void *pHeap = 0; /* Heap for use by SQLite */
|
||||
|
||||
iBegin = timeOfDay();
|
||||
#ifdef __unix__
|
||||
@@ -1085,7 +1086,6 @@ int main(int argc, char **argv){
|
||||
|
||||
/* Limit available memory, if requested */
|
||||
if( nMem>0 ){
|
||||
void *pHeap;
|
||||
sqlite3_shutdown();
|
||||
pHeap = malloc(nMem);
|
||||
if( pHeap==0 ){
|
||||
@@ -1184,5 +1184,6 @@ int main(int argc, char **argv){
|
||||
sqlite3_libversion(), sqlite3_sourceid());
|
||||
}
|
||||
free(azSrcDb);
|
||||
free(pHeap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
# 2015 November 18
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Test the __hidden__ hack.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix hidden
|
||||
|
||||
ifcapable !hiddencolumns {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(__hidden__a, b);
|
||||
INSERT INTO t1 VALUES('1');
|
||||
INSERT INTO t1(__hidden__a, b) VALUES('x', 'y');
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT * FROM t1;
|
||||
} {1 y}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT __hidden__a, * FROM t1;
|
||||
} {{} 1 x y}
|
||||
|
||||
foreach {tn view} {
|
||||
1 { CREATE VIEW v1(a, b, __hidden__c) AS SELECT a, b, c FROM x1 }
|
||||
2 { CREATE VIEW v1 AS SELECT a, b, c AS __hidden__c FROM x1 }
|
||||
} {
|
||||
do_execsql_test 2.$tn.1 {
|
||||
DROP TABLE IF EXISTS x1;
|
||||
CREATE TABLE x1(a, b, c);
|
||||
INSERT INTO x1 VALUES(1, 2, 3);
|
||||
}
|
||||
|
||||
catchsql { DROP VIEW v1 }
|
||||
execsql $view
|
||||
|
||||
do_execsql_test 2.$tn.2 {
|
||||
SELECT a, b, __hidden__c FROM v1;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 2.$tn.3 {
|
||||
SELECT * FROM v1;
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 2.$tn.4 {
|
||||
CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
|
||||
INSERT INTO x1 VALUES(new.a, new.b, new.__hidden__c);
|
||||
END;
|
||||
|
||||
INSERT INTO v1 VALUES(4, 5);
|
||||
SELECT * FROM x1;
|
||||
} {1 2 3 4 5 {}}
|
||||
|
||||
do_execsql_test 2.$tn.5 {
|
||||
INSERT INTO v1(a, b, __hidden__c) VALUES(7, 8, 9);
|
||||
SELECT * FROM x1;
|
||||
} {1 2 3 4 5 {} 7 8 9}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test INSERT INTO ... SELECT ... statements that write to tables with
|
||||
# hidden columns.
|
||||
#
|
||||
do_execsql_test 3.1 {
|
||||
CREATE TABLE t4(a, __hidden__b, c);
|
||||
INSERT INTO t4 SELECT 1, 2;
|
||||
SELECT a, __hidden__b, c FROM t4;
|
||||
} {1 {} 2}
|
||||
|
||||
do_execsql_test 3.2.1 {
|
||||
CREATE TABLE t5(__hidden__a, b, c);
|
||||
CREATE TABLE t6(__hidden__a, b, c);
|
||||
INSERT INTO t6(__hidden__a, b, c) VALUES(1, 2, 3);
|
||||
INSERT INTO t6(__hidden__a, b, c) VALUES(4, 5, 6);
|
||||
INSERT INTO t6(__hidden__a, b, c) VALUES(7, 8, 9);
|
||||
}
|
||||
|
||||
do_execsql_test 3.2.2 {
|
||||
INSERT INTO t5 SELECT * FROM t6;
|
||||
SELECT * FROM t5;
|
||||
} {2 3 5 6 8 9}
|
||||
|
||||
do_execsql_test 3.2.3 {
|
||||
SELECT __hidden__a FROM t5;
|
||||
} {{} {} {}}
|
||||
|
||||
|
||||
do_execsql_test 3.3.1 {
|
||||
CREATE TABLE t5a(a, b, __hidden__c);
|
||||
CREATE TABLE t6a(a, b, __hidden__c);
|
||||
INSERT INTO t6a(a, b, __hidden__c) VALUES(1, 2, 3);
|
||||
INSERT INTO t6a(a, b, __hidden__c) VALUES(4, 5, 6);
|
||||
INSERT INTO t6a(a, b, __hidden__c) VALUES(7, 8, 9);
|
||||
}
|
||||
|
||||
do_execsql_test 3.3.2 {
|
||||
INSERT INTO t5a SELECT * FROM t6a;
|
||||
SELECT * FROM t5a;
|
||||
} {1 2 4 5 7 8}
|
||||
|
||||
do_execsql_test 3.3.3 {
|
||||
SELECT __hidden__c FROM t5a;
|
||||
} {{} {} {}}
|
||||
|
||||
do_execsql_test 3.4.1 {
|
||||
CREATE TABLE t5b(a, __hidden__b, c);
|
||||
CREATE TABLE t6b(a, b, __hidden__c);
|
||||
INSERT INTO t6b(a, b, __hidden__c) VALUES(1, 2, 3);
|
||||
INSERT INTO t6b(a, b, __hidden__c) VALUES(4, 5, 6);
|
||||
INSERT INTO t6b(a, b, __hidden__c) VALUES(7, 8, 9);
|
||||
}
|
||||
|
||||
do_execsql_test 3.4.2 {
|
||||
INSERT INTO t5b SELECT * FROM t6b;
|
||||
SELECT * FROM t5b;
|
||||
} {1 2 4 5 7 8}
|
||||
|
||||
do_execsql_test 3.4.3 {
|
||||
SELECT __hidden__b FROM t5b;
|
||||
} {{} {} {}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test VACUUM
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.1 {
|
||||
CREATE TABLE t1(a, __hidden__b, c UNIQUE);
|
||||
INSERT INTO t1(a, __hidden__b, c) VALUES(1, 2, 3);
|
||||
INSERT INTO t1(a, __hidden__b, c) VALUES(4, 5, 6);
|
||||
INSERT INTO t1(a, __hidden__b, c) VALUES(7, 8, 9);
|
||||
DELETE FROM t1 WHERE __hidden__b = 5;
|
||||
SELECT rowid, a, __hidden__b, c FROM t1;
|
||||
} {1 1 2 3 3 7 8 9}
|
||||
do_execsql_test 4.2 {
|
||||
VACUUM;
|
||||
SELECT rowid, a, __hidden__b, c FROM t1;
|
||||
} {1 1 2 3 3 7 8 9}
|
||||
|
||||
finish_test
|
||||
@@ -701,4 +701,13 @@ do_test misc1-24.0 {
|
||||
list [catch { sqlite3_prepare_v2 db ! -1 dummy } msg] $msg
|
||||
} {1 {(1) unrecognized token: "!}}
|
||||
|
||||
# The following query (provided by Kostya Serebryany) used to take 25
|
||||
# minutes to prepare. This has been speeded up to about 250 milliseconds.
|
||||
#
|
||||
do_catchsql_test misc1-25.0 {
|
||||
SELECT-1 UNION SELECT 5 UNION SELECT 0 UNION SElECT*from(SELECT-5) UNION SELECT*from(SELECT-0) UNION SELECT:SELECT-0 UNION SELECT-1 UNION SELECT 1 UNION SELECT 1 ORDER BY S in(WITH K AS(WITH K AS(select'CREINDERcharREADEVIRTUL5TABLECONFLICT !1 USIN'' MFtOR(b38q,eWITH K AS(selectCREATe TABLE t0(a,b,c,d,e, PRIMARY KEY(a,b,c,d,c,a,b,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,a,b,b,c,d,c,a,c,d,c,d,c,e,d,d,c,a,b,b,c,c,a,b,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,a,b,c,e,d,d,c,a,b,b,c,d,d,c,a,b,c,e,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,b,c,e,d,d,c,a,b,b,c,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,e,d,d,c,a,b,b,c,c,a,b,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d'CEIl,k'',ab, g, a,b,o11b, i'nEX/charREDE IVT LR!VABLt5SG',N ,N in rement,l_vacuum,M&U,'te3(''5l' a,bB,b,l*e)SELECT:SELECT, *,*,*from(( SELECT
|
||||
$group,:conc ap0,1)fro,(select"",:PBAG,c,a,b,b,c,a,b,c,e,d,d,c,a,b,b,c,d,d,c,a,b,c,e,d,c,d,c,a,b,c,e,c,d,c,d,c,a,b,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,b,c,e,d,d,c,a,b,b,c,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,e,d,d,c,a,b,b,c,c,a,b,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,a,b,c,e,d,d,c,a,b,b,c,d,d,c,a,b,c,e,d,c,d,c,a,b,c,e,c,d,c,d,c,a,b,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,e,d,d,c,a,b,b,c,c,a,b,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,a,b,c,e,d,d,c,a,b,b,c,d,d,c,a,b,c,e,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,c,d,c,c,a,a,b,d,d,c,a,b,b,c,d,c,a,b,e,e,d,b,c,d,c,a,b,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d, foreign_keysc,d,c,e,d,d,c,a,b,b,c,c,a,b,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,a,b,d,d,c,a,b,b,c,d,c,a,b,e,e,d,b,c,d,c,a,b,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,a,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,e,d,d,c,a,b,b,c,c,a,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,a,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,e,d,d,c,a,b,b,c,c,a,b,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,a,b,c,e,d,d,c,a,b,b,c,d,d,c,a,b,c,e,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,c,d,c,a,b,d,d,c,a,a,b,d,d,c,a,b,b,c,d,c,a,b,e,e,d,b,c,d,c,a,b,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,e,d,d,c,a,b,b,c,c,a,b,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,a,b,d,d,c,a,b,b,c,d,c,a,b,e,e,d,b,c,d,c,a,b,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,c,a,b,b,c,d,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,d,c,e,d,d,c,a,b,b,c,c,a,b,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,a,bb,b,E,d,c,d,c,b,c,d,c,d,c,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,a,b,c,e,d,d,c,a,b,b,c,d,d,c,a,b,c,e,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,c,d,c,a,b,d,d,c,a,a,b,d,d,c,a,b,b,c,d,c,a,b,e,e,d,b,c,d,c,a,b,b,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,c,a,b,c,e,d,d,c,a,b,b,c,d,c,d,c,a,b,c,e,c,d,c,a,b,b,c,d,MAato_aecSELEC,+?b," "O,"i","a",""b ,5 ))KEY)SELECT*FROM((k()reaC,k,K) eA,k '' )t ,K M);
|
||||
} {1 {too many columns in result set}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+63
-6
@@ -135,10 +135,12 @@ delete_file test.db test.db-journal
|
||||
delete_file test2.db test2.db-journal
|
||||
sqlite3 db test.db
|
||||
do_execsql_test pragma2-4.1 {
|
||||
PRAGMA main.cache_size=2000;
|
||||
PRAGMA temp.cache_size=2000;
|
||||
PRAGMA cache_spill;
|
||||
PRAGMA main.cache_spill;
|
||||
PRAGMA temp.cache_spill;
|
||||
} {1 1 1}
|
||||
} {2000 2000 2000}
|
||||
do_execsql_test pragma2-4.2 {
|
||||
PRAGMA cache_spill=OFF;
|
||||
PRAGMA cache_spill;
|
||||
@@ -178,21 +180,56 @@ do_test pragma2-4.4 {
|
||||
PRAGMA lock_status;
|
||||
}
|
||||
} {main exclusive temp unknown} ;# EXCLUSIVE lock due to cache spill
|
||||
do_test pragma2-4.5 {
|
||||
do_test pragma2-4.5.1 {
|
||||
db eval {
|
||||
COMMIT;
|
||||
ROLLBACK;
|
||||
PRAGMA cache_spill=OFF;
|
||||
PRAGMA Cache_Spill;
|
||||
BEGIN;
|
||||
UPDATE t1 SET c=c-1;
|
||||
UPDATE t1 SET c=c+1;
|
||||
PRAGMA lock_status;
|
||||
}
|
||||
} {main reserved temp unknown} ;# No cache spill, so no exclusive lock
|
||||
} {0 main reserved temp unknown} ;# No cache spill, so no exclusive lock
|
||||
do_test pragma2-4.5.2 {
|
||||
db eval {
|
||||
ROLLBACK;
|
||||
PRAGMA cache_spill=100000;
|
||||
PRAGMA cache_spill;
|
||||
BEGIN;
|
||||
UPDATE t1 SET c=c+1;
|
||||
PRAGMA lock_status;
|
||||
}
|
||||
} {100000 main reserved temp unknown} ;# Big spill threshold -> no excl lock
|
||||
ifcapable !memorymanage {
|
||||
do_test pragma2-4.5.3 {
|
||||
db eval {
|
||||
ROLLBACK;
|
||||
PRAGMA cache_spill=25;
|
||||
PRAGMA main.cache_spill;
|
||||
BEGIN;
|
||||
UPDATE t1 SET c=c+1;
|
||||
PRAGMA lock_status;
|
||||
}
|
||||
} {50 main exclusive temp unknown} ;# Small cache spill -> exclusive lock
|
||||
do_test pragma2-4.5.4 {
|
||||
db eval {
|
||||
ROLLBACK;
|
||||
PRAGMA cache_spill(-25);
|
||||
PRAGMA main.cache_spill;
|
||||
BEGIN;
|
||||
UPDATE t1 SET c=c+1;
|
||||
PRAGMA lock_status;
|
||||
}
|
||||
} {50 main exclusive temp unknown} ;# Small cache spill -> exclusive lock
|
||||
}
|
||||
|
||||
|
||||
# Verify that newly attached databases inherit the cache_spill=OFF
|
||||
# setting.
|
||||
#
|
||||
do_execsql_test pragma2-4.6 {
|
||||
COMMIT;
|
||||
ROLLBACK;
|
||||
PRAGMA cache_spill=OFF;
|
||||
ATTACH 'test2.db' AS aux1;
|
||||
PRAGMA aux1.cache_size=50;
|
||||
BEGIN;
|
||||
@@ -209,6 +246,26 @@ do_execsql_test pragma2-4.8 {
|
||||
UPDATE t2 SET c=c-1;
|
||||
PRAGMA lock_status;
|
||||
} {main unlocked temp unknown aux1 exclusive}
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
|
||||
breakpoint
|
||||
do_execsql_test pragma2-5.1 {
|
||||
PRAGMA page_size=16384;
|
||||
CREATE TABLE t1(x);
|
||||
PRAGMA cache_size=2;
|
||||
PRAGMA cache_spill=YES;
|
||||
PRAGMA cache_spill;
|
||||
} {2}
|
||||
do_execsql_test pragma2-5.2 {
|
||||
PRAGMA cache_spill=NO;
|
||||
PRAGMA cache_spill;
|
||||
} {0}
|
||||
do_execsql_test pragma2-5.3 {
|
||||
PRAGMA cache_spill(-51);
|
||||
PRAGMA cache_spill;
|
||||
} {3}
|
||||
|
||||
test_restore_config_pagecache
|
||||
finish_test
|
||||
|
||||
+45
-24
@@ -119,6 +119,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_MEMSYS3=1
|
||||
-DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
-DSQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
-DSQLITE_MAX_ATTACHED=125
|
||||
}
|
||||
"Fast-One" {
|
||||
@@ -145,6 +146,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION=1
|
||||
-DSQLITE_OMIT_PROGRESS_CALLBACK=1
|
||||
-DSQLITE_OMIT_VIRTUALTABLE=1
|
||||
-DSQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
-DSQLITE_TEMP_STORE=3
|
||||
--enable-json1
|
||||
}
|
||||
@@ -213,6 +215,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
-DSQLITE_ENABLE_FTS4
|
||||
-DSQLITE_ENABLE_RTREE
|
||||
-DSQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
--enable-json1
|
||||
}
|
||||
|
||||
@@ -306,22 +309,39 @@ foreach {key value} [array get ::Platforms] {
|
||||
}
|
||||
}
|
||||
|
||||
# Output log
|
||||
# Output log. Disabled for slave interpreters.
|
||||
#
|
||||
set LOG [open releasetest-out.txt w]
|
||||
proc PUTS {args} {
|
||||
if {[llength $args]==2} {
|
||||
puts [lindex $args 0] [lindex $args 1]
|
||||
puts $::LOG [lindex $args 1]
|
||||
} else {
|
||||
puts [lindex $args 0]
|
||||
puts $::LOG [lindex $args 0]
|
||||
if {[lindex $argv end]!="--slave"} {
|
||||
set LOG [open releasetest-out.txt w]
|
||||
proc PUTS {txt} {
|
||||
puts $txt
|
||||
puts $::LOG $txt
|
||||
flush $::LOG
|
||||
}
|
||||
proc PUTSNNL {txt} {
|
||||
puts -nonewline $txt
|
||||
puts -nonewline $::LOG $txt
|
||||
flush $::LOG
|
||||
}
|
||||
proc PUTSERR {txt} {
|
||||
puts stderr $txt
|
||||
puts $::LOG $txt
|
||||
flush $::LOG
|
||||
}
|
||||
puts $LOG "$argv0 $argv"
|
||||
set tm0 [clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S} -gmt 1]
|
||||
puts $LOG "start-time: $tm0 UTC"
|
||||
} else {
|
||||
proc PUTS {txt} {
|
||||
puts $txt
|
||||
}
|
||||
proc PUTSNNL {txt} {
|
||||
puts -nonewline $txt
|
||||
}
|
||||
proc PUTSERR {txt} {
|
||||
puts stderr $txt
|
||||
}
|
||||
flush $::LOG
|
||||
}
|
||||
puts $LOG "$argv0 $argv"
|
||||
set tm0 [clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S} -gmt 1]
|
||||
puts $LOG "start-time: $tm0 UTC"
|
||||
|
||||
# Open the file $logfile and look for a report on the number of errors
|
||||
# and the number of test cases run. Add these values to the global
|
||||
@@ -422,6 +442,7 @@ proc run_slave_test {} {
|
||||
foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
|
||||
|
||||
# Create and switch to the test directory.
|
||||
set ::env(SQLITE_TMPDIR) [file normalize $dir]
|
||||
trace_cmd file mkdir $dir
|
||||
trace_cmd cd $dir
|
||||
catch {file delete core}
|
||||
@@ -809,8 +830,8 @@ proc process_options {argv} {
|
||||
}
|
||||
|
||||
default {
|
||||
PUTS stderr ""
|
||||
PUTS stderr [string trim $::USAGE_MESSAGE]
|
||||
PUTSERR stderr ""
|
||||
PUTSERR stderr [string trim $::USAGE_MESSAGE]
|
||||
exit -1
|
||||
}
|
||||
}
|
||||
@@ -818,7 +839,7 @@ proc process_options {argv} {
|
||||
|
||||
if {0==[info exists ::Platforms($platform)]} {
|
||||
PUTS "Unknown platform: $platform"
|
||||
PUTS -nonewline "Set the -platform option to "
|
||||
PUTSNNL "Set the -platform option to "
|
||||
set print [list]
|
||||
foreach p [array names ::Platforms] {
|
||||
lappend print "\"$p\""
|
||||
@@ -844,16 +865,16 @@ proc process_options {argv} {
|
||||
}
|
||||
PUTS "Running the following test configurations for $platform:"
|
||||
PUTS " [string trim $::CONFIGLIST]"
|
||||
PUTS -nonewline "Flags:"
|
||||
if {$::PROGRESS_MSGS} {PUTS -nonewline " --progress"}
|
||||
if {$::DRYRUN} {PUTS -nonewline " --dryrun"}
|
||||
if {$::BUILDONLY} {PUTS -nonewline " --buildonly"}
|
||||
if {$::MSVC} {PUTS -nonewline " --msvc"}
|
||||
PUTSNNL "Flags:"
|
||||
if {$::PROGRESS_MSGS} {PUTSNNL " --progress"}
|
||||
if {$::DRYRUN} {PUTSNNL " --dryrun"}
|
||||
if {$::BUILDONLY} {PUTSNNL " --buildonly"}
|
||||
if {$::MSVC} {PUTSNNL " --msvc"}
|
||||
switch -- $::QUICK {
|
||||
1 {PUTS -nonewline " --quick"}
|
||||
2 {PUTS -nonewline " --veryquick"}
|
||||
1 {PUTSNNL " --quick"}
|
||||
2 {PUTSNNL " --veryquick"}
|
||||
}
|
||||
if {$::JOBS>1} {PUTS -nonewline " --jobs $::JOBS"}
|
||||
if {$::JOBS>1} {PUTSNNL " --jobs $::JOBS"}
|
||||
PUTS ""
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# 2015 November 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the test_sqllog.c module.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix sqllog
|
||||
|
||||
ifcapable !sqllog {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc readfile {f} {
|
||||
set fd [open $f]
|
||||
set txt [read $fd]
|
||||
close $fd
|
||||
set txt
|
||||
}
|
||||
|
||||
proc delete_all_sqllog_files {} {
|
||||
forcedelete {*}[glob -nocomplain sqllog_*.sql]
|
||||
forcedelete {*}[glob -nocomplain sqllog_*.db]
|
||||
forcedelete {*}[glob -nocomplain sqllog_*.idx]
|
||||
}
|
||||
|
||||
proc touch {f} {
|
||||
set fd [open $f w+]
|
||||
close $fd
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
set ::env(SQLITE_SQLLOG_DIR) [pwd]
|
||||
|
||||
delete_all_sqllog_files
|
||||
|
||||
sqlite3 db test.db
|
||||
set a a
|
||||
set b b
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES($a, $b);
|
||||
SELECT * FROM t1;
|
||||
} {1 2 a b}
|
||||
db close
|
||||
|
||||
do_test 1.1 {
|
||||
readfile [lindex [glob sqllog_*.sql] 0]
|
||||
} [string trimleft {
|
||||
/-- Main database is '.*/sqllog_.*_0.db'
|
||||
CREATE TABLE t1\(x, y\);; -- clock=0
|
||||
INSERT INTO t1 VALUES\(1, 2\);; -- clock=1
|
||||
INSERT INTO t1 VALUES\('a', 'b'\);; -- clock=2
|
||||
SELECT . FROM t1;; -- clock=3
|
||||
/}]
|
||||
|
||||
do_test 1.2 {
|
||||
file size [lindex [glob sqllog_*_0.db] 0]
|
||||
} 1024
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
catch { db close }
|
||||
sqlite3_shutdown
|
||||
delete_all_sqllog_files
|
||||
forcedelete test.db-sqllog
|
||||
|
||||
set ::env(SQLITE_SQLLOG_CONDITIONAL) 1
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 2.1 {
|
||||
INSERT INTO t1 VALUES(4, 5);
|
||||
SELECT * FROM t1;
|
||||
} {1 2 a b 4 5}
|
||||
|
||||
do_test 2.2 {
|
||||
glob -nocomplain sqllog_*
|
||||
} {}
|
||||
|
||||
db close
|
||||
touch test.db-sqllog
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 2.3 {
|
||||
INSERT INTO t1 VALUES(6, 7);
|
||||
SELECT * FROM t1;
|
||||
} {1 2 a b 4 5 6 7}
|
||||
db close
|
||||
|
||||
do_test 2.4 {
|
||||
readfile [lindex [glob sqllog_*.sql] 0]
|
||||
} [string trimleft {
|
||||
/-- Main database is '.*/sqllog_.*_0.db'
|
||||
INSERT INTO t1 VALUES\(6, 7\);; -- clock=0
|
||||
SELECT . FROM t1;; -- clock=1
|
||||
/}]
|
||||
|
||||
catch { db close }
|
||||
sqlite3_shutdown
|
||||
unset ::env(SQLITE_SQLLOG_DIR)
|
||||
unset ::env(SQLITE_SQLLOG_CONDITIONAL)
|
||||
sqlite3_config_sqllog
|
||||
sqlite3_initialize
|
||||
breakpoint
|
||||
finish_test
|
||||
|
||||
|
||||
+4
-4
@@ -746,8 +746,8 @@ proc do_test {name cmd expected} {
|
||||
# if {![info exists ::testprefix] || $::testprefix eq ""} {
|
||||
# error "no test prefix"
|
||||
# }
|
||||
output2_if_no_verbose -nonewline $name...
|
||||
output2 "\nExpected: \[$expected\]\n Got: \[$result\]"
|
||||
output1 ""
|
||||
output2 "! $name expected: \[$expected\]\n! $name got: \[$result\]"
|
||||
fail_test $name
|
||||
} else {
|
||||
output1 " Ok"
|
||||
@@ -1037,7 +1037,7 @@ proc finalize_testing {} {
|
||||
output2 "$nErr errors out of $nTest tests"
|
||||
}
|
||||
if {$nErr>$nKnown} {
|
||||
output2 -nonewline "Failures on these tests:"
|
||||
output2 -nonewline "!Failures on these tests:"
|
||||
foreach x [set_test_counter fail_list] {
|
||||
if {![info exists known_error($x)]} {output2 -nonewline " $x"}
|
||||
}
|
||||
@@ -1053,7 +1053,7 @@ proc finalize_testing {} {
|
||||
foreach {rec} [lsort $omitList] {
|
||||
if {$rec==$prec} continue
|
||||
set prec $rec
|
||||
output2 [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]]
|
||||
output2 [format {. %-12s %s} [lindex $rec 0] [lindex $rec 1]]
|
||||
}
|
||||
}
|
||||
if {$nErr>0 && ![working_64bit_int]} {
|
||||
|
||||
@@ -21,7 +21,6 @@ ifcapable {!trigger} {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# Error messages resulting from qualified trigger names.
|
||||
#
|
||||
do_test trigger7-1.1 {
|
||||
|
||||
+4
-4
@@ -275,9 +275,9 @@ proc lock_callback {method filename handle lock} {
|
||||
if {$lock == "1 7 lock exclusive"} { return SQLITE_BUSY }
|
||||
return SQLITE_OK
|
||||
}
|
||||
puts " Warning: This next test case causes SQLite to call xSleep(1) 100 times."
|
||||
puts " Normally this equates to a 100ms delay, but if SQLite is built on unix"
|
||||
puts " without HAVE_USLEEP defined, it may be 100 seconds."
|
||||
puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times."
|
||||
puts "# Normally this equates to a 100ms delay, but if SQLite is built on unix"
|
||||
puts "# without HAVE_USLEEP defined, it may be 100 seconds."
|
||||
do_test wal3-4.3 {
|
||||
db close
|
||||
set ::locks [list]
|
||||
@@ -285,7 +285,7 @@ do_test wal3-4.3 {
|
||||
catchsql { SELECT * FROM x }
|
||||
} {1 {locking protocol}}
|
||||
|
||||
puts " Warning: Same again!"
|
||||
puts "# Warning: Same again!"
|
||||
proc lock_callback {method filename handle lock} {
|
||||
if {$lock == "0 1 lock exclusive"} { return SQLITE_BUSY }
|
||||
return SQLITE_OK
|
||||
|
||||
+110
@@ -865,4 +865,114 @@ do_catchsql_test 16.1 {
|
||||
SELECT * FROM i;
|
||||
} {1 {recursive aggregate queries not supported}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 17.1 {
|
||||
WITH x(a) AS (
|
||||
WITH y(b) AS (SELECT 10)
|
||||
SELECT 9 UNION ALL SELECT * FROM y
|
||||
)
|
||||
SELECT * FROM x
|
||||
} {9 10}
|
||||
|
||||
do_execsql_test 17.2 {
|
||||
WITH x AS (
|
||||
WITH y(b) AS (SELECT 10)
|
||||
SELECT * FROM y UNION ALL SELECT * FROM y
|
||||
)
|
||||
SELECT * FROM x
|
||||
} {10 10}
|
||||
|
||||
do_test 17.2 {
|
||||
db eval {
|
||||
WITH x AS (
|
||||
WITH y(b) AS (SELECT 10)
|
||||
SELECT * FROM y UNION ALL SELECT * FROM y
|
||||
)
|
||||
SELECT * FROM x
|
||||
} A {
|
||||
# no op
|
||||
}
|
||||
set A(*)
|
||||
} {b}
|
||||
|
||||
do_catchsql_test 17.3 {
|
||||
WITH i AS (
|
||||
WITH j AS (SELECT 5)
|
||||
SELECT 5 FROM i UNION SELECT 8 FROM i
|
||||
)
|
||||
SELECT * FROM i;
|
||||
} {1 {circular reference: i}}
|
||||
|
||||
do_catchsql_test 17.4 {
|
||||
WITH i AS (
|
||||
WITH j AS (SELECT 5)
|
||||
SELECT 5 FROM t1 UNION SELECT 8 FROM t11
|
||||
)
|
||||
SELECT * FROM i;
|
||||
} {1 {no such table: t11}}
|
||||
|
||||
do_execsql_test 17.5 {
|
||||
WITH
|
||||
x1 AS (SELECT 10),
|
||||
x2 AS (SELECT * FROM x1),
|
||||
x3 AS (
|
||||
WITH x1 AS (SELECT 11)
|
||||
SELECT * FROM x2 UNION ALL SELECT * FROM x2
|
||||
)
|
||||
SELECT * FROM x3;
|
||||
} {10 10}
|
||||
|
||||
do_execsql_test 17.6 {
|
||||
WITH
|
||||
x1 AS (SELECT 10),
|
||||
x2 AS (SELECT * FROM x1),
|
||||
x3 AS (
|
||||
WITH x1 AS (SELECT 11)
|
||||
SELECT * FROM x2 UNION ALL SELECT * FROM x1
|
||||
)
|
||||
SELECT * FROM x3;
|
||||
} {10 11}
|
||||
|
||||
do_execsql_test 17.7 {
|
||||
WITH
|
||||
x1 AS (SELECT 10),
|
||||
x2 AS (SELECT * FROM x1),
|
||||
x3 AS (
|
||||
WITH
|
||||
x1 AS ( SELECT 11 ),
|
||||
x4 AS ( SELECT * FROM x2 )
|
||||
SELECT * FROM x4 UNION ALL SELECT * FROM x1
|
||||
)
|
||||
SELECT * FROM x3;
|
||||
} {10 11}
|
||||
|
||||
do_execsql_test 17.8 {
|
||||
WITH
|
||||
x1 AS (SELECT 10),
|
||||
x2 AS (SELECT * FROM x1),
|
||||
x3 AS (
|
||||
WITH
|
||||
x1 AS ( SELECT 11 ),
|
||||
x4 AS ( SELECT * FROM x2 )
|
||||
SELECT * FROM x4 UNION ALL SELECT * FROM x1
|
||||
)
|
||||
SELECT * FROM x3;
|
||||
} {10 11}
|
||||
|
||||
do_execsql_test 17.9 {
|
||||
WITH
|
||||
x1 AS (SELECT 10),
|
||||
x2 AS (SELECT 11),
|
||||
x3 AS (
|
||||
SELECT * FROM x1 UNION ALL SELECT * FROM x2
|
||||
),
|
||||
x4 AS (
|
||||
WITH
|
||||
x1 AS (SELECT 12),
|
||||
x2 AS (SELECT 13)
|
||||
SELECT * FROM x3
|
||||
)
|
||||
SELECT * FROM x4;
|
||||
} {10 11}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# 2015-11-07
|
||||
#
|
||||
# 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 WITH clause.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix with3
|
||||
|
||||
ifcapable {!cte} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Test problems found by Kostya Serebryany using
|
||||
# LibFuzzer. (http://llvm.org/docs/LibFuzzer.html)
|
||||
#
|
||||
do_catchsql_test 1.0 {
|
||||
WITH i(x) AS (
|
||||
WITH j AS (SELECT 10)
|
||||
SELECT 5 FROM t0 UNION SELECT 8 FROM m
|
||||
)
|
||||
SELECT * FROM i;
|
||||
} {1 {no such table: m}}
|
||||
|
||||
# Additional test cases that came out of the work to
|
||||
# fix for Kostya's problem.
|
||||
#
|
||||
do_execsql_test 2.0 {
|
||||
WITH
|
||||
x1 AS (SELECT 10),
|
||||
x2 AS (SELECT 11),
|
||||
x3 AS (
|
||||
SELECT * FROM x1 UNION ALL SELECT * FROM x2
|
||||
),
|
||||
x4 AS (
|
||||
WITH
|
||||
x1 AS (SELECT 12),
|
||||
x2 AS (SELECT 13)
|
||||
SELECT * FROM x3
|
||||
)
|
||||
SELECT * FROM x4;
|
||||
|
||||
} {10 11}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TABLE t1(x);
|
||||
WITH
|
||||
x1(a) AS (values(100))
|
||||
INSERT INTO t1(x)
|
||||
SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
|
||||
SELECT * FROM t1;
|
||||
} {200}
|
||||
|
||||
finish_test
|
||||
+9
-3
@@ -18,7 +18,8 @@ while {![eof $in]} {
|
||||
}
|
||||
close $in
|
||||
|
||||
# The following are the extra token codes to be added
|
||||
# The following are the extra token codes to be added. SPACE and
|
||||
# ILLEGAL *must* be the last two token codes and they must be in that order.
|
||||
#
|
||||
set extras {
|
||||
TO_TEXT
|
||||
@@ -28,8 +29,6 @@ set extras {
|
||||
TO_REAL
|
||||
ISNOT
|
||||
END_OF_FILE
|
||||
ILLEGAL
|
||||
SPACE
|
||||
UNCLOSED_STRING
|
||||
FUNCTION
|
||||
COLUMN
|
||||
@@ -38,6 +37,13 @@ set extras {
|
||||
UMINUS
|
||||
UPLUS
|
||||
REGISTER
|
||||
ASTERISK
|
||||
SPACE
|
||||
ILLEGAL
|
||||
}
|
||||
if {[lrange $extras end-1 end]!="SPACE ILLEGAL"} {
|
||||
error "SPACE and ILLEGAL must be the last two token codes and they\
|
||||
must be in that order"
|
||||
}
|
||||
foreach x $extras {
|
||||
incr max
|
||||
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# A wrapper around cg_annotate that sets appropriate command-line options
|
||||
# and rearranges the output so that annotated files occur in a consistent
|
||||
# sorted order. Used by the run-speed-test.tcl script.
|
||||
#
|
||||
|
||||
set in [open "|cg_annotate --show=Ir --auto=yes --context=40 $argv" r]
|
||||
set dest !
|
||||
set out(!) {}
|
||||
while {![eof $in]} {
|
||||
set line [string map {\t { }} [gets $in]]
|
||||
if {[regexp {^-- Auto-annotated source: (.*)} $line all name]} {
|
||||
set dest $name
|
||||
} elseif {[regexp {^-- line \d+ ------} $line]} {
|
||||
set line [lreplace $line 2 2 {#}]
|
||||
} elseif {[regexp {^The following files chosen for } $line]} {
|
||||
set dest !
|
||||
}
|
||||
append out($dest) $line\n
|
||||
}
|
||||
foreach x [lsort [array names out]] {
|
||||
puts $out($x)
|
||||
}
|
||||
+181
-143
@@ -1,49 +1,67 @@
|
||||
/* Driver template for the LEMON parser generator.
|
||||
** The author disclaims copyright to this source code.
|
||||
*/
|
||||
/* First off, code is included that follows the "include" declaration
|
||||
** in the input grammar file. */
|
||||
#include <stdio.h>
|
||||
%%
|
||||
/* Next is all token values, in a form suitable for use by makeheaders.
|
||||
** This section will be null unless lemon is run with the -m switch.
|
||||
*/
|
||||
/*
|
||||
** These constants (all generated automatically by the parser generator)
|
||||
** specify the various kinds of tokens (terminals) that the parser
|
||||
** understands.
|
||||
** 2000-05-29
|
||||
**
|
||||
** Each symbol here is a terminal symbol in the grammar.
|
||||
** 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.
|
||||
**
|
||||
*************************************************************************
|
||||
** Driver template for the LEMON parser generator.
|
||||
**
|
||||
** The "lemon" program processes an LALR(1) input grammar file, then uses
|
||||
** this template to construct a parser. The "lemon" program inserts text
|
||||
** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
|
||||
** interstitial "-" characters) contained in this template is changed into
|
||||
** the value of the %name directive from the grammar. Otherwise, the content
|
||||
** of this template is copied straight through into the generate parser
|
||||
** source file.
|
||||
**
|
||||
** The following is the concatenation of all %include directives from the
|
||||
** input grammar file:
|
||||
*/
|
||||
#include <stdio.h>
|
||||
/************ Begin %include sections from the grammar ************************/
|
||||
%%
|
||||
/* Make sure the INTERFACE macro is defined.
|
||||
*/
|
||||
#ifndef INTERFACE
|
||||
# define INTERFACE 1
|
||||
#endif
|
||||
/* The next thing included is series of defines which control
|
||||
/**************** End of %include directives **********************************/
|
||||
/* These constants specify the various numeric values for terminal symbols
|
||||
** in a format understandable to "makeheaders". This section is blank unless
|
||||
** "lemon" is run with the "-m" command-line option.
|
||||
***************** Begin makeheaders token definitions *************************/
|
||||
%%
|
||||
/**************** End makeheaders token definitions ***************************/
|
||||
|
||||
/* The next sections is a series of control #defines.
|
||||
** various aspects of the generated parser.
|
||||
** YYCODETYPE is the data type used for storing terminal
|
||||
** and nonterminal numbers. "unsigned char" is
|
||||
** used if there are fewer than 250 terminals
|
||||
** and nonterminals. "int" is used otherwise.
|
||||
** YYNOCODE is a number of type YYCODETYPE which corresponds
|
||||
** to no legal terminal or nonterminal number. This
|
||||
** number is used to fill in empty slots of the hash
|
||||
** table.
|
||||
** YYCODETYPE is the data type used to store the integer codes
|
||||
** that represent terminal and non-terminal symbols.
|
||||
** "unsigned char" is used if there are fewer than
|
||||
** 256 symbols. Larger types otherwise.
|
||||
** YYNOCODE is a number of type YYCODETYPE that is not used for
|
||||
** any terminal or nonterminal symbol.
|
||||
** YYFALLBACK If defined, this indicates that one or more tokens
|
||||
** have fall-back values which should be used if the
|
||||
** original value of the token will not parse.
|
||||
** YYACTIONTYPE is the data type used for storing terminal
|
||||
** and nonterminal numbers. "unsigned char" is
|
||||
** used if there are fewer than 250 rules and
|
||||
** states combined. "int" is used otherwise.
|
||||
** ParseTOKENTYPE is the data type used for minor tokens given
|
||||
** directly to the parser from the tokenizer.
|
||||
** YYMINORTYPE is the data type used for all minor tokens.
|
||||
** (also known as: "terminal symbols") have fall-back
|
||||
** values which should be used if the original symbol
|
||||
** would not parse. This permits keywords to sometimes
|
||||
** be used as identifiers, for example.
|
||||
** YYACTIONTYPE is the data type used for "action codes" - numbers
|
||||
** that indicate what to do in response to the next
|
||||
** token.
|
||||
** ParseTOKENTYPE is the data type used for minor type for terminal
|
||||
** symbols. Background: A "minor type" is a semantic
|
||||
** value associated with a terminal or non-terminal
|
||||
** symbols. For example, for an "ID" terminal symbol,
|
||||
** the minor type might be the name of the identifier.
|
||||
** Each non-terminal can have a different minor type.
|
||||
** Terminal symbols all have the same minor type, though.
|
||||
** This macros defines the minor type for terminal
|
||||
** symbols.
|
||||
** YYMINORTYPE is the data type used for all minor types.
|
||||
** This is typically a union of many types, one of
|
||||
** which is ParseTOKENTYPE. The entry in the union
|
||||
** for base tokens is called "yy0".
|
||||
** for terminal symbols is called "yy0".
|
||||
** YYSTACKDEPTH is the maximum depth of the parser's stack. If
|
||||
** zero the stack is dynamically sized using realloc()
|
||||
** ParseARG_SDECL A static variable declaration for the %extra_argument
|
||||
@@ -62,7 +80,12 @@
|
||||
** YY_ACCEPT_ACTION The yy_action[] code for accept
|
||||
** YY_NO_ACTION The yy_action[] code for no-op
|
||||
*/
|
||||
#ifndef INTERFACE
|
||||
# define INTERFACE 1
|
||||
#endif
|
||||
/************* Begin control #defines *****************************************/
|
||||
%%
|
||||
/************* End control #defines *******************************************/
|
||||
|
||||
/* The yyzerominor constant is used to initialize instances of
|
||||
** YYMINORTYPE objects to zero. */
|
||||
@@ -131,11 +154,13 @@ static const YYMINORTYPE yyzerominor = { 0 };
|
||||
** yy_reduce_ofst[] For each state, the offset into yy_action for
|
||||
** shifting non-terminals after a reduce.
|
||||
** yy_default[] Default action for each state.
|
||||
*/
|
||||
**
|
||||
*********** Begin parsing tables **********************************************/
|
||||
%%
|
||||
/********** End of lemon-generated parsing tables *****************************/
|
||||
|
||||
/* The next table maps tokens into fallback tokens. If a construct
|
||||
** like the following:
|
||||
/* The next table maps tokens (terminal symbols) into fallback tokens.
|
||||
** If a construct like the following:
|
||||
**
|
||||
** %fallback ID X Y Z.
|
||||
**
|
||||
@@ -143,6 +168,10 @@ static const YYMINORTYPE yyzerominor = { 0 };
|
||||
** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
|
||||
** but it does not parse, the type of the token is changed to ID and
|
||||
** the parse is retried before an error is thrown.
|
||||
**
|
||||
** This feature can be used, for example, to cause some keywords in a language
|
||||
** to revert to identifiers if they keyword does not apply in the context where
|
||||
** it appears.
|
||||
*/
|
||||
#ifdef YYFALLBACK
|
||||
static const YYCODETYPE yyFallback[] = {
|
||||
@@ -265,6 +294,15 @@ static void yyGrowStack(yyParser *p){
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Datatype of the argument to the memory allocated passed as the
|
||||
** second argument to ParseAlloc() below. This can be changed by
|
||||
** putting an appropriate #define in the %include section of the input
|
||||
** grammar.
|
||||
*/
|
||||
#ifndef YYMALLOCARGTYPE
|
||||
# define YYMALLOCARGTYPE size_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function allocates a new parser.
|
||||
** The only argument is a pointer to a function which works like
|
||||
@@ -277,9 +315,9 @@ static void yyGrowStack(yyParser *p){
|
||||
** A pointer to a parser. This pointer is used in subsequent calls
|
||||
** to Parse and ParseFree.
|
||||
*/
|
||||
void *ParseAlloc(void *(*mallocProc)(size_t)){
|
||||
void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){
|
||||
yyParser *pParser;
|
||||
pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
|
||||
pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
|
||||
if( pParser ){
|
||||
pParser->yyidx = -1;
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
@@ -294,10 +332,12 @@ void *ParseAlloc(void *(*mallocProc)(size_t)){
|
||||
return pParser;
|
||||
}
|
||||
|
||||
/* The following function deletes the value associated with a
|
||||
** symbol. The symbol can be either a terminal or nonterminal.
|
||||
** "yymajor" is the symbol code, and "yypminor" is a pointer to
|
||||
** the value.
|
||||
/* The following function deletes the "minor type" or semantic value
|
||||
** associated with a symbol. The symbol can be either a terminal
|
||||
** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
|
||||
** a pointer to the value to be deleted. The code used to do the
|
||||
** deletions is derived from the %destructor and/or %token_destructor
|
||||
** directives of the input grammar.
|
||||
*/
|
||||
static void yy_destructor(
|
||||
yyParser *yypParser, /* The parser */
|
||||
@@ -313,10 +353,12 @@ static void yy_destructor(
|
||||
** being destroyed before it is finished parsing.
|
||||
**
|
||||
** Note: during a reduce, the only symbols destroyed are those
|
||||
** which appear on the RHS of the rule, but which are not used
|
||||
** which appear on the RHS of the rule, but which are *not* used
|
||||
** inside the C code.
|
||||
*/
|
||||
/********* Begin destructor definitions ***************************************/
|
||||
%%
|
||||
/********* End destructor definitions *****************************************/
|
||||
default: break; /* If no destructor action specified: do nothing */
|
||||
}
|
||||
}
|
||||
@@ -326,45 +368,37 @@ static void yy_destructor(
|
||||
**
|
||||
** If there is a destructor routine associated with the token which
|
||||
** is popped from the stack, then call it.
|
||||
**
|
||||
** Return the major token number for the symbol popped.
|
||||
*/
|
||||
static int yy_pop_parser_stack(yyParser *pParser){
|
||||
YYCODETYPE yymajor;
|
||||
yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
|
||||
|
||||
if( pParser->yyidx<0 ) return 0;
|
||||
static void yy_pop_parser_stack(yyParser *pParser){
|
||||
yyStackEntry *yytos;
|
||||
assert( pParser->yyidx>=0 );
|
||||
yytos = &pParser->yystack[pParser->yyidx--];
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE && pParser->yyidx>=0 ){
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sPopping %s\n",
|
||||
yyTracePrompt,
|
||||
yyTokenName[yytos->major]);
|
||||
}
|
||||
#endif
|
||||
yymajor = yytos->major;
|
||||
yy_destructor(pParser, yymajor, &yytos->minor);
|
||||
pParser->yyidx--;
|
||||
return yymajor;
|
||||
yy_destructor(pParser, yytos->major, &yytos->minor);
|
||||
}
|
||||
|
||||
/*
|
||||
** Deallocate and destroy a parser. Destructors are all called for
|
||||
** Deallocate and destroy a parser. Destructors are called for
|
||||
** all stack elements before shutting the parser down.
|
||||
**
|
||||
** Inputs:
|
||||
** <ul>
|
||||
** <li> A pointer to the parser. This should be a pointer
|
||||
** obtained from ParseAlloc.
|
||||
** <li> A pointer to a function used to reclaim memory obtained
|
||||
** from malloc.
|
||||
** </ul>
|
||||
** If the YYPARSEFREENEVERNULL macro exists (for example because it
|
||||
** is defined in a %include section of the input grammar) then it is
|
||||
** assumed that the input pointer is never NULL.
|
||||
*/
|
||||
void ParseFree(
|
||||
void *p, /* The parser to be deleted */
|
||||
void (*freeProc)(void*) /* Function used to reclaim memory */
|
||||
){
|
||||
yyParser *pParser = (yyParser*)p;
|
||||
#ifndef YYPARSEFREENEVERNULL
|
||||
if( pParser==0 ) return;
|
||||
#endif
|
||||
while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
|
||||
#if YYSTACKDEPTH<=0
|
||||
free(pParser->yystack);
|
||||
@@ -385,10 +419,6 @@ int ParseStackPeak(void *p){
|
||||
/*
|
||||
** Find the appropriate action for a parser given the terminal
|
||||
** look-ahead token iLookAhead.
|
||||
**
|
||||
** If the look-ahead token is YYNOCODE, then check to see if the action is
|
||||
** independent of the look-ahead. If it is, return the action, otherwise
|
||||
** return YY_NO_ACTION.
|
||||
*/
|
||||
static int yy_find_shift_action(
|
||||
yyParser *pParser, /* The parser */
|
||||
@@ -399,61 +429,62 @@ static int yy_find_shift_action(
|
||||
|
||||
if( stateno>=YY_MIN_REDUCE ) return stateno;
|
||||
assert( stateno <= YY_SHIFT_COUNT );
|
||||
i = yy_shift_ofst[stateno];
|
||||
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
|
||||
assert( iLookAhead!=YYNOCODE );
|
||||
i += iLookAhead;
|
||||
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
|
||||
if( iLookAhead>0 ){
|
||||
do{
|
||||
i = yy_shift_ofst[stateno];
|
||||
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
|
||||
assert( iLookAhead!=YYNOCODE );
|
||||
i += iLookAhead;
|
||||
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
|
||||
if( iLookAhead>0 ){
|
||||
#ifdef YYFALLBACK
|
||||
YYCODETYPE iFallback; /* Fallback token */
|
||||
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
|
||||
&& (iFallback = yyFallback[iLookAhead])!=0 ){
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
|
||||
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
|
||||
}
|
||||
#endif
|
||||
return yy_find_shift_action(pParser, iFallback);
|
||||
}
|
||||
#endif
|
||||
#ifdef YYWILDCARD
|
||||
{
|
||||
int j = i - iLookAhead + YYWILDCARD;
|
||||
if(
|
||||
#if YY_SHIFT_MIN+YYWILDCARD<0
|
||||
j>=0 &&
|
||||
#endif
|
||||
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
|
||||
j<YY_ACTTAB_COUNT &&
|
||||
#endif
|
||||
yy_lookahead[j]==YYWILDCARD
|
||||
){
|
||||
YYCODETYPE iFallback; /* Fallback token */
|
||||
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
|
||||
&& (iFallback = yyFallback[iLookAhead])!=0 ){
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
|
||||
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
|
||||
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
|
||||
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
|
||||
}
|
||||
#endif
|
||||
assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
|
||||
iLookAhead = iFallback;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef YYWILDCARD
|
||||
{
|
||||
int j = i - iLookAhead + YYWILDCARD;
|
||||
if(
|
||||
#if YY_SHIFT_MIN+YYWILDCARD<0
|
||||
j>=0 &&
|
||||
#endif
|
||||
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
|
||||
j<YY_ACTTAB_COUNT &&
|
||||
#endif
|
||||
yy_lookahead[j]==YYWILDCARD
|
||||
){
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
|
||||
yyTracePrompt, yyTokenName[iLookAhead],
|
||||
yyTokenName[YYWILDCARD]);
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
return yy_action[j];
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
return yy_action[j];
|
||||
}
|
||||
}
|
||||
#endif /* YYWILDCARD */
|
||||
}
|
||||
return yy_default[stateno];
|
||||
}else{
|
||||
return yy_action[i];
|
||||
}
|
||||
return yy_default[stateno];
|
||||
}else{
|
||||
return yy_action[i];
|
||||
}
|
||||
}while(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Find the appropriate action for a parser given the non-terminal
|
||||
** look-ahead token iLookAhead.
|
||||
**
|
||||
** If the look-ahead token is YYNOCODE, then check to see if the action is
|
||||
** independent of the look-ahead. If it is, return the action, otherwise
|
||||
** return YY_NO_ACTION.
|
||||
*/
|
||||
static int yy_find_reduce_action(
|
||||
int stateno, /* Current state number */
|
||||
@@ -496,7 +527,9 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
|
||||
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
|
||||
/* Here code is inserted which will execute if the parser
|
||||
** stack every overflows */
|
||||
/******** Begin %stack_overflow code ******************************************/
|
||||
%%
|
||||
/******** End %stack_overflow code ********************************************/
|
||||
ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
|
||||
}
|
||||
|
||||
@@ -506,15 +539,13 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
|
||||
#ifndef NDEBUG
|
||||
static void yyTraceShift(yyParser *yypParser, int yyNewState){
|
||||
if( yyTraceFILE ){
|
||||
int i;
|
||||
if( yyNewState<YYNSTATE ){
|
||||
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
|
||||
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
|
||||
for(i=1; i<=yypParser->yyidx; i++)
|
||||
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
|
||||
fprintf(yyTraceFILE,"\n");
|
||||
fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n",
|
||||
yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major],
|
||||
yyNewState);
|
||||
}else{
|
||||
fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt);
|
||||
fprintf(yyTraceFILE,"%sShift '%s'\n",
|
||||
yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -523,7 +554,7 @@ static void yyTraceShift(yyParser *yypParser, int yyNewState){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Perform a shift action. Return the number of errors.
|
||||
** Perform a shift action.
|
||||
*/
|
||||
static void yy_shift(
|
||||
yyParser *yypParser, /* The parser to be shifted */
|
||||
@@ -590,29 +621,12 @@ static void yy_reduce(
|
||||
if( yyTraceFILE && yyruleno>=0
|
||||
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
|
||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||
fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt,
|
||||
fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
|
||||
yyRuleName[yyruleno], yymsp[-yysize].stateno);
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
/* Silence complaints from purify about yygotominor being uninitialized
|
||||
** in some cases when it is copied into the stack after the following
|
||||
** switch. yygotominor is uninitialized when a rule reduces that does
|
||||
** not set the value of its left-hand side nonterminal. Leaving the
|
||||
** value of the nonterminal uninitialized is utterly harmless as long
|
||||
** as the value is never used. So really the only thing this code
|
||||
** accomplishes is to quieten purify.
|
||||
**
|
||||
** 2007-01-16: The wireshark project (www.wireshark.org) reports that
|
||||
** without this code, their parser segfaults. I'm not sure what there
|
||||
** parser is doing to make this happen. This is the second bug report
|
||||
** from wireshark this week. Clearly they are stressing Lemon in ways
|
||||
** that it has not been previously stressed... (SQLite ticket #2172)
|
||||
*/
|
||||
/*memset(&yygotominor, 0, sizeof(yygotominor));*/
|
||||
yygotominor = yyzerominor;
|
||||
|
||||
|
||||
switch( yyruleno ){
|
||||
/* Beginning here are the reduction cases. A typical example
|
||||
** follows:
|
||||
@@ -622,8 +636,11 @@ static void yy_reduce(
|
||||
** #line <lineno> <thisfile>
|
||||
** break;
|
||||
*/
|
||||
/********** Begin reduce actions **********************************************/
|
||||
%%
|
||||
/********** End reduce actions ************************************************/
|
||||
};
|
||||
assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
|
||||
yygoto = yyRuleInfo[yyruleno].lhs;
|
||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||
yypParser->yyidx -= yysize;
|
||||
@@ -666,7 +683,9 @@ static void yy_parse_failed(
|
||||
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
|
||||
/* Here code is inserted which will be executed whenever the
|
||||
** parser fails */
|
||||
/************ Begin %parse_failure code ***************************************/
|
||||
%%
|
||||
/************ End %parse_failure code *****************************************/
|
||||
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
|
||||
}
|
||||
#endif /* YYNOERRORRECOVERY */
|
||||
@@ -681,7 +700,9 @@ static void yy_syntax_error(
|
||||
){
|
||||
ParseARG_FETCH;
|
||||
#define TOKEN (yyminor.yy0)
|
||||
/************ Begin %syntax_error code ****************************************/
|
||||
%%
|
||||
/************ End %syntax_error code ******************************************/
|
||||
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
|
||||
}
|
||||
|
||||
@@ -700,7 +721,9 @@ static void yy_accept(
|
||||
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
|
||||
/* Here code is inserted which will be executed whenever the
|
||||
** parser accepts */
|
||||
/*********** Begin %parse_accept code *****************************************/
|
||||
%%
|
||||
/*********** End %parse_accept code *******************************************/
|
||||
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
|
||||
}
|
||||
|
||||
@@ -731,7 +754,9 @@ void Parse(
|
||||
){
|
||||
YYMINORTYPE yyminorunion;
|
||||
int yyact; /* The parser action. */
|
||||
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
|
||||
int yyendofinput; /* True if we are at the end of input */
|
||||
#endif
|
||||
#ifdef YYERRORSYMBOL
|
||||
int yyerrorhit = 0; /* True if yymajor has invoked an error */
|
||||
#endif
|
||||
@@ -752,14 +777,22 @@ void Parse(
|
||||
yypParser->yyerrcnt = -1;
|
||||
yypParser->yystack[0].stateno = 0;
|
||||
yypParser->yystack[0].major = 0;
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n",
|
||||
yyTracePrompt);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
yyminorunion.yy0 = yyminor;
|
||||
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
|
||||
yyendofinput = (yymajor==0);
|
||||
#endif
|
||||
ParseARG_STORE;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
|
||||
fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -873,7 +906,12 @@ void Parse(
|
||||
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt);
|
||||
int i;
|
||||
fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
|
||||
for(i=1; i<=yypParser->yyidx; i++)
|
||||
fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ',
|
||||
yyTokenName[yypParser->yystack[i].major]);
|
||||
fprintf(yyTraceFILE,"]\n");
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
|
||||
+19
-35
@@ -277,27 +277,8 @@ static Keyword aKeywordTable[] = {
|
||||
/* Number of keywords */
|
||||
static int nKeyword = (sizeof(aKeywordTable)/sizeof(aKeywordTable[0]));
|
||||
|
||||
/* An array to map all upper-case characters into their corresponding
|
||||
** lower-case character.
|
||||
*/
|
||||
const unsigned char sqlite3UpperToLower[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
|
||||
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
|
||||
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
|
||||
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
|
||||
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
|
||||
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
|
||||
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
|
||||
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
|
||||
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
|
||||
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
|
||||
252,253,254,255
|
||||
};
|
||||
#define UpperToLower sqlite3UpperToLower
|
||||
/* Map all alphabetic characters into the same case */
|
||||
#define charMap(X) (0x20|(X))
|
||||
|
||||
/*
|
||||
** Comparision function for two Keyword records
|
||||
@@ -372,8 +353,8 @@ int main(int argc, char **argv){
|
||||
assert( p->len<sizeof(p->zOrigName) );
|
||||
memcpy(p->zOrigName, p->zName, p->len+1);
|
||||
totalLen += p->len;
|
||||
p->hash = (UpperToLower[(int)p->zName[0]]*4) ^
|
||||
(UpperToLower[(int)p->zName[p->len-1]]*3) ^ p->len;
|
||||
p->hash = (charMap(p->zName[0])*4) ^
|
||||
(charMap(p->zName[p->len-1])*3) ^ (p->len*1);
|
||||
p->id = i+1;
|
||||
}
|
||||
|
||||
@@ -481,7 +462,7 @@ int main(int argc, char **argv){
|
||||
/* Begin generating code */
|
||||
printf("%s", zHdr);
|
||||
printf("/* Hash score: %d */\n", bestCount);
|
||||
printf("static int keywordCode(const char *z, int n){\n");
|
||||
printf("static int keywordCode(const char *z, int n, int *pType){\n");
|
||||
printf(" /* zText[] encodes %d bytes of keywords in %d bytes */\n",
|
||||
totalLen + nKeyword, nChar+1 );
|
||||
for(i=j=k=0; i<nKeyword; i++){
|
||||
@@ -585,24 +566,27 @@ int main(int argc, char **argv){
|
||||
printf("%s };\n", j==0 ? "" : "\n");
|
||||
|
||||
printf(" int h, i;\n");
|
||||
printf(" if( n<2 ) return TK_ID;\n");
|
||||
printf(" h = ((charMap(z[0])*4) ^\n"
|
||||
" (charMap(z[n-1])*3) ^\n"
|
||||
" n) %% %d;\n", bestSize);
|
||||
printf(" for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n");
|
||||
printf(" if( aLen[i]==n &&"
|
||||
" sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){\n");
|
||||
printf(" if( n>=2 ){\n");
|
||||
printf(" h = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) %% %d;\n",
|
||||
bestSize);
|
||||
printf(" for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n");
|
||||
printf(" if( aLen[i]==n &&"
|
||||
" sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){\n");
|
||||
for(i=0; i<nKeyword; i++){
|
||||
printf(" testcase( i==%d ); /* %s */\n",
|
||||
printf(" testcase( i==%d ); /* %s */\n",
|
||||
i, aKeywordTable[i].zOrigName);
|
||||
}
|
||||
printf(" return aCode[i];\n");
|
||||
printf(" *pType = aCode[i];\n");
|
||||
printf(" break;\n");
|
||||
printf(" }\n");
|
||||
printf(" }\n");
|
||||
printf(" }\n");
|
||||
printf(" return TK_ID;\n");
|
||||
printf(" return n;\n");
|
||||
printf("}\n");
|
||||
printf("int sqlite3KeywordCode(const unsigned char *z, int n){\n");
|
||||
printf(" return keywordCode((char*)z, n);\n");
|
||||
printf(" int id = TK_ID;\n");
|
||||
printf(" keywordCode((char*)z, n, &id);\n");
|
||||
printf(" return id;\n");
|
||||
printf("}\n");
|
||||
printf("#define SQLITE_N_KEYWORD %d\n", nKeyword);
|
||||
|
||||
|
||||
@@ -47,8 +47,6 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
|
||||
NAME: cache_spill
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_CacheSpill
|
||||
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
|
||||
NAME: reverse_unordered_selects
|
||||
@@ -170,6 +168,7 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: cache_size
|
||||
FLAG: NeedSchema
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: mmap_size
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This is a template for a script used for day-to-day size and
|
||||
# performance monitoring of SQLite. Typical usage:
|
||||
#
|
||||
# sh run-speed-test.sh trunk # Baseline measurement of trunk
|
||||
# sh run-speed-test.sh x1 # Measure some experimental change
|
||||
# fossil test-diff --tk cout-trunk.txt cout-x1.txt # View chanages
|
||||
#
|
||||
# There are multiple output files, all with a base name given by
|
||||
# the first argument:
|
||||
#
|
||||
# summary-$BASE.txt # Copy of standard output
|
||||
# cout-$BASE.txt # cachegrind output
|
||||
# explain-$BASE.txt # EXPLAIN listings
|
||||
#
|
||||
if test "$1" = ""
|
||||
then
|
||||
echo "Usage: $0 OUTPUTFILE [OPTIONS]"
|
||||
exit
|
||||
fi
|
||||
NAME=$1
|
||||
shift
|
||||
CC_OPTS="-DSQLITE_ENABLE_RTREE"
|
||||
SPEEDTEST_OPTS="--shrink-memory --reprepare"
|
||||
SIZE=5
|
||||
while test "$1" != ""; do
|
||||
case $1 in
|
||||
--reprepare)
|
||||
SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
|
||||
;;
|
||||
--autovacuum)
|
||||
SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
|
||||
;;
|
||||
--utf16be)
|
||||
SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
|
||||
;;
|
||||
--without-rowid)
|
||||
SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
|
||||
;;
|
||||
--size)
|
||||
shift; SIZE=$1
|
||||
;;
|
||||
*)
|
||||
CC_OPTS="$CC_OPTS $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --size $SIZE"
|
||||
echo "NAME = $NAME" | tee summary-$NAME.txt
|
||||
echo "SPEEDTEST_OPTS = $SPEEDTEST_OPTS" | tee -a summary-$NAME.txt
|
||||
echo "CC_OPTS = $CC_OPTS" | tee -a summary-$NAME.txt
|
||||
rm -f cachegrind.out.* speedtest1 speedtest1.db sqlite3.o
|
||||
gcc -g -Os -Wall -I. $CC_OPTS -c sqlite3.c
|
||||
size sqlite3.o | tee -a summary-$NAME.txt
|
||||
gcc -g -Os -Wall -I. $CC_OPTS \
|
||||
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
|
||||
./shell.c ./sqlite3.c -o sqlite3 -ldl -lpthread
|
||||
SRC=./speedtest1.c
|
||||
gcc -g -Os -Wall -I. $CC_OPTS $SRC ./sqlite3.o -o speedtest1 -ldl -lpthread
|
||||
ls -l speedtest1 | tee -a summary-$NAME.txt
|
||||
valgrind --tool=cachegrind ./speedtest1 speedtest1.db \
|
||||
$SPEEDTEST_OPTS 2>&1 | tee -a summary-$NAME.txt
|
||||
size sqlite3.o | tee -a summary-$NAME.txt
|
||||
wc sqlite3.c
|
||||
cg_anno.tcl cachegrind.out.* >cout-$NAME.txt
|
||||
./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt
|
||||
+31
-8
@@ -558,7 +558,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
az = columnNames("main", zTab, &nPk, 0);
|
||||
az2 = columnNames("aux", zTab, &nPk2, 0);
|
||||
if( az && az2 ){
|
||||
for(n=0; az[n]; n++){
|
||||
for(n=0; az[n] && az2[n]; n++){
|
||||
if( sqlite3_stricmp(az[n],az2[n])!=0 ) break;
|
||||
}
|
||||
}
|
||||
@@ -568,13 +568,15 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
|| az[n]
|
||||
){
|
||||
/* Schema mismatch */
|
||||
fprintf(out, "DROP TABLE %s;\n", zId);
|
||||
fprintf(out, "DROP TABLE %s; -- due to schema mismatch\n", zId);
|
||||
dump_table(zTab, out);
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
|
||||
/* Build the comparison query */
|
||||
for(n2=n; az[n2]; n2++){}
|
||||
for(n2=n; az2[n2]; n2++){
|
||||
fprintf(out, "ALTER TABLE %s ADD COLUMN %s;\n", zId, safeId(az2[n2]));
|
||||
}
|
||||
nQ = nPk2+1+2*(n2-nPk2);
|
||||
if( n2>nPk2 ){
|
||||
zSep = "SELECT ";
|
||||
@@ -585,7 +587,12 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
strPrintf(&sql, ", 1%s -- changed row\n", nPk==n ? "" : ",");
|
||||
while( az[i] ){
|
||||
strPrintf(&sql, " A.%s IS NOT B.%s, B.%s%s\n",
|
||||
az[i], az[i], az[i], i==n2-1 ? "" : ",");
|
||||
az[i], az2[i], az2[i], az2[i+1]==0 ? "" : ",");
|
||||
i++;
|
||||
}
|
||||
while( az2[i] ){
|
||||
strPrintf(&sql, " B.%s IS NOT NULL, B.%s%s\n",
|
||||
az2[i], az2[i], az2[i+1]==0 ? "" : ",");
|
||||
i++;
|
||||
}
|
||||
strPrintf(&sql, " FROM main.%s A, aux.%s B\n", zId, zId);
|
||||
@@ -597,7 +604,13 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
zSep = "\n AND (";
|
||||
while( az[i] ){
|
||||
strPrintf(&sql, "%sA.%s IS NOT B.%s%s\n",
|
||||
zSep, az[i], az[i], i==n2-1 ? ")" : "");
|
||||
zSep, az[i], az2[i], az2[i+1]==0 ? ")" : "");
|
||||
zSep = " OR ";
|
||||
i++;
|
||||
}
|
||||
while( az2[i] ){
|
||||
strPrintf(&sql, "%sB.%s IS NOT NULL%s\n",
|
||||
zSep, az2[i], az2[i+1]==0 ? ")" : "");
|
||||
zSep = " OR ";
|
||||
i++;
|
||||
}
|
||||
@@ -609,7 +622,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
zSep = ", ";
|
||||
}
|
||||
strPrintf(&sql, ", 2%s -- deleted row\n", nPk==n ? "" : ",");
|
||||
while( az[i] ){
|
||||
while( az2[i] ){
|
||||
strPrintf(&sql, " NULL, NULL%s\n", i==n2-1 ? "" : ",");
|
||||
i++;
|
||||
}
|
||||
@@ -628,7 +641,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
}
|
||||
strPrintf(&sql, ", 3%s -- inserted row\n", nPk==n ? "" : ",");
|
||||
while( az2[i] ){
|
||||
strPrintf(&sql, " 1, B.%s%s\n", az[i], i==n2-1 ? "" : ",");
|
||||
strPrintf(&sql, " 1, B.%s%s\n", az2[i], az2[i+1]==0 ? "" : ",");
|
||||
i++;
|
||||
}
|
||||
strPrintf(&sql, " FROM aux.%s B\n", zId);
|
||||
@@ -689,7 +702,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
for(i=0; i<nPk; i++){
|
||||
fprintf(out, "%s %s=", zSep, az2[i]);
|
||||
printQuoted(out, sqlite3_column_value(pStmt,i));
|
||||
zSep = ",";
|
||||
zSep = " AND";
|
||||
}
|
||||
fprintf(out, ";\n");
|
||||
}else{ /* Insert a row */
|
||||
@@ -1728,6 +1741,7 @@ static void showHelp(void){
|
||||
" --schema Show only differences in the schema\n"
|
||||
" --summary Show only a summary of the differences\n"
|
||||
" --table TAB Show only differences in table TAB\n"
|
||||
" --transaction Show SQL output inside a transaction\n"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1744,6 +1758,8 @@ int main(int argc, char **argv){
|
||||
void (*xDiff)(const char*,FILE*) = diff_one_table;
|
||||
int nExt = 0;
|
||||
char **azExt = 0;
|
||||
int useTransaction = 0;
|
||||
int neverUseTransaction = 0;
|
||||
|
||||
g.zArgv0 = argv[0];
|
||||
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
|
||||
@@ -1757,6 +1773,7 @@ int main(int argc, char **argv){
|
||||
out = fopen(argv[++i], "wb");
|
||||
if( out==0 ) cmdlineError("cannot open: %s", argv[i]);
|
||||
xDiff = changeset_one_table;
|
||||
neverUseTransaction = 1;
|
||||
}else
|
||||
if( strcmp(z,"debug")==0 ){
|
||||
if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
|
||||
@@ -1790,6 +1807,9 @@ int main(int argc, char **argv){
|
||||
if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
|
||||
zTab = argv[++i];
|
||||
}else
|
||||
if( strcmp(z,"transaction")==0 ){
|
||||
useTransaction = 1;
|
||||
}else
|
||||
{
|
||||
cmdlineError("unknown option: %s", argv[i]);
|
||||
}
|
||||
@@ -1832,6 +1852,8 @@ int main(int argc, char **argv){
|
||||
cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb2);
|
||||
}
|
||||
|
||||
if( neverUseTransaction ) useTransaction = 0;
|
||||
if( useTransaction ) printf("BEGIN TRANSACTION;\n");
|
||||
if( zTab ){
|
||||
xDiff(zTab, out);
|
||||
}else{
|
||||
@@ -1849,6 +1871,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
if( useTransaction ) printf("COMMIT;\n");
|
||||
|
||||
/* TBD: Handle trigger differences */
|
||||
/* TBD: Handle view differences */
|
||||
|
||||
Reference in New Issue
Block a user