Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 281dd84368 | |||
| 0a90717786 | |||
| 15678fa223 | |||
| f231da7e1a | |||
| 75fcb3bd4b | |||
| e5ae4a3b45 | |||
| 8d40cb7a5f | |||
| 9b7e9ff6a0 | |||
| e79619b822 |
@@ -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
@@ -1 +1 @@
|
||||
28d0d7710761114a44a1a3a425a6883c661f06e7
|
||||
82dd61fccff3e4c77e060e5734cd4b4e2eeb7c32
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -164,6 +164,8 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
0, /* isPCacheInit */
|
||||
0, /* pInitMutex */
|
||||
0, /* nRefInitMutex */
|
||||
0, /* xLog */
|
||||
0, /* pLogArg */
|
||||
};
|
||||
|
||||
|
||||
|
||||
+41
-15
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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];
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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*);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
} {}
|
||||
Reference in New Issue
Block a user