Compare commits

...

9 Commits

Author SHA1 Message Date
drh 281dd84368 Sync the database file after a rollback. This is a cherrypick merge
of check-in [b21b911f23].

FossilOrigin-Name: 82dd61fccff3e4c77e060e5734cd4b4e2eeb7c32
2010-03-22 23:55:10 +00:00
drh 0a90717786 Modify the sqlite3_log() interface and implementation so that it never uses
dynamic memory allocation - to avoid deadlocking when called while holding 
the memory allocator mutex.  Cherry-pick merge of [28d1bc98d6].

FossilOrigin-Name: 6f368b5448363ae497bd4ff49b4ceeafb27f8cb3
2010-03-03 22:40:09 +00:00
drh 15678fa223 When TEMP files are in memory, also put the massive TEMP file used by
the VACUUM command in memory.  This is a cherry-pick merge of
[9daf4e7d07]

FossilOrigin-Name: e5342234357dcfde33fb7589f87d64f6de7d9970
2010-03-03 00:02:58 +00:00
drh f231da7e1a Expire pragma statements when reset, even if they were not run to completion.
FossilOrigin-Name: b8fbf4275bded6680e368a6a8343866467bd7e22
2010-02-25 14:56:29 +00:00
drh 75fcb3bd4b Merge in all of the logging enhancements. This is a cherrypick merge of
the following check-ins: [103321e37a], [a8076aede3], [6d910245ad], 
[7c4cca6d1a], [edea3bb740], [1a6d4bb130], [a8c984c1d6], [69a493182f], and
[1168763d2c].

FossilOrigin-Name: 46f406b2022b534f396491c04adad8a2012b8fcb
2010-02-25 02:32:28 +00:00
drh e5ae4a3b45 Fix a segfault that is possible for an OOM fault in ATTACH when in
shared-cache mode.  This is a cherrypick merge of check-in [e37137376a].

FossilOrigin-Name: f73cc0e9af5e4b7a15e8947c412966f9e9935f8b
2010-02-25 02:11:22 +00:00
drh 8d40cb7a5f Enhance integrity_check to detect out-of-order rowids. This is a
cherrypick merge of check-in [cae47c5b09].

FossilOrigin-Name: ecd22ef34d5cd516d2b6138f8b80c39daad3519d
2010-02-25 02:04:35 +00:00
drh 9b7e9ff6a0 Merge in the fix for VACUUM on auto_vacuumed databases with large schemas.
Check-in [86d50ce57f].  Ticket [da1151f97df].

FossilOrigin-Name: ce624e39c2f7c5480937a8d2007e7ebd684665dc
2010-02-25 01:54:06 +00:00
drh e79619b822 Start a new branch for release 3.6.22 plus limited enhancements and fixes.
This first check-in includes the performance enhancements of check-ins
[26cb1df735], [61a2c8d4d6], and [27dc5b1c52]

FossilOrigin-Name: 9588259882541e215813f48ccfa9180d8013a876
2010-02-25 01:47:15 +00:00
44 changed files with 1263 additions and 783 deletions
+49 -48
View File
@@ -1,8 +1,8 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Version\s3.6.22\sRelease\sCandidate\s2
D 2010-01-05T15:30:36
C Sync\sthe\sdatabase\sfile\safter\sa\srollback.\s\sThis\sis\sa\scherrypick\smerge\nof\scheck-in\s[b21b911f23].
D 2010-03-22T23:55:10
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -105,25 +105,25 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c 92ba938565d7cc6bfe92aad6cc90c00800ff21d3
F src/analyze.c 55155f05ee9ab4ce33b7a4d19c449053f8935200
F src/attach.c 0ba38b38252a34bb9721de35514a1d14058a8e49
F src/analyze.c 92a65a5a402898a52b03695c7f0cd383724d711f
F src/attach.c ba4a14632976e26d121fe6015c41f768cd6920dc
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 744e98359dfc79fed43e8dec911e33e108b06aae
F src/backup.c b293534bc2df23c57668a585b17ee7faaaef0939
F src/bitvec.c 06ad2c36a9c3819c0b9cbffec7b15f58d5d834e0
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
F src/btree.c efdef3953c49e28f8b8fa9cc0ac5754cc1a7489a
F src/btree.c 5f00d6dd5c20de6ce82f39b62416ead4889afcdc
F src/btree.h 7944a9dac59eb3e541aad45fd2747f1051e7c63d
F src/btreeInt.h 54f4245decd0409ea52cf9aee422d3d761d7ac10
F src/build.c 6ab7f8d8fa5b0ac6bfdce359e85f580b7a9b2e86
F src/build.c ffad52833f5fb513b4eb0c751d06da22ec387ae2
F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f
F src/complete.c 4c8a742c4a4a6d9c835912648f5c8f032ea36c7b
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f
F src/delete.c 610dc008e88a9599f905f5cbe9577ac9c36e0581
F src/expr.c d695300ba8b7a42d6b27a52d0288b974c89bf698
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0
F src/func.c 69906340991919b4933dd8630774ad069e4d582e
F src/global.c 75946a4a2ab41c6ae58f10ca0ed31b3449694b26
F src/global.c 5a9c1e3c93213ca574786ac1caa976ce8f709105
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@@ -132,13 +132,13 @@ F src/journal.c b0ea6b70b532961118ab70301c00a33089f9315c
F src/legacy.c 9304428e71b1d622b764913e1432e69156814755
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581
F src/main.c a0f6dfbdd79e01baf75ad62bdbfdeae9e560eb96
F src/main.c 0d9826f7376f3b3692ec467d3af72172785d6bac
F src/malloc.c 5fa175797f982b178eaf38afba9c588a866be729
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 552f7e11486272f27948d2de9c012884d1f52908
F src/mem1.c 07a57cbdffb8cbc83979e6edd8dd1fa60f5f3828
F src/mem2.c 92b4f772b1ee7469e256f1c2eff0b51a0ba19460
F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
F src/mem5.c 4837b795ebdecc0cfe1522cd0c8b2c5d84ea490d
F src/mem5.c eb7a5cb98915dd7a086fa415ce3a5a0f20d0acff
F src/memjournal.c 5bfc2f33c914946e2f77ed3f882aff14dfc9355d
F src/mutex.c 581a272e09098040ca3ef543cb5f3d643eff7d50
F src/mutex.h 6fde601e55fa6c3fae768783c439797ab84c87c6
@@ -151,27 +151,27 @@ F src/os.c 4500ff276e277730776fe9b6c6c5930383ec4000
F src/os.h 534b082c3cb349ad05fa6fa0b06087e022af282c
F src/os_common.h 240c88b163b02c21a9f21f87d49678a0aa21ff30
F src/os_os2.c 75a8c7b9a00a2cf1a65f9fa4afbc27d46634bb2f
F src/os_unix.c b24510792108ffee0c8175c1d2fc644913b241d2
F src/os_win.c 5ffab20249a61e0625f869efe157fa009747039b
F src/pager.c e5421d38470fe58faee71a5a66a778ada882394c
F src/os_unix.c bf7f66b06d9f507b049de647fc725fcd20bb647f
F src/os_win.c 1c7453c2df4dab26d90ff6f91272aea18bcf7053
F src/pager.c cba88e3121d37be873e650ae0203527483965788
F src/pager.h 1b32faf2e578ac3e7bcf9c9d11217128261c5c54
F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
F src/pcache.c 3b079306376e0e04c0d3df40c0a4b750a1839310
F src/pcache.c 4956b41d6ba913f7a8a56fbf32be78caed0e45c2
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c 2bb2261190b42a348038f5b1c285c8cef415fcc8
F src/pragma.c 6936d7df5e04b9f996f8f320d15e65b6944b2caa
F src/prepare.c 170bd953058efe1c46b8ad9020d49cd6f40f0b45
F src/printf.c 644bc7d59df3dc56d6d8b9a510914bfc6b51bc69
F src/pragma.c f37f33665b02447d83669620ddc1fd4fd1f70b0a
F src/prepare.c dede8f2d7f5810cea08ab7a4ced02fcc2d6478e9
F src/printf.c 7c2ae3a3c1833691bfbeed85f75125d8752b278e
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 69a45df25039eb58e321653914ad670ffe49d486
F src/resolve.c 8e51ac017123b86f35de30ccdb0f18c73963c979
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 0109b993c360d649857523abb72919e1794f9b45
F src/shell.c b95c5fcfe458027f192914a47474652969a1ec0f
F src/sqlite.h.in d493cf5029de67fe7252324473d89140a007a6c4
F src/shell.c 546fe4b6df101c6cc3d08aa7b7b414136ce03ffc
F src/sqlite.h.in e8e40f18450884f2693f330ff5956fd920678fd1
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
F src/sqliteInt.h d6c48b1a5cd6485151e1d1b071dbe0a85ceb70fe
F src/sqliteInt.h 4d7df175023a23232cc0abc07b51081ef9a61cec
F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6
F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7
F src/status.c d329385a2cba3ea49d9d68af0ad84b22d46b4f40
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c bad6570a005b234ea670b9f7b48256da19a032d3
F src/test1.c db4d8fd2849ab9aca0f27fd3773b8d68d078cf86
@@ -206,23 +206,23 @@ F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c 00fed80690ae7f1525483a35861511c48bc579f2
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c e7f3606cc1b51a819a2bfee99100648d35bc791d
F src/tokenize.c 25ceb0f0a746ea1d0f9553787f3f0a56853cfaeb
F src/trigger.c d46f9389e3bf3dd1cc1d288aba2f289c96b34200
F src/update.c c0dc6b75ad28b76b619042d934f337b02acee208
F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052
F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592
F src/vacuum.c db6415fd0f1be191e16228457a6deb9f232e6ad6
F src/vdbe.c e05765736504d9dbcbb3dfa8964932780002ec39
F src/vdbe.h bea1f0cd530775bdb58a340265f3cf3ee920e9b2
F src/vdbeInt.h d7ea821ac7813c9bea0fe87558c35e07b2c7c44d
F src/vdbeapi.c fc3787eb2f5487d4cc3444de42d56f2e39d311f5
F src/vdbeaux.c 2e4a421bd3771ecd3b6c9a1c7abc7270a787a01b
F src/vdbeblob.c 84f924700a7a889152aeebef77ca5f4e3875ffb4
F src/util.c 56008ded7b0695939f1127b47c195525fde10276
F src/vacuum.c 137a2f494eaa12976e598a4c3299613c8f7c1039
F src/vdbe.c 1a07ddbd03ff7f8334da9467214fe9dab7176e98
F src/vdbe.h 471f6a3dcec4817ca33596fe7f6654d56c0e75f3
F src/vdbeInt.h 15d418f4c63647886cef5c71a8fb9db36bea07e3
F src/vdbeapi.c 95e66cf3cb0841134154f1d05b0de58ddaec5553
F src/vdbeaux.c 7379f5bd3809aebc109f6c2216267a4e4bd092c4
F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e
F src/vdbemem.c 1e16e3a16e55f4c3452834f0e041726021aa66e0
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
F src/vtab.c 7c7713d66cda699f16bf1cc601d8d4f5070ab935
F src/vtab.c 606adf51cd6d4ba51a8c6dccede06a6f7b0dd72d
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 43b11af016ac50724a95397c0ca447cae88f3c11
F src/where.c 0fab05c99228e3d4c1fed231d02860a14f5ec0f2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
@@ -233,7 +233,7 @@ F test/alter4.test 9386ffd1e9c7245f43eca412b2058d747509cc1f
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/analyze.test ad5329098fe4de4a96852231d53e3e9e6283ad4b
F test/analyze2.test a2ad7b0a4e13801ee3968fe70f22aff52326569c
F test/analyze3.test ae06e0f8b3eaae0dd644ac9ac9d617058b5ac131
F test/analyze3.test 506203875258ffd8ffa879b9c3c5432022d2b6d8
F test/async.test 8c75d31b8330f8b70cf2571b014d4476a063efdb
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
@@ -242,7 +242,7 @@ F test/async5.test f3592d79c84d6e83a5f50d3fd500445f7d97dfdf
F test/attach.test ce9660e51768fab93cf129787be886c5d6c4fd81
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
F test/attach3.test bd9830bc3a0d22ed1310c9bff6896927937017dc
F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61
F test/attachmalloc.test 38d2da5fdaf09ba0add57296967a3061e5842584
F test/auth.test 8f21c160a4562f54f27618e85bac869efcecbcaf
F test/auth2.test ee3ba272e2b975e913afc9b041ee75706e190005
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
@@ -275,7 +275,7 @@ F test/cache.test 3ff445c445742a7b6b9ba6e1d62a25263f9424b9
F test/capi2.test 172c717ed101e78e0798dd21b9896a22366f35b4
F test/capi3.test 168e2cd66c58c510955b0f299750e4de73b8d952
F test/capi3b.test 664eb55318132f292f2c436f90906f578cad6b97
F test/capi3c.test d9d293ce8fd4dc2944ce2dae5718fc7a6184a567
F test/capi3c.test 493385107dcedfaf4f2b1c3738c8c1fa00362006
F test/capi3d.test 57d83b690d7364bde02cddbf8339a4b50d80ce23
F test/cast.test 166951664a0b0a2e0f8fb5997a152490c6363932
F test/check.test db2b29d557544347d28e25b8406f5d5ecc3d1bc3
@@ -299,13 +299,14 @@ F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32
F test/corrupt4.test acdb01afaedf529004b70e55de1a6f5a05ae7fff
F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff
F test/corrupt6.test e69b877d478224deab7b66844566258cecacd25e
F test/corrupt7.test e66cb109ed64e7ac985d8b4a3422c213d074c62d
F test/corrupt7.test 1eb2214f29474fa6b155aa3da8a7d46bf52089e1
F test/corrupt8.test 9992ef7f67cefc576b92373f6bf5ab8775280f51
F test/corrupt9.test 4aa1cb1ef091cb0e13e89a819c72911631b5176a
F test/corruptA.test 99e95620b980161cb3e79f06a884a4bb8ae265ff
F test/corruptB.test 66b4544104dd03d0f33ea69ddac3fa4a682cd3c2
F test/corruptC.test 691ed070baef5e1345939caadf270a52837a5064
F test/corruptD.test 3ae6e2dc6e2226c6935a8a40d4b5ee3eba75f8c0
F test/corruptE.test dbf66cae4c0e977ca9625a9114cdd01df8967bef
F test/count.test 454e1ce985c94d13efeac405ce54439f49336163
F test/crash.test 1b6ac8410689ff78028887f445062dc897c9ac89
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
@@ -314,7 +315,7 @@ F test/crash4.test 02ff4f15c149ca1e88a5c299b4896c84d9450c3b
F test/crash5.test 80a2f7073381837fc082435c97df52a830abcd80
F test/crash6.test 9c730cf06335003cb1f5cfceddacd044155336e0
F test/crash7.test e20a7b9ee1d16eaef7c94a4cb7ed2191b4d05970
F test/crash8.test 5b32966fcb58fd616d24ce94303420351d076eb9
F test/crash8.test 167fbacd3e301c54c69930432134d9e4e86a1ac3
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
@@ -539,14 +540,13 @@ F test/rollback.test 73355ad4492ff9a3a31e61c7e5eb5e01a1de94ca
F test/rowhash.test 97f56043ba11f0679920416c0cdbc72e5272267b
F test/rowid.test e58e0acef38b527ed1b0b70d3ada588f804af287
F test/rtree.test 55466a200af3591946c5da77ad5dbfbc1e5e05f9
F test/safety.test b69e2b2dd5d52a3f78e216967086884bbc1a09c6
F test/savepoint.test f2ede4b643ad87ead36c041c72d774a1f5c8a564
F test/savepoint2.test 427c8b20f43d3edf17a290c6788ae9e2703ac51c
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test 2df1d093e59e78d688c64eb20e0457aaea7d08f9
F test/schema.test 23a2909d2b1f8494d28d355c1254f075b0af8ffc
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/select1.test f67ca2dfc05df41c7b86eb32ca409b427a5f43b0
F test/select2.test 9735da20ccd41e42bf2b4c19fd939141b591adae
@@ -724,6 +724,7 @@ F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test 68e39b2228b4b772166debef4a82accf6ddd32f3
F test/vacuum2.test ec57f21d394b7b72249b11f8e4b5d487bab56539
F test/vacuum3.test f39ad1428347c5808cd2da7578c470f186a4d0ce
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test e265401afefa994cdf2fe4b6f286b1e87c2f9b9d
F test/view.test 45f518205ecdb6dd23a86dd4a99bb4ae945e625d
@@ -786,14 +787,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 4ecb4725b76042ac414caf90039d5d0a5f8f7068
R 8c69565948e98c03e3dd1dcbed92c860
P 6f368b5448363ae497bd4ff49b4ceeafb27f8cb3
R bd630940bca5e76dbf9cec59380fa024
U drh
Z ced91d02ef4d59db7742a1c68eea0156
Z 7127016c75143e7ed652563bb0f1fa6a
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFLQ1sfoxKgR168RlERAoMSAJ4oSysPgDgbT0TYZR0idPBdpGRnXACfQOVY
SZcqrXAqkdego3RbALXEHK4=
=UKAs
iD8DBQFLqANioxKgR168RlERAgaVAKCHSUDoxuCNvq2jkAczXOPrZ/vbGQCfasQl
MjTiX811W87HBuGmIpQZpqU=
=gXTK
-----END PGP SIGNATURE-----
+1 -1
View File
@@ -1 +1 @@
28d0d7710761114a44a1a3a425a6883c661f06e7
82dd61fccff3e4c77e060e5734cd4b4e2eeb7c32
-6
View File
@@ -559,9 +559,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
(void)sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
(void)sqlite3SafetyOn(db);
sqlite3DbFree(db, zSql);
}
@@ -579,14 +577,11 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
(void)sqlite3SafetyOff(db);
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
(void)sqlite3SafetyOn(db);
sqlite3DbFree(db, zSql);
}
if( rc==SQLITE_OK ){
(void)sqlite3SafetyOff(db);
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char *zIndex = (char *)sqlite3_column_text(pStmt, 0);
Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase);
@@ -636,7 +631,6 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
}
}
rc = sqlite3_finalize(pStmt);
(void)sqlite3SafetyOn(db);
}
}
#endif
+5 -3
View File
@@ -145,8 +145,12 @@ static void attachFunc(
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
sqlite3PagerJournalMode(pPager, db->dfltJournalMode);
}
aNew->zName = sqlite3DbStrDup(db, zName);
aNew->safety_level = 3;
aNew->zName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && aNew->zName==0 ){
rc = SQLITE_NOMEM;
}
#if SQLITE_HAS_CODEC
if( rc==SQLITE_OK ){
@@ -184,11 +188,9 @@ static void attachFunc(
** we found it.
*/
if( rc==SQLITE_OK ){
(void)sqlite3SafetyOn(db);
sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrDyn);
sqlite3BtreeLeaveAll(db);
(void)sqlite3SafetyOff(db);
}
if( rc ){
int iDb = db->nDb - 1;
+1 -1
View File
@@ -98,10 +98,10 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
}else{
pParse->db = pDb;
if( sqlite3OpenTempDatabase(pParse) ){
sqlite3ErrorClear(pParse);
sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
rc = SQLITE_ERROR;
}
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
sqlite3StackFree(pErrorDb, pParse);
}
if( rc ){
+59 -8
View File
@@ -5901,7 +5901,7 @@ static int balance_nonroot(
if( leafData ){ i--; }
subtotal = 0;
k++;
if( k>NB+1 ){ rc = SQLITE_CORRUPT; goto balance_cleanup; }
if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
}
}
szNew[k] = subtotal;
@@ -5955,7 +5955,7 @@ static int balance_nonroot(
** Allocate k new pages. Reuse old pages where possible.
*/
if( apOld[0]->pgno<=1 ){
rc = SQLITE_CORRUPT;
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
pageFlags = apOld[0]->aData[0];
@@ -7393,7 +7393,9 @@ static void checkList(
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
char *zParentContext /* Parent context */
char *zParentContext, /* Parent context */
i64 *pnParentMinKey,
i64 *pnParentMaxKey
){
MemPage *pPage;
int i, rc, depth, d2, pgno, cnt;
@@ -7404,6 +7406,8 @@ static int checkTreePage(
int usableSize;
char zContext[100];
char *hit = 0;
i64 nMinKey = 0;
i64 nMaxKey = 0;
sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
@@ -7446,6 +7450,16 @@ static int checkTreePage(
btreeParseCellPtr(pPage, pCell, &info);
sz = info.nData;
if( !pPage->intKey ) sz += (int)info.nKey;
/* For intKey pages, check that the keys are in order.
*/
else if( i==0 ) nMinKey = nMaxKey = info.nKey;
else{
if( info.nKey <= nMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
}
nMaxKey = info.nKey;
}
assert( sz==info.nPayload );
if( (sz>info.nLocal)
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
@@ -7469,25 +7483,62 @@ static int checkTreePage(
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
d2 = checkTreePage(pCheck, pgno, zContext);
d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, zContext, "Child page depth differs");
}
depth = d2;
}
}
if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
sqlite3_snprintf(sizeof(zContext), zContext,
"On page %d at right child: ", iPage);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
checkTreePage(pCheck, pgno, zContext);
checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
}
/* For intKey leaf pages, check that the min/max keys are in order
** with any left/parent/right pages.
*/
if( pPage->leaf && pPage->intKey ){
/* if we are a left child page */
if( pnParentMinKey ){
/* if we are the left most child page */
if( !pnParentMaxKey ){
if( nMaxKey > *pnParentMinKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent min of %lld)",
nMaxKey, *pnParentMinKey);
}
}else{
if( nMinKey <= *pnParentMinKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent min of %lld)",
nMinKey, *pnParentMinKey);
}
if( nMaxKey > *pnParentMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent max of %lld)",
nMaxKey, *pnParentMaxKey);
}
*pnParentMinKey = nMaxKey;
}
/* else if we're a right child page */
} else if( pnParentMaxKey ){
if( nMinKey <= *pnParentMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent max of %lld)",
nMinKey, *pnParentMaxKey);
}
}
}
/* Check for complete coverage of the page
*/
data = pPage->aData;
@@ -7511,7 +7562,7 @@ static int checkTreePage(
}
if( (pc+size-1)>=usableSize ){
checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage,0);
"Corruption detected in cell %d on page %d",i,iPage);
}else{
for(j=pc+size-1; j>=pc; j--) hit[j]++;
}
@@ -7617,7 +7668,7 @@ char *sqlite3BtreeIntegrityCheck(
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
}
#endif
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ");
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
}
/* Make sure every page in the file is referenced
+2 -3
View File
@@ -1974,13 +1974,12 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( noErr ) db->suppressErr++;
pTab = sqlite3LocateTable(pParse, isView,
pName->a[0].zName, pName->a[0].zDatabase);
if( noErr ) db->suppressErr--;
if( pTab==0 ){
if( noErr ){
sqlite3ErrorClear(pParse);
}
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+283 -283
View File
@@ -1,283 +1,283 @@
/*
** 2001 September 15
**
** 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.
**
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that implements the sqlite3_complete() API.
** This code used to be part of the tokenizer.c source file. But by
** separating it out, the code will be automatically omitted from
** static links that do not use it.
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_COMPLETE
/*
** This is defined in tokenize.c. We just have to import the definition.
*/
#ifndef SQLITE_AMALGAMATION
#ifdef SQLITE_ASCII
#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
#endif
#ifdef SQLITE_EBCDIC
extern const char sqlite3IsEbcdicIdChar[];
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
#endif
#endif /* SQLITE_AMALGAMATION */
/*
** Token types used by the sqlite3_complete() routine. See the header
** comments on that procedure for additional information.
*/
#define tkSEMI 0
#define tkWS 1
#define tkOTHER 2
#ifndef SQLITE_OMIT_TRIGGER
#define tkEXPLAIN 3
#define tkCREATE 4
#define tkTEMP 5
#define tkTRIGGER 6
#define tkEND 7
#endif
/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
** This implementation uses a state machine with 8 states:
**
** (0) INVALID We have not yet seen a non-whitespace character.
**
** (1) START At the beginning or end of an SQL statement. This routine
** returns 1 if it ends in the START state and 0 if it ends
** in any other state.
**
** (2) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (4) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
** (5) TRIGGER We are in the middle of a trigger definition that must be
** ended by a semicolon, the keyword END, and another semicolon.
**
** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at
** the end of a trigger definition.
**
** (7) END We've seen the ";END" of the ";END;" that occurs at the end
** of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
**
** (0) tkSEMI A semicolon.
** (1) tkWS Whitespace.
** (2) tkOTHER Any other SQL token.
** (3) tkEXPLAIN The "explain" keyword.
** (4) tkCREATE The "create" keyword.
** (5) tkTEMP The "temp" or "temporary" keyword.
** (6) tkTRIGGER The "trigger" keyword.
** (7) tkEND The "end" keyword.
**
** Whitespace never causes a state transition and is always ignored.
** This means that a SQL string of all whitespace is invalid.
**
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
** to recognize the end of a trigger can be omitted. All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
#ifndef SQLITE_OMIT_TRIGGER
/* A complex statement machine used to detect the end of a CREATE TRIGGER
** statement. This is the normal case.
*/
static const u8 trans[8][8] = {
/* Token: */
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
/* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, },
/* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, },
/* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, },
/* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, },
/* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, },
/* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, },
/* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, },
/* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, },
};
#else
/* If triggers are not supported by this compile then the statement machine
** used to detect the end of a statement is much simplier
*/
static const u8 trans[3][3] = {
/* Token: */
/* State: ** SEMI WS OTHER */
/* 0 INVALID: */ { 1, 0, 2, },
/* 1 START: */ { 1, 1, 2, },
/* 2 NORMAL: */ { 1, 2, 2, },
};
#endif /* SQLITE_OMIT_TRIGGER */
while( *zSql ){
switch( *zSql ){
case ';': { /* A semicolon */
token = tkSEMI;
break;
}
case ' ':
case '\r':
case '\t':
case '\n':
case '\f': { /* White space is ignored */
token = tkWS;
break;
}
case '/': { /* C-style comments */
if( zSql[1]!='*' ){
token = tkOTHER;
break;
}
zSql += 2;
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
if( zSql[0]==0 ) return 0;
zSql++;
token = tkWS;
break;
}
case '-': { /* SQL-style comments from "--" to end of line */
if( zSql[1]!='-' ){
token = tkOTHER;
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
if( *zSql==0 ) return state==1;
token = tkWS;
break;
}
case '[': { /* Microsoft-style identifiers in [...] */
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
case '`': /* Grave-accent quoted symbols used by MySQL */
case '"': /* single- and double-quoted strings */
case '\'': {
int c = *zSql;
zSql++;
while( *zSql && *zSql!=c ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
default: {
#ifdef SQLITE_EBCDIC
unsigned char c;
#endif
if( IdChar((u8)*zSql) ){
/* Keywords and unquoted identifiers */
int nId;
for(nId=1; IdChar(zSql[nId]); nId++){}
#ifdef SQLITE_OMIT_TRIGGER
token = tkOTHER;
#else
switch( *zSql ){
case 'c': case 'C': {
if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
token = tkCREATE;
}else{
token = tkOTHER;
}
break;
}
case 't': case 'T': {
if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
token = tkTRIGGER;
}else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
token = tkTEMP;
}else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
token = tkTEMP;
}else{
token = tkOTHER;
}
break;
}
case 'e': case 'E': {
if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
token = tkEND;
}else
#ifndef SQLITE_OMIT_EXPLAIN
if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
token = tkEXPLAIN;
}else
#endif
{
token = tkOTHER;
}
break;
}
default: {
token = tkOTHER;
break;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
zSql += nId-1;
}else{
/* Operators and special symbols */
token = tkOTHER;
}
break;
}
}
state = trans[state][token];
zSql++;
}
return state==1;
}
#ifndef SQLITE_OMIT_UTF16
/*
** This routine is the same as the sqlite3_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
int sqlite3_complete16(const void *zSql){
sqlite3_value *pVal;
char const *zSql8;
int rc = SQLITE_NOMEM;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ) return rc;
#endif
pVal = sqlite3ValueNew(0);
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zSql8 ){
rc = sqlite3_complete(zSql8);
}else{
rc = SQLITE_NOMEM;
}
sqlite3ValueFree(pVal);
return sqlite3ApiExit(0, rc);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_COMPLETE */
/*
** 2001 September 15
**
** 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.
**
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that implements the sqlite3_complete() API.
** This code used to be part of the tokenizer.c source file. But by
** separating it out, the code will be automatically omitted from
** static links that do not use it.
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_COMPLETE
/*
** This is defined in tokenize.c. We just have to import the definition.
*/
#ifndef SQLITE_AMALGAMATION
#ifdef SQLITE_ASCII
#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
#endif
#ifdef SQLITE_EBCDIC
extern const char sqlite3IsEbcdicIdChar[];
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
#endif
#endif /* SQLITE_AMALGAMATION */
/*
** Token types used by the sqlite3_complete() routine. See the header
** comments on that procedure for additional information.
*/
#define tkSEMI 0
#define tkWS 1
#define tkOTHER 2
#ifndef SQLITE_OMIT_TRIGGER
#define tkEXPLAIN 3
#define tkCREATE 4
#define tkTEMP 5
#define tkTRIGGER 6
#define tkEND 7
#endif
/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
** This implementation uses a state machine with 8 states:
**
** (0) INVALID We have not yet seen a non-whitespace character.
**
** (1) START At the beginning or end of an SQL statement. This routine
** returns 1 if it ends in the START state and 0 if it ends
** in any other state.
**
** (2) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (4) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
** (5) TRIGGER We are in the middle of a trigger definition that must be
** ended by a semicolon, the keyword END, and another semicolon.
**
** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at
** the end of a trigger definition.
**
** (7) END We've seen the ";END" of the ";END;" that occurs at the end
** of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
**
** (0) tkSEMI A semicolon.
** (1) tkWS Whitespace.
** (2) tkOTHER Any other SQL token.
** (3) tkEXPLAIN The "explain" keyword.
** (4) tkCREATE The "create" keyword.
** (5) tkTEMP The "temp" or "temporary" keyword.
** (6) tkTRIGGER The "trigger" keyword.
** (7) tkEND The "end" keyword.
**
** Whitespace never causes a state transition and is always ignored.
** This means that a SQL string of all whitespace is invalid.
**
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
** to recognize the end of a trigger can be omitted. All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
#ifndef SQLITE_OMIT_TRIGGER
/* A complex statement machine used to detect the end of a CREATE TRIGGER
** statement. This is the normal case.
*/
static const u8 trans[8][8] = {
/* Token: */
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
/* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, },
/* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, },
/* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, },
/* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, },
/* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, },
/* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, },
/* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, },
/* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, },
};
#else
/* If triggers are not supported by this compile then the statement machine
** used to detect the end of a statement is much simplier
*/
static const u8 trans[3][3] = {
/* Token: */
/* State: ** SEMI WS OTHER */
/* 0 INVALID: */ { 1, 0, 2, },
/* 1 START: */ { 1, 1, 2, },
/* 2 NORMAL: */ { 1, 2, 2, },
};
#endif /* SQLITE_OMIT_TRIGGER */
while( *zSql ){
switch( *zSql ){
case ';': { /* A semicolon */
token = tkSEMI;
break;
}
case ' ':
case '\r':
case '\t':
case '\n':
case '\f': { /* White space is ignored */
token = tkWS;
break;
}
case '/': { /* C-style comments */
if( zSql[1]!='*' ){
token = tkOTHER;
break;
}
zSql += 2;
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
if( zSql[0]==0 ) return 0;
zSql++;
token = tkWS;
break;
}
case '-': { /* SQL-style comments from "--" to end of line */
if( zSql[1]!='-' ){
token = tkOTHER;
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
if( *zSql==0 ) return state==1;
token = tkWS;
break;
}
case '[': { /* Microsoft-style identifiers in [...] */
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
case '`': /* Grave-accent quoted symbols used by MySQL */
case '"': /* single- and double-quoted strings */
case '\'': {
int c = *zSql;
zSql++;
while( *zSql && *zSql!=c ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
default: {
#ifdef SQLITE_EBCDIC
unsigned char c;
#endif
if( IdChar((u8)*zSql) ){
/* Keywords and unquoted identifiers */
int nId;
for(nId=1; IdChar(zSql[nId]); nId++){}
#ifdef SQLITE_OMIT_TRIGGER
token = tkOTHER;
#else
switch( *zSql ){
case 'c': case 'C': {
if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
token = tkCREATE;
}else{
token = tkOTHER;
}
break;
}
case 't': case 'T': {
if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
token = tkTRIGGER;
}else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
token = tkTEMP;
}else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
token = tkTEMP;
}else{
token = tkOTHER;
}
break;
}
case 'e': case 'E': {
if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
token = tkEND;
}else
#ifndef SQLITE_OMIT_EXPLAIN
if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
token = tkEXPLAIN;
}else
#endif
{
token = tkOTHER;
}
break;
}
default: {
token = tkOTHER;
break;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
zSql += nId-1;
}else{
/* Operators and special symbols */
token = tkOTHER;
}
break;
}
}
state = trans[state][token];
zSql++;
}
return state==1;
}
#ifndef SQLITE_OMIT_UTF16
/*
** This routine is the same as the sqlite3_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
int sqlite3_complete16(const void *zSql){
sqlite3_value *pVal;
char const *zSql8;
int rc = SQLITE_NOMEM;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ) return rc;
#endif
pVal = sqlite3ValueNew(0);
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zSql8 ){
rc = sqlite3_complete(zSql8);
}else{
rc = SQLITE_NOMEM;
}
sqlite3ValueFree(pVal);
return sqlite3ApiExit(0, rc);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_COMPLETE */
+2
View File
@@ -164,6 +164,8 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* isPCacheInit */
0, /* pInitMutex */
0, /* nRefInitMutex */
0, /* xLog */
0, /* pLogArg */
};
+41 -15
View File
@@ -257,7 +257,7 @@ int sqlite3_config(int op, ...){
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
** the SQLite library is in use. */
if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE;
if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT;
va_start(ap, op);
switch( op ){
@@ -378,6 +378,16 @@ int sqlite3_config(int op, ...){
sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
break;
}
/* Record a pointer to the logger funcction and its first argument.
** The default is NULL. Logging is disabled if the function pointer is
** NULL.
*/
case SQLITE_CONFIG_LOG: {
sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
break;
}
default: {
rc = SQLITE_ERROR;
@@ -591,7 +601,7 @@ int sqlite3_close(sqlite3 *db){
return SQLITE_OK;
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
@@ -938,7 +948,7 @@ int sqlite3CreateFunc(
(!xFunc && (!xFinal && xStep)) ||
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
#ifndef SQLITE_OMIT_UTF16
@@ -1269,7 +1279,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
return sqlite3ErrStr(SQLITE_NOMEM);
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
return sqlite3ErrStr(SQLITE_MISUSE);
return sqlite3ErrStr(SQLITE_MISUSE_BKPT);
}
sqlite3_mutex_enter(db->mutex);
if( db->mallocFailed ){
@@ -1338,7 +1348,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
*/
int sqlite3_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
if( !db || db->mallocFailed ){
return SQLITE_NOMEM;
@@ -1347,7 +1357,7 @@ int sqlite3_errcode(sqlite3 *db){
}
int sqlite3_extended_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
if( !db || db->mallocFailed ){
return SQLITE_NOMEM;
@@ -1385,7 +1395,7 @@ static int createCollation(
enc2 = SQLITE_UTF16NATIVE;
}
if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
/* Check if this call is removing or replacing an existing collation
@@ -1929,16 +1939,34 @@ int sqlite3_get_autocommit(sqlite3 *db){
return db->autoCommit;
}
#ifdef SQLITE_DEBUG
/*
** The following routine is subtituted for constant SQLITE_CORRUPT in
** debugging builds. This provides a way to set a breakpoint for when
** corruption is first detected.
** The following routines are subtitutes for constants SQLITE_CORRUPT,
** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error
** constants. They server two purposes:
**
** 1. Serve as a convenient place to set a breakpoint in a debugger
** to detect when version error conditions occurs.
**
** 2. Invoke sqlite3_log() to provide the source code location where
** a low-level error is first detected.
*/
int sqlite3Corrupt(void){
int sqlite3CorruptError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_CORRUPT,
"database corruption found by source line %d", lineno);
return SQLITE_CORRUPT;
}
#endif
int sqlite3MisuseError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_MISUSE, "misuse detected by source line %d", lineno);
return SQLITE_MISUSE;
}
int sqlite3CantopenError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_CANTOPEN, "cannot open file at source line %d", lineno);
return SQLITE_CANTOPEN;
}
#ifndef SQLITE_OMIT_DEPRECATED
/*
@@ -1982,7 +2010,6 @@ int sqlite3_table_column_metadata(
/* Ensure the database schema has been loaded */
sqlite3_mutex_enter(db->mutex);
(void)sqlite3SafetyOn(db);
sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrMsg);
if( SQLITE_OK!=rc ){
@@ -2041,7 +2068,6 @@ int sqlite3_table_column_metadata(
error_out:
sqlite3BtreeLeaveAll(db);
(void)sqlite3SafetyOff(db);
/* Whether the function call succeeded or failed, set the output parameters
** to whatever their local counterparts contain. If an error did occur,
+20 -12
View File
@@ -42,6 +42,9 @@ static void *sqlite3MemMalloc(int nByte){
if( p ){
p[0] = nByte;
p++;
}else{
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
}
return (void *)p;
}
@@ -61,6 +64,18 @@ static void sqlite3MemFree(void *pPrior){
free(p);
}
/*
** Report the allocated size of a prior return from xMalloc()
** or xRealloc().
*/
static int sqlite3MemSize(void *pPrior){
sqlite3_int64 *p;
if( pPrior==0 ) return 0;
p = (sqlite3_int64*)pPrior;
p--;
return (int)p[0];
}
/*
** Like realloc(). Resize an allocation previously obtained from
** sqlite3MemMalloc().
@@ -81,22 +96,15 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
if( p ){
p[0] = nByte;
p++;
}else{
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM,
"failed memory resize %u to %u bytes",
sqlite3MemSize(pPrior), nByte);
}
return (void*)p;
}
/*
** Report the allocated size of a prior return from xMalloc()
** or xRealloc().
*/
static int sqlite3MemSize(void *pPrior){
sqlite3_int64 *p;
if( pPrior==0 ) return 0;
p = (sqlite3_int64*)pPrior;
p--;
return (int)p[0];
}
/*
** Round up a request size to the next valid allocation size.
*/
+5 -1
View File
@@ -268,7 +268,11 @@ static void *memsys5MallocUnsafe(int nByte){
** two in order to create a new free block of size iLogsize.
*/
for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
if( iBin>LOGMAX ) return 0;
if( iBin>LOGMAX ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
return 0;
}
i = memsys5UnlinkFirst(iBin);
while( iBin>iLogsize ){
int newSize;
+189 -6
View File
@@ -1096,7 +1096,7 @@ static int transferOwnership(unixFile *pFile){
}
if( pFile->locktype!=NO_LOCK ){
/* We cannot change ownership while we are holding a lock! */
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
OSTRACE4("Transfer ownership of %d from %d to %d\n",
pFile->h, pFile->tid, hSelf);
@@ -1543,7 +1543,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){
return SQLITE_OK;
}
if( CHECK_THREADID(pFile) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
unixEnterMutex();
h = pFile->h;
@@ -2645,7 +2645,7 @@ static int afpUnlock(sqlite3_file *id, int locktype) {
return SQLITE_OK;
}
if( CHECK_THREADID(pFile) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
unixEnterMutex();
if( pFile->locktype>SHARED_LOCK ){
@@ -3695,7 +3695,7 @@ static int openDirectory(const char *zFilename, int *pFd){
}
}
*pFd = fd;
return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN);
return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN_BKPT);
}
/*
@@ -3955,7 +3955,7 @@ static int unixOpen(
fd = open(zName, openFlags, openMode);
}
if( fd<0 ){
rc = SQLITE_CANTOPEN;
rc = SQLITE_CANTOPEN_BKPT;
goto open_finished;
}
}
@@ -4154,7 +4154,7 @@ static int unixFullPathname(
}else{
int nCwd;
if( getcwd(zOut, nOut-1)==0 ){
return SQLITE_CANTOPEN;
return SQLITE_CANTOPEN_BKPT;
}
nCwd = (int)strlen(zOut);
sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
@@ -4740,6 +4740,50 @@ static int proxyCreateUnixFile(const char *path, unixFile **ppFile) {
** unixOpen() is NULL. This tells unixOpen() may try to open a proxy-file
** for the proxy-file (creating a potential infinite loop).
*/
pUnused = findReusableFd(path, openFlags);
if( pUnused ){
fd = pUnused->fd;
}else{
pUnused = sqlite3_malloc(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM;
}
}
if( fd<0 ){
fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
terrno = errno;
if( fd<0 && errno==ENOENT && islockfile ){
if( proxyCreateLockPath(path) == SQLITE_OK ){
fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
}
}
}
if( fd<0 ){
openFlags = O_RDONLY;
fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
terrno = errno;
}
if( fd<0 ){
if( islockfile ){
return SQLITE_BUSY;
}
switch (terrno) {
case EACCES:
return SQLITE_PERM;
case EIO:
return SQLITE_IOERR_LOCK; /* even though it is the conch */
default:
return SQLITE_CANTOPEN_BKPT;
}
}
pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
if( pNew==NULL ){
rc = SQLITE_NOMEM;
goto end_create_proxy;
}
memset(pNew, 0, sizeof(unixFile));
pNew->openFlags = openFlags;
dummyVfs.pAppData = (void*)&autolockIoFinder;
dummyVfs.xOpen = 0;
rc = unixOpen(&dummyVfs, path, (sqlite3_file *)pNew, flags, &flags);
@@ -4904,11 +4948,150 @@ end_takeconch:
pCtx->lockProxyPath;
}
}
>>>>>>> BEGIN MERGE CONFLICT
/* if the conch isn't writable and doesn't match, we can't take it */
if( (conchFile->openFlags&O_RDWR) == 0 ){
rc = SQLITE_BUSY;
goto end_takeconch;
}
/* either the conch didn't match or we need to create a new one */
if( !pCtx->lockProxyPath ){
proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
tempLockPath = lockPath;
/* create a copy of the lock path _only_ if the conch is taken */
}
/* update conch with host and path (this will fail if other process
** has a shared lock already), if the host id matches, use the big
** stick.
*/
futimes(conchFile->h, NULL);
if( hostIdMatch && !createConch ){
if( conchFile->pLock && conchFile->pLock->cnt>1 ){
/* We are trying for an exclusive lock but another thread in this
** same process is still holding a shared lock. */
rc = SQLITE_BUSY;
} else {
rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
}
}else{
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
}
if( rc==SQLITE_OK ){
char writeBuffer[PROXY_MAXCONCHLEN];
int writeSize = 0;
writeBuffer[0] = (char)PROXY_CONCHVERSION;
memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
if( pCtx->lockProxyPath!=NULL ){
strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
}else{
strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
}
writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
ftruncate(conchFile->h, writeSize);
rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
fsync(conchFile->h);
/* If we created a new conch file (not just updated the contents of a
** valid conch file), try to match the permissions of the database
*/
if( rc==SQLITE_OK && createConch ){
struct stat buf;
int err = fstat(pFile->h, &buf);
if( err==0 ){
mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
S_IROTH|S_IWOTH);
/* try to match the database file R/W permissions, ignore failure */
#ifndef SQLITE_PROXY_DEBUG
fchmod(conchFile->h, cmode);
#else
if( fchmod(conchFile->h, cmode)!=0 ){
int code = errno;
fprintf(stderr, "fchmod %o FAILED with %d %s\n",
cmode, code, strerror(code));
} else {
fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
}
}else{
int code = errno;
fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
err, code, strerror(code));
#endif
}
}
}
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
end_takeconch:
OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h);
if( rc==SQLITE_OK && pFile->openFlags ){
if( pFile->h>=0 ){
#ifdef STRICT_CLOSE_ERROR
if( close(pFile->h) ){
pFile->lastErrno = errno;
return SQLITE_IOERR_CLOSE;
}
#else
close(pFile->h); /* silently leak fd if fail */
#endif
}
pFile->h = -1;
int fd = open(pCtx->dbPath, pFile->openFlags,
SQLITE_DEFAULT_FILE_PERMISSIONS);
OSTRACE2("TRANSPROXY: OPEN %d\n", fd);
if( fd>=0 ){
pFile->h = fd;
}else{
rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
during locking */
}
}
if( rc==SQLITE_OK && !pCtx->lockProxy ){
char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
/* we couldn't create the proxy lock file with the old lock file path
** so try again via auto-naming
*/
forceNewLockPath = 1;
tryOldLockPath = 0;
continue; /* go back to the do {} while start point, try again */
}
}
if( rc==SQLITE_OK ){
/* Need to make a copy of path if we extracted the value
** from the conch file or the path was allocated on the stack
*/
if( tempLockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
if( !pCtx->lockProxyPath ){
rc = SQLITE_NOMEM;
}
}
}
if( rc==SQLITE_OK ){
pCtx->conchHeld = 1;
if( pCtx->lockProxy->pMethod == &afpIoMethods ){
afpLockingContext *afpCtx;
afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
afpCtx->dbPath = pCtx->lockProxyPath;
}
} else {
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
}
OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed");
return rc;
} while (1); /* in case we need to retry the :auto: lock file - we should never get here except via the 'continue' call. */
============================
} else {
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
}
OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed");
return rc;
<<<<<<< END MERGE CONFLICT
}
}
+2 -2
View File
@@ -1417,7 +1417,7 @@ static int winOpen(
return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
}else{
return SQLITE_CANTOPEN;
return SQLITE_CANTOPEN_BKPT;
}
}
if( pOutFlags ){
@@ -1439,7 +1439,7 @@ static int winOpen(
){
CloseHandle(h);
free(zConverted);
return SQLITE_CANTOPEN;
return SQLITE_CANTOPEN_BKPT;
}
if( isTemp ){
pFile->zDeleteOnClose = zConverted;
+20 -13
View File
@@ -2019,6 +2019,9 @@ end_playback:
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){
rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
}
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zMaster[0]!='\0');
testcase( rc!=SQLITE_OK );
@@ -3164,7 +3167,7 @@ int sqlite3PagerOpen(
** as it will not be possible to open the journal file or even
** check for a hot-journal before reading.
*/
rc = SQLITE_CANTOPEN;
rc = SQLITE_CANTOPEN_BKPT;
}
if( rc!=SQLITE_OK ){
sqlite3_free(zPathname);
@@ -3623,7 +3626,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
rc = SQLITE_CANTOPEN;
rc = SQLITE_CANTOPEN_BKPT;
sqlite3OsClose(pPager->jfd);
}
}else{
@@ -3842,7 +3845,7 @@ int sqlite3PagerAcquire(
goto pager_acquire_err;
}
if( MEMDB || nMax<(int)pgno || noContent ){
if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){
if( pgno>pPager->mxPgno ){
rc = SQLITE_FULL;
goto pager_acquire_err;
@@ -4981,30 +4984,34 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
** operation. Store this value in nNew. Then free resources associated
** with any savepoints that are destroyed by this operation.
*/
nNew = iSavepoint + (op==SAVEPOINT_ROLLBACK);
nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
for(ii=nNew; ii<pPager->nSavepoint; ii++){
sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
}
pPager->nSavepoint = nNew;
/* If this is a rollback operation, playback the specified savepoint.
/* If this is a release of the outermost savepoint, truncate
** the sub-journal to zero bytes in size. */
if( op==SAVEPOINT_RELEASE ){
if( nNew==0 && isOpen(pPager->sjfd) ){
/* Only truncate if it is an in-memory sub-journal. */
if( sqlite3IsMemJournal(pPager->sjfd) ){
rc = sqlite3OsTruncate(pPager->sjfd, 0);
}
pPager->nSubRec = 0;
}
}
/* Else this is a rollback operation, playback the specified savepoint.
** If this is a temp-file, it is possible that the journal file has
** not yet been opened. In this case there have been no changes to
** the database file, so the playback operation can be skipped.
*/
if( op==SAVEPOINT_ROLLBACK && isOpen(pPager->jfd) ){
else if( isOpen(pPager->jfd) ){
PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
rc = pagerPlaybackSavepoint(pPager, pSavepoint);
assert(rc!=SQLITE_DONE);
}
/* If this is a release of the outermost savepoint, truncate
** the sub-journal to zero bytes in size. */
if( nNew==0 && op==SAVEPOINT_RELEASE && isOpen(pPager->sjfd) ){
assert( rc==SQLITE_OK );
rc = sqlite3OsTruncate(pPager->sjfd, 0);
pPager->nSubRec = 0;
}
}
return rc;
}
+2
View File
@@ -189,6 +189,7 @@ void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
if( pCache->pCache ){
sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
pCache->pCache = 0;
pCache->pPage1 = 0;
}
pCache->szPage = szPage;
}
@@ -242,6 +243,7 @@ int sqlite3PcacheFetch(
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
pPg=pPg->pDirtyPrev
);
pCache->pSynced = pPg;
if( !pPg ){
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
}
+1 -6
View File
@@ -285,6 +285,7 @@ void sqlite3Pragma(
Db *pDb;
Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);
if( v==0 ) return;
sqlite3VdbeRunOnlyOnce(v);
pParse->nMem = 2;
/* Interpret the [database.] part of the pragma statement. iDb is the
@@ -1411,12 +1412,6 @@ void sqlite3Pragma(
{/* Empty ELSE clause */}
/* Code an OP_Expire at the end of each PRAGMA program to cause
** the VDBE implementing the pragma to expire. Most (all?) pragmas
** are only valid for a single execution.
*/
sqlite3VdbeAddOp2(v, OP_Expire, 1, 0);
/*
** Reset the safety level, in case the fullfsync flag or synchronous
** setting changed.
+3 -18
View File
@@ -192,9 +192,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
initData.iDb = iDb;
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
(void)sqlite3SafetyOff(db);
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
(void)sqlite3SafetyOn(db);
if( initData.rc ){
rc = initData.rc;
goto error_out;
@@ -317,7 +315,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s",
db->aDb[iDb].zName, zMasterName);
(void)sqlite3SafetyOff(db);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
@@ -330,7 +327,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}
#endif
if( rc==SQLITE_OK ) rc = initData.rc;
(void)sqlite3SafetyOn(db);
sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
if( rc==SQLITE_OK ){
@@ -539,11 +535,6 @@ static int sqlite3Prepare(
goto end_prepare;
}
pParse->pReprepare = pReprepare;
if( sqlite3SafetyOn(db) ){
rc = SQLITE_MISUSE;
goto end_prepare;
}
assert( ppStmt && *ppStmt==0 );
assert( !db->mallocFailed );
assert( sqlite3_mutex_held(db->mutex) );
@@ -579,7 +570,6 @@ static int sqlite3Prepare(
if( rc ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, rc, "database schema is locked: %s", zDb);
(void)sqlite3SafetyOff(db);
testcase( db->flags & SQLITE_ReadUncommitted );
goto end_prepare;
}
@@ -596,7 +586,6 @@ static int sqlite3Prepare(
testcase( nBytes==mxLen+1 );
if( nBytes>mxLen ){
sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
(void)sqlite3SafetyOff(db);
rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
goto end_prepare;
}
@@ -653,10 +642,6 @@ static int sqlite3Prepare(
}
#endif
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
assert( db->init.busy==0 || saveSqlFlag==0 );
if( db->init.busy==0 ){
Vdbe *pVdbe = pParse->pVdbe;
@@ -704,7 +689,7 @@ static int sqlite3LockAndPrepare(
assert( ppStmt!=0 );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
@@ -743,7 +728,7 @@ int sqlite3Reprepare(Vdbe *p){
db->mallocFailed = 1;
}
assert( pNew==0 );
return (rc==SQLITE_LOCKED) ? SQLITE_LOCKED : SQLITE_SCHEMA;
return rc;
}else{
assert( pNew!=0 );
}
@@ -812,7 +797,7 @@ static int sqlite3Prepare16(
assert( ppStmt );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
+36
View File
@@ -937,6 +937,42 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
return z;
}
/*
** This is the routine that actually formats the sqlite3_log() message.
** We house it in a separate routine from sqlite3_log() to avoid using
** stack space on small-stack systems when logging is disabled.
**
** sqlite3_log() must render into a static buffer. It cannot dynamically
** allocate memory because it might be called while the memory allocator
** mutex is held.
*/
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */
#ifdef SQLITE_SMALL_STACK
char zMsg[150]; /* Complete log message */
#else
char zMsg[400]; /* Complete log message */
#endif
sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
acc.useMalloc = 0;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
sqlite3StrAccumFinish(&acc));
}
/*
** Format and write a message to the log if logging is enabled.
*/
void sqlite3_log(int iErrCode, const char *zFormat, ...){
va_list ap; /* Vararg list */
if( sqlite3GlobalConfig.xLog ){
va_start(ap, zFormat);
renderLogMsg(iErrCode, zFormat, ap);
va_end(ap);
}
}
#if defined(SQLITE_DEBUG)
/*
** A version of printf() that understands %lld. Used for debugging.
+9 -4
View File
@@ -664,6 +664,9 @@ static int resolveOrderByTermToExprList(
int i; /* Loop counter */
ExprList *pEList; /* The columns of the result set */
NameContext nc; /* Name context for resolving pE */
sqlite3 *db; /* Database connection */
int rc; /* Return code from subprocedures */
u8 savedSuppErr; /* Saved value of db->suppressErr */
assert( sqlite3ExprIsInteger(pE, &i)==0 );
pEList = pSelect->pEList;
@@ -676,10 +679,12 @@ static int resolveOrderByTermToExprList(
nc.pEList = pEList;
nc.allowAgg = 1;
nc.nErr = 0;
if( sqlite3ResolveExprNames(&nc, pE) ){
sqlite3ErrorClear(pParse);
return 0;
}
db = pParse->db;
savedSuppErr = db->suppressErr;
db->suppressErr = 1;
rc = sqlite3ResolveExprNames(&nc, pE);
db->suppressErr = savedSuppErr;
if( rc ) return 0;
/* Try to match the ORDER BY expression against an expression
** in the result set. Return an 1-based index of the matching
+33
View File
@@ -1277,6 +1277,7 @@ struct callback_data {
char outfile[FILENAME_MAX]; /* Filename for *out */
const char *zDbFilename; /* name of the database file */
sqlite3_stmt *pStmt; /* Current statement if any. */
FILE *pLog; /* Write log output here */
};
/*
@@ -1319,6 +1320,16 @@ static int strlen30(const char *z){
return 0x3fffffff & (int)(z2 - z);
}
/*
** A callback for the sqlite3_log() interface.
*/
static void shellLog(void *pArg, int iErrCode, const char *zMsg){
struct callback_data *p = (struct callback_data*)pArg;
if( p->pLog==0 ) return;
fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
fflush(p->pLog);
}
/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
@@ -2147,6 +2158,7 @@ static char zHelp[] =
#ifndef SQLITE_OMIT_LOAD_EXTENSION
".load FILE ?ENTRY? Load an extension library\n"
#endif
".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
" csv Comma-separated values\n"
" column Left-aligned columns. (See .width)\n"
@@ -2673,6 +2685,26 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}else
#endif
if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=1 ){
const char *zFile = azArg[1];
if( p->pLog && p->pLog!=stdout && p->pLog!=stderr ){
fclose(p->pLog);
p->pLog = 0;
}
if( strcmp(zFile,"stdout")==0 ){
p->pLog = stdout;
}else if( strcmp(zFile, "stderr")==0 ){
p->pLog = stderr;
}else if( strcmp(zFile, "off")==0 ){
p->pLog = 0;
}else{
p->pLog = fopen(zFile, "w");
if( p->pLog==0 ){
fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
}
}
}else
if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){
int n2 = strlen30(azArg[1]);
if( (n2==4 && strncmp(azArg[1],"line",n2)==0)
@@ -3318,6 +3350,7 @@ static void main_init(struct callback_data *data) {
data->mode = MODE_List;
memcpy(data->separator,"|", 2);
data->showHeader = 0;
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
}
+21 -1
View File
@@ -913,7 +913,6 @@ int sqlite3_os_end(void);
/*
** CAPI3REF: Configuring The SQLite Library
** EXPERIMENTAL
**
** The sqlite3_config() interface is used to make global configuration
** changes to SQLite in order to tune SQLite to the specific needs of
@@ -1254,6 +1253,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
/*
** CAPI3REF: Configuration Options
@@ -5642,6 +5642,26 @@ int sqlite3_unlock_notify(
*/
int sqlite3_strnicmp(const char *, const char *, int);
/*
** CAPI3REF: Error Logging Interface
** EXPERIMENTAL
**
** ^The [sqlite3_log()] interface writes a message into the error log
** established by the [SQLITE_CONFIG_ERRORLOG] option to [sqlite3_config()].
**
** The sqlite3_log() interface is intended for use by extensions such as
** virtual tables, collating functions, and SQL functions. While there is
** nothing to prevent an application from calling sqlite3_log(), doing so
** is considered bad form.
**
** To avoid deadlocks and other threading problems, the sqlite3_log() routine
** will not use dynamically allocated memory. The log message is stored in
** a fixed-length buffer on the stack. If the log message is longer than
** a few hundred characters, it will be truncated to the length of the
** buffer.
*/
void sqlite3_log(int iErrCode, const char *zFormat, ...);
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
+15 -18
View File
@@ -804,6 +804,7 @@ struct sqlite3 {
u8 dfltLockMode; /* Default locking-mode for attached dbs */
u8 dfltJournalMode; /* Default journal mode for attached dbs */
signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
u8 suppressErr; /* Do not issue error messages if true */
int nextPagesize; /* Pagesize after VACUUM if >0 */
int nTable; /* Number of tables in the database */
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
@@ -2380,6 +2381,8 @@ struct Sqlite3Config {
int isPCacheInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
void (*xLog)(void*,int,const char*); /* Function for logging */
void *pLogArg; /* First argument to xLog() */
};
/*
@@ -2421,17 +2424,19 @@ int sqlite3WalkSelectFrom(Walker*, Select*);
}
/*
** The SQLITE_CORRUPT_BKPT macro can be either a constant (for production
** builds) or a function call (for debugging). If it is a function call,
** it allows the operator to set a breakpoint at the spot where database
** corruption is first detected.
** The SQLITE_*_BKPT macros are substitutes for the error codes with
** the same name but without the _BKPT suffix. These macros invoke
** routines that report the line-number on which the error originated
** using sqlite3_log(). The routines also provide a convenient place
** to set a debugger breakpoint.
*/
#ifdef SQLITE_DEBUG
int sqlite3Corrupt(void);
# define SQLITE_CORRUPT_BKPT sqlite3Corrupt()
#else
# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT
#endif
int sqlite3CorruptError(int);
int sqlite3MisuseError(int);
int sqlite3CantopenError(int);
#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)
#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
/*
** The ctype.h header is needed for non-ASCII systems. It is also
@@ -2549,7 +2554,6 @@ char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
#endif
void sqlite3SetString(char **, sqlite3*, const char*, ...);
void sqlite3ErrorMsg(Parse*, const char*, ...);
void sqlite3ErrorClear(Parse*);
int sqlite3Dequote(char*);
int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
@@ -2719,13 +2723,6 @@ FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
void sqlite3RegisterBuiltinFunctions(sqlite3*);
void sqlite3RegisterDateTimeFunctions(void);
void sqlite3RegisterGlobalFunctions(void);
#ifdef SQLITE_DEBUG
int sqlite3SafetyOn(sqlite3*);
int sqlite3SafetyOff(sqlite3*);
#else
# define sqlite3SafetyOn(A) 0
# define sqlite3SafetyOff(A) 0
#endif
int sqlite3SafetyCheckOk(sqlite3*);
int sqlite3SafetyCheckSickOrOk(sqlite3*);
void sqlite3ChangeCookie(Parse*, int);
+1 -1
View File
@@ -83,7 +83,7 @@ void sqlite3StatusSet(int op, int X){
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
wsdStatInit;
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
*pCurrent = wsdStat.nowValue[op];
*pHighwater = wsdStat.mxValue[op];
+1
View File
@@ -480,6 +480,7 @@ abort_parse:
assert( pzErrMsg!=0 );
if( pParse->zErrMsg ){
*pzErrMsg = pParse->zErrMsg;
sqlite3_log(pParse->rc, "%s", *pzErrMsg);
pParse->zErrMsg = 0;
nErr++;
}
+32 -76
View File
@@ -146,23 +146,20 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
** (sqlite3_step() etc.).
*/
void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
char *zMsg;
va_list ap;
sqlite3 *db = pParse->db;
pParse->nErr++;
sqlite3DbFree(db, pParse->zErrMsg);
va_start(ap, zFormat);
pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap);
zMsg = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
pParse->rc = SQLITE_ERROR;
}
/*
** Clear the error message in pParse, if any
*/
void sqlite3ErrorClear(Parse *pParse){
sqlite3DbFree(pParse->db, pParse->zErrMsg);
pParse->zErrMsg = 0;
pParse->nErr = 0;
if( db->suppressErr ){
sqlite3DbFree(db, zMsg);
}else{
pParse->nErr++;
sqlite3DbFree(db, pParse->zErrMsg);
pParse->zErrMsg = zMsg;
pParse->rc = SQLITE_ERROR;
}
}
/*
@@ -997,64 +994,17 @@ void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
/*
** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY.
** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN
** when this routine is called.
**
** This routine is called when entering an SQLite API. The SQLITE_MAGIC_OPEN
** value indicates that the database connection passed into the API is
** open and is not being used by another thread. By changing the value
** to SQLITE_MAGIC_BUSY we indicate that the connection is in use.
** sqlite3SafetyOff() below will change the value back to SQLITE_MAGIC_OPEN
** when the API exits.
**
** This routine is a attempt to detect if two threads use the
** same sqlite* pointer at the same time. There is a race
** condition so it is possible that the error is not detected.
** But usually the problem will be seen. The result will be an
** error which can be used to debug the application that is
** using SQLite incorrectly.
**
** Ticket #202: If db->magic is not a valid open value, take care not
** to modify the db structure at all. It could be that db is a stale
** pointer. In other words, it could be that there has been a prior
** call to sqlite3_close(db) and db has been deallocated. And we do
** not want to write into deallocated memory.
** Log an error that is an API call on a connection pointer that should
** not have been used. The "type" of connection pointer is given as the
** argument. The zType is a word like "NULL" or "closed" or "invalid".
*/
#ifdef SQLITE_DEBUG
int sqlite3SafetyOn(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_OPEN ){
db->magic = SQLITE_MAGIC_BUSY;
assert( sqlite3_mutex_held(db->mutex) );
return 0;
}else if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_ERROR;
db->u1.isInterrupted = 1;
}
return 1;
static void logBadConnection(const char *zType){
sqlite3_log(SQLITE_MISUSE,
"API call with %s database connection pointer",
zType
);
}
#endif
/*
** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN.
** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY
** when this routine is called.
*/
#ifdef SQLITE_DEBUG
int sqlite3SafetyOff(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_OPEN;
assert( sqlite3_mutex_held(db->mutex) );
return 0;
}else{
db->magic = SQLITE_MAGIC_ERROR;
db->u1.isInterrupted = 1;
return 1;
}
}
#endif
/*
** Check to make sure we have a valid db pointer. This test is not
@@ -1072,13 +1022,15 @@ int sqlite3SafetyOff(sqlite3 *db){
*/
int sqlite3SafetyCheckOk(sqlite3 *db){
u32 magic;
if( db==0 ) return 0;
if( db==0 ){
logBadConnection("NULL");
return 0;
}
magic = db->magic;
if( magic!=SQLITE_MAGIC_OPEN
#ifdef SQLITE_DEBUG
&& magic!=SQLITE_MAGIC_BUSY
#endif
){
if( magic!=SQLITE_MAGIC_OPEN ){
if( !sqlite3SafetyCheckSickOrOk(db) ){
logBadConnection("unopened");
}
return 0;
}else{
return 1;
@@ -1089,6 +1041,10 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
magic = db->magic;
if( magic!=SQLITE_MAGIC_SICK &&
magic!=SQLITE_MAGIC_OPEN &&
magic!=SQLITE_MAGIC_BUSY ) return 0;
return 1;
magic!=SQLITE_MAGIC_BUSY ){
logBadConnection("invalid");
return 0;
}else{
return 1;
}
}
+35 -18
View File
@@ -18,28 +18,42 @@
#include "vdbeInt.h"
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/*
** Finalize a prepared statement. If there was an error, store the
** text of the error message in *pzErrMsg. Return the result code.
*/
static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
int rc;
rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
if( rc ){
sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
}
return rc;
}
/*
** Execute zSql on database db. Return an error code.
*/
static int execSql(sqlite3 *db, const char *zSql){
static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
sqlite3_stmt *pStmt;
VVA_ONLY( int rc; )
if( !zSql ){
return SQLITE_NOMEM;
}
if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
return sqlite3_errcode(db);
}
VVA_ONLY( rc = ) sqlite3_step(pStmt);
assert( rc!=SQLITE_ROW );
return sqlite3_finalize(pStmt);
return vacuumFinalize(db, pStmt, pzErrMsg);
}
/*
** Execute zSql on database db. The statement returns exactly
** one column. Execute this as SQL on the same database.
*/
static int execExecSql(sqlite3 *db, const char *zSql){
static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
sqlite3_stmt *pStmt;
int rc;
@@ -47,14 +61,14 @@ static int execExecSql(sqlite3 *db, const char *zSql){
if( rc!=SQLITE_OK ) return rc;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0));
rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
if( rc!=SQLITE_OK ){
sqlite3_finalize(pStmt);
vacuumFinalize(db, pStmt, pzErrMsg);
return rc;
}
}
return sqlite3_finalize(pStmt);
return vacuumFinalize(db, pStmt, pzErrMsg);
}
/*
@@ -124,8 +138,12 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** time to parse and run the PRAGMA to turn journalling off than it does
** to write the journal header file.
*/
zSql = "ATTACH '' AS vacuum_db;";
rc = execSql(db, zSql);
if( sqlite3TempInMemory(db) ){
zSql = "ATTACH ':memory:' AS vacuum_db;";
}else{
zSql = "ATTACH '' AS vacuum_db;";
}
rc = execSql(db, pzErrMsg, zSql);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
pDb = &db->aDb[db->nDb-1];
assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
@@ -157,7 +175,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
if( rc!=SQLITE_OK ){
goto end_of_vacuum;
}
@@ -168,23 +186,23 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
#endif
/* Begin a transaction */
rc = execSql(db, "BEGIN EXCLUSIVE;");
rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Query the schema of the main database. Create a mirror schema
** in the temporary database.
*/
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
" FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
" AND rootpage>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
" FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
" FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
@@ -193,24 +211,23 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
** the contents to the temporary database.
*/
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM main.' || quote(name) || ';'"
"FROM main.sqlite_master "
"WHERE type = 'table' AND name!='sqlite_sequence' "
" AND rootpage>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy over the sequence table
*/
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM main.' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
@@ -223,7 +240,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** associated storage, so all we have to do is copy their entries
** from the SQLITE_MASTER table.
*/
rc = execSql(db,
rc = execSql(db, pzErrMsg,
"INSERT INTO vacuum_db.sqlite_master "
" SELECT type, name, tbl_name, rootpage, sql"
" FROM main.sqlite_master"
+18 -45
View File
@@ -563,7 +563,6 @@ int sqlite3VdbeExec(
/*** INSERT STACK UNION HERE ***/
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
assert( db->magic==SQLITE_MAGIC_BUSY );
sqlite3VdbeMutexArrayEnter(p);
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
@@ -648,9 +647,7 @@ int sqlite3VdbeExec(
if( checkProgress ){
if( db->nProgressOps==nProgressOps ){
int prc;
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
prc =db->xProgress(db->pProgressArg);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
prc = db->xProgress(db->pProgressArg);
if( prc!=0 ){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
@@ -850,7 +847,13 @@ case OP_Halt: {
p->errorAction = (u8)pOp->p2;
p->pc = pc;
if( pOp->p4.z ){
assert( p->rc!=SQLITE_OK );
sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z);
}else if( p->rc ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -1393,21 +1396,12 @@ case OP_Function: {
assert( pOp[-1].opcode==OP_CollSeq );
ctx.pColl = pOp[-1].p4.pColl;
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
(*ctx.pFunc->xFunc)(&ctx, n, apVal);
if( sqlite3SafetyOn(db) ){
sqlite3VdbeMemRelease(&ctx.s);
goto abort_due_to_misuse;
}
if( db->mallocFailed ){
/* Even though a malloc() has failed, the implementation of the
** user function may have called an sqlite3_result_XXX() function
** to return a value. The following call releases any resources
** associated with such a value.
**
** Note: Maybe MemRelease() should be called if sqlite3SafetyOn()
** fails also (the if(...) statement above). But if people are
** misusing sqlite, they have bigger problems than a leaked value.
*/
sqlite3VdbeMemRelease(&ctx.s);
goto no_mem;
@@ -2059,7 +2053,7 @@ case OP_Column: {
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */
u32 szField; /* Number of bytes in the content of a field */
int szHdr; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
Mem *pReg; /* PseudoTable input register */
@@ -2234,12 +2228,16 @@ case OP_Column: {
** column and aOffset[i] will contain the offset from the beginning
** of the record to the start of the data for the i-th column
*/
offset64 = offset;
for(i=0; i<nField; i++){
if( zIdx<zEndHdr ){
aOffset[i] = (u32)offset64;
aOffset[i] = offset;
zIdx += getVarint32(zIdx, aType[i]);
offset64 += sqlite3VdbeSerialTypeLen(aType[i]);
szField = sqlite3VdbeSerialTypeLen(aType[i]);
offset += szField;
if( offset<szField ){ /* True if offset overflows */
zIdx = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
break;
}
}else{
/* If i is less that nField, then there are less fields in this
** record than SetNumColumns indicated there are columns in the
@@ -2259,8 +2257,8 @@ case OP_Column: {
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
if( (zIdx > zEndHdr)|| (offset64 > payloadSize)
|| (zIdx==zEndHdr && offset64!=(u64)payloadSize) ){
if( (zIdx > zEndHdr) || (offset > payloadSize)
|| (zIdx==zEndHdr && offset!=payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
@@ -4036,12 +4034,10 @@ case OP_Rowid: { /* out2-prerelease */
pVtab = pC->pVtabCursor->pVtab;
pModule = pVtab->pModule;
assert( pModule->xRowid );
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xRowid(pC->pVtabCursor, &v);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( pC->pCursor!=0 );
@@ -4577,7 +4573,6 @@ case OP_ParseSchema: {
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
(void)sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
initData.rc = SQLITE_OK;
@@ -4586,7 +4581,6 @@ case OP_ParseSchema: {
if( rc==SQLITE_OK ) rc = initData.rc;
sqlite3DbFree(db, zSql);
db->init.busy = 0;
(void)sqlite3SafetyOn(db);
}
}
sqlite3BtreeLeaveAll(db);
@@ -5156,9 +5150,7 @@ case OP_AggFinal: {
** a transaction.
*/
case OP_Vacuum: {
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = sqlite3RunVacuum(&p->zErrMsg, db);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
}
#endif
@@ -5302,12 +5294,10 @@ case OP_VOpen: {
pVtab = pOp->p4.pVtab->pVtab;
pModule = (sqlite3_module *)pVtab->pModule;
assert(pVtab && pModule);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xOpen(pVtab, &pVtabCursor);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
pVtabCursor->pVtab = pVtab;
@@ -5381,7 +5371,6 @@ case OP_VFilter: { /* jump */
sqlite3VdbeMemStoreType(apArg[i]);
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
p->inVtabMethod = 1;
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
p->inVtabMethod = 0;
@@ -5391,7 +5380,6 @@ case OP_VFilter: { /* jump */
if( rc==SQLITE_OK ){
res = pModule->xEof(pVtabCursor);
}
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( res ){
pc = pOp->p2 - 1;
@@ -5437,7 +5425,6 @@ case OP_VColumn: {
sqlite3VdbeMemMove(&sContext.s, pDest);
MemSetTypeFlag(&sContext.s, MEM_Null);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
@@ -5455,9 +5442,6 @@ case OP_VColumn: {
REGISTER_TRACE(pOp->p3, pDest);
UPDATE_MAX_BLOBSIZE(pDest);
if( sqlite3SafetyOn(db) ){
goto abort_due_to_misuse;
}
if( sqlite3VdbeMemTooBig(pDest) ){
goto too_big;
}
@@ -5494,7 +5478,6 @@ case OP_VNext: { /* jump */
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
p->inVtabMethod = 1;
rc = pModule->xNext(pCur->pVtabCursor);
p->inVtabMethod = 0;
@@ -5504,7 +5487,6 @@ case OP_VNext: { /* jump */
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
}
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( !res ){
/* If there is data, jump to P2 */
@@ -5530,12 +5512,10 @@ case OP_VRename: {
assert( pVtab->pModule->xRename );
REGISTER_TRACE(pOp->p1, pName);
assert( pName->flags & MEM_Str );
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pVtab->pModule->xRename(pVtab, pName->z);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
}
@@ -5586,12 +5566,10 @@ case OP_VUpdate: {
apArg[i] = pX;
pX++;
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( rc==SQLITE_OK && pOp->p1 ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
db->lastRowid = rowid;
@@ -5715,6 +5693,7 @@ default: { /* This is really OP_Noop and OP_Explain */
vdbe_error_halt:
assert( rc );
p->rc = rc;
sqlite3_log(rc, "prepared statement aborts at %d: [%s]", pc, p->zSql);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
@@ -5743,12 +5722,6 @@ no_mem:
rc = SQLITE_NOMEM;
goto vdbe_error_halt;
/* Jump to here for an SQLITE_MISUSE error.
*/
abort_due_to_misuse:
rc = SQLITE_MISUSE;
/* Fall thru into abort_due_to_error */
/* Jump to here for any other kind of fatal error. The "rc" variable
** should hold the error number.
*/
+1
View File
@@ -182,6 +182,7 @@ void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeRunOnlyOnce(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
int sqlite3VdbeFinalize(Vdbe*);
+1
View File
@@ -301,6 +301,7 @@ struct Vdbe {
u8 explain; /* True if EXPLAIN present on SQL command */
u8 changeCntOn; /* True to update the change-counter */
u8 expired; /* True if the VM needs to be recompiled */
u8 runOnlyOnce; /* Automatically expire on reset */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 inVtabMethod; /* See comments above */
u8 usesStmtJournal; /* True if uses a statement journal */
+74 -45
View File
@@ -31,6 +31,28 @@ int sqlite3_expired(sqlite3_stmt *pStmt){
}
#endif
/*
** Check on a Vdbe to make sure it has not been finalized. Log
** an error and return true if it has been finalized (or is otherwise
** invalid). Return false if it is ok.
*/
static int vdbeSafety(Vdbe *p){
if( p->db==0 ){
sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
return 1;
}else{
return 0;
}
}
static int vdbeSafetyNotNull(Vdbe *p){
if( p==0 ){
sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
return 1;
}else{
return vdbeSafety(p);
}
}
/*
** The following routine destroys a virtual machine that is created by
** the sqlite3_compile() routine. The integer returned is an SQLITE_
@@ -48,7 +70,11 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
sqlite3 *db = v->db;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = v->db->mutex;
sqlite3_mutex *mutex;
#endif
if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
#if SQLITE_THREADSAFE
mutex = v->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
rc = sqlite3VdbeFinalize(v);
@@ -295,7 +321,9 @@ static int sqlite3Step(Vdbe *p){
assert(p);
if( p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_MISUSE;
sqlite3_log(SQLITE_MISUSE,
"attempt to step a halted statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
/* Assert that malloc() has not failed */
@@ -305,16 +333,12 @@ static int sqlite3Step(Vdbe *p){
}
if( p->pc<=0 && p->expired ){
if( ALWAYS(p->rc==SQLITE_OK || p->rc==SQLITE_SCHEMA) ){
if( p->rc==SQLITE_OK ){
p->rc = SQLITE_SCHEMA;
}
rc = SQLITE_ERROR;
goto end_of_step;
}
if( sqlite3SafetyOn(db) ){
p->rc = SQLITE_MISUSE;
return SQLITE_MISUSE;
}
if( p->pc<0 ){
/* If there are no other statements currently running, then
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
@@ -347,10 +371,6 @@ static int sqlite3Step(Vdbe *p){
rc = sqlite3VdbeExec(p);
}
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
#ifndef SQLITE_OMIT_TRACE
/* Invoke the profile callback if there is one
*/
@@ -397,39 +417,44 @@ end_of_step:
** call sqlite3Reprepare() and try again.
*/
int sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_MISUSE;
if( pStmt ){
int cnt = 0;
Vdbe *v = (Vdbe*)pStmt;
sqlite3 *db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < 5
&& (rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
** from the database handle into the statement and sets the statement
** program counter to 0 to ensure that when the statement is
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
} else {
v->zErrMsg = 0;
v->rc = SQLITE_NOMEM;
}
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
int rc = SQLITE_OK; /* Result from sqlite3Step() */
int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
int cnt = 0; /* Counter to prevent infinite loop of reprepares */
sqlite3 *db; /* The database connection */
if( vdbeSafetyNotNull(v) ){
return SQLITE_MISUSE_BKPT;
}
db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < 5
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc2!=SQLITE_OK && v->isPrepareV2 && db->pErr ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
** from the database handle into the statement and sets the statement
** program counter to 0 to ensure that when the statement is
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
v->rc = rc2;
} else {
v->zErrMsg = 0;
v->rc = rc = SQLITE_NOMEM;
}
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -899,12 +924,16 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
*/
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
if( p==0 ) return SQLITE_MISUSE;
if( vdbeSafetyNotNull(p) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(p->db->mutex);
return SQLITE_MISUSE;
sqlite3_log(SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
if( i<1 || i>p->nVar ){
sqlite3Error(p->db, SQLITE_RANGE, 0);
+9 -8
View File
@@ -255,6 +255,13 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
}
}
/*
** Mark the VDBE as one that can only be run one time.
*/
void sqlite3VdbeRunOnlyOnce(Vdbe *p){
p->runOnlyOnce = 1;
}
#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
/*
@@ -1059,7 +1066,6 @@ int sqlite3VdbeList(
assert( p->explain );
assert( p->magic==VDBE_MAGIC_RUN );
assert( db->magic==SQLITE_MAGIC_BUSY );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
/* Even though this opcode does not use dynamic strings for
@@ -1474,9 +1480,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pCx->pModule;
p->inVtabMethod = 1;
(void)sqlite3SafetyOff(p->db);
pModule->xClose(pVtabCursor);
(void)sqlite3SafetyOn(p->db);
p->inVtabMethod = 0;
}
#endif
@@ -1657,9 +1661,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
/* If there are any write-transactions at all, invoke the commit hook */
if( needXcommit && db->xCommitCallback ){
(void)sqlite3SafetyOff(db);
rc = db->xCommitCallback(db->pCommitArg);
(void)sqlite3SafetyOn(db);
if( rc ){
return SQLITE_CONSTRAINT;
}
@@ -2213,9 +2215,7 @@ int sqlite3VdbeReset(Vdbe *p){
** error, then it might not have been halted properly. So halt
** it now.
*/
(void)sqlite3SafetyOn(db);
sqlite3VdbeHalt(p);
(void)sqlite3SafetyOff(db);
/* If the VDBE has be run even partially, then transfer the error code
** and error message from the VDBE into the main database structure. But
@@ -2235,6 +2235,7 @@ int sqlite3VdbeReset(Vdbe *p){
}else{
sqlite3Error(db, SQLITE_OK, 0);
}
if( p->runOnlyOnce ) p->expired = 1;
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
** to sqlite3_step(). For consistency (since sqlite3_step() was
@@ -3016,7 +3017,7 @@ int sqlite3VdbeIdxKeyCompare(
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
if( nCellKey<=0 || nCellKey>0x7fffffff ){
*res = 0;
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
memset(&m, 0, sizeof(m));
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
+2 -13
View File
@@ -95,13 +95,6 @@ int sqlite3_blob_open(
memset(pParse, 0, sizeof(Parse));
pParse->db = db;
if( sqlite3SafetyOn(db) ){
sqlite3DbFree(db, zErr);
sqlite3StackFree(db, pParse);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE;
}
sqlite3BtreeEnterAll(db);
pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
if( pTab && IsVirtual(pTab) ){
@@ -121,7 +114,6 @@ int sqlite3_blob_open(
pParse->zErrMsg = 0;
}
rc = SQLITE_ERROR;
(void)sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
@@ -136,7 +128,6 @@ int sqlite3_blob_open(
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
rc = SQLITE_ERROR;
(void)sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
@@ -177,7 +168,6 @@ int sqlite3_blob_open(
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
rc = SQLITE_ERROR;
(void)sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
@@ -227,8 +217,7 @@ int sqlite3_blob_open(
}
sqlite3BtreeLeaveAll(db);
rc = sqlite3SafetyOff(db);
if( NEVER(rc!=SQLITE_OK) || db->mallocFailed ){
if( db->mallocFailed ){
goto blob_open_out;
}
@@ -329,7 +318,7 @@ static int blobReadWrite(
Vdbe *v;
sqlite3 *db;
if( p==0 ) return SQLITE_MISUSE;
if( p==0 ) return SQLITE_MISUSE_BKPT;
db = p->db;
sqlite3_mutex_enter(db->mutex);
v = (Vdbe*)p->pStmt;
+2 -22
View File
@@ -123,16 +123,7 @@ void sqlite3VtabUnlock(VTable *pVTab){
if( pVTab->nRef==0 ){
sqlite3_vtab *p = pVTab->pVtab;
if( p ){
#ifdef SQLITE_DEBUG
if( pVTab->db->magic==SQLITE_MAGIC_BUSY ){
(void)sqlite3SafetyOff(db);
p->pModule->xDisconnect(p);
(void)sqlite3SafetyOn(db);
} else
#endif
{
p->pModule->xDisconnect(p);
}
p->pModule->xDisconnect(p);
}
sqlite3DbFree(db, pVTab);
}
@@ -468,9 +459,7 @@ static int vtabCallConstructor(
db->pVTab = pTab;
/* Invoke the virtual table constructor */
(void)sqlite3SafetyOff(db);
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
(void)sqlite3SafetyOn(db);
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
if( SQLITE_OK!=rc ){
@@ -658,7 +647,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
if( !pTab ){
sqlite3Error(db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
assert( (pTab->tabFlags & TF_Virtual)!=0 );
@@ -717,10 +706,8 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){
VTable *p = vtabDisconnectAll(db, pTab);
rc = sqlite3SafetyOff(db);
assert( rc==SQLITE_OK );
rc = p->pMod->pModule->xDestroy(p->pVtab);
(void)sqlite3SafetyOn(db);
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
if( rc==SQLITE_OK ){
@@ -772,10 +759,8 @@ static void callFinaliser(sqlite3 *db, int offset){
int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
int i;
int rc = SQLITE_OK;
int rcsafety;
VTable **aVTrans = db->aVTrans;
rc = sqlite3SafetyOff(db);
db->aVTrans = 0;
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
int (*x)(sqlite3_vtab *);
@@ -788,11 +773,6 @@ int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
}
}
db->aVTrans = aVTrans;
rcsafety = sqlite3SafetyOn(db);
if( rc==SQLITE_OK ){
rc = rcsafety;
}
return rc;
}
-2
View File
@@ -1758,12 +1758,10 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
int i;
int rc;
(void)sqlite3SafetyOff(pParse->db);
WHERETRACE(("xBestIndex for %s\n", pTab->zName));
TRACE_IDX_INPUTS(p);
rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p);
(void)sqlite3SafetyOn(pParse->db);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ){
+6 -6
View File
@@ -481,10 +481,10 @@ do_test analyze3-4.1.2 {
sqlite3_bind_text $S 2 "abc" 3
execsql { DROP TABLE t1 }
sqlite3_step $S
} {SQLITE_SCHEMA}
} {SQLITE_ERROR}
do_test analyze3-4.1.3 {
sqlite3_finalize $S
} {SQLITE_SCHEMA}
} {SQLITE_ERROR}
# Check an authorization error.
#
@@ -511,10 +511,10 @@ do_test analyze3-4.2.2 {
sqlite3_reset $S
sqlite3_bind_text $S 2 "abc" 3
sqlite3_step $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
do_test analyze3-4.2.4 {
sqlite3_finalize $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
# Check the effect of an authorization error that occurs in a re-prepare
# performed by sqlite3_step() is the same as one that occurs within
@@ -526,10 +526,10 @@ do_test analyze3-4.3.1 {
execsql { CREATE TABLE t2(d, e, f) }
db auth auth
sqlite3_step $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
do_test analyze3-4.3.2 {
sqlite3_finalize $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
db auth {}
#-------------------------------------------------------------------------
+13
View File
@@ -60,4 +60,17 @@ do_malloc_test attachmalloc-2 -tclprep {
ATTACH 'test2.db' AS db1;
}
set enable_shared_cache [sqlite3_enable_shared_cache 1]
sqlite3 dbaux test2.db
dbaux eval {SELECT * FROM sqlite_master}
do_malloc_test attachmalloc-3 -sqlbody {
SELECT * FROM sqlite_master;
ATTACH 'test2.db' AS two;
} -cleanup {
db eval { DETACH two }
}
dbaux close
sqlite3_enable_shared_cache $enable_shared_cache
finish_test
+1 -1
View File
@@ -1176,7 +1176,7 @@ do_test capi3c-19.4 {
sqlite3_reset $STMT
db eval {DROP TABLE t3}
sqlite3_step $STMT
} SQLITE_SCHEMA
} SQLITE_ERROR
do_test capi3c-19.4.1 {
sqlite3_errmsg $DB
} {no such table: t3}
+1 -1
View File
@@ -89,7 +89,7 @@ Corruption detected in cell 15 on page 2}}
sqlite3 db test.db
db eval {PRAGMA integrity_check(1)}
} {{*** in database main ***
Corruption detected in cell 15 on page 2}}
On tree page 2 cell 15: Rowid 0 out of order (previous was 15)}}
}
# The code path that was causing the buffer overrun that this test
+171
View File
@@ -0,0 +1,171 @@
# 2010 February 18
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file. It specifcally
# focuses on rowid order corruption.
#
# $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $
catch {file delete -force test.db test.db-journal test.bu}
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Construct a compact, dense database for testing.
#
do_test corruptE-1.1 {
execsql {
PRAGMA auto_vacuum = 0;
PRAGMA legacy_file_format=1;
BEGIN;
CREATE TABLE t1(x,y);
INSERT INTO t1 VALUES(1,1);
INSERT OR IGNORE INTO t1 SELECT x*2,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*3,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*11,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*13,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*17,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*19,y FROM t1;
CREATE INDEX t1i1 ON t1(x);
CREATE TABLE t2 AS SELECT x,2 as y FROM t1 WHERE rowid%5!=0;
COMMIT;
}
} {}
ifcapable {integrityck} {
integrity_check corruptE-1.2
}
# Copy file $from into $to
#
proc copy_file {from to} {
file copy -force $from $to
}
# Setup for the tests. Make a backup copy of the good database in test.bu.
#
db close
copy_file test.db test.bu
sqlite3 db test.db
set fsize [file size test.db]
do_test corruptE-2.1 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 2041 [format %02x 0x2e]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order.*previous was} $ans] \
[regexp {out of order.*max larger than parent max} $ans]
} {1 1}
do_test corruptE-2.2 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 2047 [format %02x 0x84]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order.*previous was} $ans] \
[regexp {out of order.*min less than parent min} $ans]
} {1 1}
do_test corruptE-2.3 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 7420 [format %02x 0xa8]
hexio_write test.db 10459 [format %02x 0x8d]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order.*max larger than parent min} $ans]
} {1}
do_test corruptE-2.4 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 10233 [format %02x 0xd0]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order.*min less than parent max} $ans]
} {1}
set tests [list {10233 0xd0} \
{941 0x42} \
{1028 0x53} \
{2041 0xd0} \
{2042 0x1f} \
{2047 0xaa} \
{2263 0x29} \
{2274 0x75} \
{3267 0xf2} \
{4104 0x2c} \
{5113 0x36} \
{10233 0x84} \
{10234 0x74} \
{10239 0x41} \
{10453 0x11} \
{11273 0x28} \
{11455 0x11} \
{11461 0xe6} \
{12281 0x99} \
{12296 0x9e} \
{12297 0xd7} \
{13303 0x53} ]
set tc 1
foreach test $tests {
do_test corruptE-3.$tc {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db [lindex $test 0] [format %02x [lindex $test 1]]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order} $ans]
} {1}
incr tc 1
}
finish_test
+26
View File
@@ -340,4 +340,30 @@ ifcapable pragma {
} {jkl}
}
catch { db close }
file delete -force test.db test.db-journal
sqlite3 db test.db
do_test crash8-5.1 {
execsql {
CREATE TABLE t1(x PRIMARY KEY);
INSERT INTO t1 VALUES(randomblob(900));
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 64 */
}
crashsql -file test.db -delay 1 {
PRAGMA cache_size = 10;
BEGIN;
UPDATE t1 SET x = randomblob(900);
ROLLBACK;
INSERT INTO t1 VALUES(randomblob(900));
}
execsql { PRAGMA integrity_check }
} {ok}
finish_test
-93
View File
@@ -1,93 +0,0 @@
# 2005 January 11
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the sqlite3SafetyOn and sqlite3SafetyOff
# functions. Those routines are not strictly necessary - they are
# designed to detect misuse of the library.
#
# $Id: safety.test,v 1.4 2008/03/18 13:46:53 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !debug {
puts "Skipping safety tests since SQLITE_DEBUG is off"
finish_test
return
}
# Return the UTF-8 representation of the supplied UTF-16 string $str.
proc utf8 {str} {
# If $str ends in two 0x00 0x00 bytes, knock these off before
# converting to UTF-8 using TCL.
binary scan $str \c* vals
if {[lindex $vals end]==0 && [lindex $vals end-1]==0} {
set str [binary format \c* [lrange $vals 0 end-2]]
}
set r [encoding convertfrom unicode $str]
return $r
}
do_test safety-1.1 {
set DB [sqlite3_connection_pointer db]
db eval {CREATE TABLE t1(a)}
sqlite_set_magic $DB SQLITE_MAGIC_BUSY
catchsql {
SELECT name FROM sqlite_master;
}
} {1 {library routine called out of sequence}}
do_test safety-1.2 {
sqlite_set_magic $DB SQLITE_MAGIC_OPEN
catchsql {
SELECT name FROM sqlite_master
}
} {0 t1}
do_test safety-2.1 {
proc safety_on {} "sqlite_set_magic $DB SQLITE_MAGIC_BUSY"
db function safety_on safety_on
catchsql {
SELECT safety_on(), name FROM sqlite_master
}
} {1 {library routine called out of sequence}}
ifcapable {utf16} {
do_test safety-2.1.1 {
utf8 [sqlite3_errmsg16 db]
} {library routine called out of sequence}
}
do_test safety-2.2 {
catchsql {
SELECT 'hello'
}
} {1 {library routine called out of sequence}}
do_test safety-2.3 {
sqlite3_close $DB
} {SQLITE_MISUSE}
do_test safety-2.4 {
sqlite_set_magic $DB SQLITE_MAGIC_OPEN
execsql {
SELECT name FROM sqlite_master
}
} {t1}
do_test safety-3.1 {
set rc [catch {
db eval {SELECT name FROM sqlite_master} {
sqlite_set_magic $DB SQLITE_MAGIC_BUSY
}
} msg]
lappend rc $msg
} {1 {library routine called out of sequence}}
sqlite_set_magic $DB SQLITE_MAGIC_OPEN
finish_test
+3 -3
View File
@@ -376,15 +376,15 @@ do_test schema-13.1 {
return SQLITE_OK
}
sqlite3_step $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
do_test schema-13.2 {
sqlite3_step $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
do_test schema-13.3 {
sqlite3_finalize $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
}
+67
View File
@@ -0,0 +1,67 @@
# 2010 February 21
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file implements a test of ticket [da1151f97df244a1]: An
# assertion fault while VACUUMing an auto_vacuumed database with
# large schema.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# If the VACUUM statement is disabled in the current build, skip all
# the tests in this file.
#
ifcapable !vacuum {
finish_test
return
}
do_test vacuum4-1.1 {
db eval {
PRAGMA auto_vacuum=FULL;
CREATE TABLE t1(
c000, c001, c002, c003, c004, c005, c006, c007, c008, c009,
c010, c011, c012, c013, c014, c015, c016, c017, c018, c019,
c020, c021, c022, c023, c024, c025, c026, c027, c028, c029,
c030, c031, c032, c033, c034, c035, c036, c037, c038, c039,
c040, c041, c042, c043, c044, c045, c046, c047, c048, c049,
c050, c051, c052, c053, c054, c055, c056, c057, c058, c059,
c060, c061, c062, c063, c064, c065, c066, c067, c068, c069,
c070, c071, c072, c073, c074, c075, c076, c077, c078, c079,
c080, c081, c082, c083, c084, c085, c086, c087, c088, c089,
c090, c091, c092, c093, c094, c095, c096, c097, c098, c099,
c100, c101, c102, c103, c104, c105, c106, c107, c108, c109,
c110, c111, c112, c113, c114, c115, c116, c117, c118, c119,
c120, c121, c122, c123, c124, c125, c126, c127, c128, c129,
c130, c131, c132, c133, c134, c135, c136, c137, c138, c139,
c140, c141, c142, c143, c144, c145, c146, c147, c148, c149
);
CREATE TABLE t2(
c000, c001, c002, c003, c004, c005, c006, c007, c008, c009,
c010, c011, c012, c013, c014, c015, c016, c017, c018, c019,
c020, c021, c022, c023, c024, c025, c026, c027, c028, c029,
c030, c031, c032, c033, c034, c035, c036, c037, c038, c039,
c040, c041, c042, c043, c044, c045, c046, c047, c048, c049,
c050, c051, c052, c053, c054, c055, c056, c057, c058, c059,
c060, c061, c062, c063, c064, c065, c066, c067, c068, c069,
c070, c071, c072, c073, c074, c075, c076, c077, c078, c079,
c080, c081, c082, c083, c084, c085, c086, c087, c088, c089,
c090, c091, c092, c093, c094, c095, c096, c097, c098, c099,
c100, c101, c102, c103, c104, c105, c106, c107, c108, c109,
c110, c111, c112, c113, c114, c115, c116, c117, c118, c119,
c120, c121, c122, c123, c124, c125, c126, c127, c128, c129,
c130, c131, c132, c133, c134, c135, c136, c137, c138, c139,
c140, c141, c142, c143, c144, c145, c146, c147, c148, c149
);
VACUUM;
}
} {}