Update sessions branch with latest changes from trunk.
FossilOrigin-Name: 01c84fd391a0ca1f5245c7eff0644d0cc6cff86b
This commit is contained in:
commit
af49af7f9e
@ -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
|
||||
|
@ -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;
|
||||
|
83
manifest
83
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
a9bcb432f58b96f079a73c456efd4851c582221e
|
||||
01c84fd391a0ca1f5245c7eff0644d0cc6cff86b
|
@ -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;
|
||||
|
137
src/btree.c
137
src/btree.c
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
14
src/os.c
14
src/os.c
@ -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(
|
||||
|
2
src/os.h
2
src/os.h
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
25
src/os_win.c
25
src/os_win.c
@ -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 ){
|
||||
|
26
src/pager.c
26
src/pager.c
@ -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.
|
||||
|
@ -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).
|
||||
|
@ -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 ){
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
11
src/test2.c
11
src/test2.c
@ -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;
|
||||
|
10
src/test3.c
10
src/test3.c
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_) */
|
||||
|
@ -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)) ){
|
||||
|
@ -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);
|
||||
|
@ -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
150
test/corruptF.test
Normal 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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}]
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
|
@ -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}}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
16
tool/lemon.c
16
tool/lemon.c
@ -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 ){
|
||||
|
Loading…
Reference in New Issue
Block a user