Compare commits

...

182 Commits

Author SHA1 Message Date
drh c9518d82dc Merge the 3.38.5 fix into the 3.38 subbranch of reuse-schema.
FossilOrigin-Name: bfccca2ba37dd99c28e10364ad85a3b8d5bd9547c6159cb7a1a2aa903a508e77
2022-05-06 17:06:28 +00:00
drh dcd7408db8 Version 3.38.5
FossilOrigin-Name: 78d9c993d404cdfaa7fdd2973fa1052e3da9f66215cff9c5540ebe55c407d9fe
2022-05-06 15:25:27 +00:00
drh 3666744c10 Prevent an infinite loop on SQLITE_ERROR_RETRY when trying to modify a
corrupt schema while PRAGMA writeable_schema=ON is active.
dbsqlfuzz ded83609f475cc989c7339d45efb5151c1495501

FossilOrigin-Name: 7fcdb760a4df8c5c11e94cecdc61bb8f40c86b70aa05f48e17520443a3d3b451
2022-05-06 01:02:05 +00:00
drh 3fa6f4d248 Update the version number to 3.38.5
FossilOrigin-Name: bf73b57f700ea43cd8c5849dc8d7cca184329c77b065aa3da9459ce58959d3e9
2022-05-05 10:04:38 +00:00
drh 5c701b2f56 Backout check-in [9fb20a21feb8f697] which was incorrect.
FossilOrigin-Name: 66f65b322a85c971d72397c2d7315504cc53b295bc9e207b2dfc07b9eea5fee8
2022-05-05 10:03:19 +00:00
drh ec477b6333 Merge version-3.38.4 into the reuse-schema-3.38 subbranch.
FossilOrigin-Name: d5b0fd8434f893db444eb62e254871d92a593c3c4871641b0392453444444e15
2022-05-04 16:46:10 +00:00
drh f5dc59e376 Version 3.38.4
FossilOrigin-Name: d402f49871152670a62f4f28cacb15d814f2c1644e9347ad7d258e562978e45e
2022-05-04 15:45:55 +00:00
larrybr 85ba44e1ee Fix CLI use of wrong allocator for free().
FossilOrigin-Name: 4f83c442c9b34abc292566b9547d3bd265e7a5e9662472fd6498faa22aafdd24
2022-05-04 03:48:07 +00:00
larrybr 5854a3611c Fix multi-byte column name rendition on .import and display of NULL in columnar modes.
FossilOrigin-Name: f863aabe9da11b9d424362543536c929f34a0f632ba973c278d4cd56e21960fa
2022-05-03 19:51:22 +00:00
drh c62e616278 Increase the version number to 3.38.4.
FossilOrigin-Name: def971a0e90212a2387967d4a4b266a7c39129ad66fb7df7bf11f6979d1e524a
2022-05-03 14:26:58 +00:00
drh 30b35a5572 Fix the Bloom filter pull-down optimization so that it jumps to the correct
place if it encounters a NULL key.  Fix for the bug described by
[forum:/forumpost/2482b32700384a0f|forum thread 2482b32700384a0f].

FossilOrigin-Name: 3dc9fc2f2de8696b67d0fc6f414398625d6fe7de108e95b443fb11e8f460b84c
2022-05-03 14:25:52 +00:00
drh 20ccfc67e2 Preserve the COLLATE operator on an index on an expression when resolving
the use of that expression into a reference to the index.  See
[forum:/info/7efabf4b03328e57|forum thread 7efabf4b03328e57] for details.

FossilOrigin-Name: ef72f9e289966d4bad5a2fa37d640f318dd972a9cf669425696e3e2a547fccb6
2022-04-30 12:55:29 +00:00
drh 006756c7cf Merge the version 3.38.3 fixes into the reuse-schema-3.8 subbranch.
FossilOrigin-Name: 436d0a5837a750bfb66493de6efd0a9a5d8e8b66cedab433414a1f48921f2857
2022-04-27 13:12:16 +00:00
drh a0b146cf30 Version 3.38.3
FossilOrigin-Name: 9547e2c38a1c6f751a77d4d796894dec4dc5d8f5d79b1cd39e1ffc50df7b3be4
2022-04-27 12:03:15 +00:00
drh 69110cb32a Modify utility function sqlite3SetString() so that it may be used safely on Parse.zErrMsg. Fuzzer test case "crash-1604e5d76c92574e21e437049dab9b672e06b767.txt".
FossilOrigin-Name: b9c7d2c1bdc529b8c367e4a0894f4c966957cfa4b427175d5aa10af6a25f4f12
2022-04-26 20:58:48 +00:00
drh 214bd2ebe2 Cherry-pick various minor fixes from trunk into branch-3.38.
FossilOrigin-Name: fece097c707ba563abfeca82a3d8f6fe6e90d73ae8a8ecaa4695131baa76b3b1
2022-04-26 19:48:23 +00:00
drh fc2f28fda0 Reverse the order of two tests to stop a harmless initialized value
warning from MSAN - reported by OSSFuzz.

FossilOrigin-Name: fb7e1a07a936857b2e9e50042a43d239817053e6dd3e36f3d2c55ec41fd3bdf3
2022-04-25 23:00:56 +00:00
drh ea03c17bcf Fix a problem with using multiple SQLITE_SUBTYPE function as window functions in a single query.
FossilOrigin-Name: 9caca6cb3e4eee9801cfb6f3def9b063f14c4d46269a0c4322c13a6e5f62f5a7
2022-04-25 21:31:28 +00:00
drh ba7516ae4a Increase the version number to 3.38.3.
FossilOrigin-Name: b113afa2245f465b2e3db4be3c2a323b9e6d100e7d0b462358f732402ae3e1dc
2022-04-25 21:22:59 +00:00
drh 3c2635c376 Fix a problem with automatic indexes introduced by
check-in [664b461bb5063d980] and reported by
[forum:/forumpost/0d3200f4f3bcd3a3|forum post 0d3200f4f3bcd3a3].

FossilOrigin-Name: 4fbb9ffe72f112d5f3b02760759b90ef935ddff4089013caac3a9e222a98a304
2022-04-25 21:21:08 +00:00
drh 9085b56c69 Fix two minor problems in the JSON functions associated with JSON Paths
for object labels that require quoting.

FossilOrigin-Name: 4a1553b55f085163278866617deb26df12571c55fc650f8daa9392fd77c1eba9
2022-04-04 15:26:31 +00:00
larrybr 1c3c8e00bd Incorporate fix noted as absent by forum post https://sqlite.org/forum/forumpost/aefd62fcc7ebd8b6
FossilOrigin-Name: 336851b191fe79f0282148b5c42976df9d1ce584fc93e523bc1cd2cf0c2912e7
2022-03-30 11:12:04 +00:00
drh 6750234960 Merge the version 3.38.2 patches into the reuse-schema-3.38 sub-branch.
FossilOrigin-Name: 07fc5c6eff89419ea9b8d741ea33ac853fa83bab3d78f62f652de47875c623d5
2022-03-26 14:14:08 +00:00
drh 86fbbbf964 Version 3.38.2
FossilOrigin-Name: d33c709cc0af66bc5b6dc6216eba9f1f0b40960b9ae83694c986fbf4c1d6f08f
2022-03-26 13:51:10 +00:00
drh 5eea5054d0 The "PRAGMA writable_schema=ON" flag should not allow OOM errors to pass
while parsing the schema.
dbsqlfuzz 9cc49e1a53e1cef8e3a1496a88c683aa20483163.

FossilOrigin-Name: 4977d8f453bcd56fb1dfab02cc5b283fb32d402bafdf2b6112e7dd322b7c32ad
2022-03-25 19:16:26 +00:00
drh b64cf9b28c Do not allow an #ifdef inside of an assert(), as gcc tells us that is
not portable.

FossilOrigin-Name: b193156c2a2407146e7cf77e237e0de0766d4ce8c673547d9f2bda4a1814959b
2022-03-25 17:43:32 +00:00
drh 2dc539addd Bump the version number to 3.38.2.
FossilOrigin-Name: bb3ef206ab4a92bef16cd53bf23f574e720ed4709baba58700e04dbf48c1347e
2022-03-25 01:37:26 +00:00
drh e62f31cdb4 Fix the Bloom-filter optimization so that it does not use IS NULL or
IS NOT NULL constraints from the WHERE clause when operating on a LEFT JOIN.
[forum:/forumpost/031e262a89b6a9d2|Forum thread 031e262a89b6a9d2].

FossilOrigin-Name: 8246bfbc1643497fbbebe950b5e297fdc2a90359603e5c01a79ba67168bd7d02
2022-03-25 01:31:18 +00:00
drh 1905379eb1 Ensure that database corruption does not cause the cursor passed into
sqlite3BtreeDelete() to be invalid.
dbsqlfuzz 209bf3de9ee11ae440848ab9bc9c13858f9be2e4.

FossilOrigin-Name: 780d00d4ec8c87229a639671a610c4561f2ab2b1729bb9a4386547ac18772dd4
2022-03-22 23:47:25 +00:00
drh 51907db8ca Harden the xShmLock method of both the unix and Windows VFSes so that they
are robust against being invoked when the SHM file is not open.

FossilOrigin-Name: 06d4c4d17c49b98701e4b09c19c0cc68e65a0413850fda33b4991fa24fc84fa0
2022-03-22 20:02:53 +00:00
drh e40d899afe Strengthen the defenses against corrupt databases in the
sqlite3BtreeInsert() function of the btree module.
[forum:/forumpost/c7ec29905f|Forum post c7ec29905f].

FossilOrigin-Name: 883fec9c3a410280bd5160acf1e103fa3c5fb6c6a003b2b99567d3b7037bc07e
2022-03-21 18:23:24 +00:00
drh 2f0ebf5e5c The previous assert() fix was not correct when building with
-DSQLITE_ENABLE_OFFSET_SQL_FUNC.  This is the fix.

FossilOrigin-Name: b4210bc0ba1dddd163884b75a7bcc21d580598bdab06f938b0f84982274d6346
2022-03-21 16:34:19 +00:00
drh 2fc20b68e8 Fix the assert() that attempts to verify that the table-reference to
index-reference translator finds all required translations.
[forum:/forumpost/929168fdd6|Forum post 929168fdd6].

FossilOrigin-Name: ccd2a2a7e197736a18dce28272fdb4acdf8447342523819c545d28e744c99562
2022-03-21 13:55:56 +00:00
drh 52fceac318 Fix an assert() in sqlite3TableAffinity() that might have been false if there
was a prior syntax error in the query.

FossilOrigin-Name: 940f1a400bcd58c2dc135955f261df5f96615339645c25583947f1a7dedae4ce
2022-03-21 11:50:28 +00:00
drh 72327c367c Fix the zipfile extension so that it knows that a zero-length BLOB returns
a NULL pointer.
[forum:/forumpost/ae86934905|Forum post ae86934905].

FossilOrigin-Name: b75c6bad3a5a165948077026441f02188ba30c7960815486c1973e18992401b3
2022-03-19 12:53:43 +00:00
drh 7fa8b4acf4 Another fix for a corner-case in sqlite_offset() - this one having to
do with computed virtual columns in a WITHOUT ROWID table.  Also an
assertion fault problem with sqlite_offset().

FossilOrigin-Name: 9e72cae2f15bdd1466ff4fe1e9b747d7630b581bccd8b13d1fd69e33a81a0f72
2022-03-17 11:37:02 +00:00
drh 8a5d1585f1 Disable trigger coding while running sqlite3_declare_vtab().
dbsqlfuzz 97e1865771b4226f29e6e482411c1cae14133f50

FossilOrigin-Name: 5b8a0460a2ea8720731282a396e5de835cf87876d41f7d861712b160706b838d
2022-03-14 20:39:57 +00:00
drh 2b456c8130 Merge the version 3.38.1 patches into a sub-branch of reuse-schema.
FossilOrigin-Name: 934276d15ed02310e0e88cb7c3332022a5020276ed3863713cd643b023d438a8
2022-03-12 15:30:23 +00:00
drh e3afca73dc Version 3.38.1
FossilOrigin-Name: 38c210fdd258658321c85ec9c01a072fda3ada94540e3239d29b34dc547a8cbc
2022-03-12 13:37:29 +00:00
drh 3e7d815579 Fix a case in fts5 where a corrupt database could cause a crash.
FossilOrigin-Name: 1894577c8eff6d0cb586cc8cd3a8f6a2b5800b9aa6391261121f4e26c9ba5f8f
2022-03-11 12:40:18 +00:00
drh 401697bb54 Stronger defenses against corrupt schemas in the ALTER TABLE logic.
FossilOrigin-Name: 29744e69f473638796877bd073468046d4aeff209c0a0f30beee8c5f102112b6
2022-03-10 21:14:35 +00:00
larrybr c606152c7b Doc improvements re sqlite3_column_text*() endianness (no code change)
FossilOrigin-Name: a37c20d40f97570575abb1f1db31dbc934300e7f2294d38fe41850baedb3766f
2022-03-10 19:53:49 +00:00
drh d8659ad141 Prevent a NULL-pointer dereference when trying to parse a illegal
schema entry that contains a window function while doing a RENAME COLUMN.
[forum:/forumpost/ec2a2e0deb|Forum post ec2a2e0deb].

FossilOrigin-Name: 2c393228257490efcf609f3e428f0d02c74cbea48a28763b2414e69a4ced66da
2022-03-10 16:28:13 +00:00
drh 4acead62b1 Check-in [642a0b4752743216] fixing sqlite_dbpage is not exactly correct.
This patch should fix it.

FossilOrigin-Name: b6c4c8a09a63693dd515d30a9f07f67ed81dc14df2586835fcb2b1bc6a9d01fc
2022-03-10 01:15:35 +00:00
drh c36de71968 Further refinements to the sqlite_offset() fix from [6029514b08b88e3f].
FossilOrigin-Name: 98799d7bbb6d62d71862d5fdfe87856995dd179d66612e369c5dc440e7fac31a
2022-03-09 18:30:55 +00:00
drh 468657ec19 Fix the sqlite_dbpage virtual table so that it starts a write transaction
on all attached schemas.

FossilOrigin-Name: e92c4fdb99eb09507e6b970067c1a6f2043838f67017125851469d66c1bb5b20
2022-03-09 14:29:33 +00:00
drh 3b7520b747 Fix a potentially uninitialized local variable in the ".import"
command of the CLI - introduced by [741651fd4b1b776b].  This same change
is part of the nearby [/info/5e30c6ea707f9d38|"Fix compiler warnings"]
check-in.

FossilOrigin-Name: ce9e3d903c2e5993a3fdadaf809ce2026efd1b5b933930b50dd794c9a7329cdd
2022-03-08 16:12:53 +00:00
drh c2384cdbea Disable an assert in moveToRoot() when the database is corrupt.
[forum:/forumpost/e9a176b7bd|Forum post e9a176b7bd].

FossilOrigin-Name: ab744a5da80ddcd5c7cce60626d82c0e368f675b8a11bfb93b4739ea30bb07c0
2022-03-07 18:38:12 +00:00
drh 54068138f0 Do not allocate new Trigger objects in the parser following a syntax error,
to avoid violating invariants associated with Expr nodes.  See
[forum:/forumpost/2024e94071ef1531|forum thread 2024e94071ef1531] for more
information.

FossilOrigin-Name: 369d240455a2806afb1699273864bca3f84b163c6b1f93807c9147437001132b
2022-03-07 16:40:44 +00:00
drh 312d0ec0a7 Fix the code generated for vector IN operator constraints on virtual tables
so that they work even if the "omit" field in the sqlite3_index_info object
is off.  This has apparently never worked correctly before.  Presumably, nobody
has ever before written a virtual table that can use vector IN operator
constraints and that relies on bytecode to double-check the constraints.
Test cases in TH3.  Problem discovered by
dbsqlfuzz cab8e26194a40147627094f3c6849c0a7b1e0310.

FossilOrigin-Name: 4a2040d5c78f42b892a080ba086f6ab32f59bb9c31b897af40c4359cdb17b0e9
2022-03-07 14:59:45 +00:00
drh 135f5fb747 Fix the .import problem in the CLI reported by
[forum:/forumpost/72a024c957|forum post 72a024c957].

FossilOrigin-Name: d753285bcbb68bdf8f6d95a64af58b20ce6da9f048734fdb0ae49150eb7befd4
2022-03-07 01:28:13 +00:00
drh 2614c7c873 The sqlite_offset() function should be non-deterministic.
dbsqlfuzz 3df8230bb940870db87ffca2c0fc759c1e7fa356.

FossilOrigin-Name: 8083757606920151171530f337919553fa8ba902a51744d7b21eeba1558db9fa
2022-03-06 11:44:14 +00:00
drh b9d060e934 Remove a NEVER() associated with sqlite_offset()>
FossilOrigin-Name: bf2501e26c8e4c08d679ea930bab89b9510808439aee9412ab176a9d29635cc7
2022-03-06 00:01:10 +00:00
drh 7b7932bed3 Fix the 'localtime' modifier in date/time functions so that it preserves
fractional seconds.
[forum:/forumpost/2ffbaa2c3fd7fb82|Forum post 2ffbaa2c3fd7fb82].

FossilOrigin-Name: 6833f4aeef4923c3633978720277ccbfc63b26c96092c12a6330e6d4629b5eb5
2022-03-05 20:20:45 +00:00
drh 1909223648 Increase the version number to 3.38.1.
FossilOrigin-Name: cd87e77dd062b6b9479c14f28bf7b94db86e3538d8977dc46f92fab8674dbec8
2022-03-05 19:46:17 +00:00
drh c95b28ebea Cherry-pick all bug fix changes since the 3.38.0 release.
FossilOrigin-Name: 45a5d5acf712cccf6d7043412fb21541ec00081d10fbd85421014677470a74f2
2022-03-05 19:39:19 +00:00
drh fa98d0ea0d Don't reload the schema on PRAGMA database_list.
FossilOrigin-Name: 630fe446da880b5320ff014a9f7dde683664eb5cb9fd47be5b9b32ed3c590f71
2022-02-22 20:38:45 +00:00
drh 4484700648 Merge version 3.38.0 into the reuse-schema branch.
FossilOrigin-Name: 8fe85dcdb1107a240379ea3e128c51e4be80232e632f4ec74de9b3a98e0c2061
2022-02-22 20:04:24 +00:00
drh d046825cce Merge the latest trunk changes into the reuse-schema branch.
FossilOrigin-Name: b3c26f4a34ab1557beddffccb818218a583c4daf078d338450eb79369fc2adf4
2022-02-21 16:49:49 +00:00
drh cee8c84dc9 Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: b9ba43fcb3b727fc344ab754a0132a62ff640daff8cc2ca17fd41e57fba2168d
2022-02-15 20:56:16 +00:00
drh 41a871f0d2 Merge trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 5744e1020b63f9eb89c12d6ea3ba33e17a6fea1478625c22240dcae50b50203e
2022-02-04 18:12:18 +00:00
drh da60a1b0be Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 6e4154d414afe2562b488149b10c175d1f15bd1d5060ee479d5ae9386a2e277e
2022-01-25 16:28:57 +00:00
drh 1546d749e3 Merge the latest trunk changes into the reuse-schema branch.
FossilOrigin-Name: 769ff85765746d3c94211ade114c6762baa76bb0db2dbe634334ca1beb4eed7f
2022-01-17 20:01:45 +00:00
drh bba8f23721 Merge version 3.37.0 into the reuse-schema branch.
FossilOrigin-Name: f83d50d5076339682c011329d7ab431ccaf134b37984706f199d878c3a88b553
2021-11-27 15:12:21 +00:00
drh 2ba1bb5b6f Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: d08832cb938a50891963446276d4ada3e73412ba6c316520f7cb8b180ae4f0f5
2021-11-22 16:05:44 +00:00
drh b2ded7c318 Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 748bce4c0172c60737c910c6f5b642259dcd4369b1fb473eb7fc48834fa0fcea
2021-11-09 14:00:57 +00:00
dan 9d04907363 Avoid accessing the sqlite3_module.xShadowName field if (sqlite3_module.iVersion<3).
FossilOrigin-Name: b1fc3de81e46e13f9bf592e8910a576e7573a700e8eac5be0bc839e7e2be53b6
2021-11-06 07:08:39 +00:00
drh bd564771f6 Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: ca09148e13d33a74ff75cf9c1d9e776ae0bf10ce8505656d8b5ca31398761b38
2021-11-05 23:32:17 +00:00
drh b7416ed80f Merge the latest trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 7623132efe9aaaf3a02d6c1ff82e199a075d2cadbe8030d2381c50509f862626
2021-10-29 14:04:22 +00:00
drh b963701038 Merge recent trunk enhancements into the reuse-schema branch
FossilOrigin-Name: cd15fc3c08373dad63ba7eafb117d0d09913b8fc339882fd909da5ec485a7138
2021-10-21 14:10:04 +00:00
drh 63f94dfe9f Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: 64234c5c9a5709e7c7c1b18bf32f4374692129b353c4698010abfc98bd00bcc4
2021-10-04 11:49:35 +00:00
drh fd89e834b8 Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: c8d1f17fde280acd3e98772d947a5b1e698b08d25b23bcd0731ae2d18cfbddcf
2021-08-09 18:17:26 +00:00
drh 339fbb64be Merge recent trunk enhancements into the reuse-schema branch.
FossilOrigin-Name: d71adc3fd85cfc5902b7146101d030ab2fbe932ed05848a407a7422ddeeb4c43
2021-08-03 16:11:59 +00:00
dan 3fc9378b03 Merge latest trunk changes into this branch.
FossilOrigin-Name: 0e968f9de3b706fedb675d058ed713a9e639c46d1482dec98c3449567242501e
2021-07-09 13:29:19 +00:00
drh bfab6fb822 Merge version 3.36.0
FossilOrigin-Name: 792215204d887ecb8b1a0d65773d272b84606c9867b52d94701039de5c8bb12c
2021-06-18 19:01:15 +00:00
drh 371cc2491f Merge recent trunk enhancements into reuse-schema branch.
FossilOrigin-Name: 92d8f967c9a7e4005c63703af8075b3d2ae5aa43c6b5bc6e599735dc4479bef6
2021-06-17 17:26:53 +00:00
dan babfb2e536 Update this branch with latest changes from trunk.
FossilOrigin-Name: f21a53fb4141eaeca2fb33b25bbadfad4e461b0ed1a3526f54a42316f3dd5d9b
2021-06-14 14:35:33 +00:00
drh 1b0b429f23 The SQLITE_ENABLE_SHARED_SCHEMA compile-time option is on by default in the
configure-generated makefile, permitting a complete test of this branch
using "./configure && make test".

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

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

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

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

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

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

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

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

FossilOrigin-Name: a625698048c05375f12ea8875892fdbf3518291f10917fe68dd2294280cd3b42
2017-08-09 20:35:10 +00:00
89 changed files with 4339 additions and 452 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 \
@@ -480,6 +482,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
@@ -1537,6 +1537,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.38.0
3.38.5
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.38.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.38.5.
#
#
# 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.38.0'
PACKAGE_STRING='sqlite 3.38.0'
PACKAGE_VERSION='3.38.5'
PACKAGE_STRING='sqlite 3.38.5'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1468,7 +1468,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.38.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.38.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1533,7 +1533,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.38.0:";;
short | recursive ) echo "Configuration of sqlite 3.38.5:";;
esac
cat <<\_ACEOF
@@ -1661,7 +1661,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.38.0
sqlite configure 3.38.5
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2080,7 +2080,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.38.0, which was
It was created by sqlite $as_me 3.38.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12390,7 +12390,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.38.0, which was
This file was extended by sqlite $as_me 3.38.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12456,7 +12456,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.38.0
sqlite config.status 3.38.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+142
View File
@@ -0,0 +1,142 @@
Shared-Schema Mode Notes
========================
The [reuse-schema](/timeline?r=reuse-schema) branch contains changes
to allow SQLite connections to share schemas
between database connections within the same process in order to save memory.
Schemas may be shared between multiple databases attached to the same or
distinct connection handles.
Compile with -DSQLITE\_ENABLE\_SHARED\_SCHEMA in order to enable the
shared-schema enhancement. Enabling the shared-schema enhancement causes
approximately a 0.1% increase in CPU cycles consumed and about a 3000-byte
increase in the size of the library, even if shared-schema is never used.
Assuming the compile-time requirements are satisfied, the shared-schema
feature is engaged by opening the database connection using the
sqlite3&#95;open&#95;v2() API with the SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA
flag specified. The main database and any attached databases will then share
an in-memory Schema object with any other database opened within the process
for which:
* the contents of the sqlite&#95;master table, including all object names,
SQL statements and root pages are identical, and
* have the same values for the schema-cookie.
Temp databases (those populated with "CREATE TEMP TABLE" and similar
statements) never share schemas.
Connections opened with the SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA flag
specified may not modify any database schema except that belonging to the
temp database in anyway. This includes creating or dropping database
objects, vacuuming the database, or running ANALYZE when the
sqlite&#95;stat\[14\] tables do not exist.
For SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA connections, the
SQLITE&#95;DBSTATUS&#95;SCHEMA&#95;USED sqlite3&#95;db&#95;status() verb
distributes the memory used for a shared schema object evenly between all
database connections that share it.
## The ".shared-schema" Command
The shell tool on this branch contains a special dot-command to help with
managing databases. The ".shared-schema" dot-command can be used to test
whether or not two databases are similar enough to share in-memory schemas,
and to fix minor problems that prevent them from doing so. To test if
two or more database are compatible, one database is opened directly using
the shell tool and the following command issued:
.shared-schema check <database-1> [<database-2>]...
where &lt;database-1&gt; etc. are replaced with the names of database files
on disk. For each database specified on the command line, a single line of
output is produced. If the database can share an in-memory schema with the
main database opened by the shell tool, the output is of the form:
<database> is compatible
Otherwise, if the database cannot share a schema with the main db, the output
is of the form:
<database> is NOT compatible (<reason>)
where &lt;reason&gt; indicates the cause of the incompatibility. &lt;reason&gt;
is always one of the following.
<ul>
<li> <b>objects</b> - the databases contain a different set schema objects
(tables, indexes, views and triggers).
<li> <b>SQL</b> - the databases contain the same set of objects, but the SQL
statements used to create them were not the same.
<li> <b>root pages</b> - the databases contain the same set of objects created
by the same SQL statements, but the root pages are not the same.
<li> <b>order of sqlite&#95;master rows</b> - the databases contain the same
set of objects created by the same SQL statements with the same root pages,
but the order of the rows in the sqlite&#95;master tables are different.
<li> <b>schema cookie</b> - the database schemas are compatible, but the
schema cookie values ("PRAGMA schema&#95;version") are different.
</ul>
The final three problems in the list above can be fixed using the
.shared-schema command. To modify such a database so that it can share a
schema with the main database, the following shell command is used:
.shared-schema fix <database-1> [<database-2>]...
If a database can be modified so that it may share a schema with the main
database opened by the shell tool, output is as follows:
Fixing <database>... <database> is compatible
If a database does not require modification, or cannot be modified such that
it can share a schema with the main database, the output of "fix" is identical
to that of the "check" command.
## Implementation Notes
A single Schema object is never used by more than one database simultaneously,
regardless of whether or not those databases are attached to the same or
different database handles. Instead, a pool of schema objects is maintained
for each unique sqlite&#95;master-contents/schema-cookie combination
opened within the process. Each time database schemas are required by a
connection, for example as part of an sqlite3&#95;prepare\*(),
sqlite3&#95;blob&#95;open() or sqlite3&#95;blob&#95;open() call, it obtains
the minimum number of schemas required from the various schema-pools, returning
them at the end of the call. This means that a single schema-pool only ever
contains more than one copy of the schema if:
* Two threads require schemas from the same pool at the same time, or
* A single sqlite3&#95;prepare\*() call requires schemas for two or more
attached databases that use the same schema-pool.
The size of a schema-pool never shrinks. Each schema pool always maintains
a number of schema objects equal to the highwater mark of schema objects
simultaneously required by clients.
This approach is preferred to allowing multiple databases to use the same
Schema object simultaneously for three reasons:
* The Schema object is not completely read-only. For example, the
Index.zIdxAff string is allocated lazily.
* Throughout the statement compiler, SQLite uses variables like
Table.pSchema and Index.pSchema with the sqlite3SchemaToIndex() routine
in order to determine which attached database a Table or Index object
resides in. This mechanism does not work if the same Schema may be
used by two or more attached databases.
* It may be easier to modify this approach in order to allow
SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA connections to modify database
schemas, should that be required.
SQLITE&#95;OPEN&#95;SHARED&#95;SCHEMA connections do not store their
virtual-table handles in the Table.pVTable list of each table. This would not
work, as (a) there is no guarantee that a connection will be assigned the same
Schema object each time it requests one from a schema-pool and (b) a single
Schema (and therefore Table) object may correspond to tables in two or more
databases attached to a single connection. Instead, all virtual-table handles
associated with a single database are stored in a linked-list headed at
Db.pVTable.
+1 -1
View File
@@ -804,7 +804,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
rc = sqlite3_step(pSorter->pStmt);
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
CsrFlagSet(pCsr, FTS5CSR_EOF);
CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT);
}else if( rc==SQLITE_ROW ){
const u8 *a;
const u8 *aBlob;
+154
View File
@@ -15366,6 +15366,160 @@ do_catchsql_test 79.2 {
INSERT INTO t1(t1) SELECT 'merge' FROM t2;
} {1 {query aborted}}
#-------------------------------------------------------------------------
reset_db
do_test 80.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 40960 pagesize 4096 filename crash-f928a9c1ec68dd.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 0a .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 0d 00 00 00 04 ................
| 96: 00 00 00 00 0d 00 00 00 0d 0b 6e 00 0f a3 0f 4c ..........n....L
| 112: 0e e1 0e 81 0e 24 0d cc 0d 72 0d 1b 0c b0 0c 50 .....$...r.....P
| 128: 0b f8 0b b3 0b 6e 00 00 00 00 00 00 00 00 00 00 .....n..........
| 2912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 0d ..............C.
| 2928: 06 17 11 11 08 75 74 61 62 6c 65 74 34 74 34 43 .....utablet4t4C
| 2944: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
| 2960: 42 4c 45 20 74 34 20 55 53 49 4e 47 20 66 74 73 BLE t4 USING fts
| 2976: 35 76 6f 63 61 62 28 27 74 32 27 2c 20 27 72 6f 5vocab('t2', 'ro
| 2992: 77 27 29 43 0c 06 17 11 11 08 75 74 61 62 6c 65 w')C......utable
| 3008: 74 33 74 33 43 52 45 41 54 45 20 56 49 52 54 55 t3t3CREATE VIRTU
| 3024: 41 4c 20 54 41 42 4c 45 20 74 33 20 55 53 49 4e AL TABLE t3 USIN
| 3040: 47 20 66 74 73 35 76 6f 63 61 62 28 27 74 31 27 G fts5vocab('t1'
| 3056: 2c 20 27 72 6f 77 27 29 56 0b 06 17 1f 1f 01 7d , 'row')V.......
| 3072: 74 61 62 6c 65 74 32 5f 63 6f 6e 66 69 67 74 32 tablet2_configt2
| 3088: 5f 63 6f 6e 66 69 67 0a 43 52 45 41 54 45 20 54 _config.CREATE T
| 3104: 41 42 4c 45 20 27 74 32 5f 63 6f 6e 66 69 67 27 ABLE 't2_config'
| 3120: 28 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 (k PRIMARY KEY,
| 3136: 76 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 v) WITHOUT ROWID
| 3152: 5e 0a 07 17 21 21 01 81 07 74 61 62 6c 65 74 32 ^...!!...tablet2
| 3168: 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 6f 6e 74 65 _contentt2_conte
| 3184: 6e 74 09 43 52 45 41 54 45 20 54 41 42 4c 45 20 nt.CREATE TABLE
| 3200: 27 74 32 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 't2_content'(id
| 3216: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
| 3232: 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 29 KEY, c0, c1, c2)
| 3248: 69 09 07 17 19 19 01 81 2d 74 61 62 6c 65 74 32 i.......-tablet2
| 3264: 5f 69 64 78 74 32 5f 69 64 78 08 43 52 45 41 54 _idxt2_idx.CREAT
| 3280: 45 20 54 41 42 4c 45 20 27 74 32 5f 69 64 78 27 E TABLE 't2_idx'
| 3296: 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 (segid, term, pg
| 3312: 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 no, PRIMARY KEY(
| 3328: 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 segid, term)) WI
| 3344: 54 48 4f 55 54 20 52 4f 57 49 44 55 08 07 17 1b THOUT ROWIDU....
| 3360: 1b 01 81 01 74 61 62 6c 65 74 32 5f 64 61 74 61 ....tablet2_data
| 3376: 74 32 5f 64 61 74 61 07 43 52 45 41 54 45 20 54 t2_data.CREATE T
| 3392: 41 42 4c 45 20 27 74 32 5f 64 61 74 61 27 28 69 ABLE 't2_data'(i
| 3408: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 d INTEGER PRIMAR
| 3424: 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f Y KEY, block BLO
| 3440: 42 29 58 07 07 17 11 11 08 81 1d 74 61 62 6c 65 B)X........table
| 3456: 74 32 74 32 43 52 45 41 54 45 20 56 49 52 54 55 t2t2CREATE VIRTU
| 3472: 41 4c 20 54 41 42 4c 45 20 74 32 20 55 53 49 4e AL TABLE t2 USIN
| 3488: 47 20 66 74 73 35 28 27 61 27 2c 5b 62 5d 2c 22 G fts5('a',[b],.
| 3504: 63 22 2c 64 65 74 61 69 6c 3d 6e 6f 6e 65 2c 63 c.,detail=none,c
| 3520: 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 56 06 06 17 olumnsize=0)V...
| 3536: 1f 1f 01 7d 74 61 62 6c 65 74 31 5f 63 6f 6e 66 ....tablet1_conf
| 3552: 69 67 74 31 5f 63 6f 6e 66 69 67 06 43 52 45 41 igt1_config.CREA
| 3568: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e TE TABLE 't1_con
| 3584: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b fig'(k PRIMARY K
| 3600: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52 EY, v) WITHOUT R
| 3616: 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 62 OWID[...!!...tab
| 3632: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64 let1_docsizet1_d
| 3648: 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 41 ocsize.CREATE TA
| 3664: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27 BLE 't1_docsize'
| 3680: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
| 3696: 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 ARY KEY, sz BLOB
| 3712: 29 5e 04 07 17 21 21 01 81 07 74 61 62 6c 65 74 )^...!!...tablet
| 3728: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1_contentt1_cont
| 3744: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
| 3760: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 69 64 't1_content'(id
| 3776: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
| 3792: 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 KEY, c0, c1, c2
| 3808: 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 74 )i.......-tablet
| 3824: 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 41 1_idxt1_idx.CREA
| 3840: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 78 TE TABLE 't1_idx
| 3856: 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 '(segid, term, p
| 3872: 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 gno, PRIMARY KEY
| 3888: 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 (segid, term)) W
| 3904: 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 17 ITHOUT ROWIDU...
| 3920: 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 74 .....tablet1_dat
| 3936: 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 20 at1_data.CREATE
| 3952: 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 28 TABLE 't1_data'(
| 3968: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 id INTEGER PRIMA
| 3984: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c RY KEY, block BL
| 4000: 4f 42 29 5b 01 07 17 11 11 08 81 23 74 61 62 6c OB)[.......#tabl
| 4016: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT
| 4032: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI
| 4048: 4e 47 20 66 74 73 35 28 61 2c 62 20 75 6e 69 6e NG fts5(a,b unin
| 4064: 64 65 78 65 64 2c 63 2c 74 6f 6b 65 6e 69 7a 65 dexed,c,tokenize
| 4080: 3d 22 70 6f 72 74 65 72 20 61 73 63 69 69 22 29 =.porter ascii.)
| page 2 offset 4096
| 0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 0f 7c ..h............|
| 16: 0f 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .*..............
| 3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 .......0........
| 3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80 ..........7.....
| 3888: 01 03 00 74 00 00 00 2e 02 30 61 03 02 02 01 01 ...t.....0a.....
| 3904: 62 03 02 03 01 01 63 03 02 04 01 01 67 03 06 01 b.....c.....g...
| 3920: 02 02 01 01 68 03 06 01 02 03 01 01 69 03 06 01 ....h.......i...
| 3936: 02 04 04 06 06 06 08 08 0f ef 00 14 2a 00 00 00 ............*...
| 3952: 00 01 02 02 00 02 01 01 01 02 01 01 25 88 80 80 ............%...
| 3968: 80 80 01 03 00 50 00 00 00 1f 02 30 67 02 08 02 .....P.....0g...
| 3984: 01 02 02 01 01 68 02 08 03 01 02 03 01 01 69 02 .....h........i.
| 4000: 08 04 01 02 04 04 09 09 37 84 80 80 80 80 01 03 ........7.......
| 4016: 00 74 00 00 00 2e 02 30 61 01 02 02 01 01 62 01 .t.....0a.....b.
| 4032: 02 03 01 01 63 01 02 04 01 01 67 01 06 01 02 02 ....c.....g.....
| 4048: 01 01 68 01 06 01 02 03 01 01 69 01 06 01 02 04 ..h.......i.....
| 4064: 04 06 06 06 08 08 07 01 03 00 14 03 09 00 09 00 ................
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
| page 5 offset 16384
| 0: 0d 00 00 00 03 0f e8 00 0f f8 0f f0 0f e8 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 03 ................
| 4080: 06 02 03 00 12 03 00 03 06 01 03 00 12 03 00 03 ................
| page 6 offset 20480
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 01 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| page 7 offset 24576
| 0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 00 00 00 00 ................
| 3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84 ..............A.
| 4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61 ............4.0a
| 4016: 01 01 01 01 01 62 01 01 01 01 01 63 01 01 01 01 .....b.....c....
| 4032: 01 64 01 01 01 65 01 01 01 66 01 01 01 67 01 01 .d...e...f...g..
| 4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 06 06 ...h.....i......
| 4064: 06 04 04 04 06 06 07 01 03 00 14 03 09 09 09 0f ................
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 8 offset 28672
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 12 ................
| page 9 offset 32768
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
| page 10 offset 36864
| 0: 0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 00 00 00 00 ........vers....
| end crash-f928a9c1ec68dd.db
}]} {}
do_catchsql_test 80.1 {
SELECT snippet(rowid, -1, '.', '..', '[', '(]'),snippet(rowid, -1, '.', '.', '', '(]'), highlight(t1, 29, 1 , '') FROM t1('g+ h') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY NOT (SELECT 1 FROM t1('g+ æ') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY rank);
} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test
+5
View File
@@ -1262,9 +1262,14 @@ static int zipfileFilter(
zipfileCursorErr(pCsr, "zipfile() function requires an argument");
return SQLITE_ERROR;
}else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
static const u8 aEmptyBlob = 0;
const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
int nBlob = sqlite3_value_bytes(argv[0]);
assert( pTab->pFirstEntry==0 );
if( aBlob==0 ){
aBlob = &aEmptyBlob;
nBlob = 0;
}
rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
pCsr->pFreeEntry = pTab->pFirstEntry;
pTab->pFirstEntry = pTab->pLastEntry = 0;
+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 \
@@ -400,6 +401,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 \
+92 -82
View File
@@ -1,13 +1,13 @@
C For\sthe\s"PRAGMA\sdatabase_list"\sstatement,\sdo\snot\scheck\sto\ssee\sif\sthe\sschema\nis\sup-to-date\sand\sdo\snot\stry\sto\sreload\sthe\sschema.
D 2022-02-22T20:29:31.035
C Merge\sthe\s3.38.5\sfix\sinto\sthe\s3.38\ssubbranch\sof\sreuse-schema.
D 2022-05-06T17:06:28.682
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in b210ad2733317f1a4353085dfb9d385ceec30b0e6a61d20a5accabecac6b1949
F Makefile.in bd57b03256fce1d968c432166e063232fa2659963ecd45f1cc2ff77b8aec850d
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
F Makefile.msc b28a8a7a977e7312f6859f560348e1eb110c21bd6cf9fab0d16537c0a514eef3
F Makefile.msc fccc0062959ce30dde9fa79c88e77939637fd43706b9f3dd4f68065b5594e9b5
F README.md 2dd87a5c1d108b224921f3dd47dea567973f706e1f6959386282a626f459a70c
F VERSION 392c2f83569705069415a5d98b1c138ec8fe8a56a663a0d94cea019e806537b2
F VERSION 2cef599294698e267cbcdadf44f14a0637a0015c1872cb37a16fe723d7c7add0
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -34,13 +34,14 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure a2877fe63cc821af0df41abe70f1f7c4e97cb7e23a42e0a1402e8a2f55a88aa2 x
F configure d616d46e32a1c2324a561b464175907b976ff62e8946b14e9954268841fc0bb8 x
F configure.ac 3ef6eeff4387585bfcab76b0c3f6e15a0618587bb90245dd5d44e4378141bb35
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/shared_schema.md 759fc374709fccf4e5d2d0cbd05f8fedd38fb022bdd8a6c5b5f492684c7023b9
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
@@ -120,7 +121,7 @@ F ext/fts5/fts5_config.c 501e7d3566bc92766b0e11c0109a7c5a6146bc41144195459af5422
F ext/fts5/fts5_expr.c fcd0770d53028c2b53a15d0f53bf6d0e01b1bf3dd97630b9fedf0801f03aa3ec
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
F ext/fts5/fts5_index.c fdfbc8a62827ec1d1b6f207a1e59c1c4986c3ce245592b5128ffe738867cfcd1
F ext/fts5/fts5_main.c 7c6092a53e6802962fa07b0fad3e61cb077b6c98b74b727d8d44ac2cf63bd914
F ext/fts5/fts5_main.c 6078ae86d3b813753a4f1201054550aff21a3f660e97b30f200d2b1472874151
F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
@@ -160,7 +161,7 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
F ext/fts5/test/fts5corrupt3.test 0e473620582a53ac61f468f364db8a151c1e18d2a879b16439d172c12c4c9828
F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
F ext/fts5/test/fts5corrupt5.test 550d0884c14424f9acad051a741f1dd99ec9342277d938e91ff3daf9123d1209
F ext/fts5/test/fts5corrupt6.test bf8eeae07825b088b9665d9d8e4accbd8dc9bf3cb85b6c64cf6c9e18ccc420a4
@@ -339,7 +340,7 @@ F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6b010b4546
F ext/misc/zipfile.c 238ccb990ed45a74e24d0fbb449d7752a568c2b7c1d5b255d451f11703ced592
F ext/misc/zipfile.c 3e76c6c3f73e05bfc7b2f743c268071c31e9aec0491282506ecb79cdef69d6f2
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
F ext/rbu/rbu1.test c62904bd9526dcdc3496a21199aaf14ae191bbadbf67f076bf16be6b3f2115c2
@@ -473,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 80ac3d2f82eb21c6fb4423f9c7f8e207abb51be6676845a00e246cfb22f9c77c
F main.mk 13eddb5f1360e7a1987ac699912afb4094c86c5ce3620e059c89b27fd4f4cc43
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -485,39 +486,39 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c e31cae888bc3077e34f9a82c6b4a96e4e44d37861eeb6472d68a378f1e8e46ba
F src/analyze.c 7518b99e07c5494111fe3bd867f28f804b6c5c1ad0703ec3d116de9bab3fa516
F src/attach.c f26d400f3ffe2cdca01406bca70e5f58c5488bf165b4fc37c228136dfcf1b583
F src/alter.c c4a3622fac78c595a93a079830afdcdfe2f4ec146eb47ba6787161acb2c56eff
F src/analyze.c b619f92ad33aa38c234d9620f576bceef56465088ed37f28c56d136a15c1a909
F src/attach.c f8ca7d5c85edad72f2f21a9ae0589a93c75376938b90bdb6de777ce6aae1fb3d
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 117808943727d27e38c69de4e79237e52c89ee40f6f1a70de4e6e14b5e596cbc
F src/btree.c 4ac832687f84d4c6c753f90274f7581f6c80a9ea69c2f045a5d07cb043cdf381
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
F src/build.c 9891c2160886cf7e344d7e8f1f7177f9612916c7c67ffeacd64cb34a92d387a8
F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c
F src/btreeInt.h 8be97d3939d626f734ec1b577efa4e6e186da00daf5b3227af199ca1c24cdd71
F src/build.c 6c5095126cd8aa6bb0a2e3fd63257ff7cadc2cced2ef808a38f71ad92f38bc9e
F src/callback.c f733593c95ed7ab24e0a0f57db6755b9bd433862d187766ec9f161ef7c79efeb
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 2cce39df1a13e05b7633e6d21b651f21492471f991dd7b323a4ee4e7b7f0b7f1
F src/date.c 1abbd739ae1d3fc8e0aaff995f57332af10d0b332728e4d3f241c494515495f0
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/ctime.c da293ceb565f07ad8ced251417913aec93030334d479dd4ce79946f7af464b0d
F src/date.c 15082566229d4b1e5f24fdb490bf9bcc68824b911d70e3573ef075a1b9e2d26f
F src/dbpage.c 30ff075a9a9156bd2cccb5c1ea579f2afbaa64989648e8c9d72cb4a3417f5136
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
F src/delete.c b5f1716b4d723db48254ee0f896e362cd029e865e05414139ea7f539f3884e1d
F src/expr.c b90a029105a93a93a0ed5e5f8c5eaed8f19043a3b62e4c4d235a4611d9ada178
F src/expr.c 7b9d66f012ba22bda14261c9a4d0600f4b800fad4cf5868f6a32355f037880cc
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 06e4ac33031b02dde7130c12e79cddf4dc5cfa72b23d8e63a3c26878fc9c1d3c
F src/func.c f801c6bc8b30afea51817d86a6c46259d3cca180c612cfa0a30b18d661e9c8df
F src/func.c a3407a6fbb0d4088d8d502e46f0ace63e0aeae7467ae23a9ca9815bbf9239761
F src/global.c a3daa18a1696aadd94f18d37cbbdebf0bbdb827b8397a534f021cd56c15cd0f9
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 1eea44389de3768ac98588c1410171cd53e7c6ad1af74049983dcbac82093de0
F src/json.c 225b00422112ecd7094a555f3ace16b25d7d5894062b823269ed03899907c2a2
F src/insert.c 6c0641efc3636732a02f45defe358899d695c065fc26fbba1b2cab415b5b2e57
F src/json.c 7ad9c97f36c43176bf4bd1397647dfdca540850554569c302b5380bd1e35ccf5
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c aa919a6a7884f8b34d7b791841b24d14b1b0ab43f45b3940f4851043b2855c0c
F src/main.c 0840cee6984034c7e73cc747a1562c7eaed4673694bf20b00980aaa0672c0405
F src/malloc.c fec841aa0a0400a6f7d20706178a5d8e8219a6bf562b6fe712c17f6c26813266
F src/main.c 36d30a911044d71060cb882f5ac80c75f27c7b3bef4012dfaef39ac76c12c043
F src/malloc.c a9127efdcef92d6934c6339ea9813075b90edc0ce2e5c723556381a3828fb720
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
@@ -536,32 +537,32 @@ F src/os.c b1c4f2d485961e9a5b6b648c36687d25047c252222e9660b7cc25a6e1ea436ab
F src/os.h 26890f540b475598cd9881dcc68931377b8d429d3ea3e2eeb64470cde64199f8
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e
F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_unix.c df6142ed776b5e52c7c3106767283be2d510b63d72beb3b205898462f340a176
F src/os_win.c a8ea80037e81127ca01959daa87387cc135f325c88dc745376c4f760de852a10
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c cda9e2d1df7c5fb4d777d09e23e69d78c518550d8873ed08b4a66c41d8cf2543
F src/pager.c e4f4c1e07b2cc4fa44fc0bd51957ca6066f6b8c0b0e0388f11a6728b50d8f4e6
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
F src/parse.y 0f02b27cdaa334441463153fff3ceb780fea006ab53ffd6ef566d4468f93e924
F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b
F src/pcache.c 0aab73936341fad83d107cf62c6a7bc2d2d5fb9aaec8c3ce61e19fc18e4560fc
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
F src/pragma.c 7c024d690a3dc93f61830f11f900e4af2357f31d081b0c79099ca5e28919cba7
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c a187dade741c1f09ae118fcbbf0302511807bfc0355880927d7152eb75b8260d
F src/pragma.c 770a2ce23196a4d6b88026848ec2a347264fb2e23efc0a0a0ce58e55c99680a1
F src/pragma.h 50f6d3b408ed56bde4f4e4aead8c0b2022030b692e8de237c1b7a0b5ce87a0c8
F src/prepare.c d91f59db086b7b738ada7f06c1c09e151a40ca219565d1937da3968b299166e6
F src/printf.c 05d8dfd2018bc4fc3ddb8b37eb97ccef7abf985643fa1caebdcf2916ca90fa32
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35
F src/shell.c.in 14cdfba32c73cb06169e50cd448632c28359f2bab2a0f803dc4a7f46dfc5b6fa
F src/sqlite.h.in e30cedf008d9c51511f4027a3739b727a588da553424748b48d2393f85dbde41
F src/select.c ba0cd3d264fa788c8d65f063d5ec3e1d65b0dac206c822a564a59ba550210cfc
F src/shell.c.in 71d30be41a0e43f9cdaabb7cc3334e18ccf60afafb84077101f69dd9f640ffe0
F src/sqlite.h.in c8f93ce5a0153484bd176d67d6d23deec48076fb7d45d1752411a6e1ed92fc6f
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6
F src/sqliteInt.h f8814239fb1f95056555e2d7fa475750e64681cac4221fb03610d1fde0b79d53
F src/sqliteInt.h f249dead228fcfa65e3a5848180bb3010bbd780433373ef17e2cc37bf6a21311
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/status.c d0956e57c71160155f620a3efeb1e5c05a3f8b9a897dd09c5263268e5d237579
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 1f6673991147bc2cecc08a40d22f9803b84c805b24b499fe727f392256f73474
F src/tclsqlite.c d438eb0f0d345f5cfccc6d00232677082bb9cf1dfd2422f7d7891fae58516260
F src/test1.c 87fda59eea3ac1eba1baef37c1967565cb1b8d6d264649f2e57f252ca5989914
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
@@ -577,7 +578,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 8294d8223b7f18a3ddb7f9a0e30815dcca4e61681f78b538c870f7d934f88b81
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 8264637b06a3c1f0727c88d1ea32dcf7986b9e7e358a970cae87cdac8a5b2708
F src/test_config.c 73ebdc35580900d12c20b984db9ec1abe860dc75f66ae703f2b6fc9d95e09dc1
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
@@ -601,11 +602,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
@@ -618,32 +620,32 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 6661a9fa660ecbd3ac0df1acd2ec788b3a8122b4316022bcdaf476ea6754a8de
F src/treeview.c a84b57d15e46007d8b1ae249344b3f0b7f3c62def908b98baaa54935a57c8476
F src/trigger.c 19fc6fe696a2409b04496df1ff044e6a942dad6ed3b6e897b1c9093b88cc2c62
F src/trigger.c 1759a77426f5b520c20f74575930708e4a9b9bcb064aac4fc3266da28a50bb89
F src/update.c f875b0d59da5c3055a0b2ac20560e1650229c6787e78de5e9836267b5cbb8359
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 602fe229f32a96ceccae4f40824129669582096f7c355f53dbac156c9fecef23
F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
F src/vdbe.c e179d2d6551c6cc3dda7f6f233f9fe3d3c8da2f9bfc46eaabb4b54dc4337d3cf
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
F src/vacuum.c 97424abbd3b5831d0142349a3c2dad52c364e39fab67f7e0f5c60d2694463940
F src/vdbe.c 35c770dece590b9aac00629591d3532ce87749ee79e3897fffee2572131a189e
F src/vdbe.h bfde0b0f429a0ba4203e5319780a6a1c8b2a809c5cd6baa9ae22e257a657b8b3
F src/vdbeInt.h b45599a2b59f1ce042512ab6786b0b82a8cf3002f6b0fa60b4834e2cd3ac61d8
F src/vdbeapi.c 8863ffb5a7bac42fe9a68aaa3526ee29fc18fb02a9b27188b756de41e33856e9
F src/vdbeaux.c 0d7659fe8cb38ce86092b9bc5131c99a834a04eb78745e54acb77d79d7af2fb5
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
F src/vdbemem.c 7737f0b1c480a32b057849c804d2f21d5389649bb8be80f77ad75df700adc9a1
F src/vdbeaux.c 3a86053ed0f9ffbbbab8562d9d67657f64223d5e5ef9b23f82d76c9b5c0a4ceb
F src/vdbeblob.c aa23a326ff86bdde8f7ba74cf23c3e1795b13bee749314feaf26273be2f63e89
F src/vdbemem.c 2db321ed3722f78c7f1e6743ff24ae68717fcc44c157817ae7eaf0a83439af98
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c e0eaf5b8f7f8929088485a76bea2ff6124adb12e0eb5c0997287ff5e0e4c0517
F src/vtab.c 7064064da041cf67212c60229cb81d4f78337b4bece2aa2ecc3d50fb09b8fefc
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c 0d75d7514764726409ea945520fe9fb515e7d9ae52a5a3c0a136142cfaa19087
F src/where.c be30bf0151f5cc77b2d75a664f2ab60632974165ad2bab6df9deca2fc3284264
F src/whereInt.h 15d2975c3b4c193c78c26674400a840da8647fe1777ae3b026e2d15937b38a03
F src/wherecode.c 6150f51c0368be941fad90a736ce37cc1e2a719876750a3183a516ed256a4cbb
F src/wherecode.c eae0a5778fa0ffe398cb4ecb55d3e20ee9b85a985c8c1aa9cea03d0a3069c213
F src/whereexpr.c 2a71f5491798460c9590317329234d332d9eb1717cba4f3403122189a75c465e
F src/window.c dfaec4abc6012cbc18e4a202ca3a5d5a0efcc4011d86a06d882ddaab8aedee4d
F src/window.c 8546f510dfff88e4627f004969940c648acf91c13aa155229849f926a8137b9c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
@@ -666,7 +668,7 @@ F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e2
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test 17fb3724c4b004c469c27dc4ef181608aa644555fbd3f3236767584f73747c81
F test/altermalloc3.test 55e606edf4b0acfbbd851ddfe93cfdddfae43d103644dcfd6008ae4ab3c44adf
F test/alterqf.test 3008318ba9e16b4ac0b5f83cf7683caa4b0a3154aafe3b4099838a250d4ba74a
F test/alterqf.test ff6c6f881485c29ed699b8ef4774864ca1b0c01a6c08f5cdd624a008e4b40fca
F test/altertab.test 7273b8506eab46342be016af78028df49f3bd99037412f997a8f1011b37a6912
F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
F test/altertab3.test 5929f522fd6fd708396ad9f317d4af9ff1a93e460df85bb1d54d4499eeb94960
@@ -704,7 +706,7 @@ F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39
F test/autoindex1.test fe27af92eaf884bd9c38f94be3e8afa04ec494e5eefb189902026181a6175f5e
F test/autoindex1.test b2a87aca5c3717264ef431025c1eb855f6012c9694a3c85c678c762aa0dedf58
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5
F test/autoindex4.test 75cb1191a552b8201351f5a50d160fcb9387a0fbbfb820c77798bfee7da3f8cf
@@ -813,7 +815,7 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
F test/corruptL.test 7d3440831ca24ba64305583c4d4506d417d3f89f5775c0b7cc8102db078f8ff5
F test/corruptL.test 21a951d1eb09120f3c1561af5bac30ed49be2d9dfcad039f71759c5d9e28a349
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
F test/corruptN.test 60b5a62944b4f0029ba07edaa5fd8e670539d6b0a8d99db26c068d435675cbfe
F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
@@ -837,7 +839,7 @@ F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c47
F test/cursorhint.test 0175e4404181ace3ceca8b114eb0a98eae600d565aa4e2705abbe6614c7fe201
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
F test/date.test 50d5b1eeec57041c000d2be5e9ab995026ded4255507f0206c81c1ca3b34b840
F test/date.test 118e04db8c8b4efeb885542b4918c7b869a34c460a6bebbfe927dfd75706b80d
F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64ae5
F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603
@@ -845,7 +847,7 @@ F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
F test/dbpage.test fce29035c7566fd7835ec0f19422cb4b9c6944ce0e1b936ff8452443f92e887d
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
@@ -1055,7 +1057,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
F test/func6.test 9cc9b1f43b435af34fe1416eb1e318c8920448ea7a6962f2121972f5215cb9b0
F test/func7.test b9e2a1a30a8562b00841b4a21a5d2d81754fa3ab99275fd71fd5279287b44b1c
F test/fuzz-oss1.test 514dcabb24687818ea949fa6760229eaacad74ca70157743ef36d35bbe01ffb0
F test/fuzz.test 4608c1310cff4c3014a84bcced6278139743e080046e5f6784b0de7b069371d8
@@ -1114,14 +1116,14 @@ F test/index7.test b238344318e0b4e42126717f6554f0e7dfd0b39cecad4b736039b43e1e3b6
F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a912a3
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
F test/indexexpr1.test 8f7241410e351679010f14cd7cd30357622d04a784508ff54ba5ce99f64a2228
F test/indexexpr1.test 3360c2a29a8844e7c4b13293567025281257f9e13a31854cfff6959cede11502
F test/indexexpr2.test 2c7abe3c48f8aaa5a448615ab4d13df3662185d28419c00999670834a3f0b484
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test 59cb99521be01a5aefc9be8e8b5a51ee7f3944781d4d7f6201b9f774fcd51662
F test/insert4.test 2bf81535a990c969665d66db51fcf76c23499b39893b5109f413d1de4ad34cd3
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c776e4a7f74
F test/instr.test 107df2b9b74a4b59315916b575590a08f2a714de0754abe541f10a0971d0a2a4
@@ -1143,7 +1145,7 @@ F test/join.test 25cf0ac11c3b81fedfd166f9062166bdb39dea92f5a7c16cacbf6dc1f7f6702
F test/join2.test 9bdc615841b91c97a16d68bad9508aea11fa0c6b34e5689847bcc4dac70e4990
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 37864d567928652cab79a7872ebde74b3c67a1feb0366d98bb3bc7832885f388
F test/join5.test e1ada8581c279fa210ce6c301bcd286cf0b42bfd0f0a2036b1ee0301e245ab75
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
@@ -1151,7 +1153,7 @@ F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ff
F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9e1946
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json101.test d7c84854acafaf80f883e183ac4248ea2742615086c94a61a46ad7d7382ce123
F test/json101.test 9d46b8e254c4e23306da175dd226d5c4f164db6b294bcea98e5dcd891ba48c91
F test/json102.test 327e77275f338c028faefa2da5164daf6b142a165e3015ff2a6e4251ddc6a0ac
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
F test/json104.test a502dc01853aada95d721b3b275afbe2dc18fffdac1fea6e96fb20c13586bbb5
@@ -1272,7 +1274,7 @@ F test/oserror.test 1fc9746b83d778e70d115049747ba19c7fba154afce7cc165b09feb6ca6a
F test/ossfuzz.c 9636dad2092a05a32110df0ca06713038dd0c43dd89a77dabe4b8b0d71096715
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
F test/pager1.test 8cb45ccbdb3ba423fc8158701c8f010a1d104336b8f14ef14bbfbadf14bad700
F test/pager1.test ffd885cdc98b986c9f746496508c0c4810ed0eaade3575ddf53c222e85880552
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
@@ -1316,8 +1318,15 @@ F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2
F test/releasetest_data.tcl 11ba48a21ed1c808147b0e77c6e93d204577f4327ffe6d7c3b34cd3c01eac3a2
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/returning1.test ee0b115162b17f59fe486767899596b1e8290bcd845db05d7d1d9e6c2dad1b8b
F test/returning1.test c43b8370a351f77aec6d71f4a2cde59b849369ed1933261a2c2c69e23e34ff5e
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
@@ -1388,11 +1397,11 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test b224e0793c5f48aa3749e65d8c64b93a30731bd206f2e41e6c5f1bee1bdb16c6
F test/shell2.test 89e4b2db062d52baed75022227b462d085cff495809de1699652779d8e0257d6
F test/shell1.test f7a2ef8260aa01f20be3185118213b1ae70518fdcd2105f3e25b021b5ca800ac
F test/shell2.test 7a3a23a9f57b99453f1679b1fe8072cb30e382a622874c0c4d97695fadb0a787
F test/shell3.test a50628ab1d78d90889d9d3f32fb2c084ee15674771e96afe954aaa0accd1de3c
F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759
F test/shell5.test 2b521446f55146c9aafccd0946bdb44ae288b0d25bd48f722e041974fdeeb04a
F test/shell5.test 78a7a8516b1e7de560748881424f621321549023d3e5f7ed2e1c56497f64c06c
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae
@@ -1465,7 +1474,7 @@ F test/tabfunc01.test 241425ce3998687ab24adba09cb95e8012e17499b84a0ed47e128ab45e
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test ad0bbd92edabe64cc91d990a0748142fe5ab962d74ac71fa3bfa94d50d2f4c87
F test/tclsqlite.test 350536a4233914aa437b6735e3e8e683e921a71ced8fa9fb5396057a04dbea33
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
@@ -1484,7 +1493,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
@@ -1640,7 +1649,7 @@ F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f4
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
F test/transitive1.test f8ee983600b33d167da1885657f064aec404e1c0d0bc8765fdf163f4c749237a
F test/trigger1.test d30cd09ae8ac365a088f09daba583cc5c0b8fc7d4e1d70809d0b4be3bf6ae2ab
F test/trigger1.test 02cc64dc98278816c1c1ed8e472e18db8edbad88f37018bf46223e9614831963
F test/trigger2.test 6e35bd7321c49e63d540aee980eb95dec63e1d1caca175224101045bcc80871f
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
@@ -1658,12 +1667,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
@@ -1680,7 +1690,7 @@ F test/update.test eb7f4eb172ce270e51bb67d7867521f33a63635bb671e261bbafccaef3bd6
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
F test/upfrom2.test 88d39cb755db5789541e645d4e2764abc697a56958f28a3f8451a0e9342bbd6b
F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af62328a1
F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
F test/upsert1.test b0ae2f58680c5205b4bc1cdeed3c3d444057c506f6c44494fa3eac60731d68a2
@@ -1774,7 +1784,7 @@ F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test ab41d53ce8f2a6919ea3d5b13cd1153c1375a8e3ddaa129b81781f9033981383
F test/where7.test 1c1bf436bf31b913d4764a2b62ac6e98b9681e5c7ae2b562605592a56b7e946b
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
F test/where9.test 1ffb75edc50a8faa6e7bd77f8221d783febb00b44b0bdb32fb48cec6e38eca95
F test/whereA.test 9d1077b117f1b68d5f739d94f36956c36cf995eb87bb19b77b2e81af020edd20
@@ -1813,7 +1823,7 @@ F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f
F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45f1ed
F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
F test/windowB.test b67bda5645f3226790e1a360c4225241840b84adb5aa2e69bfb0b27eef3b84d9
F test/windowB.test f2fb42b864b0cf431c956407583e9478a74c3642bdf8737fdcb6ff4a40298b07
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
@@ -1877,7 +1887,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 bd07bd59d45d0f3448e123d6937e9811195f9908a51e09d774609883055bfd3d
F tool/mkpragmatab.tcl 0e059aaab521b490c86ba3d4f945319b438558de7738e90f26c54f4ffcdd79bb
F tool/mkshellc.tcl df5d249617f9cc94d5c48eb0401673eb3f31f383ecbc54e8a13ca3dd97e89450
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1944,8 +1954,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 40fa792d359f84c3b9e9d6623743e1a59826274e221df1bde8f47086968a1bab
R 8e774d76a97f244938c2cd31e6e650dd
P d5b0fd8434f893db444eb62e254871d92a593c3c4871641b0392453444444e15 78d9c993d404cdfaa7fdd2973fa1052e3da9f66215cff9c5540ebe55c407d9fe
R 61f9a16612c1f0767ba4d18e70055209
U drh
Z 87215546f30ba5e5b58306e47d0efae5
Z f42e6393488a7a3af7a82ff8d2119365
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
710de6a2137c872812effa43ea888aa77d339362ca0b6c8990d4426c8fb20689
bfccca2ba37dd99c28e10364ad85a3b8d5bd9547c6159cb7a1a2aa903a508e77
+11 -9
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);
}
}
@@ -1131,19 +1131,21 @@ static int renameParseSql(
){
int rc;
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
/* Parse the SQL statement passed as the first argument. If no error
** occurs and the parse does not result in a new table, index or
** trigger object, the database must be corrupt. */
sqlite3ParseObjectInit(p, db);
if( zSql==0 ){
return SQLITE_NOMEM;
}
if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
return SQLITE_CORRUPT_BKPT;
}
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
rc = zSql ? sqlite3RunParser(p, zSql) : SQLITE_NOMEM;
rc = sqlite3RunParser(p, zSql);
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
&& p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0
&& NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
){
rc = SQLITE_CORRUPT_BKPT;
}
+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;
+38 -33
View File
@@ -1609,6 +1609,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
testcase( pc+x>maxPC );
return &aData[pc];
}else if( x+pc > maxPC ){
/* This slot extends off the end of the usable part of the page */
*pRc = SQLITE_CORRUPT_PAGE(pPg);
@@ -2053,7 +2055,7 @@ static int btreeInitPage(MemPage *pPage){
pPage->nOverflow = 0;
pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
pPage->aCellIdx = data + pPage->childPtrSize + 8;
pPage->aDataEnd = pPage->aData + pBt->usableSize;
pPage->aDataEnd = pPage->aData + pBt->pageSize;
pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
** number of cells on the page. */
@@ -2088,7 +2090,7 @@ static void zeroPage(MemPage *pPage, int flags){
u8 hdr = pPage->hdrOffset;
u16 first;
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -2104,7 +2106,7 @@ static void zeroPage(MemPage *pPage, int flags){
pPage->nFree = (u16)(pBt->usableSize - first);
decodeFlags(pPage, flags);
pPage->cellOffset = first;
pPage->aDataEnd = &data[pBt->usableSize];
pPage->aDataEnd = &data[pBt->pageSize];
pPage->aCellIdx = &data[first];
pPage->aDataOfst = &data[pPage->childPtrSize];
pPage->nOverflow = 0;
@@ -2230,7 +2232,7 @@ static int getAndInitPage(
goto getAndInitPage_error2;
}
}
assert( (*ppPage)->pgno==pgno );
assert( (*ppPage)->pgno==pgno || CORRUPT_DB );
assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
/* If obtaining a child page for a cursor, we must verify that the page is
@@ -5317,7 +5319,7 @@ static int moveToRoot(BtCursor *pCur){
pCur->curIntKey = pCur->pPage->intKey;
}
pRoot = pCur->pPage;
assert( pRoot->pgno==pCur->pgnoRoot );
assert( pRoot->pgno==pCur->pgnoRoot || CORRUPT_DB );
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
@@ -5808,7 +5810,7 @@ int sqlite3BtreeIndexMoveto(
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->ix<pCur->pPage->nCell );
assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
@@ -8332,7 +8334,7 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
for(k=0; b.ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
for(k=0; b.ixNx[k]<=j && ALWAYS(k<NB*2); k++){}
pSrcEnd = b.apEnd[k];
if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
@@ -8848,24 +8850,6 @@ int sqlite3BtreeInsert(
assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
return pCur->skipNext;
}
assert( cursorOwnsBtShared(pCur) );
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
&& pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
/* Assert that the caller has been consistent. If this cursor was opened
** expecting an index b-tree, then the caller should be inserting blob
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
/* Save the positions of any other cursors open on this table.
**
** In some cases, the call to btreeMoveto() below is a no-op. For
@@ -8890,6 +8874,24 @@ int sqlite3BtreeInsert(
}
}
if( pCur->eState>=CURSOR_REQUIRESEEK ){
rc = moveToRoot(pCur);
if( rc && rc!=SQLITE_EMPTY ) return rc;
}
assert( cursorOwnsBtShared(pCur) );
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
&& pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
/* Assert that the caller has been consistent. If this cursor was opened
** expecting an index b-tree, then the caller should be inserting blob
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
@@ -8978,14 +8980,13 @@ int sqlite3BtreeInsert(
}
}
assert( pCur->eState==CURSOR_VALID
|| (pCur->eState==CURSOR_INVALID && loc)
|| CORRUPT_DB );
|| (pCur->eState==CURSOR_INVALID && loc) );
pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
if( NEVER(pCur->eState>CURSOR_INVALID) ){
if( pCur->eState>CURSOR_INVALID ){
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeComputeFreeSpace(pPage);
@@ -9266,12 +9267,16 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
if( pCur->eState==CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
if( pCur->eState!=CURSOR_VALID ){
if( pCur->eState>=CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
}else{
return SQLITE_CORRUPT_BKPT;
}
}
assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );
assert( pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
+3 -1
View File
@@ -293,7 +293,9 @@ struct MemPage {
u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
BtShared *pBt; /* Pointer to BtShared that this page is part of */
u8 *aData; /* Pointer to disk image of the page data */
u8 *aDataEnd; /* One byte past the end of usable data */
u8 *aDataEnd; /* One byte past the end of the entire page - not just
** the usable space, the entire page. Used to prevent
** corruption-induced of buffer overflow. */
u8 *aCellIdx; /* The cell index area */
u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */
DbPage *pDbPage; /* Pager page handle */
+94 -61
View File
@@ -351,6 +351,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
@@ -376,59 +409,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;
}
/*
@@ -453,6 +468,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;
@@ -469,9 +485,21 @@ Table *sqlite3LocateTable(
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
testcase( pMod->pEpoTab==0 );
return pMod->pEpoTab;
if( pMod ){
if( IsSharedSchema(db) && pParse->nErr==0 ){
int bDummy = 0;
pParse->rc = sqlite3SchemaLoad(db, 0, &bDummy, &pParse->zErrMsg);
if( pParse->rc ) pParse->nErr++;
(void)bDummy;
}
if( sqlite3VtabEponymousTableInit(pParse, pMod) ){
Table *pEpoTab = pMod->pEpoTab;
if( pEpoTab ){
assert( IsSharedSchema(db)||pEpoTab->pSchema==db->aDb[0].pSchema );
pEpoTab->pSchema = db->aDb[0].pSchema; /* For SHARED_SCHEMA mode */
}
return pEpoTab;
}
}
}
#endif
@@ -481,15 +509,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;
@@ -658,11 +684,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);
}
}
}
@@ -675,16 +700,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);
@@ -1289,7 +1315,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);
@@ -2826,6 +2852,11 @@ void sqlite3EndTable(
int addrInsLoop; /* Top of the loop for inserting rows */
Table *pSelTab; /* A table that describes the SELECT results */
if( IN_SPECIAL_PARSE ){
pParse->rc = SQLITE_ERROR;
pParse->nErr++;
return;
}
regYield = ++pParse->nMem;
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
@@ -2909,7 +2940,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);
}
@@ -3461,7 +3492,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( !IsSharedSchema(db) && sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
assert( isView==0 || isView==LOCATE_VIEW );
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
@@ -3476,6 +3507,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 && iDb<db->nDb );
sqlite3SchemaWritable(pParse, iDb);
/* If pTab is a virtual table, call ViewGetColumnNames() to ensure
** it is initialized.
@@ -3930,7 +3962,7 @@ void sqlite3CreateIndex(
if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
goto exit_create_index;
}
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
if( !IsSharedSchema(db) && SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_create_index;
}
if( sqlite3HasExplicitNulls(pParse, pList) ){
@@ -4428,7 +4460,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);
}
@@ -4578,6 +4610,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.
@@ -514,15 +571,317 @@ void sqlite3SchemaClear(void *p){
}
/*
** Find and return the schema associated with a BTree. Create
** a new one if necessary.
** If this database was opened with the SQLITE_OPEN_SHARED_SCHEMA flag
** and iDb!=1, then disconnect from the schema-pool associated with
** database iDb. Otherwise, clear the Schema object belonging to
** database iDb.
**
** If an OOM error occurs while disconnecting from a schema-pool,
** the db->mallocFailed flag is set.
*/
void sqlite3SchemaClearOrDisconnect(sqlite3 *db, int iDb){
Db *pDb = &db->aDb[iDb];
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
if( IsSharedSchema(db) && iDb!=1 && pDb->pSPool ){
sqlite3SchemaDisconnect(db, iDb, 1);
}else
#endif
{
sqlite3SchemaClear(pDb->pSchema);
}
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** Global linked list of SchemaPool objects. Read and write access must
** be protected by the SQLITE_MUTEX_STATIC_MASTER mutex.
*/
static SchemaPool *SQLITE_WSD schemaPoolList = 0;
#ifdef SQLITE_TEST
/*
** Return a pointer to the head of the linked list of SchemaPool objects.
** This is used by the virtual table in file test_schemapool.c.
*/
SchemaPool *sqlite3SchemaPoolList(void){ return schemaPoolList; }
#endif
/*
** Database handle db was opened with the SHARED_SCHEMA flag, and database
** iDb is currently connected to a schema-pool. When this function is called,
** (*pnByte) is set to nInit plus the amount of memory used to store a
** single instance of the Schema objects managed by the schema-pool.
** This function adjusts (*pnByte) sot hat it is set to nInit plus
** (nSchema/nRef) of the amount of memory used by a single Schema object,
** where nSchema is the number of Schema objects allocated by this pool,
** and nRef is the number of connections to the schema-pool.
*/
void sqlite3SchemaAdjustUsed(sqlite3 *db, int iDb, int nInit, int *pnByte){
SchemaPool *pSPool = db->aDb[iDb].pSPool;
int nSchema = 0;
Schema *p;
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
for(p=pSPool->pSchema; p; p=p->pNext){
nSchema++;
}
*pnByte = nInit + ((*pnByte - nInit) * nSchema) / pSPool->nRef;
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
/*
** Check that the schema of db iDb is writable (either because it is the
** temp db schema or because the db handle was opened without
** SQLITE_OPEN_SHARED_SCHEMA). If so, do nothing. Otherwise, leave an
** error in the Parse object.
*/
void sqlite3SchemaWritable(Parse *pParse, int iDb){
if( iDb!=1 && IsSharedSchema(pParse->db) && IN_DECLARE_VTAB==0 ){
sqlite3ErrorMsg(pParse, "attempt to modify read-only schema");
}
}
/*
** The schema object passed as the only argument was allocated using
** sqlite3_malloc() and then populated using the usual mechanism. This
** function frees both the Schema object and its contents.
*/
static void schemaDelete(Schema *pSchema){
sqlite3SchemaClear((void*)pSchema);
sqlite3_free(pSchema);
}
/*
** When this function is called, the database connection Db must be
** using a schema-pool (Db.pSPool!=0) and must currently have Db.pSchema
** set to point to a populated schema object checked out from the
** schema-pool. It is also assumed that the STATIC_MASTER mutex is held.
** This function returns the Schema object to the schema-pool and sets
** Db.pSchema to point to the schema-pool's static, empty, Schema object.
*/
static void schemaRelease(sqlite3 *db, Db *pDb){
Schema *pRelease = pDb->pSchema;
SchemaPool *pSPool = pDb->pSPool;
assert( pDb->pSchema->iGeneration==pSPool->sSchema.iGeneration );
pDb->pSchema = &pSPool->sSchema;
assert( pDb->pSPool && pRelease );
assert( pRelease->schemaFlags & DB_SchemaLoaded );
assert( (pDb->pSchema->schemaFlags & DB_SchemaLoaded)==0 );
assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) );
/* If the DBFLAG_FreeSchema flag is set and the database connection holds
** at least one other copy of the schema being released, delete it instead
** of returning it to the schema-pool. */
if( db->mDbFlags & DBFLAG_FreeSchema ){
int i;
for(i=0; i<db->nDb; i++){
Db *p = &db->aDb[i];
if( p!=pDb && p->pSchema!=&pSPool->sSchema && pDb->pSPool==p->pSPool ){
pSPool->nDelete++;
schemaDelete(pRelease);
return;
}
}
}
pRelease->pNext = pDb->pSPool->pSchema;
pDb->pSPool->pSchema = pRelease;
}
/*
** The schema for database iDb of database handle db, which was opened
** with SQLITE_OPEN_SHARED_SCHEMA, has just been parsed. This function either
** finds a matching SchemaPool object on the global list (schemaPoolList) or
** else allocates a new one and sets the Db.pSPool variable accordingly.
**
** SQLITE_OK is returned if no error occurs, or an SQLite error code
** (SQLITE_NOMEM) otherwise.
*/
int sqlite3SchemaConnect(sqlite3 *db, int iDb, u64 cksum){
Schema *pSchema = db->aDb[iDb].pSchema;
SchemaPool *p;
assert( pSchema && iDb!=1 && db->aDb[iDb].pSPool==0 );
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
/* Search for a matching SchemaPool object */
for(p=schemaPoolList; p; p=p->pNext){
if( p->cksum==cksum && p->sSchema.schema_cookie==pSchema->schema_cookie ){
break;
}
}
if( !p ){
/* No SchemaPool object found. Allocate a new one. */
p = (SchemaPool*)sqlite3_malloc(sizeof(SchemaPool));
if( p ){
memset(p, 0, sizeof(SchemaPool));
p->cksum = cksum;
p->pNext = schemaPoolList;
schemaPoolList = p;
p->sSchema.schema_cookie = pSchema->schema_cookie;
p->sSchema.iGeneration = pSchema->iGeneration;
p->sSchema.file_format = pSchema->file_format;
p->sSchema.enc = pSchema->enc;
p->sSchema.cache_size = pSchema->cache_size;
}
}
if( p ) p->nRef++;
/* If the SchemaPool contains one or more free schemas at the moment,
** delete one of them. */
if( p && p->pSchema ){
Schema *pDel = p->pSchema;
p->pSchema = pDel->pNext;
schemaDelete(pDel);
}
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
db->aDb[iDb].pSPool = p;
return (p ? SQLITE_OK : SQLITE_NOMEM);
}
/*
** If parameter iDb is 1 (the temp db), or if connection handle db was not
** opened with the SQLITE_OPEN_SHARED_SCHEMA flag, this function is a no-op.
** Otherwise, it disconnects from the schema-pool associated with database
** iDb, assuming it is connected.
**
** If parameter bNew is true, then Db.pSchema is set to point to a new, empty,
** Schema object obtained from sqlite3_malloc(). Or, if bNew is false, then
** Db.pSchema is set to NULL before returning.
**
** If the bNew parameter is true, then this function may allocate memory.
** If the allocation attempt fails, then SQLITE_NOMEM is returned and the
** schema-pool is not disconnected from. Or, if no OOM error occurs,
** SQLITE_OK is returned.
*/
int sqlite3SchemaDisconnect(sqlite3 *db, int iDb, int bNew){
int rc = SQLITE_OK;
if( IsSharedSchema(db) ){
Db *pDb = &db->aDb[iDb];
SchemaPool *pSPool = pDb->pSPool;
assert_schema_state_ok(db);
assert( pDb->pSchema );
if( pSPool==0 ){
assert( pDb->pVTable==0 );
assert( bNew==0 );
schemaDelete(pDb->pSchema);
pDb->pSchema = 0;
}else{
VTable *p;
VTable *pNext;
for(p=pDb->pVTable; p; p=pNext){
pNext = p->pNext;
sqlite3VtabUnlock(p);
}
pDb->pVTable = 0;
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
if( DbHasProperty(db, iDb, DB_SchemaLoaded) ){
schemaRelease(db, pDb);
}
if( bNew ){
Schema *pNew = sqlite3SchemaGet(db, 0);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
pDb->pSchema = pNew;
}
}
if( rc==SQLITE_OK ){
assert( pSPool->nRef>=1 );
pDb->pSPool = 0;
pSPool->nRef--;
if( pSPool->nRef<=0 ){
SchemaPool **pp;
while( pSPool->pSchema ){
Schema *pNext = pSPool->pSchema->pNext;
schemaDelete(pSPool->pSchema);
pSPool->pSchema = pNext;
}
for(pp=&schemaPoolList; (*pp)!=pSPool; pp=&((*pp)->pNext));
*pp = pSPool->pNext;
sqlite3_free(pSPool);
}
}
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
}
return rc;
}
/*
** Extract and return a pointer to a schema object from the SchemaPool passed
** as the only argument, if one is available. If one is not available, return
** NULL.
*/
Schema *sqlite3SchemaExtract(SchemaPool *pSPool){
Schema *pRet = 0;
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
if( pSPool->pSchema ){
pRet = pSPool->pSchema;
pSPool->pSchema = pRet->pNext;
pRet->pNext = 0;
}
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
return pRet;
}
/*
** Return all sharable schemas held by database handle db back to their
** respective schema-pools. Db.pSchema variables are left pointing to
** the static, empty, Schema object owned by each schema-pool.
*/
void sqlite3SchemaReleaseAll(sqlite3 *db){
int i;
assert_schema_state_ok(db);
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
for(i=0; i<db->nDb; i++){
if( i!=1 ){
Db *pDb = &db->aDb[i];
if( pDb->pSPool && DbHasProperty(db,i,DB_SchemaLoaded) ){
schemaRelease(db, pDb);
}
}
}
db->mDbFlags &= ~DBFLAG_FreeSchema;
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
/*
** Release any sharable schema held by connection iDb of database handle
** db. Db.pSchema is left pointing to the static, empty, Schema object
** owned by the schema-pool.
*/
void sqlite3SchemaRelease(sqlite3 *db, int iDb){
Db *pDb = &db->aDb[iDb];
assert( iDb!=1 );
assert_schema_state_ok(db);
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
schemaRelease(db, pDb);
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
/*
** In most cases, this function finds and returns the schema associated
** with BTree handle pBt, creating a new one if necessary. However, if
** the database handle was opened with the SQLITE_OPEN_SHARED_SCHEMA flag
** specified, a new, empty, Schema object in memory obtained by
** sqlite3_malloc() is always returned.
*/
Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
Schema * p;
if( pBt ){
p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
Schema *p;
if( pBt && IsSharedSchema(db)==0 ){
p = (Schema*)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
}else{
p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));
p = (Schema*)sqlite3DbMallocZero(0, sizeof(Schema));
}
if( !p ){
sqlite3OomFault(db);
+3
View File
@@ -313,6 +313,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_SESSION
"ENABLE_SESSION",
#endif
#if SQLITE_ENABLE_SHARED_SCHEMA
"ENABLE_SHARED_SCHEMA",
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
"ENABLE_SNAPSHOT",
#endif
+1 -1
View File
@@ -602,7 +602,7 @@ static int toLocaltime(
p->D = sLocal.tm_mday;
p->h = sLocal.tm_hour;
p->m = sLocal.tm_min;
p->s = sLocal.tm_sec;
p->s = sLocal.tm_sec + (p->iJD%1000)*0.001;
p->validYMD = 1;
p->validHMS = 1;
p->validJD = 0;
+1
View File
@@ -156,6 +156,7 @@ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
){
pIdxInfo->orderByConsumed = 1;
}
sqlite3VtabWriteAll(pIdxInfo);
return SQLITE_OK;
}
+32
View File
@@ -2284,6 +2284,38 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
/*
** Check pExpr to see if it is an invariant constraint on data source pSrc.
** This is an optimization. False negatives will perhaps cause slower
** queries, but false positives will yield incorrect answers. So when in
** double, return 0.
**
** To be an invariant constraint, the following must be true:
**
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
**
** (2) pExpr cannot use subqueries or non-deterministic functions.
**
** (*) ** Not applicable to this branch **
**
** (4) If pSrc is the right operand of a LEFT JOIN, then...
** (4a) pExpr must come from an ON clause..
** (4b) and specifically the ON clause associated with the LEFT JOIN.
**
** (5) If pSrc is not the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
*/
int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){
if( pSrc->fg.jointype & JT_LEFT ){
if( !ExprHasProperty(pExpr, EP_FromJoin) ) return 0; /* rule (4a) */
if( pExpr->w.iRightJoinTable!=pSrc->iCursor ) return 0; /* rule (4b) */
}else{
if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0; /* rule (5) */
}
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
}
/*
** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
+2 -2
View File
@@ -2241,8 +2241,8 @@ void sqlite3RegisterBuiltinFunctions(void){
INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
SQLITE_FUNC_TYPEOF),
{1, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_OFFSET|SQLITE_FUNC_TYPEOF,
0, 0, noopFunc, 0, 0, 0, "sqlite_offset", {0} },
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
+7 -8
View File
@@ -181,7 +181,7 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
}
for(i=j=0; i<pTab->nCol; i++){
assert( pTab->aCol[i].affinity!=0 );
assert( pTab->aCol[i].affinity!=0 || sqlite3VdbeParser(v)->nErr>0 );
if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
zColAff[j++] = pTab->aCol[i].affinity;
}
@@ -795,7 +795,11 @@ void sqlite3Insert(
**
** This is the 2nd template.
*/
if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
if( pColumn==0
&& pSelect!=0
&& pTrigger==0
&& xferOptimization(pParse, pTab, pSelect, onError, iDb)
){
assert( !pTrigger );
assert( pList==0 );
goto insert_end;
@@ -2766,18 +2770,13 @@ static int xferOptimization(
int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
int regData, regRowid; /* Registers holding data and rowid */
if( pSelect==0 ){
return 0; /* Must be of the form INSERT INTO ... SELECT ... */
}
assert( pSelect!=0 );
if( pParse->pWith || pSelect->pWith ){
/* Do not attempt to process this query if there are an WITH clauses
** attached to it. Proceeding may generate a false "no such table: xxx"
** error if pSelect reads from a CTE named "xxx". */
return 0;
}
if( sqlite3TriggerList(pParse, pDest) ){
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pDest) ){
return 0; /* tab1 must not be a virtual table */
+34 -10
View File
@@ -1119,14 +1119,15 @@ static JsonNode *jsonLookupStep(
*pzErr = zPath;
return 0;
}
testcase( nKey==0 );
}else{
zKey = zPath;
for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
nKey = i;
}
if( nKey==0 ){
*pzErr = zPath;
return 0;
if( nKey==0 ){
*pzErr = zPath;
return 0;
}
}
j = 1;
for(;;){
@@ -2274,6 +2275,33 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){
return SQLITE_OK;
}
/* Append an object label to the JSON Path being constructed
** in pStr.
*/
static void jsonAppendObjectPathElement(
JsonString *pStr,
JsonNode *pNode
){
int jj, nn;
const char *z;
assert( pNode->eType==JSON_STRING );
assert( pNode->jnFlags & JNODE_LABEL );
assert( pNode->eU==1 );
z = pNode->u.zJContent;
nn = pNode->n;
assert( nn>=2 );
assert( z[0]=='"' );
assert( z[nn-1]=='"' );
if( nn>2 && sqlite3Isalpha(z[1]) ){
for(jj=2; jj<nn-1 && sqlite3Isalnum(z[jj]); jj++){}
if( jj==nn-1 ){
z++;
nn -= 2;
}
}
jsonPrintf(nn+2, pStr, ".%.*s", nn, z);
}
/* Append the name of the path for element i to pStr
*/
static void jsonEachComputePath(
@@ -2298,10 +2326,7 @@ static void jsonEachComputePath(
}else{
assert( pUp->eType==JSON_OBJECT );
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
assert( pNode->eType==JSON_STRING );
assert( pNode->jnFlags & JNODE_LABEL );
assert( pNode->eU==1 );
jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
jsonAppendObjectPathElement(pStr, pNode);
}
}
@@ -2372,8 +2397,7 @@ static int jsonEachColumn(
if( p->eType==JSON_ARRAY ){
jsonPrintf(30, &x, "[%d]", p->iRowid);
}else if( p->eType==JSON_OBJECT ){
assert( pThis->eU==1 );
jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
jsonAppendObjectPathElement(&x, pThis);
}
}
jsonResult(&x);
+34 -6
View File
@@ -1164,6 +1164,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);
@@ -1332,6 +1343,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
if( j!=1 ){
(void)sqlite3SchemaDisconnect(db, j, 0);
pDb->pSchema = 0;
}
}
@@ -3756,7 +3768,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;
@@ -3766,7 +3778,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 ){
@@ -3776,14 +3788,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;
@@ -3856,6 +3883,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;
}
+2 -1
View File
@@ -750,8 +750,9 @@ char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
** Free any prior content in *pz and replace it with a copy of zNew.
*/
void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
char *z = sqlite3DbStrDup(db, zNew);
sqlite3DbFree(db, *pz);
*pz = sqlite3DbStrDup(db, zNew);
*pz = z;
}
/*
+9 -3
View File
@@ -4910,11 +4910,17 @@ static int unixShmLock(
int flags /* What to do with the lock */
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
unixShm *p; /* The shared memory being locked */
unixShmNode *pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
int *aLock = pShmNode->aLock;
int *aLock;
p = pDbFd->pShm;
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
pShmNode = p->pShmNode;
if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
aLock = pShmNode->aLock;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
+5 -1
View File
@@ -4070,10 +4070,14 @@ static int winShmLock(
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
winShm *p = pDbFd->pShm; /* The shared memory being locked */
winShm *pX; /* For looping over all siblings */
winShmNode *pShmNode = p->pShmNode;
winShmNode *pShmNode;
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
pShmNode = p->pShmNode;
if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
assert( n>=1 );
assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
+3
View File
@@ -2844,6 +2844,9 @@ static int pager_playback(Pager *pPager, int isHot){
goto end_playback;
}
pPager->dbSize = mxPg;
if( pPager->mxPgno<mxPg ){
pPager->mxPgno = mxPg;
}
}
/* Copy original pages out of the journal and back into the
+2 -1
View File
@@ -551,7 +551,8 @@ void sqlite3PcacheDrop(PgHdr *p){
** make it so.
*/
void sqlite3PcacheMakeDirty(PgHdr *p){
assert( p->nRef>0 );
assert( p->nRef>0 || p->pCache->bPurgeable==0 );
testcase( p->nRef==0 );
assert( sqlite3PcachePageSanity(p) );
if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ /*OPTIMIZATION-IF-FALSE*/
p->flags &= ~PGHDR_DONT_WRITE;
+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 */
@@ -2031,9 +2037,10 @@ void sqlite3Pragma(
** applications for any purpose.
*/
case PragTyp_HEADER_VALUE: {
int iCookie = pPragma->iArg; /* Which cookie to read or write */
int iCookie; /* Which cookie to read or write */
iCookie = pPragma->iArg & PRAGMA_HEADER_VALUE_MASK;
sqlite3VdbeUsesBtree(v, iDb);
if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){
if( zRight && (pPragma->iArg & PRAGMA_HEADER_VALUE_READONLY)==0 ){
/* Write the specified cookie value */
static const VdbeOpList setCookie[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */
+23 -16
View File
@@ -56,12 +56,19 @@
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */
#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */
#define PragFlg_OneSchema 0x08 /* Only a single schema required */
#define PragFlg_Result0 0x10 /* Acts as query when no argument */
#define PragFlg_Result1 0x20 /* Acts as query when has one argument */
#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */
#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */
/* For PragTyp_HEADER_VALUE pragmas the Pragma.iArg value is set
** to the index of the header field to access (always 10 or less).
** Ored with HEADER_VALUE_READONLY if the field is read only. */
#define PRAGMA_HEADER_VALUE_READONLY 0x0100
#define PRAGMA_HEADER_VALUE_MASK 0x00FF
/* Names of columns for pragmas that return multi-column result
** or that return single-column results where the name of the
** result column is different from the name of the pragma
@@ -162,7 +169,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_AUTOVACUUM)
{/* zName: */ "auto_vacuum",
/* ePragTyp: */ PragTyp_AUTO_VACUUM,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -183,7 +190,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
/* ePragTyp: */ PragTyp_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -244,9 +251,9 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "data_version",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_DATA_VERSION },
/* iArg: */ BTREE_DATA_VERSION|PRAGMA_HEADER_VALUE_READONLY },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
{/* zName: */ "database_list",
@@ -258,7 +265,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
{/* zName: */ "default_cache_size",
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1|PragFlg_OneSchema,
/* ColNames: */ 55, 1,
/* iArg: */ 0 },
#endif
@@ -295,7 +302,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
{/* zName: */ "foreign_key_list",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt|PragFlg_OneSchema,
/* ColNames: */ 0, 8,
/* iArg: */ 0 },
#endif
@@ -311,9 +318,9 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "freelist_count",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_FREE_PAGE_COUNT },
/* iArg: */ BTREE_FREE_PAGE_COUNT|PRAGMA_HEADER_VALUE_READONLY },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "full_column_names",
@@ -353,7 +360,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_AUTOVACUUM)
{/* zName: */ "incremental_vacuum",
/* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -384,7 +391,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "journal_mode",
/* ePragTyp: */ PragTyp_JOURNAL_MODE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "journal_size_limit",
@@ -422,7 +429,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ 0 },
{/* zName: */ "max_page_count",
/* ePragTyp: */ PragTyp_PAGE_COUNT,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "mmap_size",
@@ -450,7 +457,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "page_count",
/* ePragTyp: */ PragTyp_PAGE_COUNT,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "page_size",
@@ -549,14 +556,14 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_OneSchema,
/* ColNames: */ 33, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "synchronous",
/* ePragTyp: */ PragTyp_SYNCHRONOUS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1|PragFlg_OneSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -645,7 +652,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ 0 },
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_OneSchema,
/* ColNames: */ 50, 3,
/* iArg: */ 0 },
#endif
+136 -12
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);
@@ -389,7 +458,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
sqlite3ResetAllSchemasOfConnection(db);
pDb = &db->aDb[iDb];
}else
if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
if( rc==SQLITE_OK || ((db->flags&SQLITE_NoSchemaError) && rc!=SQLITE_NOMEM)){
/* Hack: If the SQLITE_NoSchemaError flag is set, then consider
** the schema loaded, even if errors (other than OOM) occurred. In
** this situation the current sqlite3_prepare() operation will fail,
@@ -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. */
@@ -663,6 +773,14 @@ void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){
if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory");
}
/*
** Maximum number of times that we will try again to prepare a statement
** that returns SQLITE_ERROR_RETRY.
*/
#ifndef SQLITE_MAX_PREPARE_RETRY
# define SQLITE_MAX_PREPARE_RETRY 25
#endif
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
@@ -820,6 +938,7 @@ static int sqlite3LockAndPrepare(
){
int rc;
int cnt = 0;
int bReleaseSchema = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
@@ -829,6 +948,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
@@ -837,9 +957,13 @@ static int sqlite3LockAndPrepare(
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
}while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db);
sqlite3UnlockReusableSchema(db, bReleaseSchema);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
db->busyHandler.nBusy = 0;
+10 -9
View File
@@ -4822,8 +4822,7 @@ static int pushDownWhereTerms(
Parse *pParse, /* Parse context (for malloc() and error reporting) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
int iCursor, /* Cursor number of the subquery */
int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */
SrcItem *pSrc /* The subquery term of the outer FROM clause */
){
Expr *pNew;
int nChng = 0;
@@ -4858,10 +4857,11 @@ static int pushDownWhereTerms(
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
iCursor, isLeftJoin);
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrc);
pWhere = pWhere->pLeft;
}
#if 0 /* Legacy code. Checks now done by sqlite3ExprIsTableConstraint() */
if( isLeftJoin
&& (ExprHasProperty(pWhere,EP_FromJoin)==0
|| pWhere->w.iRightJoinTable!=iCursor)
@@ -4873,7 +4873,9 @@ static int pushDownWhereTerms(
){
return 0; /* restriction (5) */
}
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
#endif
if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){
nChng++;
pSubq->selFlags |= SF_PushDown;
while( pSubq ){
@@ -4881,8 +4883,8 @@ static int pushDownWhereTerms(
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
unsetJoinExpr(pNew, -1);
x.pParse = pParse;
x.iTable = iCursor;
x.iNewTable = iCursor;
x.iTable = pSrc->iCursor;
x.iNewTable = pSrc->iCursor;
x.isLeftJoin = 0;
x.pEList = pSubq->pEList;
pNew = substExpr(&x, pNew);
@@ -6664,8 +6666,7 @@ int sqlite3Select(
if( OptimizationEnabled(db, SQLITE_PushDown)
&& (pItem->fg.isCte==0
|| (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2))
&& pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
(pItem->fg.jointype & JT_OUTER)!=0)
&& pushDownWhereTerms(pParse, pSub, p->pWhere, pItem)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
+299 -34
View File
@@ -1161,13 +1161,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
*/
@@ -3346,6 +3347,8 @@ static void exec_prepared_stmt_columnar(
int bNextLine = 0;
int bMultiLineRowExists = 0;
int bw = p->cmOpts.bWordWrap;
const char *zEmpty = "";
const char *zShowNull = p->nullValue;
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ) return;
@@ -3407,12 +3410,14 @@ static void exec_prepared_stmt_columnar(
if( wx<0 ) wx = -wx;
if( useNextLine ){
uz = azNextLine[i];
if( uz==0 ) uz = (u8*)zEmpty;
}else if( p->cmOpts.bQuote ){
sqlite3_free(azQuoted[i]);
azQuoted[i] = quoted_column(pStmt,i);
uz = (const unsigned char*)azQuoted[i];
}else{
uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
if( uz==0 ) uz = (u8*)zShowNull;
}
azData[nRow*nColumn + i]
= translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
@@ -3426,7 +3431,7 @@ static void exec_prepared_stmt_columnar(
nTotal = nColumn*(nRow+1);
for(i=0; i<nTotal; i++){
z = azData[i];
if( z==0 ) z = p->nullValue;
if( z==0 ) z = (char*)zEmpty;
n = strlenChar(z);
j = i%nColumn;
if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
@@ -3530,7 +3535,10 @@ columnar_end:
utf8_printf(p->out, "Interrupt\n");
}
nData = (nRow+1)*nColumn;
for(i=0; i<nData; i++) free(azData[i]);
for(i=0; i<nData; i++){
z = azData[i];
if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
}
sqlite3_free(azData);
sqlite3_free((void*)azNextLine);
sqlite3_free(abRowDiv);
@@ -4427,6 +4435,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
@@ -4965,6 +4979,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,
@@ -7228,6 +7247,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;
}
/*
@@ -7956,12 +8206,12 @@ SELECT\
','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
||')' AS ColsSpec \
FROM (\
SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \
SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
FROM ColNames ORDER BY cpos\
)";
static const char * const zRenamesDone =
"SELECT group_concat("
" printf('\"%w\" to \"%w\"',name,printf('%.*s%s', nlen-chop, name, suff)),"
" printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff)),"
" ','||x'0a')"
"FROM ColNames WHERE suff<>'' OR chop!=0"
;
@@ -8827,7 +9077,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
char *zTable = 0; /* Insert data into this table */
char *zSchema = "main"; /* within this schema */
char *zSchema = 0; /* within this schema (may default to "main") */
char *zFile = 0; /* Name of file to extra content from */
sqlite3_stmt *pStmt = NULL; /* A statement */
int nCol; /* Number of columns in the table */
@@ -8836,11 +9086,13 @@ static int do_meta_command(char *zLine, ShellState *p){
int needCommit; /* True to COMMIT or ROLLBACK at end */
int nSep; /* Number of bytes in p->colSeparator[] */
char *zSql; /* An SQL statement */
char *zFullTabName; /* Table name with schema if applicable */
ImportCtx sCtx; /* Reader context */
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
char *zCreate = 0; /* CREATE TABLE statement text */
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
@@ -8963,7 +9215,6 @@ static int do_meta_command(char *zLine, ShellState *p){
import_cleanup(&sCtx);
goto meta_command_exit;
}
/* Below, resources must be freed before exit. */
if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
char zSep[2];
zSep[1] = 0;
@@ -8975,11 +9226,17 @@ static int do_meta_command(char *zLine, ShellState *p){
output_c_string(p->out, zSep);
utf8_printf(p->out, "\n");
}
/* Below, resources must be freed before exit. */
while( (nSkip--)>0 ){
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
}
zSql = sqlite3_mprintf("SELECT * FROM \"%w\".\"%w\"", zSchema, zTable);
if( zSql==0 ){
if( zSchema!=0 ){
zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
}else{
zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
}
zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
if( zSql==0 || zFullTabName==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
@@ -8987,11 +9244,10 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"",
zSchema, zTable);
sqlite3 *dbCols = 0;
char *zRenames = 0;
char *zColDefs;
zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
while( xRead(&sCtx) ){
zAutoColumn(sCtx.z, &dbCols, 0);
if( sCtx.cTerm!=sCtx.cColSep ) break;
@@ -9005,9 +9261,12 @@ static int do_meta_command(char *zLine, ShellState *p){
}
assert(dbCols==0);
if( zColDefs==0 ){
sqlite3_free(zCreate);
import_cleanup(&sCtx);
utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
import_fail:
sqlite3_free(zCreate);
sqlite3_free(zSql);
sqlite3_free(zFullTabName);
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
}
@@ -9018,22 +9277,18 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
if( rc ){
utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
sqlite3_free(zCreate);
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
goto import_fail;
}
sqlite3_free(zCreate);
zCreate = 0;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
}
sqlite3_free(zSql);
if( rc ){
if (pStmt) sqlite3_finalize(pStmt);
utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
goto import_fail;
}
sqlite3_free(zSql);
nCol = sqlite3_column_count(pStmt);
sqlite3_finalize(pStmt);
pStmt = 0;
@@ -9043,8 +9298,7 @@ static int do_meta_command(char *zLine, ShellState *p){
import_cleanup(&sCtx);
shell_out_of_memory();
}
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
zSchema, zTable);
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
j = strlen30(zSql);
for(i=1; i<nCol; i++){
zSql[j++] = ',';
@@ -9056,14 +9310,13 @@ static int do_meta_command(char *zLine, ShellState *p){
utf8_printf(p->out, "Insert using: %s\n", zSql);
}
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
if (pStmt) sqlite3_finalize(pStmt);
import_cleanup(&sCtx);
rc = 1;
goto meta_command_exit;
goto import_fail;
}
sqlite3_free(zSql);
sqlite3_free(zFullTabName);
needCommit = sqlite3_get_autocommit(p->db);
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
do{
@@ -10571,6 +10824,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)
@@ -11557,7 +11817,8 @@ static int process_input(ShellState *p){
qss = QSS_Start;
}
}
if( nSql && QSS_PLAINDARK(qss) ){
if( nSql ){
/* This may be incomplete. Let the SQL parser deal with that. */
errCnt += runOneSqlLine(p, zSql, p->in, startline);
}
free(zSql);
@@ -12055,6 +12316,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)
@@ -12177,6 +12440,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 ){
+9 -4
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
**
@@ -4979,6 +4980,10 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** even empty strings, are always zero-terminated. ^The return
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
**
** ^Strings returned by sqlite3_column_text16() always have the endianness
** which is native to the platform, regardless of the text encoding set
** for the database.
**
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object. In a multithreaded environment,
** an unprotected sqlite3_value object may only be used safely with
@@ -4992,7 +4997,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** [application-defined SQL functions] or [virtual tables], not within
** top-level application code.
**
** The these routines may attempt to convert the datatype of the result.
** These routines may attempt to convert the datatype of the result.
** ^For example, if the internal representation is FLOAT and a text result
** is requested, [sqlite3_snprintf()] is used internally to perform the
** conversion automatically. ^(The following table details the conversions
@@ -5017,7 +5022,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** <tr><td> TEXT <td> BLOB <td> No change
** <tr><td> BLOB <td> INTEGER <td> [CAST] to INTEGER
** <tr><td> BLOB <td> FLOAT <td> [CAST] to REAL
** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
** <tr><td> BLOB <td> TEXT <td> [CAST] to TEXT, ensure zero terminator
** </table>
** </blockquote>)^
**
@@ -9767,7 +9772,7 @@ int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);
** ^When xBestIndex returns, the sqlite3_value object returned by
** sqlite3_vtab_rhs_value() is automatically deallocated.
**
** The "_rhs_" in the name of this routine is an appreviation for
** The "_rhs_" in the name of this routine is an abbreviation for
** "Right-Hand Side".
*/
int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
+53
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;
@@ -1301,6 +1302,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
};
/*
@@ -1332,6 +1337,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
};
/*
@@ -1656,6 +1664,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.
*/
@@ -1737,6 +1751,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
@@ -2231,6 +2248,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
@@ -3737,6 +3757,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
};
/*
@@ -3848,6 +3871,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;
@@ -4662,6 +4686,7 @@ int sqlite3ExprIsConstantNotJoin(Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
int sqlite3ExprIsTableConstant(Expr*,int);
int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
int sqlite3ExprContainsSubquery(Expr*);
#endif
@@ -4961,6 +4986,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);
@@ -5101,7 +5149,12 @@ int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
int sqlite3VtabCallConnect(Parse*, Table*);
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
int sqlite3VtabBegin(sqlite3 *, VTable *);
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
void sqlite3VtabWriteAll(sqlite3_index_info*);
#endif
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
+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
@@ -3705,6 +3705,9 @@ static int sqliteCmdUsage(
"HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
" ?-nofollow BOOLEAN?"
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
" ?-shared-schema BOOLEAN?"
#endif
);
return TCL_ERROR;
}
@@ -3836,6 +3839,16 @@ static int SQLITE_TCLAPI DbMain(
}else{
flags &= ~SQLITE_OPEN_URI;
}
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
}else if( strcmp(zArg, "-shared-schema")==0 ){
int b;
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
if( b ){
flags |= SQLITE_OPEN_SHARED_SCHEMA;
}else{
flags &= ~SQLITE_OPEN_SHARED_SCHEMA;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
}else if( strcmp(zArg, "-translatefilename")==0 ){
if( Tcl_GetBooleanFromObj(interp, objv[i], &bTranslateFileName) ){
return TCL_ERROR;
+6
View File
@@ -783,6 +783,12 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
Tcl_SetVar2(interp, "sqlite_options", "sharedschema", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "sharedschema", "0", TCL_GLOBAL_ONLY);
#endif
#define LINKVAR(x) { \
static const int cv_ ## x = SQLITE_ ## x; \
Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
+282
View File
@@ -0,0 +1,282 @@
/*
** 2006 June 10
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the virtual table interfaces. This code
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
*/
/*
** None of this works unless we have virtual tables.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST)
#include <tcl.h>
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
#include "sqliteInt.h"
/* The code in this file defines a sqlite3 virtual-table module with
** the following schema.
*/
#define SCHEMAPOOL_SCHEMA \
"CREATE TABLE x(" \
" cksum INTEGER, " \
" nref INTEGER, " \
" nschema INTEGER, " \
" ndelete INTEGER " \
")"
#define SCHEMAPOOL_NFIELD 4
typedef struct schemapool_vtab schemapool_vtab;
typedef struct schemapool_cursor schemapool_cursor;
/* A schema table object */
struct schemapool_vtab {
sqlite3_vtab base;
};
/* A schema table cursor object */
struct schemapool_cursor {
sqlite3_vtab_cursor base;
sqlite3_int64 *aData;
int iRow;
int nRow;
};
/*
** Table destructor for the schema module.
*/
static int schemaPoolDestroy(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return 0;
}
/*
** Table constructor for the schema module.
*/
static int schemaPoolCreate(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
int rc = SQLITE_NOMEM;
schemapool_vtab *pVtab = sqlite3_malloc(sizeof(schemapool_vtab));
if( pVtab ){
memset(pVtab, 0, sizeof(schemapool_vtab));
rc = sqlite3_declare_vtab(db, SCHEMAPOOL_SCHEMA);
if( rc!=SQLITE_OK ){
sqlite3_free(pVtab);
pVtab = 0;
}
}
*ppVtab = (sqlite3_vtab *)pVtab;
return rc;
}
/*
** Open a new cursor on the schema table.
*/
static int schemaPoolOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
int rc = SQLITE_NOMEM;
schemapool_cursor *pCur;
pCur = sqlite3_malloc(sizeof(schemapool_cursor));
if( pCur ){
memset(pCur, 0, sizeof(schemapool_cursor));
*ppCursor = (sqlite3_vtab_cursor*)pCur;
rc = SQLITE_OK;
}
return rc;
}
/*
** Close a schema table cursor.
*/
static int schemaPoolClose(sqlite3_vtab_cursor *cur){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
sqlite3_free(pCur->aData);
sqlite3_free(pCur);
return SQLITE_OK;
}
/*
** Retrieve a column of data.
*/
static int schemaPoolColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
assert( i==0 || i==1 || i==2 || i==3 );
sqlite3_result_int64(ctx, pCur->aData[pCur->iRow*SCHEMAPOOL_NFIELD + i]);
return SQLITE_OK;
}
/*
** Retrieve the current rowid.
*/
static int schemaPoolRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
*pRowid = pCur->iRow + 1;
return SQLITE_OK;
}
static int schemaPoolEof(sqlite3_vtab_cursor *cur){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
return pCur->iRow>=pCur->nRow;
}
/*
** Advance the cursor to the next row.
*/
static int schemaPoolNext(sqlite3_vtab_cursor *cur){
schemapool_cursor *pCur = (schemapool_cursor*)cur;
pCur->iRow++;
return SQLITE_OK;
}
struct SchemaPool {
int nRef; /* Number of pointers to this object */
int nDelete; /* Schema objects deleted by ReleaseAll() */
u64 cksum; /* Checksum for this Schema contents */
Schema *pSchema; /* Linked list of Schema objects */
Schema sSchema; /* The single dummy schema object */
SchemaPool *pNext; /* Next element in schemaPoolList */
};
extern SchemaPool *sqlite3SchemaPoolList(void);
/*
** Reset a schemaPool table cursor.
*/
static int schemaPoolFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
SchemaPool *pSPool;
schemapool_cursor *pCur = (schemapool_cursor*)pVtabCursor;
sqlite3_free(pCur->aData);
pCur->aData = 0;
pCur->nRow = 0;
pCur->iRow = 0;
for(pSPool = sqlite3SchemaPoolList(); pSPool; pSPool=pSPool->pNext){
pCur->nRow++;
}
if( pCur->nRow ){
int iRow = 0;
int nByte = SCHEMAPOOL_NFIELD * pCur->nRow * sizeof(i64);
pCur->aData = (i64*)sqlite3_malloc(nByte);
if( pCur->aData==0 ) return SQLITE_NOMEM;
for(pSPool = sqlite3SchemaPoolList(); pSPool; pSPool=pSPool->pNext){
Schema *p;
i64 nSchema = 0;
for(p=pSPool->pSchema; p; p=p->pNext){
nSchema++;
}
pCur->aData[0 + iRow*SCHEMAPOOL_NFIELD] = pSPool->cksum;
pCur->aData[1 + iRow*SCHEMAPOOL_NFIELD] = (i64)pSPool->nRef;
pCur->aData[2 + iRow*SCHEMAPOOL_NFIELD] = nSchema;
pCur->aData[3 + iRow*SCHEMAPOOL_NFIELD] = (i64)pSPool->nDelete;
iRow++;
}
}
return SQLITE_OK;
}
/*
** Analyse the WHERE condition.
*/
static int schemaPoolBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
return SQLITE_OK;
}
/*
** A virtual table module that merely echos method calls into TCL
** variables.
*/
static sqlite3_module schemaPoolModule = {
0, /* iVersion */
schemaPoolCreate,
schemaPoolCreate,
schemaPoolBestIndex,
schemaPoolDestroy,
schemaPoolDestroy,
schemaPoolOpen, /* xOpen - open a cursor */
schemaPoolClose, /* xClose - close a cursor */
schemaPoolFilter, /* xFilter - configure scan constraints */
schemaPoolNext, /* xNext - advance a cursor */
schemaPoolEof, /* xEof */
schemaPoolColumn, /* xColumn - read data */
schemaPoolRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
};
/*
** Decode a pointer to an sqlite3 object.
*/
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
/*
** Register the schema virtual table module.
*/
static int SQLITE_TCLAPI register_schemapool_module(
ClientData clientData, /* Not used */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
sqlite3 *db;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_create_module(db, "schemapool", &schemaPoolModule, 0);
#endif
return TCL_OK;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST) */
/*
** Register commands with the TCL interpreter.
*/
int Sqlitetestschemapool_Init(Tcl_Interp *interp){
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
static struct {
char *zName;
Tcl_ObjCmdProc *xProc;
void *clientData;
} aObjCmd[] = {
{ "register_schemapool_module", register_schemapool_module, 0 },
};
int i;
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
return TCL_OK;
}
+2
View File
@@ -77,6 +77,7 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
extern int Sqlitetest_malloc_Init(Tcl_Interp*);
extern int Sqlitetest_mutex_Init(Tcl_Interp*);
extern int Sqlitetestschema_Init(Tcl_Interp*);
extern int Sqlitetestschemapool_Init(Tcl_Interp*);
extern int Sqlitetestsse_Init(Tcl_Interp*);
extern int Sqlitetesttclvar_Init(Tcl_Interp*);
extern int Sqlitetestfs_Init(Tcl_Interp*);
@@ -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);
+41 -5
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);
}
@@ -446,6 +473,7 @@ static TriggerStep *triggerStepAllocate(
sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
if( pParse->nErr ) return 0;
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
if( pTriggerStep ){
char *z = (char*)&pTriggerStep[1];
@@ -585,6 +613,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 +687,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
@@ -1115,7 +1147,9 @@ static TriggerPrg *codeRowTrigger(
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
Parse sSubParse; /* Parse context for sub-vdbe */
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTrigger->zName==0 || IsSharedSchema(pParse->db)
|| pTab==tableOfTrigger(pTrigger)
);
assert( pTop->pVdbe );
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
@@ -1222,7 +1256,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);
+23 -9
View File
@@ -987,6 +987,8 @@ case OP_Gosub: { /* jump */
/* Most jump operations do a goto to this spot in order to update
** the pOp pointer. */
jump_to_p2:
assert( pOp->p2>0 ); /* There are never any jumps to instruction 0 */
assert( pOp->p2<p->nOp ); /* Jumps must be in range */
pOp = &aOp[pOp->p2 - 1];
break;
}
@@ -2627,10 +2629,18 @@ case OP_Offset: { /* out3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
pOut = &p->aMem[pOp->p3];
if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){
if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){
sqlite3VdbeMemSetNull(pOut);
}else{
sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
if( pC->deferredMoveto ){
rc = sqlite3VdbeFinishMoveto(pC);
if( rc ) goto abort_due_to_error;
}
if( sqlite3BtreeEof(pC->uc.pCursor) ){
sqlite3VdbeMemSetNull(pOut);
}else{
sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
}
}
break;
}
@@ -3748,13 +3758,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.
@@ -3771,6 +3774,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;
}
@@ -5709,6 +5719,10 @@ case OP_Rowid: { /* out2 */
** Move the cursor P1 to a null row. Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
**
** Or, if P1 is a Pseudo-Cursor (a cursor opened using OP_OpenPseudo)
** just reset the cache for that cursor. This causes the row of
** content held by the pseudo-cursor to be reparsed.
*/
case OP_NullRow: {
VdbeCursor *pC;
+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);
+3 -1
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);
+3
View File
@@ -135,6 +135,7 @@ int sqlite3_blob_open(
Table *pTab;
Incrblob *pBlob = 0;
Parse sParse;
int bUnlock; /* True to unlock reusable schemas before returning */
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppBlob==0 ){
@@ -151,6 +152,7 @@ int sqlite3_blob_open(
sqlite3_mutex_enter(db->mutex);
bUnlock = sqlite3LockReusableSchema(db);
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
while(1){
sqlite3ParseObjectInit(&sParse,db);
@@ -336,6 +338,7 @@ int sqlite3_blob_open(
}
blob_open_out:
sqlite3UnlockReusableSchema(db, bUnlock);
if( rc==SQLITE_OK && db->mallocFailed==0 ){
*ppBlob = (sqlite3_blob *)pBlob;
}else{
+6 -1
View File
@@ -204,7 +204,11 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|| desiredEnc==SQLITE_UTF16BE );
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
if( !(pMem->flags&MEM_Str) ){
pMem->enc = desiredEnc;
return SQLITE_OK;
}
if( pMem->enc==desiredEnc ){
return SQLITE_OK;
}
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
@@ -916,6 +920,7 @@ void sqlite3VdbeMemSetPointer(
void (*xDestructor)(void*)
){
assert( pMem->flags==MEM_Null );
vdbeMemClear(pMem);
pMem->u.zPType = zPType ? zPType : "";
pMem->z = pPtr;
pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
+48 -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;
}
@@ -827,6 +866,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sqlite3ParseObjectInit(&sParse, db);
sParse.eParseMode = PARSE_MODE_DECLARE_VTAB;
sParse.disableTriggers = 1;
/* We should never be able to reach this point while loading the
** schema. Nevertheless, defend against that (turn off db->init.busy)
** in case a bug arises. */
+72 -8
View File
@@ -808,8 +808,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
** WHERE clause (or the ON clause of a LEFT join) that constrain which
** rows of the target table (pSrc) that can be used. */
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& ((pSrc->fg.jointype&JT_LEFT)==0 || ExprHasProperty(pExpr,EP_FromJoin))
&& sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor)
&& sqlite3ExprIsTableConstraint(pExpr, pSrc)
){
pPartial = sqlite3ExprAnd(pParse, pPartial,
sqlite3ExprDup(pParse->db, pExpr, 0));
@@ -1048,7 +1047,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsTableConstant(pExpr, iCur)
&& sqlite3ExprIsTableConstraint(pExpr, pItem)
){
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
}
@@ -1078,7 +1077,10 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
pLoop->wsFlags &= ~WHERE_BLOOMFILTER;
if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break;
while( ++iLevel < pWInfo->nLevel ){
const SrcItem *pTabItem;
pLevel = &pWInfo->a[iLevel];
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
if( pTabItem->fg.jointype & JT_LEFT ) continue;
pLoop = pLevel->pWLoop;
if( NEVER(pLoop==0) ) continue;
if( pLoop->prereq & notReady ) continue;
@@ -2591,8 +2593,17 @@ static void whereLoopOutputAdjust(
/* If there are extra terms in the WHERE clause not used by an index
** that depend only on the table being scanned, and that will tend to
** cause many rows to be omitted, then mark that table as
** "self-culling". */
pLoop->wsFlags |= WHERE_SELFCULL;
** "self-culling".
**
** 2022-03-24: Self-culling only applies if either the extra terms
** are straight comparison operators that are non-true with NULL
** operand, or if the loop is not a LEFT JOIN.
*/
if( (pTerm->eOperator & 0x3f)!=0
|| (pWC->pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0
){
pLoop->wsFlags |= WHERE_SELFCULL;
}
}
if( pTerm->truthProb<=0 ){
/* If a truth probability is specified using the likelihood() hints,
@@ -3761,7 +3772,6 @@ int sqlite3_vtab_rhs_value(
return rc;
}
/*
** Return true if ORDER BY clause may be handled as DISTINCT.
*/
@@ -3773,6 +3783,22 @@ int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){
return pHidden->eDistinct;
}
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** Cause the prepared statement that is associated with a call to
** xBestIndex to open write transactions on all attached schemas.
** This is used by the (built-in) sqlite_dbpage virtual table.
*/
void sqlite3VtabWriteAll(sqlite3_index_info *pIdxInfo){
HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
Parse *pParse = pHidden->pParse;
int nDb = pParse->db->nDb;
int i;
for(i=0; i<nDb; i++) sqlite3BeginWriteOperation(pParse, 0, i);
}
#endif
/*
** Add all WhereLoop objects for a table of the join identified by
** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
@@ -5876,6 +5902,26 @@ whereBeginError:
}
#endif
#ifdef SQLITE_DEBUG
/*
** Return true if cursor iCur is opened by instruction k of the
** bytecode. Used inside of assert() only.
*/
static int cursorIsOpen(Vdbe *v, int iCur, int k){
while( k>=0 ){
VdbeOp *pOp = sqlite3VdbeGetOp(v,k--);
if( pOp->p1!=iCur ) continue;
if( pOp->opcode==OP_Close ) return 0;
if( pOp->opcode==OP_OpenRead ) return 1;
if( pOp->opcode==OP_OpenWrite ) return 1;
if( pOp->opcode==OP_OpenDup ) return 1;
if( pOp->opcode==OP_OpenAutoindex ) return 1;
if( pOp->opcode==OP_OpenEphemeral ) return 1;
}
return 0;
}
#endif /* SQLITE_DEBUG */
/*
** Generate the end of the WHERE loop. See comments on
** sqlite3WhereBegin() for additional information.
@@ -6128,6 +6174,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
){
int x = pOp->p2;
assert( pIdx->pTable==pTab );
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
if( pOp->opcode==OP_Offset ){
/* Do not need to translate the column number */
}else
#endif
if( !HasRowid(pTab) ){
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
x = pPk->aiColumn[x];
@@ -6141,9 +6192,22 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
}else{
/* Unable to translate the table reference into an index
** reference. Verify that this is harmless - that the
** table being referenced really is open.
*/
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|| cursorIsOpen(v,pOp->p1,k)
|| pOp->opcode==OP_Offset
);
#else
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|| cursorIsOpen(v,pOp->p1,k)
);
#endif
}
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0
|| pWInfo->eOnePass );
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;
+50 -33
View File
@@ -792,6 +792,7 @@ static int codeAllEqualityTerms(
VdbeCoverageIf(v, bRev!=0);
VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
j = sqlite3VdbeAddOp0(v, OP_Goto);
assert( pLevel->addrSkip==0 );
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
iIdxCur, 0, regBase, nSkip);
VdbeCoverageIf(v, bRev==0);
@@ -1234,6 +1235,7 @@ static void preserveExpr(IdxExprTrans *pTrans, Expr *pExpr){
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
pExpr = sqlite3ExprSkipCollate(pExpr);
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
@@ -1389,9 +1391,12 @@ static SQLITE_NOINLINE void filterPullDown(
WhereLevel *pLevel = &pWInfo->a[iLevel];
WhereLoop *pLoop = pLevel->pWLoop;
if( pLevel->regFilter==0 ) continue;
if( pLevel->pWLoop->nSkip ) continue;
/* ,--- Because sqlite3ConstructBloomFilter() has will not have set
** vvvvv--' pLevel->regFilter if this were true. */
if( NEVER(pLoop->prereq & notReady) ) continue;
assert( pLevel->addrBrk==0 );
pLevel->addrBrk = addrNxt;
if( pLoop->wsFlags & WHERE_IPK ){
WhereTerm *pTerm = pLoop->aLTerm[0];
int regRowid;
@@ -1418,6 +1423,7 @@ static SQLITE_NOINLINE void filterPullDown(
VdbeCoverage(pParse->pVdbe);
}
pLevel->regFilter = 0;
pLevel->addrBrk = 0;
}
}
@@ -1523,7 +1529,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
int iReg; /* P3 Value for OP_VFilter */
int addrNotFound;
int nConstraint = pLoop->nLTerm;
int iIn; /* Counter for IN constraints */
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
addrNotFound = pLevel->addrBrk;
@@ -1569,50 +1574,54 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
if( pLoop->wsFlags & WHERE_IN_ABLE ){
iIn = pLevel->u.in.nIn;
}else{
iIn = 0;
}
for(j=nConstraint-1; j>=0; j--){
int bIn; /* True to generate byte code to loop over RHS IN values */
for(j=0; j<nConstraint; j++){
pTerm = pLoop->aLTerm[j];
if( (pTerm->eOperator & WO_IN)!=0
&& (SMASKBIT32(j) & pLoop->u.vtab.mHandleIn)==0
){
bIn = 1;
}else{
bIn = 0;
}
if( bIn ) iIn--;
if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
disableTerm(pLevel, pTerm);
}else if( bIn && sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1 ){
continue;
}
if( (pTerm->eOperator & WO_IN)!=0
&& (SMASKBIT32(j) & pLoop->u.vtab.mHandleIn)==0
&& !db->mallocFailed
){
Expr *pCompare; /* The comparison operator */
Expr *pRight; /* RHS of the comparison */
VdbeOp *pOp; /* Opcode to access the value of the IN constraint */
int iIn; /* IN loop corresponding to the j-th constraint */
/* Reload the constraint value into reg[iReg+j+2]. The same value
** was loaded into the same register prior to the OP_VFilter, but
** the xFilter implementation might have changed the datatype or
** encoding of the value in the register, so it *must* be reloaded. */
assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
if( !db->mallocFailed ){
assert( iIn>=0 && iIn<pLevel->u.in.nIn );
** encoding of the value in the register, so it *must* be reloaded.
*/
for(iIn=0; ALWAYS(iIn<pLevel->u.in.nIn); iIn++){
pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop);
assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 );
assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 );
testcase( pOp->opcode==OP_Rowid );
sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
if( (pOp->opcode==OP_Column && pOp->p3==iReg+j+2)
|| (pOp->opcode==OP_Rowid && pOp->p2==iReg+j+2)
){
testcase( pOp->opcode==OP_Rowid );
sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
break;
}
}
/* Generate code that will continue to the next row if
** the IN constraint is not satisfied */
** the IN constraint is not satisfied
*/
pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0);
assert( pCompare!=0 || db->mallocFailed );
if( pCompare ){
pCompare->pLeft = pTerm->pExpr->pLeft;
if( !db->mallocFailed ){
int iFld = pTerm->u.x.iField;
Expr *pLeft = pTerm->pExpr->pLeft;
assert( pLeft!=0 );
if( iFld>0 ){
assert( pLeft->op==TK_VECTOR );
assert( ExprUseXList(pLeft) );
assert( iFld<=pLeft->x.pList->nExpr );
pCompare->pLeft = pLeft->x.pList->a[iFld-1].pExpr;
}else{
pCompare->pLeft = pLeft;
}
pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
if( pRight ){
pRight->iTable = iReg+j+2;
@@ -1621,11 +1630,11 @@ Bitmask sqlite3WhereCodeOneLoopStart(
);
}
pCompare->pLeft = 0;
sqlite3ExprDelete(db, pCompare);
}
sqlite3ExprDelete(db, pCompare);
}
}
assert( iIn==0 || db->mallocFailed );
/* These registers need to be preserved in case there is an IN operator
** loop. So we could deallocate the registers here (and potentially
** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
@@ -2335,6 +2344,14 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** the initialization of the right-hand operand of the vector comparison
** might not occur, or might occur only in an OR branch that is not
** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1.
**
** 2022-03-03: Do not push down expressions that involve subqueries.
** The subquery might get coded as a subroutine. Any table-references
** in the subquery might be resolved to index-references for the index on
** the OR branch in which the subroutine is coded. But if the subroutine
** is invoked from a different OR branch that uses a different index, such
** index-references will not work. tag-20220303a
** https://sqlite.org/forum/forumpost/36937b197273d403
*/
if( pWC->nTerm>1 ){
int iTerm;
@@ -2348,7 +2365,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
continue;
}
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */
pExpr = sqlite3ExprDup(db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
}
+7 -2
View File
@@ -957,7 +957,11 @@ static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
*/
int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
if( p->pWin && p->pPrior==0 && ALWAYS((p->selFlags & SF_WinRewrite)==0) ){
if( p->pWin
&& p->pPrior==0
&& ALWAYS((p->selFlags & SF_WinRewrite)==0)
&& ALWAYS(!IN_RENAME_OBJECT)
){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3 *db = pParse->db;
Select *pSub = 0; /* The subquery */
@@ -1032,6 +1036,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
ExprList *pArgs;
assert( ExprUseXList(pWin->pOwner) );
assert( pWin->pFunc!=0 );
pArgs = pWin->pOwner->x.pList;
if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
@@ -1724,7 +1729,7 @@ static void windowAggStep(
for(iEnd=sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
VdbeOp *pOp = sqlite3VdbeGetOp(v, iOp);
if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
if( pOp->opcode==OP_Column && pOp->p1==pMWin->iEphCsr ){
pOp->p1 = csr;
}
}
+2 -4
View File
@@ -63,8 +63,7 @@ foreach {tn before after} {
10 {CREATE TABLE t2(abc, xyz CHECK (xyz != "123"))}
{CREATE TABLE t2(abc, xyz CHECK (xyz != '123'))}
11 {
CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
11 {CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
SELECT max("str", new."a") FROM t1
WHERE group_concat("b", ",") OVER (ORDER BY c||"str");
UPDATE t1 SET c= b + "str";
@@ -72,8 +71,7 @@ foreach {tn before after} {
SELECT 1 FROM t1 AS o WHERE o."a" = "o.a" AND t1.b IN("t1.b")
);
END;
} {
CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
} {CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
SELECT max('str', new."a") FROM t1
WHERE group_concat("b", ',') OVER (ORDER BY c||'str');
UPDATE t1 SET c= b + 'str';
+18 -2
View File
@@ -542,7 +542,23 @@ do_execsql_test autoindex1-1020 {
SELECT count(*) FROM t11 LEFT JOIN t12 WHERE t12.y IS t11.w;
} 0
# 2022-04-25
# https://sqlite.org/forum/forumpost/0d3200f4f3bcd3a3
#
reset_db
do_execsql_test autoindex-1100 {
CREATE TABLE t1(a INT, b INT);
CREATE TABLE t2(c INT, d INT);
CREATE TABLE t3(e TEXT, f TEXT);
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t2 VALUES(1, 2);
INSERT INTO t3 VALUES('abc', 'def');
} {}
do_execsql_test autoindex-1110 {
SELECT * FROM t1, t2 LEFT JOIN t3 ON (t2.d=1) WHERE t2.c = +t1.a;
} {1 1 1 2 {} {}}
do_execsql_test autoindex-1120 {
SELECT * FROM t1 LEFT JOIN t2 ON (t2.c=+t1.a) LEFT JOIN t3 ON (t2.d IS NULL);
} {1 1 1 2 {} {}}
finish_test
+55
View File
@@ -1429,4 +1429,59 @@ do_catchsql_test 18.1 {
} {1 {JSON cannot hold BLOB values}}
} ;# ifcapable json1
#-------------------------------------------------------------------------
reset_db
do_test 19.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 20480 pagesize 4096 filename crash-f022eb0ce64d27.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 96: 00 00 00 00 0d 0f f8 00 04 0e d2 00 0f 08 0f d3 ................
| 112: 0f ae 0e d2 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3792: 00 00 34 04 06 17 0f 11 01 57 69 6e 64 65 78 61 ..4......Windexa
| 3808: 74 31 05 43 52 45 41 54 45 20 55 4e 49 51 55 45 t1.CREATE UNIQUE
| 3824: 20 49 4e 44 45 58 20 61 20 4f 4e 20 74 31 28 61 INDEX a ON t1(a
| 3840: 2c 20 30 20 7c 20 61 29 81 23 01 07 17 11 11 01 , 0 | a).#......
| 3856: 82 31 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 .1tablet1t1.CREA
| 3872: 54 45 20 54 41 42 4c 45 20 74 31 28 0a 20 20 20 TE TABLE t1(.
| 3888: 20 67 63 62 20 41 53 20 28 62 2a 31 29 2c 0a 20 gcb AS (b*1),.
| 3904: 20 20 20 61 20 49 34 54 45 47 45 52 20 50 52 49 a I4TEGER PRI
| 3920: 4d 41 52 59 20 4b 45 59 2c 0a 20 20 20 20 67 63 MARY KEY,. gc
| 3936: 63 20 41 53 20 28 74 32 2b 30 29 2c 0a 20 20 20 c AS (t2+0),.
| 3952: 20 62 20 55 4e 49 51 55 45 2c 0a 20 20 20 20 67 b UNIQUE,. g
| 3968: 63 61 20 41 53 20 28 31 2a 61 2b 30 29 2c 0a 20 ca AS (1*a+0),.
| 3984: 20 20 20 74 32 20 55 4e 49 51 55 45 0a 20 20 29 t2 UNIQUE. )
| 4000: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 23 03 WITHOUT ROWID#.
| 4016: 06 17 37 11 01 00 69 6e 64 65 78 73 71 6c 69 74 ..7...indexsqlit
| 4032: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 33 e_autoindex_t1_3
| 4048: 74 31 02 23 02 06 17 37 11 01 00 69 6e 64 65 78 t1.#...7...index
| 4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 sqlite_autoindex
| 4080: 5f 74 31 5f 32 74 31 02 00 00 00 08 00 00 00 00 _t1_2t1.........
| page 2 offset 4096
| 0: 0a 00 00 00 05 0f d8 00 0f f8 0f f8 9f e8 0f e0 ................
| 16: 0f d8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4048: 00 00 00 00 00 00 00 00 07 04 01 02 00 0f 13 88 ................
| 4064: 07 04 01 02 00 0e 0f a0 07 04 01 02 00 0d 0b b8 ................
| 4080: 07 04 01 02 00 0c 07 d0 07 04 01 02 00 0b 03 e8 ................
| page 5 offset 16384
| 0: 0a 00 00 00 05 0f e2 00 0f fa 0f f4 0f ee 0f e8 ................
| 16: 0f e2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4064: 00 00 05 03 01 01 0f 0f 05 03 01 01 0e 0e 05 03 ................
| 4080: 01 01 0d 0d 05 03 01 01 0c 0c 05 03 01 01 0b 0b ................
| end crash-f022eb0ce64d27.db
}]} {}
do_execsql_test 19.1 {
PRAGMA writable_schema=ON;
}
do_catchsql_test 19.2 {
UPDATE t1 SET a=1;
} {1 {UNIQUE constraint failed: index 'a'}}
finish_test
+4 -1
View File
@@ -539,6 +539,9 @@ datetest 17.5 {datetime(2457828,'start of year')} {2017-01-01 00:00:00}
datetest 17.6 {datetime(37,'start of year')} NULL
datetest 17.7 {datetime(38,'start of year')} {-4712-01-01 00:00:00}
# 2022-03-04 https://sqlite.org/forum/forumpost/2ffbaa2c3fd7fb82
# The 'localtime' modifier should preserve fractional seconds.
#
datetest 18.1 {strftime('%f',1.234,'unixepoch','localtime')} {01.234}
finish_test
+6
View File
@@ -102,4 +102,10 @@ do_catchsql_test 270 {
PRAGMA aux1.integrity_check;
} {0 ok}
db close
sqlite3 db :memory:
do_execsql_test 300 {
SELECT * FROM sqlite_temp_schema, sqlite_dbpage;
} {}
finish_test
+9
View File
@@ -171,4 +171,13 @@ do_execsql_test func6-200 {
SELECT offrec( sqlite_offset(y), x, y ) FROM t2 ORDER BY x
} $z100
# 2022-03-14 dbsqlfuzz 474499f3977d95fdf2dbcd99c50be1d0082e4c92
reset_db
do_execsql_test func6-300 {
CREATE TABLE t2(a INT, b INT PRIMARY KEY) WITHOUT ROWID;
CREATE INDEX x3 ON t2(b);
CREATE TABLE t1(a INT PRIMARY KEY, b TEXT);
SELECT * FROM t1 WHERE a IN (SELECT sqlite_offset(b) FROM t2);
} {}
finish_test
+19
View File
@@ -487,4 +487,23 @@ ifcapable like_match_blobs {
} {2.0}
}
# 2022-04-30 https://sqlite.org/forum/info/7efabf4b03328e57
# Assertion fault during a DELETE INDEXED BY.
#
reset_db
do_execsql_test indexexpr-1900 {
CREATE TABLE t1(x TEXT PRIMARY KEY, y TEXT, z INT);
INSERT INTO t1(x,y,z) VALUES('alpha','ALPHA',1),('bravo','charlie',1);
CREATE INDEX i1 ON t1(+y COLLATE NOCASE);
SELECT * FROM t1;
} {alpha ALPHA 1 bravo charlie 1}
do_execsql_test indexexpr-1910 {
DELETE FROM t1 INDEXED BY i1
WHERE x IS +y COLLATE NOCASE IN (SELECT z FROM t1)
RETURNING *;
} {alpha ALPHA 1}
do_execsql_test indexexpr-1920 {
SELECT * FROM t1;
} {bravo charlie 1}
finish_test
+7 -1
View File
@@ -11,7 +11,6 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the INSERT transfer optimization.
#
# $Id: insert4.test,v 1.10 2008/01/21 16:22:46 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -598,6 +597,13 @@ do_test 10.3 {
set sqlite3_xferopt_count
} {1}
do_test 10.4 {
execsql { PRAGMA integrity_check }
set sqlite3_xferopt_count 0
execsql { INSERT INTO x SELECT * FROM t8 RETURNING * }
set sqlite3_xferopt_count
} {0}
#-------------------------------------------------------------------------
# xfer transfer between tables where the source has an empty partial index.
#
+85
View File
@@ -300,6 +300,13 @@ do_execsql_test 7.3 {
do_eqp_test 7.4 {
SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?);
} {
QUERY PLAN
|--SCAN t3
`--SEARCH t4 USING INDEX t4xz (x=?)
}
do_eqp_test 7.4b {
SELECT * FROM t3 CROSS JOIN t4 ON (t4.x = t3.x) WHERE (+t4.y = ? OR t4.z = ?);
} {
QUERY PLAN
|--SCAN t3
@@ -342,4 +349,82 @@ do_execsql_test 9.1 {
SELECT a FROM (SELECT a FROM t1 NATURAL LEFT JOIN t1) NATURAL LEFT JOIN t1 WHERE (rowid,1)<=(5,0);
} {1}
# 2022-03-02 https://sqlite.org/forum/info/50a1bbe08ce4c29c
# Bloom-filter pulldown is incompatible with skip-scan.
#
reset_db
do_execsql_test 10.1 {
CREATE TABLE t1(x INT);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20)
INSERT INTO t1(x) SELECT 0 FROM c;
CREATE INDEX t1x1 ON t1(x BETWEEN 0 AND 10, x);
ANALYZE;
DELETE FROM t1;
INSERT INTO t1 VALUES(0),(0);
CREATE VIEW v1 AS SELECT * FROM t1 NATURAL JOIN t1 WHERE (x BETWEEN 0 AND 10) OR true;
CREATE VIEW v2 AS SELECT * FROM v1 NATURAL JOIN v1;
CREATE VIEW v3 AS SELECT * FROM v2, v1 USING (x) GROUP BY x;
SELECT x FROM v3;
} {0}
# 2022-03-24 https://sqlite.org/forum/forumpost/031e262a89b6a9d2
# Bloom-filter on a LEFT JOIN with NULL-based WHERE constraints.
#
reset_db
do_execsql_test 11.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
CREATE TABLE t2(c INTEGER PRIMARY KEY, d INT);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<8)
INSERT INTO t1(a,b) SELECT x, 10*x FROM c;
INSERT INTO t2(c,d) SELECT b*2, 100*a FROM t1;
ANALYZE;
DELETE FROM sqlite_stat1;
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES
('t1',NULL,150105),('t2',NULL,98747);
ANALYZE sqlite_schema;
} {}
do_execsql_test 11.2 {
SELECT count(*) FROM t1 LEFT JOIN t2 ON c=b WHERE d IS NULL;
} {4}
do_execsql_test 11.3 {
SELECT count(*) FROM t1 LEFT JOIN t2 ON c=b WHERE d=100;
} {1}
do_execsql_test 11.4 {
SELECT count(*) FROM t1 LEFT JOIN t2 ON c=b WHERE d>=300;
} {2}
# 2022-05-03 https://sqlite.org/forum/forumpost/2482b32700384a0f
# Bloom-filter pull-down does not handle NOT NULL constraints correctly.
#
reset_db
do_execsql_test 12.1 {
CREATE TABLE t1(a INT, b INT, c INT);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b,c) SELECT x, x*1000, x*1000000 FROM c;
CREATE TABLE t2(b INT, x INT);
INSERT INTO t2(b,x) SELECT b, a FROM t1 WHERE a%3==0;
CREATE INDEX t2b ON t2(b);
CREATE TABLE t3(c INT, y INT);
INSERT INTO t3(c,y) SELECT c, a FROM t1 WHERE a%4==0;
CREATE INDEX t3c ON t3(c);
INSERT INTO t1(a,b,c) VALUES(200, 200000, NULL);
ANALYZE;
} {}
do_execsql_test 12.2 {
SELECT * FROM t1 NATURAL JOIN t2 NATURAL JOIN t3 WHERE x>0 AND y>0
ORDER BY +a;
} {
12 12000 12000000 12 12
24 24000 24000000 24 24
36 36000 36000000 36 36
48 48000 48000000 48 48
60 60000 60000000 60 60
72 72000 72000000 72 72
84 84000 84000000 84 84
96 96000 96000000 96 96
}
finish_test
+17
View File
@@ -850,4 +850,21 @@ do_execsql_test json-17.1 {
SELECT * FROM t1 LEFT JOIN t2 ON (SELECT b FROM json_each ORDER BY 1);
} {}
# 2022-04-04 forum post https://sqlite.org/forum/forumpost/c082aeab43
do_execsql_test json-18.1 {
SELECT json_valid('{"":5}');
} {1}
do_execsql_test json-18.2 {
SELECT json_extract('{"":5}', '$.""');
} {5}
do_execsql_test json-18.3 {
SELECT json_extract('[3,{"a":4,"":[5,{"hi":6},7]},8]', '$[1].""[1].hi');
} {6}
do_execsql_test json-18.4 {
SELECT json_extract('[3,{"a":4,"":[5,{"hi":6},7]},8]', '$[1].""[1]."hi"');
} {6}
do_catchsql_test json-18.5 {
SELECT json_extract('{"":8}', '$.');
} {1 {JSON path error near ''}}
finish_test
+28
View File
@@ -2925,4 +2925,32 @@ do_test 43.3 {
sqlite3_db_status db CACHE_MISS 0
} {0 1 0}
# 2022-03-01 Forum post https://sqlite.org/forum/forumpost/3b9e894312
# Ensure that max_page_count gets adjusted upward, if needed, on a
# ROLLBACK.
#
db close
sqlite3 db :memory:
do_execsql_test 44.1 {
PRAGMA page_size=4096;
PRAGMA auto_vacuum=FULL;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b ANY);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<50)
INSERT INTO t1(a,b) SELECT x, zeroblob(1000) FROM c;
CREATE TABLE t2 AS SELECT * FROM t1;
PRAGMA page_count;
} {31}
do_execsql_test 44.2 {
BEGIN;
DROP TABLE t2;
PRAGMA incremental_vacuum=50;
PRAGMA page_count;
PRAGMA max_page_count=2;
} {16 16}
do_execsql_test 44.3 {
ROLLBACK;
PRAGMA page_count;
PRAGMA max_page_count;
} {31 31}
finish_test
+14
View File
@@ -362,4 +362,18 @@ do_execsql_test 15.2 {
DELETE FROM t1 RETURNING x, affinity(x);
} {6.0 real}
# 2022-02-28 Forum post https://sqlite.org/forum/forumpost/595e132f71
# RETURNING with the xfer optimization
#
reset_db
do_execsql_test 16.0 {
CREATE TABLE t1(a,b,c);
INSERT INTO t1 VALUES(1,2,3),('a','b','c');
CREATE TEMP TABLE t2(x,y,z);
INSERT INTO t2 SELECT * FROM t1 RETURNING *;
} {1 2 3 a b c}
do_execsql_test 16.1 {
SELECT * FROM t2;
} {1 2 3 a b c}
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
+17
View File
@@ -1221,6 +1221,23 @@ do_test shell1-8.4 {
+------------------+-----+
| 6683623321994527 | -47 |
+------------------+-----+}}
do_test shell1-8.5 {
catchcmd ":memory: --box" {
create table t(a text, b int);
insert into t values ('too long for one line', 1), ('shorter', NULL);
.header on
.width 10 10
.nullvalue NADA
select * from t;}
} {0 {┌────────────┬────────────┐
│ a │ b │
├────────────┼────────────┤
│ too long f │ 1 │
│ or one lin │ │
│ e │ │
├────────────┼────────────┤
│ shorter │ NADA │
└────────────┴────────────┘}}
#----------------------------------------------------------------------------
# Test cases shell1-9.*: Basic test that "dot" commands and SQL intermix ok.
+9
View File
@@ -188,4 +188,13 @@ b
2
}}
# Test for rejection of incomplete input at EOF.
# Reported at https://sqlite.org/forum/forumpost/718f489a43be3197
do_test shell2-1.4.7 {
catchcmd ":memory:" {
SELECT 'unclosed;}
} {1 {Parse error near line 2: unrecognized token: "'unclosed;"
SELECT 'unclosed;
^--- error here}}
finish_test
+45 -1
View File
@@ -262,7 +262,7 @@ do_test shell5-1.7.1 {
SELECT COUNT(*) FROM t3;}]
} [list 0 $rows]
# Inport from a pipe. (Unix only, as it requires "awk")
# Import from a pipe. (Unix only, as it requires "awk")
if {$tcl_platform(platform)=="unix"} {
do_test shell5-1.8 {
forcedelete test.db
@@ -476,6 +476,20 @@ CREATE TABLE t8(a, b, c);
db eval { SELECT * FROM t8 }
} {1 2 3}
do_test shell5-4.4 {
forcedelete shell5.csv
set fd [open shell5.csv w]
puts $fd "1,2,3"
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TEMP TABLE t8(a, b, c);
.import shell5.csv t8
.nullvalue #
SELECT * FROM temp.t8
}]
} {0 1,2,3}
#----------------------------------------------------------------------------
# Tests for the shell automatic column rename.
#
@@ -526,4 +540,34 @@ Columns renamed during .import shell5.csv due to duplicates:
"CoW" to "CoW_3",
"cOw" to "cOw_4"}}
#----------------------------------------------------------------------------
# Tests for preserving utf-8 that is not also ASCII.
#
do_test shell5-6.1 {
set out [open shell5.csv w]
fconfigure $out -translation lf
puts $out {あい,うえお}
puts $out {1,2}
close $out
forcedelete test.db
catchcmd test.db {.import -csv shell5.csv t1
.mode line
SELECT * FROM t1;}
} {0 { あい = 1
うえお = 2}}
do_test shell5-6.2 {
set out [open shell5.csv w]
fconfigure $out -translation lf
puts $out {1,2}
puts $out {あい,うえお}
close $out
forcedelete test.db
catchcmd test.db {.import -csv shell5.csv t1
.mode line
SELECT * FROM t1;}
} {0 { 1 = あい
2 = うえお}}
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 };
+11
View File
@@ -827,4 +827,15 @@ do_execsql_test trigger1-22.10 {
SELECT a, CASE WHEN typeof(b)='text' THEN quote(b) ELSE '<blob>' END, '|' FROM t1;
} {1 <blob> | 2 'X' | 3 'Z' |}
# 2022-03-06 https://sqlite.org/forum/forumpost/2024e94071
# Harmless assertion fault following a syntax error.
#
reset_db
do_catchsql_test trigger1-23.1 {
CREATE TABLE t1(a INT);
CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
INSERT INTO t1 SELECT e_master LIMIT 1,#1;
END;
} {1 {near "#1": syntax error}}
finish_test
+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);"
+20
View File
@@ -382,4 +382,24 @@ do_execsql_test 6.2 {
)
} {}
# 2022-03-21
# https://sqlite.org/forum/forumpost/929168fdd6
#
reset_db
do_execsql_test 7.0 {
CREATE TABLE t1(a);
INSERT INTO t1(a) VALUES(11),(22),(33),(44),(55);
CREATE VIEW t2(b,c) AS SELECT a, COUNT(*) OVER () FROM t1;
CREATE TABLE t3(x,y);
CREATE TRIGGER t2r1 INSTEAD OF UPDATE ON t2 BEGIN
INSERT INTO t3(x,y) VALUES(new.b,new.c);
END;
SELECT * FROM t2;
} {11 5 22 5 33 5 44 5 55 5}
do_execsql_test 7.1 {
UPDATE t2 SET c=t1.a FROM t1 WHERE t2.b=t1.a;
SELECT * FROM t3;
} {11 11 22 22 33 33 44 44 55 55}
finish_test
+24
View File
@@ -23361,4 +23361,28 @@ do_eqp_test where7-3.2 {
`--USE TEMP B-TREE FOR ORDER BY
}
# 2022-03-03 https://sqlite.org/forum/forumpost/36937b197273d403
#
# In the multi-index OR, if there is an auxiliary WHERE clause term
# that includes a subquery and that subquery is pushed down into the
# OR-clause subqueries, WHERE subquery might get coded as a subroutine.
# In that case, the covering-index optimizer will attempt to change
# table-references into index-references. But it will do so for the
# index of the OR branch in which the subquery is coded. If the
# subquery subroutine is called from a different OR branch, the
# index might be different and the index-reference will no longer
# work. tag-20220303a
#
reset_db
do_execsql_test 4.1 {
CREATE TABLE t0(w);
INSERT INTO t0(w) VALUES(1);
CREATE TABLE t1(x INT, y INT PRIMARY KEY, z);
INSERT INTO t1 VALUES(0,111,222);
CREATE INDEX t1zxy ON t1(z,x,y);
SELECT y FROM t1
WHERE (z=222 OR y=111)
AND (false OR EXISTS(SELECT 1 FROM t0 WHERE t1.y));
} {111}
finish_test
+45
View File
@@ -365,4 +365,49 @@ do_execsql_test 9.0 {
FROM seps;
} {-22- -22-333- -333-4444- -4444-}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 10.1 {
CREATE TABLE t1(i INTEGER PRIMARY KEY, v);
INSERT INTO t1 VALUES( 1, 'one' );
INSERT INTO t1 VALUES( 2, 'two' );
}
do_execsql_test 10.2 {
SELECT
json_group_array( v ) OVER w,
json_group_array( v ) OVER w
FROM t1
window w as (
range between unbounded preceding and unbounded following
)
} {
{["one","two"]}
{["one","two"]}
{["one","two"]}
{["one","two"]}
}
do_execsql_test 10.3 {
SELECT
group_concat( v ) OVER w,
json_group_array( v ) OVER w,
json_group_array( v ) OVER w,
group_concat( v ) OVER w
FROM t1
window w as (
range between unbounded preceding and unbounded following
)
} {
one,two
{["one","two"]}
{["one","two"]}
one,two
one,two
{["one","two"]}
{["one","two"]}
one,two
}
finish_test
+22 -16
View File
@@ -12,7 +12,7 @@
# Flag meanings:
set flagMeaning(NeedSchema) {Force schema load before running}
set flagMeaning(ReadOnly) {Read-only HEADER_VALUE}
set flagMeaning(OneSchema) {Only a single schema required}
set flagMeaning(Result0) {Acts as query when no argument}
set flagMeaning(Result1) {Acts as query when has one argument}
set flagMeaning(SchemaReq) {Schema required - "main" is default}
@@ -150,7 +150,7 @@ set pragma_def {
ARG: SQLITE_CellSizeCk
NAME: default_cache_size
FLAG: NeedSchema Result0 SchemaReq NoColumns1
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
COLS: cache_size
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -163,12 +163,12 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: page_count
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: max_page_count
TYPE: PAGE_COUNT
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: locking_mode
@@ -176,7 +176,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: journal_mode
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: journal_size_limit
@@ -184,18 +184,18 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: cache_size
FLAG: NeedSchema Result0 SchemaReq NoColumns1
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: mmap_size
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: auto_vacuum
FLAG: NeedSchema Result0 SchemaReq NoColumns1
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
NAME: incremental_vacuum
FLAG: NeedSchema NoColumns
FLAG: NeedSchema NoColumns OneSchema
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
NAME: temp_store
@@ -215,7 +215,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
NAME: synchronous
FLAG: NeedSchema Result0 SchemaReq NoColumns1
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: table_info
@@ -238,7 +238,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: stats
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq OneSchema
COLS: tbl idx wdth hght flgs
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
@@ -290,7 +290,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: foreign_key_list
FLAG: NeedSchema Result1 SchemaOpt
FLAG: NeedSchema Result1 SchemaOpt OneSchema
COLS: id seq table from to on_update on_delete match
IF: !defined(SQLITE_OMIT_FOREIGN_KEY)
@@ -336,14 +336,14 @@ set pragma_def {
NAME: data_version
TYPE: HEADER_VALUE
ARG: BTREE_DATA_VERSION
FLAG: ReadOnly Result0
ARG: BTREE_DATA_VERSION|PRAGMA_HEADER_VALUE_READONLY
FLAG: Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: freelist_count
TYPE: HEADER_VALUE
ARG: BTREE_FREE_PAGE_COUNT
FLAG: ReadOnly Result0
ARG: BTREE_FREE_PAGE_COUNT|PRAGMA_HEADER_VALUE_READONLY
FLAG: Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: application_id
@@ -357,7 +357,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
NAME: wal_checkpoint
FLAG: NeedSchema
FLAG: NeedSchema OneSchema
COLS: busy log checkpointed
IF: !defined(SQLITE_OMIT_WAL)
@@ -516,6 +516,12 @@ foreach f [lsort [array names allflags]] {
set fv [expr {$fv*2}]
}
puts $fd "\n/* For PragTyp_HEADER_VALUE pragmas the Pragma.iArg value is set"
puts $fd "** to the index of the header field to access (always 10 or less)."
puts $fd "** Ored with HEADER_VALUE_READONLY if the field is read only. */"
puts $fd "#define PRAGMA_HEADER_VALUE_READONLY 0x0100"
puts $fd "#define PRAGMA_HEADER_VALUE_MASK 0x00FF\n"
# Sort the column lists so that longer column lists occur first
#
proc colscmp {a b} {