Compare commits

...

162 Commits

Author SHA1 Message Date
drh 33bafdf11d Merge the 3.40.1 changes into the reuse-schema branch.
FossilOrigin-Name: 126c68bd15dd7d26af7a584f28fc4ff82c591154aa6828e0021815e46e7f2809
2022-12-28 14:55:11 +00:00
drh 1fdaa9d1a7 Version 3.40.1
FossilOrigin-Name: df5c253c0b3dd24916e4ec7cf77d3db5294cc9fd45ae7b9c5e82ad8197f38a24
2022-12-28 14:03:47 +00:00
dan b199ac87a4 Fix a broken assert() in fts5.
FossilOrigin-Name: ff1d456161e57314b0bb4e2e720eb1cd00f71b4bf4c459fad9fef4f11d38c19f
2022-12-27 14:14:56 +00:00
dan 33f1e0ffd6 Fix a faulty assert() in fts5.
FossilOrigin-Name: 4acff807c68cf9751f5958bf8efac73ac2fe3d82d5efd62f1517796d05032075
2022-12-27 14:12:03 +00:00
dan 3caf5e7224 Fix an assert() in fts5. Simplify memdb xLock/xUnlock some.
FossilOrigin-Name: 43079c5246d4cee11239f4ec375a5159d5bf458c5add126c1a068f8278d432a1
2022-12-27 14:11:22 +00:00
drh e47e06e109 Fix a missing 0 at the end of an integer literal in the MEMSYS5 fix.
FossilOrigin-Name: e3bc10e8a8d944d57a4bc15e7a2839af6b17cc7bc553f00fb86e4757150ed47c
2022-12-27 14:06:13 +00:00
dan dffd1dd294 Fix minor problems in test scripts where.test and recover1.test.
FossilOrigin-Name: 64588bd5da228026da8d2ba679625f36802f19944e00db79c832884ef4e429cd
2022-12-27 11:53:28 +00:00
drh f7935acb67 Fix an unsafe use of sqlite3_mprintf() in sqlite3_overload_function() identified by forum post: [https://sqlite.org/forum/forumpost/95b338860d].
FossilOrigin-Name: a31522261921a75c59d84448dab50896ba2a6e8a8e106c38b523081f78e5e22d
2022-12-26 17:09:43 +00:00
drh 9940e04c67 Prevent the sessions rebaser from generating changesets containing UPDATE records for which non-PK fields are present in the old.* but not the new.* record. Also update the changeset iterator to work around such changesets.
FossilOrigin-Name: 629dbe254346dc0b78025bb73def853bd725201244baa35cf169cf425930e184
2022-12-26 17:02:15 +00:00
drh 3f095819d0 In the unix backend, when implementing the defenses against small file
descriptors, delete a file just created if it was opened with
O_EXCL|O_CREAT so that it can be created again the next time through the
loop.  Fix for the problem described by
[forum:/forumpost/699af709ab3a8ccf|forum post 699af709ab3a8ccf].

FossilOrigin-Name: 174acf3284434adb8b6c643c85c059fdf5ea5e24e95852834251ea3b3c3d1a4d
2022-12-26 16:54:15 +00:00
drh 103f51b643 Fix an over-zealous assert() reported by Yong Heng.
FossilOrigin-Name: 1e9dbb5a1bcbf66acc1073e23791d1eb804af207de9bd08f4f7425cd3ff2e5c6
2022-12-26 16:45:44 +00:00
drh 2927b4593a Ensure the RETURNING clause is honoured when a row of a temp table is updated by an ON CONFLICT clause.
FossilOrigin-Name: ac9568cf87efe5e52cef030c0336761134253acb25f7e5343ccefaf526c96b41
2022-12-26 16:24:52 +00:00
drh df6f15b822 Add the SQLITE_FCNTL_RESET_CACHE verb. Use it to ensure that the page cache is purged before and after a the recovery extension is run.
FossilOrigin-Name: 71dd920f92457a30aff21665de5d6b8fcdcb06119022bb8fd950960c2e041216
2022-12-26 16:12:40 +00:00
drh 2de62873d8 Fix corner cases in UTF8 handling in the REGEXP extension.
[forum:/forumpost/3ffe058b04|Forum post 3ffe058b04].

FossilOrigin-Name: 93e68b398329dcdd25758065c5f45b0e8c43368ab7a034201a244c7b3ac5b3dd
2022-12-26 16:03:34 +00:00
drh 91dd309476 Fix a off-by-one error in code generation that comes up when
doing a DISTINCT query against a virtual table with an OR term in the
WHERE clause and where the ORDER BY clause has 64 or more references to
the result set.  [forum:/forumpost/dfe8084751|Forum post dfe8084751].
The error is harmless in production builds, but might cause an assertion
fault in a debugging build.

FossilOrigin-Name: cbcd7d9be5e5fa6c55fa53a868ff07ee2c1725fc27c57a4bb390072e369b2be4
2022-12-26 15:55:10 +00:00
drh 57d4d2f984 Fix safe mode authorizer callback to reject disallowed UDFs. Reported at [forum:/forumpost/07beac8056151b2f|Forum post 07beac8056151b2f].
FossilOrigin-Name: 70964b8a1cfe8e47bac399db840afda9c35e36d62f1933744f49011e94a2343e
2022-12-26 15:44:50 +00:00
drh 306ff5d4e8 Fix an infinite loop in the MEMSYS5 auxiliary memory allocator that occurs
for memory allocations between 1GiB and 2GiB in size.  Error introduced
by check-in [949133231f8f751a].  The problem only affects builds that
include the SQLITE_ENABLE_MEMSYS5 compile-time option.

FossilOrigin-Name: c10d40ca683941be71f3be59b4251cf326a90a24e893169c744ade944dce3ee0
2022-12-26 15:21:42 +00:00
drh 51802270d0 Fix a problem in the memdb vfs xLock() function allowing clients to upgrade to EXCLUSIVE locks when other connections are holding SHARED.
FossilOrigin-Name: d18cce37b5b73bb2a4f28eb1b55eb2c3ffe1fc23c921c13170af3d74a549f48e
2022-12-05 14:23:06 +00:00
drh 7cb60ed011 Regenerate the configure script so that it includes the correct patch number.
FossilOrigin-Name: e2ae2ea195593f142e4a0c23b7d18381efcaa4114b1de04a97543ac264cd527e
2022-12-05 14:20:57 +00:00
drh 3ad0904dac Fix the error message in the CLI for "no such VFS".
[forum:/info/1217fdd6b3|Forum post 1217fdd6b3].

FossilOrigin-Name: b344f33d16213cd8861903b9e3e8efe9b4aaf36e742006e32b67b8ff4d5f8b7d
2022-11-22 18:24:59 +00:00
drh 4084560fdc Bump the version number to 3.40.1.
FossilOrigin-Name: d0ca348b25ce0e597054920c2124ad5965c11b58280b8fd83f1a115b557ca907
2022-11-22 15:48:02 +00:00
drh 87fa744610 Fix last function pointer in sqlite3Apis init. Reported at
[forum:/info/eba0faa96d|forum post eba0faa96d].

FossilOrigin-Name: b3795d28fe607d0e74ff120788a0db2fa76a6ce819b65ba042cc1ba00fd070a8
2022-11-22 15:47:09 +00:00
drh 9a5d7496e7 Merge version 3.40.0 into the reuse-schema branch.
FossilOrigin-Name: 2aec00a7294762b3f7e8138ea1686eda4a1b02e940ec39f261651b61b87fabad
2022-11-16 16:14:31 +00:00
drh 6a443c86e8 Merge the 3.40.0 rc1 changes into the reuse-schema branch.
FossilOrigin-Name: 886788b61e227a5e821eb92e01aaeaf19b2e9412408a9c1a351c85546452a807
2022-11-14 13:41:22 +00:00
dan 68df2e81c2 Update this branch to match latest trunk changes.
FossilOrigin-Name: 833f6374cc81a9b732bd852de6f98eef6c437f9fb18846e0022c6726324fab25
2022-11-07 18:09:23 +00:00
drh eea0f7d194 Fix harmless compiler warnings.
FossilOrigin-Name: fe44e7ef5387328f62c61e4482dbf63c3d1a4408baf20f3719d0ad344a3c714b
2022-11-05 17:52:41 +00:00
drh fc2d1f1b36 Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 224eaf2622ca0e0489d0d3feb20fb46082b866a98a216a84323c96a800618b60
2022-11-05 15:31:07 +00:00
drh 4465a0cd0b Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: b119a5e896184a54fa29349fa8ab114f1d7ea5b85f456a8ad012d74f7c84fbe3
2022-09-30 14:14:24 +00:00
drh 495e42cf5e Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 9c05a48ee0a6a02aa5f5c91f4fb4df3d6a72ca2e650920daea8989a87ab57c65
2022-08-22 16:30:46 +00:00
drh 7983d0f0b7 Merge version 3.39.0 into the reuse-schema branch.
FossilOrigin-Name: bee9903df5c89823e4e285fa1a56f20c8b0408d55bd74dbf71ea61e993da6dc9
2022-06-25 17:20:36 +00:00
drh 660e3fad0b Merge the 3.39.0 release candidate 1 changes into the reuse-schema branch.
FossilOrigin-Name: 506a3e6f242f42d3106f80ad4385a5ef458461fbd056258e65c82dd4e0a80e8c
2022-06-24 16:15:20 +00:00
drh af313837d5 Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 7f405fe209d141435562b69ff161a545c63c5804f7de37871d24d7b6ee80ecec
2022-06-16 13:57:58 +00:00
drh 39ade05f33 Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 4d46296ef6c2e7d63d2d2dc59af1e7d62c951b3c40784688811a6b4f230fc869
2022-05-28 15:01:35 +00:00
drh 1d373b4de6 Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 495f0353db126bd4ab4cd654842f253b4938a8e8bf285a186ec69f95fb221923
2022-05-17 15:33:05 +00:00
drh b928283248 Merge all recent trunk changes into the reuse-schema branch.
FossilOrigin-Name: 9f6d6e6135f9b8120fc20adfd595d5aba2004659859ef5cb6cc67981f850ccdc
2022-05-10 13:06:56 +00:00
drh d4ff324e8a Merge the latest trunk changes into the reuse-schema branch.
FossilOrigin-Name: f3fa81963ec40de02e0ba7226c7a509a27bf2a7ecfed933fa811e94721e36285
2022-03-12 15:21:23 +00:00
drh fa98d0ea0d Don't reload the schema on PRAGMA database_list.
FossilOrigin-Name: 630fe446da880b5320ff014a9f7dde683664eb5cb9fd47be5b9b32ed3c590f71
2022-02-22 20:38:45 +00:00
drh 4484700648 Merge version 3.38.0 into the reuse-schema branch.
FossilOrigin-Name: 8fe85dcdb1107a240379ea3e128c51e4be80232e632f4ec74de9b3a98e0c2061
2022-02-22 20:04:24 +00:00
drh d046825cce Merge the latest trunk changes into the reuse-schema branch.
FossilOrigin-Name: b3c26f4a34ab1557beddffccb818218a583c4daf078d338450eb79369fc2adf4
2022-02-21 16:49:49 +00:00
drh cee8c84dc9 Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: b9ba43fcb3b727fc344ab754a0132a62ff640daff8cc2ca17fd41e57fba2168d
2022-02-15 20:56:16 +00:00
drh 41a871f0d2 Merge trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 5744e1020b63f9eb89c12d6ea3ba33e17a6fea1478625c22240dcae50b50203e
2022-02-04 18:12:18 +00:00
drh da60a1b0be Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 6e4154d414afe2562b488149b10c175d1f15bd1d5060ee479d5ae9386a2e277e
2022-01-25 16:28:57 +00:00
drh 1546d749e3 Merge the latest trunk changes into the reuse-schema branch.
FossilOrigin-Name: 769ff85765746d3c94211ade114c6762baa76bb0db2dbe634334ca1beb4eed7f
2022-01-17 20:01:45 +00:00
drh bba8f23721 Merge version 3.37.0 into the reuse-schema branch.
FossilOrigin-Name: f83d50d5076339682c011329d7ab431ccaf134b37984706f199d878c3a88b553
2021-11-27 15:12:21 +00:00
drh 2ba1bb5b6f Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: d08832cb938a50891963446276d4ada3e73412ba6c316520f7cb8b180ae4f0f5
2021-11-22 16:05:44 +00:00
drh b2ded7c318 Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 748bce4c0172c60737c910c6f5b642259dcd4369b1fb473eb7fc48834fa0fcea
2021-11-09 14:00:57 +00:00
dan 9d04907363 Avoid accessing the sqlite3_module.xShadowName field if (sqlite3_module.iVersion<3).
FossilOrigin-Name: b1fc3de81e46e13f9bf592e8910a576e7573a700e8eac5be0bc839e7e2be53b6
2021-11-06 07:08:39 +00:00
drh bd564771f6 Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: ca09148e13d33a74ff75cf9c1d9e776ae0bf10ce8505656d8b5ca31398761b38
2021-11-05 23:32:17 +00:00
drh b7416ed80f Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 7623132efe9aaaf3a02d6c1ff82e199a075d2cadbe8030d2381c50509f862626
2021-10-29 14:04:22 +00:00
drh b963701038 Merge recent trunk enhancements into the reuse-schema branch
FossilOrigin-Name: cd15fc3c08373dad63ba7eafb117d0d09913b8fc339882fd909da5ec485a7138
2021-10-21 14:10:04 +00:00
drh 63f94dfe9f Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 64234c5c9a5709e7c7c1b18bf32f4374692129b353c4698010abfc98bd00bcc4
2021-10-04 11:49:35 +00:00
drh fd89e834b8 Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: c8d1f17fde280acd3e98772d947a5b1e698b08d25b23bcd0731ae2d18cfbddcf
2021-08-09 18:17:26 +00:00
drh 339fbb64be Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: d71adc3fd85cfc5902b7146101d030ab2fbe932ed05848a407a7422ddeeb4c43
2021-08-03 16:11:59 +00:00
dan 3fc9378b03 Merge latest trunk changes into this branch.
FossilOrigin-Name: 0e968f9de3b706fedb675d058ed713a9e639c46d1482dec98c3449567242501e
2021-07-09 13:29:19 +00:00
drh bfab6fb822 Merge version 3.36.0
FossilOrigin-Name: 792215204d887ecb8b1a0d65773d272b84606c9867b52d94701039de5c8bb12c
2021-06-18 19:01:15 +00:00
drh 371cc2491f Merge recent trunk enhancements into reuse-schema branch.
FossilOrigin-Name: 92d8f967c9a7e4005c63703af8075b3d2ae5aa43c6b5bc6e599735dc4479bef6
2021-06-17 17:26:53 +00:00
dan babfb2e536 Update this branch with latest changes from trunk.
FossilOrigin-Name: f21a53fb4141eaeca2fb33b25bbadfad4e461b0ed1a3526f54a42316f3dd5d9b
2021-06-14 14:35:33 +00:00
drh 1b0b429f23 The SQLITE_ENABLE_SHARED_SCHEMA compile-time option is on by default in the
configure-generated makefile, permitting a complete test of this branch
using "./configure && make test".

FossilOrigin-Name: e867d226226dafd850a5cdd1f8d5688b106ee2deee52602b2718bb59dd184742
2021-05-27 15:24:59 +00:00
dan ea8f049012 Merge latest trunk changes into this branch.
FossilOrigin-Name: dbc65a695877306e2add75aba2a279efbb30bfadb5339883cf74aa417f11de86
2021-05-22 15:05:02 +00:00
dan 356f24f0d3 Merge version 3.35.4 with this branch.
FossilOrigin-Name: e69f29892e5226957578b06e9f7966a8e820fc72c0a8b0a83773fb168caa500f
2021-04-07 15:13:47 +00:00
drh 6857efa5a8 Merge in changes for 3.35.3
FossilOrigin-Name: 76f19f4bcfc0228df669c89e0676845e98bbfe161d77b4573d6db513b751a8ca
2021-03-26 13:16:06 +00:00
drh 4d55331f24 Update to version 3.35.2
FossilOrigin-Name: 18bec0d263bd79ca94b5c9e196434e587fbce246178d329d4243ced0ad25ba10
2021-03-17 19:52:33 +00:00
drh 082f003903 Merge version 3.35.1 into the reuse-schema branch.
FossilOrigin-Name: 0fe60a63ae50acce53d576af98cf2fdd9a49f992168fe5be066abce13d1c9fa9
2021-03-15 19:34:44 +00:00
drh 017616e441 Merge the 3.35.0 release into the reuse-schema branch.
FossilOrigin-Name: c8237a024d14fc7827fec89d768cb533b78a77a2ed3b9b6df43f262d257d98a6
2021-03-12 17:26:59 +00:00
dan 89f4e8c325 Update this branch with latest fixes from trunk.
FossilOrigin-Name: 12363f8e176690d237b06e2fa6e9e3710574bdf841b8f6cef0cce34646367aa1
2021-03-11 21:00:42 +00:00
dan 8af662c8d6 Merge latest trunk changes into this branch.
FossilOrigin-Name: ef8c6e06cb094c5a6f5862f0f3f2a67c3db40dc39e520cc421311bcb55e0f762
2021-03-11 10:55:08 +00:00
drh ce3cc96805 Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 73bf458e1dbe21e19b7b283d5d7534dd8bcb01475570958fc2291e805c1cc56d
2021-03-03 19:54:08 +00:00
dan 7dd6817e58 Merge latest trunk changes into this branch.
FossilOrigin-Name: d29c41bd2670ccd205ca6190aa071c0ac7e9748bd9425fbfec0aa7acc8ae0aeb
2021-02-10 20:20:35 +00:00
dan 2f35820fdc Merge latest trunk changes into this branch.
FossilOrigin-Name: 9f41f604055553f0c62d4c0d5a00c6a43d1a938f36901238c52c065702b9c536
2020-12-17 11:30:12 +00:00
dan 85aaf75855 Update this branch with latest trunk changes.
FossilOrigin-Name: 846e8444f761a4f3e3e0fb89e87b329799a6e8dd32ac7580dc20eb6ff9ed0d36
2020-12-04 18:47:28 +00:00
drh 36b4ffef75 Merge the 3.34.0 release into the reuse-schema branch.
FossilOrigin-Name: 73b5f614cd6603d6cf9605ac4ccb510a2560fca70a8a3f3f930cf2a4e853c301
2020-12-01 16:36:04 +00:00
dan bd89471096 Merge trunk changes into this branch.
FossilOrigin-Name: f4b7c10057a50c5b1f38d4e35ec684ad9d6e21278675fec98961e1fa408ded52
2020-11-25 20:29:45 +00:00
dan 5422f18381 Merge trunk changes into this branch.
FossilOrigin-Name: 6004de525d90e5a32742349db9a7c818e1ae2d3bf3f57aff9058a3cb8f6f0fff
2020-11-18 21:15:42 +00:00
dan 934eb637c2 Merge latest trunk changes into this branch.
FossilOrigin-Name: ae1a778dbbab2beb171678c55b82a0dc095b1515ae16059e199af510bcf89c03
2020-09-07 11:23:22 +00:00
dan 8280fcc66f Merge tsan error fix from trunk into this branch.
FossilOrigin-Name: 93cc60b34278ec45e382edbd99aa22268eb32bfe6c917bad7d1e9f158cedf57b
2020-09-04 19:12:16 +00:00
dan 5a5f8b366b Update this branch with latest changes from trunk.
FossilOrigin-Name: ca8deb44c70c3d8a1cdde5bb92a3db812e4e38bfce9a97feb658594c8267609f
2020-09-04 17:40:22 +00:00
drh 73d2d7938e Merge the 3.33.0 release into the reuse-schema branch.
FossilOrigin-Name: e456d437083c550570063b874d685f110162a0551f51d5f190f90c1354e6e996
2020-08-14 13:55:40 +00:00
drh e805679133 Merge all changes since the 3.32.0 release into the reuse-schema branch.
FossilOrigin-Name: b1a77b7eade14d58b3ccd50b98c2ffb6362d093f2cde2bd178ea62cef2cb8d9f
2020-08-11 14:55:17 +00:00
drh bb85a9053e Update the reuse-schema branch to version 3.32.1
FossilOrigin-Name: ecf8dece0362b79d248bae1847d2224d18af395c336a604bbcf2b29ffab645d5
2020-05-25 16:34:57 +00:00
drh 19b2d07824 Merge version 3.32.0 into the reuse-schema branch.
FossilOrigin-Name: 31706878c3ab3ad8f84035553f0c4de25af1e371577e7caccba191fe172905ee
2020-05-22 18:41:15 +00:00
drh 02d30805c8 Bring the reuse-schema branch up to date with the latest trunk changes.
FossilOrigin-Name: d8ea0cb69d9b47c2d3e1048671623cada18cc997612edf8f617ea48882e2b052
2020-05-18 19:11:35 +00:00
drh 6d78967393 Merge trunk enhancements in the reuse-schema branch.
(Actual date of this check-in is 2020-05-18.)

FossilOrigin-Name: 5af4abe98c747ff5c6a84b6cc1f7b69d9b492a807a8fd5234163f3bd9c96c574
2020-05-16 18:59:59 +00:00
dan 006f49bc9b Merge trunk change [895bd20b29] into this branch.
FossilOrigin-Name: 507f972e91ffdc8d80a6ce594139ea4c7afad38791a08032637340fbf49842bc
2020-03-05 18:59:59 +00:00
drh 0a6e45f4d9 Merge trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 9d068e1ef04e84c025d2f696919dd5d1fe385abacbbd3ea31da58c74ae2812bf
2020-03-05 16:30:00 +00:00
dan 8e8c7ccc9b Merge latest trunk changes into this branch.
FossilOrigin-Name: 3f5650aae69498fce8c3f2b9c9e67e52f676776ea6d8a2f0f153fdeb8857231c
2020-02-27 15:20:37 +00:00
drh c3c71c1451 Merge in version 3.31.0
FossilOrigin-Name: f418afa1bfde909bb90a60990e16be6beace9788319a5e1871e94b442fcd688c
2020-01-22 20:02:11 +00:00
drh 5e87610fdf Merge recent fixes from trunk.
FossilOrigin-Name: 9c920bbad3d0a79279e8ff89a01d0f197c77d0a530ac51c57e57fe6db316c905
2020-01-20 15:32:47 +00:00
dan d3698b7fe8 Fix a couple of test case issues on this branch.
FossilOrigin-Name: 9830a44bc65e1176ca11ae84d7a291e6986662d2bbac5e352ae6e2423358c60b
2020-01-18 19:58:06 +00:00
dan 72d2de6eef Have this branch call sqlite3LockAndPrepare() instead of sqlite3Prepare() when parsing SQL for new schema objects in order to ensure that schemas are released as soon as possible.
FossilOrigin-Name: 7a4ec57985fc5d980048bb7f1677452fb8cc4825cff8956760a1747b81b648bb
2020-01-18 18:59:15 +00:00
drh 0df48684bd Fix the assert_schema_state_ok() routine so that it correctly ignores
ATTACH-ed database that failed to open due to an error.

FossilOrigin-Name: 1194a42add4119715347bb592feef352e4958d0c669c946d976a42049a712b68
2020-01-15 17:18:34 +00:00
drh 106ab91fc8 Merge all recent enhancements and fixes from trunk.
FossilOrigin-Name: f783917800a5ce7c4bb31725b26d266cd4f133a0cc8414c6bf4789a8cd1e45c8
2020-01-15 14:26:58 +00:00
drh 806e04ab8f Bring the reuse-schema branch up-to-date with version 3.30.0.
FossilOrigin-Name: 6e09afecd6086211253b5f8eab718dde097f92a88100e54604a3f063c1a1fc98
2019-10-04 15:31:42 +00:00
drh eb888e2497 Merge in the 3.30.0 beta 1 changes.
FossilOrigin-Name: 067961241293b99b7f716e6f05e302b8354c9e7216296148b6f4ab59f8d3f4b0
2019-09-30 16:57:25 +00:00
drh d973196e30 Merge all recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 27eb223690989a294c5aad7a8ab1927904b1041e36ce7a0c04800bce49ec9142
2019-09-16 12:35:48 +00:00
dan f6b6f46538 Merge latest trunk changes with this branch.
FossilOrigin-Name: 5b4689d89cd27b238586ddee638b856145a9731ff70ffcb1659613528b792167
2019-08-13 15:22:10 +00:00
dan f8f62070f8 In shared-schema mode, handle the case where a connection has created a virtual-table object, but is later assigned a different shared-schema object for which the virtual-table schema has not yet been initialized.
FossilOrigin-Name: e30c7414fe483fcb68aeedd364dc5a3da62b01a80808a917016a9f148f1f3130
2019-08-09 14:54:44 +00:00
dan 73debcccd1 Fix spurious "no such table: x1" errors in shared-schema mode that could occur
when a query that is a join across two or more databases needs to call the xConnect() methods of a virtual table.

FossilOrigin-Name: edf45cd7c6c1122db961ae66c21c7e974115e6048f1f5014015a5f693f1844bf
2019-08-08 15:47:32 +00:00
dan 1430806e39 Fix a bug causing "no such table" and other similar sqlite3_prepare*() errors to return SQLITE_SCHEMA instead of SQLITE_ERROR in shared-schema mode when there is an attached database for which the schema has never been loaded.
FossilOrigin-Name: 111e2c73cf430ae61e3f4cc34a1bee8ac7025b8a960fc3f3b7f493009b759ad7
2019-08-08 11:44:57 +00:00
dan 49c7657ac9 Add a multi-threaded test to threadtest3.c for the feature on this branch.
FossilOrigin-Name: 62557fab0d21d47893e69d504ae2b4405c1837ccd6300a5a6743cb756eb28ad3
2019-08-06 15:02:49 +00:00
dan e046ccb5f0 Add an assert() to the code on this branch.
FossilOrigin-Name: fdd44bbb501c7252097e79685e916e760846e183bc9f022f9cf32f1d32f0089d
2019-08-06 11:45:33 +00:00
dan 0b5d397cb4 Merge latest changes from trunk into this branch.
FossilOrigin-Name: 7f1e4e4b99644f986aa68bd40afddc4886145972eae1106347185eeff52150d6
2019-07-26 20:54:05 +00:00
drh 2833522a9a Add a ctime.c entry for SQLITE_ENABLE_SHARED_SCHEMA.
FossilOrigin-Name: 892ac94511a41dc4043ceb76aae267b1252d08fee41c475fb848c15519477adb
2019-07-18 19:50:54 +00:00
dan 06526fef2e Modify the bits used for special flags on this branch to account for the fact that some of them are now used for other purposes.
FossilOrigin-Name: 5a8d0f50f3c4dedfd7f97daba4cb1a8cfbe3bc44e0834199d4dd93a0d062ef81
2019-07-18 13:33:00 +00:00
drh 7e0410951f Merge the version 3.29.0 release enhancements into the reuse-schema branch.
FossilOrigin-Name: 9819ead089ef5ed92f529d9addbd89760ca5be7eacb3d209c99f639ec5761004
2019-07-10 18:45:50 +00:00
drh abbad7ef3c Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: fae92fee54685cf0d44937e246e79652ee4679baa3bfb2774ff3ecf739a1e1e7
2019-07-08 21:32:00 +00:00
drh cdfb4a29f4 Updates to the shared_schema.md notes document.
FossilOrigin-Name: 51af2ade8eddae16a7290ab9676bcb4a677f0be72959640d0b664966398d8319
2019-06-03 14:02:58 +00:00
drh ce86700aa7 In the CLI, add ".help" text for the .shared-schema command.
FossilOrigin-Name: 3ba6f790e029f8c66b9ba16c657463606e6d45e095a498407154477c1358fbb2
2019-06-03 13:46:50 +00:00
drh 5593a4c26d The ".shared-schema" command in the CLI requires the sqlite_dbpage table,
so disable it if the build does not include that extension.

FossilOrigin-Name: 0913ff4dc38290677357885ca40fe19ce45dafea6168a4e7403f0af083a48c65
2019-05-24 13:15:52 +00:00
drh 88e7099875 Merge recent enhancements from trunk.
FossilOrigin-Name: ff9f3e09510b4418cb166fa2557598a279e7baedc315a5d1c3ae63beb92c238d
2019-05-24 13:04:55 +00:00
drh 28c156d6d6 Merge all the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 018f3199b9ba043fbbf88ec46b4fa16728f6507e000f4813ed346aaf6665add6
2019-05-14 22:25:26 +00:00
drh e2e8e9b16f Merge recent changes from trunk into reuse-schema
FossilOrigin-Name: 5c6c9e7f6f83d565b317e3442e8bc664478adb407fe416d068fe0dcd17ffa5b5
2019-04-15 15:35:43 +00:00
dan ff0e1d8d04 Remove a "puts" statement accidentally left in a test script.
FossilOrigin-Name: 9f591ac07871958d173ae4cf9065c8000a9efb80676d158935d2700fff61a361
2019-03-26 19:14:50 +00:00
dan 98c5bff6c8 Add a few extra tests for SQLITE_STATUS_SCHEMA_USED with shared-schema databases.
FossilOrigin-Name: e399fede7b27a70f90e363d987f23004d7015844f38d00d6d216433d70e4b901
2019-03-26 18:40:38 +00:00
drh 3eadd64c0e Merge recent trunk enhancements.
FossilOrigin-Name: db4e2cc36acca2708e9bd2e0febb4e1b3d6a6a3fa60d9bd6f2a49f4a8d1bc523
2019-03-26 11:57:50 +00:00
dan d32261e7a9 Merge latest trunk changes with this branch.
FossilOrigin-Name: 3196f5f480f221dc71bb92e6718a5c356782774be25df4df79dda0ac1101255a
2019-03-21 17:22:05 +00:00
dan 6847647dc4 Disable the feature on this branch in non-SQLITE_ENABLE_SHARED_SCHEMA builds.
FossilOrigin-Name: b8e536089b0e6dec500a28556f826c99b78d979615ba3bc01ed31ead1b2112df
2019-03-21 17:13:55 +00:00
dan ae070eff74 Use the IsReuseSchema() macro more consistently. Also, rename it to IsSharedSchema().
FossilOrigin-Name: c1be211c0286a6ff3ef8ab6839136175efb000118ff8704d3cc01b2a23b841ab
2019-03-20 20:02:03 +00:00
dan f4c01da150 Fix an error message.
FossilOrigin-Name: a70fdaa3903835dca338d68e750716fd3ab9dedbdfb2be6d6e058fd5fcb415fa
2019-03-20 19:17:45 +00:00
dan 0d46c528dd Merge latest trunk changes into this branch.
FossilOrigin-Name: 4cd20ca6776ef1c2f041fe6d30f84a3cf5f8a634eb34db2dce3217ee781d5848
2019-03-20 16:03:02 +00:00
dan 209f79234b Merge latest trunk changes into this branch.
FossilOrigin-Name: 97a9604d85cf5044e8109e533d4682b25bfe6a110f403ebd0fdef03880059f37
2019-03-04 07:25:38 +00:00
dan 22b16ac3d0 Update doc/shared_schema.md to describe the shell tool ".shared-schema" dot-command.
FossilOrigin-Name: 0ce2092a5968d75d014fdc238391c362a9600c28bf18cdc631e98259a5278712
2019-02-26 16:36:21 +00:00
dan 88a96c49f2 Add new test file reuse5.test. For testing the shell tool ".shared-schema" command.
FossilOrigin-Name: fa6008d547c6b24108a26e022f3f427fa19ffae006c88fee9de97d2244521de0
2019-02-26 16:13:43 +00:00
dan 85a76ddc12 Add the ".shared-schema check|fix DB1 DB2..." command to the shell tool. For checking if a database is eligible to share an in-memory with the main database, and for fixing small problems that prevent it from being so.
FossilOrigin-Name: 7d8e8a957235479fba568e1d3ff2cdfe4695184ee1a7ac64bce905a993725164
2019-02-26 15:43:45 +00:00
dan 20a434abd3 Fix a comment in build.c.
FossilOrigin-Name: d6a9bff6f5cc52957deffe47fdba1197db111cac110760dec7680f91499a99f1
2019-02-25 19:23:01 +00:00
dan 9c2b284dbd Merge latest trunk changes into this branch.
FossilOrigin-Name: 5c1cf30859ed734eb2d6bc52adb057ca62a6b5a7eef66d8da1fa833e84468dee
2019-02-25 18:07:09 +00:00
dan 74e020a164 Where possible, avoid loading all schemas into memory for PRAGMA statements.
FossilOrigin-Name: 64f97530ad387655767b5205fb9a9c723210cd4975176ab6fb71bca0cb585a74
2019-02-25 17:54:23 +00:00
dan 94dba01337 Merge latest trunk changes into this branch.
FossilOrigin-Name: 001771afd0567c04736a778fc78fd7144492ae7c830e7f55de61869ce988f0ed
2019-02-22 17:44:58 +00:00
dan 239f69e204 Further test cases and fixes for SQLITE_OPEN_SHARED_SCHEMA.
FossilOrigin-Name: ba0ab042f401a9d3b81dc546573214bbe2ad712c932aafcf0c045f189bbf09ca
2019-02-20 18:44:28 +00:00
dan 05a094d4c5 Add test and fixes for SQLITE_OPEN_SHARED_SCHEMA mode.
FossilOrigin-Name: 9a78d89c8427ae737d4798cc146e41ada7cb83f4e39dcf3ac9469c510ed37673
2019-02-20 17:36:10 +00:00
dan aec53fa5ba Improve error messages caused by corrupt database schemas in OPEN_SHARED_SCHEMA mode.
FossilOrigin-Name: 8ac75b8a880447ea67cf7646fc5af1379ce35861f396634119d7381e1dde404a
2019-02-19 18:00:28 +00:00
dan a011145aae Ensure that creating temp schema items does not cause an OPEN_SHARABLE_SCHEMA connection to load all schemas into memory.
FossilOrigin-Name: 88cbf54eee7845f9e40e6879fc38eb98a80e81c987b7edeb39f3058590003347
2019-02-18 18:16:05 +00:00
dan 13af9ba7af Enhance the virtual table in test_schemapool.c so that it can be used to check that SHARED_SCHEMA connections are not allocating and freeing schemas when they should not be.
FossilOrigin-Name: cb236cb98564b870317ba3e481a3c7d7f9769b0294a01246bcb724f04e1e7b10
2019-02-15 19:36:47 +00:00
dan 6170a98cfa Fix a problem with eponymous virtual tables and SHARED_SCHEMA databases. Also, after preparing statements that require all database schemas (REINDEX, ANALYZE, CREATE, DROP and some PRAGMA statements), do not allow the database connection to return more than one schema to each schema-pool.
FossilOrigin-Name: ecf6251ec0bb745a4ef9bad9f9ecd3babb687a3806fd96554b265313625270c5
2019-02-15 19:00:41 +00:00
dan d0932d5358 Revert the rearrangement of VDBE code in [219b39e14] so that vdbe.c matches trunk. Since the new call to sqlite3Init() in OP_ParseSchema was removed, the rearrangement no longer provides any performance advantage.
FossilOrigin-Name: 03c4f00317233a34f29e1218786166d17837d47206532a29d2713093f01adea5
2019-02-15 11:54:57 +00:00
dan 61155cb70b Fix SQLITE_DBSTATUS_SCHEMA_USED so that it works with SQLITE_OPEN_SHARED_SCHEMA connections.
FossilOrigin-Name: d43b3c056cb13930865c504c9498b2c83e4bebce9bff01ee21293e7dc7a6711e
2019-02-14 21:04:27 +00:00
dan d746d250f0 Change the name of the SQLITE_OPEN_REUSE_SCHEMA flag to SQLITE_OPEN_SHARED_SCHEMA.
FossilOrigin-Name: 7257fcc8c990b46a4f6a9e506f4a4a40195e6b2c626efd380cfa01f0ce8eb0fb
2019-02-14 18:38:44 +00:00
dan 155a112b81 Fix a typo in shared_schema.md.
FossilOrigin-Name: e47a5aea76560e86e5417fea9e2219ec6c30e47ef383e499cfe927f64d584dac
2019-02-14 17:59:36 +00:00
dan a5150d4f05 Add documentation file doc/shared_schema.md to describe the change on this branch.
FossilOrigin-Name: a5f8067dde1e8974f779ab838a02416a7dd9d20d253af860d08d635cfede6fee
2019-02-14 17:51:38 +00:00
dan 64104062a7 Merge latest trunk into this branch.
FossilOrigin-Name: 577d1638362666a8220401d0d0d8bfb3c028ab09e7def1e4bf195db37269c22f
2019-02-14 15:56:59 +00:00
dan 1395c92f1f Add missing comments and fix other code issues in the new functions in callback.c.
FossilOrigin-Name: 441cabb62fe14bbef8b19066941426eeb2de128564ec2bfb762228fdae794447
2019-02-14 15:47:18 +00:00
dan 33a37f5ef0 Fix for sqlite3_table_column_metadata() on REUSE_SCHEMA databases.
FossilOrigin-Name: 53220ad7809954eb4118d9127849efa82787f43898af00c9127cd4998a12c619
2019-02-13 19:17:30 +00:00
dan 9d65677e57 Avoid crashing after parsing a corrupt schema with a REUSE_SCHEMA connection.
FossilOrigin-Name: b102148e71c0102eedbf28d9bc8ea8d9bd742eac45ee7f1b08ece60bcdab5036
2019-02-13 18:29:49 +00:00
dan 6758315c8e Fix a problem with the incrblob API and reusable schemas.
FossilOrigin-Name: 34f0f96f47040df1e305ac9fd4664c5ed4246580e22a00573c73d6528a5725b5
2019-02-13 15:51:07 +00:00
drh 5944230305 Rearrange the code in the VDBE to help out the C-compiler optimizer.
And fix a harmless compiler warning.

FossilOrigin-Name: 219b39e149a0334b577e094e066e1ca2fe686b408468e9f196611490f3a82810
2019-02-13 14:06:56 +00:00
drh a72a438cd7 Performance optimization in the VDBE, and a fix for a harmless compiler
warning.

FossilOrigin-Name: e002666ac79c3452a772323c6ecc696104341cd842e77541553ec028f188096b
2019-02-13 13:48:48 +00:00
dan d62150108a Fix a problem with OPEN_REUSE_SCHEMA connections reloading the temp schema.
FossilOrigin-Name: 7c2ec2d4cfcda9c0aa6d57bd9a12ff98b78e648533d49da27f91d5a37bf1e001
2019-02-13 08:40:34 +00:00
dan 2ce6757bd4 Add tests for creating temp schema objects with SQLITE_OPEN_REUSE_SCHEMA connections.
FossilOrigin-Name: 8c07b609fccc43795498b942c733896defd8887e4ddd9e0ef48c124dfcf9fd7f
2019-02-12 20:58:34 +00:00
dan 33d1394e1a Share schemas between databases attached to the same database handle.
FossilOrigin-Name: ea611d7cba604dc901c8088ccfa13367a5ee75f9499ea8d8b62a590daac2eae0
2019-02-12 19:20:33 +00:00
dan 81fb4ef019 Merge latest trunk changes into this branch.
FossilOrigin-Name: dbedd81bf2e29ae9ed88526c1cc97e5c4d0a256ad7d960304bbb5e15c44f51f0
2019-02-11 20:13:13 +00:00
dan d4e11dd78f Add eponymous virtual table "schemapool". For inspecting the current contents of the schema-pool.
FossilOrigin-Name: 2ebeb747832bd53284ab23b4c2558f0fa550c0ea2b4a6c1640eeb83f8132c556
2019-02-11 19:34:38 +00:00
dan 5add6f25e2 Fix virtual table support for SQLITE_OPEN_REUSABLE_SCHEMA connections.
FossilOrigin-Name: 3ca8856a7b1c36885cea007b8fb05b59f1fdc9d4b54436819193f498519a23c7
2019-02-09 17:47:14 +00:00
dan 30fdc47579 Add test cases and fix problems on this branch.
FossilOrigin-Name: 2b2e9f81cdc7a3ac1eacc087fbd0414ead732878aae296bab6b54b4a7cd0a06e
2019-02-08 19:30:09 +00:00
dan 73e6f3adbd Merge latest trunk into this branch.
FossilOrigin-Name: c089cc4fbe2e5e53d76154146870d14fc3b8d342a49580e41a5616817099715c
2019-02-05 19:51:15 +00:00
dan 73b8e1f2d6 Fix memory leaks on this branch.
FossilOrigin-Name: e9c5e1891ff4f7e57131031f068efea87027ddab0cd7846e0514a105853be47d
2019-02-05 19:15:36 +00:00
dan 01d6eab9a5 Fix a problem with reloading the schema on this branch.
FossilOrigin-Name: 5dfbef8349e47f9d9fcdbb648ecd18b5bc7eebdb1a3ddaf91789d036b7de8a90
2019-02-04 21:02:00 +00:00
dan e54087db7b Try new approach ensuring that each Schema object is only used by one connection/database at any one time.
FossilOrigin-Name: 9e8e5f52cf90579c3071f04a3c6857bb76b4ca1b1900a7f865de789ed0bb8678
2019-02-02 21:02:22 +00:00
dan d000f2286d Merge latest trunk changes with this branch.
FossilOrigin-Name: ae88f8e1ffc33748e45308c21ba83499228ae05344df81e41dd61e14a1270588
2018-11-09 18:44:45 +00:00
drh 8874678ecd Add the ability to open a database connection in -reuseschema mode in the CLI.
Adjust memory allocation accounting so that a shared schema is allocated
across each database sharing it.

FossilOrigin-Name: 3869b2106b9a639b5e739dc9f9acd2f7a9223d3ce562297b877c5d4d2bf76468
2018-10-08 23:29:05 +00:00
dan 8612853f70 Fix a problem with using virtual tables via reuse-schema connections.
FossilOrigin-Name: e5897dafda2b003c34eeecb44e091e2ac0d8589c9db728a0b02fb56966cfc9b7
2018-10-08 20:57:35 +00:00
drh 62012c0b34 Merge fixes from trunk.
FossilOrigin-Name: 9c8255a199d6544b02302bfe3ecd253098821170646a509d2e3dc6cf4e43289b
2018-10-08 20:37:21 +00:00
dan 7d3159668c Merge latest trunk changes into this branch.
FossilOrigin-Name: 2ac72114a1f5344b42472b941c60f460c28c981a22ea40909b30f7bf4eb4b11b
2018-10-08 18:58:51 +00:00
dan d6af93a92c Add experimental sqlite3_open_v2() flag SQLITE_OPEN_REUSE_SCHEMA. For sharing
identical in-memory schema objects between connections.

FossilOrigin-Name: a625698048c05375f12ea8875892fdbf3518291f10917fe68dd2294280cd3b42
2017-08-09 20:35:10 +00:00
70 changed files with 3877 additions and 353 deletions
+3
View File
@@ -140,6 +140,7 @@ GCOV_LDFLAGS1 = -lgcov
USE_GCOV = @USE_GCOV@
LTCOMPILE_EXTRAS += $(GCOV_CFLAGS$(USE_GCOV))
LTLINK_EXTRAS += $(GCOV_LDFLAGS$(USE_GCOV))
LTCOMPILE_EXTRAS += -DSQLITE_ENABLE_SHARED_SCHEMA
# The directory into which to store package information for
@@ -420,6 +421,7 @@ TESTSRC = \
$(TOP)/src/test_quota.c \
$(TOP)/src/test_rtree.c \
$(TOP)/src/test_schema.c \
$(TOP)/src/test_schemapool.c \
$(TOP)/src/test_server.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
@@ -484,6 +486,7 @@ TESTSRC2 = \
$(TOP)/src/bitvec.c \
$(TOP)/src/btree.c \
$(TOP)/src/build.c \
$(TOP)/src/callback.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbpage.c \
+1
View File
@@ -1538,6 +1538,7 @@ TESTSRC = \
$(TOP)\src\test_quota.c \
$(TOP)\src\test_rtree.c \
$(TOP)\src\test_schema.c \
$(TOP)\src\test_schemapool.c \
$(TOP)\src\test_server.c \
$(TOP)\src\test_superlock.c \
$(TOP)\src\test_syscall.c \
+1 -1
View File
@@ -1 +1 @@
3.40.0
3.40.1
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.40.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.40.1.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.40.0'
PACKAGE_STRING='sqlite 3.40.0'
PACKAGE_VERSION='3.40.1'
PACKAGE_STRING='sqlite 3.40.1'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1468,7 +1468,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.40.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.40.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1533,7 +1533,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.40.0:";;
short | recursive ) echo "Configuration of sqlite 3.40.1:";;
esac
cat <<\_ACEOF
@@ -1661,7 +1661,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.40.0
sqlite configure 3.40.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2080,7 +2080,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.40.0, which was
It was created by sqlite $as_me 3.40.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12390,7 +12390,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.40.0, which was
This file was extended by sqlite $as_me 3.40.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12456,7 +12456,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.40.0
sqlite config.status 3.40.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+142
View File
@@ -0,0 +1,142 @@
Shared-Schema Mode Notes
========================
The [reuse-schema](/timeline?r=reuse-schema) branch contains changes
to allow SQLite connections to share schemas
between database connections within the same process in order to save memory.
Schemas may be shared between multiple databases attached to the same or
distinct connection handles.
Compile with -DSQLITE\_ENABLE\_SHARED\_SCHEMA in order to enable the
shared-schema enhancement. Enabling the shared-schema enhancement causes
approximately a 0.1% increase in CPU cycles consumed and about a 3000-byte
increase in the size of the library, even if shared-schema is never used.
Assuming the compile-time requirements are satisfied, the shared-schema
feature is engaged by opening the database connection using the
sqlite3&#95;open&#95;v2() API with the SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA
flag specified. The main database and any attached databases will then share
an in-memory Schema object with any other database opened within the process
for which:
* the contents of the sqlite&#95;master table, including all object names,
SQL statements and root pages are identical, and
* have the same values for the schema-cookie.
Temp databases (those populated with "CREATE TEMP TABLE" and similar
statements) never share schemas.
Connections opened with the SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA flag
specified may not modify any database schema except that belonging to the
temp database in anyway. This includes creating or dropping database
objects, vacuuming the database, or running ANALYZE when the
sqlite&#95;stat\[14\] tables do not exist.
For SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA connections, the
SQLITE&#95;DBSTATUS&#95;SCHEMA&#95;USED sqlite3&#95;db&#95;status() verb
distributes the memory used for a shared schema object evenly between all
database connections that share it.
## The ".shared-schema" Command
The shell tool on this branch contains a special dot-command to help with
managing databases. The ".shared-schema" dot-command can be used to test
whether or not two databases are similar enough to share in-memory schemas,
and to fix minor problems that prevent them from doing so. To test if
two or more database are compatible, one database is opened directly using
the shell tool and the following command issued:
.shared-schema check <database-1> [<database-2>]...
where &lt;database-1&gt; etc. are replaced with the names of database files
on disk. For each database specified on the command line, a single line of
output is produced. If the database can share an in-memory schema with the
main database opened by the shell tool, the output is of the form:
<database> is compatible
Otherwise, if the database cannot share a schema with the main db, the output
is of the form:
<database> is NOT compatible (<reason>)
where &lt;reason&gt; indicates the cause of the incompatibility. &lt;reason&gt;
is always one of the following.
<ul>
<li> <b>objects</b> - the databases contain a different set schema objects
(tables, indexes, views and triggers).
<li> <b>SQL</b> - the databases contain the same set of objects, but the SQL
statements used to create them were not the same.
<li> <b>root pages</b> - the databases contain the same set of objects created
by the same SQL statements, but the root pages are not the same.
<li> <b>order of sqlite&#95;master rows</b> - the databases contain the same
set of objects created by the same SQL statements with the same root pages,
but the order of the rows in the sqlite&#95;master tables are different.
<li> <b>schema cookie</b> - the database schemas are compatible, but the
schema cookie values ("PRAGMA schema&#95;version") are different.
</ul>
The final three problems in the list above can be fixed using the
.shared-schema command. To modify such a database so that it can share a
schema with the main database, the following shell command is used:
.shared-schema fix <database-1> [<database-2>]...
If a database can be modified so that it may share a schema with the main
database opened by the shell tool, output is as follows:
Fixing <database>... <database> is compatible
If a database does not require modification, or cannot be modified such that
it can share a schema with the main database, the output of "fix" is identical
to that of the "check" command.
## Implementation Notes
A single Schema object is never used by more than one database simultaneously,
regardless of whether or not those databases are attached to the same or
different database handles. Instead, a pool of schema objects is maintained
for each unique sqlite&#95;master-contents/schema-cookie combination
opened within the process. Each time database schemas are required by a
connection, for example as part of an sqlite3&#95;prepare\*(),
sqlite3&#95;blob&#95;open() or sqlite3&#95;blob&#95;open() call, it obtains
the minimum number of schemas required from the various schema-pools, returning
them at the end of the call. This means that a single schema-pool only ever
contains more than one copy of the schema if:
* Two threads require schemas from the same pool at the same time, or
* A single sqlite3&#95;prepare\*() call requires schemas for two or more
attached databases that use the same schema-pool.
The size of a schema-pool never shrinks. Each schema pool always maintains
a number of schema objects equal to the highwater mark of schema objects
simultaneously required by clients.
This approach is preferred to allowing multiple databases to use the same
Schema object simultaneously for three reasons:
* The Schema object is not completely read-only. For example, the
Index.zIdxAff string is allocated lazily.
* Throughout the statement compiler, SQLite uses variables like
Table.pSchema and Index.pSchema with the sqlite3SchemaToIndex() routine
in order to determine which attached database a Table or Index object
resides in. This mechanism does not work if the same Schema may be
used by two or more attached databases.
* It may be easier to modify this approach in order to allow
SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA connections to modify database
schemas, should that be required.
SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA connections do not store their
virtual-table handles in the Table.pVTable list of each table. This would not
work, as (a) there is no guarantee that a connection will be assigned the same
Schema object each time it requests one from a schema-pool and (b) a single
Schema (and therefore Table) object may correspond to tables in two or more
databases attached to a single connection. Instead, all virtual-table handles
associated with a single database are stored in a linked-list headed at
Db.pVTable.
+5 -5
View File
@@ -260,7 +260,7 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
break;
case FTS5_SYNC:
assert( p->ts.eState==1 );
assert( p->ts.eState==1 || p->ts.eState==2 );
p->ts.eState = 2;
break;
@@ -275,21 +275,21 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
break;
case FTS5_SAVEPOINT:
assert( p->ts.eState==1 );
assert( p->ts.eState>=1 );
assert( iSavepoint>=0 );
assert( iSavepoint>=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint;
break;
case FTS5_RELEASE:
assert( p->ts.eState==1 );
assert( p->ts.eState>=1 );
assert( iSavepoint>=0 );
assert( iSavepoint<=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint-1;
break;
case FTS5_ROLLBACKTO:
assert( p->ts.eState==1 );
assert( p->ts.eState>=1 );
assert( iSavepoint>=-1 );
/* The following assert() can fail if another vtab strikes an error
** within an xSavepoint() call then SQLite calls xRollbackTo() - without
@@ -1625,7 +1625,7 @@ static int fts5UpdateMethod(
int rc = SQLITE_OK; /* Return code */
/* A transaction must be open when this is called. */
assert( pTab->ts.eState==1 );
assert( pTab->ts.eState==1 || pTab->ts.eState==2 );
assert( pVtab->zErrMsg==0 );
assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
+91
View File
@@ -352,5 +352,96 @@ do_test 13.3 {
sqlite3_errmsg db
} {not an error}
#-------------------------------------------------------------------------
reset_db
db close
sqlite3 db test.db -uri 1
do_execsql_test 14.0 {
PRAGMA locking_mode=EXCLUSIVE;
BEGIN;
ATTACH 'file:/one?vfs=memdb' AS aux1;
ATTACH 'file:/one?vfs=memdb' AS aux2;
CREATE VIRTUAL TABLE t1 USING fts5(x);
} {exclusive}
do_catchsql_test 14.1 {
ANALYZE;
} {1 {database is locked}}
do_catchsql_test 14.2 {
COMMIT;
} {1 {database is locked}}
do_catchsql_test 14.3 {
COMMIT;
} {1 {database is locked}}
do_catchsql_test 14.4 {
ROLLBACK;
} {0 {}}
#-------------------------------------------------------------------------
reset_db
sqlite3 db2 test.db
do_execsql_test 15.0 {
CREATE TABLE t1(a, b);
BEGIN;
SELECT * FROM t1;
}
do_execsql_test -db db2 15.1 {
BEGIN;
CREATE VIRTUAL TABLE x1 USING fts5(y);
}
do_test 15.2 {
list [catch { db2 eval COMMIT } msg] $msg
} {1 {database is locked}}
do_execsql_test -db db2 15.3 {
SAVEPOINT one;
} {}
do_execsql_test 15.4 END
do_test 15.4 {
list [catch { db2 eval COMMIT } msg] $msg
} {0 {}}
#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
sqlite3 db2 test.db
do_execsql_test 16.0 {
ATTACH 'test.db2' AS aux;
CREATE TABLE aux.t2(x,y);
INSERT INTO t2 VALUES(1, 2);
CREATE VIRTUAL TABLE x1 USING fts5(a);
BEGIN;
INSERT INTO x1 VALUES('abc');
INSERT INTO t2 VALUES(3, 4);
}
do_execsql_test -db db2 16.1 {
ATTACH 'test.db2' AS aux;
BEGIN;
SELECT * FROM t2
} {1 2}
do_catchsql_test 16.2 {
COMMIT;
} {1 {database is locked}}
do_execsql_test 16.3 {
INSERT INTO x1 VALUES('def');
}
do_execsql_test -db db2 16.4 {
END
}
do_execsql_test 16.5 {
COMMIT
}
do_execsql_test -db db2 16.6 {
SELECT * FROM x1
} {abc def}
finish_test
+4 -4
View File
@@ -185,7 +185,7 @@ static unsigned re_next_char(ReInput *p){
c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
p->i += 2;
if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
}else if( (c&0xf8)==0xf0 && p->i+3<p->mx && (p->z[p->i]&0xc0)==0x80
}else if( (c&0xf8)==0xf0 && p->i+2<p->mx && (p->z[p->i]&0xc0)==0x80
&& (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
| (p->z[p->i+2]&0x3f);
@@ -712,15 +712,15 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
** one or more matching characters, enter those matching characters into
** zInit[]. The re_match() routine can then search ahead in the input
** string looking for the initial match without having to run the whole
** regex engine over the string. Do not worry able trying to match
** regex engine over the string. Do not worry about trying to match
** unicode characters beyond plane 0 - those are very rare and this is
** just an optimization. */
if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
unsigned x = pRe->aArg[i];
if( x<=127 ){
if( x<=0x7f ){
pRe->zInit[j++] = (unsigned char)x;
}else if( x<=0xfff ){
}else if( x<=0x7ff ){
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else if( x<=0xffff ){
+43
View File
@@ -273,5 +273,48 @@ do_execsql_test 15.1 {
} {}
do_recover_test 15
#-------------------------------------------------------------------------
reset_db
if {[wal_is_capable]} {
do_execsql_test 16.1 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1), (2), (3);
} {wal}
do_test 16.2 {
set R [sqlite3_recover_init db main test.db2]
$R run
$R finish
} {}
do_execsql_test 16.3 {
SELECT * FROM t1;
} {1 2 3}
do_execsql_test 16.4 {
BEGIN;
SELECT * FROM t1;
} {1 2 3}
do_test 16.5 {
set R [sqlite3_recover_init db main test.db2]
$R run
list [catch { $R finish } msg] $msg
} {1 {cannot start a transaction within a transaction}}
do_execsql_test 16.6 {
SELECT * FROM t1;
} {1 2 3}
do_execsql_test 16.7 {
INSERT INTO t1 VALUES(4);
}
do_test 16.8 {
set R [sqlite3_recover_init db main test.db2]
$R run
list [catch { $R finish } msg] $msg
} {1 {cannot start a transaction within a transaction}}
do_execsql_test 16.9 {
SELECT * FROM t1;
COMMIT;
} {1 2 3 4}
}
finish_test
+5 -1
View File
@@ -2017,6 +2017,7 @@ static void recoverFinalCleanup(sqlite3_recover *p){
p->pTblList = 0;
sqlite3_finalize(p->pGetPage);
p->pGetPage = 0;
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
{
#ifndef NDEBUG
@@ -2315,6 +2316,7 @@ static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){
**
** + first freelist page (32-bits at offset 32)
** + size of freelist (32-bits at offset 36)
** + the wal-mode flags (16-bits at offset 18)
**
** We also try to preserve the auto-vacuum, incr-value, user-version
** and application-id fields - all 32 bit quantities at offsets
@@ -2378,7 +2380,8 @@ static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){
if( p->pPage1Cache ){
p->pPage1Disk = &p->pPage1Cache[nByte];
memcpy(p->pPage1Disk, aBuf, nByte);
aHdr[18] = a[18];
aHdr[19] = a[19];
recoverPutU32(&aHdr[28], dbsz);
recoverPutU32(&aHdr[56], enc);
recoverPutU16(&aHdr[105], pgsz-nReserve);
@@ -2574,6 +2577,7 @@ static void recoverStep(sqlite3_recover *p){
recoverOpenOutput(p);
/* Open transactions on both the input and output databases. */
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
recoverExec(p, p->dbIn, "BEGIN");
if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
+17 -1
View File
@@ -3327,6 +3327,22 @@ static int sessionChangesetNextOne(
if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE;
else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT;
}
/* If this is an UPDATE that is part of a changeset, then check that
** there are no fields in the old.* record that are not (a) PK fields,
** or (b) also present in the new.* record.
**
** Such records are technically corrupt, but the rebaser was at one
** point generating them. Under most circumstances this is benign, but
** can cause spurious SQLITE_RANGE errors when applying the changeset. */
if( p->bPatchset==0 && p->op==SQLITE_UPDATE){
for(i=0; i<p->nCol; i++){
if( p->abPK[i]==0 && p->apValue[i+p->nCol]==0 ){
sqlite3ValueFree(p->apValue[i]);
p->apValue[i] = 0;
}
}
}
}
return SQLITE_ROW;
@@ -5523,7 +5539,7 @@ static void sessionAppendPartialUpdate(
if( !pIter->abPK[i] && a1[0] ) bData = 1;
memcpy(pOut, a1, n1);
pOut += n1;
}else if( a2[0]!=0xFF ){
}else if( a2[0]!=0xFF && a1[0] ){
bData = 1;
memcpy(pOut, a2, n2);
pOut += n2;
+112
View File
@@ -98,6 +98,19 @@ int sql_exec_changeset(
}
/************************************************************************/
#ifdef SQLITE_DEBUG
static int sqlite3_test_changeset(int, void *, char **);
static void assert_changeset_is_ok(int n, void *p){
int rc = 0;
char *z = 0;
rc = sqlite3_test_changeset(n, p, &z);
assert( z==0 );
}
#else
# define assert_changeset_is_ok(n,p)
#endif
/*
** Tclcmd: sql_exec_changeset DB SQL
*/
@@ -127,6 +140,7 @@ static int SQLITE_TCLAPI test_sql_exec_changeset(
return TCL_ERROR;
}
assert_changeset_is_ok(nChangeset, pChangeset);
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pChangeset, nChangeset));
sqlite3_free(pChangeset);
return TCL_OK;
@@ -295,6 +309,7 @@ static int SQLITE_TCLAPI test_session_cmd(
}
}
if( rc==SQLITE_OK ){
assert_changeset_is_ok(o.n, o.p);
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(o.p, o.n));
}
sqlite3_free(o.p);
@@ -953,6 +968,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_invert(
if( rc!=SQLITE_OK ){
rc = test_session_error(interp, rc, 0);
}else{
assert_changeset_is_ok(sOut.n, sOut.p);
Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n));
}
sqlite3_free(sOut.p);
@@ -1001,6 +1017,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_concat(
if( rc!=SQLITE_OK ){
rc = test_session_error(interp, rc, 0);
}else{
assert_changeset_is_ok(sOut.n, sOut.p);
Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n));
}
sqlite3_free(sOut.p);
@@ -1236,6 +1253,7 @@ static int SQLITE_TCLAPI test_rebaser_cmd(
}
if( rc==SQLITE_OK ){
assert_changeset_is_ok(sOut.n, sOut.p);
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(sOut.p, sOut.n));
}
sqlite3_free(sOut.p);
@@ -1282,6 +1300,99 @@ static int SQLITE_TCLAPI test_sqlite3rebaser_create(
return TCL_OK;
}
/*
**
*/
static int sqlite3_test_changeset(
int nChangeset,
void *pChangeset,
char **pzErr
){
sqlite3_changeset_iter *pIter = 0;
char *zErr = 0;
int rc = SQLITE_OK;
int bPatch = (nChangeset>0 && ((char*)pChangeset)[0]=='P');
rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
if( rc==SQLITE_OK ){
int rc2;
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){
unsigned char *aPk = 0;
int nCol = 0;
int op = 0;
const char *zTab = 0;
sqlite3changeset_pk(pIter, &aPk, &nCol);
sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0);
if( op==SQLITE_UPDATE ){
int iCol;
for(iCol=0; iCol<nCol; iCol++){
sqlite3_value *pNew = 0;
sqlite3_value *pOld = 0;
sqlite3changeset_new(pIter, iCol, &pNew);
sqlite3changeset_old(pIter, iCol, &pOld);
if( aPk[iCol] ){
if( pOld==0 ) rc = SQLITE_ERROR;
}else if( bPatch ){
if( pOld ) rc = SQLITE_ERROR;
}else{
if( (pOld==0)!=(pNew==0) ) rc = SQLITE_ERROR;
}
if( rc!=SQLITE_OK ){
zErr = sqlite3_mprintf(
"unexpected SQLITE_UPDATE (bPatch=%d pk=%d pOld=%d pNew=%d)",
bPatch, (int)aPk[iCol], pOld!=0, pNew!=0
);
break;
}
}
}
}
rc2 = sqlite3changeset_finalize(pIter);
if( rc==SQLITE_OK ){
rc = rc2;
}
}
*pzErr = zErr;
return rc;
}
/*
** test_changeset CHANGESET
*/
static int SQLITE_TCLAPI test_changeset(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
void *pChangeset = 0; /* Buffer containing changeset */
int nChangeset = 0; /* Size of buffer aChangeset in bytes */
int rc = SQLITE_OK;
char *z = 0;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "CHANGESET");
return TCL_ERROR;
}
pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[1], &nChangeset);
Tcl_ResetResult(interp);
rc = sqlite3_test_changeset(nChangeset, pChangeset, &z);
if( rc!=SQLITE_OK ){
char *zErr = sqlite3_mprintf("(%d) - \"%s\"", rc, z);
Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
sqlite3_free(zErr);
}
sqlite3_free(z);
return rc ? TCL_ERROR : TCL_OK;
}
/*
** tclcmd: sqlite3rebaser_configure OP VALUE
*/
@@ -1337,6 +1448,7 @@ int TestSession_Init(Tcl_Interp *interp){
{ "sql_exec_changeset", test_sql_exec_changeset },
{ "sqlite3rebaser_create", test_sqlite3rebaser_create },
{ "sqlite3session_config", test_sqlite3session_config },
{ "test_changeset", test_changeset },
};
int i;
@@ -1,10 +1,7 @@
_fiddle_exec
_fiddle_interrupt
_fiddle_experiment
_fiddle_the_db
_fiddle_db_arg
_fiddle_db_filename
_fiddle_exec
_fiddle_experiment
_fiddle_interrupt
_fiddle_main
_fiddle_reset_db
_fiddle_db_handle
_fiddle_db_vfs
_fiddle_export_db
+3 -25
View File
@@ -1,4 +1,3 @@
_sqlite3_aggregate_context
_sqlite3_bind_blob
_sqlite3_bind_double
_sqlite3_bind_int
@@ -23,14 +22,10 @@ _sqlite3_column_text
_sqlite3_column_type
_sqlite3_compileoption_get
_sqlite3_compileoption_used
_sqlite3_create_function
_sqlite3_create_function_v2
_sqlite3_create_window_function
_sqlite3_data_count
_sqlite3_db_filename
_sqlite3_db_handle
_sqlite3_db_name
_sqlite3_deserialize
_sqlite3_errmsg
_sqlite3_error_offset
_sqlite3_errstr
@@ -38,22 +33,15 @@ _sqlite3_exec
_sqlite3_expanded_sql
_sqlite3_extended_errcode
_sqlite3_extended_result_codes
_sqlite3_file_control
_sqlite3_finalize
_sqlite3_free
_sqlite3_initialize
_sqlite3_interrupt
_sqlite3_libversion
_sqlite3_libversion_number
_sqlite3_malloc
_sqlite3_malloc64
_sqlite3_msize
_sqlite3_open
_sqlite3_open_v2
_sqlite3_prepare_v2
_sqlite3_prepare_v3
_sqlite3_randomness
_sqlite3_realloc
_sqlite3_realloc64
_sqlite3_reset
_sqlite3_result_blob
_sqlite3_result_double
@@ -62,11 +50,8 @@ _sqlite3_result_error_code
_sqlite3_result_error_nomem
_sqlite3_result_error_toobig
_sqlite3_result_int
_sqlite3_result_int64
_sqlite3_result_null
_sqlite3_result_text
_sqlite3_serialize
_sqlite3_shutdown
_sqlite3_sourceid
_sqlite3_sql
_sqlite3_step
@@ -74,21 +59,14 @@ _sqlite3_strglob
_sqlite3_strlike
_sqlite3_total_changes
_sqlite3_total_changes64
_sqlite3_trace_v2
_sqlite3_uri_boolean
_sqlite3_uri_int64
_sqlite3_uri_key
_sqlite3_uri_parameter
_sqlite3_user_data
_sqlite3_value_blob
_sqlite3_value_bytes
_sqlite3_value_double
_sqlite3_value_int
_sqlite3_value_int64
_sqlite3_value_text
_sqlite3_value_type
_sqlite3_vfs_find
_sqlite3_vfs_register
_sqlite3_vfs_unregister
_sqlite3_wasm_db_error
_sqlite3_wasm_enum_json
_malloc
_free
@@ -273,6 +273,11 @@
</fieldset>
</div>
</div> <!-- #view-split -->
<!-- Maintenance notes:
... TODO... currently being refactored...
-->
<script src="fiddle.js"></script>
</body>
</html>
+2
View File
@@ -345,6 +345,7 @@ TESTSRC = \
$(TOP)/src/test_quota.c \
$(TOP)/src/test_rtree.c \
$(TOP)/src/test_schema.c \
$(TOP)/src/test_schemapool.c \
$(TOP)/src/test_server.c \
$(TOP)/src/test_sqllog.c \
$(TOP)/src/test_superlock.c \
@@ -404,6 +405,7 @@ TESTSRC2 = \
$(TOP)/src/backup.c \
$(TOP)/src/btree.c \
$(TOP)/src/build.c \
$(TOP)/src/callback.c \
$(TOP)/src/date.c \
$(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
+76 -66
View File
@@ -1,13 +1,13 @@
C Version\s3.40.0
D 2022-11-16T12:10:08.388
C Merge\sthe\s3.40.1\schanges\sinto\sthe\sreuse-schema\sbranch.
D 2022-12-28T14:55:11.917
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 78e4c4916f2c3993a8a454018745ff02094a8029d449d0c22db98f1cf8260420
F Makefile.in 8274fec98db5e2e54c5a05ba7854039fe02e09ad30fa7a21505784b5910e12ba
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
F Makefile.msc e7a564ceec71f0d9666031d5638cf0d4f88b050b44e8df5d32125137cd259ac0
F Makefile.msc 4312ecc6629df35ed862c2082a3655dbda57a1e8f72b0b0fb9fed9e494cd9f7b
F README.md 8b8df9ca852aeac4864eb1e400002633ee6db84065bd01b78c33817f97d31f5e
F VERSION 8868ddfa6e1eee218286021a94b3e22d13e550c76c72d878857547ca001de24a
F VERSION abec048a7ac74ad5559a336fe048d624207ac1e21be7be4356f3fa6b1ad4bec8
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -33,13 +33,14 @@ F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea0034
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure b93755fe94b3e9b2015f3c2d6c63928e8899b0a7c54e042deb843498094179da x
F configure 291769d08ff3a3091f420ccf7d2e1010153f778d6372217d4cc6fcbd2d14bb2d x
F configure.ac 48dc6bfee293eef05910faf085760f2fd79b680aa47b50e8e6a22ca40bb026bb
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/shared_schema.md 759fc374709fccf4e5d2d0cbd05f8fedd38fb022bdd8a6c5b5f492684c7023b9
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
@@ -119,7 +120,7 @@ F ext/fts5/fts5_config.c 501e7d3566bc92766b0e11c0109a7c5a6146bc41144195459af5422
F ext/fts5/fts5_expr.c 40174a64829d30cc86e8266306ad24980f6911edd5ca0b8c1ce7821ea1341b88
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
F ext/fts5/fts5_index.c a8ee270724ae1f958d0ce9897bcd60a5b760ecbeaa058fc8632805a283f1c20a
F ext/fts5/fts5_main.c 6078ae86d3b813753a4f1201054550aff21a3f660e97b30f200d2b1472874151
F ext/fts5/fts5_main.c 2bf44b9efdecc7fd936f320064666235b91bba8a6c4f3dc6e2d7eae6662570ed
F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
@@ -194,7 +195,7 @@ F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc27826807405
F ext/fts5/test/fts5matchinfo.test 10c9a6f7fe61fb132299c4183c012770b10c4d5c2f2edb6df0b6607f683d737a
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
F ext/fts5/test/fts5misc.test 4d7d20372242cc618688de029b87d897d09fa1640302c254abee63cf3ffa2c10
F ext/fts5/test/fts5misc.test d6d4fdd7ec164e69e50af539137c0565362a4124547bf841ba474f092298637b
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
@@ -316,7 +317,7 @@ F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d
F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691
F ext/misc/prefixes.c 0f4f8cff5aebc00a7e3ac4021fd59cfe1a8e17c800ceaf592859ecb9cbc38196
F ext/misc/qpvtab.c 09738419e25f603a35c0ac8bd0a04daab794f48d08a9bc07a6085b9057b99009
F ext/misc/regexp.c 5abed0ace2d9340b42b9ab1dbe64db9c276e4e8eba38a903232b6253e05ccdaf
F ext/misc/regexp.c 064838f7b31e90d312cce089cfafbb992034e75d359009c48886ca06c0a794b2
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
@@ -387,7 +388,7 @@ F ext/rbu/sqlite3rbu.c c4ba7901b2d3e0c7845f30840e3ffb35c6f999d6da0d80f121866491f
F ext/rbu/sqlite3rbu.h 02d981e2d39c151391759e1a400e29c7388730812957ac3db8dad7f6c9f9cfc8
F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
F ext/recover/dbdata.c 8f1f75d636431de69d7977ec50fc41bfdd0c48c510d5ee7eae0cbd4164e1429a
F ext/recover/recover1.test 02004eb8f9ec2825ba77e24742c18e45162cb21d27e76a3a435b83a759a1131a
F ext/recover/recover1.test 6a12f73330a2ca4d1428730c09272e294c5082c2806ae9e56db846374e03090d
F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e
F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49
@@ -399,7 +400,7 @@ F ext/recover/recoverpgsz.test 3658ab8e68475b1bb87d6af88baa04551c84b73280a566a1b
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
F ext/recover/sqlite3recover.c 1e4de9cd30daa67e5c1cd0cafb764ddf183087ce037ab47b7c1a7e2921c90d37
F ext/recover/sqlite3recover.c 6d37a422c8917b793548a7b2c6e7ff8e1af15ba5453eef37bb69331828b73186
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c 1a34e2d04533d919a30ae4d5caeb1643f6684e9ccd7597ca27721d8af81f4ade
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -481,17 +482,17 @@ F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2
F ext/session/sessionsize.test 6f644aff31c7f1e4871e9ff3542766e18da68fc7e587b83a347ea9820a002dd8
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3session.c 1d019c5caf51936ef24c761db63552b06e0e0d951c8740bba9639b17fa0cb107
F ext/session/sqlite3session.c b4254dd6e785cdd206c9ca7118796cf82273627fe2d4fd647597f08c2f821f96
F ext/session/sqlite3session.h 0907de79bc13a2e3af30a6dc29acc60792a3eaf7d33d44cf52500d0f3c2b2171
F ext/session/test_session.c f433f68a8a8c64b0f5bc74dc725078f12483301ad4ae8375205eef790274a787
F ext/session/test_session.c 6aa7e97407987e81431b26730889db4719efebebbb6fe7502802d19d58b35798
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
F ext/wasm/GNUmakefile 3aa8c160705ab9d9d4d552a1f4e630925a65a27df216befe2e9a956904434c1d
F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20
F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 9120c2f8f51fa85f46dcf4dcb6b12f4a807d428f6089b99cdb08d8ddfcfd88b2
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api c5eaceabb9e759aaae7d3101a4a3e542f96ab2c99d89a80ce20ec18c23115f33
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md 1350088aee90e959ad9a94fab1bb6bcb5e99d4d27f976db389050f54f2640c78
F ext/wasm/api/extern-post-js.js f3dc4219a2a1f183d98452dcbd55a0c5351b759eccca75480a92473974d8b047
@@ -530,8 +531,8 @@ F ext/wasm/dist.make 481289899a07958439d07ee4302ff86235fa0fbb72f17ea05db2be90a94
F ext/wasm/fiddle.make e570ec1bfc7d803507a2e514fe32f673fe001b2114b85c73c3964a462ba8bcfc
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/fiddle/fiddle-worker.js b4a0c8ab6c0983218543ca771c45f6075449f63a1dcf290ae5a681b2cba8800d
F ext/wasm/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/index-dist.html cb0da16cba0f21cda2c25724c5869102d48eb0af04446acd3cd0ca031f80ed19
F ext/wasm/index.html ce6a68a75532b47e3c0adb83381a06d15de8c0ac0331fb7bf31d33f8e7c77dc4
F ext/wasm/jaccwabyt/jaccwabyt.js 95f573de1826474c9605dda620ee622fcb1673ae74f191eb324c0853aa4dcb66
@@ -556,7 +557,7 @@ F ext/wasm/wasmfs.make edfd60691d10fd19ada4c061280fd7fbe4cf5f6bf6b913268e8ebedfc
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk fd90f1bd90bd4070c9af7e9c8396bd0cf4208a0186c8d18fa6e2609dff447d5d
F main.mk b8ead9822424a704faf2498e6351d5e29690db1e05c0c776d22231983e4204ec
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -569,20 +570,20 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
F src/alter.c 0390ca1d69ec3626cfa9f153114b7ab233e6b2bada6a9eb91361ed385fe90deb
F src/analyze.c d2fce73f6a024897593012c6ca25368629fa4aeb49960d88a52fac664582e483
F src/attach.c 4431f82f0247bf3aaf91589acafdff77d1882235c95407b36da1585c765fbbc8
F src/alter.c 23f95fd33885c27edb5ece2bec9c184d3c7e575a3de60a97c036aa9d225e06f4
F src/analyze.c e242f6ad429477397bbf104a5c26a5682e7a70c1114673e7d5280c5bca3fcf0a
F src/attach.c e1eb237a21422b2d637fd854e1b72609b1b589e24b4b3a5cac0e13c9ef20ee8d
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca
F src/btree.c 6321ff29261bf9726e6b231058ff21b1ccf9f441a0b718b76c37341b16fa14ce
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btree.c 0d2aa1331a63eefc054faa8701cfe3ba1cbe27540cb02f65c61b0605bf6b5004
F src/btree.h edfb08230b6fd6b0a165ba82defd3471b0e71d577d0c66807d4994d4aade4332
F src/btreeInt.h 8ce1332edd89dfd2461d561ac10a0ab5601c8e06200cb5230596c3caaf54482e
F src/build.c d3e43e950e4e377c1d451a4862556792acdef1faba14a03f899d30d09731c48b
F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484a
F src/build.c e8804b9fdb873949f9bceda5e9e8c70fb6961c620534b11d4f1cc51e8e2eb404
F src/callback.c bd46ff3b1c6a241a24d80d3ffb695a63dc71eb73c8b76a3bd29b3668fa1ccb86
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
F src/ctime.c 7dd467e9116985022644f4120c812ea397fbfea67c728c892830d45bab7cee76
F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5
F src/dbpage.c f1a87f4ebcf22284e0aaf0697862f4ccfc120dcd6db3d8dfa3b049b2580c01d8
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
@@ -599,15 +600,15 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 90a32bc7faa755cd5292ade21d2b3c6edba8fd1d70754a364caccabfde2c3bb2
F src/json.c 7749b98c62f691697c7ee536b570c744c0583cab4a89200fdd0fc2aa8cc8cbd6
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 8086232d10e51e183a7f64199815bad1c579896354db69435347665f62f481e9
F src/main.c fa53bb2ae09549dab5629271c3cfd681f89059f5192afaaaf5c0d396bb3957fe
F src/loadext.c 25663175950c5c4404b9377840b7b4c6fe5c53b415caf43634c62f442c02a9a7
F src/main.c 2d8ff38a1516b2d0d7c3cf0c4bc1236c818bcaca022c3f8a68d3669ac3206a72
F src/malloc.c dfddca1e163496c0a10250cedeafaf56dff47673e0f15888fb0925340a8e3f90
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c 5a3dbd8ac8a6501152a4fc1fcae9b0900c2d7eb0589c4ec7456fdde15725a26c
F src/memdb.c c2dc88f97c410eb68a24468344b65526685e18354ddfd15906750c1eaf9dc2dd
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
F src/memdb.c 559c42e61eb70cd6d4bc692b042497133c6d96c09a3d514d92f3dac72268e223
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
@@ -621,7 +622,7 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_kv.c 0e59600d25b72034c7666b8b7dcc527f039b5d9c16f24a7eca4c08c66f63c364
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c 287aa5f5691a2b356780c63e83abaa33549add84227b8313395f04088486d79c
F src/os_unix.c c710dfac1b86a87c82053fa397ae31628217a8a86630904c5496ce649e5ada2b
F src/os_win.c 295fe45f18bd86f2477f4cd79f3377c6f883ceb941b1f46808665c73747f2345
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 6176d9752eb580419e8fef4592dc417a6b00ddfd43ee22f818819bf8840ceee8
@@ -630,23 +631,23 @@ F src/parse.y 8e67d820030d2655b9942ffe61c1e7e6b96cea2f2f72183533299393907d0564
F src/pcache.c f4268f7f73c6a3db12ce22fd25bc68dc42315d19599414ab1207d7cf32f79197
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc
F src/pragma.c 894c2621d35edd4beea9b331cfdb1b42032394420074d2294c8febe548eea8a1
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 1b02be0441eda4579471fea097f678effcbb77ef0c39ab3f703c837822bcd674
F src/pragma.c 6e211923bc179edcebcceeaba003d554db232bd72f75457a9a1e27205e9c979b
F src/pragma.h 50f6d3b408ed56bde4f4e4aead8c0b2022030b692e8de237c1b7a0b5ce87a0c8
F src/prepare.c 740e262cc0e011ac4f6f02b8a51b3da6f51d7c0760423d5a72e80c4bc536bc70
F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c 9886d6669f5787471aab6ae52af76fad90b53edb1c218fc9ed9d953363bc5184
F src/shell.c.in 458cb3de9d548342fc645b699620b1af3de770d2ceec09ac71f86c19bd244064
F src/sqlite.h.in bdb10b78166f5b735318667eb16c84ac90d9e0de88cc25c193eeb4379a126945
F src/shell.c.in cfb43ca148856b3ba8e74cee301b5ddd4fad0b69d778f906cd83b3c03a267264
F src/sqlite.h.in a9998f4cdffd9738ec54bb7e11c108bf98c306b411708ca9dff9dd107eaad8b7
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h c4b9fa7a7e2bcdf850cfeb4b8a91d5ec47b7a00033bc996fd2ee96cbf2741f5f
F src/sqliteInt.h 2c24ba38f78e32fe5d7ec136321a6ad827698b33ca98664970a8b7274d69ef7c
F src/sqliteInt.h 583cf2d0982dda1b0fc8fbf291890bbe8b7f2abf2b50983e91fa796cd04e0a8c
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/status.c 501433a8bdf64be125746a53bb9180761f9364428b59b318365eb88afd6d5cea
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 4e64ba300a5a26e0f1170e09032429faeb65e45e8f3d1a7833e8edb69fc2979e
F src/tclsqlite.c c5b9f6540d6de1adc6554589ce4011e07bb02250440a3e777ff86b40f1c1dd2c
F src/test1.c 40c9a40975512985762f87b83d0c63e4904833a9fe78cbcca664a37095301b1d
F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
@@ -662,7 +663,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 8294d8223b7f18a3ddb7f9a0e30815dcca4e61681f78b538c870f7d934f88b81
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 8264637b06a3c1f0727c88d1ea32dcf7986b9e7e358a970cae87cdac8a5b2708
F src/test_config.c 73ebdc35580900d12c20b984db9ec1abe860dc75f66ae703f2b6fc9d95e09dc1
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 7cc7623d1025d1e92c51da20fd25060759733b7a356a121545a3b7d2faa8a0f1
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
@@ -686,11 +687,12 @@ F src/test_quota.c 6cb9297115b551f433a9ad1741817a9831abed99
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b
F src/test_schema.c f5d6067dfc2f2845c4dd56df63e66ee826fb23877855c785f75cc2ca83fd0c1b
F src/test_schemapool.c ae21a79f9bc7e9099ae78dbd46d5c28ee75330e62e3256a9fde25564ff9df492
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a
F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
F src/test_tclsh.c 7dd98be675a1dc0d1fd302b8247bab992c909db384df054381a2279ad76f9b0e
F src/test_tclsh.c 88b764a4353ebea5526ce861214f627011e2aa9efd6c4512e09d3c36f74d3be4
F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
F src/test_thread.c 269ea9e1fa5828dba550eb26f619aa18aedbc29fd92f8a5f6b93521fbb74a61c
F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43
@@ -703,28 +705,28 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 1305797eab3542a0896b552c6e7669c972c1468e11e92b370533c1f37a37082b
F src/treeview.c 07787f67cd297a6d09d04b8d70c06769c60c9c1d9080378f93929c16f8fd3298
F src/trigger.c 4163ada044af89d51caba1cb713a73165347b2ec05fe84a283737c134d61fcd5
F src/trigger.c fa2fe8aa8dab6465bb1f3ba6ea5d7ee1361b8415437779db79bd41244bc1e3b9
F src/update.c 5b0302c47cf31b533d5dff04c497ca1d8b9d89c39727e633fbe7b882fd5ac5aa
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 0be191521ff6d2805995f4910f0b6231b42843678b2efdc1abecaf39929a673f
F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd
F src/vdbe.c 0c7cb1b934ad8611e14e7efaf2c3a95df7dd3f7964d63ea07fef42a23df86131
F src/vdbe.h 58675f47dcf3105bab182c3ad3726efd60ffd003e954386904ac9107d0d2b743
F src/vacuum.c 4c46040e481b32cc4f24946fd5509396bd9492ecf4c1455034b03eed8533c971
F src/vdbe.c 0cae5da94722e8fa1bc0692e0557adcaf5c7562c1f6726b9e54ac109c9c47c33
F src/vdbe.h 930a4b944dc21053d8d57943b21b4a6186dd3741bdd48b46b42bef5ad743202e
F src/vdbeInt.h 17b7461ffcf9ee760d1341731715a419f6b8c763089a7ece25c2e8098d702b3f
F src/vdbeapi.c 1e8713d0b653acb43cd1bdf579c40e005c4844ea90f414f065946a83db3c27fb
F src/vdbeaux.c 87684b89877eae0c58c78b340bb5356aa1c8fb1dd650b29410c8b745aeeb20b5
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
F src/vdbeaux.c 5b1ebb38c438dcaf80b5fd8255d9c540fcda227cff333d890f5e985bafb77f8c
F src/vdbeblob.c aa23a326ff86bdde8f7ba74cf23c3e1795b13bee749314feaf26273be2f63e89
F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c b2f993aa954078985bc40317bb2140fe0880a08a7440f3a428b60fce74636808
F src/vtab.c d25ed4bd90e8a6ab71df8887667109069349e04f808170311991b93ee3bb0e7b
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c 1ef5aae7fac877057b9f360f06b26d4275888460d8fb6e92bbb9e70e07afe946
F src/where.c 42f0433beedec9ba0ac0945732e1a8c10b5081f1e82caf4507ac493d79f552af
F src/whereInt.h df0c79388c0b71b4a91f480d02791679fe0345d40410435c541c8893e95a4d3f
F src/wherecode.c 133a94f82858787217d073143617df19e4a6a7d0b771a1519f957608109ad5a5
F src/whereexpr.c 05295b44b54eea76d1ba766f0908928d0e20e990c249344c9521454d3d09c7ae
@@ -1411,14 +1413,21 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/recover.test fd5199f928757cb308661b5fdca1abc19398a798ff7f24b57c3071e9f8e0471e
F test/regexp1.test 83c631617357150f8054ca1d1fed40a552b0d0f8eb7a7f090c3be02cee9f9913
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
F test/releasetest_data.tcl 0db8aee0c348090fd06da47020ab4ed8ec692e0723427b2f3947d4dfb806f3b0
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/returning1.test c43b8370a351f77aec6d71f4a2cde59b849369ed1933261a2c2c69e23e34ff5e
F test/returning1.test 1366e04566cfe1a082d17b1e0f195ec64473c79374b3a5d4ae00c43d885dea31
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
F test/reuse1.test faa2ce5ff566d936b8a10d9e22ba2ee66a54ce89fdcf8aef561df6b15b0ff3d3
F test/reuse2.test 5dd9c98579358f0d5a90d25e36dd6e678a03e23446b6c7f2630a8da22ae7ca94
F test/reuse3.test 876d15c42d61b1f6ab718cd8169912514ad314d7fe1cd9788080aa62168ba0d1
F test/reuse4.test adaad66253aea6cc748674328abe69b650c5c78b8676ed1162d3de09742519f9
F test/reuse5.test bbe6cf7384ef90f134392edd93d626385ef0bf6f40eefc3d993535cd0861d83b
F test/reuse6.test f4674f9967aee2a0b49c02832120b8b495291c0d87aae084c54e6c0cc18132fe
F test/reusefault.test ef646a0fb51d50ddfb4b7cd872f88e7d36eaba64bde7797b3418c3774e1c8d14
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
@@ -1491,7 +1500,7 @@ F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test e4b4de56f454708e0747b52915135baa2cbfec4965406d6eaf02a4a5c22a9880
F test/shell2.test c536c2aab4852608f8a606262330797abc4d964a4c2c782a7760f54ea1f17a6a
F test/shell2.test 1190b951373fdfe719bc6ac16962bc743dfa4355db8ae546c0bb9bf559a28d4a
F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
F test/shell4.test 7dc8a515705bc093d8ffe381670e8fa7a969661e8ed177c35c847e3c6dfc35e2
F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
@@ -1567,7 +1576,7 @@ F test/tabfunc01.test 241425ce3998687ab24adba09cb95e8012e17499b84a0ed47e128ab45e
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test ad0bbd92edabe64cc91d990a0748142fe5ab962d74ac71fa3bfa94d50d2f4c87
F test/tclsqlite.test 350536a4233914aa437b6735e3e8e683e921a71ced8fa9fb5396057a04dbea33
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
@@ -1587,7 +1596,7 @@ F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
F test/threadtest3.c 655bff6c0895ec03f014126aa65e808fac9aae8c5a7a7da58a510cbe8b43b781
F test/threadtest3.c 25cb92accb4fa6d53e708d6006ed2db7a7533ef7b838ef1306455c6fe57e978a
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
F test/threadtest5.c 9b4d782c58d8915d7e955ff8051f3d03628bda0d33b82971ea8c0f2f2808c421
F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
@@ -1761,12 +1770,13 @@ F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123
F test/triggerG.test 2b816093c91ba73c733cfa8aedcc210ad819d72a98b1da30768a3c56505233e9
F test/triggerupfrom.test d1f9e56090408115c522bee626cc33a2f3370f627a5e341d832589d72e3aa271
F test/trustschema1.test 4e970aef0bfe0cee139703cc7209d0e0f07725d999b180ba50770f49edef1494
F test/tt3_checkpoint.c ac7ca661d739280c89d9c253897df64a59a49369bd1247207ac0f655b622579d
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
F test/tt3_checkpoint.c 69214e2ce81bbbd3c1b82c31e103607fd2e6790818aef4792957fc9cc88d067e
F test/tt3_index.c 95592839426dc85ce5a7a57b41be2cbf3c2ec3457b9cd841a06ed5877f712c7c
F test/tt3_lookaside1.c 2ddd99bfffeef288f0786827ef68f912f6f47ce3d3184e62f05808d8e13b920e
F test/tt3_reuseschema.c 4d52e141f89f009028d8ab0bd1f0697d0edffa94bafc1fff0f7ad4d9d9baa549
F test/tt3_shared.c b37d22defc944a2ac4c91c927fd06c1d48cd51e2ce9d004fe868625bd2399f93
F test/tt3_stress.c f9a769ca8b026ecc76ee93ca8c9700a5619f8e51c581107c4053ba6ac97f616f
F test/tt3_vacuum.c 71b254cde1fc49d6c8c44efd54f4668f3e57d7b3a8f4601ade069f75a999ba39
F test/tt3_stress.c 077e817ac1168443b075fedb44e92db84bb4dc5bd3b6fe1aba25c94ac280b231
F test/tt3_vacuum.c 727bfda1299b18435eeba80dee8e6ff43462146d7c1e2096cc809f01db568391
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
@@ -1874,7 +1884,7 @@ F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2a
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
F test/wapptest.tcl 1bea58a6a8e68a73f542ee4fca28b771b84ed803bd0c9e385087070b3d747b3c x
F test/where.test d13cd7c24e80009d2b54e2f7a8893c457afa49c64f99359c9eb3fe668ba1d9d4
F test/where.test c033c4c156e463fe1074a56dc914dfaa91de82b0dcf8a02f5fbc67cebecfdd17
F test/where2.test 03c21a11e7b90e2845fc3c8b4002fc44cc2797fa74c86ee47d70bd7ea4f29ed6
F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67753
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
@@ -1986,7 +1996,7 @@ F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a89
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
F tool/mkopcodeh.tcl bcb2bd5affb545fd219ef0304c7978e2a356407ab723f45ec8569235892c1c3f
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl bd07bd59d45d0f3448e123d6937e9811195f9908a51e09d774609883055bfd3d
F tool/mkpragmatab.tcl 0e059aaab521b490c86ba3d4f945319b438558de7738e90f26c54f4ffcdd79bb
F tool/mkshellc.tcl 02d0de8349ef830c0fb20d29680320bde2466e2ec422e5bd94c4317a7a7e8cc9
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -2055,11 +2065,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 6ee57a2e4e3399481100c40da0229d2d33cbe3290016185c8a60839d14b209f6
R 05517d79d8355d06966e47ba4dd15a19
T +sym-major-release *
T +sym-release *
T +sym-version-3.40.0 *
P 2aec00a7294762b3f7e8138ea1686eda4a1b02e940ec39f261651b61b87fabad df5c253c0b3dd24916e4ec7cf77d3db5294cc9fd45ae7b9c5e82ad8197f38a24
R f5fd91e7344b82fd5e7d9b76d6810b75
T *branch * reuse-schema-3.40
T *sym-reuse-schema-3.40 *
T -sym-reuse-schema *
U drh
Z ec924bc422a55f57f049fa2ef8df3b06
Z f7ac59f1ac3b1ecdf3afa998fa4164d7
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
89c459e766ea7e9165d0beeb124708b955a4950d0f4792f457465d71b158d318
126c68bd15dd7d26af7a584f28fc4ff82c591154aa6828e0021815e46e7f2809
+2 -2
View File
@@ -112,8 +112,8 @@ static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){
Vdbe *v = pParse->pVdbe;
if( v ){
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5);
if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5);
sqlite3VdbeAddParseSchemaOp(pParse, iDb, 0, p5);
if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse, 1, 0, p5);
}
}
+1
View File
@@ -212,6 +212,7 @@ static void openStatTable(
** side-effect of the CREATE TABLE statement is to leave the rootpage
** of the new table in register pParse->regRoot. This is important
** because the OpenWrite opcode below will be needing it. */
sqlite3SchemaWritable(pParse, iDb);
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
);
+5 -4
View File
@@ -205,14 +205,14 @@ static void attachFunc(
** way we found it.
*/
if( rc==SQLITE_OK ){
sqlite3BtreeEnterAll(db);
db->init.iDb = 0;
db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
if( !REOPEN_AS_MEMDB(db) ){
if( !IsSharedSchema(db) && !REOPEN_AS_MEMDB(db) ){
sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrDyn);
sqlite3BtreeLeaveAll(db);
assert( zErrDyn==0 || rc!=SQLITE_OK );
}
sqlite3BtreeLeaveAll(db);
assert( zErrDyn==0 || rc!=SQLITE_OK );
}
#ifdef SQLITE_USER_AUTHENTICATION
if( rc==SQLITE_OK && !REOPEN_AS_MEMDB(db) ){
@@ -312,6 +312,7 @@ static void detachFunc(
pEntry = sqliteHashNext(pEntry);
}
(void)sqlite3SchemaDisconnect(db, i, 0);
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
pDb->pSchema = 0;
+11
View File
@@ -11072,6 +11072,17 @@ int sqlite3BtreeIsReadonly(Btree *p){
*/
int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
/*
** If no transaction is active and the database is not a temp-db, clear
** the in-memory pager cache.
*/
void sqlite3BtreeClearCache(Btree *p){
BtShared *pBt = p->pBt;
if( pBt->inTransaction==TRANS_NONE ){
sqlite3PagerClearCache(pBt->pPager);
}
}
#if !defined(SQLITE_OMIT_SHARED_CACHE)
/*
** Return true if the Btree passed as the only argument is sharable.
+2
View File
@@ -368,6 +368,8 @@ void sqlite3BtreeCursorList(Btree*);
int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
void sqlite3BtreeClearCache(Btree*);
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
+89 -61
View File
@@ -340,6 +340,39 @@ int sqlite3UserAuthTable(const char *zTable){
}
#endif
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** If this database connection was opened with the SQLITE_OPEN_SHARED_SCHEMA
** flag specified, then ensure that the database schema for database iDb
** is loaded. Either by obtaining a Schema object from the schema-pool, or
** by reading the contents of the sqlite_master table. Unless it is NULL,
** the location indicated by parameter pbUnload is set to 1 if a shared-schema
** is loaded.
**
** If the database handle was not opened with SQLITE_OPEN_SHARED_SCHEMA, or
** if the schema for database iDb is already loaded, this function is a no-op.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise. If
** an error code is returned, (*pzErr) may be set to point to a buffer
** containing an error message. It is the responsibility of the caller to
** eventually free this buffer using sqlite3_free().
*/
int sqlite3SchemaLoad(sqlite3 *db, int iDb, int *pbUnload, char **pzErr){
int rc = SQLITE_OK;
if( IsSharedSchema(db)
&& DbHasProperty(db, iDb, DB_SchemaLoaded)==0
&& (db->init.busy==0 || (iDb!=1 && db->init.iDb==1))
){
struct sqlite3InitInfo sv = db->init;
memset(&db->init, 0, sizeof(struct sqlite3InitInfo));
rc = sqlite3InitOne(db, iDb, pzErr, 0);
db->init = sv;
if( pbUnload && rc==SQLITE_OK && iDb!=1 ) *pbUnload = 1;
}
return rc;
}
#endif
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
@@ -365,59 +398,41 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
return 0;
}
#endif
if( zDatabase ){
for(i=0; i<db->nDb; i++){
if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
}
if( i>=db->nDb ){
/* No match against the official names. But always match "main"
** to schema 0 as a legacy fallback. */
if( sqlite3StrICmp(zDatabase,"main")==0 ){
i = 0;
}else{
return 0;
}
}
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( i==1 ){
if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0
|| sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0
|| sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0
){
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
LEGACY_TEMP_SCHEMA_TABLE);
while(1){
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDatabase==0 || sqlite3DbIsNamed(db, j, zDatabase) ){
int bUnload = 0;
assert( sqlite3SchemaMutexHeld(db, j, 0) );
if( IsSharedSchema(db) ){
Parse *pParse = db->pParse;
if( pParse && pParse->nErr==0 ){
pParse->rc = sqlite3SchemaLoad(db, j, &bUnload, &pParse->zErrMsg);
if( pParse->rc ) pParse->nErr++;
}
}
}else{
if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash,
LEGACY_SCHEMA_TABLE);
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
if( p ) return p;
if( bUnload ){
sqlite3SchemaRelease(db, j);
}
}
}
}else{
/* Match against TEMP first */
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
if( p ) return p;
/* The main database is second */
p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
if( p ) return p;
/* Attached databases are in order of attachment */
for(i=2; i<db->nDb; i++){
assert( sqlite3SchemaMutexHeld(db, i, 0) );
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
if( p ) break;
/* Not found. If the name we were looking for was temp.sqlite_master
** then change the name to sqlite_temp_master and try again. */
if( sqlite3StrICmp(zName, PREFERRED_SCHEMA_TABLE)==0 ){
zName = LEGACY_SCHEMA_TABLE;
continue;
}
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, LEGACY_SCHEMA_TABLE);
}else if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
LEGACY_TEMP_SCHEMA_TABLE);
}
if( sqlite3StrICmp(zName, PREFERRED_TEMP_SCHEMA_TABLE)==0 ){
zName = LEGACY_TEMP_SCHEMA_TABLE;
continue;
}
if( sqlite3StrICmp(zName, LEGACY_SCHEMA_TABLE)!=0 ) break;
if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
zName = LEGACY_TEMP_SCHEMA_TABLE;
}
return p;
return 0;
}
/*
@@ -442,6 +457,7 @@ Table *sqlite3LocateTable(
/* Read the database schema. If an error occurs, leave an error message
** and code in pParse and return NULL. */
if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0
&& !IsSharedSchema(db)
&& SQLITE_OK!=sqlite3ReadSchema(pParse)
){
return 0;
@@ -458,9 +474,21 @@ Table *sqlite3LocateTable(
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
testcase( pMod->pEpoTab==0 );
return pMod->pEpoTab;
if( pMod ){
if( IsSharedSchema(db) && pParse->nErr==0 ){
int bDummy = 0;
pParse->rc = sqlite3SchemaLoad(db, 0, &bDummy, &pParse->zErrMsg);
if( pParse->rc ) pParse->nErr++;
(void)bDummy;
}
if( sqlite3VtabEponymousTableInit(pParse, pMod) ){
Table *pEpoTab = pMod->pEpoTab;
if( pEpoTab ){
assert( IsSharedSchema(db)||pEpoTab->pSchema==db->aDb[0].pSchema );
pEpoTab->pSchema = db->aDb[0].pSchema; /* For SHARED_SCHEMA mode */
}
return pEpoTab;
}
}
}
#endif
@@ -470,15 +498,13 @@ Table *sqlite3LocateTable(
p = 0;
}
if( p==0 ){
if( p==0 && (!IsSharedSchema(db) || pParse->nErr==0) ){
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
if( zDbase ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
}else{
assert( HasRowid(p) || p->iPKey<0 );
}
return p;
@@ -647,11 +673,10 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
DbSetProperty(db, 1, DB_ResetWanted);
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
}
if( db->nSchemaLock==0 ){
for(i=0; i<db->nDb; i++){
if( DbHasProperty(db, i, DB_ResetWanted) ){
sqlite3SchemaClear(db->aDb[i].pSchema);
sqlite3SchemaClearOrDisconnect(db, i);
}
}
}
@@ -664,16 +689,17 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
int i;
sqlite3BtreeEnterAll(db);
for(i=0; i<db->nDb; i++){
for(i=0; i<db->nDb; i=(i?i+1:2)){
Db *pDb = &db->aDb[i];
if( pDb->pSchema ){
if( db->nSchemaLock==0 ){
sqlite3SchemaClear(pDb->pSchema);
sqlite3SchemaClearOrDisconnect(db, i);
}else{
DbSetProperty(db, i, DB_ResetWanted);
}
}
}
sqlite3SchemaClear(db->aDb[1].pSchema);
db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk);
sqlite3VtabUnlockList(db);
sqlite3BtreeLeaveAll(db);
@@ -1281,7 +1307,7 @@ void sqlite3StartTable(
*/
if( !IN_SPECIAL_PARSE ){
char *zDb = db->aDb[iDb].zDbSName;
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
if( !IsSharedSchema(db) && SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto begin_table_error;
}
pTable = sqlite3FindTable(db, zName, zDb);
@@ -2907,7 +2933,7 @@ void sqlite3EndTable(
#endif
/* Reparse everything to update our internal data structures */
sqlite3VdbeAddParseSchemaOp(v, iDb,
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0);
}
@@ -3466,7 +3492,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( !IsSharedSchema(db) && sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
assert( isView==0 || isView==LOCATE_VIEW );
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
@@ -3481,6 +3507,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 && iDb<db->nDb );
sqlite3SchemaWritable(pParse, iDb);
/* If pTab is a virtual table, call ViewGetColumnNames() to ensure
** it is initialized.
@@ -3935,7 +3962,7 @@ void sqlite3CreateIndex(
if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
goto exit_create_index;
}
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
if( !IsSharedSchema(db) && SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_create_index;
}
if( sqlite3HasExplicitNulls(pParse, pList) ){
@@ -4435,7 +4462,7 @@ void sqlite3CreateIndex(
if( pTblName ){
sqlite3RefillIndex(pParse, pIndex, iMem);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0);
sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
}
@@ -4585,6 +4612,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
goto exit_drop_index;
}
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
sqlite3SchemaWritable(pParse, iDb);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_INDEX;
+365 -6
View File
@@ -16,6 +16,63 @@
#include "sqliteInt.h"
/*
** Connections opened with the SQLITE_OPEN_SHARED_SCHEMA flag specified
** may use SchemaPool objects for any database that is not the temp db
** (iDb==1). For such databases (type "struct Db") there are three states
** the Schema/SchemaPool object may be in.
**
** 1) pSPool==0, pSchema points to an empty object allocated by
** sqlite3_malloc(). DB_SchemaLoaded flag is clear.
**
** 2) pSPool!=0, pSchema points to a populated object owned by the
** SchemaPool. DB_SchemaLoaded flag is set.
**
** 3) pSPool!=0, pSchema points to the SchemaPool's static object
** (SchemaPool.sSchema).
*/
struct SchemaPool {
int nRef; /* Number of pointers to this object */
int nDelete; /* Schema objects deleted by ReleaseAll() */
u64 cksum; /* Checksum for this Schema contents */
Schema *pSchema; /* Linked list of Schema objects */
Schema sSchema; /* The single dummy schema object */
SchemaPool *pNext; /* Next element in schemaPoolList */
};
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
#ifdef SQLITE_DEBUG
static void assert_schema_state_ok(sqlite3 *db){
if( IsSharedSchema(db) && db->eOpenState!=SQLITE_STATE_ZOMBIE ){
int i;
for(i=0; i<db->nDb; i++){
if( i!=1 ){
Db *pDb = &db->aDb[i];
Btree *pBt = pDb->pBt;
if( pBt==0 ) continue;
assert( sqlite3BtreeSchema(pBt, 0, 0)==0 );
assert( pDb->pSchema );
if( pDb->pSPool ){
if( DbHasProperty(db, i, DB_SchemaLoaded)==0 ){
assert( pDb->pSchema->tblHash.count==0 );
assert( pDb->pSchema==&pDb->pSPool->sSchema );
}else{
assert( pDb->pSchema!=&pDb->pSPool->sSchema );
}
}else{
assert( DbHasProperty(db, i, DB_SchemaLoaded)==0 );
assert( pDb->pSchema->tblHash.count==0 );
assert( pDb->pSchema!=&pDb->pSPool->sSchema );
}
}
}
}
}
#else
# define assert_schema_state_ok(x)
#endif
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
/*
** Invoke the 'collation needed' callback to request a collation sequence
** in the encoding enc of name zName, length nName.
@@ -516,15 +573,317 @@ void sqlite3SchemaClear(void *p){
}
/*
** Find and return the schema associated with a BTree. Create
** a new one if necessary.
** If this database was opened with the SQLITE_OPEN_SHARED_SCHEMA flag
** and iDb!=1, then disconnect from the schema-pool associated with
** database iDb. Otherwise, clear the Schema object belonging to
** database iDb.
**
** If an OOM error occurs while disconnecting from a schema-pool,
** the db->mallocFailed flag is set.
*/
void sqlite3SchemaClearOrDisconnect(sqlite3 *db, int iDb){
Db *pDb = &db->aDb[iDb];
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( IsSharedSchema(db) && iDb!=1 && pDb->pSPool ){
sqlite3SchemaDisconnect(db, iDb, 1);
}else
#endif
{
sqlite3SchemaClear(pDb->pSchema);
}
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** Global linked list of SchemaPool objects. Read and write access must
** be protected by the SQLITE_MUTEX_STATIC_MASTER mutex.
*/
static SchemaPool *SQLITE_WSD schemaPoolList = 0;
#ifdef SQLITE_TEST
/*
** Return a pointer to the head of the linked list of SchemaPool objects.
** This is used by the virtual table in file test_schemapool.c.
*/
SchemaPool *sqlite3SchemaPoolList(void){ return schemaPoolList; }
#endif
/*
** Database handle db was opened with the SHARED_SCHEMA flag, and database
** iDb is currently connected to a schema-pool. When this function is called,
** (*pnByte) is set to nInit plus the amount of memory used to store a
** single instance of the Schema objects managed by the schema-pool.
** This function adjusts (*pnByte) sot hat it is set to nInit plus
** (nSchema/nRef) of the amount of memory used by a single Schema object,
** where nSchema is the number of Schema objects allocated by this pool,
** and nRef is the number of connections to the schema-pool.
*/
void sqlite3SchemaAdjustUsed(sqlite3 *db, int iDb, int nInit, int *pnByte){
SchemaPool *pSPool = db->aDb[iDb].pSPool;
int nSchema = 0;
Schema *p;
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
for(p=pSPool->pSchema; p; p=p->pNext){
nSchema++;
}
*pnByte = nInit + ((*pnByte - nInit) * nSchema) / pSPool->nRef;
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
/*
** Check that the schema of db iDb is writable (either because it is the
** temp db schema or because the db handle was opened without
** SQLITE_OPEN_SHARED_SCHEMA). If so, do nothing. Otherwise, leave an
** error in the Parse object.
*/
void sqlite3SchemaWritable(Parse *pParse, int iDb){
if( iDb!=1 && IsSharedSchema(pParse->db) && IN_DECLARE_VTAB==0 ){
sqlite3ErrorMsg(pParse, "attempt to modify read-only schema");
}
}
/*
** The schema object passed as the only argument was allocated using
** sqlite3_malloc() and then populated using the usual mechanism. This
** function frees both the Schema object and its contents.
*/
static void schemaDelete(Schema *pSchema){
sqlite3SchemaClear((void*)pSchema);
sqlite3_free(pSchema);
}
/*
** When this function is called, the database connection Db must be
** using a schema-pool (Db.pSPool!=0) and must currently have Db.pSchema
** set to point to a populated schema object checked out from the
** schema-pool. It is also assumed that the STATIC_MASTER mutex is held.
** This function returns the Schema object to the schema-pool and sets
** Db.pSchema to point to the schema-pool's static, empty, Schema object.
*/
static void schemaRelease(sqlite3 *db, Db *pDb){
Schema *pRelease = pDb->pSchema;
SchemaPool *pSPool = pDb->pSPool;
assert( pDb->pSchema->iGeneration==pSPool->sSchema.iGeneration );
pDb->pSchema = &pSPool->sSchema;
assert( pDb->pSPool && pRelease );
assert( pRelease->schemaFlags & DB_SchemaLoaded );
assert( (pDb->pSchema->schemaFlags & DB_SchemaLoaded)==0 );
assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) );
/* If the DBFLAG_FreeSchema flag is set and the database connection holds
** at least one other copy of the schema being released, delete it instead
** of returning it to the schema-pool. */
if( db->mDbFlags & DBFLAG_FreeSchema ){
int i;
for(i=0; i<db->nDb; i++){
Db *p = &db->aDb[i];
if( p!=pDb && p->pSchema!=&pSPool->sSchema && pDb->pSPool==p->pSPool ){
pSPool->nDelete++;
schemaDelete(pRelease);
return;
}
}
}
pRelease->pNext = pDb->pSPool->pSchema;
pDb->pSPool->pSchema = pRelease;
}
/*
** The schema for database iDb of database handle db, which was opened
** with SQLITE_OPEN_SHARED_SCHEMA, has just been parsed. This function either
** finds a matching SchemaPool object on the global list (schemaPoolList) or
** else allocates a new one and sets the Db.pSPool variable accordingly.
**
** SQLITE_OK is returned if no error occurs, or an SQLite error code
** (SQLITE_NOMEM) otherwise.
*/
int sqlite3SchemaConnect(sqlite3 *db, int iDb, u64 cksum){
Schema *pSchema = db->aDb[iDb].pSchema;
SchemaPool *p;
assert( pSchema && iDb!=1 && db->aDb[iDb].pSPool==0 );
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
/* Search for a matching SchemaPool object */
for(p=schemaPoolList; p; p=p->pNext){
if( p->cksum==cksum && p->sSchema.schema_cookie==pSchema->schema_cookie ){
break;
}
}
if( !p ){
/* No SchemaPool object found. Allocate a new one. */
p = (SchemaPool*)sqlite3_malloc(sizeof(SchemaPool));
if( p ){
memset(p, 0, sizeof(SchemaPool));
p->cksum = cksum;
p->pNext = schemaPoolList;
schemaPoolList = p;
p->sSchema.schema_cookie = pSchema->schema_cookie;
p->sSchema.iGeneration = pSchema->iGeneration;
p->sSchema.file_format = pSchema->file_format;
p->sSchema.enc = pSchema->enc;
p->sSchema.cache_size = pSchema->cache_size;
}
}
if( p ) p->nRef++;
/* If the SchemaPool contains one or more free schemas at the moment,
** delete one of them. */
if( p && p->pSchema ){
Schema *pDel = p->pSchema;
p->pSchema = pDel->pNext;
schemaDelete(pDel);
}
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
db->aDb[iDb].pSPool = p;
return (p ? SQLITE_OK : SQLITE_NOMEM);
}
/*
** If parameter iDb is 1 (the temp db), or if connection handle db was not
** opened with the SQLITE_OPEN_SHARED_SCHEMA flag, this function is a no-op.
** Otherwise, it disconnects from the schema-pool associated with database
** iDb, assuming it is connected.
**
** If parameter bNew is true, then Db.pSchema is set to point to a new, empty,
** Schema object obtained from sqlite3_malloc(). Or, if bNew is false, then
** Db.pSchema is set to NULL before returning.
**
** If the bNew parameter is true, then this function may allocate memory.
** If the allocation attempt fails, then SQLITE_NOMEM is returned and the
** schema-pool is not disconnected from. Or, if no OOM error occurs,
** SQLITE_OK is returned.
*/
int sqlite3SchemaDisconnect(sqlite3 *db, int iDb, int bNew){
int rc = SQLITE_OK;
if( IsSharedSchema(db) ){
Db *pDb = &db->aDb[iDb];
SchemaPool *pSPool = pDb->pSPool;
assert_schema_state_ok(db);
assert( pDb->pSchema );
if( pSPool==0 ){
assert( pDb->pVTable==0 );
assert( bNew==0 );
schemaDelete(pDb->pSchema);
pDb->pSchema = 0;
}else{
VTable *p;
VTable *pNext;
for(p=pDb->pVTable; p; p=pNext){
pNext = p->pNext;
sqlite3VtabUnlock(p);
}
pDb->pVTable = 0;
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
if( DbHasProperty(db, iDb, DB_SchemaLoaded) ){
schemaRelease(db, pDb);
}
if( bNew ){
Schema *pNew = sqlite3SchemaGet(db, 0);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
pDb->pSchema = pNew;
}
}
if( rc==SQLITE_OK ){
assert( pSPool->nRef>=1 );
pDb->pSPool = 0;
pSPool->nRef--;
if( pSPool->nRef<=0 ){
SchemaPool **pp;
while( pSPool->pSchema ){
Schema *pNext = pSPool->pSchema->pNext;
schemaDelete(pSPool->pSchema);
pSPool->pSchema = pNext;
}
for(pp=&schemaPoolList; (*pp)!=pSPool; pp=&((*pp)->pNext));
*pp = pSPool->pNext;
sqlite3_free(pSPool);
}
}
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
}
return rc;
}
/*
** Extract and return a pointer to a schema object from the SchemaPool passed
** as the only argument, if one is available. If one is not available, return
** NULL.
*/
Schema *sqlite3SchemaExtract(SchemaPool *pSPool){
Schema *pRet = 0;
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
if( pSPool->pSchema ){
pRet = pSPool->pSchema;
pSPool->pSchema = pRet->pNext;
pRet->pNext = 0;
}
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
return pRet;
}
/*
** Return all sharable schemas held by database handle db back to their
** respective schema-pools. Db.pSchema variables are left pointing to
** the static, empty, Schema object owned by each schema-pool.
*/
void sqlite3SchemaReleaseAll(sqlite3 *db){
int i;
assert_schema_state_ok(db);
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
for(i=0; i<db->nDb; i++){
if( i!=1 ){
Db *pDb = &db->aDb[i];
if( pDb->pSPool && DbHasProperty(db,i,DB_SchemaLoaded) ){
schemaRelease(db, pDb);
}
}
}
db->mDbFlags &= ~DBFLAG_FreeSchema;
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
/*
** Release any sharable schema held by connection iDb of database handle
** db. Db.pSchema is left pointing to the static, empty, Schema object
** owned by the schema-pool.
*/
void sqlite3SchemaRelease(sqlite3 *db, int iDb){
Db *pDb = &db->aDb[iDb];
assert( iDb!=1 );
assert_schema_state_ok(db);
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
schemaRelease(db, pDb);
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
/*
** In most cases, this function finds and returns the schema associated
** with BTree handle pBt, creating a new one if necessary. However, if
** the database handle was opened with the SQLITE_OPEN_SHARED_SCHEMA flag
** specified, a new, empty, Schema object in memory obtained by
** sqlite3_malloc() is always returned.
*/
Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
Schema * p;
if( pBt ){
p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
Schema *p;
if( pBt && IsSharedSchema(db)==0 ){
p = (Schema*)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
}else{
p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));
p = (Schema*)sqlite3DbMallocZero(0, sizeof(Schema));
}
if( !p ){
sqlite3OomFault(db);
+3
View File
@@ -313,6 +313,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_SESSION
"ENABLE_SESSION",
#endif
#if SQLITE_ENABLE_SHARED_SCHEMA
"ENABLE_SHARED_SCHEMA",
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
"ENABLE_SNAPSHOT",
#endif
+1 -1
View File
@@ -510,7 +510,7 @@ static const sqlite3_api_routines sqlite3Apis = {
#endif
sqlite3_db_name,
/* Version 3.40.0 and later */
sqlite3_value_type
sqlite3_value_encoding
};
/* True if x is the directory separator character
+38 -7
View File
@@ -1167,6 +1167,17 @@ static void disconnectAllVtab(sqlite3 *db){
if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
}
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( IsSharedSchema(db) && i!=1 ){
VTable *pVTable;
VTable *pNext;
for(pVTable=db->aDb[i].pVTable; pVTable; pVTable=pNext){
pNext = pVTable->pNext;
sqlite3VtabUnlock(pVTable);
}
db->aDb[i].pVTable = 0;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
}
for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){
Module *pMod = (Module *)sqliteHashData(p);
@@ -1335,6 +1346,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
if( j!=1 ){
(void)sqlite3SchemaDisconnect(db, j, 0);
pDb->pSchema = 0;
}
}
@@ -2118,7 +2130,7 @@ int sqlite3_overload_function(
rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0;
sqlite3_mutex_leave(db->mutex);
if( rc ) return SQLITE_OK;
zCopy = sqlite3_mprintf(zName);
zCopy = sqlite3_mprintf("%s", zName);
if( zCopy==0 ) return SQLITE_NOMEM;
return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8,
zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free);
@@ -3778,7 +3790,7 @@ int sqlite3_table_column_metadata(
int *pPrimaryKey, /* OUTPUT: True if column part of PK */
int *pAutoinc /* OUTPUT: True if column is auto-increment */
){
int rc;
int rc = SQLITE_OK;
char *zErrMsg = 0;
Table *pTab = 0;
Column *pCol = 0;
@@ -3788,7 +3800,7 @@ int sqlite3_table_column_metadata(
int notnull = 0;
int primarykey = 0;
int autoinc = 0;
int bUnlock;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){
@@ -3798,14 +3810,29 @@ int sqlite3_table_column_metadata(
/* Ensure the database schema has been loaded */
sqlite3_mutex_enter(db->mutex);
bUnlock = sqlite3LockReusableSchema(db);
sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrMsg);
if( SQLITE_OK!=rc ){
goto error_out;
if( IsSharedSchema(db)==0 ){
rc = sqlite3Init(db, &zErrMsg);
}
/* Locate the table in question */
pTab = sqlite3FindTable(db, zTableName, zDbName);
if( rc==SQLITE_OK ){
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
Parse sParse; /* Fake Parse object for FindTable */
Parse *pSaved = db->pParse;
memset(&sParse, 0, sizeof(sParse));
db->pParse = &sParse;
#endif
pTab = sqlite3FindTable(db, zTableName, zDbName);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
sqlite3_free(sParse.zErrMsg);
rc = sParse.rc;
db->pParse = pSaved;
#endif
}
if( SQLITE_OK!=rc ) goto error_out;
if( !pTab || IsView(pTab) ){
pTab = 0;
goto error_out;
@@ -3878,6 +3905,7 @@ error_out:
sqlite3ErrorWithMsg(db, rc, (zErrMsg?"%s":0), zErrMsg);
sqlite3DbFree(db, zErrMsg);
rc = sqlite3ApiExit(db, rc);
sqlite3UnlockReusableSchema(db, bUnlock);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -3950,6 +3978,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0);
}
rc = SQLITE_OK;
}else if( op==SQLITE_FCNTL_RESET_CACHE ){
sqlite3BtreeClearCache(pBtree);
rc = SQLITE_OK;
}else{
int nSave = db->busyHandler.nBusy;
rc = sqlite3OsFileControl(fd, op, pArg);
+6 -2
View File
@@ -424,9 +424,13 @@ static int memsys5Roundup(int n){
if( n<=mem5.szAtom ) return mem5.szAtom;
return mem5.szAtom*2;
}
if( n>0x40000000 ) return 0;
if( n>0x10000000 ){
if( n>0x40000000 ) return 0;
if( n>0x20000000 ) return 0x40000000;
return 0x20000000;
}
for(iFullSz=mem5.szAtom*8; iFullSz<n; iFullSz *= 4);
if( (iFullSz/2)>=n ) return iFullSz/2;
if( (iFullSz/2)>=(i64)n ) return iFullSz/2;
return iFullSz;
}
+78 -28
View File
@@ -109,6 +109,7 @@ static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
static int memdbSync(sqlite3_file*, int flags);
static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int memdbLock(sqlite3_file*, int);
static int memdbUnlock(sqlite3_file*, int);
/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
static int memdbFileControl(sqlite3_file*, int op, void *pArg);
/* static int memdbSectorSize(sqlite3_file*); // not used */
@@ -167,7 +168,7 @@ static const sqlite3_io_methods memdb_io_methods = {
memdbSync, /* xSync */
memdbFileSize, /* xFileSize */
memdbLock, /* xLock */
memdbLock, /* xUnlock - same as xLock in this case */
memdbUnlock, /* xUnlock */
0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
memdbFileControl, /* xFileControl */
0, /* memdbSectorSize,*/ /* xSectorSize */
@@ -368,41 +369,83 @@ static int memdbLock(sqlite3_file *pFile, int eLock){
MemFile *pThis = (MemFile*)pFile;
MemStore *p = pThis->pStore;
int rc = SQLITE_OK;
if( eLock==pThis->eLock ) return SQLITE_OK;
if( eLock<=pThis->eLock ) return SQLITE_OK;
memdbEnter(p);
if( eLock>SQLITE_LOCK_SHARED ){
if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
rc = SQLITE_READONLY;
}else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
if( p->nWrLock ){
rc = SQLITE_BUSY;
}else{
p->nWrLock = 1;
assert( p->nWrLock==0 || p->nWrLock==1 );
assert( pThis->eLock<=SQLITE_LOCK_SHARED || p->nWrLock==1 );
assert( pThis->eLock==SQLITE_LOCK_NONE || p->nRdLock>=1 );
if( eLock>SQLITE_LOCK_SHARED && (p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
rc = SQLITE_READONLY;
}else{
switch( eLock ){
case SQLITE_LOCK_SHARED: {
assert( pThis->eLock==SQLITE_LOCK_NONE );
if( p->nWrLock>0 ){
rc = SQLITE_BUSY;
}else{
p->nRdLock++;
}
break;
};
case SQLITE_LOCK_RESERVED:
case SQLITE_LOCK_PENDING: {
assert( pThis->eLock>=SQLITE_LOCK_SHARED );
if( ALWAYS(pThis->eLock==SQLITE_LOCK_SHARED) ){
if( p->nWrLock>0 ){
rc = SQLITE_BUSY;
}else{
p->nWrLock = 1;
}
}
break;
}
default: {
assert( eLock==SQLITE_LOCK_EXCLUSIVE );
assert( pThis->eLock>=SQLITE_LOCK_SHARED );
if( p->nRdLock>1 ){
rc = SQLITE_BUSY;
}else if( pThis->eLock==SQLITE_LOCK_SHARED ){
p->nWrLock = 1;
}
break;
}
}
}else if( eLock==SQLITE_LOCK_SHARED ){
if( pThis->eLock > SQLITE_LOCK_SHARED ){
assert( p->nWrLock==1 );
p->nWrLock = 0;
}else if( p->nWrLock ){
rc = SQLITE_BUSY;
}else{
p->nRdLock++;
}
}else{
assert( eLock==SQLITE_LOCK_NONE );
if( pThis->eLock>SQLITE_LOCK_SHARED ){
assert( p->nWrLock==1 );
p->nWrLock = 0;
}
assert( p->nRdLock>0 );
p->nRdLock--;
}
if( rc==SQLITE_OK ) pThis->eLock = eLock;
memdbLeave(p);
return rc;
}
/*
** Unlock an memdb-file.
*/
static int memdbUnlock(sqlite3_file *pFile, int eLock){
MemFile *pThis = (MemFile*)pFile;
MemStore *p = pThis->pStore;
if( eLock>=pThis->eLock ) return SQLITE_OK;
memdbEnter(p);
assert( eLock==SQLITE_LOCK_SHARED || eLock==SQLITE_LOCK_NONE );
if( eLock==SQLITE_LOCK_SHARED ){
if( ALWAYS(pThis->eLock>SQLITE_LOCK_SHARED) ){
p->nWrLock--;
}
}else{
if( pThis->eLock>SQLITE_LOCK_SHARED ){
p->nWrLock--;
}
p->nRdLock--;
}
pThis->eLock = eLock;
memdbLeave(p);
return SQLITE_OK;
}
#if 0
/*
** This interface is only used for crash recovery, which does not
@@ -510,7 +553,7 @@ static int memdbOpen(
memset(pFile, 0, sizeof(*pFile));
szName = sqlite3Strlen30(zName);
if( szName>1 && zName[0]=='/' ){
if( szName>1 && (zName[0]=='/' || zName[0]=='\\') ){
int i;
#ifndef SQLITE_MUTEX_OMIT
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
@@ -857,6 +900,13 @@ end_deserialize:
return rc;
}
/*
** Return true if the VFS is the memvfs.
*/
int sqlite3IsMemdb(const sqlite3_vfs *pVfs){
return pVfs==&memdb_vfs;
}
/*
** This routine is called when the extension is loaded.
** Register the new VFS.
+3
View File
@@ -686,6 +686,9 @@ static int robust_open(const char *z, int f, mode_t m){
break;
}
if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
if( (f & (O_EXCL|O_CREAT))==(O_EXCL|O_CREAT) ){
(void)osUnlink(z);
}
osClose(fd);
sqlite3_log(SQLITE_WARNING,
"attempt to open \"%s\" as file descriptor %d", z, fd);
+10 -3
View File
@@ -476,7 +476,13 @@ void sqlite3Pragma(
/* Make sure the database schema is loaded if the pragma requires that */
if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
if( IsSharedSchema(db) && (zDb || (pPragma->mPragFlg & PragFlg_OneSchema)) ){
assert( iDb>=0 && iDb<db->nDb );
pParse->rc = sqlite3SchemaLoad(db, iDb, 0, &pParse->zErrMsg);
if( pParse->rc ) goto pragma_out;
}else{
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
}
}
/* Register the result column names for pragmas that return results */
@@ -2153,9 +2159,10 @@ void sqlite3Pragma(
** applications for any purpose.
*/
case PragTyp_HEADER_VALUE: {
int iCookie = pPragma->iArg; /* Which cookie to read or write */
int iCookie; /* Which cookie to read or write */
iCookie = pPragma->iArg & PRAGMA_HEADER_VALUE_MASK;
sqlite3VdbeUsesBtree(v, iDb);
if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){
if( zRight && (pPragma->iArg & PRAGMA_HEADER_VALUE_READONLY)==0 ){
/* Write the specified cookie value */
static const VdbeOpList setCookie[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */
+23 -16
View File
@@ -56,12 +56,19 @@
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */
#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */
#define PragFlg_OneSchema 0x08 /* Only a single schema required */
#define PragFlg_Result0 0x10 /* Acts as query when no argument */
#define PragFlg_Result1 0x20 /* Acts as query when has one argument */
#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */
#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */
/* For PragTyp_HEADER_VALUE pragmas the Pragma.iArg value is set
** to the index of the header field to access (always 10 or less).
** Ored with HEADER_VALUE_READONLY if the field is read only. */
#define PRAGMA_HEADER_VALUE_READONLY 0x0100
#define PRAGMA_HEADER_VALUE_MASK 0x00FF
/* Names of columns for pragmas that return multi-column result
** or that return single-column results where the name of the
** result column is different from the name of the pragma
@@ -162,7 +169,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_AUTOVACUUM)
{/* zName: */ "auto_vacuum",
/* ePragTyp: */ PragTyp_AUTO_VACUUM,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -183,7 +190,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
/* ePragTyp: */ PragTyp_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -244,9 +251,9 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "data_version",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_DATA_VERSION },
/* iArg: */ BTREE_DATA_VERSION|PRAGMA_HEADER_VALUE_READONLY },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
{/* zName: */ "database_list",
@@ -258,7 +265,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
{/* zName: */ "default_cache_size",
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1|PragFlg_OneSchema,
/* ColNames: */ 55, 1,
/* iArg: */ 0 },
#endif
@@ -295,7 +302,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
{/* zName: */ "foreign_key_list",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt|PragFlg_OneSchema,
/* ColNames: */ 0, 8,
/* iArg: */ 0 },
#endif
@@ -311,9 +318,9 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "freelist_count",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_FREE_PAGE_COUNT },
/* iArg: */ BTREE_FREE_PAGE_COUNT|PRAGMA_HEADER_VALUE_READONLY },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "full_column_names",
@@ -353,7 +360,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_AUTOVACUUM)
{/* zName: */ "incremental_vacuum",
/* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -384,7 +391,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "journal_mode",
/* ePragTyp: */ PragTyp_JOURNAL_MODE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "journal_size_limit",
@@ -422,7 +429,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ 0 },
{/* zName: */ "max_page_count",
/* ePragTyp: */ PragTyp_PAGE_COUNT,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "mmap_size",
@@ -450,7 +457,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "page_count",
/* ePragTyp: */ PragTyp_PAGE_COUNT,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "page_size",
@@ -549,14 +556,14 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_OneSchema,
/* ColNames: */ 33, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "synchronous",
/* ePragTyp: */ PragTyp_SYNCHRONOUS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -645,7 +652,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ 0 },
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_OneSchema,
/* ColNames: */ 50, 3,
/* iArg: */ 0 },
#endif
+126 -10
View File
@@ -43,6 +43,11 @@ static void corruptSchema(
pData->rc = SQLITE_ERROR;
}else if( db->flags & SQLITE_WriteSchema ){
pData->rc = SQLITE_CORRUPT_BKPT;
}else if( IsSharedSchema(db)
&& 0==sqlite3StrNICmp(zExtra, "malformed database schema", 17)
){
pData->rc = SQLITE_CORRUPT_BKPT;
*pData->pzErrMsg = sqlite3DbStrDup(db, zExtra);
}else{
char *z;
const char *zObj = azObj[1] ? azObj[1] : "?";
@@ -53,6 +58,28 @@ static void corruptSchema(
}
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** Update the Schema.cksum checksum to account for the database object
** specified by the three arguments following the first.
*/
static void schemaUpdateChecksum(
InitData *pData, /* Schema parse context */
const char *zName, /* Name of new database object */
const char *zRoot, /* Root page of new database object */
const char *zSql /* SQL used to create new database object */
){
int i;
u64 cksum = pData->cksum;
if( zName ){
for(i=0; zName[i]; i++) cksum += (cksum<<3) + zName[i];
}
if( zRoot ) for(i=0; zRoot[i]; i++) cksum += (cksum<<3) + zRoot[i];
if( zSql ) for(i=0; zSql[i]; i++) cksum += (cksum<<3) + zSql[i];
pData->cksum = cksum;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
/*
** Check to see if any sibling index (another index on the same table)
** of pIndex has the same root page number, and if it does, return true.
@@ -76,6 +103,15 @@ static int sqlite3Prepare(
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
);
static int sqlite3LockAndPrepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
Vdbe *pReprepare, /* VM being reprepared */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
);
/*
@@ -141,7 +177,11 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
db->init.orphanTrigger = 0;
db->init.azInit = (const char**)argv;
pStmt = 0;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
TESTONLY(rcp = ) sqlite3LockAndPrepare(db, argv[4], -1, 0, 0, &pStmt, 0);
#else
TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
#endif
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
@@ -153,7 +193,12 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
if( rc > pData->rc ) pData->rc = rc;
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(db);
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
}else if( rc!=SQLITE_INTERRUPT
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
&& (rc&0xFF)!=SQLITE_LOCKED
&& (rc&0xFF)!=SQLITE_IOERR
#endif
){
corruptSchema(pData, argv, sqlite3_errmsg(db));
}
}
@@ -184,6 +229,12 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
}
}
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( IsSharedSchema(db) && iDb!=1 ){
schemaUpdateChecksum(pData, argv[0], argv[1], argv[2]);
}
#endif
return 0;
}
@@ -211,10 +262,28 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pSchema );
assert( db->aDb[iDb].pSchema || (IsSharedSchema(db) && iDb!=1) );
assert( sqlite3_mutex_held(db->mutex) );
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
pDb = &db->aDb[iDb];
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
assert( pDb->pSPool==0 || IsSharedSchema(db) );
if( pDb->pSPool ){
/* See if there is a free schema object in the schema-pool. If not,
** disconnect from said schema pool and continue. This function will
** connect to a (possibly different) schema-pool before returning. */
Schema *pNew = sqlite3SchemaExtract(pDb->pSPool);
if( pNew ){
pDb->pSchema = pNew;
return SQLITE_OK;
}
rc = sqlite3SchemaDisconnect(db, iDb, 1);
if( rc!=SQLITE_OK ) goto error_out;
assert( pDb->pSchema && pDb->pSPool==0 );
}
#endif
db->init.busy = 1;
/* Construct the in-memory representation schema tables (sqlite_schema or
@@ -235,6 +304,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
initData.pzErrMsg = pzErrMsg;
initData.mInitFlags = mFlags;
initData.nInitRow = 0;
initData.cksum = 0;
initData.mxPage = 0;
sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
db->mDbFlags &= mask;
@@ -245,7 +315,6 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
/* Create a cursor to hold the database open
*/
pDb = &db->aDb[iDb];
if( pDb->pBt==0 ){
assert( iDb==1 );
DbSetProperty(db, 1, DB_SchemaLoaded);
@@ -404,6 +473,10 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
rc = SQLITE_OK;
}
if( rc==SQLITE_OK && iDb!=1 && IsSharedSchema(db) ){
rc = sqlite3SchemaConnect(db, iDb, initData.cksum);
}
/* Jump here for an error that occurs after successfully allocating
** curMain and calling sqlite3BtreeEnter(). For an error that occurs
** before that point, jump to error_out.
@@ -425,6 +498,35 @@ error_out:
return rc;
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** If this is a SHARED_SCHEMA connection and the DBFLAG_SchemaInUse flag
** is not currently set, set it and return non-zero. Otherwise, return 0.
*/
int sqlite3LockReusableSchema(sqlite3 *db){
if( IsSharedSchema(db) && (db->mDbFlags & DBFLAG_SchemaInuse)==0 ){
db->mDbFlags |= DBFLAG_SchemaInuse;
return 1;
}
return 0;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** This function is a no-op for non-SHARED_SCHEMA connections, or if bRelease
** is zero. Otherwise, clear the DBFLAG_SchemaInuse flag and release all
** schema references currently held.
*/
void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease){
if( bRelease ){
db->mDbFlags &= ~DBFLAG_SchemaInuse;
sqlite3SchemaReleaseAll(db);
}
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
@@ -435,8 +537,12 @@ error_out:
** bit is set in the flags field of the Db structure.
*/
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
int rc = SQLITE_OK;
int bReleaseSchema;
int i;
int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange);
bReleaseSchema = sqlite3LockReusableSchema(db);
assert( sqlite3_mutex_held(db->mutex) );
assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
@@ -446,20 +552,19 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
/* Do the main schema first */
if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
rc = sqlite3InitOne(db, 0, pzErrMsg, 0);
if( rc ) return rc;
}
/* All other schemas after the main schema. The "temp" schema must be last */
for(i=db->nDb-1; i>0; i--){
for(i=db->nDb-1; rc==SQLITE_OK && i>0; i--){
assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) );
if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
rc = sqlite3InitOne(db, i, pzErrMsg, 0);
if( rc ) return rc;
}
}
if( commit_internal ){
if( rc==SQLITE_OK && commit_internal ){
sqlite3CommitInternalChanges(db);
}
return SQLITE_OK;
sqlite3UnlockReusableSchema(db, bReleaseSchema);
return rc;
}
/*
@@ -471,11 +576,12 @@ int sqlite3ReadSchema(Parse *pParse){
sqlite3 *db = pParse->db;
assert( sqlite3_mutex_held(db->mutex) );
if( !db->init.busy ){
db->mDbFlags |= DBFLAG_FreeSchema; /* For sharable-schema mode */
rc = sqlite3Init(db, &pParse->zErrMsg);
if( rc!=SQLITE_OK ){
pParse->rc = rc;
pParse->nErr++;
}else if( db->noSharedCache ){
}else if( db->noSharedCache && !IsSharedSchema(db) ){
db->mDbFlags |= DBFLAG_SchemaKnownOk;
}
}
@@ -501,6 +607,10 @@ static void schemaIsValid(Parse *pParse){
Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */
if( pBt==0 ) continue;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( IsSharedSchema(db) && iDb!=1 && db->aDb[iDb].pSPool==0 ) continue;
#endif
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
@@ -830,6 +940,7 @@ static int sqlite3LockAndPrepare(
){
int rc;
int cnt = 0;
int bReleaseSchema = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
@@ -839,6 +950,7 @@ static int sqlite3LockAndPrepare(
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
bReleaseSchema = sqlite3LockReusableSchema(db);
sqlite3BtreeEnterAll(db);
do{
/* Make multiple attempts to compile the SQL, until it either succeeds
@@ -849,7 +961,11 @@ static int sqlite3LockAndPrepare(
if( rc==SQLITE_OK || db->mallocFailed ) break;
}while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db);
sqlite3UnlockReusableSchema(db, bReleaseSchema);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
db->busyHandler.nBusy = 0;
+303 -11
View File
@@ -1213,13 +1213,14 @@ static ShellState shellState;
/* Allowed values for ShellState.openMode
*/
#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
#define SHELL_OPEN_NORMAL 1 /* Normal database file */
#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
#define SHELL_OPEN_NORMAL 1 /* Normal database file */
#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
#define SHELL_OPEN_SHAREDSCHEMA 7 /* Open for schema reuse */
/* Allowed values for ShellState.eTraceType
*/
@@ -1875,7 +1876,7 @@ static int safeModeAuth(
"zipfile",
"zipfile_cds",
};
UNUSED_PARAMETER(zA2);
UNUSED_PARAMETER(zA1);
UNUSED_PARAMETER(zA3);
UNUSED_PARAMETER(zA4);
switch( op ){
@@ -1890,7 +1891,7 @@ static int safeModeAuth(
case SQLITE_FUNCTION: {
int i;
for(i=0; i<ArraySize(azProhibitedFunctions); i++){
if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
if( sqlite3_stricmp(zA2, azProhibitedFunctions[i])==0 ){
failIfSafeMode(p, "cannot use the %s() function in safe mode",
azProhibitedFunctions[i]);
}
@@ -4558,6 +4559,12 @@ static const char *(azHelp[]) = {
" --sha3-384 Use the sha3-384 algorithm",
" --sha3-512 Use the sha3-512 algorithm",
" Any other argument is a LIKE pattern for tables to hash",
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
".shared-schema CMD DB1 DB2 ...",
" Commands:",
" check Determine if DB1, DB2, etc have identical schemas",
" fix Attempt to make DB1, DB2, etc compatible",
#endif
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
".shell CMD ARGS... Run CMD ARGS... in a system shell",
#endif
@@ -5098,6 +5105,11 @@ static void open_db(ShellState *p, int openFlags){
SQLITE_OPEN_READONLY|p->openFlags, 0);
break;
}
case SHELL_OPEN_SHAREDSCHEMA: {
sqlite3_open_v2(p->pAuxDb->zDbFilename, &p->db,
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_SHARED_SCHEMA,0);
break;
}
case SHELL_OPEN_UNSPEC:
case SHELL_OPEN_NORMAL: {
sqlite3_open_v2(zDbFilename, &p->db,
@@ -7286,8 +7298,277 @@ end_ar_command:
*******************************************************************************/
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
#if SQLITE_SHELL_HAVE_RECOVER
/*
** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
** Otherwise, the SQL statement or statements in zSql are executed using
** database connection db and the error code written to *pRc before
** this function returns.
*/
static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
int rc = *pRc;
if( rc==SQLITE_OK ){
char *zErr = 0;
rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
if( rc!=SQLITE_OK ){
raw_printf(stderr, "SQL error: %s\n", zErr);
}
sqlite3_free(zErr);
*pRc = rc;
}
}
/*
** Like shellExec(), except that zFmt is a printf() style format string.
*/
static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
char *z = 0;
if( *pRc==SQLITE_OK ){
va_list ap;
va_start(ap, zFmt);
z = sqlite3_vmprintf(zFmt, ap);
va_end(ap);
if( z==0 ){
*pRc = SQLITE_NOMEM;
}else{
shellExec(db, pRc, z);
}
sqlite3_free(z);
}
}
static int sharedSchemaFix(ShellState *pState, const char *zDb){
int rc = SQLITE_OK;
i64 iLast = 0;
int iCookie = 0;
int iAutoVacuum = 0;
sqlite3_stmt *pStmt = 0;
shellExecPrintf(pState->db, &rc, "ATTACH '%q' AS _shared_schema_tmp", zDb);
shellExecPrintf(pState->db, &rc, "PRAGMA writable_schema = 1");
shellExecPrintf(pState->db, &rc, "BEGIN");
shellPreparePrintf(pState->db, &rc, &pStmt,
"SELECT max(rowid) FROM _shared_schema_tmp.sqlite_master"
);
sqlite3_step(pStmt);
iLast = sqlite3_column_int64(pStmt, 0);
shellFinalize(&rc, pStmt);
shellPreparePrintf(pState->db, &rc, &pStmt,
"INSERT INTO _shared_schema_tmp.sqlite_master SELECT "
" type, name, tbl_name, ("
" SELECT rootpage FROM _shared_schema_tmp.sqlite_master WHERE "
" type IS o.type AND name IS o.name AND rowid<=?"
" ), sql FROM main.sqlite_master AS o"
);
sqlite3_bind_int64(pStmt, 1, iLast);
sqlite3_step(pStmt);
shellFinalize(&rc, pStmt);
shellExecPrintf(pState->db, &rc,
"DELETE FROM _shared_schema_tmp.sqlite_master WHERE rowid<=%lld",
iLast
);
shellExecPrintf(pState->db, &rc, "COMMIT");
sqlite3_exec(pState->db, "PRAGMA writable_schema = 0", 0, 0, 0);
/* Copy the auto-vacuum setting from main to the target db */
shellPreparePrintf(pState->db, &rc, &pStmt, "PRAGMA main.auto_vacuum");
sqlite3_step(pStmt);
iAutoVacuum = sqlite3_column_int(pStmt, 0);
shellFinalize(&rc, pStmt);
shellExecPrintf(pState->db, &rc,
"PRAGMA _shared_schema_tmp.auto_vacuum = %d", iAutoVacuum
);
/* Vacuum the db in order to standardize the rootpage numbers. */
shellExecPrintf(pState->db, &rc, "VACUUM _shared_schema_tmp");
/* Set the schema-cookie value to the same as database "main" */
shellPreparePrintf(pState->db, &rc, &pStmt, "PRAGMA main.schema_version");
sqlite3_step(pStmt);
iCookie = sqlite3_column_int(pStmt, 0);
shellFinalize(&rc, pStmt);
shellExecPrintf(pState->db, &rc,
"PRAGMA _shared_schema_tmp.schema_version = %d", iCookie
);
sqlite3_exec(pState->db, "DETACH _shared_schema_tmp", 0, 0, 0);
return rc;
}
static int sharedSchemaCheck(ShellState *pState, const char *zDb, int *peFix){
int rc = SQLITE_OK;
int bFailed = 0;
sqlite3_stmt *pStmt = 0;
if( peFix ) *peFix = 0;
shellExecPrintf(pState->db, &rc, "ATTACH '%q' AS _shared_schema_tmp", zDb);
/* Check if this database has the same set of objects as the current db */
shellPreparePrintf(pState->db, &rc, &pStmt,
"SELECT type, name FROM _shared_schema_tmp.sqlite_master AS o "
"WHERE NOT EXISTS ("
" SELECT 1 FROM main.sqlite_master "
" WHERE name IS o.name AND type IS o.type"
")"
" UNION ALL "
"SELECT type, name FROM main.sqlite_master AS o "
"WHERE NOT EXISTS ("
" SELECT 1 FROM _shared_schema_tmp.sqlite_master "
" WHERE name IS o.name AND type IS o.type"
")"
);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
utf8_printf(pState->out, "%s is NOT compatible (objects)\n", zDb);
bFailed = 1;
}
shellFinalize(&rc, pStmt);
/* Check if this database has the same set of SQL statements as the
** current db. */
if( bFailed==0 ){
shellPreparePrintf(pState->db, &rc, &pStmt,
"SELECT 1 FROM _shared_schema_tmp.sqlite_master AS o "
"WHERE sql IS NOT ("
" SELECT sql FROM main.sqlite_master "
" WHERE name IS o.name AND type IS o.type"
")"
);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
utf8_printf(pState->out, "%s is NOT compatible (SQL)\n", zDb);
bFailed = 1;
}
shellFinalize(&rc, pStmt);
}
/* Check if this database has the same set of root pages as the current
** db. */
if( bFailed==0 ){
shellPreparePrintf(pState->db, &rc, &pStmt,
"SELECT 1 FROM _shared_schema_tmp.sqlite_master AS o "
"WHERE rootpage IS NOT ("
" SELECT rootpage FROM main.sqlite_master "
" WHERE name IS o.name AND type IS o.type"
")"
);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
if( peFix==0 ){
utf8_printf(pState->out, "%s is NOT compatible (root pages)\n", zDb);
}
bFailed = 1;
if( peFix ) *peFix = 1;
}
shellFinalize(&rc, pStmt);
}
if( bFailed==0 ){
shellPreparePrintf(pState->db, &rc, &pStmt,
"SELECT 1 WHERE ("
" SELECT group_concat(rootpage || '.' || name || '.' || sql, '.') "
" FROM _shared_schema_tmp.sqlite_master"
") IS NOT ("
" SELECT group_concat(rootpage || '.' || name || '.' || sql, '.') "
" FROM main.sqlite_master"
")"
);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
if( peFix==0 ){
utf8_printf(pState->out,
"%s is NOT compatible (order of sqlite_master rows)\n", zDb
);
}
bFailed = 1;
if( peFix ) *peFix = 2;
}
shellFinalize(&rc, pStmt);
}
if( bFailed==0 ){
int iMain = -1;
int iNew = +1;
shellPreparePrintf(pState->db, &rc, &pStmt,
"PRAGMA main.schema_version"
);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
iMain = sqlite3_column_int(pStmt, 0);
}
shellFinalize(&rc, pStmt);
shellPreparePrintf(pState->db, &rc, &pStmt,
"PRAGMA _shared_schema_tmp.schema_version"
);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
iNew = sqlite3_column_int(pStmt, 0);
}
shellFinalize(&rc, pStmt);
if( rc==SQLITE_OK && iMain!=iNew ){
if( peFix==0 ){
utf8_printf(pState->out,
"%s is NOT compatible (schema cookie)\n", zDb
);
}
bFailed = 1;
if( peFix ) *peFix = 3;
}
}
if( rc==SQLITE_OK && bFailed==0 ){
utf8_printf(pState->out, "%s is compatible\n", zDb);
}
sqlite3_exec(pState->db, "DETACH _shared_schema_tmp", 0, 0, 0);
return rc;
}
/*
** .shared-schema check|fix DB1 DB2...
*/
static int sharedSchemaDotCommand(
ShellState *pState, /* Current shell tool state */
char **azArg, /* Array of arguments passed to dot command */
int nArg /* Number of entries in azArg[] */
){
int rc = SQLITE_OK;
int bFix = 0; /* Fix databases if possible */
int n1;
int i;
if( nArg<3 ){
goto shared_schema_usage;
}
n1 = (int)strlen(azArg[1]);
if( n1>0 && n1<=3 && memcmp("fix", azArg[1], n1)==0 ){
bFix = 1;
}else if( n1==0 || n1>5 || memcmp("check", azArg[1], n1) ){
goto shared_schema_usage;
}
for(i=2; rc==SQLITE_OK && i<nArg; i++){
int eFix = 0;
rc = sharedSchemaCheck(pState, azArg[i], bFix ? &eFix : 0);
if( rc==SQLITE_OK && bFix && eFix ){
utf8_printf(pState->out, "Fixing %s... ", azArg[i]);
fflush(pState->out);
rc = sharedSchemaFix(pState, azArg[i]);
if( rc==SQLITE_OK ){
rc = sharedSchemaCheck(pState, azArg[i], &eFix);
if( rc==SQLITE_OK && eFix ){
utf8_printf(pState->out, "VACUUMing main... ");
fflush(pState->out);
rc = sqlite3_exec(pState->db, "VACUUM main", 0, 0, 0);
if( rc==SQLITE_OK ){
rc = sharedSchemaCheck(pState, azArg[i], 0);
}
}
}
}
}
return rc;
shared_schema_usage:
raw_printf(stderr, "usage: .shared-schema check|fix DB1 DB2...\n");
return SQLITE_ERROR;
}
#if SQLITE_SHELL_HAVE_RECOVER
/*
** This function is used as a callback by the recover extension. Simply
** print the supplied SQL statement to stdout.
@@ -10148,6 +10429,13 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(zSql);
}else
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
if( c=='s' && strncmp(azArg[0], "shared-schema", n)==0 ){
open_db(p, 0);
sharedSchemaDotCommand(p, azArg, nArg);
}else
#endif
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
if( c=='s'
&& (cli_strncmp(azArg[0], "shell", n)==0
@@ -11690,6 +11978,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( cli_strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
}else if( strcmp(z,"-sharedschema")==0 ){
data.openMode = SHELL_OPEN_SHAREDSCHEMA;
}else if( cli_strcmp(z,"-nofollow")==0 ){
data.openFlags = SQLITE_OPEN_NOFOLLOW;
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
@@ -11732,7 +12022,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
if( pVfs ){
sqlite3_vfs_register(pVfs, 1);
}else{
utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
utf8_printf(stderr, "no such VFS: \"%s\"\n", zVfs);
exit(1);
}
}
@@ -11814,6 +12104,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( cli_strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
}else if( strcmp(z,"-sharedschema")==0 ){
data.openMode = SHELL_OPEN_SHAREDSCHEMA;
}else if( cli_strcmp(z,"-nofollow")==0 ){
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
}else if( cli_strcmp(z,"-ascii")==0 ){
+9 -1
View File
@@ -612,10 +612,11 @@ int sqlite3_exec(
#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */
/* Reserved: 0x00F00000 */
#define SQLITE_OPEN_SHARED_SCHEMA 0x01000000 /* Ok for sqlite3_open_v2() */
/* Legacy compatibility: */
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
/*
** CAPI3REF: Device Characteristics
**
@@ -1192,6 +1193,12 @@ struct sqlite3_io_methods {
**
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
** Used by the cksmvfs VFS module only.
**
** <li>[[SQLITE_FCNTL_RESET_CACHE]]
** If there is currently no transaction open on the database, and the
** database is not a temp db, then this file-control purges the contents
** of the in-memory page cache. If there is an open transaction, or if
** the db is a temp-db, it is a no-op, not an error.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -1234,6 +1241,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CKPT_START 39
#define SQLITE_FCNTL_EXTERNAL_READER 40
#define SQLITE_FCNTL_CKSM_FILE 41
#define SQLITE_FCNTL_RESET_CACHE 42
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
+47
View File
@@ -1181,6 +1181,7 @@ typedef struct CteUse CteUse;
typedef struct Db Db;
typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct SchemaPool SchemaPool;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FKey FKey;
@@ -1321,6 +1322,10 @@ struct Db {
u8 safety_level; /* How aggressive at syncing data to disk */
u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */
Schema *pSchema; /* Pointer to database schema (possibly shared) */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
SchemaPool *pSPool; /* For REUSE_SCHEMA mode */
VTable *pVTable; /* List of all VTable objects (REUSE_SCHEMA mode only) */
#endif
};
/*
@@ -1352,6 +1357,9 @@ struct Schema {
u8 enc; /* Text encoding used by this database */
u16 schemaFlags; /* Flags associated with this schema */
int cache_size; /* Number of pages to use in the cache */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
Schema *pNext; /* Next Schema object SchemaPool (REUSE_SCHEMA) */
#endif
};
/*
@@ -1677,6 +1685,12 @@ struct sqlite3 {
#endif
};
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
# define IsSharedSchema(db) (((db)->openFlags & SQLITE_OPEN_SHARED_SCHEMA)!=0)
#else
# define IsSharedSchema(db) 0
#endif
/*
** A macro to discover the encoding of a database.
*/
@@ -1758,6 +1772,9 @@ struct sqlite3 {
#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */
#define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */
#define DBFLAG_SchemaInuse 0x0080 /* Do not release sharable schemas */
#define DBFLAG_FreeSchema 0x0100 /* Free extra shared schemas on release */
/*
** Bits of the sqlite3.dbOptFlags field that are used by the
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
@@ -2258,6 +2275,9 @@ struct VTable {
u8 eVtabRisk; /* Riskiness of allowing hacker access */
int iSavepoint; /* Depth of the SAVEPOINT stack */
VTable *pNext; /* Next in linked list (see above) */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
char *zName; /* Table name (REUSE_SCHEMA mode) */
#endif
};
/* Allowed values for VTable.eVtabRisk
@@ -3841,6 +3861,9 @@ struct Trigger {
Schema *pTabSchema; /* Schema containing the table */
TriggerStep *step_list; /* Link list of trigger program steps */
Trigger *pNext; /* Next trigger associated with the table */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
char *zTabSchema; /* Temp triggers in IsSharedSchema() dbs only */
#endif
};
/*
@@ -3957,6 +3980,7 @@ typedef struct {
int rc; /* Result code stored here */
u32 mInitFlags; /* Flags controlling error messages */
u32 nInitRow; /* Number of rows processed */
u64 cksum; /* Schema checksum for REUSE_SCHEMA mode */
Pgno mxPage; /* Maximum page number. 0 for no limit. */
} InitData;
@@ -5114,6 +5138,29 @@ void sqlite3DefaultRowEst(Index*);
void sqlite3RegisterLikeFunctions(sqlite3*, int);
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
void sqlite3SchemaClear(void *);
void sqlite3SchemaClearOrDisconnect(sqlite3*, int);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
int sqlite3SchemaConnect(sqlite3*, int, u64);
int sqlite3SchemaDisconnect(sqlite3 *, int, int);
Schema *sqlite3SchemaExtract(SchemaPool*);
int sqlite3SchemaLoad(sqlite3*, int, int*, char**);
void sqlite3SchemaReleaseAll(sqlite3*);
void sqlite3SchemaRelease(sqlite3*, int);
void sqlite3SchemaAdjustUsed(sqlite3*, int, int, int*);
void sqlite3SchemaWritable(Parse*, int);
void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease);
int sqlite3LockReusableSchema(sqlite3 *db);
#else
# define sqlite3SchemaWritable(x,y)
# define sqlite3UnlockReusableSchema(x,y) (void)(y)
# define sqlite3LockReusableSchema(x) 0
# define sqlite3SchemaDisconnect(x,y,z) SQLITE_OK
# define sqlite3SchemaLoad(w,x,y,z) SQLITE_OK
# define sqlite3SchemaRelease(y,z)
# define sqlite3SchemaConnect(x,y,z) SQLITE_OK
#endif
Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
+21 -1
View File
@@ -288,13 +288,26 @@ int sqlite3_db_status(
case SQLITE_DBSTATUS_SCHEMA_USED: {
int i; /* Used to iterate through schemas */
int nByte = 0; /* Used to accumulate return value */
int bReleaseSchema;
sqlite3BtreeEnterAll(db);
bReleaseSchema = sqlite3LockReusableSchema(db);
db->pnBytesFreed = &nByte;
assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
db->lookaside.pEnd = db->lookaside.pStart;
for(i=0; i<db->nDb; i++){
Schema *pSchema = db->aDb[i].pSchema;
Schema *pSchema;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
int bUnload = 0;
int nUsed = nByte;
if( db->aDb[i].pSPool ){
char *zDummy = 0;
rc = sqlite3SchemaLoad(db, i, &bUnload, &zDummy);
sqlite3_free(zDummy);
if( rc ) break;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
pSchema = db->aDb[i].pSchema;
if( ALWAYS(pSchema!=0) ){
HashElem *p;
@@ -316,7 +329,14 @@ int sqlite3_db_status(
sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
}
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( db->aDb[i].pSPool ){
if( bUnload ) sqlite3SchemaRelease(db, i);
sqlite3SchemaAdjustUsed(db, i, nUsed, &nByte);
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
}
sqlite3UnlockReusableSchema(db, bReleaseSchema);
db->pnBytesFreed = 0;
db->lookaside.pEnd = db->lookaside.pTrueEnd;
sqlite3BtreeLeaveAll(db);
+13
View File
@@ -3705,6 +3705,9 @@ static int sqliteCmdUsage(
"HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
" ?-nofollow BOOLEAN?"
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
" ?-shared-schema BOOLEAN?"
#endif
);
return TCL_ERROR;
}
@@ -3836,6 +3839,16 @@ static int SQLITE_TCLAPI DbMain(
}else{
flags &= ~SQLITE_OPEN_URI;
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
}else if( strcmp(zArg, "-shared-schema")==0 ){
int b;
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
if( b ){
flags |= SQLITE_OPEN_SHARED_SCHEMA;
}else{
flags &= ~SQLITE_OPEN_SHARED_SCHEMA;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
}else if( strcmp(zArg, "-translatefilename")==0 ){
if( Tcl_GetBooleanFromObj(interp, objv[i], &bTranslateFileName) ){
return TCL_ERROR;
+6
View File
@@ -783,6 +783,12 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
Tcl_SetVar2(interp, "sqlite_options", "sharedschema", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "sharedschema", "0", TCL_GLOBAL_ONLY);
#endif
#define LINKVAR(x) { \
static const int cv_ ## x = SQLITE_ ## x; \
Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
+282
View File
@@ -0,0 +1,282 @@
/*
** 2006 June 10
**
** 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.
**
*************************************************************************
** Code for testing the virtual table interfaces. This code
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
*/
/*
** None of this works unless we have virtual tables.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST)
#include <tcl.h>
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
#include "sqliteInt.h"
/* The code in this file defines a sqlite3 virtual-table module with
** the following schema.
*/
#define SCHEMAPOOL_SCHEMA \
"CREATE TABLE x(" \
" cksum INTEGER, " \
" nref INTEGER, " \
" nschema INTEGER, " \
" ndelete INTEGER " \
")"
#define SCHEMAPOOL_NFIELD 4
typedef struct schemapool_vtab schemapool_vtab;
typedef struct schemapool_cursor schemapool_cursor;
/* A schema table object */
struct schemapool_vtab {
sqlite3_vtab base;
};
/* A schema table cursor object */
struct schemapool_cursor {
sqlite3_vtab_cursor base;
sqlite3_int64 *aData;
int iRow;
int nRow;
};
/*
** Table destructor for the schema module.
*/
static int schemaPoolDestroy(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return 0;
}
/*
** Table constructor for the schema module.
*/
static int schemaPoolCreate(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
int rc = SQLITE_NOMEM;
schemapool_vtab *pVtab = sqlite3_malloc(sizeof(schemapool_vtab));
if( pVtab ){
memset(pVtab, 0, sizeof(schemapool_vtab));
rc = sqlite3_declare_vtab(db, SCHEMAPOOL_SCHEMA);
if( rc!=SQLITE_OK ){
sqlite3_free(pVtab);
pVtab = 0;
}
}
*ppVtab = (sqlite3_vtab *)pVtab;
return rc;
}
/*
** Open a new cursor on the schema table.
*/
static int schemaPoolOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
int rc = SQLITE_NOMEM;
schemapool_cursor *pCur;
pCur = sqlite3_malloc(sizeof(schemapool_cursor));
if( pCur ){
memset(pCur, 0, sizeof(schemapool_cursor));
*ppCursor = (sqlite3_vtab_cursor*)pCur;
rc = SQLITE_OK;
}
return rc;
}
/*
** Close a schema table cursor.
*/
static int schemaPoolClose(sqlite3_vtab_cursor *cur){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
sqlite3_free(pCur->aData);
sqlite3_free(pCur);
return SQLITE_OK;
}
/*
** Retrieve a column of data.
*/
static int schemaPoolColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
assert( i==0 || i==1 || i==2 || i==3 );
sqlite3_result_int64(ctx, pCur->aData[pCur->iRow*SCHEMAPOOL_NFIELD + i]);
return SQLITE_OK;
}
/*
** Retrieve the current rowid.
*/
static int schemaPoolRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
*pRowid = pCur->iRow + 1;
return SQLITE_OK;
}
static int schemaPoolEof(sqlite3_vtab_cursor *cur){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
return pCur->iRow>=pCur->nRow;
}
/*
** Advance the cursor to the next row.
*/
static int schemaPoolNext(sqlite3_vtab_cursor *cur){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
pCur->iRow++;
return SQLITE_OK;
}
struct SchemaPool {
int nRef; /* Number of pointers to this object */
int nDelete; /* Schema objects deleted by ReleaseAll() */
u64 cksum; /* Checksum for this Schema contents */
Schema *pSchema; /* Linked list of Schema objects */
Schema sSchema; /* The single dummy schema object */
SchemaPool *pNext; /* Next element in schemaPoolList */
};
extern SchemaPool *sqlite3SchemaPoolList(void);
/*
** Reset a schemaPool table cursor.
*/
static int schemaPoolFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
SchemaPool *pSPool;
schemapool_cursor *pCur = (schemapool_cursor*)pVtabCursor;
sqlite3_free(pCur->aData);
pCur->aData = 0;
pCur->nRow = 0;
pCur->iRow = 0;
for(pSPool = sqlite3SchemaPoolList(); pSPool; pSPool=pSPool->pNext){
pCur->nRow++;
}
if( pCur->nRow ){
int iRow = 0;
int nByte = SCHEMAPOOL_NFIELD * pCur->nRow * sizeof(i64);
pCur->aData = (i64*)sqlite3_malloc(nByte);
if( pCur->aData==0 ) return SQLITE_NOMEM;
for(pSPool = sqlite3SchemaPoolList(); pSPool; pSPool=pSPool->pNext){
Schema *p;
i64 nSchema = 0;
for(p=pSPool->pSchema; p; p=p->pNext){
nSchema++;
}
pCur->aData[0 + iRow*SCHEMAPOOL_NFIELD] = pSPool->cksum;
pCur->aData[1 + iRow*SCHEMAPOOL_NFIELD] = (i64)pSPool->nRef;
pCur->aData[2 + iRow*SCHEMAPOOL_NFIELD] = nSchema;
pCur->aData[3 + iRow*SCHEMAPOOL_NFIELD] = (i64)pSPool->nDelete;
iRow++;
}
}
return SQLITE_OK;
}
/*
** Analyse the WHERE condition.
*/
static int schemaPoolBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
return SQLITE_OK;
}
/*
** A virtual table module that merely echos method calls into TCL
** variables.
*/
static sqlite3_module schemaPoolModule = {
0, /* iVersion */
schemaPoolCreate,
schemaPoolCreate,
schemaPoolBestIndex,
schemaPoolDestroy,
schemaPoolDestroy,
schemaPoolOpen, /* xOpen - open a cursor */
schemaPoolClose, /* xClose - close a cursor */
schemaPoolFilter, /* xFilter - configure scan constraints */
schemaPoolNext, /* xNext - advance a cursor */
schemaPoolEof, /* xEof */
schemaPoolColumn, /* xColumn - read data */
schemaPoolRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
};
/*
** Decode a pointer to an sqlite3 object.
*/
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
/*
** Register the schema virtual table module.
*/
static int SQLITE_TCLAPI register_schemapool_module(
ClientData clientData, /* Not used */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
sqlite3 *db;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_create_module(db, "schemapool", &schemaPoolModule, 0);
#endif
return TCL_OK;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST) */
/*
** Register commands with the TCL interpreter.
*/
int Sqlitetestschemapool_Init(Tcl_Interp *interp){
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
static struct {
char *zName;
Tcl_ObjCmdProc *xProc;
void *clientData;
} aObjCmd[] = {
{ "register_schemapool_module", register_schemapool_module, 0 },
};
int i;
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
return TCL_OK;
}
+2
View File
@@ -77,6 +77,7 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
extern int Sqlitetest_malloc_Init(Tcl_Interp*);
extern int Sqlitetest_mutex_Init(Tcl_Interp*);
extern int Sqlitetestschema_Init(Tcl_Interp*);
extern int Sqlitetestschemapool_Init(Tcl_Interp*);
extern int Sqlitetestsse_Init(Tcl_Interp*);
extern int Sqlitetesttclvar_Init(Tcl_Interp*);
extern int Sqlitetestfs_Init(Tcl_Interp*);
@@ -149,6 +150,7 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
Sqlitetest_malloc_Init(interp);
Sqlitetest_mutex_Init(interp);
Sqlitetestschema_Init(interp);
Sqlitetestschemapool_Init(interp);
Sqlitetesttclvar_Init(interp);
Sqlitetestfs_Init(interp);
SqlitetestThread_Init(interp);
+41 -6
View File
@@ -52,23 +52,44 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
Trigger *pList; /* List of triggers to return */
HashElem *p; /* Loop variable for TEMP triggers */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
char *zSchema = 0;
sqlite3 *db = pParse->db;
if( IsSharedSchema(db) ){
zSchema = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
}
#endif
assert( pParse->disableTriggers==0 );
pTmpSchema = pParse->db->aDb[1].pSchema;
p = sqliteHashFirst(&pTmpSchema->trigHash);
pList = pTab->pTrigger;
while( p ){
Trigger *pTrig = (Trigger *)sqliteHashData(p);
if( pTrig->pTabSchema==pTab->pSchema
int bSchemaMatch;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( zSchema ){
/* Shared-schema */
bSchemaMatch = (0==sqlite3StrICmp(pTrig->zTabSchema, zSchema));
}else
#endif
{
/* Non-shared-schema */
bSchemaMatch = (pTrig->pTabSchema==pTab->pSchema);
}
if( bSchemaMatch
&& pTrig->table
&& 0==sqlite3StrICmp(pTrig->table, pTab->zName)
&& pTrig->pTabSchema!=pTmpSchema
&& (pTrig->pTabSchema!=pTmpSchema || pTrig->bReturning)
){
pTrig->pNext = pList;
pList = pTrig;
}else if( pTrig->op==TK_RETURNING ){
#ifndef SQLITE_OMIT_VIRTUALTABLE
assert( pParse->db->pVtabCtx==0 );
#endif
#endif
assert( pParse->bReturning );
assert( &(pParse->u1.pReturning->retTrig) == pTrig );
pTrig->table = pTab->zName;
@@ -258,6 +279,12 @@ void sqlite3BeginTrigger(
pTrigger->zName = zName;
zName = 0;
pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( IsSharedSchema(db) && iDb==1 ){
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pTrigger->zTabSchema = sqlite3DbStrDup(db, db->aDb[iTabDb].zDbSName);
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
pTrigger->pSchema = db->aDb[iDb].pSchema;
pTrigger->pTabSchema = pTab->pSchema;
pTrigger->op = (u8)op;
@@ -381,7 +408,7 @@ void sqlite3FinishTrigger(
pTrig->table, z);
sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0);
}
@@ -600,6 +627,9 @@ void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
sqlite3DeleteTriggerStep(db, pTrigger->step_list);
sqlite3DbFree(db, pTrigger->zName);
sqlite3DbFree(db, pTrigger->table);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
sqlite3DbFree(db, pTrigger->zTabSchema);
#endif
sqlite3ExprDelete(db, pTrigger->pWhen);
sqlite3IdListDelete(db, pTrigger->pColumns);
sqlite3DbFree(db, pTrigger);
@@ -671,6 +701,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
assert( iDb>=0 && iDb<db->nDb );
sqlite3SchemaWritable(pParse, iDb);
pTable = tableOfTrigger(pTrigger);
assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 );
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -1163,7 +1194,9 @@ static TriggerPrg *codeRowTrigger(
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
Parse sSubParse; /* Parse context for sub-vdbe */
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTrigger->zName==0 || IsSharedSchema(pParse->db)
|| pTab==tableOfTrigger(pTrigger)
);
assert( pTop->pVdbe );
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
@@ -1270,7 +1303,9 @@ static TriggerPrg *getRowTrigger(
Parse *pRoot = sqlite3ParseToplevel(pParse);
TriggerPrg *pPrg;
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTrigger->zName==0 || IsSharedSchema(pParse->db)
|| pTab==tableOfTrigger(pTrigger)
);
/* It may be that this trigger has already been coded (or is in the
** process of being coded). If this is the case, then an entry with
+1
View File
@@ -125,6 +125,7 @@ void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){
}
if( iDb!=1 ){
int iIntoReg = 0;
sqlite3SchemaWritable(pParse, iDb);
if( pInto && sqlite3ResolveSelfReference(pParse,0,0,pInto,0)==0 ){
iIntoReg = ++pParse->nMem;
sqlite3ExprCode(pParse, pInto, iIntoReg);
+7 -7
View File
@@ -3943,13 +3943,6 @@ case OP_Transaction: {
&& pOp->p5
&& (iMeta!=pOp->p3 || pDb->pSchema->iGeneration!=pOp->p4.i)
){
/*
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
** version is checked to ensure that the schema has not changed since the
** SQL statement was prepared.
*/
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
** stored with the in-memory representation of the schema, do
** not reload the schema from the database file.
@@ -3966,6 +3959,13 @@ case OP_Transaction: {
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
sqlite3ResetOneSchema(db, pOp->p1);
}
/*
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
** version is checked to ensure that the schema has not changed since the
** SQL statement was prepared.
*/
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
p->expired = 1;
rc = SQLITE_SCHEMA;
+1 -1
View File
@@ -222,7 +222,7 @@ VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
#else
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16);
void sqlite3VdbeAddParseSchemaOp(Parse*,int,char*,u16);
void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
+4 -2
View File
@@ -481,8 +481,10 @@ void sqlite3VdbeExplainPop(Parse *pParse){
** The zWhere string must have been obtained from sqlite3_malloc().
** This routine will take ownership of the allocated memory.
*/
void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
void sqlite3VdbeAddParseSchemaOp(Parse *pParse, int iDb, char *zWhere, u16 p5){
Vdbe *p = pParse->pVdbe;
int j;
sqlite3SchemaWritable(pParse, iDb);
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
sqlite3VdbeChangeP5(p, p5);
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
@@ -1457,7 +1459,7 @@ void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){
if( p->db->mallocFailed ){
freeP4(p->db, n, pP4);
}else{
assert( pP4!=0 );
assert( pP4!=0 || n==P4_DYNAMIC );
assert( p->nOp>0 );
pOp = &p->aOp[p->nOp-1];
assert( pOp->p4type==P4_NOTUSED );
+3
View File
@@ -135,6 +135,7 @@ int sqlite3_blob_open(
Table *pTab;
Incrblob *pBlob = 0;
Parse sParse;
int bUnlock; /* True to unlock reusable schemas before returning */
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppBlob==0 ){
@@ -151,6 +152,7 @@ int sqlite3_blob_open(
sqlite3_mutex_enter(db->mutex);
bUnlock = sqlite3LockReusableSchema(db);
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
while(1){
sqlite3ParseObjectInit(&sParse,db);
@@ -336,6 +338,7 @@ int sqlite3_blob_open(
}
blob_open_out:
sqlite3UnlockReusableSchema(db, bUnlock);
if( rc==SQLITE_OK && db->mallocFailed==0 ){
*ppBlob = (sqlite3_blob *)pBlob;
}else{
+47 -8
View File
@@ -192,6 +192,24 @@ void sqlite3VtabLock(VTable *pVTab){
VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
VTable *pVtab;
assert( IsVirtual(pTab) );
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( IsSharedSchema(db) ){
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
if( iDb!=1 ){
VTable **pp;
for(pp=&db->aDb[iDb].pVTable; *pp; pp=&(*pp)->pNext){
if( sqlite3StrICmp(pTab->zName, (*pp)->zName)==0 ) break;
}
pVtab = *pp;
if( pVtab && pTab->nCol<=0 ){
*pp = pVtab->pNext;
sqlite3VtabUnlock(pVtab);
pVtab = 0;
}
return pVtab;
}
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
return pVtab;
}
@@ -500,7 +518,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
sqlite3VdbeAddOp0(v, OP_Expire);
zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0);
sqlite3VdbeAddParseSchemaOp(pParse, iDb, zWhere, 0);
sqlite3DbFree(db, zStmt);
iReg = ++pParse->nMem;
@@ -570,6 +588,7 @@ static int vtabCallConstructor(
char *zModuleName;
int iDb;
VtabCtx *pCtx;
int nByte; /* Bytes of space to allocate */
assert( IsVirtual(pTab) );
azArg = (const char *const*)pTab->u.vtab.azArg;
@@ -589,7 +608,11 @@ static int vtabCallConstructor(
return SQLITE_NOMEM_BKPT;
}
pVTable = sqlite3MallocZero(sizeof(VTable));
nByte = sizeof(VTable);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
nByte += sqlite3Strlen30(pTab->zName) + 1;
#endif
pVTable = (VTable*)sqlite3MallocZero(nByte);
if( !pVTable ){
sqlite3OomFault(db);
sqlite3DbFree(db, zModuleName);
@@ -597,6 +620,10 @@ static int vtabCallConstructor(
}
pVTable->db = db;
pVTable->pMod = pMod;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
pVTable->zName = (char*)&pVTable[1];
memcpy(pVTable->zName, pTab->zName, nByte-sizeof(VTable));
#endif
pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -639,12 +666,23 @@ static int vtabCallConstructor(
int iCol;
u16 oooHidden = 0;
/* If everything went according to plan, link the new VTable structure
** into the linked list headed by pTab->u.vtab.p. Then loop through the
** columns of the table to see if any of them contain the token "hidden".
** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
** the type string. */
pVTable->pNext = pTab->u.vtab.p;
pTab->u.vtab.p = pVTable;
** into the linked list headed by pTab->u.vtab.p. Or, if this is a
** reusable schema, into the linked list headed by Db.pVTable.
**
** Then loop through the columns of the table to see if any of them
** contain the token "hidden". If so, set the Column COLFLAG_HIDDEN flag
** and remove the token from the type string. */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( IsSharedSchema(db) && iDb!=1 ){
pVTable->pNext = db->aDb[iDb].pVTable;
db->aDb[iDb].pVTable = pVTable;
}else
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
{
assert( IsVirtual(pTab) );
pVTable->pNext = pTab->u.vtab.p;
pTab->u.vtab.p = pVTable;
}
for(iCol=0; iCol<pTab->nCol; iCol++){
char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
@@ -699,6 +737,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
assert( pTab );
assert( IsVirtual(pTab) );
if( sqlite3GetVTable(db, pTab) ){
assert( !IsVirtual(pTab) || pTab->nCol>0 );
return SQLITE_OK;
}
+1 -1
View File
@@ -67,7 +67,7 @@ int sqlite3WhereIsDistinct(WhereInfo *pWInfo){
** block sorting is required.
*/
int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
return pWInfo->nOBSat;
return pWInfo->nOBSat<0 ? 0 : pWInfo->nOBSat;
}
/*
+27
View File
@@ -303,6 +303,33 @@ do_execsql_test regexp1-6.7 {SELECT 'xabc' REGEXP '(^abc|def)';} {0}
do_execsql_test regexp1-6.8 {SELECT 'def' REGEXP '(^abc|def)';} {1}
do_execsql_test regexp1-6.9 {SELECT 'xdef' REGEXP '(^abc|def)';} {1}
# 2022-11-17
# https://sqlite.org/forum/forumpost/3ffe058b04
#
do_execsql_test regexp1-7.1 {
SELECT char(0x61,0x7ff,0x62) REGEXP char(0x7ff);
} 1
do_execsql_test regexp1-7.2 {
SELECT char(0x61,0x800,0x62) REGEXP char(0x800);
} 1
do_execsql_test regexp1-7.3 {
SELECT char(0x61,0xabc,0x62) REGEXP char(0xabc);
} 1
do_execsql_test regexp1-7.4 {
SELECT char(0x61,0xfff,0x62) REGEXP char(0xfff);
} 1
do_execsql_test regexp1-7.5 {
SELECT char(0x61,0x1000,0x62) REGEXP char(0x1000);
} 1
do_execsql_test regexp1-7.10 {
SELECT char(0x61,0xffff,0x62) REGEXP char(0xffff);
} 1
do_execsql_test regexp1-7.11 {
SELECT char(0x61,0x10000,0x62) REGEXP char(0x10000);
} 1
do_execsql_test regexp1-7.12 {
SELECT char(0x61,0x10ffff,0x62) REGEXP char(0x10ffff);
} 1
finish_test
+24
View File
@@ -376,4 +376,28 @@ do_execsql_test 16.1 {
SELECT * FROM t2;
} {1 2 3 a b c}
foreach {tn temp} {
1 ""
2 TEMP
} {
reset_db
do_execsql_test 17.$tn.0 "
CREATE $temp TABLE foo (
fooid INTEGER PRIMARY KEY,
fooval INTEGER NOT NULL UNIQUE,
refcnt INTEGER NOT NULL DEFAULT 1
);
"
do_execsql_test 17.$tn.1 {
INSERT INTO foo (fooval) VALUES (17), (4711), (17)
ON CONFLICT DO
UPDATE SET refcnt = refcnt+1
RETURNING fooid;
} {
1 2 1
}
}
finish_test
+394
View File
@@ -0,0 +1,394 @@
# 2017 August 9
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reuse1
ifcapable !sharedschema {
finish_test
return
}
forcedelete test.db2
sqlite3 db2 test.db2
do_execsql_test 1.0 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
CREATE INDEX i1 ON t1(z);
PRAGMA schema_version;
} {2}
do_execsql_test -db db2 1.1 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
CREATE INDEX i1 ON t1(z);
PRAGMA schema_version;
} {2}
do_test 1.2 {
db close
db2 close
sqlite3 db2 test.db2 -shared-schema 1
sqlite3 db test.db -shared-schema 1
} {}
do_execsql_test -db db2 1.3.1 {
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
}
do_execsql_test 1.3.2 {
SELECT * FROM t1;
PRAGMA integrity_check;
} {ok}
do_execsql_test -db db2 1.3.3 {
SELECT * FROM t1;
PRAGMA integrity_check;
} {1 2 3 4 5 6 ok}
sqlite3 db3 test.db2
do_execsql_test -db db3 1.4.1 {
ALTER TABLE t1 ADD COLUMN a;
}
do_execsql_test -db db2 1.4.2 {
SELECT * FROM t1;
} {1 2 3 {} 4 5 6 {}}
do_execsql_test 1.4.3 {
SELECT * FROM t1;
} {}
db3 close
sqlite3 db3 test.db
do_execsql_test -db db3 1.5.0 {
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
SELECT 1, 2, 3;
END;
}
# Check that the schema cannot be modified if the db was opened with
# SQLITE_OPEN_REUSE_SCHEMA.
#
foreach {tn sql} {
1 { CREATE TABLE t2(x, y) }
2 { CREATE INDEX i2 ON t1(z) }
3 { CREATE VIEW v2 AS SELECT * FROM t2 }
4 { ALTER TABLE t1 RENAME TO t3 }
5 { ALTER TABLE t1 ADD COLUMN xyz }
6 { VACUUM }
7 { DROP INDEX i1 }
8 { DROP TABLE t1 }
9 { DROP TRIGGER tr1 }
10 { ANALYZE }
11 { ALTER TABLE t1 RENAME z TO zzz }
} {
do_catchsql_test 1.5.$tn $sql {1 {attempt to modify read-only schema}}
}
#-------------------------------------------------------------------------
#
reset_db
forcedelete test.db2
ifcapable fts5 {
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE ft USING fts5(a);
INSERT INTO ft VALUES('one'), ('two'), ('three');
ATTACH 'test.db2' AS aux;
CREATE VIRTUAL TABLE aux.ft USING fts5(a);
INSERT INTO aux.ft VALUES('aux1'), ('aux2'), ('aux3');
}
db close
sqlite3 db test.db -shared-schema 1
do_execsql_test 2.1 {
ATTACH 'test.db2' AS aux;
SELECT * FROM main.ft;
} {one two three}
breakpoint
do_execsql_test 2.2 {
SELECT * FROM aux.ft;
} {aux1 aux2 aux3}
do_execsql_test 2.2 {
SELECT * FROM aux.ft_content;
} {1 aux1 2 aux2 3 aux3}
}
#-------------------------------------------------------------------------
#
reset_db
forcedelete test.db2
do_execsql_test 3.0 {
CREATE TABLE t1(a PRIMARY KEY, b, c);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TRIGGER v1_ins INSTEAD OF INSERT ON v1 BEGIN
INSERT INTO t1 VALUES(new.a, new.b, new.c);
END;
CREATE TRIGGER v1_del INSTEAD OF DELETE ON v1 BEGIN
DELETE FROM t1 WHERE a=old.a;
END;
CREATE TRIGGER v1_up INSTEAD OF UPDATE ON v1 BEGIN
UPDATE t1 SET a=new.a, b=new.b, c=new.c WHERE a=old.a;
END;
}
forcecopy test.db test.db2
do_test 3.1 {
sqlite3 db2 test.db2
execsql { INSERT INTO t1 VALUES(1, 2, 3) } db
execsql { INSERT INTO t1 VALUES(4, 5, 6) } db2
db2 close
execsql { ATTACH 'test.db2' AS aux; }
} {}
do_execsql_test 3.2 {
SELECT * FROM main.v1;
} {1 2 3}
do_execsql_test 3.3 {
SELECT * FROM aux.v1;
} {4 5 6}
db close
sqlite3 db test.db -shared-schema 1
do_execsql_test 3.4 { ATTACH 'test.db2' AS aux } {}
do_execsql_test 3.5 { SELECT * FROM main.v1 } {1 2 3}
do_execsql_test 3.6 { SELECT * FROM aux.v1 } {4 5 6}
do_execsql_test 3.7.1 { INSERT INTO aux.t1 VALUES(8, 9, 10); }
do_execsql_test 3.7.2 { SELECT * FROM main.v1 } {1 2 3}
do_execsql_test 3.7.3 { SELECT * FROM aux.v1 } {4 5 6 8 9 10}
do_execsql_test 3.8.1 { DELETE FROM aux.t1 WHERE b=5 }
do_execsql_test 3.8.2 { SELECT * FROM main.v1 } {1 2 3}
do_execsql_test 3.8.3 { SELECT * FROM aux.v1 } {8 9 10}
do_execsql_test 3.9.1 { UPDATE aux.t1 SET b='abc' }
do_execsql_test 3.9.2 { SELECT * FROM main.v1 } {1 2 3}
do_execsql_test 3.9.3 { SELECT * FROM aux.v1 } {8 abc 10}
do_execsql_test 3.10.1 { INSERT INTO aux.v1 VALUES(11, 12, 13) }
do_execsql_test 3.10.2 { SELECT * FROM main.v1 } {1 2 3}
do_execsql_test 3.10.3 { SELECT * FROM aux.v1 } {8 abc 10 11 12 13}
do_execsql_test 3.11.1 { DELETE FROM aux.v1 WHERE b='abc' }
do_execsql_test 3.11.2 { SELECT * FROM main.v1 } {1 2 3}
do_execsql_test 3.11.3 { SELECT * FROM aux.v1 } {11 12 13}
do_execsql_test 3.12.1 { UPDATE aux.v1 SET b='def' }
do_execsql_test 3.12.2 { SELECT * FROM main.v1 } {1 2 3}
do_execsql_test 3.12.3 { SELECT * FROM aux.v1 } {11 def 13}
do_execsql_test 3.13.1 {
CREATE TEMP TRIGGER xyz AFTER INSERT ON aux.t1 BEGIN
INSERT INTO v1 VALUES(new.a, new.b, new.c);
END
}
do_execsql_test 3.13.2 {
INSERT INTO aux.v1 VALUES('x', 'y', 'z');
}
do_execsql_test 3.13.3 {
SELECT * FROM v1;
} {1 2 3 x y z}
#-------------------------------------------------------------------------
#
reset_db
forcedelete test.db2
do_execsql_test 4.0 {
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
CREATE TABLE del(a, b, c);
CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN
INSERT INTO del VALUES(old.a, old.b, old.c);
END;
}
forcecopy test.db test.db2
db close
sqlite3 db test.db -shared-schema 1
execsql {
ATTACH 'test.db2' AS aux;
PRAGMA recursive_triggers = 1;
}
do_execsql_test 4.1 {
INSERT INTO main.t1 VALUES(1, 2, 3);
INSERT INTO aux.t1 VALUES(4, 5, 6);
}
do_execsql_test 4.2.1 {
INSERT OR REPLACE INTO aux.t1 VALUES('a', 'b', 6);
SELECT * FROM aux.t1;
} {a b 6}
do_execsql_test 4.2.2 { SELECT * FROM aux.del } {4 5 6}
do_execsql_test 4.2.3 { SELECT * FROM main.del } {}
do_execsql_test 4.3.1 {
INSERT INTO aux.t1 VALUES('x', 'y', 'z');
UPDATE OR REPLACE aux.t1 SET c='z' WHERE a='a';
} {}
do_execsql_test 4.3.2 { SELECT * FROM aux.del } {4 5 6 x y z}
do_execsql_test 4.3.3 { SELECT * FROM main.del } {}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b);
INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6);
ANALYZE;
PRAGMA writable_schema = 1;
DELETE FROM sqlite_stat1;
}
db close
forcecopy test.db test.db2
sqlite3 db test.db -shared-schema 1
execsql { ATTACH 'test.db2' AS aux }
foreach {tn sql} {
1 { CREATE TABLE t3(x) }
2 { DROP TABLE t2 }
3 { CREATE INDEX i2 ON t2(b) }
4 { DROP INDEX i1 }
5 { ALTER TABLE t1 ADD COLUMN d }
6 { ALTER TABLE t1 RENAME TO t3 }
7 { ALTER TABLE t1 RENAME c TO d }
} {
do_catchsql_test 5.1.$tn $sql {1 {attempt to modify read-only schema}}
}
do_execsql_test 5.2.1 { ANALYZE aux.t1 } {}
do_execsql_test 5.2.2 { SELECT * FROM aux.sqlite_stat1 } {t1 i1 {2 1}}
do_execsql_test 5.2.3 { SELECT * FROM main.sqlite_stat1 } {}
do_test 5.3.0 {
sqlite3 db2 test.db2
db2 eval {
PRAGMA writable_schema = 1;
DELETE FROM sqlite_stat1;
}
} {}
do_execsql_test 5.3.1 { SELECT * FROM aux.sqlite_stat1 } {}
do_execsql_test 5.3.2 { ANALYZE aux } {}
do_execsql_test 5.3.3 { SELECT * FROM aux.sqlite_stat1 } {t1 i1 {2 1}}
do_execsql_test 5.3.4 { SELECT * FROM main.sqlite_stat1 } {}
#-------------------------------------------------------------------------
# Attempting to run ANALYZE when the required sqlite_statXX functions
# are missing is an error (because it would modify the database schema).
#
reset_db
do_execsql_test 5.4 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b);
INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6);
}
db close
sqlite3 db test.db -shared-schema 1
foreach {tn sql} {
1 { ANALYZE }
2 { ANALYZE t1 }
3 { ANALYZE i1 }
4 { ANALYZE main }
5 { ANALYZE main.t1 }
6 { ANALYZE main.i1 }
} {
do_catchsql_test 5.4.$tn $sql {1 {attempt to modify read-only schema}}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 6.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE VIEW v1 AS SELECT * FROM t1;
}
db close
forcecopy test.db test.db2
sqlite3 db test.db -shared-schema 1
execsql { ATTACH 'test.db2' AS aux }
do_execsql_test 6.1 {
INSERT INTO main.t1(a) VALUES(1), (2), (3);
INSERT INTO aux.t1(a) VALUES(4), (5), (6);
CREATE TEMP TABLE t2(i,t);
INSERT INTO t2 VALUES(2, 'two'), (5, 'five');
}
do_execsql_test 6.2 {
SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.t1)
} {five}
do_execsql_test 6.3 {
SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.v1)
} {five}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.0 {
CREATE TABLE p1(a PRIMARY KEY, b);
CREATE TABLE p2(a PRIMARY KEY, b);
CREATE TABLE c1(x REFERENCES p1 ON UPDATE CASCADE ON DELETE CASCADE);
}
db close
forcecopy test.db test.db2
sqlite3 db test.db -shared-schema 1
execsql { ATTACH 'test.db2' AS aux }
do_execsql_test 7.1 {
INSERT INTO aux.p1 VALUES(1, 'one');
INSERT INTO aux.p1 VALUES(2, 'two');
PRAGMA foreign_keys = on;
}
do_execsql_test 7.2 {
INSERT INTO aux.c1 VALUES(2);
}
do_execsql_test 7.3.1 {
PRAGMA foreign_keys = off;
INSERT INTO main.p2 SELECT * FROM aux.p1;
}
do_execsql_test 7.3.2 {
SELECT * FROM main.p2;
} {1 one 2 two}
do_execsql_test 7.3.3 {
INSERT INTO aux.p2 VALUES(1, 2);
}
do_execsql_test 7.3.4 {
SELECT main.p2.a FROM main.p2, aux.p2;
} {1 2}
do_execsql_test 7.3.5 {
SELECT * FROM main.p2, aux.p2;
} {1 one 1 2 2 two 1 2}
do_execsql_test 7.4 {
SELECT count(*) FROM aux.p2;
} {1}
finish_test
+336
View File
@@ -0,0 +1,336 @@
# 2017 August 9
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reuse2
ifcapable !sharedschema {
finish_test
return
}
do_execsql_test 1.0 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
CREATE INDEX i1 ON t1(z);
PRAGMA schema_version;
} {2}
do_test 1.2 {
catch { db close }
catch { db2 close }
sqlite3 db2 test.db -shared-schema 1
sqlite3 db test.db -shared-schema 1
} {}
do_execsql_test -db db2 1.3.1 {
INSERT INTO t1 VALUES(1, 2, 3);
}
do_execsql_test -db db2 1.3.2 {
INSERT INTO t1 VALUES(4, 5, 6);
}
do_execsql_test 1.3.3 {
SELECT * FROM t1;
} {1 2 3 4 5 6}
#--------------------------------------------------------------------------
reset_db
ifcapable fts5 {
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE ft USING fts5(c);
INSERT INTO ft VALUES('one two three');
}
db close
sqlite3 db test.db -shared-schema 1
do_execsql_test 2.1 {
SELECT * FROM ft
} {{one two three}}
}
#--------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
CREATE INDEX i1 ON t1(z);
PRAGMA schema_version;
} {2}
do_test 3.1 {
sqlite3 db1 test.db -shared-schema 1
sqlite3 db2 test.db -shared-schema 1
} {}
do_execsql_test -db db1 3.2.1 { SELECT * FROM t1 }
do_execsql_test -db db2 3.2.2 { SELECT * FROM t1 }
register_schemapool_module db
do_execsql_test 3.3 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=2 nschema=1 ndelete=0}
sqlite3 db3 test.db -shared-schema 1
register_schemapool_module db3
do_execsql_test 3.5 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=2 nschema=1 ndelete=0}
do_execsql_test -db db3 3.6 {
SELECT * FROM t1;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=3 nschema=1 ndelete=0}
do_execsql_test 3.7 {
CREATE TABLE t2(x);
}
do_execsql_test 3.8 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=3 nschema=1 ndelete=0}
do_execsql_test -db db1 3.9.1 { SELECT * FROM t1 }
do_execsql_test 3.9.2 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=1 nschema=1 ndelete=0 nref=2 nschema=1 ndelete=0}
do_execsql_test -db db2 3.10.1 { SELECT * FROM t1 }
do_execsql_test 3.10.2 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool ORDER BY 1;
} {nref=1 nschema=1 ndelete=0 nref=2 nschema=1 ndelete=0}
do_execsql_test -db db3 3.11.1 { SELECT * FROM t1 }
do_execsql_test 3.11.2 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=3 nschema=1 ndelete=0}
#--------------------------------------------------------------------------
catch {db1 close}
catch {db2 close}
catch {db3 close}
reset_db
do_execsql_test 4.0.1 {
CREATE TABLE x1(a, b, c);
CREATE INDEX x1a ON x1(a);
CREATE INDEX x1b ON x1(b);
}
do_test 4.0.2 {
db close
for {set i 1} {$i < 6} {incr i} {
forcedelete test.db${i}-journal test.db${i}-wal test.db${i}-wal2
forcecopy test.db test.db${i}
}
sqlite3 db test.db
sqlite3 db2 test.db -shared-schema 1
} {}
register_schemapool_module db
do_execsql_test 4.0.3 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {}
do_test 4.1.1 {
execsql {
ATTACH 'test.db1' AS db1;
ATTACH 'test.db2' AS db2;
ATTACH 'test.db3' AS db3;
ATTACH 'test.db4' AS db4;
ATTACH 'test.db5' AS db5;
} db2
} {}
do_execsql_test 4.1.2 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {}
do_execsql_test -db db2 4.1.3 {
SELECT * FROM db3.x1
}
do_execsql_test 4.1.4 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=1 nschema=1 ndelete=0}
do_execsql_test -db db2 4.1.5 {
SELECT * FROM db2.x1
}
do_execsql_test 4.1.6 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=2 nschema=1 ndelete=0}
do_execsql_test -db db2 4.1.7 {
SELECT * FROM x1
}
do_execsql_test 4.1.8 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=6 nschema=1 ndelete=0}
do_test 4.2.1 {
catchsql { SELECT * FROM abc } db2
} {1 {no such table: abc}}
do_execsql_test 4.2.2 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=6 nschema=1 ndelete=0}
register_schemapool_module db2
do_execsql_test -db db2 4.3.1 {
INSERT INTO x1 VALUES(1, 2, 3);
INSERT INTO db1.x1 VALUES(4, 5, 6);
INSERT INTO db2.x1 VALUES(7, 8, 9);
INSERT INTO db3.x1 VALUES(10, 11, 12);
INSERT INTO db4.x1 VALUES(13, 14, 15);
INSERT INTO db5.x1 VALUES(16, 17, 18);
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=6 nschema=1 ndelete=0}
do_execsql_test -db db2 4.3.2 {
SELECT * FROM db5.x1;
SELECT * FROM db4.x1;
SELECT * FROM db3.x1;
SELECT * FROM db2.x1;
SELECT * FROM db1.x1;
SELECT * FROM x1;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {
16 17 18 13 14 15 10 11 12 7 8 9 4 5 6 1 2 3
nref=6 nschema=1 ndelete=0
}
do_execsql_test -db db2 4.3.3 {
UPDATE x1 SET a=a+10;
UPDATE db5.x1 SET a=a+10;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {
nref=6 nschema=1 ndelete=0
}
do_execsql_test -db db2 4.3.4 {
SELECT * FROM db5.x1;
SELECT * FROM db4.x1;
SELECT * FROM db3.x1;
SELECT * FROM db2.x1;
SELECT * FROM db1.x1;
SELECT * FROM x1;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {
26 17 18 13 14 15 10 11 12 7 8 9 4 5 6 11 2 3
nref=6 nschema=1 ndelete=0
}
do_execsql_test -db db2 4.3.5 {
DELETE FROM db3.x1;
DELETE FROM x1;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {
nref=6 nschema=1 ndelete=0
}
do_execsql_test -db db2 4.3.6 {
SELECT * FROM db5.x1;
SELECT * FROM db4.x1;
SELECT * FROM db3.x1;
SELECT * FROM db2.x1;
SELECT * FROM db1.x1;
SELECT * FROM x1;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {
26 17 18 13 14 15 7 8 9 4 5 6
nref=6 nschema=1 ndelete=0
}
do_execsql_test -db db2 4.3.6 {
SELECT * FROM db5.x1, db4.x1, db1.x1;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {26 17 18 13 14 15 4 5 6 nref=6 nschema=3 ndelete=0}
#--------------------------------------------------------------------------
# Test the incremental-blob API with REUSE_SCHEMA connections.
#
catch {db1 close}
catch {db2 close}
catch {db3 close}
reset_db
do_execsql_test 5.0.1 {
CREATE TABLE bbb(a INTEGER PRIMARY KEY, b);
}
db close
do_test 5.0.2 {
sqlite3 db2 test.db -shared-schema 1
register_schemapool_module db2
for {set i 1} {$i<6} {incr i} {
forcedelete test.db${i}-journal test.db${i}-wal test.db${i}-wal2
forcecopy test.db test.db${i}
sqlite3 db test.db${i}
db eval { INSERT INTO bbb VALUES(123, 'database_' || $i) }
db close
db2 eval "ATTACH 'test.db${i}' AS db${i}"
}
execsql {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} db2
} {nref=6 nschema=1 ndelete=0}
do_test 5.1.1 {
set res [list]
for {set i 1} {$i<6} {incr i} {
set chan [db2 incrblob db${i} bbb b 123]
lappend res [gets $chan]
close $chan
}
set res
} {database_1 database_2 database_3 database_4 database_5}
do_execsql_test -db db2 5.1.2 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=6 nschema=1 ndelete=0}
do_test 5.2.1 {
sqlite3_table_column_metadata db2 main bbb a
} {INTEGER BINARY 0 1 0}
do_test 5.2.2 {
sqlite3_table_column_metadata db2 main bbb b
} {{} BINARY 0 0 0}
do_execsql_test -db db2 5.2.3 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=6 nschema=1 ndelete=0}
do_execsql_test -db db2 5.2.4 {
PRAGMA integrity_check;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {ok nref=6 nschema=1 ndelete=5}
finish_test
+355
View File
@@ -0,0 +1,355 @@
# 2019 February 12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reuse3
ifcapable !sharedschema {
finish_test
return
}
do_execsql_test 1.0 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
CREATE INDEX i1 ON t1(z);
CREATE TABLE t2(a);
} {}
db close
sqlite3 db test.db -shared-schema 1
do_execsql_test 1.1 {
CREATE TEMP VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1;
}
do_execsql_test 1.2 {
CREATE TEMP TRIGGER tr1 AFTER INSERT ON t1 BEGIN
INSERT INTO t2 VALUES(new.x);
END;
}
do_execsql_test 1.3 {
INSERT INTO t1 VALUES(1, 2, 3);
}
do_execsql_test 1.4 {
SELECT * FROM t2
} {1}
do_execsql_test 1.5 {
SELECT * FROM v1
} {1 2 3}
do_execsql_test 1.6 {
BEGIN;
DROP TRIGGER tr1;
ROLLBACK;
}
do_execsql_test 1.7 {
SELECT * FROM v1
} {1 2 3}
do_execsql_test 1.8 {
INSERT INTO t1 VALUES(4, 5, 6);
SELECT * FROM t2
} {1 4}
do_execsql_test 1.9 {
SELECT * FROM v1
} {1 2 3 4 5 6}
#-------------------------------------------------------------------------
# Test error messages when parsing the schema with a REUSE_SCHEMA
# connection.
reset_db
do_execsql_test 2.0 {
CREATE TABLE x1(a, b, c);
CREATE TABLE y1(d, e, f);
PRAGMA writable_schema = 1;
UPDATE sqlite_master SET sql = 'CREATE TBL y1(d, e, f)' WHERE name = 'y1';
}
db close
sqlite3 db test.db -shared-schema 1
do_catchsql_test 2.1 {
SELECT * FROM x1;
} {1 {malformed database schema (y1) - near "TBL": syntax error}}
do_catchsql_test 2.2 {
SELECT * FROM x1;
} {1 {malformed database schema (y1) - near "TBL": syntax error}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
CREATE TABLE x1(a, b, c);
CREATE INDEX i1 ON x1(a, b, c);
CREATE TRIGGER tr1 AFTER INSERT ON x1 BEGIN
SELECT 1, 2, 3, 4, 5;
END;
INSERT INTO x1 VALUES(1, 2, 3);
}
sqlite3 db1 test.db -shared-schema 1
do_test 3.1 {
execsql { SELECT * FROM x1 } db1
set N [lindex [sqlite3_db_status db1 SCHEMA_USED 0] 1]
expr $N==$N
} 1
sqlite3 db2 test.db -shared-schema 1
do_test 3.2 {
execsql { SELECT * FROM x1 } db2
set N2 [lindex [sqlite3_db_status db2 SCHEMA_USED 0] 1]
expr $N2>($N/2) && $N2<($N/2)+400
} 1
sqlite3 db3 test.db -shared-schema 1
sqlite3 db4 test.db -shared-schema 1
do_test 3.3 {
execsql { SELECT * FROM x1 } db3
execsql { SELECT * FROM x1 } db4
set N4 [lindex [sqlite3_db_status db2 SCHEMA_USED 0] 1]
set M [expr 2*($N-$N2)]
set {} {}
} {}
do_test 3.3.1 { expr {(($M / 4) + $N-$M)} } "#/$N4/"
catch { db1 close }
catch { db2 close }
catch { db3 close }
catch { db4 close }
#-------------------------------------------------------------------------
# 4.1 Test the REINDEX command.
# 4.2 Test CREATE TEMP ... commands.
#
reset_db
do_execsql_test 4.1.0 {
CREATE TABLE x1(a, b, c);
CREATE INDEX x1a ON x1(a);
CREATE INDEX x1b ON x1(b);
CREATE INDEX x1c ON x1(c);
}
db close
sqlite3 db test.db -shared-schema 1
do_execsql_test 4.1.1 {
REINDEX x1;
REINDEX x1a;
REINDEX x1b;
REINDEX x1c;
REINDEX;
}
do_test 4.1.2 {
for {set i 1} {$i < 5} {incr i} {
forcedelete test.db${i} test.db${i}-wal test.db${i}-journal
forcecopy test.db test.db${i}
execsql "ATTACH 'test.db${i}' AS db${i}"
}
register_schemapool_module db
set {} {}
execsql {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool
}
} {nref=5 nschema=1 ndelete=0}
do_execsql_test 4.1.3 {
REINDEX x1;
REINDEX x1a;
REINDEX x1b;
REINDEX x1c;
REINDEX db1.x1a;
REINDEX db2.x1b;
REINDEX db3.x1c;
}
do_execsql_test 4.1.4 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool
} {nref=5 nschema=1 ndelete=28}
#-------------------------------------------------------------------------
db close
sqlite3 db test.db -shared-schema 1
register_schemapool_module db
do_execsql_test 4.2.0 {
ATTACH 'test.db1' AS db1;
ATTACH 'test.db2' AS db2;
ATTACH 'test.db3' AS db3;
ATTACH 'test.db4' AS db4;
SELECT * FROM db1.x1;
SELECT * FROM db2.x1;
SELECT * FROM db3.x1;
SELECT * FROM db4.x1;
}
do_execsql_test 4.2.1 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=5 nschema=1 ndelete=0}
do_execsql_test 4.2.2 {
CREATE TEMP TABLE t1(a, b, c);
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=5 nschema=1 ndelete=0}
do_execsql_test 4.2.3 {
CREATE INDEX t1a ON t1(a);
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=5 nschema=1 ndelete=0}
do_execsql_test 4.2.4 {
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
SELECT 1,2,3,4;
END;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=5 nschema=1 ndelete=0}
do_execsql_test 4.2.5 {
DROP TABLE t1;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=5 nschema=1 ndelete=0}
do_execsql_test 4.2.6 {
CREATE TEMP TRIGGER tr1 AFTER INSERT ON db2.x1 BEGIN
SELECT 1,2,3,4;
END;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=5 nschema=1 ndelete=0}
do_execsql_test 4.2.7 {
DROP TRIGGER tr1;
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
FROM schemapool;
} {nref=5 nschema=1 ndelete=4}
#--------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(a, b);
CREATE TABLE t3(a, b);
}
sqlite3 db2 test.db -shared-schema 1
register_schemapool_module db2
do_execsql_test 5.1 {
PRAGMA writable_schema = 1;
UPDATE sqlite_master SET sql='CREATE TABLE t3 a,b' WHERE name = 't3';
}
do_test 5.2 {
catchsql { SELECT * FROM t1 } db2
} {1 {malformed database schema (t3) - near "a": syntax error}}
do_test 5.3 {
catchsql { SELECT nref,nschema FROM schemapool } db2
} {1 {vtable constructor failed: schemapool}}
do_execsql_test 5.4 {
PRAGMA writable_schema = 1;
UPDATE sqlite_master SET sql='CREATE TABLE t3(a,b)' WHERE name = 't3';
}
do_test 5.5 {
catchsql { SELECT nref,nschema FROM schemapool } db2
} {0 {1 1}}
db2 close
db close
do_test 5.6.1 {
forcedelete test.db2 test.db2-wal test.db2-journal
forcecopy test.db test.db2
sqlite3 db test.db
sqlite3 db2 test.db -shared-schema 1
sqlite3 db3 test.db2 -shared-schema 1
register_schemapool_module db
} {}
do_execsql_test -db db2 5.6.2 { SELECT * FROM t1 }
do_execsql_test -db db3 5.6.3 { SELECT * FROM t1 }
do_execsql_test 5.6.4 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool;
CREATE TABLE t4(x);
DROP TABLE t4;
} {nref=2 nschema=1}
do_execsql_test -db db2 5.6.5 { SELECT * FROM t1 }
do_execsql_test -db db3 5.6.6 { SELECT * FROM t1 }
do_execsql_test 5.6.7 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool;
ATTACH 'test.db2' AS db2;
CREATE TABLE db2.t4(x);
DROP TABLE db2.t4;
} {nref=1 nschema=1 nref=1 nschema=1}
do_execsql_test -db db2 5.6.8 { SELECT * FROM t1 }
do_execsql_test -db db3 5.6.9 { SELECT * FROM t1 }
do_execsql_test 5.6.10 {
SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool;
} {nref=2 nschema=1}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(a, b);
CREATE TABLE t3(a, b);
}
do_test 6.1 {
db close
sqlite3 db test.db -shared-schema 1
for {set i 1} {$i < 5} {incr i} {
set base "test.db$i"
set nm "aux$i"
forcedelete $base $base-wal $base-journal
forcecopy test.db $base
execsql "ATTACH '$base' AS $nm"
}
} {}
do_test 6.2 {
set N1 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
set N2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
expr ($N1==0 && $N2==0)
} {1}
do_test 6.3 {
execsql { SELECT * FROM main.t1 }
set N1 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
set N2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
expr {$N1>0 && $N2>0 && $N1==$N2}
} {1}
do_test 6.4 {
execsql { SELECT * FROM aux1.t1 }
set N3 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
set N4 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
list $N3 $N4
} "#/$N1 $N1/"
finish_test
+173
View File
@@ -0,0 +1,173 @@
# 2019 February 12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reuse4
ifcapable !sharedschema {
finish_test
return
}
foreach {tn sharedschema} {
1 0
2 1
} {
reset_db
do_execsql_test 1.$tn.0 {
CREATE TABLE x1(a, b);
CREATE INDEX x1a ON x1(a);
CREATE INDEX x1b ON x1(b);
CREATE TABLE x2(a, b);
}
db close
do_test 1.$tn.1 {
for {set i 1} {$i<4} {incr i} {
forcedelete test.db$i test.db$i-journal test.db$i-wal
forcecopy test.db test.db$i
}
sqlite3 db test.db -shared-schema $sharedschema
for {set i 1} {$i<4} {incr i} {
execsql " ATTACH 'test.db$i' AS db$i "
}
} {}
do_execsql_test 1.$tn.2 {
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10 )
INSERT INTO x1 SELECT i, i FROM s;
INSERT INTO db3.x2 SELECT * FROM x1;
INSERT INTO db2.x1 SELECT * FROM db3.x2;
CREATE TEMP TRIGGER tr1 AFTER INSERT ON db2.x2 BEGIN
INSERT INTO x1 VALUES(new.a, new.b);
END;
INSERT INTO db2.x2 SELECT * FROM x1 WHERE a%2;
DELETE FROM x1 WHERE a<3;
INSERT INTO db3.x1 SELECT * FROM db2.x2;
DETACH db3;
ATTACH 'test.db3' AS db3;
UPDATE db3.x1 SET a=a-10 WHERE b NOT IN (SELECT b FROM db2.x2);
CREATE TEMP TABLE x1(a, b);
INSERT INTO db2.x2 VALUES(50, 60), (60, 70), (80, 90);
ALTER TABLE x1 RENAME TO x2;
ALTER TABLE x2 ADD COLUMN c;
ALTER TABLE x2 RENAME a TO aaa;
DELETE FROM x1 WHERE b>8;
UPDATE db3.x2 SET b=b*10;
BEGIN;
CREATE TEMP TABLE x5(x);
INSERT INTO x5 VALUES(1);
ROLLBACK;
INSERT INTO main.x2 VALUES(123, 456);
}
integrity_check 1.$tn.3
do_execsql_test 1.$tn.4 {
SELECT * FROM main.x1; SELECT 'xxx';
SELECT * FROM main.x2; SELECT 'xxx';
SELECT * FROM temp.x2; SELECT 'xxx';
SELECT * FROM db1.x1; SELECT 'xxx';
SELECT * FROM db1.x2; SELECT 'xxx';
SELECT * FROM db2.x1; SELECT 'xxx';
SELECT * FROM db2.x2; SELECT 'xxx';
SELECT * FROM db3.x1; SELECT 'xxx';
SELECT * FROM db3.x2; SELECT 'xxx';
} {
3 3 4 4 5 5 6 6 7 7 8 8 3 3 5 5 7 7 xxx
123 456 xxx
50 60 {} 60 70 {} 80 90 {} xxx
xxx
xxx
1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 xxx
1 1 3 3 5 5 7 7 9 9 50 60 60 70 80 90 xxx
1 1 3 3 5 5 7 7 9 9 xxx
1 10 2 20 3 30 4 40 5 50 6 60 7 70 8 80 9 90 10 100 xxx
}
do_test 1.$tn.5.1 {
sqlite3 db2 test.db
db2 eval { CREATE TABLE x3(x) }
} {}
do_execsql_test 1.$tn.5.2 {
SELECT * FROM main.x1; SELECT 'xxx';
SELECT * FROM main.x2; SELECT 'xxx';
SELECT * FROM main.x3; SELECT 'xxx';
} {
3 3 4 4 5 5 6 6 7 7 8 8 3 3 5 5 7 7 xxx
123 456 xxx
xxx
}
}
#-------------------------------------------------------------------------
# Test some PRAGMA statements with shared-schema connections.
#
reset_db
do_execsql_test 2.0 {
CREATE TABLE t1(a, b, c);
CREATE INDEX t1abc ON t1(a, b, c);
}
foreach {tn pragma nSchema nDelete} {
1 "PRAGMA synchronous = OFF" 1 0
2 "PRAGMA cache_size = 200" 1 0
3 "PRAGMA aux2.integrity_check" 1 0
4 "PRAGMA integrity_check" 1 5
5 "PRAGMA index_info=t1abc" 1 5
6 "PRAGMA aux3.index_info=t1abc" 1 0
7 "PRAGMA journal_mode" 1 0
8 "PRAGMA aux2.wal_checkpoint" 1 0
9 "PRAGMA wal_checkpoint" 1 0
} {
do_test 2.$tn.1 {
catch { db close }
catch { db2 close }
for {set i 1} {$i < 6} {incr i} {
forcedelete "test.db$i" "test.db${i}-wal" "test.db${i}-journal"
forcecopy test.db test.db$i
}
sqlite3 db2 test.db -shared-schema 1
for {set i 1} {$i < 6} {incr i} {
execsql "ATTACH 'test.db$i' AS aux$i" db2
}
} {}
sqlite3 db test.db
register_schemapool_module db
do_test 2.$tn.2 {
execsql $pragma db2
execsql { SELECT 'nschema='||nschema, 'ndelete='||nDelete FROM schemapool }
} "nschema=$nSchema ndelete=$nDelete"
do_test 2.$tn.3 {
execsql {
SELECT * FROM main.t1,aux1.t1,aux2.t1,aux3.t1,aux4.t1,aux5.t1
} db2
execsql { SELECT 'nschema=' || nschema, 'nref=' || nref FROM schemapool }
} "nschema=6 nref=6"
}
finish_test
+125
View File
@@ -0,0 +1,125 @@
# 2019 February 26
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reuse5
set CLI [test_find_cli]
ifcapable !sharedschema {
finish_test
return
}
do_execsql_test 1.0 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(a, b, c);
CREATE INDEX t1x ON t1(x);
CREATE INDEX t1y ON t1(y);
CREATE VIEW v1 AS SELECT * FROM t2;
}
foreach {tn sql out1 out2} {
1 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(a, b, c);
CREATE INDEX t1x ON t1(x);
CREATE INDEX t1y ON t1(y);
CREATE VIEW v1 AS SELECT * FROM t2;
} {
test.db2 is compatible
} {}
2 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(a, b, c);
CREATE INDEX t1x ON t1(x);
CREATE INDEX t1y ON t1(y);
CREATE VIEW v1 AS SELECT * FROM t2;
CREATE TABLE x1(x);
DROP TABLE x1;
} {
test.db2 is NOT compatible (schema cookie)
} {
Fixing test.db2... test.db2 is compatible
}
3 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(a, b, c);
CREATE INDEX t1y ON t1(y);
CREATE VIEW v1 AS SELECT * FROM t2;
} {
test.db2 is NOT compatible (objects)
} {}
4 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(a, b, c);
CREATE INDEX t1x ON t1(X);
CREATE INDEX t1y ON t1(y);
CREATE VIEW v1 AS SELECT * FROM t2;
} {
test.db2 is NOT compatible (SQL)
} {}
5 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(a, b, c);
CREATE INDEX t1y ON t1(y);
CREATE INDEX t1x ON t1(x);
CREATE VIEW v1 AS SELECT * FROM t2;
} {
test.db2 is NOT compatible (root pages)
} {
Fixing test.db2... test.db2 is compatible
}
6 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(a, b, c);
CREATE INDEX t1x ON t1(x);
CREATE INDEX t1y ON t1(y);
CREATE VIEW v1 AS SELECT * FROM t2;
DROP INDEX t1x;
CREATE INDEX t1x ON t1(x);
} {
test.db2 is NOT compatible (order of sqlite_master rows)
} {
Fixing test.db2... test.db2 is compatible
}
} {
forcedelete test.db2
sqlite3 db2 test.db2
db2 eval $sql
db2 close
if {$out2==""} {set out2 $out1}
do_test 1.$tn.1 {
catchcmd test.db ".shared-schema check test.db2"
} [list 0 [string trim $out1]]
do_test 1.$tn.2 {
catchcmd test.db ".shared-schema fix test.db2"
} [list 0 [string trim $out2]]
do_test 1.$tn.3 {
catchcmd test.db2 "PRAGMA integrity_check"
} [list 0 ok]
}
finish_test
+143
View File
@@ -0,0 +1,143 @@
# 2019 February 26
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reuse6
ifcapable !sharedschema {
finish_test
return
}
do_execsql_test 1.0 {
CREATE TABLE t1(x, y);
CREATE TABLE t2(a, b, c);
CREATE INDEX t1x ON t1(x);
CREATE INDEX t1y ON t1(y);
CREATE VIEW v1 AS SELECT * FROM t2;
INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6);
INSERT INTO t2 VALUES('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i');
ATTACH 'test.db2' AS aux;
CREATE TABLE t3(i, ii);
INSERT INTO t3 VALUES(10, 20);
}
sqlite3 db1 test.db -shared-schema 1
sqlite3 db2 test.db -shared-schema 1
do_execsql_test -db db1 1.1 {
ATTACH 'test.db2' AS aux;
}
do_test 1.2 {
execsql {SELECT * FROM t3} db1
} {10 20}
do_execsql_test -db db2 1.3 {
ATTACH 'test.db2' AS aux;
}
do_test 1.3 {
execsql {SELECT * FROM t3} db1
} {10 20}
do_execsql_test -db db2 1.5 {
SELECT * FROM t3;
} {10 20}
do_test 1.6 {
execsql {SELECT * FROM t3} db1
} {10 20}
db1 close
db2 close
#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
forcedelete test.db3
do_execsql_test 2.0 {
CREATE TABLE t1(x, y);
ATTACH 'test.db2' AS aux2;
CREATE TABLE aux2.t2(x, y);
ATTACH 'test.db3' AS aux3;
CREATE TABLE aux3.t3(x, y);
}
sqlite3 db1 test.db -shared-schema 1
do_execsql_test -db db1 2.1 {
ATTACH 'test.db2' AS aux2;
ATTACH 'test.db3' AS aux3;
}
do_test 2.2.1 {
catchsql { SELECT * FROM aux2.nosuchtable } db1
} {1 {no such table: aux2.nosuchtable}}
do_test 2.2.2 {
sqlite3_errcode db1
} {SQLITE_ERROR}
db1 close
#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
ifcapable fts5 {
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE ft USING fts5(a, b);
ATTACH 'test.db2' AS aux;
CREATE TABLE aux.t1(x, y, z);
}
sqlite3 db1 test.db -shared-schema 1
do_execsql_test -db db1 3.1 {
ATTACH 'test.db2' AS aux;
}
do_execsql_test -db db1 3.2 {
SELECT * FROM main.ft, aux.t1;
}
db1 close
}
#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
ifcapable fts5 {
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE ft USING fts5(a, b);
}
forcecopy test.db test.db2
sqlite3 db1 test.db -shared-schema 1
do_execsql_test -db db1 4.1 {
ATTACH 'test.db2' AS aux;
SELECT * FROM main.ft;
SELECT * FROM aux.ft;
}
do_execsql_test -db db1 4.2 {
SELECT * FROM main.ft, aux.ft
}
}
finish_test
+54
View File
@@ -0,0 +1,54 @@
# 2019 February 12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reusefault
ifcapable !sharedschema {
finish_test
return
}
do_execsql_test 1.0 {
PRAGMA cache_size = 10;
CREATE TABLE t1(a UNIQUE, b UNIQUE);
INSERT INTO t1 VALUES(1, 2), (3, 4);
}
faultsim_save_and_close
do_faultsim_test 1.1 -prep {
faultsim_restore
sqlite3 db test.db -shared-schema 1
} -body {
execsql { SELECT * FROM t1 }
} -test {
faultsim_test_result {0 {1 2 3 4}}
}
do_faultsim_test 1.2 -prep {
faultsim_restore
sqlite3 db test.db -shared-schema 1
execsql { SELECT * FROM t1 }
sqlite3 db2 test.db
db2 eval {CREATE TABLE a(a)}
db2 close
} -body {
execsql { SELECT * FROM t1 }
} -test {
faultsim_test_result {0 {1 2 3 4}}
}
finish_test
+12
View File
@@ -191,4 +191,16 @@ do_test shell2-1.4.7 {
SELECT 'unclosed;
^--- error here}}
# Verify that safe mode rejects certain UDFs
# Reported at https://sqlite.org/forum/forumpost/07beac8056151b2f
do_test shell2-1.4.8 {
catchcmd "-safe :memory:" {
SELECT edit('DoNotCare');}
} {1 {line 2: cannot use the edit() function in safe mode}}
do_test shell2-1.4.9 {
catchcmd "-safe :memory:" {
SELECT writefile('DoNotCare', x'');}
} {1 {line 2: cannot use the writefile() function in safe mode}}
finish_test
+3
View File
@@ -26,6 +26,9 @@ set testprefix tcl
# Check the error messages generated by tclsqlite
#
set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nofollow BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
ifcapable sharedschema {
append r " ?-shared-schema BOOLEAN?"
}
if {[sqlite3 -has-codec]} {
append r " ?-key CODECKEY?"
}
+24 -19
View File
@@ -38,7 +38,7 @@
#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))
/* Database functions */
#define opendb(w,x,y,z) (SEL(w), opendb_x(w,x,y,z))
#define opendb(w,x,y,z,f) (SEL(w), opendb_x(w,x,y,z,f))
#define closedb(y,z) (SEL(y), closedb_x(y,z))
/* Functions to execute SQL */
@@ -545,11 +545,14 @@ static void opendb_x(
Error *pErr, /* IN/OUT: Error code */
Sqlite *pDb, /* OUT: Database handle */
const char *zFile, /* Database file name */
int bDelete /* True to delete db file before opening */
int bDelete, /* True to delete db file before opening */
int flags
){
if( pErr->rc==SQLITE_OK ){
int rc;
int flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
if( flags==0 ){
flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
}
if( bDelete ) unlink(zFile);
rc = sqlite3_open_v2(zFile, &pDb->db, flags, 0);
if( rc ){
@@ -985,7 +988,7 @@ static char *walthread1_thread(int iTid, void *pArg){
Sqlite db = {0}; /* SQLite database connection */
int nIter = 0; /* Iterations so far */
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
const char *azSql[] = {
"SELECT md5sum(x) FROM t1 WHERE rowid != (SELECT max(rowid) FROM t1)",
@@ -1024,7 +1027,7 @@ static char *walthread1_ckpt_thread(int iTid, void *pArg){
Sqlite db = {0}; /* SQLite database connection */
int nCkpt = 0; /* Checkpoints so far */
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
sqlite3_sleep(500);
execsql(&err, &db, "PRAGMA wal_checkpoint");
@@ -1043,7 +1046,7 @@ static void walthread1(int nMs){
Threadset threads = {0}; /* Test threads */
int i; /* Iterator variable */
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"PRAGMA journal_mode = WAL;"
"CREATE TABLE t1(x PRIMARY KEY);"
@@ -1076,7 +1079,7 @@ static char *walthread2_thread(int iTid, void *pArg){
int journal_exists = 0;
int wal_exists = 0;
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
sql_script(&err, &db, zJournal);
clear_error(&err, SQLITE_BUSY);
@@ -1106,7 +1109,7 @@ static void walthread2(int nMs){
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db, "CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE)");
closedb(&err, &db);
@@ -1126,7 +1129,7 @@ static char *walthread3_thread(int iTid, void *pArg){
i64 iNextWrite; /* Next value this thread will write */
int iArg = PTR2INT(pArg);
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
sql_script(&err, &db, "PRAGMA wal_autocheckpoint = 10");
iNextWrite = iArg+1;
@@ -1163,7 +1166,7 @@ static void walthread3(int nMs){
Threadset threads = {0};
int i;
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"PRAGMA journal_mode = WAL;"
"CREATE TABLE t1(cnt PRIMARY KEY, sum1, sum2);"
@@ -1186,7 +1189,7 @@ static char *walthread4_reader_thread(int iTid, void *pArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
integrity_check(&err, &db);
}
@@ -1201,7 +1204,7 @@ static char *walthread4_writer_thread(int iTid, void *pArg){
Sqlite db = {0}; /* SQLite database connection */
i64 iRow = 1;
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
sql_script(&err, &db, "PRAGMA wal_autocheckpoint = 15;");
while( !timetostop(&err) ){
execsql_i64(
@@ -1221,7 +1224,7 @@ static void walthread4(int nMs){
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"PRAGMA journal_mode = WAL;"
"CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);"
@@ -1241,7 +1244,7 @@ static char *walthread5_thread(int iTid, void *pArg){
Sqlite db = {0}; /* SQLite database connection */
i64 nRow;
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
nRow = execsql_i64(&err, &db, "SELECT count(*) FROM t1");
closedb(&err, &db);
@@ -1254,7 +1257,7 @@ static void walthread5(int nMs){
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"PRAGMA wal_autocheckpoint = 0;"
"PRAGMA page_size = 1024;"
@@ -1345,7 +1348,7 @@ static void cgt_pager_1(int nMs){
Error err = {0};
Sqlite db = {0};
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"PRAGMA cache_size = 2000;"
"PRAGMA page_size = 1024;"
@@ -1374,7 +1377,7 @@ static char *dynamic_triggers_1(int iTid, void *pArg){
int nDrop = 0;
int nCreate = 0;
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
int i;
@@ -1427,7 +1430,7 @@ static char *dynamic_triggers_2(int iTid, void *pArg){
int nInsert = 0;
int nDelete = 0;
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
do {
iVal = (iVal+1)%100;
@@ -1452,7 +1455,7 @@ static void dynamic_triggers(int nMs){
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"PRAGMA page_size = 1024;"
"PRAGMA journal_mode = WAL;"
@@ -1492,6 +1495,7 @@ static void dynamic_triggers(int nMs){
#include "tt3_lookaside1.c"
#include "tt3_vacuum.c"
#include "tt3_stress.c"
#include "tt3_reuseschema.c"
#include "tt3_shared.c"
int main(int argc, char **argv){
@@ -1517,6 +1521,7 @@ int main(int argc, char **argv){
{ vacuum1, "vacuum1", 10000 },
{ stress1, "stress1", 10000 },
{ stress2, "stress2", 60000 },
{ reuse_schema_1, "reuse_schema_1", 20000 },
{ shared1, "shared1", 10000 },
};
static char *substArgv[] = { 0, "*", 0 };
+2 -2
View File
@@ -70,7 +70,7 @@ static char *checkpoint_starvation_reader(int iTid, void *pArg){
Error err = {0};
Sqlite db = {0};
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
i64 iCount1, iCount2;
sql_script(&err, &db, "BEGIN");
@@ -96,7 +96,7 @@ static void checkpoint_starvation_main(int nMs, CheckpointStarvationCtx *p){
int nInsert = 0;
int i;
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"PRAGMA page_size = 1024;"
"PRAGMA journal_mode = WAL;"
+2 -2
View File
@@ -19,7 +19,7 @@ static char *create_drop_index_thread(int iTid, void *pArg){
Sqlite db = {0}; /* SQLite database connection */
while( !timetostop(&err) ){
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
sql_script(&err, &db,
"DROP INDEX IF EXISTS i1;"
@@ -51,7 +51,7 @@ static void create_drop_index_1(int nMs){
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"CREATE TABLE t11(a, b, c, d);"
"WITH data(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM data WHERE x<100) "
+3 -3
View File
@@ -22,7 +22,7 @@ static char *lookaside1_thread_reader(int iTid, void *pArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
sqlite3_stmt *pStmt = 0;
@@ -47,7 +47,7 @@ static char *lookaside1_thread_writer(int iTid, void *pArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
do{
sql_script(&err, &db,
@@ -68,7 +68,7 @@ static void lookaside1(int nMs){
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"CREATE TABLE t1(x PRIMARY KEY) WITHOUT ROWID;"
"WITH data(x,y) AS ("
+73
View File
@@ -0,0 +1,73 @@
/*
** 2014 December 9
**
** 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.
**
*************************************************************************
**
** reuse_schema_1
*/
static char *reuse_schema_thread(int iTid, void *pArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
int iRep = 0;
while( !timetostop(&err) ){
int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_SHARED_SCHEMA;
opendb(&err, &db, "test.db", 0, f);
execsql_i64(&err, &db, "SELECT count(*) FROM t1");
sql_script(&err, &db, "ATTACH 'test.db2' AS aux");
execsql_i64(&err, &db, "SELECT count(*) FROM t1");
closedb(&err, &db);
iRep++;
}
print_and_free_err(&err);
return sqlite3_mprintf("%d", iRep);
}
static void reuse_schema_1(int nMs){
Error err = {0};
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"CREATE TABLE t1(a, b, c, d);"
"WITH data(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM data WHERE x<100) "
"INSERT INTO t1 SELECT x,x,x,x FROM data;"
);
closedb(&err, &db);
opendb(&err, &db, "test.db2", 1, 0);
sql_script(&err, &db,
#ifdef SQLITE_ENABLE_FTS5
"CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, d);"
#else
"CREATE TABLE t2(a, b, c, d);"
#endif
"WITH data(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM data WHERE x<100) "
"INSERT INTO t2 SELECT x*2,x*2,x*2,x*2 FROM data;"
);
closedb(&err, &db);
setstoptime(&err, nMs);
launch_thread(&err, &threads, reuse_schema_thread, 0);
launch_thread(&err, &threads, reuse_schema_thread, 0);
launch_thread(&err, &threads, reuse_schema_thread, 0);
launch_thread(&err, &threads, reuse_schema_thread, 0);
launch_thread(&err, &threads, reuse_schema_thread, 0);
join_all_threads(&err, &threads);
sqlite3_enable_shared_cache(0);
print_and_free_err(&err);
}
+10 -10
View File
@@ -21,7 +21,7 @@ static char *stress_thread_1(int iTid, void *pArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
sql_script(&err, &db, "CREATE TABLE IF NOT EXISTS t1(a PRIMARY KEY, b)");
clear_error(&err, SQLITE_LOCKED);
@@ -40,7 +40,7 @@ static char *stress_thread_2(int iTid, void *pArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
while( !timetostop(&err) ){
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
sql_script(&err, &db, "SELECT * FROM sqlite_schema;");
clear_error(&err, SQLITE_LOCKED);
closedb(&err, &db);
@@ -59,7 +59,7 @@ static char *stress_thread_3(int iTid, void *pArg){
int i1 = 0;
int i2 = 0;
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
sql_script(&err, &db, "SELECT * FROM t1 ORDER BY a;");
i1++;
@@ -82,11 +82,11 @@ static char *stress_thread_4(int iTid, void *pArg){
int i2 = 0;
int iArg = PTR2INT(pArg);
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
if( iArg ){
closedb(&err, &db);
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
}
sql_script(&err, &db,
"WITH loop(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM loop LIMIT 200) "
@@ -113,12 +113,12 @@ static char *stress_thread_5(int iTid, void *pArg){
int i1 = 0;
int i2 = 0;
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
i64 i = (i1 % 4);
if( iArg ){
closedb(&err, &db);
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
}
execsql(&err, &db, "DELETE FROM t1 WHERE (rowid % 4)==:i", &i);
i1++;
@@ -265,7 +265,7 @@ static char *stress2_workload19(int iTid, void *pArg){
Sqlite db = {0}; /* SQLite database connection */
const char *zDb = (const char*)pArg;
while( !timetostop(&err) ){
opendb(&err, &db, zDb, 0);
opendb(&err, &db, zDb, 0, 0);
sql_script(&err, &db, "SELECT * FROM sqlite_schema;");
clear_error(&err, SQLITE_LOCKED);
closedb(&err, &db);
@@ -290,7 +290,7 @@ static char *stress2_thread_wrapper(int iTid, void *pArg){
while( !timetostop(&err) ){
int cnt;
opendb(&err, &db, pCtx->zDb, 0);
opendb(&err, &db, pCtx->zDb, 0, 0);
for(cnt=0; err.rc==SQLITE_OK && cnt<STRESS2_TABCNT; cnt++){
pCtx->xProc(&err, &db, i1);
i2 += (err.rc==SQLITE_OK);
@@ -342,7 +342,7 @@ static void stress2(int nMs){
Threadset threads = {0};
/* To make sure the db file is empty before commencing */
opendb(&err, &db, zDb, 1);
opendb(&err, &db, zDb, 1, 0);
sql_script(&err, &db,
"CREATE TABLE IF NOT EXISTS t0(x PRIMARY KEY, y, z);"
"CREATE INDEX IF NOT EXISTS i0 ON t0(y);"
+3 -3
View File
@@ -25,7 +25,7 @@ static char *vacuum1_thread_writer(int iTid, void *pArg){
Sqlite db = {0}; /* SQLite database connection */
i64 i = 0;
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
while( !timetostop(&err) ){
i++;
@@ -52,7 +52,7 @@ static char *vacuum1_thread_writer(int iTid, void *pArg){
static char *vacuum1_thread_vacuumer(int iTid, void *pArg){
Error err = {0}; /* Error code and message */
Sqlite db = {0}; /* SQLite database connection */
opendb(&err, &db, "test.db", 0);
opendb(&err, &db, "test.db", 0, 0);
do{
sql_script(&err, &db, "VACUUM");
@@ -69,7 +69,7 @@ static void vacuum1(int nMs){
Sqlite db = {0};
Threadset threads = {0};
opendb(&err, &db, "test.db", 1);
opendb(&err, &db, "test.db", 1, 0);
sql_script(&err, &db,
"CREATE TABLE t1(x PRIMARY KEY, y BLOB);"
"CREATE INDEX i1 ON t1(y);"
+17
View File
@@ -1617,4 +1617,21 @@ do_execsql_test where-28.1 {
19 5
}
# 2022-12-07 Yong Heng [https://sqlite.org/forum/forumpost/dfe8084751]
#
ifcapable vtab {
do_execsql_test where-29.1 {
SELECT DISTINCT 'xyz' FROM pragma_cache_size
WHERE rowid OR abs(0)
ORDER BY
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1;
} {xyz}
}
finish_test
+22 -16
View File
@@ -12,7 +12,7 @@
# Flag meanings:
set flagMeaning(NeedSchema) {Force schema load before running}
set flagMeaning(ReadOnly) {Read-only HEADER_VALUE}
set flagMeaning(OneSchema) {Only a single schema required}
set flagMeaning(Result0) {Acts as query when no argument}
set flagMeaning(Result1) {Acts as query when has one argument}
set flagMeaning(SchemaReq) {Schema required - "main" is default}
@@ -150,7 +150,7 @@ set pragma_def {
ARG: SQLITE_CellSizeCk
NAME: default_cache_size
FLAG: NeedSchema Result0 SchemaReq NoColumns1
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
COLS: cache_size
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -163,12 +163,12 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: page_count
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: max_page_count
TYPE: PAGE_COUNT
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: locking_mode
@@ -176,7 +176,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: journal_mode
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: journal_size_limit
@@ -184,18 +184,18 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: cache_size
FLAG: NeedSchema Result0 SchemaReq NoColumns1
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: mmap_size
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: auto_vacuum
FLAG: NeedSchema Result0 SchemaReq NoColumns1
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
NAME: incremental_vacuum
FLAG: NeedSchema NoColumns
FLAG: NeedSchema NoColumns OneSchema
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
NAME: temp_store
@@ -215,7 +215,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
NAME: synchronous
FLAG: NeedSchema Result0 SchemaReq NoColumns1
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: table_info
@@ -238,7 +238,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: stats
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq OneSchema
COLS: tbl idx wdth hght flgs
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
@@ -290,7 +290,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: foreign_key_list
FLAG: NeedSchema Result1 SchemaOpt
FLAG: NeedSchema Result1 SchemaOpt OneSchema
COLS: id seq table from to on_update on_delete match
IF: !defined(SQLITE_OMIT_FOREIGN_KEY)
@@ -336,14 +336,14 @@ set pragma_def {
NAME: data_version
TYPE: HEADER_VALUE
ARG: BTREE_DATA_VERSION
FLAG: ReadOnly Result0
ARG: BTREE_DATA_VERSION|PRAGMA_HEADER_VALUE_READONLY
FLAG: Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: freelist_count
TYPE: HEADER_VALUE
ARG: BTREE_FREE_PAGE_COUNT
FLAG: ReadOnly Result0
ARG: BTREE_FREE_PAGE_COUNT|PRAGMA_HEADER_VALUE_READONLY
FLAG: Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: application_id
@@ -357,7 +357,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
NAME: wal_checkpoint
FLAG: NeedSchema
FLAG: NeedSchema OneSchema
COLS: busy log checkpointed
IF: !defined(SQLITE_OMIT_WAL)
@@ -516,6 +516,12 @@ foreach f [lsort [array names allflags]] {
set fv [expr {$fv*2}]
}
puts $fd "\n/* For PragTyp_HEADER_VALUE pragmas the Pragma.iArg value is set"
puts $fd "** to the index of the header field to access (always 10 or less)."
puts $fd "** Ored with HEADER_VALUE_READONLY if the field is read only. */"
puts $fd "#define PRAGMA_HEADER_VALUE_READONLY 0x0100"
puts $fd "#define PRAGMA_HEADER_VALUE_MASK 0x00FF\n"
# Sort the column lists so that longer column lists occur first
#
proc colscmp {a b} {