1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Merge recent enhancements, and especially the WAL overwrite change, from trunk.

FossilOrigin-Name: c4a858b228a164be2f89f5b01833f0b5e0d7735b
This commit is contained in:
drh
2016-01-11 13:10:41 +00:00
25 changed files with 478 additions and 174 deletions

View File

@ -1 +1 @@
3.10.0 3.11.0

18
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.10.0. # Generated by GNU Autoconf 2.69 for sqlite 3.11.0.
# #
# #
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='sqlite' PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite' PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.10.0' PACKAGE_VERSION='3.11.0'
PACKAGE_STRING='sqlite 3.10.0' PACKAGE_STRING='sqlite 3.11.0'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='' PACKAGE_URL=''
@ -1460,7 +1460,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures sqlite 3.10.0 to adapt to many kinds of systems. \`configure' configures sqlite 3.11.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1525,7 +1525,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.10.0:";; short | recursive ) echo "Configuration of sqlite 3.11.0:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1646,7 +1646,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
sqlite configure 3.10.0 sqlite configure 3.11.0
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -2065,7 +2065,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.10.0, which was It was created by sqlite $as_me 3.11.0, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -12023,7 +12023,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by sqlite $as_me 3.10.0, which was This file was extended by sqlite $as_me 3.11.0, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -12089,7 +12089,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
sqlite config.status 3.10.0 sqlite config.status 3.11.0
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -1,10 +1,10 @@
C Merge\schanges\sfor\sversion\s3.10.0. C Merge\srecent\senhancements,\sand\sespecially\sthe\sWAL\soverwrite\schange,\sfrom\strunk.
D 2016-01-06T15:14:53.379 D 2016-01-11T13:10:41.337
F Makefile.in e3c1e13b4eba06cbb7f9295148383b7e284596be F Makefile.in e3c1e13b4eba06cbb7f9295148383b7e284596be
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 6862a51bfd3716bbe3c387c724feb73937b107d2 F Makefile.msc 6862a51bfd3716bbe3c387c724feb73937b107d2
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 8b9d3ac6f1962f94e06ba05462422a544f9c4e36 F VERSION 866588d1edf0ccb5b0d33896974338f97564f719
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@ -29,7 +29,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0 F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure e511ceefe595e35051933a90c848ab4fa1d48add x F configure b4519bb54fff37e7cde9d03d8f2946f18d5d0086 x
F configure.ac fcfc67b323d32daaa3e46cf7782d9465ed423a6d F configure.ac fcfc67b323d32daaa3e46cf7782d9465ed423a6d
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1 F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
@ -295,21 +295,21 @@ F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc
F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c 4d3452b2a3daf875490ac4f0a278da7f85fabe12 F src/btree.c 6bd9b3d778a023e2238a81cd0b87b00085220e0e
F src/btree.h 2d76dee44704c47eed323356a758662724b674a0 F src/btree.h 68ef301795e00cdf1d3ab93abc44a43b7fe771e0
F src/btreeInt.h b5f2651b41808f038dee9282c5dc0232ce6532d3 F src/btreeInt.h b5f2651b41808f038dee9282c5dc0232ce6532d3
F src/build.c d8006e9030c61b9495d0b2f724edd3fcdae16930 F src/build.c 9d497ff4bf3c82cecb520436e0e9963785627583
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c e4655393bb403fa310eef66cc4583d75d4d7fd93 F src/date.c e4655393bb403fa310eef66cc4583d75d4d7fd93
F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78 F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78
F src/delete.c 86e3940d07fe69a40270c2aaf6ca6c7adf19246c F src/delete.c 86e3940d07fe69a40270c2aaf6ca6c7adf19246c
F src/expr.c 38790e65d1219f2b7dc26458f39a5252fe7c60cd F src/expr.c fe55c489362d1429c364e98c877514f4455f45a6
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c e18b3dff7d47c7bcac5ac4fc178a89b9fd322b44 F src/fkey.c e18b3dff7d47c7bcac5ac4fc178a89b9fd322b44
F src/func.c cf5e10af9125b245f1b962e8ba4d520a37818795 F src/func.c ccaf46fa98f795673afbfab73dff7c18db88f3cd
F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
@ -324,7 +324,7 @@ F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 262055c242fa7db59c5f07ad77fdc4e97888c054 F src/mem5.c 71f81a11fc5e29a57428761ab38a7bf2ef4ee19d
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85 F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
@ -337,14 +337,14 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c 0ca6d8710366fbb01a275160f018334cd347cbda F src/os_unix.c 82986e1e75782b54da7822dca42d36d974fc2948
F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811 F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 58d2593612acb6b542de6715b4af397ea1fa0a35 F src/pager.c 58d2593612acb6b542de6715b4af397ea1fa0a35
F src/pager.h bf25005b4656cd805af43487c3139fca9678d0cc F src/pager.h bf25005b4656cd805af43487c3139fca9678d0cc
F src/parse.y 23737e649c26ce327603799e57f5c2ff50e5e6ba F src/parse.y caad1e98edeca6960493d0c60d31b76820dd7776
F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23
F src/pcache.h 1ff11adce609ba7de139b6abfabaf9a2bac947b5 F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6 F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
@ -353,16 +353,16 @@ F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c a83b41104e6ff69855d03cd0aaa09e93927ec39f F src/resolve.c a83b41104e6ff69855d03cd0aaa09e93927ec39f
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c f8fded11fc443a9f5a73cc5db069d06b34460e2f F src/select.c d84c091185bc160c349e8bf460ebd084dbd77e64
F src/shell.c 40ded7e3ade5f2cc89ab1180994f6a6975ebc6f3 F src/shell.c 40ded7e3ade5f2cc89ab1180994f6a6975ebc6f3
F src/sqlite.h.in 686be87fcbaea46b1aa8197a17b7a437d39764fc F src/sqlite.h.in 686be87fcbaea46b1aa8197a17b7a437d39764fc
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
F src/sqliteInt.h 961c445154db6d8240ddc0900aa48c5745c23e80 F src/sqliteInt.h 09f70fe715a74ea0048ae05526f2a1b6e3a3b6a2
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tclsqlite.c e2344bee0d192397f555a24ef3fab26f2ed93bcc F src/tclsqlite.c b2fa693e57720dc87c18183dd5c0399bf7038ebd
F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7 F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
@ -420,16 +420,16 @@ F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c a479a4bd02b6b77b7ff3ff84825fccc0b967fe6a F src/vdbe.c a479a4bd02b6b77b7ff3ff84825fccc0b967fe6a
F src/vdbe.h bfe3f80dba435377cdb64fd917f2529f0f48ab77 F src/vdbe.h bfe3f80dba435377cdb64fd917f2529f0f48ab77
F src/vdbeInt.h 4f3b46806b93faa92f0511c7ce30ed31aaec65be F src/vdbeInt.h 1bff4effc71888e3f304e2e6ac7484e39ab78c28
F src/vdbeapi.c ab2cb8fe23fb9f3195f1311eaa800495d83b6118 F src/vdbeapi.c ab2cb8fe23fb9f3195f1311eaa800495d83b6118
F src/vdbeaux.c 13ddc450aa8113660497bcbd244139880b30966c F src/vdbeaux.c 77b4a5cbde74f7c3b1d7052c5c4afea89fb20341
F src/vdbeblob.c cc13eca96b8ec51b6248de785a1aec5df11f5805 F src/vdbeblob.c cc13eca96b8ec51b6248de785a1aec5df11f5805
F src/vdbemem.c 25b6cfd665b5073480452426e84136edd94140c0 F src/vdbemem.c 25b6cfd665b5073480452426e84136edd94140c0
F src/vdbesort.c a7ec02da4494c59dfd071126dd3726be5a11459d F src/vdbesort.c a7ec02da4494c59dfd071126dd3726be5a11459d
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806 F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 974928c988681c5157202c79dd9f26afaa7b5086 F src/wal.c 92ca9e7923c337c497e4c9aa7edac800e269a1d8
F src/wal.h 907943dfdef10b583e81906679a347e0ec6f1b1b F src/wal.h 907943dfdef10b583e81906679a347e0ec6f1b1b
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
F src/where.c c6d3d2f6af57d574a7365ee2b225a5024f2a6bec F src/where.c c6d3d2f6af57d574a7365ee2b225a5024f2a6bec
@ -769,7 +769,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzcheck.c ccdcdc28579b2c9744696bca8726bdbd729eea11 F test/fuzzcheck.c 3309d793165ca61a9996271cb799694839348f9a
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@ -1082,7 +1082,7 @@ F test/tclsqlite.test 7179b4e0bf236ddf0bfa6bfaefa76fbe0a23c28a
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl 24d971d001a5bb10ef13c27768caed182eb1566e F test/tester.tcl a4b1c8e78ad88426dc0b2375e0b5348d2b841c88
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@ -1295,12 +1295,12 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96 F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe
F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
F test/vtabH.test 492ba03dcb7bb8fedcc53f258c410d04013adbc9 F test/vtabH.test 5f5157a1501d9889ec35c1a1832f69612dd31444
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772 F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772
F test/wal.test dbfc482e10c7263298833bb1fc60b3ac9d6340a1 F test/wal.test 65bfc68f3f09dcbc62cee9f794e560428d96cec7
F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada
F test/wal3.test b1d425f68a1f61d12563f0fa1ee6fca7d5afabf4 F test/wal3.test b1d425f68a1f61d12563f0fa1ee6fca7d5afabf4
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
@ -1322,6 +1322,7 @@ F test/walfault.test 1f8389f7709877e9b4cc679033d71d6fe529056b
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483 F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496 F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
F test/waloverwrite.test 8702964967c2f28204f0b4f27af65da81999fc99
F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6 F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57 F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
@ -1427,7 +1428,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P c785cd7813e4ef6d6f2cb362a0f822713db6bcea fd0a50f0797d154fefff724624f00548b5320566 P fa4705c91f9650ecd7ec967dbbf0028aabd8a98c 8e807bfaa197027d0cb73532baa96755ce71ea12
R bf5c420f78514c3466fbe2f1d92a5b04 R 207c595909cfacc40e672adb0642fe8a
U drh U drh
Z d51966c7773281c88034ef287a881d30 Z c05d49256eed75a98851d063f39abe2d

View File

@ -1 +1 @@
fa4705c91f9650ecd7ec967dbbf0028aabd8a98c c4a858b228a164be2f89f5b01833f0b5e0d7735b

View File

@ -169,21 +169,6 @@ int sqlite3BtreeHoldsMutex(Btree *p){
#endif #endif
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Enter and leave a mutex on a Btree given a cursor owned by that
** Btree. These entry points are used by incremental I/O and can be
** omitted if that module is not used.
*/
void sqlite3BtreeEnterCursor(BtCursor *pCur){
sqlite3BtreeEnter(pCur->pBtree);
}
void sqlite3BtreeLeaveCursor(BtCursor *pCur){
sqlite3BtreeLeave(pCur->pBtree);
}
#endif /* SQLITE_OMIT_INCRBLOB */
/* /*
** Enter the mutex on every Btree associated with a database ** Enter the mutex on every Btree associated with a database
** connection. This is needed (for example) prior to parsing ** connection. This is needed (for example) prior to parsing
@ -217,14 +202,6 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){
} }
} }
/*
** Return true if a particular Btree requires a lock. Return FALSE if
** no lock is ever required since it is not sharable.
*/
int sqlite3BtreeSharable(Btree *p){
return p->sharable;
}
#ifndef NDEBUG #ifndef NDEBUG
/* /*
** Return true if the current thread holds the database connection ** Return true if the current thread holds the database connection
@ -298,4 +275,23 @@ void sqlite3BtreeEnterAll(sqlite3 *db){
} }
} }
#endif /* if SQLITE_THREADSAFE */ #endif /* if SQLITE_THREADSAFE */
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Enter a mutex on a Btree given a cursor owned by that Btree.
**
** These entry points are used by incremental I/O only. Enter() is required
** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not
** the build is threadsafe. Leave() is only required by threadsafe builds.
*/
void sqlite3BtreeEnterCursor(BtCursor *pCur){
sqlite3BtreeEnter(pCur->pBtree);
}
# if SQLITE_THREADSAFE
void sqlite3BtreeLeaveCursor(BtCursor *pCur){
sqlite3BtreeLeave(pCur->pBtree);
}
# endif
#endif /* ifndef SQLITE_OMIT_INCRBLOB */
#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */

View File

@ -450,6 +450,10 @@ static void releasePage(MemPage *pPage); /* Forward reference */
static int cursorHoldsMutex(BtCursor *p){ static int cursorHoldsMutex(BtCursor *p){
return sqlite3_mutex_held(p->pBt->mutex); return sqlite3_mutex_held(p->pBt->mutex);
} }
static int cursorOwnsBtShared(BtCursor *p){
assert( cursorHoldsMutex(p) );
return (p->pBtree->db==p->pBt->db);
}
#endif #endif
/* /*
@ -786,7 +790,7 @@ static int btreeMoveto(
static int btreeRestoreCursorPosition(BtCursor *pCur){ static int btreeRestoreCursorPosition(BtCursor *pCur){
int rc; int rc;
int skipNext; int skipNext;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState>=CURSOR_REQUIRESEEK ); assert( pCur->eState>=CURSOR_REQUIRESEEK );
if( pCur->eState==CURSOR_FAULT ){ if( pCur->eState==CURSOR_FAULT ){
return pCur->skipNext; return pCur->skipNext;
@ -3126,7 +3130,6 @@ int sqlite3BtreeNewDb(Btree *p){
** proceed. ** proceed.
*/ */
int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
sqlite3 *pBlock = 0;
BtShared *pBt = p->pBt; BtShared *pBt = p->pBt;
int rc = SQLITE_OK; int rc = SQLITE_OK;
@ -3149,27 +3152,30 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
} }
#ifndef SQLITE_OMIT_SHARED_CACHE #ifndef SQLITE_OMIT_SHARED_CACHE
/* If another database handle has already opened a write transaction {
** on this shared-btree structure and a second write transaction is sqlite3 *pBlock = 0;
** requested, return SQLITE_LOCKED. /* If another database handle has already opened a write transaction
*/ ** on this shared-btree structure and a second write transaction is
if( (wrflag && pBt->inTransaction==TRANS_WRITE) ** requested, return SQLITE_LOCKED.
|| (pBt->btsFlags & BTS_PENDING)!=0 */
){ if( (wrflag && pBt->inTransaction==TRANS_WRITE)
pBlock = pBt->pWriter->db; || (pBt->btsFlags & BTS_PENDING)!=0
}else if( wrflag>1 ){ ){
BtLock *pIter; pBlock = pBt->pWriter->db;
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ }else if( wrflag>1 ){
if( pIter->pBtree!=p ){ BtLock *pIter;
pBlock = pIter->pBtree->db; for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
break; if( pIter->pBtree!=p ){
pBlock = pIter->pBtree->db;
break;
}
} }
} }
} if( pBlock ){
if( pBlock ){ sqlite3ConnectionBlocked(p->db, pBlock);
sqlite3ConnectionBlocked(p->db, pBlock); rc = SQLITE_LOCKED_SHAREDCACHE;
rc = SQLITE_LOCKED_SHAREDCACHE; goto trans_begun;
goto trans_begun; }
} }
#endif #endif
@ -4286,7 +4292,7 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
** to return an integer result code for historical reasons. ** to return an integer result code for historical reasons.
*/ */
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 ); assert( pCur->iPage>=0 );
assert( pCur->iPage<BTCURSOR_MAX_DEPTH ); assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
@ -4666,7 +4672,7 @@ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
} }
#endif #endif
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
rc = restoreCursorPosition(pCur); rc = restoreCursorPosition(pCur);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
@ -4704,7 +4710,7 @@ static const void *fetchPayload(
assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->info.nSize>0 ); assert( pCur->info.nSize>0 );
assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB ); assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
@ -4750,7 +4756,7 @@ const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){
static int moveToChild(BtCursor *pCur, u32 newPgno){ static int moveToChild(BtCursor *pCur, u32 newPgno){
BtShared *pBt = pCur->pBt; BtShared *pBt = pCur->pBt;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage<BTCURSOR_MAX_DEPTH ); assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
assert( pCur->iPage>=0 ); assert( pCur->iPage>=0 );
@ -4796,7 +4802,7 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
** the largest cell index. ** the largest cell index.
*/ */
static void moveToParent(BtCursor *pCur){ static void moveToParent(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>0 ); assert( pCur->iPage>0 );
assert( pCur->apPage[pCur->iPage] ); assert( pCur->apPage[pCur->iPage] );
@ -4836,7 +4842,7 @@ static int moveToRoot(BtCursor *pCur){
MemPage *pRoot; MemPage *pRoot;
int rc = SQLITE_OK; int rc = SQLITE_OK;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
@ -4915,7 +4921,7 @@ static int moveToLeftmost(BtCursor *pCur){
int rc = SQLITE_OK; int rc = SQLITE_OK;
MemPage *pPage; MemPage *pPage;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell ); assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
@ -4940,7 +4946,7 @@ static int moveToRightmost(BtCursor *pCur){
int rc = SQLITE_OK; int rc = SQLITE_OK;
MemPage *pPage = 0; MemPage *pPage = 0;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){ while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
@ -4961,7 +4967,7 @@ static int moveToRightmost(BtCursor *pCur){
int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
int rc; int rc;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
rc = moveToRoot(pCur); rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
@ -4984,7 +4990,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
int rc; int rc;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor already points to the last entry, this is a no-op. */ /* If the cursor already points to the last entry, this is a no-op. */
@ -5062,7 +5068,7 @@ int sqlite3BtreeMovetoUnpacked(
int rc; int rc;
RecordCompare xRecordCompare; RecordCompare xRecordCompare;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( pRes ); assert( pRes );
assert( (pIdxKey==0)==(pCur->pKeyInfo==0) ); assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
@ -5310,7 +5316,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
int idx; int idx;
MemPage *pPage; MemPage *pPage;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( *pRes==0 ); assert( *pRes==0 );
if( pCur->eState!=CURSOR_VALID ){ if( pCur->eState!=CURSOR_VALID ){
@ -5374,7 +5380,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
} }
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
MemPage *pPage; MemPage *pPage;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pRes!=0 ); assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 ); assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
@ -5419,7 +5425,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
int rc; int rc;
MemPage *pPage; MemPage *pPage;
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pRes!=0 ); assert( pRes!=0 );
assert( *pRes==0 ); assert( *pRes==0 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
@ -5475,7 +5481,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
return rc; return rc;
} }
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pRes!=0 ); assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 ); assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
@ -7955,7 +7961,7 @@ int sqlite3BtreeInsert(
return pCur->skipNext; return pCur->skipNext;
} }
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( (pCur->curFlags & BTCF_WriteFlag)!=0 assert( (pCur->curFlags & BTCF_WriteFlag)!=0
&& pBt->inTransaction==TRANS_WRITE && pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 ); && (pBt->btsFlags & BTS_READ_ONLY)==0 );
@ -8102,7 +8108,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
u16 szCell; /* Size of the cell being deleted */ u16 szCell; /* Size of the cell being deleted */
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
assert( cursorHoldsMutex(pCur) ); assert( cursorOwnsBtShared(pCur) );
assert( pBt->inTransaction==TRANS_WRITE ); assert( pBt->inTransaction==TRANS_WRITE );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( pCur->curFlags & BTCF_WriteFlag ); assert( pCur->curFlags & BTCF_WriteFlag );
@ -9564,7 +9570,7 @@ int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
*/ */
int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
int rc; int rc;
assert( cursorHoldsMutex(pCsr) ); assert( cursorOwnsBtShared(pCsr) );
assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
assert( pCsr->curFlags & BTCF_Incrblob ); assert( pCsr->curFlags & BTCF_Incrblob );
@ -9671,3 +9677,12 @@ int sqlite3BtreeIsReadonly(Btree *p){
** Return the size of the header added to each page by this module. ** Return the size of the header added to each page by this module.
*/ */
int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
#if !defined(SQLITE_OMIT_SHARED_CACHE)
/*
** Return true if the Btree passed as the only argument is sharable.
*/
int sqlite3BtreeSharable(Btree *p){
return p->sharable;
}
#endif

View File

@ -287,15 +287,17 @@ void sqlite3BtreeCursorList(Btree*);
#ifndef SQLITE_OMIT_SHARED_CACHE #ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3BtreeEnter(Btree*); void sqlite3BtreeEnter(Btree*);
void sqlite3BtreeEnterAll(sqlite3*); void sqlite3BtreeEnterAll(sqlite3*);
int sqlite3BtreeSharable(Btree*);
void sqlite3BtreeEnterCursor(BtCursor*);
#else #else
# define sqlite3BtreeEnter(X) # define sqlite3BtreeEnter(X)
# define sqlite3BtreeEnterAll(X) # define sqlite3BtreeEnterAll(X)
# define sqlite3BtreeSharable(X) 0
# define sqlite3BtreeEnterCursor(X)
#endif #endif
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
int sqlite3BtreeSharable(Btree*);
void sqlite3BtreeLeave(Btree*); void sqlite3BtreeLeave(Btree*);
void sqlite3BtreeEnterCursor(BtCursor*);
void sqlite3BtreeLeaveCursor(BtCursor*); void sqlite3BtreeLeaveCursor(BtCursor*);
void sqlite3BtreeLeaveAll(sqlite3*); void sqlite3BtreeLeaveAll(sqlite3*);
#ifndef NDEBUG #ifndef NDEBUG
@ -306,9 +308,7 @@ void sqlite3BtreeCursorList(Btree*);
#endif #endif
#else #else
# define sqlite3BtreeSharable(X) 0
# define sqlite3BtreeLeave(X) # define sqlite3BtreeLeave(X)
# define sqlite3BtreeEnterCursor(X)
# define sqlite3BtreeLeaveCursor(X) # define sqlite3BtreeLeaveCursor(X)
# define sqlite3BtreeLeaveAll(X) # define sqlite3BtreeLeaveAll(X)

View File

@ -24,15 +24,6 @@
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
/*
** This routine is called when a new SQL statement is beginning to
** be parsed. Initialize the pParse structure as needed.
*/
void sqlite3BeginParse(Parse *pParse, int explainFlag){
pParse->explain = (u8)explainFlag;
pParse->nVar = 0;
}
#ifndef SQLITE_OMIT_SHARED_CACHE #ifndef SQLITE_OMIT_SHARED_CACHE
/* /*
** The TableLock structure is only used by the sqlite3TableLock() and ** The TableLock structure is only used by the sqlite3TableLock() and

View File

@ -461,8 +461,9 @@ Expr *sqlite3ExprAlloc(
assert( iValue>=0 ); assert( iValue>=0 );
} }
} }
pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra); pNew = sqlite3DbMallocRaw(db, sizeof(Expr)+nExtra);
if( pNew ){ if( pNew ){
memset(pNew, 0, sizeof(Expr));
pNew->op = (u8)op; pNew->op = (u8)op;
pNew->iAgg = -1; pNew->iAgg = -1;
if( pToken ){ if( pToken ){

View File

@ -567,10 +567,10 @@ static void total_changes(
** A structure defining how to do GLOB-style comparisons. ** A structure defining how to do GLOB-style comparisons.
*/ */
struct compareInfo { struct compareInfo {
u8 matchAll; u8 matchAll; /* "*" or "%" */
u8 matchOne; u8 matchOne; /* "?" or "_" */
u8 matchSet; u8 matchSet; /* "[" or 0 */
u8 noCase; u8 noCase; /* true to ignore case differences */
}; };
/* /*
@ -633,22 +633,14 @@ static int patternCompare(
const u8 *zPattern, /* The glob pattern */ const u8 *zPattern, /* The glob pattern */
const u8 *zString, /* The string to compare against the glob */ const u8 *zString, /* The string to compare against the glob */
const struct compareInfo *pInfo, /* Information about how to do the compare */ const struct compareInfo *pInfo, /* Information about how to do the compare */
u32 esc /* The escape character */ u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */
){ ){
u32 c, c2; /* Next pattern and input string chars */ u32 c, c2; /* Next pattern and input string chars */
u32 matchOne = pInfo->matchOne; /* "?" or "_" */ u32 matchOne = pInfo->matchOne; /* "?" or "_" */
u32 matchAll = pInfo->matchAll; /* "*" or "%" */ u32 matchAll = pInfo->matchAll; /* "*" or "%" */
u32 matchOther; /* "[" or the escape character */
u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */ u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
const u8 *zEscaped = 0; /* One past the last escaped input char */ const u8 *zEscaped = 0; /* One past the last escaped input char */
/* The GLOB operator does not have an ESCAPE clause. And LIKE does not
** have the matchSet operator. So we either have to look for one or
** the other, never both. Hence the single variable matchOther is used
** to store the one we have to look for.
*/
matchOther = esc ? esc : pInfo->matchSet;
while( (c = Utf8Read(zPattern))!=0 ){ while( (c = Utf8Read(zPattern))!=0 ){
if( c==matchAll ){ /* Match "*" */ if( c==matchAll ){ /* Match "*" */
/* Skip over multiple "*" characters in the pattern. If there /* Skip over multiple "*" characters in the pattern. If there
@ -662,7 +654,7 @@ static int patternCompare(
if( c==0 ){ if( c==0 ){
return 1; /* "*" at the end of the pattern matches */ return 1; /* "*" at the end of the pattern matches */
}else if( c==matchOther ){ }else if( c==matchOther ){
if( esc ){ if( pInfo->matchSet==0 ){
c = sqlite3Utf8Read(&zPattern); c = sqlite3Utf8Read(&zPattern);
if( c==0 ) return 0; if( c==0 ) return 0;
}else{ }else{
@ -670,7 +662,7 @@ static int patternCompare(
** recursive search in this case, but it is an unusual case. */ ** recursive search in this case, but it is an unusual case. */
assert( matchOther<0x80 ); /* '[' is a single-byte character */ assert( matchOther<0x80 ); /* '[' is a single-byte character */
while( *zString while( *zString
&& patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){ && patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){
SQLITE_SKIP_UTF8(zString); SQLITE_SKIP_UTF8(zString);
} }
return *zString!=0; return *zString!=0;
@ -696,18 +688,18 @@ static int patternCompare(
} }
while( (c2 = *(zString++))!=0 ){ while( (c2 = *(zString++))!=0 ){
if( c2!=c && c2!=cx ) continue; if( c2!=c && c2!=cx ) continue;
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
} }
}else{ }else{
while( (c2 = Utf8Read(zString))!=0 ){ while( (c2 = Utf8Read(zString))!=0 ){
if( c2!=c ) continue; if( c2!=c ) continue;
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
} }
} }
return 0; return 0;
} }
if( c==matchOther ){ if( c==matchOther ){
if( esc ){ if( pInfo->matchSet==0 ){
c = sqlite3Utf8Read(&zPattern); c = sqlite3Utf8Read(&zPattern);
if( c==0 ) return 0; if( c==0 ) return 0;
zEscaped = zPattern; zEscaped = zPattern;
@ -760,7 +752,7 @@ static int patternCompare(
** The sqlite3_strglob() interface. ** The sqlite3_strglob() interface.
*/ */
int sqlite3_strglob(const char *zGlobPattern, const char *zString){ int sqlite3_strglob(const char *zGlobPattern, const char *zString){
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0; return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0;
} }
/* /*
@ -798,9 +790,10 @@ static void likeFunc(
sqlite3_value **argv sqlite3_value **argv
){ ){
const unsigned char *zA, *zB; const unsigned char *zA, *zB;
u32 escape = 0; u32 escape;
int nPat; int nPat;
sqlite3 *db = sqlite3_context_db_handle(context); sqlite3 *db = sqlite3_context_db_handle(context);
struct compareInfo *pInfo = sqlite3_user_data(context);
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
if( sqlite3_value_type(argv[0])==SQLITE_BLOB if( sqlite3_value_type(argv[0])==SQLITE_BLOB
@ -840,13 +833,13 @@ static void likeFunc(
return; return;
} }
escape = sqlite3Utf8Read(&zEsc); escape = sqlite3Utf8Read(&zEsc);
}else{
escape = pInfo->matchSet;
} }
if( zA && zB ){ if( zA && zB ){
struct compareInfo *pInfo = sqlite3_user_data(context);
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
sqlite3_like_count++; sqlite3_like_count++;
#endif #endif
sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)); sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
} }
} }

View File

@ -102,6 +102,7 @@ static SQLITE_WSD struct Mem5Global {
*/ */
sqlite3_mutex *mutex; sqlite3_mutex *mutex;
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/* /*
** Performance statistics ** Performance statistics
*/ */
@ -113,6 +114,7 @@ static SQLITE_WSD struct Mem5Global {
u32 maxOut; /* Maximum instantaneous currentOut */ u32 maxOut; /* Maximum instantaneous currentOut */
u32 maxCount; /* Maximum instantaneous currentCount */ u32 maxCount; /* Maximum instantaneous currentCount */
u32 maxRequest; /* Largest allocation (exclusive of internal frag) */ u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
#endif
/* /*
** Lists of free blocks. aiFreelist[0] is a list of free blocks of ** Lists of free blocks. aiFreelist[0] is a list of free blocks of
@ -224,14 +226,17 @@ static void *memsys5MallocUnsafe(int nByte){
/* nByte must be a positive */ /* nByte must be a positive */
assert( nByte>0 ); assert( nByte>0 );
/* No more than 1GiB per allocation */
if( nByte > 0x40000000 ) return 0;
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/* Keep track of the maximum allocation request. Even unfulfilled /* Keep track of the maximum allocation request. Even unfulfilled
** requests are counted */ ** requests are counted */
if( (u32)nByte>mem5.maxRequest ){ if( (u32)nByte>mem5.maxRequest ){
/* Abort if the requested allocation size is larger than the largest
** power of two that we can represent using 32-bit signed integers. */
if( nByte > 0x40000000 ) return 0;
mem5.maxRequest = nByte; mem5.maxRequest = nByte;
} }
#endif
/* Round nByte up to the next valid power of two */ /* Round nByte up to the next valid power of two */
for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){} for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){}
@ -258,6 +263,7 @@ static void *memsys5MallocUnsafe(int nByte){
} }
mem5.aCtrl[i] = iLogsize; mem5.aCtrl[i] = iLogsize;
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/* Update allocator performance statistics. */ /* Update allocator performance statistics. */
mem5.nAlloc++; mem5.nAlloc++;
mem5.totalAlloc += iFullSz; mem5.totalAlloc += iFullSz;
@ -266,6 +272,7 @@ static void *memsys5MallocUnsafe(int nByte){
mem5.currentOut += iFullSz; mem5.currentOut += iFullSz;
if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount; if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut; if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
#endif
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
/* Make sure the allocated memory does not assume that it is set to zero /* Make sure the allocated memory does not assume that it is set to zero
@ -300,12 +307,15 @@ static void memsys5FreeUnsafe(void *pOld){
mem5.aCtrl[iBlock] |= CTRL_FREE; mem5.aCtrl[iBlock] |= CTRL_FREE;
mem5.aCtrl[iBlock+size-1] |= CTRL_FREE; mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
assert( mem5.currentCount>0 ); assert( mem5.currentCount>0 );
assert( mem5.currentOut>=(size*mem5.szAtom) ); assert( mem5.currentOut>=(size*mem5.szAtom) );
mem5.currentCount--; mem5.currentCount--;
mem5.currentOut -= size*mem5.szAtom; mem5.currentOut -= size*mem5.szAtom;
assert( mem5.currentOut>0 || mem5.currentCount==0 ); assert( mem5.currentOut>0 || mem5.currentCount==0 );
assert( mem5.currentCount>0 || mem5.currentOut==0 ); assert( mem5.currentCount>0 || mem5.currentOut==0 );
#endif
mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
while( ALWAYS(iLogsize<LOGMAX) ){ while( ALWAYS(iLogsize<LOGMAX) ){

View File

@ -437,26 +437,36 @@ static struct unix_syscall {
#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
{ "mmap", (sqlite3_syscall_ptr)mmap, 0 }, { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
#else
{ "mmap", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent) #define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
{ "munmap", (sqlite3_syscall_ptr)munmap, 0 }, { "munmap", (sqlite3_syscall_ptr)munmap, 0 },
#else
{ "munmap", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent) #define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent)
#if HAVE_MREMAP #if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
{ "mremap", (sqlite3_syscall_ptr)mremap, 0 }, { "mremap", (sqlite3_syscall_ptr)mremap, 0 },
#else #else
{ "mremap", (sqlite3_syscall_ptr)0, 0 }, { "mremap", (sqlite3_syscall_ptr)0, 0 },
#endif #endif
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent) #define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent)
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
{ "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 }, { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
#else
{ "getpagesize", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent) #define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent)
{ "readlink", (sqlite3_syscall_ptr)readlink, 0 }, { "readlink", (sqlite3_syscall_ptr)readlink, 0 },
#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
#endif
}; /* End of the overrideable system calls */ }; /* End of the overrideable system calls */

View File

@ -114,10 +114,10 @@ cmdlist ::= cmdlist ecmd.
cmdlist ::= ecmd. cmdlist ::= ecmd.
ecmd ::= SEMI. ecmd ::= SEMI.
ecmd ::= explain cmdx SEMI. ecmd ::= explain cmdx SEMI.
explain ::= . { sqlite3BeginParse(pParse, 0); } explain ::= .
%ifndef SQLITE_OMIT_EXPLAIN %ifndef SQLITE_OMIT_EXPLAIN
explain ::= EXPLAIN. { sqlite3BeginParse(pParse, 1); } explain ::= EXPLAIN. { pParse->explain = 1; }
explain ::= EXPLAIN QUERY PLAN. { sqlite3BeginParse(pParse, 2); } explain ::= EXPLAIN QUERY PLAN. { pParse->explain = 2; }
%endif SQLITE_OMIT_EXPLAIN %endif SQLITE_OMIT_EXPLAIN
cmdx ::= cmd. { sqlite3FinishCoding(pParse); } cmdx ::= cmd. { sqlite3FinishCoding(pParse); }

View File

@ -55,6 +55,8 @@ struct PgHdr {
#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ #define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
#define PGHDR_MMAP 0x040 /* This is an mmap page object */ #define PGHDR_MMAP 0x040 /* This is an mmap page object */
#define PGHDR_WAL_APPEND 0x080 /* Appended to wal file */
/* Initialize and shutdown the page cache subsystem */ /* Initialize and shutdown the page cache subsystem */
int sqlite3PcacheInitialize(void); int sqlite3PcacheInitialize(void);
void sqlite3PcacheShutdown(void); void sqlite3PcacheShutdown(void);

View File

@ -111,29 +111,34 @@ Select *sqlite3SelectNew(
Select *pNew; Select *pNew;
Select standin; Select standin;
sqlite3 *db = pParse->db; sqlite3 *db = pParse->db;
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
if( pNew==0 ){ if( pNew==0 ){
assert( db->mallocFailed ); assert( db->mallocFailed );
pNew = &standin; pNew = &standin;
memset(pNew, 0, sizeof(*pNew));
} }
if( pEList==0 ){ if( pEList==0 ){
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0)); pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
} }
pNew->pEList = pEList; pNew->pEList = pEList;
pNew->op = TK_SELECT;
pNew->selFlags = selFlags;
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
pNew->pSrc = pSrc; pNew->pSrc = pSrc;
pNew->pWhere = pWhere; pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy; pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving; pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy; pNew->pOrderBy = pOrderBy;
pNew->selFlags = selFlags; pNew->pPrior = 0;
pNew->op = TK_SELECT; pNew->pNext = 0;
pNew->pLimit = pLimit; pNew->pLimit = pLimit;
pNew->pOffset = pOffset; pNew->pOffset = pOffset;
pNew->pWith = 0;
assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 ); assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
if( db->mallocFailed ) { if( db->mallocFailed ) {
clearSelect(db, pNew, pNew!=&standin); clearSelect(db, pNew, pNew!=&standin);
pNew = 0; pNew = 0;

View File

@ -767,10 +767,6 @@ typedef INT16_TYPE LogEst;
*/ */
#ifdef __APPLE__ #ifdef __APPLE__
# include <TargetConditionals.h> # include <TargetConditionals.h>
# if TARGET_OS_IPHONE
# undef SQLITE_MAX_MMAP_SIZE
# define SQLITE_MAX_MMAP_SIZE 0
# endif
#endif #endif
#ifndef SQLITE_MAX_MMAP_SIZE #ifndef SQLITE_MAX_MMAP_SIZE
# if defined(__linux__) \ # if defined(__linux__) \
@ -3352,7 +3348,6 @@ void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
void sqlite3ResetAllSchemasOfConnection(sqlite3*); void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int); void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*); void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3BeginParse(Parse*,int);
void sqlite3CommitInternalChanges(sqlite3*); void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*); void sqlite3DeleteColumnNames(sqlite3*,Table*);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);

View File

@ -3122,6 +3122,10 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0); Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0);
return TCL_OK; return TCL_OK;
} }
if( strcmp(zArg,"-sourceid")==0 ){
Tcl_AppendResult(interp,sqlite3_sourceid(), (char*)0);
return TCL_OK;
}
if( strcmp(zArg,"-has-codec")==0 ){ if( strcmp(zArg,"-has-codec")==0 ){
#ifdef SQLITE_HAS_CODEC #ifdef SQLITE_HAS_CODEC
Tcl_AppendResult(interp,"1",(char*)0); Tcl_AppendResult(interp,"1",(char*)0);

View File

@ -510,11 +510,15 @@ int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 #if !defined(SQLITE_OMIT_SHARED_CACHE)
void sqlite3VdbeEnter(Vdbe*); void sqlite3VdbeEnter(Vdbe*);
void sqlite3VdbeLeave(Vdbe*);
#else #else
# define sqlite3VdbeEnter(X) # define sqlite3VdbeEnter(X)
#endif
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
void sqlite3VdbeLeave(Vdbe*);
#else
# define sqlite3VdbeLeave(X) # define sqlite3VdbeLeave(X)
#endif #endif

View File

@ -1318,7 +1318,7 @@ void sqlite3VdbeUsesBtree(Vdbe *p, int i){
} }
} }
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 #if !defined(SQLITE_OMIT_SHARED_CACHE)
/* /*
** If SQLite is compiled to support shared-cache mode and to be threadsafe, ** If SQLite is compiled to support shared-cache mode and to be threadsafe,
** this routine obtains the mutex associated with each BtShared structure ** this routine obtains the mutex associated with each BtShared structure

107
src/wal.c
View File

@ -445,6 +445,7 @@ struct Wal {
u8 padToSectorBoundary; /* Pad transactions out to the next sector */ u8 padToSectorBoundary; /* Pad transactions out to the next sector */
WalIndexHdr hdr; /* Wal-index header for current transaction */ WalIndexHdr hdr; /* Wal-index header for current transaction */
u32 minFrame; /* Ignore wal frames before this one */ u32 minFrame; /* Ignore wal frames before this one */
u32 iReCksum; /* On commit, recalculate checksums from here */
const char *zWalName; /* Name of WAL file */ const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
@ -698,14 +699,16 @@ static void walEncodeFrame(
assert( WAL_FRAME_HDRSIZE==24 ); assert( WAL_FRAME_HDRSIZE==24 );
sqlite3Put4byte(&aFrame[0], iPage); sqlite3Put4byte(&aFrame[0], iPage);
sqlite3Put4byte(&aFrame[4], nTruncate); sqlite3Put4byte(&aFrame[4], nTruncate);
memcpy(&aFrame[8], pWal->hdr.aSalt, 8); if( pWal->iReCksum==0 ){
memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
sqlite3Put4byte(&aFrame[16], aCksum[0]); sqlite3Put4byte(&aFrame[16], aCksum[0]);
sqlite3Put4byte(&aFrame[20], aCksum[1]); sqlite3Put4byte(&aFrame[20], aCksum[1]);
}
} }
/* /*
@ -2632,6 +2635,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
/* Cannot start a write transaction without first holding a read /* Cannot start a write transaction without first holding a read
** transaction. */ ** transaction. */
assert( pWal->readLock>=0 ); assert( pWal->readLock>=0 );
assert( pWal->writeLock==0 && pWal->iReCksum==0 );
if( pWal->readOnly ){ if( pWal->readOnly ){
return SQLITE_READONLY; return SQLITE_READONLY;
@ -2667,6 +2671,7 @@ int sqlite3WalEndWriteTransaction(Wal *pWal){
if( pWal->writeLock ){ if( pWal->writeLock ){
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
pWal->writeLock = 0; pWal->writeLock = 0;
pWal->iReCksum = 0;
pWal->truncateOnCommit = 0; pWal->truncateOnCommit = 0;
} }
return SQLITE_OK; return SQLITE_OK;
@ -2885,6 +2890,59 @@ static int walWriteOneFrame(
return rc; return rc;
} }
/*
** This function is called as part of committing a transaction within which
** one or more frames have been overwritten. It updates the checksums for
** all frames written to the wal file by the current transaction starting
** with the earliest to have been overwritten.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
static int walRewriteChecksums(Wal *pWal, u32 iLast){
const int szPage = pWal->szPage;/* Database page size */
int rc = SQLITE_OK; /* Return code */
u8 *aBuf; /* Buffer to load data from wal file into */
u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-headers in */
u32 iRead; /* Next frame to read from wal file */
i64 iCksumOff;
aBuf = sqlite3_malloc(szPage + WAL_FRAME_HDRSIZE);
if( aBuf==0 ) return SQLITE_NOMEM;
/* Find the checksum values to use as input for the recalculating the
** first checksum. If the first frame is frame 1 (implying that the current
** transaction restarted the wal file), these values must be read from the
** wal-file header. Otherwise, read them from the frame header of the
** previous frame. */
assert( pWal->iReCksum>0 );
if( pWal->iReCksum==1 ){
iCksumOff = 24;
}else{
iCksumOff = walFrameOffset(pWal->iReCksum-1, szPage) + 16;
}
rc = sqlite3OsRead(pWal->pWalFd, aBuf, sizeof(u32)*2, iCksumOff);
pWal->hdr.aFrameCksum[0] = sqlite3Get4byte(aBuf);
pWal->hdr.aFrameCksum[1] = sqlite3Get4byte(&aBuf[sizeof(u32)]);
iRead = pWal->iReCksum;
pWal->iReCksum = 0;
for(; rc==SQLITE_OK && iRead<=iLast; iRead++){
i64 iOff = walFrameOffset(iRead, szPage);
rc = sqlite3OsRead(pWal->pWalFd, aBuf, szPage+WAL_FRAME_HDRSIZE, iOff);
if( rc==SQLITE_OK ){
u32 iPgno, nDbSize;
iPgno = sqlite3Get4byte(aBuf);
nDbSize = sqlite3Get4byte(&aBuf[4]);
walEncodeFrame(pWal, iPgno, nDbSize, &aBuf[WAL_FRAME_HDRSIZE], aFrame);
rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOff);
}
}
sqlite3_free(aBuf);
return rc;
}
/* /*
** Write a set of frames to the log. The caller must hold the write-lock ** Write a set of frames to the log. The caller must hold the write-lock
** on the log file (obtained using sqlite3WalBeginWriteTransaction()). ** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
@ -2905,6 +2963,8 @@ int sqlite3WalFrames(
int szFrame; /* The size of a single frame */ int szFrame; /* The size of a single frame */
i64 iOffset; /* Next byte to write in WAL file */ i64 iOffset; /* Next byte to write in WAL file */
WalWriter w; /* The writer */ WalWriter w; /* The writer */
u32 iFirst = 0; /* First frame that may be overwritten */
WalIndexHdr *pLive; /* Pointer to shared header */
assert( pList ); assert( pList );
assert( pWal->writeLock ); assert( pWal->writeLock );
@ -2920,6 +2980,11 @@ int sqlite3WalFrames(
} }
#endif #endif
pLive = (WalIndexHdr*)walIndexHdr(pWal);
if( memcmp(&pWal->hdr, (void *)pLive, sizeof(WalIndexHdr))!=0 ){
iFirst = pLive->mxFrame+1;
}
/* See if it is possible to write these frames into the start of the /* See if it is possible to write these frames into the start of the
** log file, instead of appending to it at pWal->hdr.mxFrame. ** log file, instead of appending to it at pWal->hdr.mxFrame.
*/ */
@ -2984,6 +3049,27 @@ int sqlite3WalFrames(
/* Write all frames into the log file exactly once */ /* Write all frames into the log file exactly once */
for(p=pList; p; p=p->pDirty){ for(p=pList; p; p=p->pDirty){
int nDbSize; /* 0 normally. Positive == commit flag */ int nDbSize; /* 0 normally. Positive == commit flag */
/* Check if this page has already been written into the wal file by
** the current transaction. If so, overwrite the existing frame and
** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that
** checksums must be recomputed when the transaction is committed. */
if( iFirst && (p->pDirty || isCommit==0) ){
u32 iWrite = 0;
VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite);
assert( rc==SQLITE_OK || iWrite==0 );
if( iWrite>=iFirst ){
i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){
pWal->iReCksum = iWrite;
}
rc = sqlite3OsWrite(pWal->pWalFd, p->pData, szPage, iOff);
if( rc ) return rc;
p->flags &= ~PGHDR_WAL_APPEND;
continue;
}
}
iFrame++; iFrame++;
assert( iOffset==walFrameOffset(iFrame, szPage) ); assert( iOffset==walFrameOffset(iFrame, szPage) );
nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0; nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0;
@ -2991,6 +3077,13 @@ int sqlite3WalFrames(
if( rc ) return rc; if( rc ) return rc;
pLast = p; pLast = p;
iOffset += szFrame; iOffset += szFrame;
p->flags |= PGHDR_WAL_APPEND;
}
/* Recalculate checksums within the wal file if required. */
if( isCommit && pWal->iReCksum ){
rc = walRewriteChecksums(pWal, iFrame);
if( rc ) return rc;
} }
/* If this is the end of a transaction, then we might need to pad /* If this is the end of a transaction, then we might need to pad
@ -3042,6 +3135,7 @@ int sqlite3WalFrames(
*/ */
iFrame = pWal->hdr.mxFrame; iFrame = pWal->hdr.mxFrame;
for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){ for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
if( (p->flags & PGHDR_WAL_APPEND)==0 ) continue;
iFrame++; iFrame++;
rc = walIndexAppend(pWal, iFrame, p->pgno); rc = walIndexAppend(pWal, iFrame, p->pgno);
} }
@ -3154,6 +3248,7 @@ int sqlite3WalCheckpoint(
/* Copy data from the log to the database file. */ /* Copy data from the log to the database file. */
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
rc = SQLITE_CORRUPT_BKPT; rc = SQLITE_CORRUPT_BKPT;
}else{ }else{

View File

@ -865,8 +865,13 @@ int main(int argc, char **argv){
return 0; return 0;
}else }else
if( strcmp(z,"limit-mem")==0 ){ if( strcmp(z,"limit-mem")==0 ){
#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
fatalError("the %s option requires -DSQLITE_ENABLE_MEMSYS5 or _MEMSYS3",
argv[i]);
#else
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
nMem = integerValue(argv[++i]); nMem = integerValue(argv[++i]);
#endif
}else }else
if( strcmp(z,"limit-vdbe")==0 ){ if( strcmp(z,"limit-vdbe")==0 ){
vdbeLimitFlag = 1; vdbeLimitFlag = 1;

View File

@ -1034,7 +1034,13 @@ proc finalize_testing {} {
output2 "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\ output2 "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\
out of $nTest tests" out of $nTest tests"
} else { } else {
output2 "$nErr errors out of $nTest tests" set cpuinfo {}
if {[catch {exec hostname} hname]==0} {set cpuinfo [string trim $hname]}
append cpuinfo " $::tcl_platform(os)"
append cpuinfo " [expr {$::tcl_platform(pointerSize)*8}]-bit"
append cpuinfo " [string map {E -e} $::tcl_platform(byteOrder)]"
output2 "SQLite [sqlite3 -sourceid]"
output2 "$nErr errors out of $nTest tests on $cpuinfo"
} }
if {$nErr>$nKnown} { if {$nErr>$nKnown} {
output2 -nonewline "!Failures on these tests:" output2 -nonewline "!Failures on these tests:"

View File

@ -68,19 +68,19 @@ set x7 backbone
set x8 backarrow set x8 backarrow
set x9 castle set x9 castle
db func glob gfunc db func glob -argcount 2 gfunc
proc gfunc {a b} { proc gfunc {a b} {
incr ::gfunc incr ::gfunc
return 1 return 1
} }
db func like lfunc db func like -argcount 2 lfunc
proc lfunc {a b} { proc lfunc {a b} {
incr ::gfunc 100 incr ::gfunc 100
return 1 return 1
} }
db func regexp rfunc db func regexp -argcount 2 rfunc
proc rfunc {a b} { proc rfunc {a b} {
incr ::gfunc 10000 incr ::gfunc 10000
return 1 return 1

View File

@ -712,7 +712,7 @@ do_test wal-11.5 {
do_test wal-11.6 { do_test wal-11.6 {
execsql COMMIT execsql COMMIT
list [expr [file size test.db]/1024] [file size test.db-wal] list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 3 [wal_file_size 41 1024]] } [list 3 [wal_file_size 40 1024]]
do_test wal-11.7 { do_test wal-11.7 {
execsql { execsql {
SELECT count(*) FROM t1; SELECT count(*) FROM t1;
@ -722,15 +722,22 @@ do_test wal-11.7 {
do_test wal-11.8 { do_test wal-11.8 {
execsql { PRAGMA wal_checkpoint } execsql { PRAGMA wal_checkpoint }
list [expr [file size test.db]/1024] [file size test.db-wal] list [expr [file size test.db]/1024] [file size test.db-wal]
} [list 37 [wal_file_size 41 1024]] } [list 37 [wal_file_size 40 1024]]
do_test wal-11.9 { do_test wal-11.9 {
db close db close
list [expr [file size test.db]/1024] [log_deleted test.db-wal] list [expr [file size test.db]/1024] [log_deleted test.db-wal]
} {37 1} } {37 1}
sqlite3_wal db test.db sqlite3_wal db test.db
set nWal 39
if {[permutation]!="mmap"} {set nWal 37} # After adding the capability of WAL to overwrite prior uncommitted
ifcapable !mmap {set nWal 37} # frame in the WAL-file with revised content, the size of the WAL file
# following cache-spill is smaller.
#
#set nWal 39
#if {[permutation]!="mmap"} {set nWal 37}
#ifcapable !mmap {set nWal 37}
set nWal 34
do_test wal-11.10 { do_test wal-11.10 {
execsql { execsql {
PRAGMA cache_size = 10; PRAGMA cache_size = 10;

164
test/waloverwrite.test Normal file
View File

@ -0,0 +1,164 @@
# 2010 May 5
#
# 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 operation of the library in
# "PRAGMA journal_mode=WAL" mode.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/wal_common.tcl
set testprefix waloverwrite
ifcapable !wal {finish_test ; return }
# Simple test:
#
# Test cases *.1 - *.6:
#
# + Create a database of blobs roughly 50 pages in size.
#
# + Set the db cache size to something much smaller than this (5 pages)
#
# + Within a transaction, loop through the set of blobs 5 times. Update
# each blob as it is visited.
#
# + Test that the wal file is roughly 50 pages in size - even though many
# database pages have been written to it multiple times.
#
# + Take a copy of the database and wal file. Test that recovery can
# be run on it.
#
# Test cases *.7 - *.9:
#
# + Same thing, but before committing the statement transaction open
# a SAVEPOINT, update the blobs another 5 times, then roll it back.
#
# + Check that if recovery is run on the resulting wal file, the rolled
# back changes from within the SAVEPOINT are not present in the db.
#
# The above is run twice - once where the wal file is empty at the start of
# step 3 (tn==1) and once where it already contains a transaction (tn==2).
#
foreach {tn xtra} {
1 {}
2 { UPDATE t1 SET y = randomblob(799) WHERE x=4 }
} {
reset_db
do_execsql_test 1.$tn.0 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(x, y);
CREATE INDEX i1y ON t1(y);
WITH cnt(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<20
)
INSERT INTO t1 SELECT i, randomblob(800) FROM cnt;
} {}
do_test 1.$tn.1 {
set nPg [db one { PRAGMA page_count } ]
expr $nPg>40 && $nPg<50
} {1}
do_test 1.$tn.2 {
db close
sqlite3 db test.db
execsql {PRAGMA journal_mode = wal}
execsql {PRAGMA cache_size = 5}
execsql $xtra
db transaction {
for {set i 0} {$i < 5} {incr i} {
foreach x [db eval {SELECT x FROM t1}] {
execsql { UPDATE t1 SET y = randomblob(799) WHERE x=$x }
}
}
}
set nPg [wal_frame_count test.db-wal 1024]
expr $nPg>40 && $nPg<60
} {1}
do_execsql_test 1.$tn.3 { PRAGMA integrity_check } ok
do_test 1.$tn.4 {
forcedelete test.db2 test.db2-wal
forcecopy test.db test.db2
sqlite3 db2 test.db2
execsql { SELECT sum(length(y)) FROM t1 } db2
} [expr 20*800]
do_test 1.$tn.5 {
db2 close
forcecopy test.db test.db2
forcecopy test.db-wal test.db2-wal
sqlite3 db2 test.db2
execsql { SELECT sum(length(y)) FROM t1 } db2
} [expr 20*799]
do_test 1.$tn.6 {
execsql { PRAGMA integrity_check } db2
} ok
db2 close
do_test 1.$tn.7 {
execsql { PRAGMA wal_checkpoint }
db transaction {
for {set i 0} {$i < 1} {incr i} {
foreach x [db eval {SELECT x FROM t1}] {
execsql { UPDATE t1 SET y = randomblob(798) WHERE x=$x }
}
}
execsql {
WITH cnt(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<20)
INSERT INTO t2 SELECT i, randomblob(800) FROM cnt;
}
execsql {SAVEPOINT abc}
for {set i 0} {$i < 5} {incr i} {
foreach x [db eval {SELECT x FROM t1}] {
execsql { UPDATE t1 SET y = randomblob(797) WHERE x=$x }
}
}
breakpoint
execsql {ROLLBACK TO abc}
}
set nPg [wal_frame_count test.db-wal 1024]
expr $nPg>55 && $nPg<75
} {1}
do_test 1.$tn.8 {
forcedelete test.db2 test.db2-wal
forcecopy test.db test.db2
sqlite3 db2 test.db2
execsql { SELECT sum(length(y)) FROM t1 } db2
} [expr 20*799]
do_test 1.$tn.9 {
db2 close
forcecopy test.db-wal test.db2-wal
sqlite3 db2 test.db2
execsql { SELECT sum(length(y)) FROM t1 } db2
} [expr 20*798]
do_test 1.$tn.9 {
execsql { PRAGMA integrity_check } db2
} ok
db2 close
}
finish_test