Compare commits

...

149 Commits

Author SHA1 Message Date
drh a9328b904d Merge the 3.37.2 patches into the reuse-schema branch.
FossilOrigin-Name: d7ec5a2b4a2b4739b1e991893d87bb2d03fd3ade480035fa50500c5ee5813ad8
2022-01-06 14:16:56 +00:00
drh eecb3e6b16 Version 3.37.2
FossilOrigin-Name: 872ba256cbf61d9290b571c0e6d82a20c224ca3ad82971edc46b29818d5d17a0
2022-01-06 13:25:41 +00:00
drh 7bc0d3862a Remove two NEVER() macros that can sometimes be true if the database is
corrupt.  dbsqlfuzz 0414d2c18290fc80fd5fb540def7d3e46c1ae9c6.

FossilOrigin-Name: e1871201e73c1d970f0434d3c7190da2c1c49ded3a359640d959ec0c0450b8ed
2022-01-05 21:08:48 +00:00
drh 2300c5a646 Increase the version number to 3.37.2
FossilOrigin-Name: 7b911356af8f985eefdb190e1205933eaa0bef35e5d755b279514e7b96f9d0c4
2022-01-05 18:56:59 +00:00
drh dde17957b7 Fix an assert() failure that could follow an OOM when coding a RETURNING trigger. dbsqlfuzz case 5d3e2438f15dc32b473d9f29413157857efa1212.
FossilOrigin-Name: 93965e67e2478fc99d7abfd6790edac353358373873bb6ac82c7c65dbe52a5de
2022-01-05 16:02:23 +00:00
drh cf6b0e27d2 Improved handling of OOM errors in sqlite3ExpandReturning().
dbsqlfuzz 1040b720f0bbc3bdcfe7336acffbf71517e3ef82.

FossilOrigin-Name: b9ed2a2921a8f3f07a3a2c9b954806df924b3806795ab876bbbda28578175288
2022-01-05 12:01:34 +00:00
drh 36d39bcc48 Do not open a rollback journal file when the journal_mode is OFF, even if
such a file exists on disk. See
[forum/forumpost/ec2a102440|forum post ec2a102440] for a description.  I so
far have been unable to find any harm to come of the problem, other than the
assertion fault when in DEBUG mode.

FossilOrigin-Name: 71f21f172cbc033f70604d166f17118472491fcf8b78350bd347de016132b464
2022-01-02 19:43:58 +00:00
drh 024806ffb6 Clear the cache of triggers used to implement CASCADE foreign key constraints
whenever the schema changes.  Fix for the problem identified by
[forum:/forumpost/2831335356|forum post 2831335356].

FossilOrigin-Name: 4f1313c67f8c3025ed15793e370617d14e950c13217f179bfb01f8f48fbbead9
2022-01-02 18:10:48 +00:00
drh c84cb56f81 Earlier detection of corruption in sqlite3BtreeDelete(). Fix for
the assertion fault reported by
[forum:/forumpost/9d78389221|forum post 9d78389221].

FossilOrigin-Name: eb07219965721e0a2017d0462747b07178c23f51e3333036e0cb8f5b4751f404
2022-01-02 17:46:49 +00:00
drh 2f2b676b7b Do not raise an SQLITE_SCHEMA error if in sqlite3Init(). Fix for PoC #2 in
[forum:/forumpost/b03d86f951|forum post b03d86f951].  See TH3 for test
cases.

FossilOrigin-Name: 25beca31cf3dbad0e78085c5ceed797a461cfaddc2d41fb7a093aa27098e50d5
2022-01-02 17:37:56 +00:00
drh 2718c7dec7 Fix an obscure problem with releasing savepoints stored in an in-memory journal that could cause subsequent savepoint rollback to fail.
FossilOrigin-Name: 3c0806e4df3ba795962b0111236b2b6f27f63a35a02055c251f750ef02622803
2022-01-02 17:24:29 +00:00
drh 4a6393e96e Remove an obsolete assert() statement that no longer does anything useful
and which is not always true.  Fix for PoC #1 of
[forum:/forumpost/b03d86f951|forum post b03d86f951].

FossilOrigin-Name: 0829c1001bcfadf0d0af2b2c2e01ed60b24156b7c4e7c49cb29f3002ce8e36db
2022-01-02 17:14:39 +00:00
drh 48b9d17680 Fix a faulty assert() statement - adding a CORRUPT_DB term - based on a test
case derived from [562805cf488a455c].  Also add a test case to that prior
issue.

FossilOrigin-Name: f9505fcb28d05ac2319a56d936f840b8de502a49dda16ded8b7ed9dd9dffe509
2022-01-02 17:13:36 +00:00
drh 9dba2cc038 Fix harmless compiler warnings seen with MSVC.
FossilOrigin-Name: 6e08a542ad6af7032e5badcdd50a8ed95c07bf7b15ae2b62334376b75a2e9731
2022-01-02 17:02:54 +00:00
drh adb21d4482 Move the pTriggerPrg and pCleanup elements of the Parse object up into the
section of that object that is persisted across calls to sqlite3NestedParse().
This fixes a memory leak
[forum:/info/24bd1fef7e9323ef|reported in forum post 24bd1fef7e9323ef].

FossilOrigin-Name: ee8b2397a67c14badb836570f815ca6c59f6936100669adafe815d7cb997cb43
2022-01-02 17:00:19 +00:00
drh bac7cf46d4 Merge the 3.37.1 patches into the reuse-schema branch.
FossilOrigin-Name: e9e95c8fc61d5c505ebc0a3b1434cc8a3e0206d197aa21bdfa6fb103df3bce08
2021-12-30 16:14:09 +00:00
drh 57acbb1380 Version 3.37.1
FossilOrigin-Name: 378629bf2ea546f73eee84063c5358439a12f7300e433f18c9e1bddd948dea62
2021-12-30 15:30:28 +00:00
drh f74840dadb Disable the atoi1.test test module on non-x64 hardware.
FossilOrigin-Name: 986a94d036f029539c3bb3873096f4a85ee26fc674f56856c57ca3dfd3bd0f37
2021-12-30 12:26:16 +00:00
drh 2e4f1fd0f8 Fix windowC tests to specify little-endian or big-endian UTF16, for cross-platform portability. [forum post 559b84a5c6|forum:/forumpost/559b84a5c6]. And
give the correct prefix to tests in the windowC.test module.

FossilOrigin-Name: 8af7cb2a3e7ca778695a7a44359537457bf57dc8bdad9b2b4d20a73385c028d8
2021-12-30 11:35:38 +00:00
drh b484ae62b8 Do not attempt to reprepare a prepared statement that returns SQLITE_SCHEMA
if there was an OOM.  This enhancement supercedes check-in
[fee469925231d074].

FossilOrigin-Name: 103f95db3e17d7d021b489c160b84e66c630b4f13516be11d10fffe2b42599fa
2021-12-30 11:27:53 +00:00
drh be531827a6 Change an assert() in FTS3 into assert_fts3_nc(), since it is a harmless
condition that can occur when processing a corrupt database file.

FossilOrigin-Name: 35e2b27af7242a3f74b31e0e25a0ea892f6aec66341b9194c0f5957f9d1926bc
2021-12-30 11:13:44 +00:00
drh bbefc9e821 Fix a minor issue in the configure script.
FossilOrigin-Name: 0413d37e327525d7747d9f9643eb73197a83d9e810bcdc3e0cd35762a94ba22b
2021-12-30 03:56:30 +00:00
drh 7771ab2192 Following a prior error, an ALWAYS() in sqlite3ExprCanBeNull() might be false.
dbsqlfuzz 5dbec6678a20e7595a34dfdd869a3b9722b3ca43.

FossilOrigin-Name: b33e47709a2eb56b543ee3a34af201cd05e316bde8dcf45cebcf4e157d728508
2021-12-30 03:22:21 +00:00
drh fe553b671c When a table has an INTEGER PRIMARY KEY ON CONFLICT REPLACE and some other
uniqueness constraint, and it participates in an upsert on that other
constraint, ensure that code that checks for conflicts on the INTEGER PRIMARY
KEY is well-formed.  Fix for the problem reported by
[forum:/forumpost/06b16b8b29f8c8c3|forum post 06b16b8b29f8c8c3].

FossilOrigin-Name: 1f1e0b4e6d3a63fecaef8fafc8374ff17cff6d7af4c03994fa245e9953ee42cb
2021-12-30 03:12:37 +00:00
drh 3d25b94a13 Fix an OOB read that could occur in fts5 when processing corrupt records.
FossilOrigin-Name: 734606ea1a42c2e31ea62c114f2480b52182114b6bd87eb2f1145a171daad80f
2021-12-06 19:03:56 +00:00
drh b8b877b3dd Do not allow SQLITE_LIMIT_LENGTH to be set lower than 1 as an
SQLITE_LIMIT_LENGTH of 0 causes lots of unnecessary problems for
users of the sqlite3_str object.

FossilOrigin-Name: 286243f3a49f721b2ed5b278738e9edd8ca0f190abdbec645866bce97fcc7d04
2021-12-06 16:56:06 +00:00
drh 5b6692dddd Do not allow certain dangerous ".testctrl" commands in safe mode.
FossilOrigin-Name: 4602644f858eb3b55fec0ead1de58de1f60cb85165cbb309bfe6bb136099a895
2021-12-06 16:51:03 +00:00
drh 7956fbb7b6 Fix SQLITE_TESTCTRL_IMPOSTER so that it is a harmless no-op if the schema
parameter is invalid.

FossilOrigin-Name: b15c553c2ca3143c269e25f41e1a4e6c00f72a89e4b0a382260620567f159081
2021-12-06 16:42:31 +00:00
drh 764d1809ce In the shell tool, avoid modifying internal data structures until after the arguments to ".open" have been parsed.
FossilOrigin-Name: cbd69ed8afd3facda39fe8c81a3e8e4a1928923bcfd93e99d1bb8b3868ef3e5b
2021-12-06 16:36:37 +00:00
drh 5aa46f9bd6 Start a new branch on which to cherrypick fixes against 3.37.0.
FossilOrigin-Name: cea9e41aaee9b43496909fa2ba80dddaee1dd77d44bcb4d8d38034d1b003d762
2021-12-06 16:29:53 +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
69 changed files with 3747 additions and 380 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
@@ -419,6 +420,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 \
@@ -479,6 +481,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.37.0
3.37.2
Vendored
+35 -45
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.37.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.37.2.
#
#
# 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.37.0'
PACKAGE_STRING='sqlite 3.37.0'
PACKAGE_VERSION='3.37.2'
PACKAGE_STRING='sqlite 3.37.2'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -770,11 +770,11 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
BUILD_CFLAGS
AMALGAMATION_LINE_MACROS
USE_GCOV
OPT_FEATURE_FLAGS
HAVE_ZLIB
USE_AMALGAMATION
AMALGAMATION_LINE_MACROS
TARGET_DEBUG
TARGET_HAVE_EDITLINE
TARGET_HAVE_READLINE
@@ -903,7 +903,6 @@ with_readline_lib
with_readline_inc
enable_debug
enable_amalgamation
amalgamation_line_macros
enable_load_extension
enable_math
enable_all
@@ -1469,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.37.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.37.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1534,7 +1533,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.37.0:";;
short | recursive ) echo "Configuration of sqlite 3.37.2:";;
esac
cat <<\_ACEOF
@@ -1662,7 +1661,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.37.0
sqlite configure 3.37.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2081,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.37.0, which was
It was created by sqlite $as_me 3.37.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3939,13 +3938,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3940: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3941: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3943: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3944: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3946: output\"" >&5)
(eval echo "\"\$as_me:3947: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5151,7 +5150,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5152 "configure"' > conftest.$ac_ext
echo '#line 5153 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6676,11 +6675,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6677: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6678: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6681: \$? = $ac_status" >&5
echo "$as_me:6682: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7015,11 +7014,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7016: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7017: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7020: \$? = $ac_status" >&5
echo "$as_me:7021: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7120,11 +7119,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7121: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7122: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7125: \$? = $ac_status" >&5
echo "$as_me:7126: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7175,11 +7174,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7176: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7177: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7180: \$? = $ac_status" >&5
echo "$as_me:7181: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9555,7 +9554,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9556 "configure"
#line 9557 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9651,7 +9650,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9652 "configure"
#line 9653 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10307,13 +10306,6 @@ done
#
USE_AMALGAMATION=1
#########
# By default, amalgamation sqlite3.c will have #line directives.
# This is a build option not shown by ./configure --help
# To control it, use configure option: amalgamation_line_macros=?
# where ? is no to suppress #line directives or yes to create them.
AMALGAMATION_LINE_MACROS=--linemacros=0
#########
# See whether we can run specific tclsh versions known to work well;
# if not, then we fall back to plain tclsh.
@@ -11284,19 +11276,6 @@ if test "${enable_amalgamation}" = "no" ; then
USE_AMALGAMATION=0
fi
########
# See whether --disable
if test "${amalgamation_line_macros+set}" = set; then :
enableval=$amalgamation_line_macros;
fi
if test "${amalgamation_line_macros}" = "yes" ; then
AMALGAMATION_LINE_MACROS=--linemacros=1
fi
if test "${amalgamation_line_macros}" = "no" ; then
AMALGAMATION_LINE_MACROS=--linemacros=0
fi
#########
# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
@@ -11882,6 +11861,17 @@ else
fi
#########
# Enable/disabled amalagamation line macros
########
AMALGAMATION_LINE_MACROS=--linemacros=0
if test "${amalgamation_line_macros}" = "yes" ; then
AMALGAMATION_LINE_MACROS=--linemacros=1
fi
if test "${amalgamation_line_macros}" = "no" ; then
AMALGAMATION_LINE_MACROS=--linemacros=0
fi
#########
# Output the config header
@@ -12400,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.37.0, which was
This file was extended by sqlite $as_me 3.37.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12466,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.37.0
sqlite config.status 3.37.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+11
View File
@@ -791,6 +791,17 @@ else
fi
AC_SUBST(USE_GCOV)
#########
# Enable/disabled amalagamation line macros
########
AMALGAMATION_LINE_MACROS=--linemacros=0
if test "${amalgamation_line_macros}" = "yes" ; then
AMALGAMATION_LINE_MACROS=--linemacros=1
fi
if test "${amalgamation_line_macros}" = "no" ; then
AMALGAMATION_LINE_MACROS=--linemacros=0
fi
AC_SUBST(AMALGAMATION_LINE_MACROS)
#########
# Output the config header
+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.
+1 -1
View File
@@ -4473,7 +4473,7 @@ void sqlite3Fts3DoclistPrev(
assert( nDoclist>0 );
assert( *pbEof==0 );
assert( p || *piDocid==0 );
assert_fts3_nc( p || *piDocid==0 );
assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
if( p==0 ){
+6 -2
View File
@@ -1879,8 +1879,12 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
int iRowidOff;
iRowidOff = fts5LeafFirstRowidOff(pNew);
if( iRowidOff ){
pIter->pLeaf = pNew;
pIter->iLeafOffset = iRowidOff;
if( iRowidOff>=pNew->szLeaf ){
p->rc = FTS5_CORRUPT;
}else{
pIter->pLeaf = pNew;
pIter->iLeafOffset = iRowidOff;
}
}
}
+54
View File
@@ -0,0 +1,54 @@
# 2015 Apr 24
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file tests that FTS5 handles corrupt databases (i.e. internal
# inconsistencies in the backing tables) correctly. In this case
# "correctly" means without crashing.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5corrupt6
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
sqlite3_fts5_may_be_corrupt 1
database_may_be_corrupt
proc editblock {block} {
binary format Sa* 20000 [string range $block 2 end]
}
db func editblock editblock
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE ft USING fts5(abc, def);
WITH a(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM a WHERE i<1000
)
INSERT INTO ft SELECT
'abc abc abc abc abc abc abc abc abc abc',
'def def def def def def def def def def'
FROM a;
UPDATE ft_data SET block = editblock(block) WHERE id=(
SELECT id FROM ft_data ORDER BY id LIMIT 1 OFFSET 5
);
}
do_catchsql_test 1.1 {
SELECT rowid FROM ft('def') ORDER BY rowid DESC LIMIT 1 OFFSET 9999;
} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test
+1 -1
View File
@@ -304,7 +304,7 @@ static int box_query(sqlite3_rtree_query_info *pInfo){
static void box_query_destroy(void *p){
BoxQueryCtx *pCtx = (BoxQueryCtx*)p;
Tcl_DecrRefCount(pCtx->pScript);
ckfree(pCtx);
ckfree((char*)pCtx);
}
static int SQLITE_TCLAPI register_box_query(
+2
View File
@@ -344,6 +344,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 \
@@ -399,6 +400,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 \
+73 -62
View File
@@ -1,13 +1,13 @@
C Version\s3.37.0
D 2021-11-27T14:13:22.430
C Merge\sthe\s3.37.2\spatches\sinto\sthe\sreuse-schema\sbranch.
D 2022-01-06T14:16:56.678
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 0e91c42a1dd13a569b1fa4f4dfb7d3632f3164a1c05c71341533d67db5b641dd
F Makefile.in 9b31893e6677a04291db2c70ef2e4edbf77e8acf2a95192c285ab141809bdb33
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
F Makefile.msc 88f05063ee36a5fb77d69b877ef824d0743b5325c95bfbf74d6ff17bd1c9fb1f
F Makefile.msc 59085acb7680998a476cac00e4a151f196a484505d3008285714245a660dc52d
F README.md 27fb76aa7eb57ed63a53bbba7292b6bf71f51125554f79f16b5d040edd1e6110
F VERSION c6595fef606851f2bc3ebed6a7386c73751835fc909feab7c093739fa4b3c1d1
F VERSION b8218d35896c0f381cf64a499abbab64eeb86b40116a7d35c5a39c6677e8bb89
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -34,12 +34,13 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure e8003577b8c433cf61371d27d4beeca3a3ed37611a504ff5f4d4286923b87d03 x
F configure.ac 4e4b58b32f88c8da9914a2f2c3158f80e69907eccc019fcc7e3ba14ffd91c640
F configure f8a03394ccec572e76a570aa858ccd24e0d54fd76c995b7220a4dfda8b899d27 x
F configure.ac c8ba54bac7e73e000acdfef5e394fe21a3876aa09d0f5c07131bf5ac5a525299
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
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
@@ -84,7 +85,7 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c da41de21622774b1cb8c3415e8d2a6961ad7c978ab534f2a54434f76a5c4dfbc
F ext/fts3/fts3.c 6bfdc941372ee431e3d362986674a8708eb0e700b28c3d35d46d953a9351155f
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h cff59b8b13dafe9d59924a5d710f771ed8b121a55cccbc99b6e2a723fcde14dc
F ext/fts3/fts3_aux.c f0dc9bd98582615b7750218899bd0c729879b6bbf94d1be57ca1833ff49afc6f
@@ -119,7 +120,7 @@ F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b7292
F ext/fts5/fts5_config.c 501e7d3566bc92766b0e11c0109a7c5a6146bc41144195459af5422f6c2078aa
F ext/fts5/fts5_expr.c fcd0770d53028c2b53a15d0f53bf6d0e01b1bf3dd97630b9fedf0801f03aa3ec
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
F ext/fts5/fts5_index.c a3ada4897c3b14b8a15a8695d2cb3a46b5761137aae0964fc44efe96a877ddd0
F ext/fts5/fts5_index.c b1b2e5d4a9e3b54c740d8354cc47e3fa879f54c2176de55e0b882dab45ab7b07
F ext/fts5/fts5_main.c 7c6092a53e6802962fa07b0fad3e61cb077b6c98b74b727d8d44ac2cf63bd914
F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
@@ -163,6 +164,7 @@ F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec99
F ext/fts5/test/fts5corrupt3.test 0e473620582a53ac61f468f364db8a151c1e18d2a879b16439d172c12c4c9828
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
F ext/fts5/test/fts5corrupt5.test 550d0884c14424f9acad051a741f1dd99ec9342277d938e91ff3daf9123d1209
F ext/fts5/test/fts5corrupt6.test bf8eeae07825b088b9665d9d8e4accbd8dc9bf3cb85b6c64cf6c9e18ccc420a4
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
@@ -425,7 +427,7 @@ F ext/rtree/rtreedoc2.test 194ebb7d561452dcdc10bf03f44e30c082c2f0c14efeb07f5e02c
F ext/rtree/rtreedoc3.test 555a878c4d79c4e37fa439a1c3b02ee65d3ebaf75d9e8d96a9c55d66db3efbf8
F ext/rtree/rtreefuzz001.test 0fc793f67897c250c5fde96cefee455a5e2fb92f4feeabde5b85ea02040790ee
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
F ext/rtree/test_rtreedoc.c 0167f9243a56d08e79230f604f3979d6b7cde4816355acf7a7d436d9d788bf38
F ext/rtree/test_rtreedoc.c 5ad4029d6804eb9efafcac1598a9e0582f6119e48f818854f5b4db1788ca8bd4
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
@@ -472,7 +474,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 002e77acdfeb08d1d8f4d360b01e130aa243fb5701728e81fac9085794f27155
F main.mk 2a87e919ae96ab47f20b0c4e6568a58071233fe7306afa56b925a356e5c26399
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -484,37 +486,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 23743384e59f9d36df870ce41adfdf7934fd0adb619d7fa6fd1aac77c28a7533
F src/analyze.c 7518b99e07c5494111fe3bd867f28f804b6c5c1ad0703ec3d116de9bab3fa516
F src/attach.c e3f9d9a2a4a844750f3f348f37afb244535f21382cbfcd840152cb21cb41cfaf
F src/alter.c 0b0b8c74bd94b6c1e3f7023b2341a57b6f45e9ff8210fedbc1e6f6b443746dec
F src/analyze.c b619f92ad33aa38c234d9620f576bceef56465088ed37f28c56d136a15c1a909
F src/attach.c 173d0cadb5eeee2c5ac59400955a821fd80095bb248e21c99194dc84cc214078
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 13b965a0f3cd57221e3b4e61e24452ec264a5b163de347b03b5039ddcd95cd54
F src/btree.c 012772a0cbd1c8ee7ac34f5a9ff9861de989725cb26e7a07afbbb2d43deeccd9
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
F src/build.c c46bd4f5a69f398410c4472f7c1c4291fb8078d2c9758a2dad5916edd1d30ecc
F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc
F src/build.c 990ff9ab703428e9a58405d57d88706a7b829f34877664082fa71154207a8b33
F src/callback.c a3449287e62b63ac7edee94175a4db5fa56a0fbfc48fa463d8222a952af2966a
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1
F src/ctime.c 22b5ea591c18d677b521a99d375dfc626917bc23786c5f52aca113924b8edb9e
F src/date.c fa928630fecf1d436cdc7a7a5c950c781709023ca782c21b7a43cc7361a9451e
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
F src/delete.c 0c151975fa99560767d7747f9b60543d0093d9f8b89f13d2d6058e9c83ad19e7
F src/expr.c 4b6dfb224b6234ff4f529023993b503048e1b045ff49cbb911e7d28a28cca795
F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5
F src/fkey.c 5b73f7a7c00f06017531a5bd258cbc2c7a294e55a7f84a729fe27aa525242560
F src/func.c 1cfb09d7ffca81238eccefdb0293e1f5b7cfebbd1816dfad5ec6024742a7496b
F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 7fcbbe9114ac402ea3c0c6a3810f13fc89cae8131ea1659ec472be7caac10192
F src/insert.c 04c9b133be6152b4f229aab8e38230b3bf6d2e7e76455a893bff5f70e566237b
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c
F src/main.c 7bd4fdc41ef53535271a1816ff043ba153cda03842b444b6e2f57b27b2cb9090
F src/main.c 258eb7090a3dc65c121075327923688f114e13d50d31652a6b88bc7aae595102
F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -522,7 +524,7 @@ F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
F src/memdb.c c2dc88f97c410eb68a24468344b65526685e18354ddfd15906750c1eaf9dc2dd
F src/memjournal.c a85f0dc5c02a42453d0bc3819ecfb5666cb6433e5deefcd93ccbe05c9f088b83
F src/memjournal.c ff4336a98b05ede2adee7595f22d6f7d1cdc6bf0f0a5c3d77b0acdf017b2e8b2
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
@@ -537,29 +539,29 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e
F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c bc10c191d18bffd3d76eda5f162799e43a9f875ecfe7c4869f752e2ddef87ea2
F src/pager.c 5b79a1c09bc19628a763c822ef96326832090703a6608c64dc5fc166ab8dda79
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
F src/parse.y 0bd7971a7489bbf6c3726f1b50da6e508bdff8fa493e9cc3f5a96b12cbb2361e
F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f
F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad
F src/prepare.c 7520a371f1de8a53e3023eba75bc0d3473196833c6363d285cad8d002eabef0b
F src/pragma.c 401df25173a16e13923af6e4cb6c5a2fb14106117ac0a4ec1f419f0e696d22f5
F src/pragma.h 270bff5fefbc3c56ddcb5627d706904ec289853a5ef65662f6fac810b5a1923f
F src/prepare.c 01e70c7154846e737766b7ddef2c9f80607065c194e08e289cc53abb8126b59a
F src/printf.c 5901672228f305f7d493cbc4e7d76a61a5caecdbc1cd06b1f9ec42ea4265cf8d
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a
F src/shell.c.in 975f268ef261773fcbed1e519dfa10c4f33e8b1cffc12120563e61857fff07c6
F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0
F src/shell.c.in b06b3d0e23a47a174937579ce0e2284b4638280e27a4ea2654ea2b36ab4c39f3
F src/sqlite.h.in d36a609734942eddefdfbb6e774f8bfa46f00030e1be45a1997f761249ccb339
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839
F src/sqliteInt.h 193e716a67c877a6054a8c261c932bdc64f8c8be9b66388c74f21d94a259b7ce
F src/sqliteInt.h 7f12b123d3fa5ed2aedaa4ebfb9fa5737e745fc2fab004f96bd9bea602823a64
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/status.c d0956e57c71160155f620a3efeb1e5c05a3f8b9a897dd09c5263268e5d237579
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 48f291e1a7e672a7204884d4c164a8ed3a522ff087c361ada2991f5d54e987f6
F src/tclsqlite.c d59959ac596aa96b60575ebf863e295a105e617f6aa28bc0188252e134e15308
F src/test1.c d6c945a8bb211ed72ea515f0b9743caeaf38c66da6418a7b1dcf3764e1368bbb
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
@@ -575,7 +577,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 284c29912736f68b0a583a920bf63fd8f9125dffb8a75cb0676e58502b2f7908
F src/test_config.c 0e61f2cd80fe27186192507ab42e55abdd62cf58557b3d63df50f369fdfbccef
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
@@ -599,11 +601,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 c4065ced25126e25c40122c5ff62dc89902ea617d72cdd27765151cdd7fcc477
F src/test_tclsh.c ec192bceacfe67d427e97d4985a298b0aaadb266dfbc77c54425537c5e263b65
F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
F src/test_thread.c 269ea9e1fa5828dba550eb26f619aa18aedbc29fd92f8a5f6b93521fbb74a61c
F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43
@@ -616,23 +619,23 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 865911afa00fed589cd03b25c140ca88544842aaef7b81f7d41ed769a7a54120
F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc
F src/trigger.c 2ef56f0b7b75349a5557d0604b475126329c2e1a02432e7d49c4c710613e8254
F src/trigger.c 026250cb54a91df1bea0495c0375d8fc962190cc0495913f242e937b3513cb6f
F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167
F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
F src/vdbe.c e98f1baf54a00db2c4669dbd04f8bbc89b5909a5b43e76fbbbf1a97007adba2b
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
F src/vacuum.c 97424abbd3b5831d0142349a3c2dad52c364e39fab67f7e0f5c60d2694463940
F src/vdbe.c eaf40ef5065e99e1ae853efe76af5220c0f7f9c3502a0b8a3e437fba9b4445a1
F src/vdbe.h bfde0b0f429a0ba4203e5319780a6a1c8b2a809c5cd6baa9ae22e257a657b8b3
F src/vdbeInt.h 31fbabdc1ed61d9695337dfe5269ea94e1cf615c17f5cafeaa1bb01066820bab
F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a
F src/vdbeaux.c 21db442d159fd745a7693d157b5f998260b6af4ca60de559fa3b7b68c7405af2
F src/vdbeblob.c 29c4118f7ee615cdee829e8401f6ead1b96b95d545b4de0042f6de39c962c652
F src/vdbeaux.c 8ccf6eddce64e2383cb1e1f33db56e67c2ccf86248533055ec8c43f444091c2a
F src/vdbeblob.c a01a2a6d08a6ba108449d836939df78d5fa1251283939767f64ec60fb29fe919
F src/vdbemem.c a3d91dc9bb9ef725db77e4e9de7e1acef43192c9f8406c307665d503e3c2837c
F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c 9d5c3f49d3a6959b6eef287bb8fa773563102a80a835c3314c57144412709e78
F src/vtab.c 13cce9cae0b4f65615a7952620b8517d2773304ba1478624835dff88e7881d98
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
@@ -688,7 +691,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
F test/atof1.test 10049623e77006691c4c2978c1dc8a3f75276377a53417811aa85bda7493f963
F test/atof1.test 77e8517df10cb39f2e4e65dbefe1e81c8d8e65f29f68b09265ca6e534c68227e
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
@@ -907,7 +910,7 @@ F test/filter1.test 6c483ecf7886c8843a8612c021aa23f33c581f584151f251842b3a3592c9
F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f93393e8
F test/filter2.test 485cf95d1f6d6ceee5632201ca52a71868599836f430cdee42e5f7f14666e30a
F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b
F test/fkey1.test 03503639d266d565db90ee3b8fe211ba446624030ac4eb24895cec265e9631d0
F test/fkey1.test 55663090ab6735319a52647057b9f19f8ec8c6c7d7da25170b71a75e3e5bdeb7
F test/fkey2.test 1063d65e5923c054cfb8f0555a92a3ae0fa8c067275a33ee1715bd856cdb304c
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
@@ -1202,6 +1205,7 @@ F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
F test/memdb1.test 2c4e9cc10d21c6bf4e217d72b7f6b8ba9b2605971bb2c5e6df76018e189f98f5
F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c
F test/memjournal2.test 89a4e0d1084170a281efa4d54c2677599f986f44227f98f7dfae282802737b65
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
@@ -1309,6 +1313,14 @@ F test/releasetest_data.tcl 7cea6c852ae6bb3a9ff1a2b910e4dd13c16a05f74443984dfd52
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/returning1.test f96c7245f6ac16038e802760cd90b93479369939a8a7a44e2329ee5aed28239c
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
@@ -1456,7 +1468,7 @@ F test/tabfunc01.test d6821e7042e5653104dac0c63d75eff24a2415ab1889fc68b5db7fde59
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test 97cda6e4843e9f3e06c56f656d9b77ee0178fe1ee33fb09a6eeae8f125757ac1
F test/tclsqlite.test 207d3661a36de1c4a11affc020f6626aed2ac2693c4bfa8ddbb54e3c36ff05d7
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
@@ -1475,7 +1487,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
@@ -1649,12 +1661,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
@@ -1674,7 +1687,7 @@ F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666
F test/upfrom2.test 88d39cb755db5789541e645d4e2764abc697a56958f28a3f8451a0e9342bbd6b
F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
F test/upsert1.test 88f9e258c6a0eeeb85937b08831e8daad440ba41f125af48439e9d33f266fb18
F test/upsert1.test b0ae2f58680c5205b4bc1cdeed3c3d444057c506f6c44494fa3eac60731d68a2
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
@@ -1803,7 +1816,7 @@ F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45
F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
F test/windowB.test b67bda5645f3226790e1a360c4225241840b84adb5aa2e69bfb0b27eef3b84d9
F test/windowC.test 8799158a2a3ea365980371400f08fd4dff70eadffa5a1e45d42430246da70706
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
@@ -1815,7 +1828,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982
F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
F test/with6.test 661d7e416bef6c0a2556b2c9f0c8178a5b15932bed65246abed99723a8d4e7c0
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
F test/without_rowid1.test df3de14f1cc422d2b0f9b79969b5ef8e51c86ed87834ab35fb5139403e7f5a03
F test/without_rowid1.test 78fd9b437f4cdb46f76e6a510d545334e4f58e3e4ce37aaf19384eda5b27de8c
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
@@ -1855,7 +1868,7 @@ F tool/lemon.c 258881835bd5bccd0c74fb110fe54244ff18e8e7ef3d949cbdab7187f02132bb
F tool/lempar.c 57478ea48420da05faa873c6d1616321caa5464644588c97fbe8e0ea04450748
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
F tool/logest.c 06446d42942a7128ab4963eb438eb3f528e07095d5d1080f9105a6f337238d33
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
@@ -1866,7 +1879,7 @@ F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a89
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
F tool/mkopcodeh.tcl 130b88697da6ec5b89b41844d955d08fb62c2552e889dec8c7bcecb28d8f50bd
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl de206c64b6e9ac8cd5e3cbd0ffe456f07d5710605ef8385d677e60ce3335ea12
F tool/mkpragmatab.tcl 670bc23facb66ed982cc6cd7f678505bd6544ebb501bdf4f5fd22ebecbaca73f
F tool/mkshellc.tcl df5d249617f9cc94d5c48eb0401673eb3f31f383ecbc54e8a13ca3dd97e89450
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1883,7 +1896,7 @@ F tool/replace.tcl 937c931ad560688e85bdd6258bdc754371bb1e2732e1fb28ef441e44c9228
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
F tool/showdb.c 7cc12c6deeddfe40ba5d948b408730696d8365988da05fcb6b6a90ea4965e2b4
F tool/showdb.c 72239e95e1d05a2941c6a1d86b4d857812be4dadd71f24e381db572f350fc172
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
@@ -1933,10 +1946,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 7c567338ae4dd31097e9ae5c693b84369c35c5a52534797e8186b4be7297ba78
R 1bdaa083fa0abfc53c61429627c688f2
T +sym-major-release *
T +sym-release *
T +sym-version-3.37.0 *
P e9e95c8fc61d5c505ebc0a3b1434cc8a3e0206d197aa21bdfa6fb103df3bce08 872ba256cbf61d9290b571c0e6d82a20c224ca3ad82971edc46b29818d5d17a0
R 12acee82b8855b22197a968922deb50a
U drh
Z 6f6dbee10adfe1c5275055f73bc6984f
Z 8e1df986c492ba5edabd5ec8c95a9cf5
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a
d7ec5a2b4a2b4739b1e991893d87bb2d03fd3ade480035fa50500c5ee5813ad8
+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;
+17 -10
View File
@@ -1246,7 +1246,7 @@ static void btreeParseCellPtr(
pInfo->nPayload = nPayload;
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
testcase( nPayload==pPage->maxLocal+1 );
testcase( nPayload==(u32)pPage->maxLocal+1 );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
@@ -1283,7 +1283,7 @@ static void btreeParseCellPtrIndex(
pInfo->nPayload = nPayload;
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
testcase( nPayload==pPage->maxLocal+1 );
testcase( nPayload==(u32)pPage->maxLocal+1 );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
@@ -1346,7 +1346,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
while( (*pIter++)&0x80 && pIter<pEnd );
}
testcase( nSize==pPage->maxLocal );
testcase( nSize==pPage->maxLocal+1 );
testcase( nSize==(u32)pPage->maxLocal+1 );
if( nSize<=pPage->maxLocal ){
nSize += (u32)(pIter - pCell);
if( nSize<4 ) nSize = 4;
@@ -1354,7 +1354,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
int minLocal = pPage->minLocal;
nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
testcase( nSize==pPage->maxLocal );
testcase( nSize==pPage->maxLocal+1 );
testcase( nSize==(u32)pPage->maxLocal+1 );
if( nSize>pPage->maxLocal ){
nSize = minLocal;
}
@@ -4245,7 +4245,7 @@ static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){
int nPage = get4byte(&pPage1->aData[28]);
testcase( nPage==0 );
if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
testcase( pBt->nPage!=nPage );
testcase( pBt->nPage!=(u32)nPage );
pBt->nPage = nPage;
}
@@ -6810,16 +6810,18 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
if( *pRC ) return;
assert( idx>=0 && idx<pPage->nCell );
assert( idx>=0 );
assert( idx<pPage->nCell );
assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( pPage->nFree>=0 );
data = pPage->aData;
ptr = &pPage->aCellIdx[2*idx];
assert( pPage->pBt->usableSize > (int)(ptr-data) );
pc = get2byte(ptr);
hdr = pPage->hdrOffset;
testcase( pc==get2byte(&data[hdr+5]) );
testcase( pc==(u32)get2byte(&data[hdr+5]) );
testcase( pc+sz==pPage->pBt->usableSize );
if( pc+sz > pPage->pBt->usableSize ){
*pRC = SQLITE_CORRUPT_BKPT;
@@ -7111,7 +7113,7 @@ static int rebuildPage(
assert( i<iEnd );
j = get2byte(&aData[hdr+5]);
if( NEVER(j>(u32)usableSize) ){ j = 0; }
if( j>(u32)usableSize ){ j = 0; }
memcpy(&pTmp[j], &aData[j], usableSize - j);
for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
@@ -7342,7 +7344,7 @@ static int editPage(
pData = &aData[get2byteNotZero(&aData[hdr+5])];
if( pData<pBegin ) goto editpage_fail;
if( NEVER(pData>pPg->aDataEnd) ) goto editpage_fail;
if( pData>pPg->aDataEnd ) goto editpage_fail;
/* Add cells to the start of the page */
if( iNew<iOld ){
@@ -9245,7 +9247,12 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
iCellIdx = pCur->ix;
pPage = pCur->pPage;
pCell = findCell(pPage, iCellIdx);
if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT;
if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){
return SQLITE_CORRUPT_BKPT;
}
if( pPage->nCell<=iCellIdx ){
return SQLITE_CORRUPT_BKPT;
}
/* If the bPreserve flag is set to true, then the cursor position must
** be preserved following this delete operation. If the current delete
+88 -61
View File
@@ -346,6 +346,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
@@ -371,59 +404,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;
}
/*
@@ -448,6 +463,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;
@@ -464,9 +480,20 @@ 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++;
}
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
@@ -476,15 +503,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;
@@ -653,11 +678,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);
}
}
}
@@ -670,16 +694,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);
@@ -1284,7 +1309,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);
@@ -2902,7 +2927,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);
}
@@ -3454,7 +3479,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]);
@@ -3469,6 +3494,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.
@@ -3921,7 +3947,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) ){
@@ -4420,7 +4446,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);
}
@@ -4570,6 +4596,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.
@@ -515,15 +572,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
@@ -311,6 +311,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
@@ -2457,7 +2457,7 @@ int sqlite3ExprCanBeNull(const Expr *p){
return ExprHasProperty(p, EP_CanBeNull) ||
p->y.pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0
&& ALWAYS(p->y.pTab->aCol!=0) /* Defense against OOM problems */
&& p->y.pTab->aCol!=0 /* Possible due to prior error */
&& p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
+19
View File
@@ -702,6 +702,25 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
}
}
/*
** Clear the apTrigger[] cache of CASCADE triggers for all foreign keys
** in a particular database. This needs to happen when the schema
** changes.
*/
void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){
HashElem *k;
Hash *pHash = &db->aDb[iDb].pSchema->tblHash;
for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k)){
Table *pTab = sqliteHashData(k);
FKey *pFKey;
if( !IsOrdinaryTable(pTab) ) continue;
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
fkTriggerDelete(db, pFKey->apTrigger[0]); pFKey->apTrigger[0] = 0;
fkTriggerDelete(db, pFKey->apTrigger[1]); pFKey->apTrigger[1] = 0;
}
}
}
/*
** This function is called to generate code that runs when table pTab is
** being dropped from the database. The SrcList passed as the second argument
+3 -2
View File
@@ -43,7 +43,7 @@ void sqlite3OpenTable(
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
assert( pPk->tnum==pTab->tnum );
assert( pPk->tnum==pTab->tnum || CORRUPT_DB );
sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
VdbeComment((v, "%s", pTab->zName));
@@ -2009,6 +2009,7 @@ void sqlite3GenerateConstraintChecks(
if( onError==OE_Replace /* IPK rule is REPLACE */
&& onError!=overrideError /* Rules for other constraints are different */
&& pTab->pIndex /* There exist other constraints */
&& !upsertIpkDelay /* IPK check already deferred by UPSERT */
){
ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
VdbeComment((v, "defer IPK REPLACE until last"));
@@ -2417,6 +2418,7 @@ void sqlite3GenerateConstraintChecks(
if( ipkTop ){
sqlite3VdbeGoto(v, ipkTop);
VdbeComment((v, "Do IPK REPLACE"));
assert( ipkBottom>0 );
sqlite3VdbeJumpHere(v, ipkBottom);
}
@@ -2547,7 +2549,6 @@ void sqlite3CompleteInsertion(
}
pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
if( update_flags==0 ){
+45 -11
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;
}
}
@@ -2857,6 +2869,8 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
}else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){
newLimit = 1;
}
db->aLimit[limitId] = newLimit;
}
@@ -3744,7 +3758,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;
@@ -3754,7 +3768,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 ){
@@ -3764,14 +3778,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;
@@ -3844,6 +3873,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;
}
@@ -4260,12 +4290,16 @@ int sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_IMPOSTER: {
sqlite3 *db = va_arg(ap, sqlite3*);
int iDb;
sqlite3_mutex_enter(db->mutex);
db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
db->init.busy = db->init.imposterTable = va_arg(ap,int);
db->init.newTnum = va_arg(ap,int);
if( db->init.busy==0 && db->init.newTnum>0 ){
sqlite3ResetAllSchemasOfConnection(db);
iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
if( iDb>=0 ){
db->init.iDb = iDb;
db->init.busy = db->init.imposterTable = va_arg(ap,int);
db->init.newTnum = va_arg(ap,int);
if( db->init.busy==0 && db->init.newTnum>0 ){
sqlite3ResetAllSchemasOfConnection(db);
}
}
sqlite3_mutex_leave(db->mutex);
break;
+1 -1
View File
@@ -265,7 +265,7 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
p->pFirst = 0;
}else{
i64 iOff = p->nChunkSize;
for(pIter=p->pFirst; ALWAYS(pIter) && iOff<=size; pIter=pIter->pNext){
for(pIter=p->pFirst; ALWAYS(pIter) && iOff<size; pIter=pIter->pNext){
iOff += p->nChunkSize;
}
if( ALWAYS(pIter) ){
+2 -2
View File
@@ -3917,7 +3917,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
#if defined(SQLITE_DEBUG)
static void assertTruncateConstraintCb(PgHdr *pPg){
assert( pPg->flags&PGHDR_DIRTY );
assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
assert( pPg->pgno<=pPg->pPager->dbSize || !subjRequiresPage(pPg) );
}
static void assertTruncateConstraint(Pager *pPager){
sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
@@ -5258,7 +5258,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
** may mean that the pager was in the error-state when this
** function was called and the journal file does not exist.
*/
if( !isOpen(pPager->jfd) ){
if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
sqlite3_vfs * const pVfs = pPager->pVfs;
int bExists; /* True if journal file exists */
rc = sqlite3OsAccess(
+10 -3
View File
@@ -475,7 +475,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 */
@@ -2027,9 +2033,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 */
+24 -17
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,21 +251,21 @@ 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",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_OneSchema,
/* ColNames: */ 47, 3,
/* iArg: */ 0 },
#endif
#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
+128 -11
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. */
@@ -747,7 +857,7 @@ static int sqlite3Prepare(
sParse.checkSchema = 0;
}
if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
if( sParse.checkSchema ){
if( sParse.checkSchema && db->init.busy==0 ){
schemaIsValid(&sParse);
}
if( sParse.pVdbe ){
@@ -792,6 +902,7 @@ static int sqlite3LockAndPrepare(
){
int rc;
int cnt = 0;
int bReleaseSchema = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
@@ -801,6 +912,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
@@ -808,9 +920,14 @@ static int sqlite3LockAndPrepare(
** reset is considered a permanent error. */
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
assert( rc==SQLITE_OK || *ppStmt==0 );
if( rc==SQLITE_OK || db->mallocFailed ) break;
}while( rc==SQLITE_ERROR_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;
+308 -42
View File
@@ -1191,13 +1191,14 @@ struct 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
*/
@@ -4157,6 +4158,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
#ifndef SQLITE_NOHAVE_SYSTEM
".shell CMD ARGS... Run CMD ARGS... in a system shell",
#endif
@@ -4696,6 +4703,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,
@@ -6951,6 +6963,237 @@ static char *shellMPrintf(int *pRc, const char *zFmt, ...){
}
return z;
}
static int sharedSchemaFix(ShellState *pState, const char *zDb, int eFix){
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], eFix);
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;
}
/*
** When running the ".recover" command, each output table, and the special
@@ -8941,16 +9184,8 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zNewFilename = 0; /* Name of the database file to open */
int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */
/* Close the existing database */
session_close_all(p, -1);
close_db(p->db);
p->db = 0;
p->pAuxDb->zDbFilename = 0;
sqlite3_free(p->pAuxDb->zFreeOnClose);
p->pAuxDb->zFreeOnClose = 0;
p->openMode = SHELL_OPEN_UNSPEC;
p->openFlags = 0;
p->szMax = 0;
int openMode = SHELL_OPEN_UNSPEC;
/* Check for command-line arguments */
for(iName=1; iName<nArg; iName++){
const char *z = azArg[iName];
@@ -8958,19 +9193,21 @@ static int do_meta_command(char *zLine, ShellState *p){
newFlag = 1;
#ifdef SQLITE_HAVE_ZLIB
}else if( optionMatch(z, "zip") ){
p->openMode = SHELL_OPEN_ZIPFILE;
openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( optionMatch(z, "append") ){
p->openMode = SHELL_OPEN_APPENDVFS;
openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
p->openMode = SHELL_OPEN_READONLY;
openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "sharedschema") ){
p->openMode = SHELL_OPEN_SHAREDSCHEMA;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE;
openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
p->openMode = SHELL_OPEN_HEXDB;
openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){
p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
@@ -8986,6 +9223,18 @@ static int do_meta_command(char *zLine, ShellState *p){
zNewFilename = sqlite3_mprintf("%s", z);
}
}
/* Close the existing database */
session_close_all(p, -1);
close_db(p->db);
p->db = 0;
p->pAuxDb->zDbFilename = 0;
sqlite3_free(p->pAuxDb->zFreeOnClose);
p->pAuxDb->zFreeOnClose = 0;
p->openMode = openMode;
p->openFlags = 0;
p->szMax = 0;
/* If a filename is specified, try to open it first */
if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename);
@@ -9994,6 +10243,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
#ifndef SQLITE_NOHAVE_SYSTEM
if( c=='s'
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
@@ -10204,30 +10460,31 @@ static int do_meta_command(char *zLine, ShellState *p){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
int unSafe; /* Not valid for --safe mode */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
{ "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
{ "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
/*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
/*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
{ "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/
{ "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
{ "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
{ "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
{ "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
/*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
/*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
{ "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
{ "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
{ "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
#ifdef YYCOVERAGE
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
#endif
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
{ "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, "NMAX" },
{ "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" },
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
{ "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
{ "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
};
int testctrl = -1;
int iCtrl = -1;
@@ -10275,6 +10532,11 @@ static int do_meta_command(char *zLine, ShellState *p){
if( testctrl<0 ){
utf8_printf(stderr,"Error: unknown test-control: %s\n"
"Use \".testctrl --help\" for help\n", zCmd);
}else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
utf8_printf(stderr,
"line %d: \".testctrl %s\" may not be used in safe mode\n",
p->lineno, aCtrl[iCtrl].zCtrlName);
exit(1);
}else{
switch(testctrl){
@@ -11446,6 +11708,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
}else if( strcmp(z,"-sharedschema")==0 ){
data.openMode = SHELL_OPEN_SHAREDSCHEMA;
}else if( strcmp(z,"-nofollow")==0 ){
data.openFlags = SQLITE_OPEN_NOFOLLOW;
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
@@ -11568,6 +11832,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
}else if( strcmp(z,"-sharedschema")==0 ){
data.openMode = SHELL_OPEN_SHAREDSCHEMA;
}else if( strcmp(z,"-nofollow")==0 ){
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
}else if( strcmp(z,"-ascii")==0 ){
+2 -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
**
+51 -2
View File
@@ -1164,6 +1164,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;
@@ -1300,6 +1301,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
};
/*
@@ -1331,6 +1336,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
};
/*
@@ -1654,6 +1662,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.
*/
@@ -1735,6 +1749,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
@@ -2222,6 +2239,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
@@ -3555,6 +3575,8 @@ struct Parse {
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
union {
int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
Returning *pReturning; /* The RETURNING clause */
@@ -3609,9 +3631,7 @@ struct Parse {
Token sArg; /* Complete text of a module argument */
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
#ifndef SQLITE_OMIT_ALTERTABLE
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
#endif
@@ -3723,6 +3743,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
};
/*
@@ -3834,6 +3857,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;
@@ -4945,6 +4969,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)
# 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);
@@ -5145,6 +5192,7 @@ const char *sqlite3JournalModename(int);
int sqlite3FkRequired(Parse*, Table*, int*, int);
u32 sqlite3FkOldmask(Parse*, Table*);
FKey *sqlite3FkReferences(Table *);
void sqlite3FkClearTriggerCache(sqlite3*,int);
#else
#define sqlite3FkActions(a,b,c,d,e,f)
#define sqlite3FkCheck(a,b,c,d,e,f)
@@ -5152,6 +5200,7 @@ const char *sqlite3JournalModename(int);
#define sqlite3FkOldmask(a,b) 0
#define sqlite3FkRequired(a,b,c,d) 0
#define sqlite3FkReferences(a) 0
#define sqlite3FkClearTriggerCache(a,b)
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
void sqlite3FkDelete(sqlite3 *, Table*);
+21 -1
View File
@@ -288,11 +288,24 @@ 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;
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;
@@ -314,7 +327,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;
sqlite3BtreeLeaveAll(db);
+13
View File
@@ -3693,6 +3693,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;
}
@@ -3824,6 +3827,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*);
@@ -148,6 +149,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);
+48 -10
View File
@@ -52,6 +52,14 @@ 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
if( pParse->disableTriggers ){
return 0;
}
@@ -60,7 +68,20 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
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
@@ -70,7 +91,7 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
}else if( pTrig->op==TK_RETURNING
#ifndef SQLITE_OMIT_VIRTUALTABLE
&& pParse->db->pVtabCtx==0
#endif
#endif
){
assert( pParse->bReturning );
assert( &(pParse->u1.pReturning->retTrig) == pTrig );
@@ -261,6 +282,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;
@@ -367,7 +394,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);
}
@@ -585,6 +612,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);
@@ -656,6 +686,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
@@ -933,7 +964,7 @@ static void codeReturningTrigger(
}
sqlite3ExprListDelete(db, sSelect.pEList);
pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
if( pNew ){
if( !db->mallocFailed ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
if( pReturning->nRetCol==0 ){
@@ -945,7 +976,9 @@ static void codeReturningTrigger(
sNC.ncFlags = NC_UBaseReg;
pParse->eTriggerOp = pTrigger->op;
pParse->pTriggerTab = pTab;
if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK ){
if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK
&& !db->mallocFailed
){
int i;
int nCol = pNew->nExpr;
int reg = pParse->nMem+1;
@@ -953,16 +986,17 @@ static void codeReturningTrigger(
pReturning->iRetReg = reg;
for(i=0; i<nCol; i++){
Expr *pCol = pNew->a[i].pExpr;
assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */
sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
}
sqlite3ExprListDelete(db, pNew);
pParse->eTriggerOp = 0;
pParse->pTriggerTab = 0;
}
sqlite3ExprListDelete(db, pNew);
pParse->eTriggerOp = 0;
pParse->pTriggerTab = 0;
}
@@ -1107,7 +1141,9 @@ static TriggerPrg *codeRowTrigger(
Parse *pSubParse; /* Parse context for sub-vdbe */
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
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
@@ -1215,7 +1251,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);
+8 -7
View File
@@ -3720,13 +3720,6 @@ case OP_Transaction: {
&& (iMeta!=pOp->p3
|| db->aDb[pOp->p1].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.
@@ -3743,6 +3736,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;
}
@@ -3813,6 +3813,7 @@ case OP_SetCookie: {
/* When the schema cookie changes, record the new cookie internally */
pDb->pSchema->schema_cookie = pOp->p3 - pOp->p5;
db->mDbFlags |= DBFLAG_SchemaChange;
sqlite3FkClearTriggerCache(db, pOp->p1);
}else if( pOp->p2==BTREE_FILE_FORMAT ){
/* Record changes in the file format */
pDb->pSchema->file_format = pOp->p3;
+1 -1
View File
@@ -223,7 +223,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
@@ -473,8 +473,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);
@@ -4934,7 +4936,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
/* The index entry must begin with a header size */
getVarint32NR((u8*)m.z, szHdr);
testcase( szHdr==3 );
testcase( szHdr==m.n );
testcase( szHdr==(u32)m.n );
testcase( szHdr>0x7fffffff );
assert( m.n>=0 );
if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
+6
View File
@@ -134,7 +134,9 @@ int sqlite3_blob_open(
char *zErr = 0;
Table *pTab;
Incrblob *pBlob = 0;
Parse *pParentParse = db->pParse;
Parse sParse;
int bUnlock; /* True to unlock reusable schemas before returning */
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppBlob==0 ){
@@ -151,11 +153,13 @@ int sqlite3_blob_open(
sqlite3_mutex_enter(db->mutex);
bUnlock = sqlite3LockReusableSchema(db);
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
do {
memset(&sParse, 0, sizeof(Parse));
if( !pBlob ) goto blob_open_out;
sParse.db = db;
db->pParse = &sParse;
sqlite3DbFree(db, zErr);
zErr = 0;
@@ -335,6 +339,8 @@ int sqlite3_blob_open(
} while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
blob_open_out:
db->pParse = pParentParse;
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;
}
@@ -499,7 +517,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;
@@ -569,6 +587,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;
@@ -588,7 +607,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);
@@ -596,6 +619,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);
@@ -638,12 +665,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], "");
@@ -698,6 +736,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;
}
+5
View File
@@ -19,6 +19,11 @@ if {$::longdouble_size<=8} {
finish_test
return
}
if {![info exists tcl_platform(machine)]
|| $::tcl_platform(machine)!="x86_64"} {
finish_test
return
}
expr srand(1)
for {set i 1} {$i<20000} {incr i} {
+30
View File
@@ -241,5 +241,35 @@ do_execsql_test 7.2 {
PRAGMA foreign_key_check;
} {}
# 2021-12-31 forum https://sqlite.org/forum/forumpost/24bd1fef7e9323ef
# Memory leak caused by sqlite3NestedParse() running on a corrupt system
# table. Discovered by Jingzhou Fu.
#
reset_db
do_execsql_test 8.1 {
PRAGMA writable_schema=ON;
PRAGMA foreign_keys = ON;
CREATE TABLE sqlite_stat1 (tbl INTEGER PRIMARY KEY DESC, idx UNIQUE DEFAULT NULL) WITHOUT ROWID;
PRAGMA writable_schema=OFF;
CREATE TABLE sqlsim4(stat PRIMARY KEY);;
CREATE TABLE t1(sqlsim7 REFERENCES sqlite_stat1 ON DELETE CASCADE);
DROP table "sqlsim4";
} {}
# 2022-01-01 dbsqlfuzz 1c57440219f6f0aedf5e8f72a8ddd75f15aea381
# Follow-up case to the above. Assertion is not true if the schema
# is corrupt.
reset_db
database_may_be_corrupt
do_execsql_test 8.2 {
CREATE TABLE t1(a REFERENCES sqlite_stat1 ON DELETE CASCADE);
CREATE TABLE t2(a TEXT PRIMARY KEY);
PRAGMA writable_schema=ON;
CREATE TABLE sqlite_stat1(tbl INTEGER PRIMARY KEY DESC, idx UNIQUE DEFAULT NULL) WITHOUT ROWID;
UPDATE sqlite_schema SET name='sqlite_autoindex_sqlite_stat1_1' WHERE name='sqlite_autoindex_sqlite_stat1_2';
PRAGMA writable_schema=RESET;
} {}
do_catchsql_test 8.3 {
REINDEX;
} {1 {database disk image is malformed}}
finish_test
+62
View File
@@ -0,0 +1,62 @@
# 2022 Jan 01
#
# 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.
#
#***********************************************************************
# Tests focused on the in-memory journal.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix memjournal2
do_execsql_test 1.0 {
PRAGMA journal_mode = memory;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
} {memory}
set nRow [expr 2000]
do_execsql_test 1.1 {
BEGIN;
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<$nRow
)
INSERT INTO t1 SELECT NULL, randomblob(700) FROM s;
}
for {set jj 200} {$jj <= 300} {incr jj} {
do_execsql_test 1.2.$jj.1 {
SAVEPOINT one;
UPDATE t1 SET b=randomblob(700) WHERE a<=$jj;
}
do_execsql_test 1.2.$jj.2 {
SAVEPOINT two;
UPDATE t1 SET b=randomblob(700) WHERE a==1;
ROLLBACK TO two;
RELEASE two;
}
do_execsql_test 1.2.$jj.3 {
SAVEPOINT two;
UPDATE t1 SET b=randomblob(700) WHERE a==1;
ROLLBACK TO two;
RELEASE two;
}
do_execsql_test 1.2.$jj.4 {
PRAGMA integrity_check;
ROLLBACK TO one;
RELEASE one;
} {ok}
}
finish_test
+36
View File
@@ -0,0 +1,36 @@
# 2022 January 5
#
# 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
source $testdir/malloc_common.tcl
do_execsql_test 1.0 {
CREATE TABLE t1 (b);
} {}
faultsim_save_and_close
do_faultsim_test pagerfault-1 -faults oom-t* -prep {
faultsim_restore_and_reopen
} -body {
execsql {
INSERT INTO t1(b) VALUES(65) RETURNING (
SELECT * FROM sqlite_temp_schema
) AS aaa;
}
} -test {
faultsim_test_result {1 {sub-select returns 5 columns - expected 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
+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);"
+14
View File
@@ -241,4 +241,18 @@ do_catchsql_test upsert1-1000 {
ON CONFLICT(c2) DO UPDATE SET c1 = c0;
} {1 {NOT NULL constraint failed: t0.c0}}
# 2021-12-29 forum post https://sqlite.org/forum/forumpost/06b16b8b29f8c8c3
# By Jingzhou Fu. When there is both an INTEGER PRIMARY KEY ON CONFLICT REPLACE
# and an upsert on a constraint other than the INTEGER PRIMARY KEY, the
# constraint checking logic generates invalid bytecode which might result
# in a NULL pointer dereference.
#
reset_db
do_execsql_test upsert1-1100 {
CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b UNIQUE);
INSERT INTO t1(b) VALUES(22);
INSERT INTO t1 VALUES(2,22) ON CONFLICT (b) DO NOTHING;
SELECT * FROM t1;
} {1 22}
finish_test
+10 -2
View File
@@ -13,7 +13,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix windowB
set testprefix windowC
ifcapable !windowfunc {
finish_test
@@ -67,11 +67,19 @@ foreach {tn bBlob seps} {
#
reset_db
do_execsql_test 2.0 {
PRAGMA encoding=UTF16;
PRAGMA encoding=UTF16le;
WITH separator(x) AS (VALUES(',a,'),(',bc,')),
value(y) AS (VALUES(1),(x'5585d09013455178cd11ce4a'))
SELECT group_concat(y,x) OVER (ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
FROM separator, value;
} {{} 1 蕕郐䔓硑ᇍ䫎 1}
reset_db
do_execsql_test 2.1 {
PRAGMA encoding=UTF16be;
WITH separator(x) AS (VALUES(',a,'),(',bc,')),
value(y) AS (VALUES(1),(x'5585d09013455178cd11ce4a'))
SELECT group_concat(y,x) OVER (ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
FROM separator, value;
} {{} 1 喅킐ፅ典촑칊 1}
finish_test
+16 -1
View File
@@ -470,5 +470,20 @@ ifcapable altertable {
EXPLAIN QUERY PLAN SELECT * FROM dual, t1 WHERE a=10 AND b=10;
} {~/b=/}
}
# 2022-01-01 https://sqlite.org/forum/forumpost/b03d86f951 PoC #1
# Omit an assert() from 2013 that no longer serves any purpose and
# is no longer always true.
#
reset_db
do_execsql_test 15.1 {
PRAGMA writable_schema=ON;
CREATE TABLE sqlite_sequence (name PRIMARY KEY) WITHOUT ROWID;
PRAGMA writable_schema=OFF;
CREATE TABLE c1(x);
INSERT INTO sqlite_sequence(name) VALUES('c0'),('c1'),('c2');
ALTER TABLE c1 RENAME TO a;
SELECT name FROM sqlite_sequence ORDER BY +name;
} {a c0 c2}
finish_test
+3
View File
@@ -75,6 +75,9 @@ static sqlite3_uint64 logEstToInt(LogEst x){
x /= 10;
if( n>=5 ) n -= 2;
else if( n>=1 ) n -= 1;
if( x>60 ){
return (((sqlite3_uint64)0xffffffff)<<32)+(sqlite3_uint64)0xffffffff;
}
if( x>=3 ) return (n+8)<<(x-3);
return (n+8)>>(3-x);
}
+23 -17
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)
@@ -262,7 +262,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: database_list
FLAG: NeedSchema Result0
FLAG: NeedSchema Result0 OneSchema
COLS: seq name file
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
@@ -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} {
+3 -3
View File
@@ -726,7 +726,7 @@ static void decode_btree_page(
}
if( showMap ){
printf("Page map: (H=header P=cell-index 1=page-1-header .=free-space)\n");
for(i=0; i<g.pagesize; i+=64){
for(i=0; (u32)i<g.pagesize; i+=64){
printf(" %03x: %.64s\n", i, &zMap[i]);
}
sqlite3_free(zMap);
@@ -861,7 +861,7 @@ static int allZero(unsigned char *a, int n){
*/
static void page_usage_btree(
u32 pgno, /* Page to describe */
u32 parent, /* Parent of this page. 0 for root pages */
int parent, /* Parent of this page. 0 for root pages */
int idx, /* Which child of the parent */
const char *zName /* Name of the table */
){
@@ -954,7 +954,7 @@ static void page_usage_freelist(u32 pgno){
int iNext;
int parent = 1;
while( pgno>0 && pgno<=g.mxPage && (cnt++)<g.mxPage ){
while( pgno>0 && pgno<=g.mxPage && (u32)(cnt++)<g.mxPage ){
page_usage_msg(pgno, "freelist trunk #%d child of %d", cnt, parent);
a = fileRead((pgno-1)*g.pagesize, g.pagesize);
iNext = decodeInt32(a);