Pull in the patches to support read-only WAL databases into a new branch

off of the apple-osx branch.  This also pulls in all the other pending
3.7.7 changes such as URI support.

FossilOrigin-Name: 97b980107676b2ea45a07c9c1a7de2e1ca74881f
This commit is contained in:
drh
2011-05-12 15:32:51 +00:00
37 changed files with 1835 additions and 247 deletions
+1 -1
View File
@@ -3661,7 +3661,7 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
}
static const sqlite3_module fts3Module = {
/* iVersion */ 1,
/* iVersion */ 2,
/* xCreate */ fts3CreateMethod,
/* xConnect */ fts3ConnectMethod,
/* xBestIndex */ fts3BestIndexMethod,
+44 -37
View File
@@ -1,5 +1,5 @@
C Merge\sthe\slatest\strunk\schanges\sinto\sthe\sapple-osx\sbranch.
D 2011-05-05T15:52:46.864
C Pull\sin\sthe\spatches\sto\ssupport\sread-only\sWAL\sdatabases\sinto\sa\snew\sbranch\noff\sof\sthe\sapple-osx\sbranch.\s\sThis\salso\spulls\sin\sall\sthe\sother\spending\n3.7.7\schanges\ssuch\sas\sURI\ssupport.
D 2011-05-12T15:32:51.588
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 46b5d5017359f89b1aa89ca3581d6ec577738d96
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -61,7 +61,7 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 73d6718dba1e4ef621ff8a4ac1c22019460c84cc
F ext/fts3/fts3.c 0077bd07395d2aabafa1ed1b104552619ecad34a
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 8c2ac39ee17362571c58ab2c4f0667324c31f738
F ext/fts3/fts3_aux.c 9e931f55eed8498dafe7bc1160f10cbb1a652fdf
@@ -120,15 +120,15 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c 280f5c04b11b492703a342222b3de0a999445280
F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a
F src/attach.c 7f97ca76ef2453440170929531a9c778267c0830
F src/attach.c a87bfb77a720f7aa02791434aacfd9bc8feb50cc
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 6a9164af8a2ef4612ee30b253635a9bd8e5e1b1b
F src/btree.h 11753dd46597a20702bca8746cb4caa4486a82b5
F src/btree.c 26f8a9d6169413c5682b89b5397d20437b653154
F src/btree.h d796dc4030b3cce7f5a0cc4f2f986d2befa6b8ac
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
F src/build.c f09c46c66a1e7668c6ee25c9a2518aaa6842044c
F src/build.c 0132bc6631fa617a1d28ef805921f6dbac18a514
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
@@ -138,7 +138,7 @@ F src/expr.c e3cf0957c6b8faaaf7386a3bc69e53c0dc9705be
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c a43ba8a005fb5efd1deeee06853e3a6120d46a91
F src/func.c c02fda657f2366c493198c3e480695fc69972c5f
F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
F src/global.c 29bfb85611dd816b04f10fba0ca910366e128d38
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@@ -147,8 +147,8 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
F src/legacy.c 015826a958f690302d27e096a68d50b3657e4201
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
F src/main.c 3f1e9329c1e689375adf143d4303077d4c14aade
F src/malloc.c 74c740e8ba22b806cfb980c8c0ddea1cbd54a20e
F src/main.c f50e8d60c6ee3c5c1d450e922edb0b1981b76ae8
F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 46095d62b241466ef51970e592aa3a7a87e443e1
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
@@ -166,10 +166,10 @@ F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
F src/os_unix.c b206f9d56b6e3021f195914b63f394d28f23e1cd
F src/os_win.c 4271f0bf733c0b45635ddcfb41c935573de8284c
F src/pager.c 055239dcdfe12b3f5d97f6f01f85da01e2d6d912
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
F src/os_unix.c dabbe23efc9de8fb30caad63f73c88e10ab0499e
F src/os_win.c ff0e14615a5086fa5ba6926e4ec0dc9cfb5a1a84
F src/pager.c 4056376f83f85cea9922a11161087c529e39f7dc
F src/pager.h 34c6b029446f06f40847746d22faac0d354dd909
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
@@ -182,17 +182,17 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
F src/shell.c 72e7e176bf46d5c6518d15ac4ad6847c4bb5df79
F src/sqlite.h.in 9bf19a5dcf6317b0f091c255edaed0b1fc01dcd0
F src/sqlite.h.in adeb2c8019a3851a10e3872f44b34c95c6e409f2
F src/sqlite3_private.h 2a814d17913732831acf13e7e87860105a3416e4
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
F src/sqliteInt.h e70a03bb66d209e279b3edeb57d4fdc42a1d9fda
F src/sqliteInt.h 798fb09648cefc159ac9b3ce5e00f5ada1377ed1
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 501c9a200fd998a268be475be5858febc90b725b
F src/test1.c 89bc831e1d3ecae3d17eac49e9f59e5f84f6f66b
F src/test1.c 77ea7bcaab8656e28acee1cb4e327dd730476fcb
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc
F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
F src/test5.c e1a19845625144caf038031234a12185e40d315c
F src/test6.c c7256cc21d2409486d094277d5b017e8eced44ba
@@ -214,7 +214,7 @@ F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d
F src/test_malloc.c 7ca7be34e0e09ef0ed6619544552ed95732e41f6
F src/test_multiplex.c fdabd793ee7a9642c5a8a470def2347144c46d05
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
@@ -230,7 +230,7 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
F src/test_syscall.c 162c4ec0137a549c009bb9ecab550527743cfc5d
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c 361ae0a0f1cbf5a28ad0388a258b104017a370c0
F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86
F src/test_vfs.c 0ac5b2e3da61bc385c1017890687c359746be2fd
F src/test_vfstrace.c 2265c9895f350c8d3c39b079998fbe7481505cc1
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
@@ -238,9 +238,9 @@ F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
F src/trigger.c 144cc18bb701f3286484aae4292a9531f09278c8
F src/update.c 5bcb56e5c7380a2eecb0e71891dbd4ad7437748f
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
F src/util.c 465fe10aabf0ca7d7826a156dab919b0b65c525a
F src/util.c 914e860d21496b19a912cd14f6f7a889a22f44e1
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
F src/vdbe.c bf969a63096ebf3209963ddf76e085f5465a7dae
F src/vdbe.c ed2668549331d523812ca4b3b6755299d1eb4c43
F src/vdbe.h 8a675fefdf7119441fe817c800a9a52440c2e797
F src/vdbeInt.h fe8f58d305e629fff02f61f655aca1d299f1f6ae
F src/vdbeapi.c 34b6686d9079264bc715f63e41bc2f0d9b98de89
@@ -248,15 +248,15 @@ F src/vdbeaux.c 25aa5ba7d46b4fe7c8f33dc132d474242d5f9726
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
F src/vtab.c 1491acb3e0a67eafe69134fb65bfa0b7b7e82342
F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
F src/vtab.c 48dcef8bc757c2e7b488f68b5ddebb1650da2450
F src/wal.c 6d8ee757f62bca9b0b713724677878dff5bf7e79
F src/wal.h c1e05cdf3d42ed7c9263739ca8f5cdd8761e7de3
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
F test/alter.test 4e47fb9ea59348b88fce4e8bb49de530128b104c
F test/alter.test a3f570072b53d7c0fe463bab3f5affa8e113c487
F test/alter2.test 75f731508f1bf27ba09a6075c66cd02216ba464b
F test/alter3.test 8677e48d95536f7a6ed86a1a774744dadcc22b07
F test/alter4.test 1e5dd6b951e9f65ca66422edff02e56df82dd403
@@ -316,7 +316,7 @@ F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test bea67403a5e37a4b33230ee4723e315a2ffb31e7
F test/capi3d.test cd36571f014f34bdc4421967f6453cbb597d5d16
F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde
F test/cast.test 166951664a0b0a2e0f8fb5997a152490c6363932
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/check.test db2b29d557544347d28e25b8406f5d5ecc3d1bc3
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04
@@ -383,6 +383,7 @@ F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
F test/e_select.test bf385ae3aa0f014c4933ae66fd3e1302138493eb
F test/e_select2.test 5c3d3da19c7b3e90ae444579db2b70098599ab92
F test/e_update.test 963d6876064e65f318d1c93aaed36a02b9b389bf
F test/e_uri.test 9ce11319fb9b271bf7392027f913f7830e93e7a7
F test/e_vacuum.test 6c09c2af7f2f140518f371c5342100118f779dcf
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
@@ -394,7 +395,7 @@ F test/exclusive.test 897074dc6706b0c4f3b1dc4580ffddffe2a79206
F test/exclusive2.test 343d55130c12c67b8bf10407acec043a6c26c86b
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 5e2d64b4eb5a9d08876599bdae2e1213d2d12e2a
F test/expr.test 19e8ac40313e2282a47b586d11c4892040990d3a
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
F test/fallocate.test a9927b638567e2e776c112f54d701402a0e74023
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c
@@ -550,7 +551,7 @@ F test/lock4.test c82268c031d39345d05efa672f80b025481b3ae5
F test/lock5.test d0d313f059ae5661726d3f197ba6ed8f69257d8e
F test/lock6.test 83434ae8ca1d1c5e2eaf74d4e44aa24ab62b291c
F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64
F test/lock_common.tcl d279887a0ab16cdb6d935c1203e64113c5a000e9
F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
F test/lock_proxy.test 95be9c32d79be25cf643b4e41a0aa0e53aa21621
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
F test/main.test 753e2b772c041bd8dbd17c7e4132b3981378eaab
@@ -596,7 +597,7 @@ F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
F test/multiplex.test a88f3e2c16e567e72be7296195c59fbdd6a8d3d4
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723
F test/nan.test dc212a22b36109fd1ae37154292444ef249c5ec2
F test/notify1.test 8433bc74bd952fb8a6e3f8d7a4c2b28dfd69e310
F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
@@ -604,7 +605,7 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
F test/oserror.test 498d8337e9d15543eb7b004fef8594bf204ff43c
F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe
F test/pager1.test 8baf4470b29511503abcaf1f17d16b16462e4d54
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pagerfault.test bea066b9162e1ab6843c2c1524ebb0965715e956
@@ -694,7 +695,7 @@ F test/tclsqlite.test 8c154101e704170c2be10f137a5499ac2c6da8d3
F test/tempdb.test 3263e5c3f0604e54d307481e8587327c54544d18
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
F test/tester.tcl 7fb83d5dd1eff130a0a020d1746f1ccd723c414b
F test/tester.tcl 51d761878d9934e19fc0eda3c9c5dbc39d02522d
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
@@ -806,13 +807,13 @@ F test/tkt3793.test 754b73f0e6a9349c70dc57e522cf3247272ecd5d
F test/tkt3810.test 90fa0635dfa7da9680c8cd3513350a49b3a8ae12
F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
F test/tkt3838.test f956f0719b5f805b12dd1dbf19f19d298bacebc3
F test/tkt3838.test d8490365a1c473d214f7878007e543410cbb715f
F test/tkt3841.test 4659845bc53f809a5932c61c6ce8c5bb9d6b947f
F test/tkt3871.test 43ecbc8d90dc83908e2a454aef345acc9d160c6f
F test/tkt3879.test 2ad5bef2c87e9991ce941e054c31abe26ef7fb90
F test/tkt3911.test 74cd324f3ba653040cc6d94cc4857b290d12d633
F test/tkt3918.test e6cdf6bfcfe9ba939d86a4238a9dc55d6eec5d42
F test/tkt3922.test 022ace32c049e3964f68492c12eb803e8e4856d8
F test/tkt3922.test f26be40ab4fe6c00795629bd2006d96e270d9b1a
F test/tkt3929.test 75a862e45bcb39e9a7944c89b92afa531304afca
F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767
F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
@@ -845,6 +846,7 @@ F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
F test/unixexcl.test 9d80a54d86d2261f660758928959368ffc36151e
F test/unordered.test e81169ce2a8f31b2c6b66af691887e1376ab3ced
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
F test/uri.test 2d08a6f77bf93ca925743a65802c4aa23aaaf373
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test 29b60e8cc9e573b39676df6c4a75fe9e02d04a09
F test/vacuum2.test 91a84c9b08adfc4472097d2e8deb0150214e0e76
@@ -886,6 +888,7 @@ F test/walfault.test 7db81f3dac64ce8897196f199c2909078bcabf8d
F test/walhook.test c934ac5219fee2b4e7653d291db9107b8dc73bba
F test/walmode.test feb39956ec6f415fbb9dcb12d91243391c2c4715
F test/walnoshm.test a074428046408f4eb5c6a00e09df8cc97ff93317
F test/walro.test 1f15853383a976ff8bbec78dd44bc15c4e237392
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test 989854bc5c214700a9f2d545bb158643813b8881
F test/walthread.test e6e32e93ccebfa401dfc0dd930c79daa3472b0ae
@@ -938,7 +941,11 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 289194d68e891e4977407d07e452e48844777a36 930be6a1bdec8c150caafd790973f7a401fc1970
R f9953bf7534b463a52ab1fb53587971d
P f9b149e53815235aaf92f722e37c4819503d72b3 6a2ea52e6c09a570428161090c2f087c66f714ec
R b49a9b1444f8fd9af23f810ca3a9099d
T *bgcolor * #95b28e
T *branch * apple-wal-readonly
T *sym-apple-wal-readonly *
T -sym-apple-osx *
U drh
Z 363d2e190ed85f758bd8ad149ca95188
Z 6c6aea48ffe39f9291f96ce0e3f37ff9
+1 -1
View File
@@ -1 +1 @@
f9b149e53815235aaf92f722e37c4819503d72b3
97b980107676b2ea45a07c9c1a7de2e1ca74881f
+18 -2
View File
@@ -70,8 +70,14 @@ static void attachFunc(
sqlite3 *db = sqlite3_context_db_handle(context);
const char *zName;
const char *zFile;
char *zPath = 0;
char *zErr = 0;
unsigned int flags;
Db *aNew;
char *zErrDyn = 0;
sqlite3_vfs *pVfs;
const char *zVfs = db->pVfs->zName; /* Name of default (main) VFS */
int btflags = 0;
UNUSED_PARAMETER(NotUsed);
@@ -124,8 +130,18 @@ static void attachFunc(
** it to obtain the database schema. At this point the schema may
** or may not be initialised.
*/
rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0,
db->openFlags | SQLITE_OPEN_MAIN_DB);
flags = db->openFlags;
rc = sqlite3ParseUri(zVfs, zFile, &flags, &btflags, &pVfs, &zPath, &zErr);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
sqlite3_result_error(context, zErr, -1);
sqlite3_free(zErr);
return;
}
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, btflags, flags);
sqlite3_free( zPath );
db->nDb++;
if( rc==SQLITE_CONSTRAINT ){
rc = SQLITE_ERROR;
+2 -2
View File
@@ -1688,13 +1688,13 @@ static int btreeInvokeBusyHandler(void *pArg){
** to problems with locking.
*/
int sqlite3BtreeOpen(
sqlite3_vfs *pVfs, /* VFS to use for this b-tree */
const char *zFilename, /* Name of the file containing the BTree database */
sqlite3 *db, /* Associated database handle */
Btree **ppBtree, /* Pointer to new Btree object written here */
int flags, /* Options */
int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */
){
sqlite3_vfs *pVfs; /* The VFS to use for this btree */
BtShared *pBt = 0; /* Shared part of btree structure */
Btree *p; /* Handle to return */
sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */
@@ -1716,6 +1716,7 @@ int sqlite3BtreeOpen(
#endif
assert( db!=0 );
assert( pVfs!=0 );
assert( sqlite3_mutex_held(db->mutex) );
assert( (flags&0xff)==flags ); /* flags fit in 8 bits */
@@ -1734,7 +1735,6 @@ int sqlite3BtreeOpen(
if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
}
pVfs = db->pVfs;
p = sqlite3MallocZero(sizeof(Btree));
if( !p ){
return SQLITE_NOMEM;
+2
View File
@@ -42,6 +42,7 @@ typedef struct BtShared BtShared;
int sqlite3BtreeOpen(
sqlite3_vfs *pVfs, /* VFS to use with this b-tree */
const char *zFilename, /* Name of database file to open */
sqlite3 *db, /* Associated database connection */
Btree **ppBtree, /* Return open Btree* here */
@@ -60,6 +61,7 @@ int sqlite3BtreeOpen(
#define BTREE_MEMORY 4 /* This is an in-memory DB */
#define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */
#define BTREE_READONLYSHM 32 /* Read-only SHM access is acceptable */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
+1 -1
View File
@@ -3443,7 +3443,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TEMP_DB;
rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags);
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
"file for storing temporary tables");
+4 -1
View File
@@ -129,7 +129,9 @@ const unsigned char sqlite3CtypeMap[256] = {
};
#endif
#ifndef SQLITE_USE_URI
# define SQLITE_USE_URI 0
#endif
/*
** The following singleton contains the global configuration for
@@ -139,6 +141,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
1, /* bCoreMutex */
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
0x7ffffffe, /* mxStrlen */
100, /* szLookaside */
500, /* nLookaside */
+269 -15
View File
@@ -429,6 +429,11 @@ int sqlite3_config(int op, ...){
break;
}
case SQLITE_CONFIG_URI: {
sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
break;
}
default: {
rc = SQLITE_ERROR;
break;
@@ -1798,6 +1803,248 @@ static void profile_sql(void *aux, const char *sql, u64 ns) {
}
#endif
/*
** This function is used to parse both URIs and non-URI filenames passed by the
** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
** URIs specified as part of ATTACH statements.
**
** The first argument to this function is the name of the VFS to use (or
** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
** query parameter. The second argument contains the URI (or non-URI filename)
** itself. When this function is called the *pFlags variable should contain
** the default flags to open the database handle with. The value stored in
** *pFlags may be updated before returning if the URI filename contains
** "cache=xxx" or "mode=xxx" query parameters.
**
** The third argument, pBtflags, points to an integer containing the flags
** that will be passed as the 5th argument to sqlite3BtreeOpen (BTREE_XXX
** flags). This value will be edited if the URI filename contains a
** "readonly_shm=1" or "readonly_shm=0" query parameter.
**
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
** the VFS that should be used to open the database file. *pzFile is set to
** point to a buffer containing the name of the file to open. It is the
** responsibility of the caller to eventually call sqlite3_free() to release
** this buffer.
**
** If an error occurs, then an SQLite error code is returned and *pzErrMsg
** may be set to point to a buffer containing an English language error
** message. It is the responsibility of the caller to eventually release
** this buffer by calling sqlite3_free().
*/
int sqlite3ParseUri(
const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
const char *zUri, /* Nul-terminated URI to parse */
unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */
int *pBtflags, /* IN/OUT: BTREE_XXX flags */
sqlite3_vfs **ppVfs, /* OUT: VFS to use */
char **pzFile, /* OUT: Filename component of URI */
char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
){
int rc = SQLITE_OK;
unsigned int flags = *pFlags;
const char *zVfs = zDefaultVfs;
char *zFile;
char c;
int nUri = sqlite3Strlen30(zUri);
assert( *pzErrMsg==0 );
if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
&& nUri>=5 && memcmp(zUri, "file:", 5)==0
){
char *zOpt;
int eState; /* Parser state when parsing URI */
int iIn; /* Input character index */
int iOut = 0; /* Output character index */
int nByte = nUri+2; /* Bytes of space to allocate */
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
** method that there may be extra parameters following the file-name. */
flags |= SQLITE_OPEN_URI;
for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
zFile = sqlite3_malloc(nByte);
if( !zFile ) return SQLITE_NOMEM;
/* Discard the scheme and authority segments of the URI. */
if( zUri[5]=='/' && zUri[6]=='/' ){
iIn = 7;
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
*pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
iIn-7, &zUri[7]);
rc = SQLITE_ERROR;
goto parse_uri_out;
}
}else{
iIn = 5;
}
/* Copy the filename and any query parameters into the zFile buffer.
** Decode %HH escape codes along the way.
**
** Within this loop, variable eState may be set to 0, 1 or 2, depending
** on the parsing context. As follows:
**
** 0: Parsing file-name.
** 1: Parsing name section of a name=value query parameter.
** 2: Parsing value section of a name=value query parameter.
*/
eState = 0;
while( (c = zUri[iIn])!=0 && c!='#' ){
iIn++;
if( c=='%'
&& sqlite3Isxdigit(zUri[iIn])
&& sqlite3Isxdigit(zUri[iIn+1])
){
int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
octet += sqlite3HexToInt(zUri[iIn++]);
assert( octet>=0 && octet<256 );
if( octet==0 ){
/* This branch is taken when "%00" appears within the URI. In this
** case we ignore all text in the remainder of the path, name or
** value currently being parsed. So ignore the current character
** and skip to the next "?", "=" or "&", as appropriate. */
while( (c = zUri[iIn])!=0 && c!='#'
&& (eState!=0 || c!='?')
&& (eState!=1 || (c!='=' && c!='&'))
&& (eState!=2 || c!='&')
){
iIn++;
}
continue;
}
c = octet;
}else if( eState==1 && (c=='&' || c=='=') ){
if( zFile[iOut-1]==0 ){
/* An empty option name. Ignore this option altogether. */
while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
continue;
}
if( c=='&' ){
zFile[iOut++] = '\0';
}else{
eState = 2;
}
c = 0;
}else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
c = 0;
eState = 1;
}
zFile[iOut++] = c;
}
if( eState==1 ) zFile[iOut++] = '\0';
zFile[iOut++] = '\0';
zFile[iOut++] = '\0';
/* Check if there were any options specified that should be interpreted
** here. Options that are interpreted here include "vfs" and those that
** correspond to flags that may be passed to the sqlite3_open_v2()
** method. */
zOpt = &zFile[sqlite3Strlen30(zFile)+1];
while( zOpt[0] ){
int nOpt = sqlite3Strlen30(zOpt);
char *zVal = &zOpt[nOpt+1];
int nVal = sqlite3Strlen30(zVal);
if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
zVfs = zVal;
}else if( nOpt==12 && memcmp("readonly_shm", zOpt, 12)==0 ){
if( sqlite3Atoi(zVal) ){
*pBtflags |= BTREE_READONLYSHM;
}else{
*pBtflags &= ~BTREE_READONLYSHM;
}
}else{
struct OpenMode {
const char *z;
int mode;
} *aMode = 0;
char *zModeType;
int mask;
int limit;
if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
static struct OpenMode aCacheMode[] = {
{ "shared", SQLITE_OPEN_SHAREDCACHE },
{ "private", SQLITE_OPEN_PRIVATECACHE },
{ 0, 0 }
};
mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
aMode = aCacheMode;
limit = mask;
zModeType = "cache";
}
if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
static struct OpenMode aOpenMode[] = {
{ "ro", SQLITE_OPEN_READONLY },
{ "rw", SQLITE_OPEN_READWRITE },
{ "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
{ 0, 0 }
};
mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
aMode = aOpenMode;
limit = mask & flags;
zModeType = "access";
}
if( aMode ){
int i;
int mode = 0;
for(i=0; aMode[i].z; i++){
const char *z = aMode[i].z;
if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
mode = aMode[i].mode;
break;
}
}
if( mode==0 ){
*pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
rc = SQLITE_ERROR;
goto parse_uri_out;
}
if( mode>limit ){
*pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
zModeType, zVal);
rc = SQLITE_PERM;
goto parse_uri_out;
}
flags = (flags & ~mask) | mode;
}
}
zOpt = &zVal[nVal+1];
}
}else{
zFile = sqlite3_malloc(nUri+2);
if( !zFile ) return SQLITE_NOMEM;
memcpy(zFile, zUri, nUri);
zFile[nUri] = '\0';
zFile[nUri+1] = '\0';
}
*ppVfs = sqlite3_vfs_find(zVfs);
if( *ppVfs==0 ){
*pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
rc = SQLITE_ERROR;
}
parse_uri_out:
if( rc!=SQLITE_OK ){
sqlite3_free(zFile);
zFile = 0;
}
*pFlags = flags;
*pzFile = zFile;
return rc;
}
/*
** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
@@ -1806,12 +2053,15 @@ static void profile_sql(void *aux, const char *sql, u64 ns) {
static int openDatabase(
const char *zFilename, /* Database filename UTF-8 encoded */
sqlite3 **ppDb, /* OUT: Returned database handle */
unsigned flags, /* Operational flags */
unsigned int flags, /* Operational flags */
const char *zVfs /* Name of the VFS to use */
){
sqlite3 *db;
int rc;
int isThreadsafe;
sqlite3 *db; /* Store allocated handle here */
int rc; /* Return code */
int isThreadsafe; /* True for threadsafe connections */
char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
int btflags = 0; /* Mask of BTREE_XXX flags */
*ppDb = 0;
#ifndef SQLITE_OMIT_AUTOINIT
@@ -1835,7 +2085,7 @@ static int openDatabase(
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE;
if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;
if( sqlite3GlobalConfig.bCoreMutex==0 ){
isThreadsafe = 0;
@@ -1916,13 +2166,6 @@ static int openDatabase(
sqlite3HashInit(&db->aModule);
#endif
db->pVfs = sqlite3_vfs_find(zVfs);
if( !db->pVfs ){
rc = SQLITE_ERROR;
sqlite3Error(db, rc, "no such vfs: %s", zVfs);
goto opendb_out;
}
/* Add the default collation sequence BINARY. BINARY works for both UTF-8
** and UTF-16, so add a version for each to avoid any unnecessary
** conversions. The only error that can occur here is a malloc() failure.
@@ -1945,9 +2188,19 @@ static int openDatabase(
createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
nocaseCollatingFunc, 0);
/* Open the backend database driver */
/* Parse the filename/URI argument. */
db->openFlags = flags;
rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0,
rc = sqlite3ParseUri(
zVfs, zFilename, &flags, &btflags, &db->pVfs, &zOpen, &zErrMsg);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
sqlite3_free(zErrMsg);
goto opendb_out;
}
/* Open the backend database driver */
rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, btflags,
flags | SQLITE_OPEN_MAIN_DB);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_IOERR_NOMEM ){
@@ -2040,6 +2293,7 @@ static int openDatabase(
sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
opendb_out:
sqlite3_free(zOpen);
if( db ){
assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
sqlite3_mutex_leave(db->mutex);
@@ -2083,7 +2337,7 @@ int sqlite3_open_v2(
int flags, /* Flags */
const char *zVfs /* Name of VFS module to use */
){
return openDatabase(filename, ppDb, flags, zVfs);
return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
}
#ifndef SQLITE_OMIT_UTF16
+2 -2
View File
@@ -533,7 +533,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
nDiff = nNew - nOld;
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nNew-nOld);
sqlite3MallocAlarm(nDiff);
}
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
@@ -544,7 +544,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
}
if( pNew ){
nNew = sqlite3MallocSize(pNew);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nDiff);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
}
sqlite3_mutex_leave(mem0.mutex);
}else{
+38 -13
View File
@@ -212,6 +212,7 @@ struct unixFile {
UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
int readOnlyShm; /* True to open shared-memory read-only */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
@@ -3473,6 +3474,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
case SQLITE_FCNTL_SIZE_HINT: {
return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
}
case SQLITE_FCNTL_READONLY_SHM: {
((unixFile*)id)->readOnlyShm = (pArg!=0);
return SQLITE_OK;
}
#ifndef NDEBUG
/* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and
@@ -3775,6 +3780,7 @@ struct unixShmNode {
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
u8 readOnly; /* True if this is a read-only mapping */
#ifdef SQLITE_DEBUG
u8 exclMask; /* Mask of exclusive locks held */
u8 sharedMask; /* Mask of shared locks held */
@@ -4031,29 +4037,48 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
}
if( pInode->bProcessLock==0 ){
pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
(sStat.st_mode & 0777));
int flags = (pDbFd->readOnlyShm ? O_RDONLY : O_RDWR|O_CREAT);
pShmNode->h = robust_open(zShmFilename, flags, (sStat.st_mode & 0777));
if( pShmNode->h<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
goto shm_open_err;
}
pShmNode->readOnly = pDbFd->readOnlyShm;
/* Check to see if another process is holding the dead-man switch.
** If not, truncate the file to zero length.
*/
rc = SQLITE_OK;
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
if( robust_ftruncate(pShmNode->h, 0) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
** If not, zero the first few bytes of the shared-memory file to make
** sure it is not mistaken for valid by code in wal.c. Except, if this
** is a read-only connection to the shared-memory then it is not possible
** to check check if another process is holding a read-lock on the DMS
** byte, as we cannot attempt a write-lock via a read-only file
** descriptor. So in this case, we just assume the shared-memory
** contents are Ok and proceed. */
if( pShmNode->readOnly==0 ){
rc = SQLITE_OK;
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
if( pDbFd->readOnlyShm ){
rc = SQLITE_IOERR_SHMOPEN;
}else if( 4!=osWrite(pShmNode->h, "\00\00\00\00", 4) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
}
}
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
}
if( rc ) goto shm_open_err;
}
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
}
if( rc ) goto shm_open_err;
}
}
/* If the unixShmNode is read-only, but SQLITE_FCNTL_READONLY_SHM has not
** been set for file-descriptor pDbFd, return an error. The wal.c module
** will then call this function again with SQLITE_FCNTL_READONLY_SHM set.
*/
else if( pShmNode->readOnly && !pDbFd->readOnlyShm ){
rc = SQLITE_IOERR_SHMOPEN;
goto shm_open_err;
}
/* Make the new connection a child of the unixShmNode */
p->pShmNode = pShmNode;
#ifdef SQLITE_DEBUG
@@ -4174,7 +4199,7 @@ static int unixShmMap(
while(pShmNode->nRegion<=iRegion){
void *pMem;
if( pShmNode->h>=0 ){
pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
pMem = mmap(0, szRegion, PROT_READ|(!pShmNode->readOnly?PROT_WRITE:0),
MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
);
if( pMem==MAP_FAILED ){
+7
View File
@@ -2465,6 +2465,13 @@ static int winFullPathname(
void *zConverted;
char *zOut;
/* If this path name begins with "/X:", where "X" is any alphabetic
** character, discard the initial "/" from the pathname.
*/
if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
zRelative++;
}
/* 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
** function failing. This function could fail if, for example, the
+17 -4
View File
@@ -620,6 +620,7 @@ struct Pager {
u8 tempFile; /* zFilename is a temporary file */
u8 readOnly; /* True for a read-only database */
u8 memDb; /* True to inhibit all file I/O */
u8 readOnlyShm; /* True if read-only shm access is Ok */
/**************************************************************************
** The following block contains those class members that change during
@@ -3017,6 +3018,7 @@ static int pagerWalFrames(
static int pagerBeginReadTransaction(Pager *pPager){
int rc; /* Return code */
int changed = 0; /* True if cache must be reset */
Wal *pWal = pPager->pWal;
assert( pagerUseWal(pPager) );
assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
@@ -3026,9 +3028,9 @@ static int pagerBeginReadTransaction(Pager *pPager){
** are in locking_mode=NORMAL and EndRead() was previously called,
** the duplicate call is harmless.
*/
sqlite3WalEndReadTransaction(pPager->pWal);
sqlite3WalEndReadTransaction(pWal);
rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
rc = sqlite3WalBeginReadTransaction(pWal, pPager->readOnlyShm, &changed);
if( rc!=SQLITE_OK || changed ){
pager_reset(pPager);
}
@@ -4299,6 +4301,8 @@ int sqlite3PagerOpen(
int noReadlock = (flags & PAGER_NO_READLOCK)!=0; /* True to omit read-lock */
int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
const char *zUri = 0; /* URI args to copy */
int nUri = 0; /* Number of bytes of URI args at *zUri */
/* Figure out how much space is required for each journal file-handle
** (there are two of them, the main journal and the sub-journal). This
@@ -4329,6 +4333,7 @@ int sqlite3PagerOpen(
** leave both nPathname and zPathname set to 0.
*/
if( zFilename && zFilename[0] ){
const char *z;
nPathname = pVfs->mxPathname+1;
zPathname = sqlite3Malloc(nPathname*2);
if( zPathname==0 ){
@@ -4337,6 +4342,12 @@ int sqlite3PagerOpen(
zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
nPathname = sqlite3Strlen30(zPathname);
z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
while( *z ){
z += sqlite3Strlen30(z)+1;
z += sqlite3Strlen30(z)+1;
}
nUri = &z[1] - zUri;
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
/* This branch is taken when the journal path required by
** the database being opened will be more than pVfs->mxPathname
@@ -4369,7 +4380,7 @@ int sqlite3PagerOpen(
ROUND8(pcacheSize) + /* PCache object */
ROUND8(pVfs->szOsFile) + /* The main db file */
journalFileSize * 2 + /* The two journal files */
nPathname + 1 + /* zFilename */
nPathname + 1 + nUri + /* zFilename */
nPathname + 8 + 1 /* zJournal */
#ifndef SQLITE_OMIT_WAL
+ nPathname + 4 + 1 /* zWal */
@@ -4391,8 +4402,9 @@ int sqlite3PagerOpen(
/* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
if( zPathname ){
assert( nPathname>0 );
pPager->zJournal = (char*)(pPtr += nPathname + 1);
pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
memcpy(pPager->zFilename, zPathname, nPathname);
memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
memcpy(pPager->zJournal, zPathname, nPathname);
memcpy(&pPager->zJournal[nPathname], "-journal", 8);
#ifndef SQLITE_OMIT_WAL
@@ -4404,6 +4416,7 @@ int sqlite3PagerOpen(
}
pPager->pVfs = pVfs;
pPager->vfsFlags = vfsFlags;
pPager->readOnlyShm = (flags & PAGER_READONLYSHM)!=0;
/* Open the pager file.
*/
+1
View File
@@ -60,6 +60,7 @@ typedef struct PgHdr DbPage;
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
#define PAGER_MEMORY 0x0004 /* In-memory database */
#define PAGER_READONLYSHM 0x0020 /* Read-only SHM access is acceptable */
/*
** Valid values for the second argument to sqlite3PagerLockingMode().
+185 -35
View File
@@ -454,6 +454,9 @@ int sqlite3_exec(
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
/*
** CAPI3REF: Flags For File Open Operations
**
@@ -480,6 +483,7 @@ int sqlite3_exec(
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
#define SQLITE_OPEN_URI 0x00100000 /* Ok for sqlite3_open_v2() */
/* Reserved: 0x00F00000 */
@@ -732,6 +736,27 @@ struct sqlite3_io_methods {
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.
**
** The [SQLITE_FCNTL_READONLY_SHM] may be generated internally by SQLite if
** the "readonly_shm=1" URI option is specified when the database is opened.
** The fourth argument passed to the VFS xFileControl methods is a pointer
** to a variable of type "int" containing the value 1 or 0. If the variable
** contains the value 1, then this indicates to the VFS that a read-only
** mapping of the shared-memory region is acceptable. If it is set to 0, then
** this indicates that a read-write mapping is required (as normal). If
** a read-only mapping is returned, then the VFS may also return read-only
** mappings for any subsequent requests via the same file-descriptor -
** regardless of the value most recently configured using
** SQLITE_FCNTL_READONLY_SHM.
**
** In practice, if "readonly_shm=1" is specified and the first attempt to
** map a shared-memory region fails, then this file-control is invoked with
** the argument variable set to 1 and a second attempt to map the shared-memory
** region is made. If this mapping succeeds, then the connection continues
** with the read-only mapping. Otherwise, if it fails, SQLITE_CANTOPEN is
** returned to the caller. Whether or not the second (read-only) mapping
** attempt succeeds, the file-control is invoked again with the argument
** variable set to 0.
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_GET_LOCKPROXYFILE 2
@@ -741,6 +766,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CHUNK_SIZE 6
#define SQLITE_FCNTL_FILE_POINTER 7
#define SQLITE_FCNTL_SYNC_OMITTED 8
#define SQLITE_FCNTL_READONLY_SHM 9
/*
@@ -757,6 +783,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
/*
** CAPI3REF: OS Interface Object
** KEYWORDS: VFS VFSes
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system. The "vfs"
@@ -1427,6 +1454,18 @@ struct sqlite3_mem_methods {
** In a multi-threaded application, the application-defined logger
** function must be threadsafe. </dd>
**
** <dt>SQLITE_CONFIG_URI
** <dd> This option takes a single argument of type int. If non-zero, then
** URI handling is globally enabled. If the parameter is zero, then URI handling
** is globally disabled. If URI handling is globally enabled, all filenames
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
** connection is opened. If it is globally disabled, filenames are
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
** database connection is opened. By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -1445,6 +1484,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
#define SQLITE_CONFIG_URI 17 /* int */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -2324,7 +2364,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
/*
** CAPI3REF: Opening A New Database Connection
**
** ^These routines open an SQLite database file whose name is given by the
** ^These routines open an SQLite database file as specified by the
** filename argument. ^The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
** order for sqlite3_open16(). ^(A [database connection] handle is usually
@@ -2387,6 +2427,11 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
** participate in [shared cache mode] even if it is enabled.
**
** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use. ^If the fourth parameter is
** a NULL pointer then the default [sqlite3_vfs] object is used.
**
** ^If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection. ^This in-memory database will vanish when
** the database connection is closed. Future versions of SQLite might
@@ -2399,10 +2444,116 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** on-disk database will be created. ^This private database will be
** automatically deleted as soon as the database connection is closed.
**
** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use. ^If the fourth parameter is
** a NULL pointer then the default [sqlite3_vfs] object is used.
** ^If URI filename interpretation is enabled, and the filename argument
** begins with "file:", then the filename is interpreted as a URI. ^URI
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
** is set in the fourth argument to sqlite3_open_v2(), or if it has
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
** [sqlite3_config()] method.
**
** URI filenames are parsed according to RFC 1738. If the URI contains an
** 'authority', then it must be either an empty string or the string
** "localhost". ^If the authority is not an empty string or "localhost", an
** error is returned to the caller. ^The 'fragment' component of a URI, if
** present, is always ignored.
**
** ^SQLite uses the 'path' component of the URI as the path to the database file
** to open. ^If the path begins with a '/' character, then it is interpreted as
** an absolute path. ^If it does not begin with a '/', it is interpreted as a
** relative path. ^On windows, the first component of an absolute path
** is a drive specification (e.g. "C:").
**
** The query component of a URI may contain parameters that are interpreted
** either by SQLite itself, or by a [sqlite3_vfs | custom VFS implementation].
** SQLite interprets the following four query parameters:
**
** <ul>
** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
** a VFS object that provides the operating system interface that should
** be used to access the database file on disk. ^If this option is set to
** an empty string the default VFS object is used. ^Specifying an unknown
** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
** present, then the VFS specified by the option takes precedence over
** the value passed as the fourth parameter to sqlite3_open_v2().
**
** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
** "rwc". Attempting to set it to any other value is an error)^.
** ^If "ro" is specified, then the database is opened for read-only
** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
** "rw", then the database is opened for read-write (but not create)
** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
** been set. ^Value "rwc" is equivalent to setting both
** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
** used, it is an error to specify a value for the mode parameter that is
** less restrictive than that specified by the flags passed as the third
** parameter.
**
** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
** "private". ^Setting it to "shared" is equivalent to setting the
** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behaviour requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
** <li> <b>readonly_shm</b>: ^The readonly_shm parameter may be set to
** either "1" or "0". Setting it to "1" indicates that if the database
** is in WAL mode and read-write access to the associated shared
** memory region cannot be obtained, then an attempt should be made to open
** the shared-memory in read-only mode instead. If there exist one or
** more other database clients that have read-write connections to the
** database shared-memory, then a read-only shared-memory connection works
** fine. However, if there exist no clients with read-write connections
** to the shared-memory and the most recent such crashed or was interrupted
** by a power failure, then it is possible for a database client using a
** read-only connection to return incorrect data, incorrectly report
** database corruption, or return an SQLITE_READONLY error. Or if the
** most recent read-write connection shut down cleanly, it may not be
** possible to open the shared-memory in read-only mode at all, and SQLite
** will return SQLITE_CANTOPEN.
** </ul>
**
** ^Specifying an unknown parameter in the query component of a URI is not an
** error.
**
** URI filename examples:
**
** <table border="1" align=center cellpadding=5>
** <tr><th> URI filenames <th> Results
** <tr><td> file:data.db <td>
** Open the file "data.db" in the current directory.
** <tr><td> file:/home/fred/data.db<br>
** file:///home/fred/data.db <br>
** file://localhost/home/fred/data.db <br> <td>
** Open the database file "/home/fred/data.db".
** <tr><td> file://darkstar/home/fred/data.db <td>
** An error. "darkstar" is not a recognized authority.
** <tr><td style="white-space:nowrap">
** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
** <td> Windows only: Open the file "data.db" on fred's desktop on drive
** C:. Note that the %20 escaping in this example is not strictly
** necessary - space characters can be used literally
** in URI filenames.
** <tr><td> file:data.db?mode=ro&cache=private <td>
** Open file "data.db" in the current directory for read-only access.
** Regardless of whether or not shared-cache mode is enabled by
** default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
** query components of a URI. A hexadecimal escape sequence consists of a
** percent sign - "%" - followed by exactly two hexadecimal digits
** specifying an octet value. ^Before the path or query components of a
** URI filename are interpreted, they are encoded using UTF-8 and all
** hexadecimal escape sequences replaced by a single byte containing the
** corresponding octet. If this process generates an invalid UTF-8 encoding,
** the results are undefined.
**
** <b>Note to Windows users:</b> The encoding used for the filename argument
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
@@ -4611,8 +4762,8 @@ struct sqlite3_module {
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg);
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
/* The methods above are in version 0 of the sqlite_module object. Those
** below are for version 1 and greater. */
/* The methods above are in version 1 of the sqlite_module object. Those
** below are for version 2 and greater. */
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
@@ -6425,37 +6576,36 @@ int sqlite3_vtab_config(sqlite3*, int op, ...);
** can use to customize and optimize their behavior.
**
** <dl>
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>If the second argument to [sqlite3_vtab_config()] is
** SQLITE_VTAB_CONSTRAINT_SUPPORT, then SQLite expects this function to
** have been called with three arguments, the third of which being of
** type 'int'. If the third argument is zero, then the virtual table
** is indicating that it does not support constraints. In this case if
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], the entire
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
** specified as part of the users SQL statement, regardless of the actual
** ON CONFLICT mode specified.
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
** where X is an integer. If X is zero, then the [virtual table] whose
** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
** support constraints. In this configuration (which is the default) if
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
** specified as part of the users SQL statement, regardless of the actual
** ON CONFLICT mode specified.
**
** If the third argument passed is non-zero, then the virtual table
** implementation must guarantee that if [xUpdate] returns
** [SQLITE_CONSTRAINT], it does so before any modifications to internal
** or persistent data structures have been made. If the [ON CONFLICT]
** mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite is able to roll back
** a statement or database transaction, and abandon or continue processing
** the current SQL statement as appropriate. If the ON CONFLICT mode is
** REPLACE and the [xUpdate] method returns [SQLITE_CONSTRAINT], SQLite
** handles this as if the ON CONFLICT mode had been ABORT.
** If X is non-zero, then the virtual table implementation guarantees
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
** any modifications to internal or persistent data structures have been made.
** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
** is able to roll back a statement or database transaction, and abandon
** or continue processing the current SQL statement as appropriate.
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
** had been ABORT.
**
** Virtual table implementations that are required to handle OR REPLACE
** must do so within the xUpdate method. If a call to the
** [sqlite3_vtab_on_conflict()] function indicates that the current ON
** CONFLICT policy is REPLACE, the virtual table implementation should
** silently replace the appropriate rows within the xUpdate callback and
** return SQLITE_OK. Or, if this is not possible, it may return
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
** constraint handling.
** Virtual table implementations that are required to handle OR REPLACE
** must do so within the [xUpdate] method. If a call to the
** [sqlite3_vtab_on_conflict()] function indicates that the current ON
** CONFLICT policy is REPLACE, the virtual table implementation should
** silently replace the appropriate rows within the xUpdate callback and
** return SQLITE_OK. Or, if this is not possible, it may return
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
** constraint handling.
** </dl>
**
*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+5 -1
View File
@@ -803,7 +803,7 @@ struct sqlite3 {
int nDb; /* Number of backends currently in use */
Db *aDb; /* All backends */
int flags; /* Miscellaneous flags. See below */
int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
u8 autoCommit; /* The auto-commit flag. */
@@ -2423,6 +2423,7 @@ struct Sqlite3Config {
int bMemstat; /* True to enable memory status */
int bCoreMutex; /* True to enable core mutexing */
int bFullMutex; /* True to enable full mutexing */
int bOpenUri; /* True to interpret filenames as URIs */
int mxStrlen; /* Maximum string length */
int szLookaside; /* Default lookaside buffer size */
int nLookaside; /* Default lookaside buffer count */
@@ -2672,6 +2673,8 @@ void sqlite3AddColumnType(Parse*,Token*);
void sqlite3AddDefaultValue(Parse*,ExprSpan*);
void sqlite3AddCollateType(Parse*, Token*);
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
int sqlite3ParseUri(const char*,const char*,unsigned int*,int*,
sqlite3_vfs**,char**,char **);
Bitvec *sqlite3BitvecCreate(u32);
int sqlite3BitvecTest(Bitvec*, u32);
@@ -2922,6 +2925,7 @@ char sqlite3ExprAffinity(Expr *pExpr);
int sqlite3Atoi64(const char*, i64*, int, u8);
void sqlite3Error(sqlite3*, int, const char*,...);
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
u8 sqlite3HexToInt(int h);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
+74
View File
@@ -163,6 +163,9 @@ const char *sqlite3TestErrorName(int rc){
case SQLITE_IOERR_CHECKRESERVEDLOCK:
zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break;
case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break;
default: zName = "SQLITE_Unknown"; break;
}
return zName;
@@ -3863,6 +3866,76 @@ static int test_open(
return TCL_OK;
}
/*
** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
*/
static int test_open_v2(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
const char *zFilename;
const char *zVfs;
int flags = 0;
sqlite3 *db;
int rc;
char zBuf[100];
int nFlag;
Tcl_Obj **apFlag;
int i;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
return TCL_ERROR;
}
zFilename = Tcl_GetString(objv[1]);
zVfs = Tcl_GetString(objv[3]);
if( zVfs[0]==0x00 ) zVfs = 0;
rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
if( rc!=TCL_OK ) return rc;
for(i=0; i<nFlag; i++){
int iFlag;
struct OpenFlag {
const char *zFlag;
int flag;
} aFlag[] = {
{ "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
{ "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
{ "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
{ "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
{ "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
{ "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
{ "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
{ "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
{ "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
{ "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
{ "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
{ "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
{ "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
{ "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
{ "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
{ "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
{ "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
{ "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
{ "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
{ 0, 0 }
};
rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
"flag", 0, &iFlag
);
if( rc!=TCL_OK ) return rc;
flags |= aFlag[iFlag].flag;
}
rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
/*
** Usage: sqlite3_open16 filename options
*/
@@ -5703,6 +5776,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_errmsg16", test_errmsg16 ,0 },
{ "sqlite3_open", test_open ,0 },
{ "sqlite3_open16", test_open16 ,0 },
{ "sqlite3_open_v2", test_open_v2 ,0 },
{ "sqlite3_complete16", test_complete16 ,0 },
{ "sqlite3_prepare", test_prepare ,0 },
+1 -1
View File
@@ -78,7 +78,7 @@ static int btree_open(
sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
sqlite3_mutex_enter(sDb.mutex);
}
rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, 0,
rc = sqlite3BtreeOpen(sDb.pVfs, argv[1], &sDb, &pBt, 0,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
+30
View File
@@ -1174,6 +1174,35 @@ static int test_config_error(
return TCL_OK;
}
/*
** tclcmd: sqlite3_config_uri BOOLEAN
**
** Invoke sqlite3_config() or sqlite3_db_config() with invalid
** opcodes and verify that they return errors.
*/
static int test_config_uri(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
int rc;
int bOpenUri;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
return TCL_ERROR;
}
if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
return TCL_ERROR;
}
rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
return TCL_OK;
}
/*
** Usage:
**
@@ -1422,6 +1451,7 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
{ "sqlite3_config_memstatus", test_config_memstatus ,0 },
{ "sqlite3_config_lookaside", test_config_lookaside ,0 },
{ "sqlite3_config_error", test_config_error ,0 },
{ "sqlite3_config_uri", test_config_uri ,0 },
{ "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
{ "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
{ "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
+49 -27
View File
@@ -114,20 +114,21 @@ struct Testvfs {
** + Simulating IO errors, and
** + Invoking the Tcl callback script.
*/
#define TESTVFS_SHMOPEN_MASK 0x00000001
#define TESTVFS_SHMLOCK_MASK 0x00000010
#define TESTVFS_SHMMAP_MASK 0x00000020
#define TESTVFS_SHMBARRIER_MASK 0x00000040
#define TESTVFS_SHMCLOSE_MASK 0x00000080
#define TESTVFS_SHMOPEN_MASK 0x00000001
#define TESTVFS_SHMLOCK_MASK 0x00000010
#define TESTVFS_SHMMAP_MASK 0x00000020
#define TESTVFS_SHMBARRIER_MASK 0x00000040
#define TESTVFS_SHMCLOSE_MASK 0x00000080
#define TESTVFS_OPEN_MASK 0x00000100
#define TESTVFS_SYNC_MASK 0x00000200
#define TESTVFS_DELETE_MASK 0x00000400
#define TESTVFS_CLOSE_MASK 0x00000800
#define TESTVFS_WRITE_MASK 0x00001000
#define TESTVFS_TRUNCATE_MASK 0x00002000
#define TESTVFS_ACCESS_MASK 0x00004000
#define TESTVFS_ALL_MASK 0x00007FFF
#define TESTVFS_OPEN_MASK 0x00000100
#define TESTVFS_SYNC_MASK 0x00000200
#define TESTVFS_DELETE_MASK 0x00000400
#define TESTVFS_CLOSE_MASK 0x00000800
#define TESTVFS_WRITE_MASK 0x00001000
#define TESTVFS_TRUNCATE_MASK 0x00002000
#define TESTVFS_ACCESS_MASK 0x00004000
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
#define TESTVFS_ALL_MASK 0x0001FFFF
#define TESTVFS_MAX_PAGES 1024
@@ -545,7 +546,7 @@ static int tvfsOpen(
/* Evaluate the Tcl script:
**
** SCRIPT xOpen FILENAME
** SCRIPT xOpen FILENAME KEY-VALUE-ARGS
**
** If the script returns an SQLite error code other than SQLITE_OK, an
** error is returned to the caller. If it returns SQLITE_OK, the new
@@ -554,7 +555,19 @@ static int tvfsOpen(
*/
Tcl_ResetResult(p->interp);
if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){
tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
Tcl_Obj *pArg = Tcl_NewObj();
Tcl_IncrRefCount(pArg);
if( flags&SQLITE_OPEN_MAIN_DB ){
const char *z = &zName[strlen(zName)+1];
while( *z ){
Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
z += strlen(z) + 1;
Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
z += strlen(z) + 1;
}
}
tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0);
Tcl_DecrRefCount(pArg);
if( tvfsResultCode(p, &rc) ){
if( rc!=SQLITE_OK ) return rc;
}else{
@@ -663,6 +676,14 @@ static int tvfsFullPathname(
int nOut,
char *zOut
){
Testvfs *p = (Testvfs *)pVfs->pAppData;
if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
int rc;
tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0);
if( tvfsResultCode(p, &rc) ){
if( rc!=SQLITE_OK ) return rc;
}
}
return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
}
@@ -1028,18 +1049,19 @@ static int testvfs_obj_cmd(
char *zName;
int mask;
} vfsmethod [] = {
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
{ "xShmMap", TESTVFS_SHMMAP_MASK },
{ "xSync", TESTVFS_SYNC_MASK },
{ "xDelete", TESTVFS_DELETE_MASK },
{ "xWrite", TESTVFS_WRITE_MASK },
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
{ "xOpen", TESTVFS_OPEN_MASK },
{ "xClose", TESTVFS_CLOSE_MASK },
{ "xAccess", TESTVFS_ACCESS_MASK },
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
{ "xShmMap", TESTVFS_SHMMAP_MASK },
{ "xSync", TESTVFS_SYNC_MASK },
{ "xDelete", TESTVFS_DELETE_MASK },
{ "xWrite", TESTVFS_WRITE_MASK },
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
{ "xOpen", TESTVFS_OPEN_MASK },
{ "xClose", TESTVFS_CLOSE_MASK },
{ "xAccess", TESTVFS_ACCESS_MASK },
{ "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
};
Tcl_Obj **apElem = 0;
int nElem = 0;
+2 -4
View File
@@ -983,13 +983,12 @@ void sqlite3Put4byte(unsigned char *p, u32 v){
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character: 0..9a..fA..F
*/
static u8 hexToInt(int h){
u8 sqlite3HexToInt(int h){
assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
h += 9*(1&(h>>6));
@@ -999,7 +998,6 @@ static u8 hexToInt(int h){
#endif
return (u8)(h & 0xf);
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
@@ -1016,7 +1014,7 @@ void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
n--;
if( zBlob ){
for(i=0; i<n; i+=2){
zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
}
zBlob[i/2] = 0;
}
+1 -1
View File
@@ -3149,7 +3149,7 @@ case OP_OpenEphemeral: {
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
rc = sqlite3BtreeOpen(0, db, &pCx->pBt,
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
+3 -3
View File
@@ -874,7 +874,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
int i;
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
const sqlite3_module *pMod = db->aVTrans[i]->pMod->pModule;
if( pMod->iVersion>=1 ){
if( pMod->iVersion>=2 ){
int (*xMethod)(sqlite3_vtab *, int);
switch( op ){
case SAVEPOINT_BEGIN:
@@ -1001,7 +1001,7 @@ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
*/
int sqlite3_vtab_on_conflict(sqlite3 *db){
static const unsigned char aMap[] = {
SQLITE_ROLLBACK, SQLITE_IGNORE, SQLITE_ABORT, SQLITE_FAIL, SQLITE_REPLACE
SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
};
assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
assert( OE_Ignore==4 && OE_Replace==5 );
@@ -1027,7 +1027,7 @@ int sqlite3_vtab_config(sqlite3 *db, int op, ...){
if( !p ){
rc = SQLITE_MISUSE_BKPT;
}else{
assert( (p->pTab->tabFlags & TF_Virtual)!=0 );
assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
p->pVTable->bConstraint = (u8)va_arg(ap, int);
}
break;
+61 -18
View File
@@ -406,6 +406,14 @@ struct WalCkptInfo {
/*
** An open write-ahead log file is represented by an instance of the
** following object.
**
** The readOnlyShm variable is normally set to 0. If it is set to 1, then
** the connection to shared-memory is read-only. This means it cannot
** be written at all (even when read-locking the database). If it is set
** to 2, then the shared-memory region is not yet open, but a read-only
** connection is acceptable. In this case when the shared-memory is opened
** (see function walIndexPage()), readOnlyShm is set to either 0 or 1 as
** appropriate.
*/
struct Wal {
sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
@@ -420,6 +428,7 @@ struct Wal {
u8 writeLock; /* True if in a write transaction */
u8 ckptLock; /* True if holding a checkpoint lock */
u8 readOnly; /* True if the WAL file is open read-only */
u8 readOnlyShm; /* True if the SHM file is open read-only */
WalIndexHdr hdr; /* Wal-index header for current transaction */
const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
@@ -528,11 +537,23 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
if( rc==SQLITE_CANTOPEN && pWal->readOnlyShm>1 ){
assert( iPage==0 );
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)1);
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
if( rc==SQLITE_OK ){
pWal->readOnly = pWal->readOnlyShm = 1;
}
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)0);
}
}
}
*ppPage = pWal->apWiData[iPage];
assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
if( pWal->readOnlyShm>1 ) pWal->readOnlyShm = 0;
return rc;
}
@@ -772,6 +793,7 @@ static void walUnlockShared(Wal *pWal, int lockIdx){
}
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
int rc;
assert( pWal->readOnlyShm==0 );
if( pWal->exclusiveMode ) return SQLITE_OK;
rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
@@ -781,6 +803,7 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
assert( pWal->readOnlyShm==0 );
if( pWal->exclusiveMode ) return;
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
@@ -1056,6 +1079,7 @@ static int walIndexRecover(Wal *pWal){
assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
assert( pWal->writeLock );
assert( pWal->readOnlyShm==0 );
iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
nLock = SQLITE_SHM_NLOCK - iLock;
rc = walLockExclusive(pWal, iLock, nLock);
@@ -1895,6 +1919,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
return rc;
};
assert( page0 || pWal->writeLock==0 );
assert( pWal->readOnlyShm==0 || pWal->readOnlyShm==1 );
/* If the first page of the wal-index has been mapped, try to read the
** wal-index header immediately, without holding any lock. This usually
@@ -1904,24 +1929,31 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
/* If the first attempt failed, it might have been due to a race
** with a writer. So get a WRITE lock and try again.
** with a writer. So lock the WAL_WRITE_LOCK byte and try again.
*/
assert( badHdr==0 || pWal->writeLock==0 );
if( badHdr && SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
if( badHdr ){
/* If the wal-index header is still malformed even while holding
** a WRITE lock, it can only mean that the header is corrupted and
** needs to be reconstructed. So run recovery to do exactly that.
*/
rc = walIndexRecover(pWal);
*pChanged = 1;
if( badHdr ){
if( pWal->readOnlyShm ){
if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
walUnlockShared(pWal, WAL_WRITE_LOCK);
rc = SQLITE_READONLY_RECOVERY;
}
}else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
if( badHdr ){
/* If the wal-index header is still malformed even while holding
** a WRITE lock, it can only mean that the header is corrupted and
** needs to be reconstructed. So run recovery to do exactly that.
*/
rc = walIndexRecover(pWal);
*pChanged = 1;
}
}
pWal->writeLock = 0;
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
}
pWal->writeLock = 0;
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
}
/* If the header is read successfully, check the version number to make
@@ -2108,7 +2140,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
}
/* There was once an "if" here. The extra "{" is to preserve indentation. */
{
if( mxReadMark < pWal->hdr.mxFrame || mxI==0 ){
if( pWal->readOnlyShm==0 && (mxReadMark < pWal->hdr.mxFrame || mxI==0) ){
for(i=1; i<WAL_NREADER; i++){
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
if( rc==SQLITE_OK ){
@@ -2123,7 +2155,8 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
}
if( mxI==0 ){
assert( rc==SQLITE_BUSY );
return WAL_RETRY;
assert( rc==SQLITE_BUSY || (pWal->readOnlyShm && rc==SQLITE_OK) );
return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
}
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
@@ -2178,13 +2211,18 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** Pager layer will use this to know that is cache is stale and
** needs to be flushed.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
int sqlite3WalBeginReadTransaction(Wal *pWal, int readOnlyShm, int *pChanged){
int rc; /* Return code */
int cnt = 0; /* Number of TryBeginRead attempts */
if( pWal->nWiData==0 || pWal->apWiData[0]==0 ){
assert( readOnlyShm==0 || readOnlyShm==1 );
pWal->readOnlyShm = readOnlyShm*2;
}
do{
rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
}while( rc==WAL_RETRY );
assert( rc || pWal->readOnlyShm==0 || (readOnlyShm && pWal->readOnlyShm==1) );
testcase( (rc&0xff)==SQLITE_BUSY );
testcase( (rc&0xff)==SQLITE_IOERR );
testcase( rc==SQLITE_PROTOCOL );
@@ -2359,6 +2397,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
if( pWal->readOnly ){
return SQLITE_READONLY;
}
assert( pWal->readOnlyShm==0 );
/* Only one writer allowed at a time. Get the write lock. Return
** SQLITE_BUSY if unable.
@@ -2748,6 +2787,10 @@ int sqlite3WalCheckpoint(
assert( pWal->writeLock==0 );
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
if( pWal->readOnlyShm ){
return SQLITE_READONLY;
}
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
if( rc ){
/* Usually this is SQLITE_BUSY meaning that another thread or process
+2 -2
View File
@@ -22,7 +22,7 @@
#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z) 0
# define sqlite3WalClose(w,x,y,z) 0
# define sqlite3WalBeginReadTransaction(y,z) 0
# define sqlite3WalBeginReadTransaction(x,y,z) 0
# define sqlite3WalEndReadTransaction(z)
# define sqlite3WalRead(v,w,x,y,z) 0
# define sqlite3WalDbsize(y) 0
@@ -56,7 +56,7 @@ int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
** transaction and releases the lock.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
int sqlite3WalBeginReadTransaction(Wal *pWal, int, int *);
void sqlite3WalEndReadTransaction(Wal *pWal);
/* Read a page from the write-ahead log, if it is present. */
+1 -1
View File
@@ -650,7 +650,7 @@ do_test alter-6.7 {
# Ticket #1665: Make sure ALTER TABLE ADD COLUMN works on a table
# that includes a COLLATE clause.
#
do_test alter-7.1 {
do_realnum_test alter-7.1 {
execsql {
CREATE TABLE t1(a TEXT COLLATE BINARY);
ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE;
+5 -5
View File
@@ -234,7 +234,7 @@ do_test cast-3.1 {
do_test cast-3.2 {
execsql {SELECT CAST(9223372036854774800 AS numeric)}
} 9223372036854774800
do_test cast-3.3 {
do_realnum_test cast-3.3 {
execsql {SELECT CAST(9223372036854774800 AS real)}
} 9.22337203685477e+18
do_test cast-3.4 {
@@ -246,7 +246,7 @@ do_test cast-3.5 {
do_test cast-3.6 {
execsql {SELECT CAST(-9223372036854774800 AS numeric)}
} -9223372036854774800
do_test cast-3.7 {
do_realnum_test cast-3.7 {
execsql {SELECT CAST(-9223372036854774800 AS real)}
} -9.22337203685477e+18
do_test cast-3.8 {
@@ -258,7 +258,7 @@ do_test cast-3.11 {
do_test cast-3.12 {
execsql {SELECT CAST('9223372036854774800' AS numeric)}
} 9223372036854774800
do_test cast-3.13 {
do_realnum_test cast-3.13 {
execsql {SELECT CAST('9223372036854774800' AS real)}
} 9.22337203685477e+18
ifcapable long_double {
@@ -272,7 +272,7 @@ do_test cast-3.15 {
do_test cast-3.16 {
execsql {SELECT CAST('-9223372036854774800' AS numeric)}
} -9223372036854774800
do_test cast-3.17 {
do_realnum_test cast-3.17 {
execsql {SELECT CAST('-9223372036854774800' AS real)}
} -9.22337203685477e+18
ifcapable long_double {
@@ -287,7 +287,7 @@ if {[db eval {PRAGMA encoding}]=="UTF-8"} {
do_test cast-3.22 {
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS numeric)}
} 9223372036854774800
do_test cast-3.23 {
do_realnum_test cast-3.23 {
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS real)}
} 9.22337203685477e+18
ifcapable long_double {
+456
View File
@@ -0,0 +1,456 @@
# 2011 May 06
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix e_uri
db close
proc parse_uri {uri} {
testvfs tvfs2
testvfs tvfs
tvfs filter xOpen
tvfs script parse_uri_open_cb
set ::uri_open [list]
set DB [sqlite3_open_v2 $uri {
SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL
} tvfs]
sqlite3_close $DB
tvfs delete
tvfs2 delete
set ::uri_open
}
proc parse_uri_open_cb {method file arglist} {
set ::uri_open [list $file $arglist]
}
proc open_uri_error {uri} {
set flags {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL}
set DB [sqlite3_open_v2 $uri $flags ""]
set e [sqlite3_errmsg $DB]
sqlite3_close $DB
set e
}
# EVIDENCE-OF: R-35840-33204 If URI filename interpretation is enabled,
# and the filename argument begins with "file:", then the filename is
# interpreted as a URI.
#
# EVIDENCE-OF: R-00067-59538 URI filename interpretation is enabled if
# the SQLITE_OPEN_URI flag is is set in the fourth argument to
# sqlite3_open_v2(), or if it has been enabled globally using the
# SQLITE_CONFIG_URI option with the sqlite3_config() method.
#
if {$tcl_platform(platform) == "unix"} {
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE]
# Tests with SQLITE_CONFIG_URI configured to false. URI intepretation is
# only enabled if the SQLITE_OPEN_URI flag is specified.
sqlite3_shutdown
sqlite3_config_uri 0
do_test 1.1 {
forcedelete file:test.db test.db
set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
list [file exists file:test.db] [file exists test.db]
} {0 1}
do_test 1.2 {
forcedelete file:test.db2 test.db2
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
sqlite3_step $STMT
sqlite3_finalize $STMT
list [file exists file:test.db2] [file exists test.db2]
} {0 1}
sqlite3_close $DB
do_test 1.3 {
forcedelete file:test.db test.db
set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
list [file exists file:test.db] [file exists test.db]
} {1 0}
do_test 1.4 {
forcedelete file:test.db2 test.db2
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
sqlite3_step $STMT
sqlite3_finalize $STMT
list [file exists file:test.db2] [file exists test.db2]
} {1 0}
sqlite3_close $DB
# Tests with SQLITE_CONFIG_URI configured to true. URI intepretation is
# enabled with or without SQLITE_OPEN_URI.
#
sqlite3_shutdown
sqlite3_config_uri 1
do_test 1.5 {
forcedelete file:test.db test.db
set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
list [file exists file:test.db] [file exists test.db]
} {0 1}
do_test 1.6 {
forcedelete file:test.db2 test.db2
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
sqlite3_step $STMT
sqlite3_finalize $STMT
list [file exists file:test.db2] [file exists test.db2]
} {0 1}
sqlite3_close $DB
do_test 1.7 {
forcedelete file:test.db test.db
set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
list [file exists file:test.db] [file exists test.db]
} {0 1}
do_test 1.8 {
forcedelete file:test.db2 test.db2
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
sqlite3_step $STMT
sqlite3_finalize $STMT
list [file exists file:test.db2] [file exists test.db2]
} {0 1}
sqlite3_close $DB
}
# EVIDENCE-OF: R-17482-00398 If the authority is not an empty string or
# "localhost", an error is returned to the caller.
#
if {$tcl_platform(platform) == "unix"} {
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
foreach {tn uri error} "
1 {file://localhost[pwd]/test.db} {not an error}
2 {file://[pwd]/test.db} {not an error}
3 {file://x[pwd]/test.db} {invalid uri authority: x}
4 {file://invalid[pwd]/test.db} {invalid uri authority: invalid}
" {
do_test 2.$tn {
set DB [sqlite3_open_v2 $uri $flags ""]
set e [sqlite3_errmsg $DB]
sqlite3_close $DB
set e
} $error
}
}
# EVIDENCE-OF: R-43804-65312 The 'fragment' component of a URI, if
# present, is always ignored.
#
# It is difficult to test that something is ignore correctly. So these tests
# just show that adding a fragment does not interfere with the pathname or
# parameters passed through to the VFS xOpen() methods.
#
if {$tcl_platform(platform) == "unix"} {
foreach {tn uri parse} "
1 {file:test.db#abc} {[pwd]/test.db {}}
2 {file:test.db?a=b#abc} {[pwd]/test.db {a b}}
3 {file:test.db?a=b#?c=d} {[pwd]/test.db {a b}}
" {
do_test 3.$tn { parse_uri $uri } $parse
}
}
# EVIDENCE-OF: R-00273-20588 SQLite uses the 'path' component of the URI
# as the path to the database file to open.
#
# EVIDENCE-OF: R-28659-11035 If the path begins with a '/' character,
# then it is interpreted as an absolute path.
#
# EVIDENCE-OF: R-39349-47203 If it does not begin with a '/', it is
# interpreted as a relative path.
#
if {$tcl_platform(platform) == "unix"} {
foreach {tn uri parse} "
1 {file:test.db} {[pwd]/test.db {}}
2 {file:/test.db} {/test.db {}}
3 {file:///test.db} {/test.db {}}
4 {file://localhost/test.db} {/test.db {}}
5 {file:/a/b/c/test.db} {/a/b/c/test.db {}}
" {
do_test 4.$tn { parse_uri $uri } $parse
}
}
# EVIDENCE-OF: R-01612-30877 The "vfs" parameter may be used to specify
# the name of a VFS object that provides the operating system interface
# that should be used to access the database file on disk.
#
# The above is tested by cases 1.* below.
#
# EVIDENCE-OF: R-52293-58497 If this option is set to an empty string
# the default VFS object is used.
#
# The above is tested by cases 2.* below.
#
# EVIDENCE-OF: R-31855-18665 If sqlite3_open_v2() is used and the vfs
# option is present, then the VFS specified by the option takes
# precedence over the value passed as the fourth parameter to
# sqlite3_open_v2().
#
# The above is tested by cases 3.* below.
#
proc vfs_open_cb {name args} {
set ::vfs $name
}
foreach {name default} {vfs1 0 vfs2 0 vfs3 1} {
testvfs $name -default $default
$name filter xOpen
$name script [list vfs_open_cb $name]
}
foreach {tn uri defvfs vfs} {
1.1 "file:test.db?vfs=vfs1" "" vfs1
1.2 "file:test.db?vfs=vfs2" "" vfs2
2.1 "file:test.db" vfs1 vfs1
2.2 "file:test.db?vfs=" vfs1 vfs3
3.1 "file:test.db?vfs=vfs1" vfs2 vfs1
3.2 "file:test.db?vfs=vfs2" vfs1 vfs2
3.3 "file:test.db?xvfs=vfs1" vfs2 vfs2
3.4 "file:test.db?xvfs=vfs2" vfs1 vfs1
} {
do_test 5.$tn {
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
sqlite3_close [
sqlite3_open_v2 $uri $flags $defvfs
]
set ::vfs
} $vfs
}
vfs1 delete
vfs2 delete
vfs3 delete
# EVIDENCE-OF: R-48365-36308 Specifying an unknown VFS is an error.
#
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
do_test 6.1 {
set DB [sqlite3_open_v2 file:test.db?vfs=nosuchvfs $flags ""]
set errmsg [sqlite3_errmsg $DB]
sqlite3_close $DB
set errmsg
} {no such vfs: nosuchvfs}
# EVIDENCE-OF: R-60479-64270 The mode parameter may be set to either
# "ro", "rw" or "rwc". Attempting to set it to any other value is an
# error
#
sqlite3 db test.db
db close
foreach {tn uri error} "
1 {file:test.db?mode=ro} {not an error}
2 {file:test.db?mode=rw} {not an error}
3 {file:test.db?mode=rwc} {not an error}
4 {file:test.db?mode=Ro} {no such access mode: Ro}
5 {file:test.db?mode=Rw} {no such access mode: Rw}
6 {file:test.db?mode=Rwc} {no such access mode: Rwc}
" {
do_test 7.$tn { open_uri_error $uri } $error
}
# EVIDENCE-OF: R-09651-31805 If "ro" is specified, then the database is
# opened for read-only access, just as if the SQLITE_OPEN_READONLY flag
# had been set in the third argument to sqlite3_prepare_v2().
#
# EVIDENCE-OF: R-40137-26050 If the mode option is set to "rw", then the
# database is opened for read-write (but not create) access, as if
# SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set.
#
# EVIDENCE-OF: R-26845-32976 Value "rwc" is equivalent to setting both
# SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.
#
sqlite3_shutdown
sqlite3_config_uri 1
foreach {tn uri read write create} {
1 {file:test.db?mode=ro} 1 0 0
2 {file:test.db?mode=rw} 1 1 0
3 {file:test.db?mode=rwc} 1 1 1
} {
set RES(c,0) {1 {unable to open database file}}
set RES(c,1) {0 {}}
set RES(w,0) {1 {attempt to write a readonly database}}
set RES(w,1) {0 {}}
set RES(r,0) {1 {this never happens}}
set RES(r,1) {0 {a b}}
# Test CREATE access:
forcedelete test.db
do_test 8.$tn.c { list [catch { sqlite3 db $uri } msg] $msg } $RES(c,$create)
catch { db close }
sqlite3 db test.db
db eval { CREATE TABLE t1(a, b) ; INSERT INTO t1 VALUES('a', 'b') ;}
db close
# Test READ access:
do_test 8.$tn.r {
sqlite3 db $uri
catchsql { SELECT * FROM t1 }
} $RES(r,$read)
# Test WRITE access:
do_test 8.$tn.w {
sqlite3 db $uri
catchsql { INSERT INTO t1 VALUES(1, 2) }
} $RES(w,$write)
catch {db close}
}
# EVIDENCE-OF: R-56032-32287 If sqlite3_open_v2() is used, it is an
# error to specify a value for the mode parameter that is less
# restrictive than that specified by the flags passed as the third
# parameter.
#
forcedelete test.db
sqlite3 db test.db
db close
foreach {tn uri flags error} {
1 {file:test.db?mode=ro} ro {not an error}
2 {file:test.db?mode=ro} rw {not an error}
3 {file:test.db?mode=ro} rwc {not an error}
4 {file:test.db?mode=rw} ro {access mode not allowed: rw}
5 {file:test.db?mode=rw} rw {not an error}
6 {file:test.db?mode=rw} rwc {not an error}
7 {file:test.db?mode=rwc} ro {access mode not allowed: rwc}
8 {file:test.db?mode=rwc} rw {access mode not allowed: rwc}
9 {file:test.db?mode=rwc} rwc {not an error}
} {
set f(ro) [list SQLITE_OPEN_READONLY SQLITE_OPEN_URI]
set f(rw) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_URI]
set f(rwc) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
set DB [sqlite3_open_v2 $uri $f($flags) ""]
set e [sqlite3_errmsg $DB]
sqlite3_close $DB
do_test 9.$tn { set e } $error
}
# EVIDENCE-OF: R-23182-54295 The cache parameter may be set to either
# "shared" or "private".
sqlite3 db test.db
db close
foreach {tn uri error} "
1 {file:test.db?cache=private} {not an error}
2 {file:test.db?cache=shared} {not an error}
3 {file:test.db?cache=yes} {no such cache mode: yes}
4 {file:test.db?cache=} {no such cache mode: }
" {
do_test 10.$tn { open_uri_error $uri } $error
}
# EVIDENCE-OF: R-23027-03515 Setting it to "shared" is equivalent to
# setting the SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed
# to sqlite3_open_v2().
#
# EVIDENCE-OF: R-49793-28525 Setting the cache parameter to "private" is
# equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
#
# EVIDENCE-OF: R-19510-48080 If sqlite3_open_v2() is used and the
# "cache" parameter is present in a URI filename, its value overrides
# any behaviour requested by setting SQLITE_OPEN_PRIVATECACHE or
# SQLITE_OPEN_SHAREDCACHE flag.
#
set orig [sqlite3_enable_shared_cache]
foreach {tn uri flags shared_default isshared} {
1.1 "file:test.db" "" 0 0
1.2 "file:test.db" "" 1 1
1.3 "file:test.db" private 0 0
1.4 "file:test.db" private 1 0
1.5 "file:test.db" shared 0 1
1.6 "file:test.db" shared 1 1
2.1 "file:test.db?cache=private" "" 0 0
2.2 "file:test.db?cache=private" "" 1 0
2.3 "file:test.db?cache=private" private 0 0
2.4 "file:test.db?cache=private" private 1 0
2.5 "file:test.db?cache=private" shared 0 0
2.6 "file:test.db?cache=private" shared 1 0
3.1 "file:test.db?cache=shared" "" 0 1
3.2 "file:test.db?cache=shared" "" 1 1
3.3 "file:test.db?cache=shared" private 0 1
3.4 "file:test.db?cache=shared" private 1 1
3.5 "file:test.db?cache=shared" shared 0 1
3.6 "file:test.db?cache=shared" shared 1 1
} {
forcedelete test.db
sqlite3_enable_shared_cache 1
sqlite3 db test.db
sqlite3_enable_shared_cache 0
db eval {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES('ok');
}
unset -nocomplain f
set f() {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI}
set f(shared) [concat $f() SQLITE_OPEN_SHAREDCACHE]
set f(private) [concat $f() SQLITE_OPEN_PRIVATECACHE]
sqlite3_enable_shared_cache $shared_default
set DB [sqlite3_open_v2 $uri $f($flags) ""]
set STMT [sqlite3_prepare $DB "SELECT * FROM t1" -1 dummy]
db eval {
BEGIN;
INSERT INTO t1 VALUES('ko');
}
sqlite3_step $STMT
sqlite3_finalize $STMT
set RES(0) {not an error}
set RES(1) {database table is locked: t1}
do_test 11.$tn { sqlite3_errmsg $DB } $RES($isshared)
sqlite3_close $DB
db close
}
sqlite3_enable_shared_cache $orig
# EVIDENCE-OF: R-63472-46769 Specifying an unknown parameter in the
# query component of a URI is not an error.
#
do_test 12.1 {
parse_uri file://localhost/test.db?an=unknown&parameter=is&ok=
} {/test.db {an unknown parameter is ok {}}}
do_test 12.2 {
parse_uri file://localhost/test.db?an&unknown&parameter&is&ok
} {/test.db {an {} unknown {} parameter {} is {} ok {}}}
# EVIDENCE-OF: R-27458-04043 URI hexadecimal escape sequences (%HH) are
# supported within the path and query components of a URI.
#
# EVIDENCE-OF: R-52765-50368 Before the path or query components of a
# URI filename are interpreted, they are encoded using UTF-8 and all
# hexadecimal escape sequences replaced by a single byte containing the
# corresponding octet.
#
# The second of the two statements above is tested by creating a
# multi-byte utf-8 character using a sequence of %HH escapes.
#
foreach {tn uri parse} "
1 {file:/test.%64%62} {/test.db {}}
2 {file:/test.db?%68%65%6c%6c%6f=%77%6f%72%6c%64} {/test.db {hello world}}
3 {file:/%C3%BF.db} {/\xFF.db {}}
" {
do_test 13.$tn { parse_uri $uri } $parse
}
finish_test
+58 -53
View File
@@ -32,6 +32,11 @@ proc test_expr {name settings expr result} {
execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
} $settings $expr] $result
}
proc test_realnum_expr {name settings expr result} {
do_realnum_test $name [format {
execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
} $settings $expr] $result
}
test_expr expr-1.1 {i1=10, i2=20} {i1+i2} 30
test_expr expr-1.2 {i1=10, i2=20} {i1-i2} -10
@@ -164,7 +169,7 @@ ifcapable floatingpoint {
}
if {[working_64bit_int]} {
test_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
test_realnum_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
}
test_expr expr-1.107 {i1=0} {-9223372036854775808%-1} 0
@@ -203,100 +208,100 @@ test_expr expr-1.126 {i1=8, i2=8} \
ifcapable floatingpoint {if {[working_64bit_int]} {
test_expr expr-1.200\
{i1=9223372036854775806, i2=1} {i1+i2} 9223372036854775807
test_expr expr-1.201\
test_realnum_expr expr-1.201\
{i1=9223372036854775806, i2=2} {i1+i2} 9.22337203685478e+18
test_expr expr-1.202\
test_realnum_expr expr-1.202\
{i1=9223372036854775806, i2=100000} {i1+i2} 9.22337203685488e+18
test_expr expr-1.203\
test_realnum_expr expr-1.203\
{i1=9223372036854775807, i2=0} {i1+i2} 9223372036854775807
test_expr expr-1.204\
test_realnum_expr expr-1.204\
{i1=9223372036854775807, i2=1} {i1+i2} 9.22337203685478e+18
test_expr expr-1.205\
test_realnum_expr expr-1.205\
{i2=9223372036854775806, i1=1} {i1+i2} 9223372036854775807
test_expr expr-1.206\
test_realnum_expr expr-1.206\
{i2=9223372036854775806, i1=2} {i1+i2} 9.22337203685478e+18
test_expr expr-1.207\
test_realnum_expr expr-1.207\
{i2=9223372036854775806, i1=100000} {i1+i2} 9.22337203685488e+18
test_expr expr-1.208\
test_realnum_expr expr-1.208\
{i2=9223372036854775807, i1=0} {i1+i2} 9223372036854775807
test_expr expr-1.209\
test_realnum_expr expr-1.209\
{i2=9223372036854775807, i1=1} {i1+i2} 9.22337203685478e+18
test_expr expr-1.210\
test_realnum_expr expr-1.210\
{i1=-9223372036854775807, i2=-1} {i1+i2} -9223372036854775808
test_expr expr-1.211\
test_realnum_expr expr-1.211\
{i1=-9223372036854775807, i2=-2} {i1+i2} -9.22337203685478e+18
test_expr expr-1.212\
test_realnum_expr expr-1.212\
{i1=-9223372036854775807, i2=-100000} {i1+i2} -9.22337203685488e+18
test_expr expr-1.213\
test_realnum_expr expr-1.213\
{i1=-9223372036854775808, i2=0} {i1+i2} -9223372036854775808
test_expr expr-1.214\
test_realnum_expr expr-1.214\
{i1=-9223372036854775808, i2=-1} {i1+i2} -9.22337203685478e+18
test_expr expr-1.215\
test_realnum_expr expr-1.215\
{i2=-9223372036854775807, i1=-1} {i1+i2} -9223372036854775808
test_expr expr-1.216\
test_realnum_expr expr-1.216\
{i2=-9223372036854775807, i1=-2} {i1+i2} -9.22337203685478e+18
test_expr expr-1.217\
test_realnum_expr expr-1.217\
{i2=-9223372036854775807, i1=-100000} {i1+i2} -9.22337203685488e+18
test_expr expr-1.218\
test_realnum_expr expr-1.218\
{i2=-9223372036854775808, i1=0} {i1+i2} -9223372036854775808
test_expr expr-1.219\
test_realnum_expr expr-1.219\
{i2=-9223372036854775808, i1=-1} {i1+i2} -9.22337203685478e+18
test_expr expr-1.220\
test_realnum_expr expr-1.220\
{i1=9223372036854775806, i2=-1} {i1-i2} 9223372036854775807
test_expr expr-1.221\
test_realnum_expr expr-1.221\
{i1=9223372036854775806, i2=-2} {i1-i2} 9.22337203685478e+18
test_expr expr-1.222\
test_realnum_expr expr-1.222\
{i1=9223372036854775806, i2=-100000} {i1-i2} 9.22337203685488e+18
test_expr expr-1.223\
test_realnum_expr expr-1.223\
{i1=9223372036854775807, i2=0} {i1-i2} 9223372036854775807
test_expr expr-1.224\
test_realnum_expr expr-1.224\
{i1=9223372036854775807, i2=-1} {i1-i2} 9.22337203685478e+18
test_expr expr-1.225\
test_realnum_expr expr-1.225\
{i2=-9223372036854775806, i1=1} {i1-i2} 9223372036854775807
test_expr expr-1.226\
test_realnum_expr expr-1.226\
{i2=-9223372036854775806, i1=2} {i1-i2} 9.22337203685478e+18
test_expr expr-1.227\
test_realnum_expr expr-1.227\
{i2=-9223372036854775806, i1=100000} {i1-i2} 9.22337203685488e+18
test_expr expr-1.228\
test_realnum_expr expr-1.228\
{i2=-9223372036854775807, i1=0} {i1-i2} 9223372036854775807
test_expr expr-1.229\
test_realnum_expr expr-1.229\
{i2=-9223372036854775807, i1=1} {i1-i2} 9.22337203685478e+18
test_expr expr-1.230\
test_realnum_expr expr-1.230\
{i1=-9223372036854775807, i2=1} {i1-i2} -9223372036854775808
test_expr expr-1.231\
test_realnum_expr expr-1.231\
{i1=-9223372036854775807, i2=2} {i1-i2} -9.22337203685478e+18
test_expr expr-1.232\
test_realnum_expr expr-1.232\
{i1=-9223372036854775807, i2=100000} {i1-i2} -9.22337203685488e+18
test_expr expr-1.233\
test_realnum_expr expr-1.233\
{i1=-9223372036854775808, i2=0} {i1-i2} -9223372036854775808
test_expr expr-1.234\
test_realnum_expr expr-1.234\
{i1=-9223372036854775808, i2=1} {i1-i2} -9.22337203685478e+18
test_expr expr-1.235\
test_realnum_expr expr-1.235\
{i2=9223372036854775807, i1=-1} {i1-i2} -9223372036854775808
test_expr expr-1.236\
test_realnum_expr expr-1.236\
{i2=9223372036854775807, i1=-2} {i1-i2} -9.22337203685478e+18
test_expr expr-1.237\
test_realnum_expr expr-1.237\
{i2=9223372036854775807, i1=-100000} {i1-i2} -9.22337203685488e+18
test_expr expr-1.238\
test_realnum_expr expr-1.238\
{i2=9223372036854775807, i1=0} {i1-i2} -9223372036854775807
test_expr expr-1.239\
test_realnum_expr expr-1.239\
{i2=9223372036854775807, i1=-1} {i1-i2} -9223372036854775808
test_expr expr-1.250\
test_realnum_expr expr-1.250\
{i1=4294967296, i2=2147483648} {i1*i2} 9.22337203685478e+18
test_expr expr-1.251\
test_realnum_expr expr-1.251\
{i1=4294967296, i2=2147483647} {i1*i2} 9223372032559808512
test_expr expr-1.252\
test_realnum_expr expr-1.252\
{i1=-4294967296, i2=2147483648} {i1*i2} -9223372036854775808
test_expr expr-1.253\
test_realnum_expr expr-1.253\
{i1=-4294967296, i2=2147483647} {i1*i2} -9223372032559808512
test_expr expr-1.254\
test_realnum_expr expr-1.254\
{i1=4294967296, i2=-2147483648} {i1*i2} -9223372036854775808
test_expr expr-1.255\
test_realnum_expr expr-1.255\
{i1=4294967296, i2=-2147483647} {i1*i2} -9223372032559808512
test_expr expr-1.256\
test_realnum_expr expr-1.256\
{i1=-4294967296, i2=-2147483648} {i1*i2} 9.22337203685478e+18
test_expr expr-1.257\
test_realnum_expr expr-1.257\
{i1=-4294967296, i2=-2147483647} {i1*i2} 9223372032559808512
}}
@@ -883,7 +888,7 @@ do_test expr-12.2 {
} {1 {near ")": syntax error}}
ifcapable floatingpoint {
do_test expr-13.1 {
do_realnum_test expr-13.1 {
execsql {
SELECT 12345678901234567890;
}
@@ -908,12 +913,12 @@ if {[working_64bit_int]} {
# If the value is too large, use String->Float conversion.
#
ifcapable floatingpoint {
do_test expr-13.4 {
do_realnum_test expr-13.4 {
execsql {
SELECT 0+'9223372036854775808'
}
} {9.22337203685478e+18}
do_test expr-13.5 {
do_realnum_test expr-13.5 {
execsql {
SELECT '9223372036854775808'+0
}
@@ -923,12 +928,12 @@ ifcapable floatingpoint {
# Use String->float conversion if the value is explicitly a floating
# point value.
#
do_test expr-13.6 {
do_realnum_test expr-13.6 {
execsql {
SELECT 0+'9223372036854775807.0'
}
} {9.22337203685478e+18}
do_test expr-13.7 {
do_realnum_test expr-13.7 {
execsql {
SELECT '9223372036854775807.0'+0
}
+2 -2
View File
@@ -55,8 +55,8 @@ proc do_multiclient_test {varname script} {
uplevel set $varname $tn
uplevel $script
code2 { db2 close }
code3 { db3 close }
catch { code2 { db2 close } }
catch { code3 { db3 close } }
catch { close $::code2_chan }
catch { close $::code3_chan }
catch { db close }
+8 -8
View File
@@ -42,31 +42,31 @@ do_test nan-1.1.1 {
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
if {$tcl_platform(platform) != "symbian"} {
do_test nan-1.1.2 {
do_realnum_test nan-1.1.2 {
sqlite3_bind_double $::STMT 1 +Inf
sqlite3_step $::STMT
sqlite3_reset $::STMT
db eval {SELECT x, typeof(x) FROM t1}
} {{} null inf real}
do_test nan-1.1.3 {
do_realnum_test nan-1.1.3 {
sqlite3_bind_double $::STMT 1 -Inf
sqlite3_step $::STMT
sqlite3_reset $::STMT
db eval {SELECT x, typeof(x) FROM t1}
} {{} null inf real -inf real}
do_test nan-1.1.4 {
do_realnum_test nan-1.1.4 {
sqlite3_bind_double $::STMT 1 -NaN
sqlite3_step $::STMT
sqlite3_reset $::STMT
db eval {SELECT x, typeof(x) FROM t1}
} {{} null inf real -inf real {} null}
do_test nan-1.1.5 {
do_realnum_test nan-1.1.5 {
sqlite3_bind_double $::STMT 1 NaN0
sqlite3_step $::STMT
sqlite3_reset $::STMT
db eval {SELECT x, typeof(x) FROM t1}
} {{} null inf real -inf real {} null {} null}
do_test nan-1.1.6 {
do_realnum_test nan-1.1.6 {
sqlite3_bind_double $::STMT 1 -NaN0
sqlite3_step $::STMT
sqlite3_reset $::STMT
@@ -231,12 +231,12 @@ if {$tcl_platform(platform) != "symbian"} {
# Do not run these tests on Symbian, as the Tcl port doesn't like to
# convert from floating point value "-inf" to a string.
#
do_test nan-4.7 {
do_realnum_test nan-4.7 {
db eval {DELETE FROM t1}
db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)"
db eval {SELECT x, typeof(x) FROM t1}
} {inf real}
do_test nan-4.8 {
do_realnum_test nan-4.8 {
db eval {DELETE FROM t1}
db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)"
db eval {SELECT x, typeof(x) FROM t1}
@@ -313,7 +313,7 @@ do_test nan-4.18 {
db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
} {-9.88131291682493e-324 real}
do_test nan-4.20 {
do_realnum_test nan-4.20 {
db eval {DELETE FROM t1}
set big [string repeat 9 10000].0e-9000
db eval "INSERT INTO t1 VALUES($big)"
+3 -2
View File
@@ -1653,7 +1653,7 @@ for {set i 0} {$i<513} {incr i 3} {
testvfs tv -default 1
tv script xOpenCb
tv filter xOpen
proc xOpenCb {method filename} {
proc xOpenCb {method filename args} {
set ::file_len [string length $filename]
}
sqlite3 db test.db
@@ -2381,6 +2381,7 @@ do_test pager1-30.1 {
# file can still be rolled back. This is required for backward compatibility -
# versions of SQLite prior to 3.5.8 always set this field to zero.
#
if {$tcl_platform(platform)=="unix"} {
do_test pager1-31.1 {
faultsim_delete_and_reopen
execsql {
@@ -2408,7 +2409,7 @@ do_test pager1-31.1 {
sqlite3 db2 test.db2
execsql { PRAGMA integrity_check } db2
} {ok}
}
finish_test
+9
View File
@@ -354,6 +354,15 @@ proc do_test {name cmd expected} {
flush stdout
}
proc realnum_normalize {r} {
string map {1.#INF inf} [regsub -all {(e[+-])0+} $r {\1}]
}
proc do_realnum_test {name cmd expected} {
uplevel [list do_test $name [
subst -nocommands { realnum_normalize [ $cmd ] }
] [realnum_normalize $expected]]
}
proc fix_testname {varname} {
upvar $varname testname
if {[info exists ::testprefix]
+1 -1
View File
@@ -25,7 +25,7 @@ ifcapable !altertable {
return
}
do_test tkt3838-1.1 {
do_realnum_test tkt3838-1.1 {
db eval {
PRAGMA encoding=UTF16;
CREATE TABLE t1(x);
+4 -4
View File
@@ -36,21 +36,21 @@ if {[working_64bit_int]} {
}
} {-1 integer}
}
do_test tkt3922.2 {
do_realnum_test tkt3922.2 {
execsql {
DELETE FROM t1;
INSERT INTO t1 VALUES('-9223372036854775809');
SELECT a, typeof(a) FROM t1;
}
} {-9.22337203685478e+18 real}
do_test tkt3922.3 {
do_realnum_test tkt3922.3 {
execsql {
DELETE FROM t1;
INSERT INTO t1 VALUES('-9223372036854776832');
SELECT a, typeof(a) FROM t1;
}
} {-9.22337203685478e+18 real}
do_test tkt3922.4 {
do_realnum_test tkt3922.4 {
execsql {
DELETE FROM t1;
INSERT INTO t1 VALUES('-9223372036854776833');
@@ -78,7 +78,7 @@ if {[working_64bit_int]} {
}
} {1 integer}
}
do_test tkt3922.6 {
do_realnum_test tkt3922.6 {
execsql {
DELETE FROM t1;
INSERT INTO t1 VALUES('9223372036854775808');
+309
View File
@@ -0,0 +1,309 @@
# 2011 April 22
#
# 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
# Test organization:
#
# 1.*: That file names are correctly extracted from URIs.
# 2.*: That URI options (query parameters) are correctly extracted from URIs.
# 3.*: That specifying an unknown VFS causes an error.
# 4.*: Tests for specifying other options (other than "vfs").
# 5.*: Test using a different VFS with an attached database.
# 6.*: Test that authorities other than "" and localhost cause errors.
# 7.*: Test that a read-write db can be attached to a read-only connection.
#
set testprefix uri
db close
sqlite3_shutdown
sqlite3_config_uri 1
#-------------------------------------------------------------------------
# Test that file names are correctly extracted from URIs.
#
foreach {tn uri file} {
1 test.db test.db
2 file:test.db test.db
3 file://PWD/test.db test.db
4 file:PWD/test.db test.db
5 file:test.db?mork=1 test.db
6 file:test.db?mork=1&tonglor=2 test.db
7 file:test.db?mork=1#boris test.db
8 file:test.db#boris test.db
9 test.db#boris test.db#boris
10 file:test%2Edb test.db
11 file file
12 http:test.db http:test.db
13 file:test.db%00extra test.db
14 file:test%00.db%00extra test
15 test.db?mork=1#boris test.db?mork=1#boris
16 file://localhostPWD/test.db%3Fhello test.db?hello
} {
if {$tcl_platform(platform)=="windows"} {
if {$tn>14} break
set uri [string map [list PWD /[pwd]] $uri]
} else {
set uri [string map [list PWD [pwd]] $uri]
}
forcedelete $file
do_test 1.$tn.1 { file exists $file } 0
set DB [sqlite3_open $uri]
do_test 1.$tn.2 { file exists $file } 1
sqlite3_close $DB
forcedelete $file
do_test 1.$tn.3 { file exists $file } 0
sqlite3 db xxx.db
catchsql { ATTACH $uri AS aux }
do_test 1.$tn.4 { file exists $file } 1
db close
}
#-------------------------------------------------------------------------
# Test that URI query parameters are passed through to the VFS layer
# correctly.
#
testvfs tvfs2
testvfs tvfs -default 1
tvfs filter xOpen
tvfs script open_method
proc open_method {method file arglist} {
set ::arglist $arglist
}
foreach {tn uri kvlist} {
1 file:test.db?hello=world {hello world}
2 file:test.db?hello&world {hello {} world {}}
3 file:test.db?hello=1&world=2&vfs=tvfs {hello 1 world 2 vfs tvfs}
4 file:test.db?hello=1&world=2&vfs=tvfs2 {}
5 file:test.db?%68%65%6C%6C%6F=%77%6F%72%6C%64 {hello world}
6 file:test%00.db?hello%00extra=world%00ex {hello world}
7 file:test%00.db?hello%00=world%00 {hello world}
8 file:test%00.db?=world&xyz=abc {xyz abc}
9 file:test.db?%00hello=world&xyz=abc {xyz abc}
10 file:test.db?hello=%00world&xyz= {hello {} xyz {}}
11 file:test.db?=#ravada {}
12 file:test.db?&&&&&&&&hello=world&&&&&&& {hello world}
13 test.db?&&&&&&&&hello=world&&&&&&& {}
14 http:test.db?hello&world {}
} {
if {$tcl_platform(platform) == "windows" && $tn>12} {
continue
}
set ::arglist ""
set DB [sqlite3_open $uri]
do_test 2.$tn.1 { set ::arglist } $kvlist
sqlite3_close $DB
sqlite3 db xxx.db
set ::arglist ""
execsql { ATTACH $uri AS aux }
do_test 2.$tn.2 { set ::arglist } $kvlist
db close
}
tvfs delete
tvfs2 delete
#-------------------------------------------------------------------------
# Test that specifying a non-existent VFS raises an error.
#
do_test 3.1 {
list [catch { sqlite3 db "file:test.db?vfs=nosuchvfs" } msg] $msg
} {1 {no such vfs: nosuchvfs}}
#-------------------------------------------------------------------------
# Test some of the other options (other than "vfs").
#
foreach {tn mode create_ok write_ok readonly_ok} {
1 ro 0 0 1
2 rw 0 1 0
3 rwc 1 1 0
} {
catch { db close }
forcedelete test.db
set A(1) {0 {}}
set A(0) {1 {unable to open database file}}
do_test 4.1.$tn.1 {
list [catch {sqlite3 db "file:test.db?mode=$mode"} msg] $msg
} $A($create_ok)
catch { db close }
forcedelete test.db
sqlite3 db test.db
db eval { CREATE TABLE t1(a, b) }
db close
set A(1) {0 {}}
set A(0) {1 {attempt to write a readonly database}}
do_test 4.1.$tn.2 {
sqlite3 db "file:test.db?mode=$mode"
catchsql { INSERT INTO t1 VALUES(1, 2) }
} $A($write_ok)
set A(1) {0 {}}
set A(0) [list 1 "access mode not allowed: $mode"]
do_test 4.1.$tn.3 {
list [catch {sqlite3 db "file:test.db?mode=$mode" -readonly 1} msg] $msg
} $A($readonly_ok)
}
set orig [sqlite3_enable_shared_cache]
foreach {tn options sc_default is_shared} {
1 "" 1 1
2 "cache=private" 1 0
3 "cache=shared" 1 1
4 "" 0 0
5 "cache=private" 0 0
6 "cache=shared" 0 1
} {
catch { db close }
forcedelete test.db
sqlite3_enable_shared_cache 1
sqlite3 db2 test.db
db2 eval {CREATE TABLE t1(a, b)}
sqlite3_enable_shared_cache $sc_default
sqlite3 db "file:test.db?$options"
db eval {SELECT * FROM t1}
set A(1) {1 {database table is locked: t1}}
set A(0) {0 {}}
do_test 4.2.$tn {
db2 eval {BEGIN; INSERT INTO t1 VALUES(1, 2);}
catchsql { SELECT * FROM t1 }
} $A($is_shared)
db2 close
}
do_test 4.3.1 {
list [catch {sqlite3 db "file:test.db?mode=rc"} msg] $msg
} {1 {no such access mode: rc}}
do_test 4.3.2 {
list [catch {sqlite3 db "file:test.db?cache=public"} msg] $msg
} {1 {no such cache mode: public}}
#-------------------------------------------------------------------------
# Test that things work if an ATTACHed database uses a different VFS than
# the main database. The important point is that for all operations
# involving the ATTACHed database, the correct versions of the following
# VFS are used for all operations involving the attached database.
#
# xOpen
# xDelete
# xAccess
# xFullPathname
#
# This block of code creates two VFS - "tvfs1" and "tvfs2". Each time one
# of the above methods is called using "tvfs1", global variable ::T1(X) is
# set, where X is the file-name the method is called on. Calls to the above
# methods using "tvfs2" set entries in the global T2 array.
#
testvfs tvfs1
tvfs1 filter {xOpen xDelete xAccess xFullPathname}
tvfs1 script tvfs1_callback
proc tvfs1_callback {method filename args} {
set ::T1([file tail $filename]) 1
}
testvfs tvfs2
tvfs2 filter {xOpen xDelete xAccess xFullPathname}
tvfs2 script tvfs2_callback
proc tvfs2_callback {method filename args} {
set ::T2([file tail $filename]) 1
}
catch {db close}
eval forcedelete [glob test.db*]
do_test 5.1.1 {
sqlite3 db file:test.db1?vfs=tvfs1
execsql {
ATTACH 'file:test.db2?vfs=tvfs2' AS aux;
PRAGMA main.journal_mode = PERSIST;
PRAGMA aux.journal_mode = PERSIST;
CREATE TABLE t1(a, b);
CREATE TABLE aux.t2(a, b);
PRAGMA main.journal_mode = WAL;
PRAGMA aux.journal_mode = WAL;
INSERT INTO t1 VALUES('x', 'y');
INSERT INTO t2 VALUES('x', 'y');
}
lsort [array names ::T1]
} {test.db1 test.db1-journal test.db1-wal}
do_test 5.1.2 {
lsort [array names ::T2]
} {test.db2 test.db2-journal test.db2-wal}
db close
tvfs1 delete
tvfs2 delete
#-------------------------------------------------------------------------
# Check that only "" and "localhost" are acceptable as authorities.
#
catch {db close}
foreach {tn uri res} {
1 "file://localhost/PWD/test.db" {not an error}
2 "file:///PWD/test.db" {not an error}
3 "file:/PWD/test.db" {not an error}
4 "file://l%6Fcalhost/PWD/test.db" {invalid uri authority: l%6Fcalhost}
5 "file://lbcalhost/PWD/test.db" {invalid uri authority: lbcalhost}
6 "file://x/PWD/test.db" {invalid uri authority: x}
} {
if {$tcl_platform(platform)=="windows"} {
set uri [string map [list PWD [string range [pwd] 3 end]] $uri]
} else {
set uri [string map [list PWD [string range [pwd] 1 end]] $uri]
}
do_test 6.$tn {
set DB [sqlite3_open $uri]
sqlite3_errmsg $DB
} $res
catch { sqlite3_close $DB }
}
forcedelete test.db test.db2
do_test 7.1 {
sqlite3 db test.db
execsql {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
ATTACH 'test.db2' AS aux;
CREATE TABLE aux.t2(a, b);
INSERT INTO t1 VALUES('a', 'b');
}
db close
} {}
do_test 7.2 {
sqlite3 db file:test.db?mode=ro
execsql { ATTACH 'file:test.db2?mode=rw' AS aux }
} {}
do_execsql_test 7.3 {
INSERT INTO t2 VALUES('c', 'd')
} {}
do_catchsql_test 7.4 {
INSERT INTO t1 VALUES(3, 4)
} {1 {attempt to write a readonly database}}
finish_test
+159
View File
@@ -0,0 +1,159 @@
# 2011 May 09
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for using WAL databases in read-only mode.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set ::testprefix walro
do_multiclient_test tn {
# These tests are only going to work on unix.
#
if {$tcl_platform(platform) != "unix"} continue
# Do not run tests with the connections in the same process.
#
if {$tn==2} continue
# Close all connections and delete the database.
#
code1 { db close }
code2 { db2 close }
code3 { db3 close }
forcedelete test.db
forcedelete walro
foreach c {code1 code2 code3} {
$c {
sqlite3_shutdown
sqlite3_config_uri 1
}
}
file mkdir walro
do_test 1.1.1 {
code2 { sqlite3 db2 test.db }
sql2 {
PRAGMA journal_mode = WAL;
CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES('a', 'b');
}
file exists test.db-shm
} {1}
do_test 1.1.2 {
file attributes test.db-shm -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
} {}
do_test 1.1.3 { sql1 "SELECT * FROM t1" } {a b}
do_test 1.1.4 { sql2 "INSERT INTO t1 VALUES('c', 'd')" } {}
do_test 1.1.5 { sql1 "SELECT * FROM t1" } {a b c d}
# Check that the read-only connection cannot write or checkpoint the db.
#
do_test 1.1.6 {
csql1 "INSERT INTO t1 VALUES('e', 'f')"
} {1 {attempt to write a readonly database}}
do_test 1.1.7 {
csql1 "PRAGMA wal_checkpoint"
} {1 {attempt to write a readonly database}}
do_test 1.1.9 { sql2 "INSERT INTO t1 VALUES('e', 'f')" } {}
do_test 1.1.10 { sql1 "SELECT * FROM t1" } {a b c d e f}
do_test 1.1.11 {
sql2 {
INSERT INTO t1 VALUES('g', 'h');
PRAGMA wal_checkpoint;
}
set {} {}
} {}
do_test 1.1.12 { sql1 "SELECT * FROM t1" } {a b c d e f g h}
do_test 1.1.13 { sql2 "INSERT INTO t1 VALUES('i', 'j')" } {}
do_test 1.2.1 {
code2 { db2 close }
code1 { db close }
list [file exists test.db-wal] [file exists test.db-shm]
} {1 1}
do_test 1.2.2 {
code1 { sqlite3 db file:test.db?readonly_shm=1 }
sql1 { SELECT * FROM t1 }
} {a b c d e f g h i j}
do_test 1.2.3 {
code1 { db close }
file attributes test.db-shm -permissions rw-r--r--
hexio_write test.db-shm 0 01020304
file attributes test.db-shm -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
csql1 { SELECT * FROM t1 }
} {1 {attempt to write a readonly database}}
do_test 1.2.4 {
code1 { sqlite3_extended_errcode db }
} {SQLITE_READONLY_RECOVERY}
do_test 1.2.5 {
file attributes test.db-shm -permissions rw-r--r--
code2 { sqlite3 db2 test.db }
sql2 "SELECT * FROM t1"
} {a b c d e f g h i j}
file attributes test.db-shm -permissions r--r--r--
do_test 1.2.6 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j}
do_test 1.2.7 {
sql2 {
PRAGMA wal_checkpoint;
INSERT INTO t1 VALUES('k', 'l');
}
set {} {}
} {}
do_test 1.2.8 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j k l}
# Now check that if the readonly_shm option is not supplied, or if it
# is set to zero, it is not possible to connect to the database without
# read-write access to the shm.
do_test 1.3.1 {
code1 { db close }
code1 { sqlite3 db test.db }
csql1 { SELECT * FROM t1 }
} {1 {unable to open database file}}
# Also test that if the -shm file can be opened for read/write access,
# it is, even if readonly_shm=1 is present in the URI.
do_test 1.3.2.1 {
code1 { db close }
code2 { db2 close }
file exists test.db-shm
} {0}
do_test 1.3.2.2 {
code1 { sqlite3 db file:test.db?readonly_shm=1 }
sql1 { SELECT * FROM t1 }
} {a b c d e f g h i j k l}
do_test 1.3.2.3 {
code1 { db close }
close [open test.db-shm w]
file attributes test.db-shm -permissions r--r--r--
code1 { sqlite3 db file:test.db?readonly_shm=1 }
csql1 { SELECT * FROM t1 }
} {1 {attempt to write a readonly database}}
do_test 1.3.2.4 {
code1 { sqlite3_extended_errcode db }
} {SQLITE_READONLY_RECOVERY}
}
finish_test