Update sessions branch with latest changes from trunk.

FossilOrigin-Name: 01c84fd391a0ca1f5245c7eff0644d0cc6cff86b
This commit is contained in:
dan 2012-01-14 13:50:12 +00:00
commit af49af7f9e
38 changed files with 544 additions and 269 deletions

View File

@ -31,7 +31,7 @@ TCC = @CC@ @CPPFLAGS@ @CFLAGS@ -I. -I${TOP}/src -I${TOP}/ext/rtree
# Define this for the autoconf-based build, so that the code knows it can
# include the generated config.h
#
TCC += -D_HAVE_SQLITE_CONFIG_H
TCC += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and

View File

@ -40,7 +40,7 @@ typedef struct porter_tokenizer {
} porter_tokenizer;
/*
** Class derived from sqlit3_tokenizer_cursor
** Class derived from sqlite3_tokenizer_cursor
*/
typedef struct porter_tokenizer_cursor {
sqlite3_tokenizer_cursor base;

View File

@ -1,7 +1,7 @@
C Merge\sall\sof\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch.
D 2012-01-05T13:02:36.422
C Update\ssessions\sbranch\swith\slatest\schanges\sfrom\strunk.
D 2012-01-14T13:50:12.463
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc dcad80fa69f17d46fe6778ba873fc108ca16298d
F Makefile.vxworks 1deb39c8bb047296c30161ffa10c1b5423e632f9
@ -71,7 +71,7 @@ F ext/fts3/fts3_expr.c f5df26bddf46a5916b2a5f80c4027996e92b7b15
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
F ext/fts3/fts3_icu.c 6c8f395cdf9e1e3afa7fadb7e523dbbf381c6dfa
F ext/fts3/fts3_porter.c 8d946908f4812c005d3d33fcbe78418b1f4eb70c
F ext/fts3/fts3_porter.c b7e5276f9f0a5fc7018b6fa55ce0f31f269ef881
F ext/fts3/fts3_snippet.c 1f9ee6a8e0e242649645968dcec4deb253d86c2a
F ext/fts3/fts3_term.c a5457992723455a58804cb75c8cbd8978db5c2ef
F ext/fts3/fts3_test.c 24fa13f330db011500acb95590da9eee24951894
@ -134,12 +134,12 @@ F src/alter.c ac80a0f31189f8b4a524ebf661e47e84536ee7f5
F src/analyze.c f32ff304da413851eefa562b04e61ff6cb88248b
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 80d713109d295cc3a674f55cfe6446afb9b024ad
F src/backup.c e9538bad2d4a4fcd4308f1aed7cb18a0fbc968f9
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 8f683b1fcfd9ac92efa781c9c56c537e080a7117
F src/btree.c a65816cc000bdd421772986e64c88c9035331332
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
F src/btreeInt.h 6e57bacaa4feb7dd56719678133e63a7c289c6e7
F src/btreeInt.h 6c9960645c431c9456ca56498f43a2b3bf1fa8c2
F src/build.c 8e2a4dedad860fed982270ef43968505f35ec57f
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
@ -174,19 +174,19 @@ F src/mutex_os2.c 882d735098c07c8c6a5472b8dd66e19675fe117f
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c 519bdf7c608c4848024e1d87934f9305454145f4
F src/os.h c7d888830f168a9b681b3aec30789f4ad2445c17
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c
F src/os.h a2219c3b05ce31230bb000fdc4f1a542b33ee649
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
F src/os_unix.c f19ca2ef603e4f6510f3daf206e244476a68413d
F src/os_win.c 88b35c8fe7b32c7398ceace727ea01120cb21989
F src/pager.c 5b89ab92631a8fc488b87cc663ab064802173fec
F src/os_unix.c 657672fab2580a84116c140b36ee3d6b6fc75b4e
F src/os_win.c 5ac061ae1326a71500cee578ed0fd9113b4f6a37
F src/pager.c 4d58c983d9f4d34bc2d48e4280361ccaeecd03c5
F src/pager.h 5cd760857707529b403837d813d86b68938d6183
F src/parse.y fabb2e7047417d840e6fdb3ef0988a86849a08ba
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h b1d8775a9bddf44e65edb0d20bfc57a4982f840f
F src/pcache1.c e1aaa3bc9bbfd8b0bc391ca731f5f8185467375d
F src/pragma.c dd66f21fafe7be40e1a48ad4195764cc191cf583
F src/pcache1.c 281822d22265245b19f908cb3f5df725f7e11b06
F src/pragma.c fb979b7b5103ad0db1b72bcf349c83f5dec62574
F src/prepare.c ec4989f7f480544bdc4192fe663470d2a2d7d61e
F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
@ -194,16 +194,16 @@ F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c a1d075db66a0ea42807353501b62997969e5be79
F src/shell.c aa4183d4a5243d8110b1d3d77faa4aea7e9c9c2d
F src/sqlite.h.in e819002c73cc667717aa0eab4f0584e201c4e102
F src/sqlite.h.in 132b3140f29469dc1222a43fd9451c1785c80a51
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
F src/sqliteInt.h 701b38210f369a802853894309af5185b44061b4
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 008daf83b287c600c2495845ac46a9d364c1961a
F src/tclsqlite.c 47d088f383a106b2914ac970586fdab66c1bd169
F src/test1.c 1b1e514e85ffe7152b02cba38bd0a1ce8cd56113
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
F src/test2.c 711555927f1f7e8db9aab86b512bc6934a774abe
F src/test3.c 91d3f1a09cfae3533ef17d8b484a160f3d1f1a21
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
F src/test5.c e1a19845625144caf038031234a12185e40d315c
F src/test6.c cf6ab27a59e1ab64b011bb251ba600131e803e59
@ -223,16 +223,16 @@ F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a
F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
F src/test_journal.c 2c06e4be6584d51b935dc8b353980a9388de62ef
F src/test_journal.c a6a6baf343f79b942331f13378d045e7e270ae64
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
F src/test_malloc.c 8d416f29ad8573f32601f6056c9d2b17472e9ad5
F src/test_multiplex.c 2bf2eb36c9eff73c808ba6d19388e2f577438d9e
F src/test_multiplex.c afab2c9d292677ab31e0dd4b3dde2420fb655c5f
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
F src/test_osinst.c 6abf0a37ce831120c4ef1b913afdd813e7ac1a73
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 1a5874e3ee9074426f43b37e8d7404948065b585
F src/test_quota.c b4a6519417d87870e7ef5838dbf3cae164dcc28d
F src/test_quota.h 9ffa1d3ad6d0a6a24e8670ea64b909c717ec3358
F src/test_rtree.c 6d06306e29946dc36f528a3a2cdc3add794656f1
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
@ -250,19 +250,19 @@ F src/tokenize.c 1e86210d3976717a19238ea7b047fac481fe8c12
F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684
F src/update.c 89de085a0bf4da448472029d0420a2b1cf1824ee
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
F src/util.c ad06374bc92b98071f221f00d553daea514f2b60
F src/util.c 9e07bd67dfafe9c75b1da78c87ba030cebbb5388
F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa
F src/vdbe.c 3338717cb2ff8ead889109813149d2182484b835
F src/vdbe.c 502f3deb63c24fbb3fe6b88a10c984ec897f5b7b
F src/vdbe.h 87b8ff40de3f55dbcdc33029416862f517c37a2f
F src/vdbeInt.h 57ca039ec5291566b667932a31ee03e51872caaa
F src/vdbeInt.h 1aa78a0c2d6e4fdc4b9b8ff29192e98182d25afa
F src/vdbeapi.c 2fc381f651738feb2495cb001cf2114dea596cc3
F src/vdbeaux.c ca1eada4b21723a67c510c0f456217c03ad15e48
F src/vdbeblob.c 11248c6362389569764682eb0f59ce910f3cc381
F src/vdbemem.c dadc7465860ad2e980f01c9b0b1ba44903249257
F src/vdbemem.c 4f7d25d5ea2e2040254095b8f6de07f8dbbadf80
F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
F src/vdbetrace.c d6e50e04e1ec498150e519058f617d91b8f5c843
F src/vtab.c e9318d88feac85be8e27ee783ac8f5397933fc8a
F src/wal.c 932f09509d70fc115a7cc3d494d6fdcb825099ed
F src/wal.c 5f7bcc0610af759953defd769eacebfd98a22bc8
F src/wal.h eaa00b9a403ddda2b56d01b7afc19ef600f9363f
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c af623942514571895818b9b7ae11db95ae3b3d88
@ -302,7 +302,7 @@ F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 71eeb75ea567c060774c4e8db4b0e703f21c7677
F test/backup.test 6970614b002b056ae5bab5b76559905e02b6f0b2
F test/backup2.test b4966934b2dc10a9a6546114566ea69b34a5185e
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
F test/backup_ioerr.test 40d208bc9224b666ee3ed423f49bc9062a36a9d0
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
@ -361,6 +361,7 @@ F test/corruptB.test 20d4a20cbed23958888c3e8995b424a47223d647
F test/corruptC.test 62a767fe64acb1975f58cc6171192839c783edbb
F test/corruptD.test 99b1999dbfa7cc04aaeac9d695a2445d4e7c7458
F test/corruptE.test 1b9eb20a8711251ce57b44a257e241085b39b52d
F test/corruptF.test 984b1706c9c0e4248141b056c21124612628d12e
F test/count.test 454e1ce985c94d13efeac405ce54439f49336163
F test/crash.test 519dc29f6fea151f015a23236e555239353946eb
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
@ -584,7 +585,7 @@ F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test bc745155ff4252d4f35ec8316625b0dfe2abc659
F test/malloc3.test de8eca0c3e748878845fdca3663ec4b642073caf
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
F test/malloc5.test 30dc30b57fa22552eba0d8c95210d96c3d958a39
F test/malloc5.test a577cbbcc1594c7763b9b3515b3633555751c7f0
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
@ -619,7 +620,7 @@ F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test eafaa41b9133d7a2ded4641bbe5f340731d35a52
F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054
F test/multiplex.test 8bc3c71f73fe833bc8a659d454d320044a33b5da
F test/multiplex.test e08cc7177bd6d85990ee1d71100bb6c684c02256
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
F test/multiplex3.test 15903c343f1eaa4b00998b7ceacfc4987e4ccfe9
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
@ -642,7 +643,7 @@ F test/pageropt.test 9191867ed19a2b3db6c42d1b36b6fbc657cd1ab0
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/permutations.test 4ec9fbb2f1389f96be8a7108a86f7f2674ae5d4b
F test/permutations.test ab9fbb673617734869af2fc4cbdb04baa3339d1c
F test/pragma.test 7fa35e53085812dac94c2bfcbb02c2a4ad35df5e
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@ -697,7 +698,7 @@ F test/shared7.test 960760bc8d03e1419e70dea69cf41db62853616e
F test/shared_err.test 91e26ec4f3fbe07951967955585137e2f18993de
F test/sharedlock.test ffa0a3c4ac192145b310f1254f8afca4d553eabf
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/shrink.test 28165922bfea5c003c51a2d02bce69c4141ef013
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test c16709a16ad79fa43b32929b2e623d1d117ccf53
@ -723,7 +724,7 @@ F test/syscall.test 265cda616f56a297406728ee1e74c9b4a93aa6dd
F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f
F test/table.test a59d985ca366e39b17b175f387f9d5db5a18d4e2
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tclsqlite.test d5298750115768bca173da8043ffac2924be21a0
F test/tclsqlite.test 2f2aa887763af30641f5561bdc26c5d3fbc73a88
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test 51edd31c65ed1560dd600b1796e8325df96318e2
F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d
@ -885,7 +886,7 @@ F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
F test/unixexcl.test c82934b3fda907573c7dfccc4f4c9506e5537f36
F test/unixexcl.test a9870e46cc6f8390a494513d4f2bf55b5a8b3e46
F test/unordered.test f53095cee37851bf30130fa1bf299a8845e837bb
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
F test/uri.test 0d289d32396bdbc491e9dc845f1a52e13f861e0b
@ -926,10 +927,10 @@ F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877
F test/walbig.test 0ab8a430ef420a3114f7092e0f30fc9585ffa155
F test/walcksum.test f5447800a157c9e2234fbb8e80243f0813941bde
F test/walcrash.test 4fcb661faf71db91214156d52d43ee327f52bde1
F test/walcrash.test 4457436593be8c136f9148487c7dccd5e9013af2
F test/walcrash2.test 019d60b89d96c1937adb2b30b850ac7e86e5a142
F test/walcrash3.test 595e44c6197f0d0aa509fc135be2fd0209d11a2c
F test/walfault.test efb0d5724893133e71b8d9d90abdb781845a6bb0
F test/walfault.test 97394d8de82a99f7abf1c12ed229640607fd0ad2
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
@ -954,7 +955,7 @@ F test/whereC.test 13ff5ec0dba407c0e0c075980c75b3275a6774e5
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/win32lock.test b2a539e85ae6b2d78475e016a9636b4451dc7fb9
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test 7ef0680559163118705975be132933898d349674
F test/zerodamage.test 0de750389990b1078bab203c712dc3fefd1d8b82
F tool/build-shell.sh 12aa4391073a777fcb6dcc490b219a018ae98bac
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
@ -962,7 +963,7 @@ F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 949328f67cac94969d3112b105b8457edf27f44e
F tool/lemon.c 445f18999b700d83b83a5d9be00c596546c21052
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
@ -999,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
P 23580718e1c15ddb89682d0e7566da4d7276bfe9 1378f905d37544701776d38987fe7a312b255983
R 5ebf66e93e6aec7fb5582a0e00987618
U drh
Z e88b35dabf798061ce032430eb1150b1
P a9bcb432f58b96f079a73c456efd4851c582221e 88ad2f23c5036cbb4a69b73ce5792bd5c33a9177
R 30723a7c24a6752d8bfb2c322e9b8748
U dan
Z 241182607d7d4efdfae3b5115d25b877

View File

@ -1 +1 @@
a9bcb432f58b96f079a73c456efd4851c582221e
01c84fd391a0ca1f5245c7eff0644d0cc6cff86b

View File

@ -678,9 +678,9 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
if( pFd->pMethods ){
i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
sqlite3BeginBenignMalloc();
sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte);
sqlite3EndBenignMalloc();
rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte);
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
if( rc ) goto copy_finished;
}
/* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set
@ -705,12 +705,13 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
assert( b.rc!=SQLITE_OK );
rc = sqlite3_backup_finish(&b);
if( rc==SQLITE_OK ){
pTo->pBt->pageSizeFixed = 0;
pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
}else{
sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
}
assert( sqlite3BtreeIsInTrans(pTo)==0 );
copy_finished:
sqlite3BtreeLeave(pFrom);
sqlite3BtreeLeave(pTo);
return rc;

View File

@ -243,7 +243,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
/* If some other connection is holding an exclusive lock, the
** requested lock may not be obtained.
*/
if( pBt->pWriter!=p && pBt->isExclusive ){
if( pBt->pWriter!=p && (pBt->btsFlags & BTS_EXCLUSIVE)!=0 ){
sqlite3ConnectionBlocked(p->db, pBt->pWriter->db);
return SQLITE_LOCKED_SHAREDCACHE;
}
@ -264,7 +264,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
sqlite3ConnectionBlocked(p->db, pIter->pBtree->db);
if( eLock==WRITE_LOCK ){
assert( p==pBt->pWriter );
pBt->isPending = 1;
pBt->btsFlags |= BTS_PENDING;
}
return SQLITE_LOCKED_SHAREDCACHE;
}
@ -352,7 +352,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
** the setSharedCacheTableLock() procedure) held by Btree object p.
**
** This function assumes that Btree p has an open read or write
** transaction. If it does not, then the BtShared.isPending variable
** transaction. If it does not, then the BTS_PENDING flag
** may be incorrectly cleared.
*/
static void clearAllSharedCacheTableLocks(Btree *p){
@ -365,7 +365,7 @@ static void clearAllSharedCacheTableLocks(Btree *p){
while( *ppIter ){
BtLock *pLock = *ppIter;
assert( pBt->isExclusive==0 || pBt->pWriter==pLock->pBtree );
assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree );
assert( pLock->pBtree->inTrans>=pLock->eLock );
if( pLock->pBtree==p ){
*ppIter = pLock->pNext;
@ -378,22 +378,21 @@ static void clearAllSharedCacheTableLocks(Btree *p){
}
}
assert( pBt->isPending==0 || pBt->pWriter );
assert( (pBt->btsFlags & BTS_PENDING)==0 || pBt->pWriter );
if( pBt->pWriter==p ){
pBt->pWriter = 0;
pBt->isExclusive = 0;
pBt->isPending = 0;
pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
}else if( pBt->nTransaction==2 ){
/* This function is called when Btree p is concluding its
** transaction. If there currently exists a writer, and p is not
** that writer, then the number of locks held by connections other
** than the writer must be about to drop to zero. In this case
** set the isPending flag to 0.
** set the BTS_PENDING flag to 0.
**
** If there is not currently a writer, then BtShared.isPending must
** If there is not currently a writer, then BTS_PENDING must
** be zero already. So this next line is harmless in that case.
*/
pBt->isPending = 0;
pBt->btsFlags &= ~BTS_PENDING;
}
}
@ -405,8 +404,7 @@ static void downgradeAllSharedCacheTableLocks(Btree *p){
if( pBt->pWriter==p ){
BtLock *pLock;
pBt->pWriter = 0;
pBt->isExclusive = 0;
pBt->isPending = 0;
pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){
assert( pLock->eLock==READ_LOCK || pLock->pBtree==p );
pLock->eLock = READ_LOCK;
@ -1264,7 +1262,7 @@ static int freeSpace(MemPage *pPage, int start, int size){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( size>=0 ); /* Minimum cell size is 4 */
if( pPage->pBt->secureDelete ){
if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){
/* Overwrite deleted information with zeros when the secure_delete
** option is enabled */
memset(&data[start], 0, size);
@ -1367,6 +1365,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
}else{
return SQLITE_CORRUPT_BKPT;
}
pPage->max1bytePayload = pBt->max1bytePayload;
return SQLITE_OK;
}
@ -1502,7 +1501,7 @@ static void zeroPage(MemPage *pPage, int flags){
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pBt->mutex) );
if( pBt->secureDelete ){
if( pBt->btsFlags & BTS_SECURE_DELETE ){
memset(&data[hdr], 0, pBt->usableSize - hdr);
}
data[hdr] = (char)flags;
@ -1855,9 +1854,9 @@ int sqlite3BtreeOpen(
pBt->pCursor = 0;
pBt->pPage1 = 0;
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY;
#ifdef SQLITE_SECURE_DELETE
pBt->secureDelete = 1;
pBt->btsFlags |= BTS_SECURE_DELETE;
#endif
pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16);
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
@ -1878,7 +1877,7 @@ int sqlite3BtreeOpen(
nReserve = 0;
}else{
nReserve = zDbHeader[20];
pBt->pageSizeFixed = 1;
pBt->btsFlags |= BTS_PAGESIZE_FIXED;
#ifndef SQLITE_OMIT_AUTOVACUUM
pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0);
@ -2166,7 +2165,7 @@ int sqlite3BtreeSyncDisabled(Btree *p){
** If parameter nReserve is less than zero, then the number of reserved
** bytes per page is left unchanged.
**
** If the iFix!=0 then the pageSizeFixed flag is set so that the page size
** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size
** and autovacuum mode can no longer be changed.
*/
int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
@ -2174,7 +2173,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
BtShared *pBt = p->pBt;
assert( nReserve>=-1 && nReserve<=255 );
sqlite3BtreeEnter(p);
if( pBt->pageSizeFixed ){
if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
sqlite3BtreeLeave(p);
return SQLITE_READONLY;
}
@ -2191,7 +2190,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
}
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
pBt->usableSize = pBt->pageSize - (u16)nReserve;
if( iFix ) pBt->pageSizeFixed = 1;
if( iFix ) pBt->btsFlags |= BTS_PAGESIZE_FIXED;
sqlite3BtreeLeave(p);
return rc;
}
@ -2231,8 +2230,8 @@ int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
}
/*
** Set the secureDelete flag if newFlag is 0 or 1. If newFlag is -1,
** then make no changes. Always return the value of the secureDelete
** Set the BTS_SECURE_DELETE flag if newFlag is 0 or 1. If newFlag is -1,
** then make no changes. Always return the value of the BTS_SECURE_DELETE
** setting after the change.
*/
int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
@ -2240,9 +2239,10 @@ int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
if( p==0 ) return 0;
sqlite3BtreeEnter(p);
if( newFlag>=0 ){
p->pBt->secureDelete = (newFlag!=0) ? 1 : 0;
p->pBt->btsFlags &= ~BTS_SECURE_DELETE;
if( newFlag ) p->pBt->btsFlags |= BTS_SECURE_DELETE;
}
b = p->pBt->secureDelete;
b = (p->pBt->btsFlags & BTS_SECURE_DELETE)!=0;
sqlite3BtreeLeave(p);
return b;
}
@ -2263,7 +2263,7 @@ int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
u8 av = (u8)autoVacuum;
sqlite3BtreeEnter(p);
if( pBt->pageSizeFixed && (av ?1:0)!=pBt->autoVacuum ){
if( (pBt->btsFlags & BTS_PAGESIZE_FIXED)!=0 && (av ?1:0)!=pBt->autoVacuum ){
rc = SQLITE_READONLY;
}else{
pBt->autoVacuum = av ?1:0;
@ -2337,14 +2337,14 @@ static int lockBtree(BtShared *pBt){
#ifdef SQLITE_OMIT_WAL
if( page1[18]>1 ){
pBt->readOnly = 1;
pBt->btsFlags |= BTS_READ_ONLY;
}
if( page1[19]>1 ){
goto page1_init_failed;
}
#else
if( page1[18]>2 ){
pBt->readOnly = 1;
pBt->btsFlags |= BTS_READ_ONLY;
}
if( page1[19]>2 ){
goto page1_init_failed;
@ -2358,7 +2358,7 @@ static int lockBtree(BtShared *pBt){
** may not be the latest version - there may be a newer one in the log
** file.
*/
if( page1[19]==2 && pBt->doNotUseWAL==0 ){
if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
int isOpen = 0;
rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
if( rc!=SQLITE_OK ){
@ -2435,6 +2435,11 @@ static int lockBtree(BtShared *pBt){
pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23);
pBt->maxLeaf = (u16)(pBt->usableSize - 35);
pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23);
if( pBt->maxLocal>127 ){
pBt->max1bytePayload = 127;
}else{
pBt->max1bytePayload = (u8)pBt->maxLocal;
}
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
pBt->pPage1 = pPage1;
pBt->nPage = nPage;
@ -2498,7 +2503,7 @@ static int newDatabase(BtShared *pBt){
data[23] = 32;
memset(&data[24], 0, 100-24);
zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
pBt->pageSizeFixed = 1;
pBt->btsFlags |= BTS_PAGESIZE_FIXED;
#ifndef SQLITE_OMIT_AUTOVACUUM
assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
@ -2562,7 +2567,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
}
/* Write transactions are not possible on a read-only database */
if( pBt->readOnly && wrflag ){
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
rc = SQLITE_READONLY;
goto trans_begun;
}
@ -2572,7 +2577,9 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
** on this shared-btree structure and a second write transaction is
** requested, return SQLITE_LOCKED.
*/
if( (wrflag && pBt->inTransaction==TRANS_WRITE) || pBt->isPending ){
if( (wrflag && pBt->inTransaction==TRANS_WRITE)
|| (pBt->btsFlags & BTS_PENDING)!=0
){
pBlock = pBt->pWriter->db;
}else if( wrflag>1 ){
BtLock *pIter;
@ -2596,7 +2603,8 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
if( SQLITE_OK!=rc ) goto trans_begun;
pBt->initiallyEmpty = (u8)(pBt->nPage==0);
pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
do {
/* Call lockBtree() until either pBt->pPage1 is populated or
** lockBtree() returns something other than SQLITE_OK. lockBtree()
@ -2608,7 +2616,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) );
if( rc==SQLITE_OK && wrflag ){
if( pBt->readOnly ){
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
rc = SQLITE_READONLY;
}else{
rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
@ -2645,7 +2653,8 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
#ifndef SQLITE_OMIT_SHARED_CACHE
assert( !pBt->pWriter );
pBt->pWriter = p;
pBt->isExclusive = (u8)(wrflag>1);
pBt->btsFlags &= ~BTS_EXCLUSIVE;
if( wrflag>1 ) pBt->btsFlags |= BTS_EXCLUSIVE;
#endif
/* If the db-size header field is incorrect (as it may be if an old
@ -3374,7 +3383,7 @@ int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
assert( p->inTrans==TRANS_WRITE );
assert( pBt->readOnly==0 );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( iStatement>0 );
assert( iStatement>p->db->nSavepoint );
assert( pBt->inTransaction==TRANS_WRITE );
@ -3409,7 +3418,9 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
sqlite3BtreeEnter(p);
rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
if( rc==SQLITE_OK ){
if( iSavepoint<0 && pBt->initiallyEmpty ) pBt->nPage = 0;
if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
pBt->nPage = 0;
}
rc = newDatabase(pBt);
pBt->nPage = get4byte(28 + pBt->pPage1->aData);
@ -3479,7 +3490,7 @@ static int btreeCursor(
assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
assert( pBt->pPage1 && pBt->pPage1->aData );
if( NEVER(wrFlag && pBt->readOnly) ){
if( NEVER(wrFlag && (pBt->btsFlags & BTS_READ_ONLY)!=0) ){
return SQLITE_READONLY;
}
if( iTable==1 && btreePagecount(pBt)==0 ){
@ -4183,7 +4194,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
return SQLITE_OK;
}
#ifndef NDEBUG
#if 0
/*
** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
@ -4216,11 +4227,21 @@ static void moveToParent(BtCursor *pCur){
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>0 );
assert( pCur->apPage[pCur->iPage] );
/* UPDATE: It is actually possible for the condition tested by the assert
** below to be untrue if the database file is corrupt. This can occur if
** one cursor has modified page pParent while a reference to it is held
** by a second cursor. Which can only happen if a single page is linked
** into more than one b-tree structure in a corrupt database. */
#if 0
assertParentIndex(
pCur->apPage[pCur->iPage-1],
pCur->aiIdx[pCur->iPage-1],
pCur->apPage[pCur->iPage]->pgno
);
#endif
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
releasePage(pCur->apPage[pCur->iPage]);
pCur->iPage--;
pCur->info.nSize = 0;
@ -4559,9 +4580,8 @@ int sqlite3BtreeMovetoUnpacked(
** 2 bytes of the cell.
*/
int nCell = pCell[0];
if( !(nCell & 0x80)
&& nCell<=pPage->maxLocal
&& (pCell+nCell+1)<=pPage->aDataEnd
if( nCell<=pPage->max1bytePayload
/* && (pCell+nCell)<pPage->aDataEnd */
){
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
@ -4570,7 +4590,7 @@ int sqlite3BtreeMovetoUnpacked(
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
&& (pCell+nCell+2)<=pPage->aDataEnd
/* && (pCell+nCell+2)<=pPage->aDataEnd */
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
@ -4691,7 +4711,13 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
pPage = pCur->apPage[pCur->iPage];
idx = ++pCur->aiIdx[pCur->iPage];
assert( pPage->isInit );
assert( idx<=pPage->nCell );
/* If the database file is corrupt, it is possible for the value of idx
** to be invalid here. This can only occur if a second cursor modifies
** the page while cursor pCur is holding a reference to it. Which can
** only happen if the database is corrupt in such a way as to link the
** page into more than one b-tree structure. */
testcase( idx>pPage->nCell );
pCur->info.nSize = 0;
pCur->validNKey = 0;
@ -5116,7 +5142,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
nFree = get4byte(&pPage1->aData[36]);
put4byte(&pPage1->aData[36], nFree+1);
if( pBt->secureDelete ){
if( pBt->btsFlags & BTS_SECURE_DELETE ){
/* If the secure_delete option is enabled, then
** always fully overwrite deleted information with zeros.
*/
@ -5177,7 +5203,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
if( rc==SQLITE_OK ){
put4byte(&pTrunk->aData[4], nLeaf+1);
put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
if( pPage && !pBt->secureDelete ){
if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){
sqlite3PagerDontWrite(pPage->pDbPage);
}
rc = btreeSetHasContent(pBt, iPage);
@ -6018,7 +6044,7 @@ static int balance_nonroot(
** In this case, temporarily copy the cell into the aOvflSpace[]
** buffer. It will be copied out again as soon as the aSpace[] buffer
** is allocated. */
if( pBt->secureDelete ){
if( pBt->btsFlags & BTS_SECURE_DELETE ){
int iOff;
iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
@ -6760,7 +6786,8 @@ int sqlite3BtreeInsert(
}
assert( cursorHoldsMutex(pCur) );
assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE && !pBt->readOnly );
assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
/* Assert that the caller has been consistent. If this cursor was opened
@ -6889,7 +6916,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pBt->inTransaction==TRANS_WRITE );
assert( !pBt->readOnly );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( pCur->wrFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
@ -7010,7 +7037,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
assert( sqlite3BtreeHoldsMutex(p) );
assert( pBt->inTransaction==TRANS_WRITE );
assert( !pBt->readOnly );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
#ifdef SQLITE_OMIT_AUTOVACUUM
rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
@ -7384,7 +7411,9 @@ void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
/* If auto-vacuum is disabled in this build and this is an auto-vacuum
** database, mark the database as read-only. */
#ifdef SQLITE_OMIT_AUTOVACUUM
if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ) pBt->readOnly = 1;
if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
pBt->btsFlags |= BTS_READ_ONLY;
}
#endif
sqlite3BtreeLeave(p);
@ -8184,7 +8213,8 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
if( !pCsr->wrFlag ){
return SQLITE_READONLY;
}
assert( !pCsr->pBt->readOnly && pCsr->pBt->inTransaction==TRANS_WRITE );
assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
&& pCsr->pBt->inTransaction==TRANS_WRITE );
assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
assert( pCsr->apPage[pCsr->iPage]->intKey );
@ -8224,7 +8254,8 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
/* If setting the version fields to 1, do not automatically open the
** WAL connection, even if the version fields are currently set to 2.
*/
pBt->doNotUseWAL = (u8)(iVersion==1);
pBt->btsFlags &= ~BTS_NO_WAL;
if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
rc = sqlite3BtreeBeginTrans(pBtree, 0);
if( rc==SQLITE_OK ){
@ -8241,6 +8272,6 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
}
}
pBt->doNotUseWAL = 0;
pBt->btsFlags &= ~BTS_NO_WAL;
return rc;
}

View File

@ -277,6 +277,7 @@ struct MemPage {
u8 hasData; /* True if this page stores data */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
u8 max1bytePayload; /* min(maxLocal,127) */
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
@ -407,17 +408,14 @@ struct BtShared {
sqlite3 *db; /* Database connection currently using this Btree */
BtCursor *pCursor; /* A list of all open cursors */
MemPage *pPage1; /* First page of the database */
u8 readOnly; /* True if the underlying file is readonly */
u8 pageSizeFixed; /* True if the page size can no longer be changed */
u8 secureDelete; /* True if secure_delete is enabled */
u8 initiallyEmpty; /* Database is empty at start of transaction */
u8 openFlags; /* Flags to sqlite3BtreeOpen() */
#ifndef SQLITE_OMIT_AUTOVACUUM
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */
#endif
u8 inTransaction; /* Transaction state */
u8 doNotUseWAL; /* If true, do not open write-ahead-log file */
u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
@ -435,12 +433,21 @@ struct BtShared {
BtShared *pNext; /* Next on a list of sharable BtShared structs */
BtLock *pLock; /* List of locks held on this shared-btree struct */
Btree *pWriter; /* Btree with currently open write transaction */
u8 isExclusive; /* True if pWriter has an EXCLUSIVE lock on the db */
u8 isPending; /* If waiting for read-locks to clear */
#endif
u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */
};
/*
** Allowed values for BtShared.btsFlags
*/
#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
#define BTS_INITIALLY_EMPTY 0x0008 /* Database was empty at trans start */
#define BTS_NO_WAL 0x0010 /* Do not open write-ahead-log files */
#define BTS_EXCLUSIVE 0x0020 /* pWriter has an exclusive lock */
#define BTS_PENDING 0x0040 /* Waiting for read-locks to clear */
/*
** An instance of the following structure is used to hold information
** about a cell. The parseCellPtr() function fills in this structure

View File

@ -97,10 +97,23 @@ int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
DO_OS_MALLOC_TEST(id);
return id->pMethods->xCheckReservedLock(id, pResOut);
}
/*
** Use sqlite3OsFileControl() when we are doing something that might fail
** and we need to know about the failures. Use sqlite3OsFileControlHint()
** when simply tossing information over the wall to the VFS and we do not
** really care if the VFS receives and understands the information since it
** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
** routine has no return value since the return value would be meaningless.
*/
int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
DO_OS_MALLOC_TEST(id);
return id->pMethods->xFileControl(id, op, pArg);
}
void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
(void)id->pMethods->xFileControl(id, op, pArg);
}
int sqlite3OsSectorSize(sqlite3_file *id){
int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
@ -151,6 +164,7 @@ int sqlite3OsOpen(
}
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
DO_OS_MALLOC_TEST(0);
assert( dirSync==0 || dirSync==1 );
return pVfs->xDelete(pVfs, zPath, dirSync);
}
int sqlite3OsAccess(

View File

@ -252,6 +252,7 @@ int sqlite3OsLock(sqlite3_file*, int);
int sqlite3OsUnlock(sqlite3_file*, int);
int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
int sqlite3OsFileControl(sqlite3_file*,int,void*);
void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
int sqlite3OsSectorSize(sqlite3_file *id);
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
@ -260,6 +261,7 @@ int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
void sqlite3OsShmBarrier(sqlite3_file *id);
int sqlite3OsShmUnmap(sqlite3_file *id, int);
/*
** Functions for accessing sqlite3_vfs methods
*/

View File

@ -225,7 +225,6 @@ struct unixFile {
unsigned fsFlags; /* cached details from statfs() */
#endif
#if OS_VXWORKS
int isDelete; /* Delete on close if true */
struct vxworksFileId *pId; /* Unique file ID */
#endif
#ifndef NDEBUG
@ -260,6 +259,9 @@ struct unixFile {
# define UNIXFILE_DIRSYNC 0x00
#endif
#define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
#define UNIXFILE_DELETE 0x20 /* Delete on close */
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
/*
** Include code that is common to all os_*.c files
@ -1765,7 +1767,7 @@ static int closeUnixFile(sqlite3_file *id){
}
#if OS_VXWORKS
if( pFile->pId ){
if( pFile->isDelete ){
if( pFile->ctrlFlags & UNIXFILE_DELETE ){
osUnlink(pFile->pId->zCanonicalName);
}
vxworksReleaseFileId(pFile->pId);
@ -3872,7 +3874,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
rc = SQLITE_NOMEM;
goto shm_open_err;
}
memset(pShmNode, 0, sizeof(*pShmNode));
memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
#ifdef SQLITE_SHM_DIRECTORY
sqlite3_snprintf(nShmFilename, zShmFilename,
@ -4555,12 +4557,9 @@ typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
static int fillInUnixFile(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
int h, /* Open file descriptor of file being opened */
int syncDir, /* True to sync directory on first sync */
sqlite3_file *pId, /* Write to the unixFile structure here */
const char *zFilename, /* Name of the file being opened */
int noLock, /* Omit locking if true */
int isDelete, /* Delete on close if true */
int isReadOnly /* True if the file is opened read-only */
int ctrlFlags /* Zero or more UNIXFILE_* values */
){
const sqlite3_io_methods *pLockingStyle;
unixFile *pNew = (unixFile *)pId;
@ -4568,11 +4567,6 @@ static int fillInUnixFile(
assert( pNew->pInode==NULL );
/* Parameter isDelete is only used on vxworks. Express this explicitly
** here to prevent compiler warnings about unused parameters.
*/
UNUSED_PARAMETER(isDelete);
/* Usually the path zFilename should not be a relative pathname. The
** exception is when opening the proxy "conch" file in builds that
** include the special Apple locking styles.
@ -4585,35 +4579,30 @@ static int fillInUnixFile(
#endif
/* No locking occurs in temporary files */
assert( zFilename!=0 || noLock );
assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
OSTRACE(("OPEN %-3d %s\n", h, zFilename));
pNew->h = h;
pNew->pVfs = pVfs;
pNew->zPath = zFilename;
pNew->ctrlFlags = 0;
if( sqlite3_uri_boolean(zFilename, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
pNew->ctrlFlags = (u8)ctrlFlags;
if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
"psow", SQLITE_POWERSAFE_OVERWRITE) ){
pNew->ctrlFlags |= UNIXFILE_PSOW;
}
if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
pNew->ctrlFlags |= UNIXFILE_EXCL;
}
if( isReadOnly ){
pNew->ctrlFlags |= UNIXFILE_RDONLY;
}
if( syncDir ){
pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
}
#if OS_VXWORKS
pNew->pId = vxworksFindFileId(zFilename);
if( pNew->pId==0 ){
noLock = 1;
ctrlFlags |= UNIXFILE_NOLOCK;
rc = SQLITE_NOMEM;
}
#endif
if( noLock ){
if( ctrlFlags & UNIXFILE_NOLOCK ){
pLockingStyle = &nolockIoMethods;
}else{
pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
@ -4734,7 +4723,7 @@ static int fillInUnixFile(
osUnlink(zFilename);
isDelete = 0;
}
pNew->isDelete = isDelete;
if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE;
#endif
if( rc!=SQLITE_OK ){
if( h>=0 ) robust_close(pNew, h, __LINE__);
@ -4799,18 +4788,19 @@ static int unixGetTempname(int nBuf, char *zBuf){
/* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
*/
if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= (size_t)nBuf ){
if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
return SQLITE_ERROR;
}
do{
sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
j = (int)strlen(zBuf);
sqlite3_randomness(15, &zBuf[j]);
for(i=0; i<15; i++, j++){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
zBuf[j+1] = 0;
}while( osAccess(zBuf,0)==0 );
return SQLITE_OK;
}
@ -4989,6 +4979,7 @@ static int unixOpen(
int eType = flags&0xFFFFFF00; /* Type of file to open */
int noLock; /* True to omit locking primitives */
int rc = SQLITE_OK; /* Function Return Code */
int ctrlFlags = 0; /* UNIXFILE_* flags */
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
@ -5015,7 +5006,7 @@ static int unixOpen(
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
*/
char zTmpname[MAX_PATHNAME+1];
char zTmpname[MAX_PATHNAME+2];
const char *zName = zPath;
/* Check the following statements are true:
@ -5058,14 +5049,24 @@ static int unixOpen(
}
}
p->pUnused = pUnused;
/* Database filenames are double-zero terminated if they are not
** URIs with parameters. Hence, they can always be passed into
** sqlite3_uri_parameter(). */
assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
}else if( !zName ){
/* If zName is NULL, the upper layer is requesting a temp file. */
assert(isDelete && !syncDir);
rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
rc = unixGetTempname(MAX_PATHNAME+2, zTmpname);
if( rc!=SQLITE_OK ){
return rc;
}
zName = zTmpname;
/* Generated temporary filenames are always double-zero terminated
** for use by sqlite3_uri_parameter(). */
assert( zName[strlen(zName)+1]==0 );
}
/* Determine the value of the flags parameter passed to POSIX function
@ -5142,7 +5143,14 @@ static int unixOpen(
((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
}
#endif
/* Set up appropriate ctrlFlags */
if( isDelete ) ctrlFlags |= UNIXFILE_DELETE;
if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC;
if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
#if SQLITE_ENABLE_LOCKING_STYLE
#if SQLITE_PREFER_PROXY_LOCKING
isAutoProxy = 1;
@ -5172,8 +5180,7 @@ static int unixOpen(
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
}
if( useProxy ){
rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
isDelete, isReadonly);
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
if( rc==SQLITE_OK ){
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
if( rc!=SQLITE_OK ){
@ -5190,8 +5197,8 @@ static int unixOpen(
}
#endif
rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
isDelete, isReadonly);
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
open_finished:
if( rc!=SQLITE_OK ){
sqlite3_free(p->pUnused);
@ -5216,7 +5223,7 @@ static int unixDelete(
return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
}
#ifndef SQLITE_DISABLE_DIRSYNC
if( dirSync ){
if( (dirSync & 1)!=0 ){
int fd;
rc = osOpenDirectory(zPath, &fd);
if( rc==SQLITE_OK ){
@ -5862,7 +5869,7 @@ static int proxyCreateUnixFile(
pUnused->flags = openFlags;
pNew->pUnused = pUnused;
rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
if( rc==SQLITE_OK ){
*ppFile = pNew;
return SQLITE_OK;

View File

@ -2428,7 +2428,9 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
}
if( deleteFlag ){
SimulateIOErrorBenign(1);
sqlite3BeginBenignMalloc();
winDelete(pVfs, p->zFilename, 0);
sqlite3EndBenignMalloc();
SimulateIOErrorBenign(0);
}
*pp = p->pNext;
@ -2463,12 +2465,12 @@ static int winOpenSharedMemory(winFile *pDbFd){
if( p==0 ) return SQLITE_IOERR_NOMEM;
memset(p, 0, sizeof(*p));
nName = sqlite3Strlen30(pDbFd->zPath);
pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 16 );
pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 17 );
if( pNew==0 ){
sqlite3_free(p);
return SQLITE_IOERR_NOMEM;
}
memset(pNew, 0, sizeof(*pNew));
memset(pNew, 0, sizeof(*pNew) + nName + 17);
pNew->zFilename = (char*)&pNew[1];
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
@ -2504,7 +2506,6 @@ static int winOpenSharedMemory(winFile *pDbFd){
SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
0);
if( SQLITE_OK!=rc ){
rc = SQLITE_CANTOPEN_BKPT;
goto shm_open_err;
}
@ -2927,7 +2928,7 @@ static int getTempname(int nBuf, char *zBuf){
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
size_t i, j;
char zTempPath[MAX_PATH+1];
char zTempPath[MAX_PATH+2];
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
@ -2970,14 +2971,14 @@ static int getTempname(int nBuf, char *zBuf){
/* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
*/
if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){
if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
return SQLITE_ERROR;
}
for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
zTempPath[i] = 0;
sqlite3_snprintf(nBuf-17, zBuf,
sqlite3_snprintf(nBuf-18, zBuf,
"%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
j = sqlite3Strlen30(zBuf);
sqlite3_randomness(15, &zBuf[j]);
@ -2985,6 +2986,7 @@ static int getTempname(int nBuf, char *zBuf){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
zBuf[j+1] = 0;
OSTRACE(("TEMP FILENAME: %s\n", zBuf));
return SQLITE_OK;
@ -3017,7 +3019,7 @@ static int winOpen(
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
*/
char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */
char zTmpname[MAX_PATH+2]; /* Buffer used to create temp filename */
int rc = SQLITE_OK; /* Function Return Code */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
@ -3076,13 +3078,20 @@ static int winOpen(
*/
if( !zUtf8Name ){
assert(isDelete && !isOpenJournal);
rc = getTempname(MAX_PATH+1, zTmpname);
rc = getTempname(MAX_PATH+2, zTmpname);
if( rc!=SQLITE_OK ){
return rc;
}
zUtf8Name = zTmpname;
}
/* Database filenames are double-zero terminated if they are not
** URIs with parameters. Hence, they can always be passed into
** sqlite3_uri_parameter().
*/
assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
zUtf8Name[strlen(zUtf8Name)+1]==0 );
/* Convert the filename to the system encoding. */
zConverted = convertUtf8Filename(zUtf8Name);
if( zConverted==0 ){

View File

@ -2486,10 +2486,9 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
if( rc==SQLITE_OK && currentSize!=newSize ){
if( currentSize>newSize ){
rc = sqlite3OsTruncate(pPager->fd, newSize);
}else{
}else if( (currentSize+szPage)<=newSize ){
char *pTmp = pPager->pTmpSpace;
memset(pTmp, 0, szPage);
testcase( (newSize-szPage) < currentSize );
testcase( (newSize-szPage) == currentSize );
testcase( (newSize-szPage) > currentSize );
rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
@ -2747,10 +2746,11 @@ end_playback:
** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
** assertion that the transaction counter was modified.
*/
assert(
pPager->fd->pMethods==0 ||
sqlite3OsFileControl(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0)>=SQLITE_OK
);
#ifdef SQLITE_DEBUG
if( pPager->fd->pMethods ){
sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
}
#endif
/* If this playback is happening automatically as a result of an IO or
** malloc error that occurred after the change-counter was updated but
@ -3087,10 +3087,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
return rc;
}
}
nPage = (Pgno)(n / pPager->pageSize);
if( nPage==0 && n>0 ){
nPage = 1;
}
nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
}
/* If the current number of pages in the file is greater than the
@ -3521,7 +3518,7 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
if( rc==SQLITE_OK ){
pager_reset(pPager);
pPager->dbSize = (Pgno)(nByte/pageSize);
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
pPager->pageSize = pageSize;
sqlite3PageFree(pPager->pTmpSpace);
pPager->pTmpSpace = pNew;
@ -4029,9 +4026,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
if( rc==SQLITE_OK && pPager->dbSize>pPager->dbHintSize ){
sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
sqlite3BeginBenignMalloc();
sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
sqlite3EndBenignMalloc();
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
pPager->dbHintSize = pPager->dbSize;
}
@ -6055,7 +6050,8 @@ int sqlite3PagerRollback(Pager *pPager){
}
assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
assert( rc==SQLITE_OK || rc==SQLITE_FULL || (rc&0xFF)==SQLITE_IOERR );
assert( rc==SQLITE_OK || rc==SQLITE_FULL
|| rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
/* If an error occurs during a ROLLBACK, we can no longer trust the pager
** cache. So call pager_error() on the way out to make any error persistent.

View File

@ -40,7 +40,7 @@ typedef struct PGroup PGroup;
** Mode 1 uses more memory (since PCache instances are not able to rob
** unused pages from other PCaches) but it also operates without a mutex,
** and is therefore often faster. Mode 2 requires a mutex in order to be
** threadsafe, but is able recycle pages more efficient.
** threadsafe, but recycles pages more efficiently.
**
** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single
** PGroup which is the pcache1.grp global variable and its mutex is
@ -66,7 +66,7 @@ struct PGroup {
struct PCache1 {
/* Cache configuration parameters. Page size (szPage) and the purgeable
** flag (bPurgeable) are set when the cache is created. nMax may be
** modified at any time by a call to the pcache1CacheSize() method.
** modified at any time by a call to the pcache1Cachesize() method.
** The PGroup mutex must be held when accessing nMax.
*/
PGroup *pGroup; /* PGroup this cache belongs to */
@ -357,7 +357,7 @@ void sqlite3PageFree(void *p){
** for all page cache needs and we should not need to spill the
** allocation onto the heap.
**
** Or, the heap is used for all page cache memory put the heap is
** Or, the heap is used for all page cache memory but the heap is
** under memory pressure, then again it is desirable to avoid
** allocating a new page cache entry in order to avoid stressing
** the heap even further.
@ -668,7 +668,7 @@ static int pcache1Pagecount(sqlite3_pcache *p){
** For a non-purgeable cache (a cache used as the storage for an in-memory
** database) there is really no difference between createFlag 1 and 2. So
** the calling function (pcache.c) will never have a createFlag of 1 on
** a non-purgable cache.
** a non-purgeable cache.
**
** There are three different approaches to obtaining space for a page,
** depending on the value of parameter createFlag (which may be 0, 1 or 2).

View File

@ -795,7 +795,7 @@ void sqlite3Pragma(
Pager *pPager = sqlite3BtreePager(pDb->pBt);
char *proxy_file_path = NULL;
sqlite3_file *pFile = sqlite3PagerFile(pPager);
sqlite3OsFileControl(pFile, SQLITE_GET_LOCKPROXYFILE,
sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE,
&proxy_file_path);
if( proxy_file_path ){

View File

@ -2627,8 +2627,10 @@ int sqlite3_open_v2(
** to see if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of that query parameter.
**
** If F is the filename pointer passed into the xOpen() method of a VFS
** implementation and P is the name of the query parameter, then
** If F is the database filename pointer passed into the xOpen() method of
** a VFS implementation when the flags parameter to xOpen() has one or
** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
** P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a
** query parameter on F. If P is a query parameter of F
@ -2648,8 +2650,9 @@ int sqlite3_open_v2(
**
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
** is not a pathname pointer that SQLite passed into the xOpen VFS method,
** then the behavior of this routine is undefined and probably undesirable.
** is not a database file pathname pointer that SQLite passed into the xOpen
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
*/
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
@ -6205,7 +6208,7 @@ struct sqlite3_pcache_page {
** [[the xShrink() page cache method]]
** ^SQLite invokes the xShrink() method when it wants the page cache to
** free up as much of heap memory as possible. The page cache implementation
** is not obligated to free any memory, but well-behaved implementions should
** is not obligated to free any memory, but well-behaved implementations should
** do their best.
*/
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;

View File

@ -3163,7 +3163,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
if( objc<3 || (objc&1)!=1 ){
Tcl_WrongNumArgs(interp, 1, objv,
"HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN?"
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
#ifdef SQLITE_HAS_CODEC
" ?-key CODECKEY?"
#endif

View File

@ -537,6 +537,8 @@ static int fake_big_file(
int rc;
int n;
i64 offset;
char *zFile;
int nFile;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" N-MEGABYTES FILE\"", 0);
@ -545,17 +547,24 @@ static int fake_big_file(
if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
pVfs = sqlite3_vfs_find(0);
rc = sqlite3OsOpenMalloc(pVfs, argv[2], &fd,
nFile = strlen(argv[2]);
zFile = sqlite3_malloc( nFile+2 );
if( zFile==0 ) return TCL_ERROR;
memcpy(zFile, argv[2], nFile+1);
zFile[nFile+1] = 0;
rc = sqlite3OsOpenMalloc(pVfs, zFile, &fd,
(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0
);
if( rc ){
Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0);
sqlite3_free(zFile);
return TCL_ERROR;
}
offset = n;
offset *= 1024*1024;
rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
sqlite3OsCloseFree(fd);
sqlite3_free(zFile);
if( rc ){
Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0);
return TCL_ERROR;

View File

@ -66,6 +66,8 @@ static int btree_open(
Btree *pBt;
int rc, nCache;
char zBuf[100];
int n;
char *zFilename;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" FILENAME NCACHE FLAGS\"", 0);
@ -78,8 +80,14 @@ static int btree_open(
sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
sqlite3_mutex_enter(sDb.mutex);
}
rc = sqlite3BtreeOpen(sDb.pVfs, argv[1], &sDb, &pBt, 0,
n = strlen(argv[1]);
zFilename = sqlite3_malloc( n+2 );
if( zFilename==0 ) return TCL_ERROR;
memcpy(zFilename, argv[1], n+1);
zFilename[n+1] = 0;
rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
sqlite3_free(zFilename);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;

View File

@ -409,6 +409,7 @@ static int openTransaction(jt_file *pMain, jt_file *pJournal){
if( iOff==PENDING_BYTE ) continue;
rc = sqlite3OsRead(pMain->pReal, aData, pMain->nPagesize, iOff);
pMain->aCksum[ii] = genCksum(aData, pMain->nPagesize);
if( ii+1==pMain->nPage && rc==SQLITE_IOERR_SHORT_READ ) rc = SQLITE_OK;
}
}
@ -662,7 +663,7 @@ static int jtCheckReservedLock(sqlite3_file *pFile, int *pResOut){
*/
static int jtFileControl(sqlite3_file *pFile, int op, void *pArg){
jt_file *p = (jt_file *)pFile;
return sqlite3OsFileControl(p->pReal, op, pArg);
return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
}
/*

View File

@ -220,9 +220,27 @@ static int multiplexStrlen30(const char *z){
/*
** Generate the file-name for chunk iChunk of the group with base name
** zBase. The file-name is written to buffer zOut before returning. Buffer
** zOut must be allocated by the caller so that it is at least (nBase+4)
** zOut must be allocated by the caller so that it is at least (nBase+5)
** bytes in size, where nBase is the length of zBase, not including the
** nul-terminator.
**
** If iChunk is 0 (or 400 - the number for the first journal file chunk),
** the output is a copy of the input string. Otherwise, if
** SQLITE_ENABLE_8_3_NAMES is not defined or the input buffer does not contain
** a "." character, then the output is a copy of the input string with the
** three-digit zero-padded decimal representation if iChunk appended to it.
** For example:
**
** zBase="test.db", iChunk=4 -> zOut="test.db004"
**
** Or, if SQLITE_ENABLE_8_3_NAMES is defined and the input buffer contains
** a "." character, then everything after the "." is replaced by the
** three-digit representation of iChunk.
**
** zBase="test.db", iChunk=4 -> zOut="test.004"
**
** The output buffer string is terminated by 2 0x00 bytes. This makes it safe
** to pass to sqlite3_uri_parameter() and similar.
*/
static void multiplexFilename(
const char *zBase, /* Filename for chunk 0 */
@ -231,9 +249,9 @@ static void multiplexFilename(
int iChunk, /* Chunk to generate filename for */
char *zOut /* Buffer to write generated name to */
){
memcpy(zOut, zBase, nBase+1);
int n = nBase;
memcpy(zOut, zBase, n+1);
if( iChunk!=0 && iChunk!=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
int n = nBase;
#ifdef SQLITE_ENABLE_8_3_NAMES
int i;
for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){}
@ -247,7 +265,11 @@ static void multiplexFilename(
}
#endif
sqlite3_snprintf(4,&zOut[n],"%03d",iChunk);
n += 3;
}
assert( zOut[n]=='\0' );
zOut[n+1] = '\0';
}
/* Compute the filename for the iChunk-th chunk
@ -266,7 +288,7 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
char *z;
int n = pGroup->nName;
pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+4 );
pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+5 );
if( z==0 ){
return SQLITE_NOMEM;
}
@ -306,7 +328,6 @@ static sqlite3_file *multiplexSubOpen(
*rc = multiplexSubFilename(pGroup, iChunk);
if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
int flags, bExists;
createFlag = (pGroup->flags & SQLITE_OPEN_CREATE)!=0;
flags = pGroup->flags;
if( createFlag ){
flags |= SQLITE_OPEN_CREATE;
@ -350,6 +371,7 @@ static sqlite3_int64 multiplexSubSize(
sqlite3_file *pSub;
sqlite3_int64 sz = 0;
if( *rc ) return 0;
pSub = multiplexSubOpen(pGroup, iChunk, rc, NULL, 0);
if( pSub==0 ) return 0;
*rc = pSub->pMethods->xFileSize(pSub, &sz);
@ -491,13 +513,14 @@ static int multiplexOpen(
}
if( rc==SQLITE_OK ){
const char *zUri = (flags & SQLITE_OPEN_URI) ? zName : 0;
/* assign pointers to extra space allocated */
memset(pGroup, 0, sz);
pMultiplexOpen->pGroup = pGroup;
pGroup->bEnabled = -1;
pGroup->bTruncate = sqlite3_uri_boolean(zName, "truncate",
(flags & SQLITE_OPEN_MAIN_DB)==0);
pGroup->szChunk = sqlite3_uri_int64(zName, "chunksize",
pGroup->bTruncate = sqlite3_uri_boolean(zUri, "truncate",
(flags & SQLITE_OPEN_MAIN_DB)==0);
pGroup->szChunk = sqlite3_uri_int64(zUri, "chunksize",
SQLITE_MULTIPLEX_CHUNK_SIZE);
pGroup->szChunk = (pGroup->szChunk+0xffff)&~0xffff;
if( zName ){
@ -611,7 +634,7 @@ static int multiplexDelete(
*/
int nName = strlen(zName);
char *z;
z = sqlite3_malloc(nName + 4);
z = sqlite3_malloc(nName + 5);
if( z==0 ){
rc = SQLITE_IOERR_NOMEM;
}else{

View File

@ -937,30 +937,38 @@ int sqlite3_quota_file(const char *zFilename){
int rc;
int outFlags = 0;
sqlite3_int64 iSize;
fd = (sqlite3_file*)sqlite3_malloc(gQuota.sThisVfs.szOsFile +
gQuota.sThisVfs.mxPathname+1);
if( fd==0 ) return SQLITE_NOMEM;
zFull = gQuota.sThisVfs.szOsFile + (char*)fd;
rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename,
gQuota.sThisVfs.mxPathname+1, zFull);
int nAlloc = gQuota.sThisVfs.szOsFile + gQuota.sThisVfs.mxPathname+2;
/* Allocate space for a file-handle and the full path for file zFilename */
fd = (sqlite3_file *)sqlite3_malloc(nAlloc);
if( fd==0 ){
rc = SQLITE_NOMEM;
}else{
zFull = &((char *)fd)[gQuota.sThisVfs.szOsFile];
rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename,
gQuota.sThisVfs.mxPathname+1, zFull);
}
if( rc==SQLITE_OK ){
zFull[strlen(zFull)+1] = '\0';
rc = quotaOpen(&gQuota.sThisVfs, zFull, fd,
SQLITE_OPEN_READONLY | SQLITE_OPEN_MAIN_DB, &outFlags);
}
if( rc==SQLITE_OK ){
fd->pMethods->xFileSize(fd, &iSize);
fd->pMethods->xClose(fd);
}else if( rc==SQLITE_CANTOPEN ){
quotaGroup *pGroup;
quotaFile *pFile;
quotaEnter();
pGroup = quotaGroupFind(zFull);
if( pGroup ){
pFile = quotaFindFile(pGroup, zFull, 0);
if( pFile ) quotaRemoveFile(pFile);
if( rc==SQLITE_OK ){
fd->pMethods->xFileSize(fd, &iSize);
fd->pMethods->xClose(fd);
}else if( rc==SQLITE_CANTOPEN ){
quotaGroup *pGroup;
quotaFile *pFile;
quotaEnter();
pGroup = quotaGroupFind(zFull);
if( pGroup ){
pFile = quotaFindFile(pGroup, zFull, 0);
if( pFile ) quotaRemoveFile(pFile);
}
quotaLeave();
}
quotaLeave();
}
sqlite3_free(fd);
return rc;
}

View File

@ -1164,10 +1164,6 @@ int sqlite3AbsInt32(int x){
** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
** do the suffix shortening regardless of URI parameter.
**
** Assume that zBaseFilename contains two \000 terminator bytes (so that
** it can be harmlessly passed into sqlite3_uri_parameter()) and copy both
** zero terminator bytes into the end of the revised name.
**
** Examples:
**
** test.db-journal => test.nal
@ -1176,7 +1172,6 @@ int sqlite3AbsInt32(int x){
** test.db-mj7f3319fa => test.9fa
*/
void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
assert( zBaseFilename[strlen(zBaseFilename)+1]==0 );
#if SQLITE_ENABLE_8_3_NAMES<2
if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
#endif
@ -1184,7 +1179,7 @@ void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
int i, sz;
sz = sqlite3Strlen30(z);
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 5);
if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
}
}
#endif

View File

@ -161,12 +161,6 @@ int sqlite3_found_count = 0;
if( ((P)->flags&MEM_Ephem)!=0 \
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
** P if required.
*/
#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
#ifdef SQLITE_OMIT_MERGE_SORT
# define isSorter(x) 0

View File

@ -486,8 +486,10 @@ int sqlite3VdbeMemHandleBom(Mem *pMem);
#ifndef SQLITE_OMIT_INCRBLOB
int sqlite3VdbeMemExpandBlob(Mem *);
#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
#else
#define sqlite3VdbeMemExpandBlob(x) SQLITE_OK
#define ExpandBlob(P) SQLITE_OK
#endif
#endif /* !defined(_VDBEINT_H_) */

View File

@ -18,12 +18,6 @@
#include "sqliteInt.h"
#include "vdbeInt.h"
/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
** P if required.
*/
#define expandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
/*
** If pMem is an object with a valid string representation, this routine
** ensures the internal encoding for the string representation is
@ -123,7 +117,7 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
int f;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( (pMem->flags&MEM_RowSet)==0 );
expandBlob(pMem);
ExpandBlob(pMem);
f = pMem->flags;
if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){
if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
@ -960,7 +954,7 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
}
assert( (MEM_Blob>>3) == MEM_Str );
pVal->flags |= (pVal->flags & MEM_Blob)>>3;
expandBlob(pVal);
ExpandBlob(pVal);
if( pVal->flags&MEM_Str ){
sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){

View File

@ -1727,7 +1727,7 @@ static int walCheckpoint(
i64 nReq = ((i64)mxPage * szPage);
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
if( rc==SQLITE_OK && nSize<nReq ){
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
}
}
@ -1843,7 +1843,9 @@ int sqlite3WalClose(
);
if( rc==SQLITE_OK ){
int bPersist = -1;
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist);
sqlite3OsFileControlHint(
pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
);
if( bPersist!=1 ){
/* Try to delete the WAL file if the checkpoint completed and
** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal
@ -1864,7 +1866,9 @@ int sqlite3WalClose(
walIndexClose(pWal, isDelete);
sqlite3OsClose(pWal->pWalFd);
if( isDelete ){
sqlite3BeginBenignMalloc();
sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
sqlite3EndBenignMalloc();
}
WALTRACE(("WAL%p: closed\n", pWal));
sqlite3_free((void *)pWal->apWiData);

View File

@ -142,21 +142,18 @@ do_test backup2-9 {
# Try to restore from an unreadable file.
#
if {$tcl_platform(platform)=="windows"} {
do_test backup2-10 {
forcedelete bu3.db
file mkdir bu3.db
set rc [catch {db restore temp bu3.db} res]
lappend rc $res
} {1 {cannot open source database: unable to open database file}}
}
if {$tcl_platform(platform)!="windows"} {
do_test backup2-10 {
forcedelete bu3.db
file mkdir bu3.db
set rc [catch {db restore temp bu3.db} res]
lappend rc $res
} {1 {cannot open source database: disk I/O error}}
set msg {cannot open source database: unable to open database file}
} elseif {$tcl_platform(os)=="OpenBSD"} {
set msg {restore failed: file is encrypted or is not a database}
} else {
set msg {cannot open source database: disk I/O error}
}
do_test backup2-10 {
forcedelete bu3.db
file mkdir bu3.db
set rc [catch {db restore temp bu3.db} res]
lappend rc $res
} [list 1 $msg]
# Try to restore from something that is not a database file.
#

150
test/corruptF.test Normal file
View File

@ -0,0 +1,150 @@
# 2012 January 12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptF
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
proc str {i} { format %08d $i }
# Create a 6 page database containing a single table - t1. Table t1
# consists of page 2 (the root page) and pages 5 and 6 (leaf pages).
# Database pages 3 and 4 are on the free list.
#
proc create_test_db {} {
catch { db close }
forcedelete test.db
sqlite3 db test.db
db func str str
execsql {
PRAGMA auto_vacuum = 0;
PRAGMA page_size = 1024;
CREATE TABLE t1(x); /* root page = 2 */
CREATE TABLE t2(x); /* root page = 3 */
CREATE TABLE t3(x); /* root page = 4 */
INSERT INTO t1 VALUES(str(1));
INSERT INTO t1 SELECT str(rowid+1) FROM t1;
INSERT INTO t1 SELECT str(rowid+2) FROM t1;
INSERT INTO t1 SELECT str(rowid+4) FROM t1;
INSERT INTO t1 SELECT str(rowid+8) FROM t1;
INSERT INTO t1 SELECT str(rowid+16) FROM t1;
INSERT INTO t1 SELECT str(rowid+32) FROM t1;
INSERT INTO t1 SELECT str(rowid+64) FROM t1;
DROP TABLE t2;
DROP TABLE t3;
}
db close
}
do_test 1.1 { create_test_db } {}
# Check the db is as we expect. 6 pages in total, with 3 and 4 on the free
# list. Page 3 is the free list trunk and page 4 is a leaf.
#
do_test 1.2 { file size test.db } [expr 6*1024]
do_test 1.3 { hexio_read test.db 32 4 } 00000003
do_test 1.4 { hexio_read test.db [expr 2*1024] 12 } 000000000000000100000004
# Change the free-list entry to page 6 and reopen the db file.
do_test 1.5 {
hexio_write test.db [expr 2*1024 + 8] 00000006
sqlite3 db test.db
} {}
# Now create a new table in the database file. The root of the new table
# is page 6, which is also the right-most leaf page in table t1.
#
do_execsql_test 1.6 {
CREATE TABLE t4(x);
SELECT * FROM sqlite_master;
} {
table t1 t1 2 {CREATE TABLE t1(x)}
table t4 t4 6 {CREATE TABLE t4(x)}
}
# At one point this was causing an assert to fail.
#
# This statement opens a cursor on table t1 and does a full table scan. As
# each row is visited, it is copied into table t4. There is no temporary
# table.
#
# When the t1 cursor reaches page 6 (which is both the right-most leaf of
# t1 and the root of t4), it continues to iterate through the keys within
# it (which at this point are keys that have been inserted into t4). And
# for each row visited, another row is inserted into page 6 - it being the
# root page of t4. Eventually, page 6 becomes full and the height of the
# b-tree for table t4 increased. From the point of view of the t1 cursor,
# this unexpectedly reduces the number of keys on page 6 in the middle of
# its iteration, which causes an assert() to fail.
#
db_save_and_close
if 1 {
for {set i 0} {$i < 128} {incr i} {
db_restore_and_reopen
do_test 1.7.$i {
set res [
catchsql { INSERT INTO t4 SELECT x FROM t1 WHERE rowid>$i }
]
if {$res == "0 {}" || $res == "1 {database disk image is malformed}"} {
set res ""
}
set res
} {}
}
}
do_test 2.1 { create_test_db } {}
do_test 2.2 { file size test.db } [expr 6*1024]
do_test 2.3 { hexio_read test.db 32 4 } 00000003
do_test 2.4 { hexio_read test.db [expr 2*1024] 12 } 000000000000000100000004
# Change the free-list entry to page 5 and reopen the db file.
do_test 2.5 {
hexio_write test.db [expr 2*1024 + 8] 00000005
sqlite3 db test.db
} {}
# Now create a new table in the database file. The root of the new table
# is page 5, which is also the right-most leaf page in table t1.
#
do_execsql_test 2.6 {
CREATE TABLE t4(x);
SELECT * FROM sqlite_master;
} {
table t1 t1 2 {CREATE TABLE t1(x)}
table t4 t4 5 {CREATE TABLE t4(x)}
}
db_save_and_close
for {set i 127} {$i >= 0} {incr i -1} {
db_restore_and_reopen
do_test 2.7.$i {
set res [
catchsql {
INSERT INTO t4 SELECT x FROM t1 WHERE rowid<$i ORDER BY rowid DESC
}
]
if {$res == "0 {}" || $res == "1 {database disk image is malformed}"} {
set res ""
}
set res
} {}
}
finish_test

View File

@ -352,7 +352,7 @@ do_test malloc5-6.3.1 {
do_test malloc5-6.3.2 {
# Try to release 7700 bytes. This should release all the
# non-dirty pages held by db2.
sqlite3_release_memory [expr 7*1100]
sqlite3_release_memory [expr 7*1132]
list [nPage db] [nPage db2]
} {10 3}
do_test malloc5-6.3.3 {
@ -366,7 +366,7 @@ do_test malloc5-6.3.4 {
# the rest of the db cache. But the db2 cache remains intact, because
# SQLite tries to avoid calling sync().
if {$::tcl_platform(wordSize)==8} {
sqlite3_release_memory 10177
sqlite3_release_memory 10500
} else {
sqlite3_release_memory 9900
}

View File

@ -156,6 +156,9 @@ sqlite3_multiplex_initialize "" 1
multiplex_set db main 32768 16
forcedelete test.x
foreach f [glob -nocomplain {test.x*[0-9][0-9][0-9]}] {
forcedelete $f
}
do_test multiplex-2.1.2 {
sqlite3 db test.x
execsql {
@ -192,12 +195,17 @@ do_test multiplex-2.4.2 {
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168}
do_test multiplex-2.4.99 {
do_test multiplex-2.4.5 {
db close
sqlite3 db test.x
db eval vacuum
db close
glob test.x*
} {test.x}
do_test multiplex-2.4.99 {
sqlite3_multiplex_shutdown
} {SQLITE_OK}
do_test multiplex-2.5.1 {
multiplex_delete test.x
sqlite3_multiplex_initialize "" 1

View File

@ -145,7 +145,7 @@ test_suite "valgrind" -prefix "" -description {
Run the "veryquick" test suite with a couple of multi-process tests (that
fail under valgrind) omitted.
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test
] -initialize {
set ::G(valgrind) 1
} -shutdown {
@ -533,6 +533,8 @@ test_suite "inmemory_journal" -description {
# Exclude stmt.test, which expects sub-journals to use temporary files.
stmt.test
zerodamage.test
# WAL mode is different.
wal* tkt-2d1a5c67d.test backcompat.test
}]

View File

@ -19,6 +19,7 @@ source $testdir/tester.tcl
unset -nocomplain baseline
do_test shrink-1.1 {
db eval {
PRAGMA cache_size = 2000;
CREATE TABLE t1(x,y);
INSERT INTO t1 VALUES(randomblob(1000000),1);
}

View File

@ -25,7 +25,7 @@ source $testdir/tester.tcl
if {[sqlite3 -has-codec]} {
set r "sqlite_orig HANDLE FILENAME ?-key CODEC-KEY?"
} else {
set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN?"
set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
}
do_test tcl-1.1 {
set v [catch {sqlite3 bogus} msg]

View File

@ -85,6 +85,7 @@ do_multiclient_test tn {
code1 { db close; sqlite3 db file:test.db?psow=0 -vfs unix-excl -uri 1 }
code2 { db2 close; sqlite3 db2 file:test.db?psow=0 -vfs unix-excl -uri 1 }
sql1 {
PRAGMA auto_vacuum = 0;
PRAGMA journal_mode = WAL;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);

View File

@ -76,7 +76,7 @@ for {set i 1} {$i < $REPEATS} {incr i} {
for {set i 1} {$i < $REPEATS} {incr i} {
forcedelete test.db test.db-wal
do_test walcrash-2.$i.1 {
crashsql -delay 4 -file test.db-wal -seed [incr seed] {
crashsql -delay 5 -file test.db-wal -seed [incr seed] {
PRAGMA journal_mode = WAL;
CREATE TABLE t1(a PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 2);
@ -147,7 +147,7 @@ for {set i 1} {$i < $REPEATS} {incr i} {
forcedelete test2.db test2.db-wal
do_test walcrash-4.$i.1 {
crashsql -delay 3 -file test.db-wal -seed [incr seed] -blocksize 4096 {
crashsql -delay 4 -file test.db-wal -seed [incr seed] -blocksize 4096 {
PRAGMA journal_mode = WAL;
PRAGMA page_size = 1024;
CREATE TABLE t1(a PRIMARY KEY, b);
@ -175,7 +175,7 @@ for {set i 1} {$i < $REPEATS} {incr i} {
forcedelete test2.db test2.db-wal
do_test walcrash-5.$i.1 {
crashsql -delay 11 -file test.db-wal -seed [incr seed] -blocksize 4096 {
crashsql -delay 13 -file test.db-wal -seed [incr seed] -blocksize 4096 {
PRAGMA journal_mode = WAL;
PRAGMA page_size = 1024;
BEGIN;
@ -216,7 +216,7 @@ for {set i 1} {$i < $REPEATS} {incr i} {
forcedelete test2.db test2.db-wal
do_test walcrash-6.$i.1 {
crashsql -delay 12 -file test.db-wal -seed [incr seed] -blocksize 512 {
crashsql -delay 14 -file test.db-wal -seed [incr seed] -blocksize 512 {
PRAGMA journal_mode = WAL;
PRAGMA page_size = 1024;
BEGIN;
@ -234,9 +234,9 @@ for {set i 1} {$i < $REPEATS} {incr i} {
INSERT INTO t1 SELECT randomblob(900) FROM t1 LIMIT 4; /* 32 */
PRAGMA wal_checkpoint;
INSERT INTO t1 VALUES(randomblob(900));
INSERT INTO t1 VALUES(randomblob(900));
INSERT INTO t1 VALUES(randomblob(900));
INSERT INTO t1 VALUES(randomblob(9000));
INSERT INTO t1 VALUES(randomblob(9000));
INSERT INTO t1 VALUES(randomblob(9000));
}
} {1 {child process exited abnormally}}

View File

@ -123,7 +123,6 @@ do_faultsim_test walfault-3 -prep {
faultsim_test_result {0 {}}
}
#--------------------------------------------------------------------------
#
if {[permutation] != "inmemory_journal"} {
@ -141,7 +140,9 @@ if {[permutation] != "inmemory_journal"} {
SELECT * FROM t1;
}
} -test {
faultsim_test_result {0 {wal 0 7 7 a b}}
# Update: The following changed from {0 {wal 0 7 7 a b}} as a result
# of PSOW being set by default.
faultsim_test_result {0 {wal 0 5 5 a b}}
faultsim_integrity_check
}
}
@ -542,10 +543,11 @@ do_faultsim_test walfault-14 -prep {
INSERT INTO abc VALUES(randomblob(1500));
}
} -test {
faultsim_test_result {0 {0 10 10}}
faultsim_test_result {0 {0 9 9}}
faultsim_integrity_check
set nRow [db eval {SELECT count(*) FROM abc}]
if {!(($nRow==2 && $testrc) || $nRow==3)} { error "Bad db content" }
}
finish_test
finish_test

View File

@ -20,6 +20,11 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix wal5
ifcapable !vtab {
finish_test
return
}
# POWERSAFE_OVERWRITE defaults to true
#
do_test zerodamage-1.0 {
@ -110,3 +115,5 @@ do_test zerodamage-3.1 {
}
file size test.db-wal
} {8416}
finish_test

View File

@ -117,8 +117,6 @@ void ResortStates(struct lemon *);
void SetSize(int); /* All sets will be of size N */
char *SetNew(void); /* A new set for element 0..N */
void SetFree(char*); /* Deallocate a set */
char *SetNew(void); /* A new set for element 0..N */
int SetAdd(char*,int); /* Add element to a set */
int SetUnion(char *,char *); /* A <- A U B, thru element N */
#define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
@ -686,8 +684,9 @@ void FindFirstSets(struct lemon *lemp)
for(rp=lemp->rule; rp; rp=rp->next){
if( rp->lhs->lambda ) continue;
for(i=0; i<rp->nrhs; i++){
struct symbol *sp = rp->rhs[i];
if( sp->type!=TERMINAL || sp->lambda==LEMON_FALSE ) break;
struct symbol *sp = rp->rhs[i];
assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE );
if( sp->lambda==LEMON_FALSE ) break;
}
if( i==rp->nrhs ){
rp->lhs->lambda = LEMON_TRUE;
@ -968,7 +967,7 @@ void FindFollowSets(struct lemon *lemp)
}while( progress );
}
static int resolve_conflict(struct action *,struct action *, struct symbol *);
static int resolve_conflict(struct action *,struct action *);
/* Compute the reduce actions, and resolve conflicts.
*/
@ -1022,7 +1021,7 @@ void FindActions(struct lemon *lemp)
for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
/* The two actions "ap" and "nap" have the same lookahead.
** Figure out which one should be used */
lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym);
lemp->nconflict += resolve_conflict(ap,nap);
}
}
}
@ -1057,8 +1056,7 @@ void FindActions(struct lemon *lemp)
*/
static int resolve_conflict(
struct action *apx,
struct action *apy,
struct symbol *errsym /* The error symbol (if defined. NULL otherwise) */
struct action *apy
){
struct symbol *spx, *spy;
int errcnt = 0;
@ -1995,7 +1993,7 @@ static void parseonetoken(struct pstate *psp)
}else if( x[0]=='{' ){
if( psp->prevrule==0 ){
ErrorMsg(psp->filename,psp->tokenlineno,
"There is no prior rule opon which to attach the code \
"There is no prior rule upon which to attach the code \
fragment which begins on this line.");
psp->errorcnt++;
}else if( psp->prevrule->code!=0 ){