mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Merge latest trunk changes.
FossilOrigin-Name: d184cf00574b52b93f1f089025d6a0addca57558
This commit is contained in:
44
manifest
44
manifest
@@ -1,5 +1,5 @@
|
|||||||
C If\sthe\ssessions\smodule\sis\sbeing\sbuilt\sas\spart\sof\sthe\samalgamation,\sdo\snot\stry\sto\sinclude\ssqliteInt.h\sand\svdbeInt.h.
|
C Merge\slatest\strunk\schanges.
|
||||||
D 2011-04-01T15:30:39.770
|
D 2011-04-01T15:43:40.999
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
|
F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -123,8 +123,8 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
|||||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||||
F src/alter.c 6a0c176e64a34929a4436048066a84ef4f1445b3
|
F src/alter.c 280f5c04b11b492703a342222b3de0a999445280
|
||||||
F src/analyze.c a038162344265ac21dfb24b3fcc06c666ebb9c07
|
F src/analyze.c d0a673d303f611690fc7a3293aaefed57cccc5c8
|
||||||
F src/attach.c 438ea6f6b5d5961c1f49b737f2ce0f14ce7c6877
|
F src/attach.c 438ea6f6b5d5961c1f49b737f2ce0f14ce7c6877
|
||||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||||
F src/backup.c 537f89c7ef5021cb580f31f782e556ffffcb2ed1
|
F src/backup.c 537f89c7ef5021cb580f31f782e556ffffcb2ed1
|
||||||
@@ -171,7 +171,7 @@ F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
|
|||||||
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
|
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
|
||||||
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||||
F src/os_os2.c 2596fd2d5d0976c6c0c628d0c3c7c4e7a724f4cf
|
F src/os_os2.c 2596fd2d5d0976c6c0c628d0c3c7c4e7a724f4cf
|
||||||
F src/os_unix.c 0b37759312e8adb58c0c7dab1ab8ca16957bf299
|
F src/os_unix.c a3b4cdf50a9c9be8b50dc4932354ab749962a07f
|
||||||
F src/os_win.c 24d72407a90551969744cf9bcbb1b4c72c5fa845
|
F src/os_win.c 24d72407a90551969744cf9bcbb1b4c72c5fa845
|
||||||
F src/pager.c 6aa906b60a59664ba58d3f746164bb010d407ce1
|
F src/pager.c 6aa906b60a59664ba58d3f746164bb010d407ce1
|
||||||
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
|
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
|
||||||
@@ -194,7 +194,7 @@ F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
|
|||||||
F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc
|
F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
F src/tclsqlite.c 8376ae45f7e28d521ad708a0086771fab3c96475
|
F src/tclsqlite.c 8376ae45f7e28d521ad708a0086771fab3c96475
|
||||||
F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290
|
F src/test1.c 9ca440e80e16e53920904a0a5ac7feffb9b2c9a1
|
||||||
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
|
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
|
||||||
F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc
|
F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc
|
||||||
F src/test4.c 0528360b5025688002a5feb6be906ddce52eaaee
|
F src/test4.c 0528360b5025688002a5feb6be906ddce52eaaee
|
||||||
@@ -211,7 +211,7 @@ F src/test_config.c 3050df9faf023fb52937f7e9998004c2415d4122
|
|||||||
F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5
|
F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5
|
||||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||||
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
|
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
|
||||||
F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2
|
F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a
|
||||||
F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c
|
F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c
|
||||||
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
|
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
|
||||||
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
|
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
|
||||||
@@ -229,7 +229,7 @@ F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
|||||||
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
|
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
|
||||||
F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
|
F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
|
||||||
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||||
F src/test_syscall.c d12e8cd163cd33b66d0a3d1b8daaf136d09d65c2
|
F src/test_syscall.c 349a2b913e82b029f01527f58f65d66a02a09a84
|
||||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||||
F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0
|
F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0
|
||||||
F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86
|
F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86
|
||||||
@@ -245,7 +245,7 @@ F src/vdbe.c 4784ded3d2c97f8084a17cacbeea490a0dccf75e
|
|||||||
F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9
|
F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9
|
||||||
F src/vdbeInt.h b6748a8ac9be169d83585a0f5daf747863c6b8db
|
F src/vdbeInt.h b6748a8ac9be169d83585a0f5daf747863c6b8db
|
||||||
F src/vdbeapi.c 7ef519083e3420bf7793d8b4eae2961d894d98ab
|
F src/vdbeapi.c 7ef519083e3420bf7793d8b4eae2961d894d98ab
|
||||||
F src/vdbeaux.c b526e30d7a5d5b8b18408b2ec077e7286df2f6dc
|
F src/vdbeaux.c 0dcfffca621c534d8c64abfc47888dca5dd7b809
|
||||||
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
||||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||||
F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5
|
F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5
|
||||||
@@ -253,21 +253,22 @@ F src/vtab.c e1edca38c4c4310710635bb91bb3c87fdf60f21d
|
|||||||
F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
|
F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
|
||||||
F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
|
F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
|
||||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||||
F src/where.c a6e89fe7e56ab7e633be6fdebdddd857e9e5bc99
|
F src/where.c 176574bfeee13775761ce56416f773b0ec115d3f
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||||
F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
|
F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
|
||||||
F test/alter.test 15f9224868b290d6bf7a63f31437f31aee070636
|
F test/alter.test 4e47fb9ea59348b88fce4e8bb49de530128b104c
|
||||||
F test/alter2.test 75f731508f1bf27ba09a6075c66cd02216ba464b
|
F test/alter2.test 75f731508f1bf27ba09a6075c66cd02216ba464b
|
||||||
F test/alter3.test 8677e48d95536f7a6ed86a1a774744dadcc22b07
|
F test/alter3.test 8677e48d95536f7a6ed86a1a774744dadcc22b07
|
||||||
F test/alter4.test 1e5dd6b951e9f65ca66422edff02e56df82dd403
|
F test/alter4.test 1e5dd6b951e9f65ca66422edff02e56df82dd403
|
||||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||||
F test/analyze.test c1eb87067fc16ece7c07e823d6395fd831b270c5
|
F test/analyze.test c8cb89e8736336f1f0646c8123e6028a14c7b55e
|
||||||
F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
|
F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
|
||||||
F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
|
F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
|
||||||
F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
|
F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
|
||||||
F test/analyze5.test adc89b92fc9fee5ca1cb0bc8512f3206ad0fe5aa
|
F test/analyze5.test adc89b92fc9fee5ca1cb0bc8512f3206ad0fe5aa
|
||||||
F test/analyze6.test 1ba1aea8fad25a77ffd71f24522d1bb9ecc949fc
|
F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290
|
||||||
|
F test/analyze7.test 06405dd3d2a3101de14270da508016a59254873b
|
||||||
F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
|
F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
|
||||||
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
|
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
|
||||||
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
|
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
|
||||||
@@ -291,7 +292,7 @@ F test/backup2.test b7c69f937c912e85ac8a5dbd1e1cf290302b2d49
|
|||||||
F test/backup_ioerr.test 1f012e692f42c0442ae652443258f70e9f20fa38
|
F test/backup_ioerr.test 1f012e692f42c0442ae652443258f70e9f20fa38
|
||||||
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
|
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
|
||||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||||
F test/badutf2.test a47fda0d986d5325aa0ec2a0ebdd2d68db45e623
|
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
|
||||||
F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070
|
F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070
|
||||||
F test/bigfile.test a8ec8073a20207456dab01a29ad9cde42b0dd103
|
F test/bigfile.test a8ec8073a20207456dab01a29ad9cde42b0dd103
|
||||||
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
||||||
@@ -598,7 +599,7 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
|
|||||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||||
F test/omitunique.test bbb2ec4345d9125d9ee21cd9488d97a163020d5f
|
F test/omitunique.test bbb2ec4345d9125d9ee21cd9488d97a163020d5f
|
||||||
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
|
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
|
||||||
F test/oserror.test d1f085bdbac20456fccdf5877f52016453654fc3
|
F test/oserror.test 6c61c859cd94864cfd6af83e0549e2800238c413
|
||||||
F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe
|
F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe
|
||||||
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
|
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
|
||||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||||
@@ -682,8 +683,8 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
|||||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||||
F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082
|
F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082
|
||||||
F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3
|
F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3
|
||||||
F test/syscall.test 125d9781d914c408e8629053b5f914dc920ab3eb
|
F test/syscall.test d1dae1fee88613cf763d97ad0038d867509e0c42
|
||||||
F test/sysfault.test be42aa42f89a82305cf3807047d419595e430480
|
F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f
|
||||||
F test/table.test 04ba066432430657712d167ebf28080fe878d305
|
F test/table.test 04ba066432430657712d167ebf28080fe878d305
|
||||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||||
F test/tclsqlite.test 1ce9b6340d6d412420634e129a2e3722c651056a
|
F test/tclsqlite.test 1ce9b6340d6d412420634e129a2e3722c651056a
|
||||||
@@ -838,6 +839,7 @@ F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
|
|||||||
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
|
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
|
||||||
F test/types3.test a0f66bf12f80fad89493535474f7a6d16fa58150
|
F test/types3.test a0f66bf12f80fad89493535474f7a6d16fa58150
|
||||||
F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
|
F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
|
||||||
|
F test/unixexcl.test 9d80a54d86d2261f660758928959368ffc36151e
|
||||||
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
|
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
|
||||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||||
F test/vacuum.test 29b60e8cc9e573b39676df6c4a75fe9e02d04a09
|
F test/vacuum.test 29b60e8cc9e573b39676df6c4a75fe9e02d04a09
|
||||||
@@ -885,7 +887,7 @@ F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
|
|||||||
F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
|
F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
|
||||||
F test/where.test de337a3fe0a459ec7c93db16a519657a90552330
|
F test/where.test de337a3fe0a459ec7c93db16a519657a90552330
|
||||||
F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554
|
F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554
|
||||||
F test/where3.test c81d4ecfaed54e8aef9c1a8a90ac83c9f5c49090
|
F test/where3.test 8e1175c7ef710c70502858fc4fb08d784b3620b9
|
||||||
F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
|
F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
|
||||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||||
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
|
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
|
||||||
@@ -929,7 +931,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
P 6634521461e6acff7cc778590e62d57831f9230d
|
P f87bfe6e12093e5958b658a49d3766fb29562cbb d9707ef8dcd29667b6d366897f6ad02c87aa0041
|
||||||
R 7a473314ef2d0233cdf9f16418e4fb53
|
R e5326ee14e908456b763c8934a17defb
|
||||||
U dan
|
U dan
|
||||||
Z 1c0b7044d6d9a7b111c49878de940801
|
Z 5580ee572f02ed202a1934709ea63a74
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
f87bfe6e12093e5958b658a49d3766fb29562cbb
|
d184cf00574b52b93f1f089025d6a0addca57558
|
||||||
28
src/alter.c
28
src/alter.c
@@ -370,6 +370,22 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Parameter zName is the name of a table that is about to be altered
|
||||||
|
** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
|
||||||
|
** If the table is a system table, this function leaves an error message
|
||||||
|
** in pParse->zErr (system tables may not be altered) and returns non-zero.
|
||||||
|
**
|
||||||
|
** Or, if zName is not a system table, zero is returned.
|
||||||
|
*/
|
||||||
|
static int isSystemTable(Parse *pParse, const char *zName){
|
||||||
|
if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
|
||||||
|
sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
|
** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
|
||||||
** command.
|
** command.
|
||||||
@@ -420,14 +436,11 @@ void sqlite3AlterRenameTable(
|
|||||||
/* Make sure it is not a system table being altered, or a reserved name
|
/* Make sure it is not a system table being altered, or a reserved name
|
||||||
** that the table is being renamed to.
|
** that the table is being renamed to.
|
||||||
*/
|
*/
|
||||||
if( sqlite3Strlen30(pTab->zName)>6
|
if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
|
||||||
&& 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
|
|
||||||
){
|
|
||||||
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
|
|
||||||
goto exit_rename_table;
|
goto exit_rename_table;
|
||||||
}
|
}
|
||||||
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
|
||||||
goto exit_rename_table;
|
exit_rename_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_VIEW
|
#ifndef SQLITE_OMIT_VIEW
|
||||||
@@ -759,6 +772,9 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
|||||||
sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
|
sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
|
||||||
goto exit_begin_add_column;
|
goto exit_begin_add_column;
|
||||||
}
|
}
|
||||||
|
if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
|
||||||
|
goto exit_begin_add_column;
|
||||||
|
}
|
||||||
|
|
||||||
assert( pTab->addColOffset>0 );
|
assert( pTab->addColOffset>0 );
|
||||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ static void openStatTable(
|
|||||||
Parse *pParse, /* Parsing context */
|
Parse *pParse, /* Parsing context */
|
||||||
int iDb, /* The database we are looking in */
|
int iDb, /* The database we are looking in */
|
||||||
int iStatCur, /* Open the sqlite_stat1 table on this cursor */
|
int iStatCur, /* Open the sqlite_stat1 table on this cursor */
|
||||||
const char *zWhere /* Delete entries associated with this table */
|
const char *zWhere, /* Delete entries for this table or index */
|
||||||
|
const char *zWhereType /* Either "tbl" or "idx" */
|
||||||
){
|
){
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *zName;
|
const char *zName;
|
||||||
@@ -79,7 +80,7 @@ static void openStatTable(
|
|||||||
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
|
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
|
||||||
if( zWhere ){
|
if( zWhere ){
|
||||||
sqlite3NestedParse(pParse,
|
sqlite3NestedParse(pParse,
|
||||||
"DELETE FROM %Q.%s WHERE tbl=%Q", pDb->zName, zTab, zWhere
|
"DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
|
||||||
);
|
);
|
||||||
}else{
|
}else{
|
||||||
/* The sqlite_stat[12] table already exists. Delete all rows. */
|
/* The sqlite_stat[12] table already exists. Delete all rows. */
|
||||||
@@ -103,6 +104,7 @@ static void openStatTable(
|
|||||||
static void analyzeOneTable(
|
static void analyzeOneTable(
|
||||||
Parse *pParse, /* Parser context */
|
Parse *pParse, /* Parser context */
|
||||||
Table *pTab, /* Table whose indices are to be analyzed */
|
Table *pTab, /* Table whose indices are to be analyzed */
|
||||||
|
Index *pOnlyIdx, /* If not NULL, only analyze this one index */
|
||||||
int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */
|
int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */
|
||||||
int iMem /* Available memory locations begin here */
|
int iMem /* Available memory locations begin here */
|
||||||
){
|
){
|
||||||
@@ -113,8 +115,7 @@ static void analyzeOneTable(
|
|||||||
int i; /* Loop counter */
|
int i; /* Loop counter */
|
||||||
int topOfLoop; /* The top of the loop */
|
int topOfLoop; /* The top of the loop */
|
||||||
int endOfLoop; /* The end of the loop */
|
int endOfLoop; /* The end of the loop */
|
||||||
int addr = 0; /* The address of an instruction */
|
int jZeroRows = -1; /* Jump from here if number of rows is zero */
|
||||||
int jZeroRows = 0; /* Jump from here if number of rows is zero */
|
|
||||||
int iDb; /* Index of database containing pTab */
|
int iDb; /* Index of database containing pTab */
|
||||||
int regTabname = iMem++; /* Register containing table name */
|
int regTabname = iMem++; /* Register containing table name */
|
||||||
int regIdxname = iMem++; /* Register containing index name */
|
int regIdxname = iMem++; /* Register containing index name */
|
||||||
@@ -125,6 +126,7 @@ static void analyzeOneTable(
|
|||||||
int regRowid = iMem++; /* Rowid for the inserted record */
|
int regRowid = iMem++; /* Rowid for the inserted record */
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_STAT2
|
#ifdef SQLITE_ENABLE_STAT2
|
||||||
|
int addr = 0; /* Instruction address */
|
||||||
int regTemp2 = iMem++; /* Temporary use register */
|
int regTemp2 = iMem++; /* Temporary use register */
|
||||||
int regSamplerecno = iMem++; /* Index of next sample to record */
|
int regSamplerecno = iMem++; /* Index of next sample to record */
|
||||||
int regRecno = iMem++; /* Current sample index */
|
int regRecno = iMem++; /* Current sample index */
|
||||||
@@ -160,9 +162,12 @@ static void analyzeOneTable(
|
|||||||
iIdxCur = pParse->nTab++;
|
iIdxCur = pParse->nTab++;
|
||||||
sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
|
sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
|
||||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||||
int nCol = pIdx->nColumn;
|
int nCol;
|
||||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
KeyInfo *pKey;
|
||||||
|
|
||||||
|
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
|
||||||
|
nCol = pIdx->nColumn;
|
||||||
|
pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
||||||
if( iMem+1+(nCol*2)>pParse->nMem ){
|
if( iMem+1+(nCol*2)>pParse->nMem ){
|
||||||
pParse->nMem = iMem+1+(nCol*2);
|
pParse->nMem = iMem+1+(nCol*2);
|
||||||
}
|
}
|
||||||
@@ -319,7 +324,7 @@ static void analyzeOneTable(
|
|||||||
** is never possible.
|
** is never possible.
|
||||||
*/
|
*/
|
||||||
sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regSampleno);
|
sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regSampleno);
|
||||||
if( jZeroRows==0 ){
|
if( jZeroRows<0 ){
|
||||||
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
|
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
|
||||||
}
|
}
|
||||||
for(i=0; i<nCol; i++){
|
for(i=0; i<nCol; i++){
|
||||||
@@ -345,10 +350,10 @@ static void analyzeOneTable(
|
|||||||
VdbeComment((v, "%s", pTab->zName));
|
VdbeComment((v, "%s", pTab->zName));
|
||||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regSampleno);
|
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regSampleno);
|
||||||
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
|
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
|
||||||
|
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regSampleno);
|
||||||
}else{
|
}else{
|
||||||
assert( jZeroRows>0 );
|
|
||||||
addr = sqlite3VdbeAddOp0(v, OP_Goto);
|
|
||||||
sqlite3VdbeJumpHere(v, jZeroRows);
|
sqlite3VdbeJumpHere(v, jZeroRows);
|
||||||
|
jZeroRows = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
|
sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
|
||||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
|
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
|
||||||
@@ -356,9 +361,7 @@ static void analyzeOneTable(
|
|||||||
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid);
|
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid);
|
||||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||||
if( pParse->nMem<regRec ) pParse->nMem = regRec;
|
if( pParse->nMem<regRec ) pParse->nMem = regRec;
|
||||||
if( jZeroRows ){
|
sqlite3VdbeJumpHere(v, jZeroRows);
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -385,20 +388,21 @@ static void analyzeDatabase(Parse *pParse, int iDb){
|
|||||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||||
iStatCur = pParse->nTab;
|
iStatCur = pParse->nTab;
|
||||||
pParse->nTab += 2;
|
pParse->nTab += 2;
|
||||||
openStatTable(pParse, iDb, iStatCur, 0);
|
openStatTable(pParse, iDb, iStatCur, 0, 0);
|
||||||
iMem = pParse->nMem+1;
|
iMem = pParse->nMem+1;
|
||||||
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||||
Table *pTab = (Table*)sqliteHashData(k);
|
Table *pTab = (Table*)sqliteHashData(k);
|
||||||
analyzeOneTable(pParse, pTab, iStatCur, iMem);
|
analyzeOneTable(pParse, pTab, 0, iStatCur, iMem);
|
||||||
}
|
}
|
||||||
loadAnalysis(pParse, iDb);
|
loadAnalysis(pParse, iDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code that will do an analysis of a single table in
|
** Generate code that will do an analysis of a single table in
|
||||||
** a database.
|
** a database. If pOnlyIdx is not NULL then it is a single index
|
||||||
|
** in pTab that should be analyzed.
|
||||||
*/
|
*/
|
||||||
static void analyzeTable(Parse *pParse, Table *pTab){
|
static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){
|
||||||
int iDb;
|
int iDb;
|
||||||
int iStatCur;
|
int iStatCur;
|
||||||
|
|
||||||
@@ -408,8 +412,12 @@ static void analyzeTable(Parse *pParse, Table *pTab){
|
|||||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||||
iStatCur = pParse->nTab;
|
iStatCur = pParse->nTab;
|
||||||
pParse->nTab += 2;
|
pParse->nTab += 2;
|
||||||
openStatTable(pParse, iDb, iStatCur, pTab->zName);
|
if( pOnlyIdx ){
|
||||||
analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem+1);
|
openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx");
|
||||||
|
}else{
|
||||||
|
openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl");
|
||||||
|
}
|
||||||
|
analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem+1);
|
||||||
loadAnalysis(pParse, iDb);
|
loadAnalysis(pParse, iDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +439,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
|
|||||||
int i;
|
int i;
|
||||||
char *z, *zDb;
|
char *z, *zDb;
|
||||||
Table *pTab;
|
Table *pTab;
|
||||||
|
Index *pIdx;
|
||||||
Token *pTableName;
|
Token *pTableName;
|
||||||
|
|
||||||
/* Read the database schema. If an error occurs, leave an error message
|
/* Read the database schema. If an error occurs, leave an error message
|
||||||
@@ -455,11 +464,12 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
|
|||||||
}else{
|
}else{
|
||||||
z = sqlite3NameFromToken(db, pName1);
|
z = sqlite3NameFromToken(db, pName1);
|
||||||
if( z ){
|
if( z ){
|
||||||
pTab = sqlite3LocateTable(pParse, 0, z, 0);
|
if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){
|
||||||
sqlite3DbFree(db, z);
|
analyzeTable(pParse, pIdx->pTable, pIdx);
|
||||||
if( pTab ){
|
}else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){
|
||||||
analyzeTable(pParse, pTab);
|
analyzeTable(pParse, pTab, 0);
|
||||||
}
|
}
|
||||||
|
sqlite3DbFree(db, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -469,11 +479,12 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
|
|||||||
zDb = db->aDb[iDb].zName;
|
zDb = db->aDb[iDb].zName;
|
||||||
z = sqlite3NameFromToken(db, pTableName);
|
z = sqlite3NameFromToken(db, pTableName);
|
||||||
if( z ){
|
if( z ){
|
||||||
pTab = sqlite3LocateTable(pParse, 0, z, zDb);
|
if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
|
||||||
sqlite3DbFree(db, z);
|
analyzeTable(pParse, pIdx->pTable, pIdx);
|
||||||
if( pTab ){
|
}else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){
|
||||||
analyzeTable(pParse, pTab);
|
analyzeTable(pParse, pTab, 0);
|
||||||
}
|
}
|
||||||
|
sqlite3DbFree(db, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
242
src/os_unix.c
242
src/os_unix.c
@@ -593,8 +593,21 @@ static int robust_ftruncate(int h, sqlite3_int64 sz){
|
|||||||
*/
|
*/
|
||||||
static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
||||||
switch (posixError) {
|
switch (posixError) {
|
||||||
|
#if 0
|
||||||
|
/* At one point this code was not commented out. In theory, this branch
|
||||||
|
** should never be hit, as this function should only be called after
|
||||||
|
** a locking-related function (i.e. fcntl()) has returned non-zero with
|
||||||
|
** the value of errno as the first argument. Since a system call has failed,
|
||||||
|
** errno should be non-zero.
|
||||||
|
**
|
||||||
|
** Despite this, if errno really is zero, we still don't want to return
|
||||||
|
** SQLITE_OK. The system call failed, and *some* SQLite error should be
|
||||||
|
** propagated back to the caller. Commenting this branch out means errno==0
|
||||||
|
** will be handled by the "default:" case below.
|
||||||
|
*/
|
||||||
case 0:
|
case 0:
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
|
#endif
|
||||||
|
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
case ETIMEDOUT:
|
case ETIMEDOUT:
|
||||||
@@ -617,8 +630,15 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
|||||||
case EPERM:
|
case EPERM:
|
||||||
return SQLITE_PERM;
|
return SQLITE_PERM;
|
||||||
|
|
||||||
|
/* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
|
||||||
|
** this module never makes such a call. And the code in SQLite itself
|
||||||
|
** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
|
||||||
|
** this case is also commented out. If the system does set errno to EDEADLK,
|
||||||
|
** the default SQLITE_IOERR_XXX code will be returned. */
|
||||||
|
#if 0
|
||||||
case EDEADLK:
|
case EDEADLK:
|
||||||
return SQLITE_IOERR_BLOCKED;
|
return SQLITE_IOERR_BLOCKED;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if EOPNOTSUPP!=ENOTSUP
|
#if EOPNOTSUPP!=ENOTSUP
|
||||||
case EOPNOTSUPP:
|
case EOPNOTSUPP:
|
||||||
@@ -1037,7 +1057,7 @@ static void closePendingFds(unixFile *pFile){
|
|||||||
static void releaseInodeInfo(unixFile *pFile){
|
static void releaseInodeInfo(unixFile *pFile){
|
||||||
unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
assert( unixMutexHeld() );
|
assert( unixMutexHeld() );
|
||||||
if( pInode ){
|
if( ALWAYS(pInode) ){
|
||||||
pInode->nRef--;
|
pInode->nRef--;
|
||||||
if( pInode->nRef==0 ){
|
if( pInode->nRef==0 ){
|
||||||
assert( pInode->pShmNode==0 );
|
assert( pInode->pShmNode==0 );
|
||||||
@@ -1179,10 +1199,9 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|||||||
lock.l_start = RESERVED_BYTE;
|
lock.l_start = RESERVED_BYTE;
|
||||||
lock.l_len = 1;
|
lock.l_len = 1;
|
||||||
lock.l_type = F_WRLCK;
|
lock.l_type = F_WRLCK;
|
||||||
if (-1 == osFcntl(pFile->h, F_GETLK, &lock)) {
|
if( osFcntl(pFile->h, F_GETLK, &lock) ){
|
||||||
int tErrno = errno;
|
rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
|
pFile->lastErrno = errno;
|
||||||
pFile->lastErrno = tErrno;
|
|
||||||
} else if( lock.l_type!=F_UNLCK ){
|
} else if( lock.l_type!=F_UNLCK ){
|
||||||
reserved = 1;
|
reserved = 1;
|
||||||
}
|
}
|
||||||
@@ -1211,6 +1230,9 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|||||||
** This function is a pass-through to fcntl(F_SETLK) if pFile is using
|
** This function is a pass-through to fcntl(F_SETLK) if pFile is using
|
||||||
** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
|
** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
|
||||||
** and is read-only.
|
** and is read-only.
|
||||||
|
**
|
||||||
|
** Zero is returned if the call completes successfully, or -1 if a call
|
||||||
|
** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
|
||||||
*/
|
*/
|
||||||
static int unixFileLock(unixFile *pFile, struct flock *pLock){
|
static int unixFileLock(unixFile *pFile, struct flock *pLock){
|
||||||
int rc;
|
int rc;
|
||||||
@@ -1307,7 +1329,6 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
|||||||
unixFile *pFile = (unixFile*)id;
|
unixFile *pFile = (unixFile*)id;
|
||||||
unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
struct flock lock;
|
struct flock lock;
|
||||||
int s = 0;
|
|
||||||
int tErrno = 0;
|
int tErrno = 0;
|
||||||
|
|
||||||
assert( pFile );
|
assert( pFile );
|
||||||
@@ -1376,11 +1397,10 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
|||||||
){
|
){
|
||||||
lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
|
lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
|
||||||
lock.l_start = PENDING_BYTE;
|
lock.l_start = PENDING_BYTE;
|
||||||
s = unixFileLock(pFile, &lock);
|
if( unixFileLock(pFile, &lock) ){
|
||||||
if( s==(-1) ){
|
|
||||||
tErrno = errno;
|
tErrno = errno;
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
if( rc!=SQLITE_BUSY ){
|
||||||
pFile->lastErrno = tErrno;
|
pFile->lastErrno = tErrno;
|
||||||
}
|
}
|
||||||
goto end_lock;
|
goto end_lock;
|
||||||
@@ -1394,33 +1414,31 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
|||||||
if( eFileLock==SHARED_LOCK ){
|
if( eFileLock==SHARED_LOCK ){
|
||||||
assert( pInode->nShared==0 );
|
assert( pInode->nShared==0 );
|
||||||
assert( pInode->eFileLock==0 );
|
assert( pInode->eFileLock==0 );
|
||||||
|
assert( rc==SQLITE_OK );
|
||||||
|
|
||||||
/* Now get the read-lock */
|
/* Now get the read-lock */
|
||||||
lock.l_start = SHARED_FIRST;
|
lock.l_start = SHARED_FIRST;
|
||||||
lock.l_len = SHARED_SIZE;
|
lock.l_len = SHARED_SIZE;
|
||||||
if( (s = unixFileLock(pFile, &lock))==(-1) ){
|
if( unixFileLock(pFile, &lock) ){
|
||||||
tErrno = errno;
|
tErrno = errno;
|
||||||
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Drop the temporary PENDING lock */
|
/* Drop the temporary PENDING lock */
|
||||||
lock.l_start = PENDING_BYTE;
|
lock.l_start = PENDING_BYTE;
|
||||||
lock.l_len = 1L;
|
lock.l_len = 1L;
|
||||||
lock.l_type = F_UNLCK;
|
lock.l_type = F_UNLCK;
|
||||||
if( unixFileLock(pFile, &lock)!=0 ){
|
if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
|
||||||
if( s != -1 ){
|
/* This could happen with a network mount */
|
||||||
/* This could happen with a network mount */
|
tErrno = errno;
|
||||||
tErrno = errno;
|
rc = SQLITE_IOERR_UNLOCK;
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
|
||||||
pFile->lastErrno = tErrno;
|
|
||||||
}
|
|
||||||
goto end_lock;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if( s==(-1) ){
|
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
if( rc ){
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
if( rc!=SQLITE_BUSY ){
|
||||||
pFile->lastErrno = tErrno;
|
pFile->lastErrno = tErrno;
|
||||||
}
|
}
|
||||||
|
goto end_lock;
|
||||||
}else{
|
}else{
|
||||||
pFile->eFileLock = SHARED_LOCK;
|
pFile->eFileLock = SHARED_LOCK;
|
||||||
pInode->nLock++;
|
pInode->nLock++;
|
||||||
@@ -1437,22 +1455,20 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
|||||||
*/
|
*/
|
||||||
assert( 0!=pFile->eFileLock );
|
assert( 0!=pFile->eFileLock );
|
||||||
lock.l_type = F_WRLCK;
|
lock.l_type = F_WRLCK;
|
||||||
switch( eFileLock ){
|
|
||||||
case RESERVED_LOCK:
|
assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
|
||||||
lock.l_start = RESERVED_BYTE;
|
if( eFileLock==RESERVED_LOCK ){
|
||||||
break;
|
lock.l_start = RESERVED_BYTE;
|
||||||
case EXCLUSIVE_LOCK:
|
lock.l_len = 1L;
|
||||||
lock.l_start = SHARED_FIRST;
|
}else{
|
||||||
lock.l_len = SHARED_SIZE;
|
lock.l_start = SHARED_FIRST;
|
||||||
break;
|
lock.l_len = SHARED_SIZE;
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
s = unixFileLock(pFile, &lock);
|
|
||||||
if( s==(-1) ){
|
if( unixFileLock(pFile, &lock) ){
|
||||||
tErrno = errno;
|
tErrno = errno;
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
if( rc!=SQLITE_BUSY ){
|
||||||
pFile->lastErrno = tErrno;
|
pFile->lastErrno = tErrno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1523,7 +1539,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||||||
struct flock lock;
|
struct flock lock;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
int h;
|
int h;
|
||||||
int tErrno; /* Error code from system call errors */
|
|
||||||
|
|
||||||
assert( pFile );
|
assert( pFile );
|
||||||
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
|
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
|
||||||
@@ -1578,15 +1593,16 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||||||
#endif
|
#endif
|
||||||
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
||||||
if( handleNFSUnlock ){
|
if( handleNFSUnlock ){
|
||||||
|
int tErrno; /* Error code from system call errors */
|
||||||
off_t divSize = SHARED_SIZE - 1;
|
off_t divSize = SHARED_SIZE - 1;
|
||||||
|
|
||||||
lock.l_type = F_UNLCK;
|
lock.l_type = F_UNLCK;
|
||||||
lock.l_whence = SEEK_SET;
|
lock.l_whence = SEEK_SET;
|
||||||
lock.l_start = SHARED_FIRST;
|
lock.l_start = SHARED_FIRST;
|
||||||
lock.l_len = divSize;
|
lock.l_len = divSize;
|
||||||
if( unixFileLock(pFile,, &lock)==(-1) ){
|
if( unixFileLock(pFile, &lock)==(-1) ){
|
||||||
tErrno = errno;
|
tErrno = errno;
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
rc = SQLITE_IOERR_UNLOCK;
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
if( IS_LOCK_ERROR(rc) ){
|
||||||
pFile->lastErrno = tErrno;
|
pFile->lastErrno = tErrno;
|
||||||
}
|
}
|
||||||
@@ -1610,7 +1626,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||||||
lock.l_len = SHARED_SIZE-divSize;
|
lock.l_len = SHARED_SIZE-divSize;
|
||||||
if( unixFileLock(pFile, &lock)==(-1) ){
|
if( unixFileLock(pFile, &lock)==(-1) ){
|
||||||
tErrno = errno;
|
tErrno = errno;
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
rc = SQLITE_IOERR_UNLOCK;
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
if( IS_LOCK_ERROR(rc) ){
|
||||||
pFile->lastErrno = tErrno;
|
pFile->lastErrno = tErrno;
|
||||||
}
|
}
|
||||||
@@ -1623,12 +1639,15 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||||||
lock.l_whence = SEEK_SET;
|
lock.l_whence = SEEK_SET;
|
||||||
lock.l_start = SHARED_FIRST;
|
lock.l_start = SHARED_FIRST;
|
||||||
lock.l_len = SHARED_SIZE;
|
lock.l_len = SHARED_SIZE;
|
||||||
if( unixFileLock(pFile, &lock)==(-1) ){
|
if( unixFileLock(pFile, &lock) ){
|
||||||
tErrno = errno;
|
/* In theory, the call to unixFileLock() cannot fail because another
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
|
** process is holding an incompatible lock. If it does, this
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
** indicates that the other process is not following the locking
|
||||||
pFile->lastErrno = tErrno;
|
** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
|
||||||
}
|
** SQLITE_BUSY would confuse the upper layer (in practice it causes
|
||||||
|
** an assert to fail). */
|
||||||
|
rc = SQLITE_IOERR_RDLOCK;
|
||||||
|
pFile->lastErrno = errno;
|
||||||
goto end_unlock;
|
goto end_unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1637,14 +1656,11 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||||||
lock.l_whence = SEEK_SET;
|
lock.l_whence = SEEK_SET;
|
||||||
lock.l_start = PENDING_BYTE;
|
lock.l_start = PENDING_BYTE;
|
||||||
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
|
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
|
||||||
if( unixFileLock(pFile, &lock)!=(-1) ){
|
if( unixFileLock(pFile, &lock)==0 ){
|
||||||
pInode->eFileLock = SHARED_LOCK;
|
pInode->eFileLock = SHARED_LOCK;
|
||||||
}else{
|
}else{
|
||||||
tErrno = errno;
|
rc = SQLITE_IOERR_UNLOCK;
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
pFile->lastErrno = errno;
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
|
||||||
pFile->lastErrno = tErrno;
|
|
||||||
}
|
|
||||||
goto end_unlock;
|
goto end_unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1661,14 +1677,11 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||||||
SimulateIOErrorBenign(1);
|
SimulateIOErrorBenign(1);
|
||||||
SimulateIOError( h=(-1) )
|
SimulateIOError( h=(-1) )
|
||||||
SimulateIOErrorBenign(0);
|
SimulateIOErrorBenign(0);
|
||||||
if( unixFileLock(pFile, &lock)!=(-1) ){
|
if( unixFileLock(pFile, &lock)==0 ){
|
||||||
pInode->eFileLock = NO_LOCK;
|
pInode->eFileLock = NO_LOCK;
|
||||||
}else{
|
}else{
|
||||||
tErrno = errno;
|
rc = SQLITE_IOERR_UNLOCK;
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
pFile->lastErrno = errno;
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
|
||||||
pFile->lastErrno = tErrno;
|
|
||||||
}
|
|
||||||
pInode->eFileLock = NO_LOCK;
|
pInode->eFileLock = NO_LOCK;
|
||||||
pFile->eFileLock = NO_LOCK;
|
pFile->eFileLock = NO_LOCK;
|
||||||
}
|
}
|
||||||
@@ -1714,29 +1727,27 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){
|
|||||||
*/
|
*/
|
||||||
static int closeUnixFile(sqlite3_file *id){
|
static int closeUnixFile(sqlite3_file *id){
|
||||||
unixFile *pFile = (unixFile*)id;
|
unixFile *pFile = (unixFile*)id;
|
||||||
if( pFile ){
|
if( pFile->dirfd>=0 ){
|
||||||
if( pFile->dirfd>=0 ){
|
robust_close(pFile, pFile->dirfd, __LINE__);
|
||||||
robust_close(pFile, pFile->dirfd, __LINE__);
|
pFile->dirfd=-1;
|
||||||
pFile->dirfd=-1;
|
|
||||||
}
|
|
||||||
if( pFile->h>=0 ){
|
|
||||||
robust_close(pFile, pFile->h, __LINE__);
|
|
||||||
pFile->h = -1;
|
|
||||||
}
|
|
||||||
#if OS_VXWORKS
|
|
||||||
if( pFile->pId ){
|
|
||||||
if( pFile->isDelete ){
|
|
||||||
unlink(pFile->pId->zCanonicalName);
|
|
||||||
}
|
|
||||||
vxworksReleaseFileId(pFile->pId);
|
|
||||||
pFile->pId = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
OSTRACE(("CLOSE %-3d\n", pFile->h));
|
|
||||||
OpenCounter(-1);
|
|
||||||
sqlite3_free(pFile->pUnused);
|
|
||||||
memset(pFile, 0, sizeof(unixFile));
|
|
||||||
}
|
}
|
||||||
|
if( pFile->h>=0 ){
|
||||||
|
robust_close(pFile, pFile->h, __LINE__);
|
||||||
|
pFile->h = -1;
|
||||||
|
}
|
||||||
|
#if OS_VXWORKS
|
||||||
|
if( pFile->pId ){
|
||||||
|
if( pFile->isDelete ){
|
||||||
|
unlink(pFile->pId->zCanonicalName);
|
||||||
|
}
|
||||||
|
vxworksReleaseFileId(pFile->pId);
|
||||||
|
pFile->pId = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OSTRACE(("CLOSE %-3d\n", pFile->h));
|
||||||
|
OpenCounter(-1);
|
||||||
|
sqlite3_free(pFile->pUnused);
|
||||||
|
memset(pFile, 0, sizeof(unixFile));
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1745,24 +1756,25 @@ static int closeUnixFile(sqlite3_file *id){
|
|||||||
*/
|
*/
|
||||||
static int unixClose(sqlite3_file *id){
|
static int unixClose(sqlite3_file *id){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
if( id ){
|
unixFile *pFile = (unixFile *)id;
|
||||||
unixFile *pFile = (unixFile *)id;
|
unixUnlock(id, NO_LOCK);
|
||||||
unixUnlock(id, NO_LOCK);
|
unixEnterMutex();
|
||||||
unixEnterMutex();
|
|
||||||
assert( pFile->pInode==0 || pFile->pInode->nLock>0
|
/* unixFile.pInode is always valid here. Otherwise, a different close
|
||||||
|| pFile->pInode->bProcessLock==0 );
|
** routine (e.g. nolockClose()) would be called instead.
|
||||||
if( pFile->pInode && pFile->pInode->nLock ){
|
*/
|
||||||
/* If there are outstanding locks, do not actually close the file just
|
assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
|
||||||
** yet because that would clear those locks. Instead, add the file
|
if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
|
||||||
** descriptor to pInode->pUnused list. It will be automatically closed
|
/* If there are outstanding locks, do not actually close the file just
|
||||||
** when the last lock is cleared.
|
** yet because that would clear those locks. Instead, add the file
|
||||||
*/
|
** descriptor to pInode->pUnused list. It will be automatically closed
|
||||||
setPendingFd(pFile);
|
** when the last lock is cleared.
|
||||||
}
|
*/
|
||||||
releaseInodeInfo(pFile);
|
setPendingFd(pFile);
|
||||||
rc = closeUnixFile(id);
|
|
||||||
unixLeaveMutex();
|
|
||||||
}
|
}
|
||||||
|
releaseInodeInfo(pFile);
|
||||||
|
rc = closeUnixFile(id);
|
||||||
|
unixLeaveMutex();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1977,7 +1989,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
int tErrno = errno;
|
int tErrno = errno;
|
||||||
if( ENOENT != tErrno ){
|
if( ENOENT != tErrno ){
|
||||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
rc = SQLITE_IOERR_UNLOCK;
|
||||||
}
|
}
|
||||||
if( IS_LOCK_ERROR(rc) ){
|
if( IS_LOCK_ERROR(rc) ){
|
||||||
pFile->lastErrno = tErrno;
|
pFile->lastErrno = tErrno;
|
||||||
@@ -2065,7 +2077,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|||||||
if ( lrc ) {
|
if ( lrc ) {
|
||||||
int tErrno = errno;
|
int tErrno = errno;
|
||||||
/* unlock failed with an error */
|
/* unlock failed with an error */
|
||||||
lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
lrc = SQLITE_IOERR_UNLOCK;
|
||||||
if( IS_LOCK_ERROR(lrc) ){
|
if( IS_LOCK_ERROR(lrc) ){
|
||||||
pFile->lastErrno = tErrno;
|
pFile->lastErrno = tErrno;
|
||||||
rc = lrc;
|
rc = lrc;
|
||||||
@@ -2187,21 +2199,12 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* no, really, unlock. */
|
/* no, really, unlock. */
|
||||||
int rc = robust_flock(pFile->h, LOCK_UN);
|
if( robust_flock(pFile->h, LOCK_UN) ){
|
||||||
if (rc) {
|
|
||||||
int r, tErrno = errno;
|
|
||||||
r = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
|
||||||
if( IS_LOCK_ERROR(r) ){
|
|
||||||
pFile->lastErrno = tErrno;
|
|
||||||
}
|
|
||||||
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||||
if( (r & SQLITE_IOERR) == SQLITE_IOERR ){
|
return SQLITE_OK;
|
||||||
r = SQLITE_BUSY;
|
|
||||||
}
|
|
||||||
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
|
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
|
||||||
|
return SQLITE_IOERR_UNLOCK;
|
||||||
return r;
|
}else{
|
||||||
} else {
|
|
||||||
pFile->eFileLock = NO_LOCK;
|
pFile->eFileLock = NO_LOCK;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@@ -3007,6 +3010,7 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
|
|||||||
do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
|
do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
|
||||||
#else
|
#else
|
||||||
newOffset = lseek(id->h, offset, SEEK_SET);
|
newOffset = lseek(id->h, offset, SEEK_SET);
|
||||||
|
SimulateIOError( newOffset-- );
|
||||||
if( newOffset!=offset ){
|
if( newOffset!=offset ){
|
||||||
if( newOffset == -1 ){
|
if( newOffset == -1 ){
|
||||||
((unixFile*)id)->lastErrno = errno;
|
((unixFile*)id)->lastErrno = errno;
|
||||||
@@ -3375,12 +3379,16 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
|
|||||||
|
|
||||||
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
|
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
|
||||||
if( nSize>(i64)buf.st_size ){
|
if( nSize>(i64)buf.st_size ){
|
||||||
|
|
||||||
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
|
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
|
||||||
int rc;
|
/* The code below is handling the return value of osFallocate()
|
||||||
|
** correctly. posix_fallocate() is defined to "returns zero on success,
|
||||||
|
** or an error number on failure". See the manpage for details. */
|
||||||
|
int err;
|
||||||
do{
|
do{
|
||||||
rc = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
|
err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
|
||||||
}while( rc<0 && errno==EINTR );
|
}while( err==EINTR );
|
||||||
if( rc ) return SQLITE_IOERR_WRITE;
|
if( err ) return SQLITE_IOERR_WRITE;
|
||||||
#else
|
#else
|
||||||
/* If the OS does not have posix_fallocate(), fake it. First use
|
/* If the OS does not have posix_fallocate(), fake it. First use
|
||||||
** ftruncate() to set the file size, then write a single byte to
|
** ftruncate() to set the file size, then write a single byte to
|
||||||
@@ -5733,7 +5741,9 @@ static int proxyCreateUnixFile(
|
|||||||
}
|
}
|
||||||
memset(pNew, 0, sizeof(unixFile));
|
memset(pNew, 0, sizeof(unixFile));
|
||||||
pNew->openFlags = openFlags;
|
pNew->openFlags = openFlags;
|
||||||
|
memset(&dummyVfs, 0, sizeof(dummyVfs));
|
||||||
dummyVfs.pAppData = (void*)&autolockIoFinder;
|
dummyVfs.pAppData = (void*)&autolockIoFinder;
|
||||||
|
dummyVfs.zName = "dummy";
|
||||||
pUnused->fd = fd;
|
pUnused->fd = fd;
|
||||||
pUnused->flags = openFlags;
|
pUnused->flags = openFlags;
|
||||||
pNew->pUnused = pUnused;
|
pNew->pUnused = pUnused;
|
||||||
|
|||||||
39
src/test1.c
39
src/test1.c
@@ -4888,6 +4888,44 @@ static int file_control_chunksize_test(
|
|||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** tclcmd: file_control_sizehint_test DB DBNAME SIZE
|
||||||
|
**
|
||||||
|
** This TCL command runs the sqlite3_file_control interface and
|
||||||
|
** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
|
||||||
|
** SQLITE_SET_LOCKPROXYFILE verbs.
|
||||||
|
*/
|
||||||
|
static int file_control_sizehint_test(
|
||||||
|
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||||
|
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||||
|
int objc, /* Number of arguments */
|
||||||
|
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||||
|
){
|
||||||
|
sqlite3_int64 nSize; /* Hinted size */
|
||||||
|
char *zDb; /* Db name ("main", "temp" etc.) */
|
||||||
|
sqlite3 *db; /* Database handle */
|
||||||
|
int rc; /* file_control() return code */
|
||||||
|
|
||||||
|
if( objc!=4 ){
|
||||||
|
Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
|
||||||
|
|| Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
|
||||||
|
){
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
zDb = Tcl_GetString(objv[2]);
|
||||||
|
if( zDb[0]=='\0' ) zDb = NULL;
|
||||||
|
|
||||||
|
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
|
||||||
|
if( rc ){
|
||||||
|
Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** tclcmd: file_control_lockproxy_test DB PWD
|
** tclcmd: file_control_lockproxy_test DB PWD
|
||||||
**
|
**
|
||||||
@@ -5608,6 +5646,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
|||||||
{ "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
|
{ "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
|
||||||
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
|
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
|
||||||
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
|
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
|
||||||
|
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
|
||||||
{ "sqlite3_vfs_list", vfs_list, 0 },
|
{ "sqlite3_vfs_list", vfs_list, 0 },
|
||||||
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
|
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
|
||||||
|
|
||||||
|
|||||||
@@ -312,8 +312,13 @@ static int utf8_to_utf8(
|
|||||||
sqlite3TestBinToHex(z,nOut);
|
sqlite3TestBinToHex(z,nOut);
|
||||||
Tcl_AppendResult(interp, (char*)z, 0);
|
Tcl_AppendResult(interp, (char*)z, 0);
|
||||||
sqlite3_free(z);
|
sqlite3_free(z);
|
||||||
#endif
|
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
|
#else
|
||||||
|
Tcl_AppendResult(interp,
|
||||||
|
"[utf8_to_utf8] unavailable - SQLITE_DEBUG not defined", 0
|
||||||
|
);
|
||||||
|
return TCL_ERROR;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getFts3Varint(const char *p, sqlite_int64 *v){
|
static int getFts3Varint(const char *p, sqlite_int64 *v){
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ struct TestSyscallArray {
|
|||||||
/* 4 */ { "stat", (sqlite3_syscall_ptr)ts_stat, 0, 0, 0 },
|
/* 4 */ { "stat", (sqlite3_syscall_ptr)ts_stat, 0, 0, 0 },
|
||||||
/* 5 */ { "fstat", (sqlite3_syscall_ptr)ts_fstat, 0, 0, 0 },
|
/* 5 */ { "fstat", (sqlite3_syscall_ptr)ts_fstat, 0, 0, 0 },
|
||||||
/* 6 */ { "ftruncate", (sqlite3_syscall_ptr)ts_ftruncate, 0, EIO, 0 },
|
/* 6 */ { "ftruncate", (sqlite3_syscall_ptr)ts_ftruncate, 0, EIO, 0 },
|
||||||
/* 7 */ { "fcntl", (sqlite3_syscall_ptr)ts_fcntl, 0, 0, 0 },
|
/* 7 */ { "fcntl", (sqlite3_syscall_ptr)ts_fcntl, 0, EACCES, 0 },
|
||||||
/* 8 */ { "read", (sqlite3_syscall_ptr)ts_read, 0, 0, 0 },
|
/* 8 */ { "read", (sqlite3_syscall_ptr)ts_read, 0, 0, 0 },
|
||||||
/* 9 */ { "pread", (sqlite3_syscall_ptr)ts_pread, 0, 0, 0 },
|
/* 9 */ { "pread", (sqlite3_syscall_ptr)ts_pread, 0, 0, 0 },
|
||||||
/* 10 */ { "pread64", (sqlite3_syscall_ptr)ts_pread64, 0, 0, 0 },
|
/* 10 */ { "pread64", (sqlite3_syscall_ptr)ts_pread64, 0, 0, 0 },
|
||||||
@@ -275,7 +275,7 @@ static int ts_ftruncate(int fd, off_t n){
|
|||||||
static int ts_fcntl(int fd, int cmd, ... ){
|
static int ts_fcntl(int fd, int cmd, ... ){
|
||||||
va_list ap;
|
va_list ap;
|
||||||
void *pArg;
|
void *pArg;
|
||||||
if( tsIsFail() ){
|
if( tsIsFailErrno("fcntl") ){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
va_start(ap, cmd);
|
va_start(ap, cmd);
|
||||||
@@ -287,7 +287,7 @@ static int ts_fcntl(int fd, int cmd, ... ){
|
|||||||
** A wrapper around read().
|
** A wrapper around read().
|
||||||
*/
|
*/
|
||||||
static int ts_read(int fd, void *aBuf, size_t nBuf){
|
static int ts_read(int fd, void *aBuf, size_t nBuf){
|
||||||
if( tsIsFail() ){
|
if( tsIsFailErrno("read") ){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return orig_read(fd, aBuf, nBuf);
|
return orig_read(fd, aBuf, nBuf);
|
||||||
@@ -297,7 +297,7 @@ static int ts_read(int fd, void *aBuf, size_t nBuf){
|
|||||||
** A wrapper around pread().
|
** A wrapper around pread().
|
||||||
*/
|
*/
|
||||||
static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
|
static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
|
||||||
if( tsIsFail() ){
|
if( tsIsFailErrno("pread") ){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return orig_pread(fd, aBuf, nBuf, off);
|
return orig_pread(fd, aBuf, nBuf, off);
|
||||||
@@ -307,7 +307,7 @@ static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
|
|||||||
** A wrapper around pread64().
|
** A wrapper around pread64().
|
||||||
*/
|
*/
|
||||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off){
|
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off){
|
||||||
if( tsIsFail() ){
|
if( tsIsFailErrno("pread64") ){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return orig_pread64(fd, aBuf, nBuf, off);
|
return orig_pread64(fd, aBuf, nBuf, off);
|
||||||
@@ -317,7 +317,7 @@ static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off){
|
|||||||
** A wrapper around write().
|
** A wrapper around write().
|
||||||
*/
|
*/
|
||||||
static int ts_write(int fd, const void *aBuf, size_t nBuf){
|
static int ts_write(int fd, const void *aBuf, size_t nBuf){
|
||||||
if( tsIsFail() ){
|
if( tsIsFailErrno("write") ){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return orig_write(fd, aBuf, nBuf);
|
return orig_write(fd, aBuf, nBuf);
|
||||||
@@ -327,7 +327,7 @@ static int ts_write(int fd, const void *aBuf, size_t nBuf){
|
|||||||
** A wrapper around pwrite().
|
** A wrapper around pwrite().
|
||||||
*/
|
*/
|
||||||
static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
|
static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
|
||||||
if( tsIsFail() ){
|
if( tsIsFailErrno("pwrite") ){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return orig_pwrite(fd, aBuf, nBuf, off);
|
return orig_pwrite(fd, aBuf, nBuf, off);
|
||||||
@@ -337,7 +337,7 @@ static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
|
|||||||
** A wrapper around pwrite64().
|
** A wrapper around pwrite64().
|
||||||
*/
|
*/
|
||||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off){
|
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off){
|
||||||
if( tsIsFail() ){
|
if( tsIsFailErrno("pwrite64") ){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return orig_pwrite64(fd, aBuf, nBuf, off);
|
return orig_pwrite64(fd, aBuf, nBuf, off);
|
||||||
@@ -531,11 +531,17 @@ static int test_syscall_errno(
|
|||||||
const char *z;
|
const char *z;
|
||||||
int i;
|
int i;
|
||||||
} aErrno[] = {
|
} aErrno[] = {
|
||||||
{ "EACCES", EACCES },
|
{ "EACCES", EACCES },
|
||||||
{ "EINTR", EINTR },
|
{ "EINTR", EINTR },
|
||||||
{ "EIO", EIO },
|
{ "EIO", EIO },
|
||||||
{ "EOVERFLOW", EOVERFLOW },
|
{ "EOVERFLOW", EOVERFLOW },
|
||||||
{ "ENOMEM", ENOMEM },
|
{ "ENOMEM", ENOMEM },
|
||||||
|
{ "EAGAIN", EAGAIN },
|
||||||
|
{ "ETIMEDOUT", ETIMEDOUT },
|
||||||
|
{ "EBUSY", EBUSY },
|
||||||
|
{ "EPERM", EPERM },
|
||||||
|
{ "EDEADLK", EDEADLK },
|
||||||
|
{ "ENOLCK", ENOLCK },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -560,6 +560,7 @@ void sqlite3VdbeChangeP5(Vdbe *p, u8 val){
|
|||||||
** the address of the next instruction to be coded.
|
** the address of the next instruction to be coded.
|
||||||
*/
|
*/
|
||||||
void sqlite3VdbeJumpHere(Vdbe *p, int addr){
|
void sqlite3VdbeJumpHere(Vdbe *p, int addr){
|
||||||
|
assert( addr>=0 );
|
||||||
sqlite3VdbeChangeP2(p, addr, p->nOp);
|
sqlite3VdbeChangeP2(p, addr, p->nOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2942,7 +2942,7 @@ static void bestBtreeIndex(
|
|||||||
if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
|
if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 ){
|
||||||
if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
|
if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
|
||||||
testcase( pFirstTerm->eOperator==WO_EQ );
|
testcase( pFirstTerm->eOperator==WO_EQ );
|
||||||
testcase( pFirstTerm->pOperator==WO_ISNULL );
|
testcase( pFirstTerm->eOperator==WO_ISNULL );
|
||||||
whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
|
whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
|
||||||
}else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
|
}else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){
|
||||||
whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
|
whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
|
||||||
|
|||||||
@@ -840,4 +840,23 @@ do_test alter-14.2 {
|
|||||||
} {1 {Cannot add a PRIMARY KEY column}}
|
} {1 {Cannot add a PRIMARY KEY column}}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Test that it is not possible to use ALTER TABLE on any system table.
|
||||||
|
#
|
||||||
|
set system_table_list {1 sqlite_master}
|
||||||
|
catchsql ANALYZE
|
||||||
|
ifcapable analyze { lappend system_table_list 2 sqlite_stat1 }
|
||||||
|
ifcapable stat2 { lappend system_table_list 3 sqlite_stat2 }
|
||||||
|
|
||||||
|
foreach {tn tbl} $system_table_list {
|
||||||
|
do_test alter-15.$tn.1 {
|
||||||
|
catchsql "ALTER TABLE $tbl RENAME TO xyz"
|
||||||
|
} [list 1 "table $tbl may not be altered"]
|
||||||
|
|
||||||
|
do_test alter-15.$tn.2 {
|
||||||
|
catchsql "ALTER TABLE $tbl ADD COLUMN xyz"
|
||||||
|
} [list 1 "table $tbl may not be altered"]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ do_test analyze-1.11 {
|
|||||||
execsql {
|
execsql {
|
||||||
SELECT * FROM sqlite_stat1
|
SELECT * FROM sqlite_stat1
|
||||||
}
|
}
|
||||||
} {t1 {} 0}
|
} {}
|
||||||
do_test analyze-1.12 {
|
do_test analyze-1.12 {
|
||||||
catchsql {
|
catchsql {
|
||||||
ANALYZE t1;
|
ANALYZE t1;
|
||||||
@@ -106,7 +106,7 @@ do_test analyze-1.13 {
|
|||||||
execsql {
|
execsql {
|
||||||
SELECT * FROM sqlite_stat1
|
SELECT * FROM sqlite_stat1
|
||||||
}
|
}
|
||||||
} {t1 {} 0}
|
} {}
|
||||||
|
|
||||||
# Create some indices that can be analyzed. But do not yet add
|
# Create some indices that can be analyzed. But do not yet add
|
||||||
# data. Without data in the tables, no analysis is done.
|
# data. Without data in the tables, no analysis is done.
|
||||||
@@ -117,21 +117,21 @@ do_test analyze-2.1 {
|
|||||||
ANALYZE main.t1;
|
ANALYZE main.t1;
|
||||||
SELECT * FROM sqlite_stat1 ORDER BY idx;
|
SELECT * FROM sqlite_stat1 ORDER BY idx;
|
||||||
}
|
}
|
||||||
} {t1 {} 0}
|
} {}
|
||||||
do_test analyze-2.2 {
|
do_test analyze-2.2 {
|
||||||
execsql {
|
execsql {
|
||||||
CREATE INDEX t1i2 ON t1(b);
|
CREATE INDEX t1i2 ON t1(b);
|
||||||
ANALYZE t1;
|
ANALYZE t1;
|
||||||
SELECT * FROM sqlite_stat1 ORDER BY idx;
|
SELECT * FROM sqlite_stat1 ORDER BY idx;
|
||||||
}
|
}
|
||||||
} {t1 {} 0}
|
} {}
|
||||||
do_test analyze-2.3 {
|
do_test analyze-2.3 {
|
||||||
execsql {
|
execsql {
|
||||||
CREATE INDEX t1i3 ON t1(a,b);
|
CREATE INDEX t1i3 ON t1(a,b);
|
||||||
ANALYZE main;
|
ANALYZE main;
|
||||||
SELECT * FROM sqlite_stat1 ORDER BY idx;
|
SELECT * FROM sqlite_stat1 ORDER BY idx;
|
||||||
}
|
}
|
||||||
} {t1 {} 0}
|
} {}
|
||||||
|
|
||||||
# Start adding data to the table. Verify that the analysis
|
# Start adding data to the table. Verify that the analysis
|
||||||
# is done correctly.
|
# is done correctly.
|
||||||
|
|||||||
@@ -71,4 +71,52 @@ do_test analyze6-1.2 {
|
|||||||
} {0 0 0 {SCAN TABLE cat (~16 rows)} 0 1 1 {SEARCH TABLE ev USING COVERING INDEX evy (y=?) (~32 rows)}}
|
} {0 0 0 {SCAN TABLE cat (~16 rows)} 0 1 1 {SEARCH TABLE ev USING COVERING INDEX evy (y=?) (~32 rows)}}
|
||||||
|
|
||||||
|
|
||||||
|
# Ticket [83ea97620bd3101645138b7b0e71c12c5498fe3d] 2011-03-30
|
||||||
|
# If ANALYZE is run on an empty table, make sure indices are used
|
||||||
|
# on the table.
|
||||||
|
#
|
||||||
|
do_test analyze6-2.1 {
|
||||||
|
execsql {
|
||||||
|
CREATE TABLE t201(x INTEGER PRIMARY KEY, y UNIQUE, z);
|
||||||
|
CREATE INDEX t201z ON t201(z);
|
||||||
|
ANALYZE;
|
||||||
|
}
|
||||||
|
eqp {SELECT * FROM t201 WHERE z=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?) (~10 rows)}}
|
||||||
|
do_test analyze6-2.2 {
|
||||||
|
eqp {SELECT * FROM t201 WHERE y=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?) (~1 rows)}}
|
||||||
|
do_test analyze6-2.3 {
|
||||||
|
eqp {SELECT * FROM t201 WHERE x=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
|
||||||
|
do_test analyze6-2.4 {
|
||||||
|
execsql {
|
||||||
|
INSERT INTO t201 VALUES(1,2,3);
|
||||||
|
ANALYZE t201;
|
||||||
|
}
|
||||||
|
eqp {SELECT * FROM t201 WHERE z=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?) (~10 rows)}}
|
||||||
|
do_test analyze6-2.5 {
|
||||||
|
eqp {SELECT * FROM t201 WHERE y=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?) (~1 rows)}}
|
||||||
|
do_test analyze6-2.6 {
|
||||||
|
eqp {SELECT * FROM t201 WHERE x=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
|
||||||
|
do_test analyze6-2.7 {
|
||||||
|
execsql {
|
||||||
|
INSERT INTO t201 VALUES(4,5,7);
|
||||||
|
INSERT INTO t201 SELECT x+100, y+100, z+100 FROM t201;
|
||||||
|
INSERT INTO t201 SELECT x+200, y+200, z+200 FROM t201;
|
||||||
|
INSERT INTO t201 SELECT x+400, y+400, z+400 FROM t201;
|
||||||
|
ANALYZE t201;
|
||||||
|
}
|
||||||
|
eqp {SELECT * FROM t201 WHERE z=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?) (~10 rows)}}
|
||||||
|
do_test analyze6-2.8 {
|
||||||
|
eqp {SELECT * FROM t201 WHERE y=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?) (~1 rows)}}
|
||||||
|
do_test analyze6-2.9 {
|
||||||
|
eqp {SELECT * FROM t201 WHERE x=5}
|
||||||
|
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|||||||
106
test/analyze7.test
Normal file
106
test/analyze7.test
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# 2011 April 1
|
||||||
|
#
|
||||||
|
# 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 for the ANALYZE command when an idnex
|
||||||
|
# name is given as the argument.
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
|
||||||
|
# There is nothing to test if ANALYZE is disable for this build.
|
||||||
|
#
|
||||||
|
ifcapable {!analyze} {
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate some test data
|
||||||
|
#
|
||||||
|
do_test analyze7-1.0 {
|
||||||
|
execsql {
|
||||||
|
CREATE TABLE sequence(x INTEGER PRIMARY KEY);
|
||||||
|
INSERT INTO sequence VALUES(1);
|
||||||
|
INSERT INTO sequence VALUES(2);
|
||||||
|
INSERT INTO sequence SELECT x+2 FROM sequence;
|
||||||
|
INSERT INTO sequence SELECT x+4 FROM sequence;
|
||||||
|
INSERT INTO sequence SELECT x+8 FROM sequence;
|
||||||
|
INSERT INTO sequence SELECT x+16 FROM sequence;
|
||||||
|
INSERT INTO sequence SELECT x+32 FROM sequence;
|
||||||
|
INSERT INTO sequence SELECT x+64 FROM sequence;
|
||||||
|
INSERT INTO sequence SELECT x+128 FROM sequence;
|
||||||
|
INSERT INTO sequence SELECT x+256 FROM sequence;
|
||||||
|
CREATE TABLE t1(a,b,c,d);
|
||||||
|
CREATE INDEX t1a ON t1(a);
|
||||||
|
CREATE INDEX t1b ON t1(b);
|
||||||
|
CREATE INDEX t1cd ON t1(c,d);
|
||||||
|
INSERT INTO t1 SELECT x, x, x/100, x FROM sequence;
|
||||||
|
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;
|
||||||
|
}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~10 rows)}}
|
||||||
|
do_test analyze7-1.1 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~10 rows)}}
|
||||||
|
do_test analyze7-1.2 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~10 rows)}}
|
||||||
|
|
||||||
|
# Run an analyze on one of the three indices. Verify that this
|
||||||
|
# effects the row-count estimate on the one query that uses that
|
||||||
|
# one index.
|
||||||
|
#
|
||||||
|
do_test analyze7-2.0 {
|
||||||
|
execsql {ANALYZE t1a;}
|
||||||
|
db cache flush
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
|
||||||
|
do_test analyze7-2.1 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~10 rows)}}
|
||||||
|
do_test analyze7-2.2 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~10 rows)}}
|
||||||
|
|
||||||
|
# Verify that since the query planner now things that t1a is more
|
||||||
|
# selective than t1b, it prefers to use t1a.
|
||||||
|
#
|
||||||
|
do_test analyze7-2.3 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
|
||||||
|
|
||||||
|
# Run an analysis on another of the three indices. Verify that this
|
||||||
|
# new analysis works and does not disrupt the previous analysis.
|
||||||
|
#
|
||||||
|
do_test analyze7-3.0 {
|
||||||
|
execsql {ANALYZE t1cd;}
|
||||||
|
db cache flush;
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
|
||||||
|
do_test analyze7-3.1 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~10 rows)}}
|
||||||
|
do_test analyze7-3.2 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~102 rows)}}
|
||||||
|
do_test analyze7-3.3 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
|
||||||
|
do_test analyze7-3.4 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
|
||||||
|
do_test analyze7-3.5 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
|
||||||
|
do_test analyze7-3.6 {
|
||||||
|
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
|
||||||
|
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?) (~1 rows)}}
|
||||||
|
|
||||||
|
finish_test
|
||||||
@@ -105,9 +105,11 @@ foreach { i len uval xstr ustr u2u } {
|
|||||||
utf8_to_ustr2 [ sqlite3_column_text $S 0 ]
|
utf8_to_ustr2 [ sqlite3_column_text $S 0 ]
|
||||||
} $ustr
|
} $ustr
|
||||||
|
|
||||||
do_test badutf2-5.1.$i {
|
ifcapable debug {
|
||||||
utf8_to_utf8 $uval
|
do_test badutf2-5.1.$i {
|
||||||
} $u2u
|
utf8_to_utf8 $uval
|
||||||
|
} $u2u
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ proc do_re_test {tn script expression} {
|
|||||||
|
|
||||||
# Test a failure in open() due to too many files.
|
# Test a failure in open() due to too many files.
|
||||||
#
|
#
|
||||||
|
# The xOpen() method of the unix VFS calls getcwd() as well as open().
|
||||||
|
# Although this does not appear to be documented in the man page, on OSX
|
||||||
|
# a call to getcwd() may fail if there are no free file descriptors. So
|
||||||
|
# an error may be reported for either open() or getcwd() here.
|
||||||
|
#
|
||||||
do_test 1.1.1 {
|
do_test 1.1.1 {
|
||||||
set ::log [list]
|
set ::log [list]
|
||||||
list [catch {
|
list [catch {
|
||||||
@@ -55,8 +60,9 @@ do_test 1.1.1 {
|
|||||||
do_test 1.1.2 {
|
do_test 1.1.2 {
|
||||||
catch { for {set i 0} {$i < 2000} {incr i} { dbh_$i close } }
|
catch { for {set i 0} {$i < 2000} {incr i} { dbh_$i close } }
|
||||||
} {1}
|
} {1}
|
||||||
|
do_re_test 1.1.3 {
|
||||||
do_re_test 1.1.3 { lindex $::log 0 } {^os_unix.c:\d+: \(\d+\) open\(.*test.db\) - }
|
lindex $::log 0
|
||||||
|
} {^os_unix.c:\d+: \(\d+\) (open|getcwd)\(.*test.db\) - }
|
||||||
|
|
||||||
|
|
||||||
# Test a failure in open() due to the path being a directory.
|
# Test a failure in open() due to the path being a directory.
|
||||||
|
|||||||
@@ -194,6 +194,57 @@ do_test 6.2 {
|
|||||||
db close
|
db close
|
||||||
} {}
|
} {}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Test that a database file a single byte in size is treated as an empty
|
||||||
|
# file. Whereas a file 2 bytes or larger might be considered corrupt.
|
||||||
|
#
|
||||||
|
catch { db close }
|
||||||
|
forcedelete test.db test.db2
|
||||||
|
|
||||||
|
proc create_db_file {nByte} {
|
||||||
|
set fd [open test.db w]
|
||||||
|
fconfigure $fd -translation binary -encoding binary
|
||||||
|
puts -nonewline $fd [string range "xSQLite" 1 $nByte]
|
||||||
|
close $fd
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach {nByte res} {
|
||||||
|
1 {0 {}}
|
||||||
|
2 {1 {file is encrypted or is not a database}}
|
||||||
|
3 {1 {file is encrypted or is not a database}}
|
||||||
|
} {
|
||||||
|
do_test 7.$nByte {
|
||||||
|
create_db_file $nByte
|
||||||
|
sqlite3 db test.db
|
||||||
|
catchsql { CREATE TABLE t1(a, b) }
|
||||||
|
} $res
|
||||||
|
catch { db close }
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
catch { db close }
|
||||||
|
forcedelete test.db test.db2
|
||||||
|
|
||||||
|
do_test 8.1 {
|
||||||
|
sqlite3 db test.db
|
||||||
|
file_control_chunksize_test db main 4096
|
||||||
|
file size test.db
|
||||||
|
} {0}
|
||||||
|
|
||||||
|
foreach {tn hint size} {
|
||||||
|
1 1000 4096
|
||||||
|
2 1000 4096
|
||||||
|
3 3000 4096
|
||||||
|
4 4096 4096
|
||||||
|
5 4197 8192
|
||||||
|
} {
|
||||||
|
do_test 8.2.$tn {
|
||||||
|
file_control_sizehint_test db main $hint
|
||||||
|
file size test.db
|
||||||
|
} $size
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|||||||
@@ -66,7 +66,11 @@ do_faultsim_test 1 -faults vfsfault-* -prep {
|
|||||||
{1 {attempt to write a readonly database}}
|
{1 {attempt to write a readonly database}}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Errors in the fstat() function when opening and writing a file.
|
#-------------------------------------------------------------------------
|
||||||
|
# Errors in the fstat() function when opening and writing a file. Cases
|
||||||
|
# where fstat() fails and sets errno to ENOMEM and EOVERFLOW are both
|
||||||
|
# tested. EOVERFLOW is interpreted as meaning that a file on disk is
|
||||||
|
# too large to be opened by the OS.
|
||||||
#
|
#
|
||||||
foreach {tn errno errlist} {
|
foreach {tn errno errlist} {
|
||||||
1 ENOMEM {{disk I/O error}}
|
1 ENOMEM {{disk I/O error}}
|
||||||
@@ -85,12 +89,57 @@ foreach {tn errno errlist} {
|
|||||||
"
|
"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Various errors in locking functions.
|
||||||
|
#
|
||||||
|
foreach vfs {unix unix-excl} {
|
||||||
|
foreach {tn errno errlist} {
|
||||||
|
1 EAGAIN {{database is locked} {disk I/O error}}
|
||||||
|
2 ETIMEDOUT {{database is locked} {disk I/O error}}
|
||||||
|
3 EBUSY {{database is locked} {disk I/O error}}
|
||||||
|
4 EINTR {{database is locked} {disk I/O error}}
|
||||||
|
5 ENOLCK {{database is locked} {disk I/O error}}
|
||||||
|
6 EACCES {{database is locked} {disk I/O error}}
|
||||||
|
7 EPERM {{access permission denied} {disk I/O error}}
|
||||||
|
8 EDEADLK {{disk I/O error}}
|
||||||
|
9 ENOMEM {{disk I/O error}}
|
||||||
|
} {
|
||||||
|
proc vfsfault_install {} { test_syscall install fcntl }
|
||||||
|
set errs [list]
|
||||||
|
foreach e $errlist { lappend errs [list 1 $e] }
|
||||||
|
|
||||||
|
set body [string map [list %VFS% $vfs] {
|
||||||
|
sqlite3 db test.db
|
||||||
|
db eval {
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
INSERT INTO t1 VALUES(1, 2);
|
||||||
|
}
|
||||||
|
set fd [open test.db-journal w]
|
||||||
|
puts $fd "hello world"
|
||||||
|
close $fd
|
||||||
|
sqlite3 db test.db -vfs %VFS%
|
||||||
|
db eval {
|
||||||
|
SELECT * FROM t1;
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
do_faultsim_test 1.3.$vfs.$tn -faults vfsfault-* -prep {
|
||||||
|
faultsim_restore
|
||||||
|
} -body "
|
||||||
|
test_syscall errno fcntl $errno
|
||||||
|
$body
|
||||||
|
" -test "
|
||||||
|
faultsim_test_result {0 {1 2}} $errs
|
||||||
|
"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Check that a single EINTR error does not affect processing.
|
# Check that a single EINTR error does not affect processing.
|
||||||
#
|
#
|
||||||
proc vfsfault_install {} {
|
proc vfsfault_install {} {
|
||||||
test_syscall reset
|
test_syscall reset
|
||||||
test_syscall install {open ftruncate close}
|
test_syscall install {open ftruncate close read pread pread64 write fallocate}
|
||||||
}
|
}
|
||||||
|
|
||||||
forcedelete test.db test.db2
|
forcedelete test.db test.db2
|
||||||
@@ -113,16 +162,25 @@ do_faultsim_test 2.1 -faults vfsfault-transient -prep {
|
|||||||
test_syscall errno open EINTR
|
test_syscall errno open EINTR
|
||||||
test_syscall errno ftruncate EINTR
|
test_syscall errno ftruncate EINTR
|
||||||
test_syscall errno close EINTR
|
test_syscall errno close EINTR
|
||||||
|
test_syscall errno read EINTR
|
||||||
|
test_syscall errno pread EINTR
|
||||||
|
test_syscall errno pread64 EINTR
|
||||||
|
test_syscall errno write EINTR
|
||||||
|
test_syscall errno fallocate EINTR
|
||||||
|
|
||||||
sqlite3 db test.db
|
sqlite3 db test.db
|
||||||
|
file_control_chunksize_test db main 8192
|
||||||
|
|
||||||
set res [db eval {
|
set res [db eval {
|
||||||
ATTACH 'test.db2' AS 'aux';
|
ATTACH 'test.db2' AS 'aux';
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
PRAGMA journal_mode = truncate;
|
PRAGMA journal_mode = truncate;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO t1 VALUES('jkl', 'mno', 'pqr');
|
INSERT INTO t1 VALUES('jkl', 'mno', 'pqr');
|
||||||
|
INSERT INTO t1 VALUES(randomblob(10000), 0, 0);
|
||||||
UPDATE t2 SET x = 2;
|
UPDATE t2 SET x = 2;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
DELETE FROM t1 WHERE length(a)>3;
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
SELECT * FROM t2;
|
SELECT * FROM t2;
|
||||||
}]
|
}]
|
||||||
@@ -159,8 +217,31 @@ do_faultsim_test 2.2 -faults vfsfault-* -prep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
|
||||||
|
|
||||||
|
proc vfsfault_install {} {
|
||||||
|
test_syscall reset
|
||||||
|
test_syscall install {fstat fallocate}
|
||||||
|
}
|
||||||
|
do_faultsim_test 3 -faults vfsfault-* -prep {
|
||||||
|
faultsim_delete_and_reopen
|
||||||
|
file_control_chunksize_test db main 8192
|
||||||
|
execsql {
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
BEGIN;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
}
|
||||||
|
} -body {
|
||||||
|
test_syscall errno fstat EIO
|
||||||
|
test_syscall errno fallocate EIO
|
||||||
|
|
||||||
|
execsql {
|
||||||
|
INSERT INTO t1 VALUES(randomblob(10000), randomblob(10000));
|
||||||
|
SELECT length(a) + length(b) FROM t1;
|
||||||
|
COMMIT;
|
||||||
|
}
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 20000}
|
||||||
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|||||||
83
test/unixexcl.test
Normal file
83
test/unixexcl.test
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# 2011 March 30
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source code. In place of
|
||||||
|
# a legal notice, here is a blessing:
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
#
|
||||||
|
# This file contains tests for the "unix-excl" VFS module (part of
|
||||||
|
# os_unix.c).
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
source $testdir/lock_common.tcl
|
||||||
|
source $testdir/malloc_common.tcl
|
||||||
|
|
||||||
|
if {$::tcl_platform(platform)!="unix" || [info commands test_syscall]==""} {
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set testprefix unixexcl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Test that when using VFS "unix-excl", the first time the database is read
|
||||||
|
# a process-wide exclusive lock is taken on it. This means other connections
|
||||||
|
# within the process may still access the db normally, but connections from
|
||||||
|
# outside the process cannot.
|
||||||
|
#
|
||||||
|
do_multiclient_test tn {
|
||||||
|
do_test unixexcl-1.$tn.1 {
|
||||||
|
sql1 {
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
INSERT INTO t1 VALUES('hello', 'world');
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
do_test unixexcl-1.$tn.2 { sql2 { SELECT * FROM t1 } } {hello world}
|
||||||
|
do_test unixexcl-1.$tn.3 {
|
||||||
|
code1 {
|
||||||
|
db close
|
||||||
|
sqlite3 db test.db -vfs unix-excl
|
||||||
|
db eval { SELECT * FROM t1 }
|
||||||
|
}
|
||||||
|
} {hello world}
|
||||||
|
if {$tn==1} {
|
||||||
|
do_test unixexcl-1.$tn.4.multiproc {
|
||||||
|
csql2 { SELECT * FROM t1 }
|
||||||
|
} {1 {database is locked}}
|
||||||
|
} else {
|
||||||
|
do_test unixexcl-1.$tn.4.singleproc {
|
||||||
|
csql2 { SELECT * FROM t1 }
|
||||||
|
} {0 {hello world}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test that when using VFS "unix-excl", if a file is opened in read-only mode
|
||||||
|
# the behaviour is the same as if VFS "unix" were used.
|
||||||
|
#
|
||||||
|
do_multiclient_test tn {
|
||||||
|
do_test unixexcl-2.$tn.1 {
|
||||||
|
sql1 {
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
INSERT INTO t1 VALUES('hello', 'world');
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
do_test unixexcl-2.$tn.2 { sql2 { SELECT * FROM t1 } } {hello world}
|
||||||
|
do_test unixexcl-2.$tn.3 {
|
||||||
|
code1 {
|
||||||
|
db close
|
||||||
|
sqlite3 db test.db -readonly yes -vfs unix-excl
|
||||||
|
db eval { SELECT * FROM t1 }
|
||||||
|
}
|
||||||
|
} {hello world}
|
||||||
|
do_test unixexcl-2.$tn.4 {
|
||||||
|
csql2 { SELECT * FROM t1 }
|
||||||
|
} {0 {hello world}}
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_test
|
||||||
@@ -222,6 +222,7 @@ do_execsql_test where3-3.0 {
|
|||||||
CREATE INDEX t301c ON t301(c);
|
CREATE INDEX t301c ON t301(c);
|
||||||
INSERT INTO t301 VALUES(1,2,3);
|
INSERT INTO t301 VALUES(1,2,3);
|
||||||
CREATE TABLE t302(x, y);
|
CREATE TABLE t302(x, y);
|
||||||
|
INSERT INTO t302 VALUES(4,5);
|
||||||
ANALYZE;
|
ANALYZE;
|
||||||
explain query plan SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
|
explain query plan SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
|
||||||
} {
|
} {
|
||||||
@@ -341,5 +342,4 @@ do_execsql_test where3-5.3 {
|
|||||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|||||||
Reference in New Issue
Block a user