Compare commits

...

88 Commits

Author SHA1 Message Date
drh ccc132c5be Version 3.53.2
FossilOrigin-Name: d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24
2026-06-03 19:12:13 +00:00
drh 5e132e142f Fix harmless compiler warning.
FossilOrigin-Name: ac00a18dcf132180295d41299f31fbc68087a27b61782d00b9633dd9661ded2b
2026-06-03 18:51:23 +00:00
drh b9e656f6f7 Fix a faulty assert() in rtree that could fire when processing an unusually large record.
FossilOrigin-Name: 004d85c5f1bf04409ce85d5131f1d9697f25f531046e60160e78b0bae7f55123
2026-06-03 16:58:01 +00:00
drh c867ce4b89 Use tail recursion on the larger of the two partitions when doing a
quicksort as part of the implementation of the median() function,
to avoid excess stack usage on pathological inputs.

FossilOrigin-Name: b8fce837cf633af7e489e9750bcd1764e96f9ad7ea01847d5ef9c7060f01a4bf
2026-06-03 16:23:45 +00:00
drh ceb66403bb Fix an integer overflow problem in fts3 that could lead to a buffer overwrite on platforms where size_t is 32-bits.
FossilOrigin-Name: 1389ec7bf6a7f68406adae6fd532497b2496f01fb5b465e18bd683da3f8f53ad
2026-06-03 15:54:58 +00:00
drh 6c1aa834f6 Fix another buffer overread in fts5 that could occur when processing
corrupt records.

FossilOrigin-Name: 8427cac76455ecbef224ceaccbb37b79338015bcfe67209ae462f36ffefa8466
2026-06-03 15:02:29 +00:00
drh e7d405200a Fix another potential buffer overrun that could occur in fts5 when
processing corrupt records.

FossilOrigin-Name: e583a723fa501d0c53ad124b571bcd6a42d76daba1ea983d3a547763c2c94c22
2026-06-03 14:24:19 +00:00
drh c911dda3d3 Fix a potential UAF bug in the zipfile extension.
FossilOrigin-Name: 46fbc23c16b3d104605f5abe5d7a5e779021e264bde409f2d9939de9b5cb9b37
2026-06-03 13:16:20 +00:00
drh edec48cd40 Avoid excessive recursion and stack overflow in fts3 when processing a corrupt
database.

FossilOrigin-Name: c32ddb6a3fe2b8cd5f8a8a133bd2d4061243a3bc0e7e29a96b4d0e5e6090977f
2026-06-03 12:04:07 +00:00
drh f7915390d5 The prefix_length() function should stop at the first NUL terminator.
FossilOrigin-Name: b5f9dc646df5059e546ceb1404a62aadeff4a33163d9b3758e78a33ff3c23467
2026-06-03 11:30:01 +00:00
drh 42be6fdf22 Make the (unused, untested, and unsupported) ext/misc/compress.c routines
responsive to OOM conditions.

FossilOrigin-Name: 2d1dc1c6c679d920e4f5d79acefbf318183ef37bc65bc78dc50f8512f317c1f5
2026-06-03 11:05:22 +00:00
dan 31a9e5c5d9 Update the session module so that it can apply changesets containing two or more UPDATE changes that form a dependency loop - so that no single UPDATE can be applied independently without violating a constraint.
FossilOrigin-Name: 919d393a3bc483bf58be1f8d6c2ef70f570d63cc9ad8d8df6a6562fb270ea7e5
2026-06-02 18:23:55 +00:00
drh 0851e6a4fe Remove a NEVER() that is actually reachable. This same NEVER() was removed
from trunk at check-in [0de3d95500b7ecd4].

FossilOrigin-Name: 46e74947f155199f5ce2440e8d5f19849d0daeb1d9d47381b0f84388901eab4c
2026-06-02 13:44:21 +00:00
drh b2543d0098 Disable transitive WHERE constraints when there are explicit COLLATE
operators.

FossilOrigin-Name: 4c0455efe57d1e3c27327e942a1509de3eb7b0902bc3b90473e2cba8df90139b
2026-06-01 18:07:44 +00:00
drh 4902f35e63 For expressions of the form "(x, y...) IN (SELECT a, b ...)" where the
result is not true, consider the collation sequences of columns "a" and "b" 
when determinining if the result should be false or NULL.

FossilOrigin-Name: 5ceba3fe8d9fb2b1e44a048b6e010d427b7f464b727b58824a2af1b53d57f1ec
2026-06-01 16:38:10 +00:00
drh 2a95fade33 Fix a minor problem with test case mjournal-3.3.
FossilOrigin-Name: dc1cc4d908df0e36447d0422ecbbbb6d2f59c7b49243407f8a9602e7bb0d1a00
2026-06-01 15:47:23 +00:00
drh 193a8f3673 Do not allow the argument to a table-valued function to reference a table
to its right, even if the SELECT is inside a common table expression.

FossilOrigin-Name: 27b4f821c752a65197746952cc168fab6a3aa0039d1a0100e3d8415225b5d4bf
2026-06-01 13:48:25 +00:00
drh 81ceb00b00 Fix an integer overflow that could lead to a buffer overrun in the zipfile
extension.

FossilOrigin-Name: ae9c99b904a8d1b9745a8f09cb35412e4107f4f24f95cabccc18a777b9e76bdf
2026-06-01 13:44:19 +00:00
drh 8626a528e1 Extra defenses against integer overflows in the untested, unused, and
unsupported transliterate() SQL extension function found in the
ext/misc/spellfix.c extension.

FossilOrigin-Name: ca800b1d2d243715426045df0d40ad171aed89182f4a5bb1055787964e74ff3c
2026-06-01 13:39:15 +00:00
drh b8c5fe2c19 Fix the zipfile extension so that ZIP archives containing files whose names
contain embedded \000 bytes do not cause problems.

FossilOrigin-Name: f6108e2fbdddfa03154a12efab17e5c1d681884ebcdfb6da5c319544601676ed
2026-05-31 15:52:29 +00:00
drh c3a422d794 Fix the format() SQL function so that it reports TOOBIG and NOMEM errors.
Fix a possible integer overflow on %#Q formatting.

FossilOrigin-Name: cd0c6953cdc3b2952070d4150da9c773da193d6710f41455a5c9832cd944831a
2026-05-31 09:23:09 +00:00
drh d542c33c9d Add a test to ensure an application does not try to create a geopoly
virtual table with too many columns.

FossilOrigin-Name: 00dc6063077080c7922c335f04bc1a34a7c8c8c3e85b8771c3133d264af3119e
2026-05-30 13:25:49 +00:00
drh fa5d2efbfc Remove the untested and undocumented "scrub" utility program. It was written
in 2016, but made obsolete by the VACUUM INTO command in 2019.

FossilOrigin-Name: 20c458172e0b09f7ada7f8cb8be95450c3988e620cbf6f174470bf8e78dcfbf0
2026-05-30 10:15:58 +00:00
drh c22fe7a31c Be sure to do floating-point to text conversions in JSON to the full
17-digits.

FossilOrigin-Name: 9498dade8754909d6fadc8cdff44dafc7770d53a1984ba27a00317ecd7e2f3dd
2026-05-29 23:17:09 +00:00
drh a15c394233 Fix potential integer overflow in btree overflow page cache computation.
FossilOrigin-Name: 093e23814e35f0cd0a4bded29b79ddecd7835626d9fe627bfbf4eb138403277f
2026-05-28 10:18:42 +00:00
drh d38b6c0a19 Fix a potential 1-byte overread in sqlite3changeset_invert() when
processing a corrupt buffer.

FossilOrigin-Name: 69554ec4e8354e8573071bc423e2dbd0059058388481be3e76fcb7c0fc1ff467
2026-05-26 15:09:07 +00:00
drh 600eb440c2 Fix a 32-bit integer overflow in sqlite3changegroup_change_blob() that
could lead to a buffer overwrite.

FossilOrigin-Name: f2a8ae2251561f2255c2974914293647cf304c6db79de9da957755fccaf8a8b6
2026-05-26 14:23:36 +00:00
drh e9b5658888 Fix QRF so that it works sensibly with "--wrap 1"
FossilOrigin-Name: 90eb6c22687449441824c7da5741a31e78bb78098c170382b230e851d03212c0
2026-05-26 13:57:36 +00:00
drh e44fc2ba34 Strength the defense against malicious command-line arguments in the
sqlite3_rsync utility program.

FossilOrigin-Name: a8d18783fb2dbe9683bb6f3b57ebb3cc3ccf1e5afdd5e14786abf1e4e240f51a
2026-05-26 11:46:58 +00:00
drh 18bc656fe1 Fix HTML ">" quoting in QRF.
FossilOrigin-Name: f6b35a9b5fc38245414f1bea9bc3c81b57f774711e77ab32fb91c984370ed5e9
2026-05-25 23:47:05 +00:00
drh 2e6dc01ea7 Enhance the defenses against malformed JSONB in the jsonbPayloadSize()
routine.

FossilOrigin-Name: 73dfb252f86807464642037df6ec7353b5b52d8c447837c7c4a6540ec622f29d
2026-05-25 18:53:35 +00:00
drh bf5c8d7d16 Fix a potential 1 byte overwrite that could occur when processing
a carefully crafted super-journal file.

FossilOrigin-Name: f654fa5ac938bb61d917fc33298052f5bd7a6e5e33b0539ac15cbd45bec023d3
2026-05-25 18:50:36 +00:00
drh 48aa50931a Fix a potential buffer overwrite that could occur when in fts5 when handling corrupt records.
FossilOrigin-Name: 02733fc4bc27df64b50ca5027ac94fc643146efb24bb4fdbcc70c45e1c58c919
2026-05-25 17:23:58 +00:00
drh 9bb1173b4f Fix the VFSes so that there is no 32-bit integer overflow in the
xShmMap method if the WAL file size exceeds about 25 terabytes, or
if the header is corrupted to make SQLite think that the WAL file size
is that big.

FossilOrigin-Name: 39a72dbe53c94be6784fa042cf093151eff43d67086449a4da975416adde120a
2026-05-21 15:27:55 +00:00
drh 2b6b982a77 Limit the length of inputs to the spellfix1_editdist() extension
function (not part of the standard SQLite build and rarely used)
to 99999 characters, to avoid any possibility of integer overflow.

FossilOrigin-Name: e56ac902fa4f1219d3affbe3ac9f822406a58486e456f0200a5d0f47fa4e5b43
2026-05-21 13:39:43 +00:00
drh 22bce652b3 A join constraint is not an equivalence unless both operands have the
same collation.

FossilOrigin-Name: 4247f48eec004c311cb046b1e97fbd44bc35d4b09e33c2b930dd3e1baabdb813
2026-05-21 13:06:04 +00:00
drh c4a831733f Fix a bug causing the session module to dereference a NULL pointer when applying a corrupt changeset.
FossilOrigin-Name: c813d9b777bedd58005b53d38fa3c235ca56bd57b76424cf9238c01a977a4b3d
2026-05-20 15:29:37 +00:00
drh 9f426fa956 Check-in [0d01c90bd7779192] was incomplete in that it did not remove
the incorrect assert() statement.  Fixed here.

FossilOrigin-Name: 2e9bb51ae951c421f7e5ed8e55fd6dca8b7d4b8543fd3ba3a9e9f017592c028b
2026-05-20 11:59:36 +00:00
drh 18bdf31933 Avoid returning an SQLITE_SCHEMA error from within sqlite3session_diff() if the schema has been recently modified.
FossilOrigin-Name: 15fb7ffe4be49d5242c47bef1b3cad5c923cd7f500896058db4dd257bc7b3924
2026-05-20 11:56:17 +00:00
drh 2c6e131593 Increase the patch level to 3.53.2
FossilOrigin-Name: 076d214410fc8aba38c7ada60a985adc6773e51a13add19cbd07a91375b483fd
2026-05-20 10:04:04 +00:00
drh f034bd10f0 Fix a potential buffer overread in fts5 that could occur when handling
corrupt records.  Improved detection of corrupt fts5 records.

FossilOrigin-Name: fad98805b7d73abf0cf17919397ac50757a2b888354fcf42b72640a12f32926c
2026-05-20 10:01:25 +00:00
drh 0d8e4e27b7 Silently ignore nested porter tokenizers in FTS5. Having nested porter
tokenizers is pointless, but it does use stack space unnecessarily.

FossilOrigin-Name: 8207ca671e1253135e5e36cd123fdcfb4d1f0fcf939d2c94238425fafd38c75a
2026-05-20 09:36:42 +00:00
drh dfc91368e7 Prevent integer overflow in the ICU extension.
FossilOrigin-Name: 42ef6f3f4fbe9fce3312259855df53d89e002adb0cf798c4aad074a8b7e988d5
2026-05-19 18:59:39 +00:00
drh d75e0a89ad Fix an assertion fault that can occur in RTree given a carefully
corrupted database.

FossilOrigin-Name: 0d01c90bd7779192f0541dfc43624f70241c45accf06ad43666310ec50e486d6
2026-05-19 18:47:37 +00:00
drh 0d56a90b3d Early detection of attempts to overwrite an in-use cache page due
to database corruption.

FossilOrigin-Name: c37b0d93bf750ddad0b271c5f133320f754e5af73c0b68a3d19f9276e196d667
2026-05-19 15:24:00 +00:00
drh 62587d292b Limit the size of input strings to the (disused) spellfix extension
to avoid excessive runtime and integer overflows.

FossilOrigin-Name: 2a8951b548a9408df300d238a9fea313268a30c322f0efc0b233bdd3e71a7f9d
2026-05-19 10:33:53 +00:00
drh 4e2383b65b Fix a NULL pointer dereference in the obscure (and unused) prefixes
extension, which I had forgotten even existed.

FossilOrigin-Name: 24b8ecd17f70f222c40aa91382515a7d0d0b82c882498ae0714818d672806e7f
2026-05-19 10:30:29 +00:00
drh 0b223f1027 Fix an off-by-one error in matchinfo('b') for FTS3 when there are a large
number of columns.

FossilOrigin-Name: 9bf2f4ca8f3d0cce2ac0bf3742a04a83460d309bd8864bd414946d35106014a9
2026-05-18 23:42:58 +00:00
drh 83f261d5a0 Limit the NEAR span in FTS3 to 1 billion, to avoid integer overflow.
FossilOrigin-Name: 99ea33f48d2e3b0df6561c63814750bd848577df83eae9132e9ea0d009925838
2026-05-18 20:46:08 +00:00
drh 8d36080bd5 Prevent integer overflow due to database corruption in.
fts3auxNextMethod().

FossilOrigin-Name: aebf56a78d57b06079063fd008d56d1b4637c25de8cd5e5883ed8f8f63d42cca
2026-05-18 20:30:31 +00:00
drh 1cddaab5f9 When a subquery is an argument to an SQLITE_SUBTYPE function, then set
the EP_SubtArg flag on the result-set expressions of that subquery.

FossilOrigin-Name: d496e9320393d3c249a30499bd5c7278c9282a77416b5bbef3da175714d9284c
2026-05-18 19:46:38 +00:00
drh a66d74e1de Fix the window-function variant of the json_group_object() function so
that it correctly handles NULL entries.

FossilOrigin-Name: d29d9512a72972778c374524a3cd5d52a1377bf7fb7ff34028135146d75909b8
2026-05-18 17:58:30 +00:00
drh 574d888a10 Do not attempt the OR-optimization on conjuncts that contain COLLATE
operators.

FossilOrigin-Name: 4c105d79010939bdb8cb0461c3926f80815d4f0213bc0206be76015218cb8125
2026-05-18 14:32:45 +00:00
drh a523e20bba Correction to the bugfix at [212c68249cc0e890] so that it works
for 2nd and subsequent terms of a row value.

FossilOrigin-Name: 49c9b80e52642b94f1fa0b50ecd33a96b98a8c28d1175ac2c490d22e8c1433ce
2026-05-18 12:12:06 +00:00
drh 3580d166e5 When two tables are joined by USING, the affinity and collating sequence of
the join column will be the same as one or the other of the columns in the
two tables (which are hopefully the same).

FossilOrigin-Name: 8096d548eb035afc94653303000cff2f63a4c996c1dd9bf6114c4299376088fc
2026-05-16 20:29:03 +00:00
drh 1e4ec59e3f Fix false-negatives in the sqlite3ExprCanReturnSubtype() routine having
to do with CASE, CAST, and COLLATE expressions and the "+" no-op operator.

FossilOrigin-Name: 8eb07e92cfecb6f369206f71b42edad81d7eced0ca5576a13fd754eb7db16e55
2026-05-16 17:34:27 +00:00
drh af24f5e21e Have window functions sum(), total() and avg() correctly handle the obscure case where integer overflow occurs as part of the same step that adds the first real value to the running total. Fix for forum post [forum:ec538b04ce | ec538b04ce].
FossilOrigin-Name: eb95d18aee8ffb9a2550aadbecccaf43c0a5778973386da1196a46f645e04286
2026-05-16 17:09:12 +00:00
drh 7678510ff2 Have the sqlite_dbpage module correctly handle constraints of the form "WHERE pgno=$pgno" when $pgno is an integer that cannot be represented as a signed, 32-bit value.
FossilOrigin-Name: b6ce57f807297966f305d257e616f1c88a2f25c29f622249194b19d6fa014580
2026-05-16 16:08:03 +00:00
drh 066b667313 Prevent internal-use-only SQL functions from being used inside of a CHECK
constraint added using ALTER TABLE ADD CONSTRAINT.

FossilOrigin-Name: 6cb565fe20049a48619fa3c7995de30fd9e284cfacd1652465e1f9083daf2669
2026-05-11 14:47:45 +00:00
drh e0b995b2a6 Fix potential buffer overwrite that could occur in fts5 when processing corrupt records.
FossilOrigin-Name: 061febcf41ca4872a0f407951e1507209daca7895122b909a7806c60b6e200c4
2026-05-11 12:00:19 +00:00
stephan 9db56a4935 In sqlite-config.tcl remove a reference to the platform name apple when checking for Mac platforms, relying on a check for darwin instead, analog to [b5c6cb13cff53f]. Resolves how DLL names are formulated on some systems.
FossilOrigin-Name: 640f2016ab06125ebc9756344f28093750defbedc6fad2894b0d02a12b585149
2026-05-09 15:07:27 +00:00
drh a5ce91b319 Fix upward propagation of expression properties into row-value expressions.
FossilOrigin-Name: 5e639b7f15c1de773a83eccfeea67122616a62105299af41dd7c2df2ea74102c
2026-05-09 13:57:11 +00:00
drh 0268517163 Fix a corner-case floating-point rounding problem in the generate_series()
virtual table.

FossilOrigin-Name: 931119281252ba73693770ac301010a84eb9c2b06247b17e3252271163341ab0
2026-05-09 12:08:59 +00:00
drh ccd445d76a Version 3.53.1
FossilOrigin-Name: c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9
2026-05-05 10:34:17 +00:00
stephan b14b7681f4 Fix a predicate which causes a false error in the OPFS SAHPool tests when building with SEE.
FossilOrigin-Name: 1d2f770713f9d75d0de923515f4cee8ff83e95826d77f049b7bb1fbfad042248
2026-05-05 08:12:37 +00:00
drh 55f2cf294f When using the OR-optimization on a loop created by exists-to-join,
do the early-exit logic for the whole loop, not for each individual
OR branch.

FossilOrigin-Name: b827cdcb371d07cd4ffba4d3c7b404bece43fcc808db528b94a66bf77b6aab4f
2026-05-04 18:30:02 +00:00
drh 10305aa4a4 Fix a harmless compiler warning.
FossilOrigin-Name: 9957c3b907d66ed1b8afa3b71ba0ad23b2de3ec486e6232b58166fd3a410705a
2026-05-02 13:18:40 +00:00
drh 20847aca95 Harden the recovery extension against SQL injections coming from the
sqlite_schema table of the database being recovered.

FossilOrigin-Name: 555401fe048a51ecaed3ef672723b6ef8e1340c7028c11a17731abbc399bc078
2026-05-01 13:56:19 +00:00
drh e64e95b437 Fix a crash that could occur if sqlite3_deserialize() was used to overwrite a database with an open transaction on it. Bug introduced by [fc42d31d6fca21ab] on 2018-03-07 and first released in version 3.23.0. This is not a vulnerability as an attacker that can exploit this already has the ability to execute arbitrary code. Forum post [forum:39134ba029 | 39134ba029].
FossilOrigin-Name: b7b0745d6def6b141c900884cd97f10f3afedcbfb4bd9ce2409ee2380a8602dd
2026-04-27 12:28:23 +00:00
drh 27e808ff2c Feature detection fix for uint128 on RISCV 32-bit.
FossilOrigin-Name: e3f318bf52932460890333c6dcae352ab4b0c943d7be67734649eff1ff9fc9fc
2026-04-27 12:25:36 +00:00
stephan 0e4b46a649 Increase a stack-local buffer size to resolve a test regression introduced in [ff084ae341eab5c], in which some tests fail a pattern match check if their absolute file names are too long. Resolves [forum:205f73db1b2806f5|forum post 205f73db1b2806f5].
FossilOrigin-Name: 4eeb1f74f61589f115810bd2a6876dcec9e674a2baf686f3b5b25678695aa797
2026-04-27 12:07:31 +00:00
drh 2ba7864bc4 Fix a single-byte OOB read that could occur in the session module when concatenating patchsets.
FossilOrigin-Name: 5150cf9a89aebfd7121b4742c8b359116f16d890e83b64105bb192d3d0f68971
2026-04-25 15:04:21 +00:00
dan 2114d8bbd2 Update interrupt2.test to avoid using Tcl_GetCommandInfo() from within calls to Tcl_DeleteCommand().
FossilOrigin-Name: 00daafed79290b9bbf7a9359b656d8841745caf22c1c3cdcbacf05eebcfe300c
2026-04-23 11:33:26 +00:00
drh 928890f18f Various minor bug fixes cherrypicked from trunk.
FossilOrigin-Name: f1276db5dabe797dfeee2afbb9f3a3fe367b5f860a07af88963f16aa3986f7b9
2026-04-21 22:55:44 +00:00
drh 7b3ed290d3 Fix another bug in EXISTS-to-JOIN - this one
having to do with an OFFSET clause of a LIMIT.

FossilOrigin-Name: f91099ecee5413b3ab7261461e774436f5a9214101eea10d234135abe70bb444
2026-04-21 13:06:15 +00:00
stephan 002226b549 Reformulate how the OPFS async proxy Worker is loaded for the bundler-friendly builds to work around a bug in Vite in which it incompatibly rewrites the Worker's URL arguments. Addresses the discussion at [https://github.com/sqlite/sqlite-wasm/pull/159|npm package PR 159] and patch validated by Jure Rotar.
FossilOrigin-Name: 6215c9dd27ca446bf61d8ee7adcf455d35914853b19cb5f5feff5ce0f420e7b7
2026-04-21 10:15:16 +00:00
stephan 7ad112014b On platforms which support ./configure --with-icu-config, ensure that 'make tclextension' includes the ICU pieces in the tcl extension. Intended to resolve [forum:92a88de4b88929fe|forum post 92a88de4b88929fe].
FossilOrigin-Name: a4f27adb97f2fb8bf44931d3a44f9d05f0485e743ad086177b8f9471ee9dfff5
2026-04-17 04:59:42 +00:00
drh f9c7f9fb52 Fix parsing of options to the .once command.
FossilOrigin-Name: fd21b079e9ded037f9ec65f04864684060b8b80d034dfc9b07e01b5a1f75d79a
2026-04-17 01:55:29 +00:00
drh 02bd4aa037 Version number to 3.53.1
FossilOrigin-Name: b4c1cc5efcc1e538ed71ffd847030d80ab03fe6e6785f14fbad7f6079321d199
2026-04-15 19:09:34 +00:00
dan 8113b83c01 Handle a special case of a corrupt changeset in sqlite3changegroup_add().
FossilOrigin-Name: dceee93ab38a623a6c94658583ad6e012e141d5a4eaa91b074de06e175cb4175
2026-04-15 17:13:42 +00:00
dan 4c6c2ed134 Handle the case where the name of the constraint in an "ALTER TABLE DROP CONSTRAINT" command is quoted. [forum:8bfbaec404 | Forum post 8bfbaec404].
FossilOrigin-Name: 2d37af77a139cdcecb959b0821e5ed925f12789a759d0c94dce29d4b30b5750a
2026-04-15 16:22:59 +00:00
drh df330b6f92 Bug fix in sqlite3_str_free(): Do not crash if called on an sqlite3_str
object returned from sqlite3_str_new() following an OOM.

FossilOrigin-Name: b6b1d069cd5528b79ab0412137971fca1963a500f99e5c53ae57de1dd90066d2
2026-04-15 14:22:35 +00:00
stephan ef152ec09f Fix a typo which caused .headers to not show up in the shell's .help.
FossilOrigin-Name: 9efc1b6497ac5a4d0aef8fa73cdb016160720b076183c3727edc3de438e094e6
2026-04-12 05:43:12 +00:00
stephan 2c01c19968 Ensure that sqlite3-opfs-async-proxy.js is copied into the fiddle target dirs.
FossilOrigin-Name: d4e0e81afda425b23ac52f08ab9c3a2c136b8a963bd09ebcfb2f6f305b23e396
2026-04-10 23:33:31 +00:00
stephan 81fa34e507 API doc correction for sqlite3_js_retry_busy(). No code changes.
FossilOrigin-Name: e2bfb67da9538527b2eb92d261c82d4d0854a36ac55989373f07e3b854678694
2026-04-10 17:56:54 +00:00
drh 1bb371e6d3 Use sqlite3_malloc() for memory allocation inside of sqlite3_str_vappendf(),
since it invokes sqlite3_initialize(), whereas sqlite3DbMallocRaw() does
not.

FossilOrigin-Name: d959559d1fc34381861085ed8ac97b7ce72a4a83c6f846a6abd1e4552db081b4
2026-04-10 17:16:46 +00:00
drh 916f74e485 Fix the printf() optimization added on 2026-03-29 so that
sqlite3_snprintf() does not incorrectly truncate floating-point
conversions.

FossilOrigin-Name: 7c6883ecd3b284f38bfa93b03653fb48eaa42f223ae7ab12e1ad03082f3db44b
2026-04-10 16:06:09 +00:00
stephan 282e2cea0a Correct shell result code propagation regression introduced in [ff084ae341eab5c4] and reported in [forum:6fa3247e9724844c|forum post 6fa3247e9724844c].
FossilOrigin-Name: 5306da4231efcaf1bd7afa3cdcfcb87edf70958e3dd2edaed765a0d844e3be03
2026-04-10 08:39:51 +00:00
99 changed files with 2957 additions and 1103 deletions
-3
View File
@@ -1896,9 +1896,6 @@ RSYNC_OPT = \
sqlite3_rsync.exe: $(RSYNC_SRC) $(LIBRESOBJS)
$(LTLINK) $(RSYNC_OPT) $(NO_WARN) $(RSYNC_SRC) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
srcck1.exe: $(TOP)\tool\srcck1.c
$(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\srcck1.c
+1 -1
View File
@@ -1 +1 @@
3.53.0
3.53.2
+6 -2
View File
@@ -1745,8 +1745,12 @@ proc sqlite-handle-env-quirks {} {
set autoDll 0; # true if --out-implib/--dll-basename should be implied
set host [get-define host]
switch -glob -- $host {
*apple* -
*darwin* { set instName darwin }
*-*-darwin* {
set instName darwin
# We don't look for *apple* because:
# https://sqlite.org/forum/forumpost/7b218c3c9f207646
# There's at least one Linux out there which matches *apple*.
}
default {
set x [sqlite-env-is-unix-on-windows $host]
if {"" ne $x} {
+11 -1
View File
@@ -302,6 +302,12 @@
SQLITE_EXTENSION_INIT1
#endif
/*
** Assume any b-tree layer with more levels than this is corrupt.
*/
#define FTS3_MAX_BTREE_HEIGHT 48
typedef struct Fts3HashWrapper Fts3HashWrapper;
struct Fts3HashWrapper {
Fts3Hash hash; /* Hash table */
@@ -2018,7 +2024,11 @@ static int fts3SelectLeaf(
assert( piLeaf || piLeaf2 );
fts3GetVarint32(zNode, &iHeight);
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
if( iHeight>FTS3_MAX_BTREE_HEIGHT ){
rc = FTS_CORRUPT_VTAB;
}else{
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
}
assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
if( rc==SQLITE_OK && iHeight>1 ){
+1 -1
View File
@@ -341,7 +341,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
/* State 3. The integer just read is a column number. */
default: assert( eState==3 );
iCol = (int)v;
if( iCol<1 ){
if( iCol<1 || iCol>(pFts3->nColumn+1) ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
+1
View File
@@ -471,6 +471,7 @@ static int getNextNode(
assert( nKey==4 );
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
if( nNear>=1000000000 ) nNear = 1000000000;
}
}
+1 -1
View File
@@ -887,7 +887,7 @@ static int fts3ExprLHits(
if( p->flag==FTS3_MATCHINFO_LHITS ){
p->aMatchinfo[iStart + iCol] = (u32)nHit;
}else if( nHit ){
p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
p->aMatchinfo[iStart + iCol/32] |= (1U << (iCol&0x1F));
}
}
assert( *pIter==0x00 || *pIter==0x01 );
+16 -5
View File
@@ -922,7 +922,7 @@ static void fts5DataRelease(Fts5Data *pData){
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
Fts5Data *pRet = fts5DataRead(p, iRowid);
if( pRet ){
if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
if( pRet->szLeaf<4 || pRet->szLeaf>pRet->nn ){
FTS5_CORRUPT_ROWID(p, iRowid);
fts5DataRelease(pRet);
pRet = 0;
@@ -2576,6 +2576,10 @@ static void fts5LeafSeek(
if( nKeep<nMatch ){
goto search_failed;
}
if( (iOff+nNew)>n ){
FTS5_CORRUPT_ITER(p, pIter);
return;
}
assert( nKeep>=nMatch );
if( nKeep==nMatch ){
@@ -3552,8 +3556,7 @@ static void fts5PoslistFilterCallback(
do {
while( i<nChunk && pChunk[i]!=0x01 ){
while( pChunk[i] & 0x80 ) i++;
i++;
fts5IndexSkipVarint(pChunk, i);
}
if( pCtx->eState ){
fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
@@ -3702,7 +3705,7 @@ static void fts5IndexExtractColset(
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
** not part of a varint */
while( p<pEnd && *p!=0x01 ){
while( *p++ & 0x80 );
while( p<pEnd && (*p++ & 0x80) );
}
if( pColset->aiCol[i]==iCurrent ){
@@ -3799,8 +3802,11 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
assert( pIter->pColset );
assert( pIter->poslist.nSpace>=pIter->pIndex->pConfig->nCol );
if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf
|| pSeg->nPos>pIter->pIndex->pConfig->nCol
){
fts5IterSetOutputs_Col(pIter, pSeg);
}else{
u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
@@ -5294,6 +5300,11 @@ static void fts5DoSecureDelete(
}else{
iStart = fts5GetU16(&aPg[0]);
}
if( iStart>nPg ){
FTS5_CORRUPT_IDX(p);
sqlite3_free(aIdx);
return;
}
iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
assert_nc( iSOP<=pSeg->iLeafOffset );
+8 -2
View File
@@ -586,8 +586,14 @@ static int fts5PorterCreate(
const char *zBase = "unicode61";
fts5_tokenizer_v2 *pV2 = 0;
if( nArg>0 ){
zBase = azArg[0];
while( nArg>0 ){
if( sqlite3_stricmp(azArg[0],"porter")==0 ){
nArg--;
azArg++;
}else{
zBase = azArg[0];
break;
}
}
pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer));
+2 -2
View File
@@ -15153,9 +15153,9 @@ do_execsql_test 78.1 {
CREATE VIRTUAL TABLE t3 USING fts5vocab('t1','col');
}
do_execsql_test 78.2 {
do_catchsql_test 78.2 {
SELECT count(rowid) FROM t3 WHERE term>='nsocse';
} 2
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
+217 -1
View File
@@ -1220,7 +1220,7 @@ do_test 8.0 {
do_catchsql_test 8.1 {
SELECT rowid FROM t1('a* NOT ý‘') ;
} {0 {1 2 3 4 5 6 7}}
} {1 {fts5: corruption on page 1, segment 1, table "t1"}}
#-------------------------------------------------------------------------
reset_db
@@ -1917,6 +1917,222 @@ do_catchsql_test 11.3 {
REPLACE INTO t1(rowid,b,a,rowid) VALUES(x'44023b9eb002d28b0ee90c',1,2,3);
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_test 12.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename p.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 03 00 00 00 06 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 ................
| 96: 00 2e 76 89 0d 00 00 00 06 0d ed 00 0f bb 0f 64 ..v............d
| 112: 0e f9 0e a2 0e 45 0d ed 00 00 00 00 00 00 00 00 .....E..........
| 3552: 00 00 00 00 00 00 00 00 00 00 00 00 00 56 06 06 .............V..
| 3568: 17 1f 1f 01 7d 74 61 62 6c 65 66 74 5f 63 6f 6e .....tableft_con
| 3584: 66 69 67 66 74 5f 63 6f 6e 66 69 67 06 43 52 45 figft_config.CRE
| 3600: 41 54 45 20 54 41 42 4c 45 20 27 66 74 5f 63 6f ATE TABLE 'ft_co
| 3616: 6e 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 nfig'(k PRIMARY
| 3632: 4b 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 KEY, v) WITHOUT
| 3648: 52 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 ROWID[...!!...ta
| 3664: 62 6c 65 66 74 5f 64 6f 63 73 69 7a 65 66 74 5f bleft_docsizeft_
| 3680: 64 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 docsize.CREATE T
| 3696: 41 42 4c 45 20 27 66 74 5f 64 6f 63 73 69 7a 65 ABLE 'ft_docsize
| 3712: 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 '(id INTEGER PRI
| 3728: 4d 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f MARY KEY, sz BLO
| 3744: 42 29 55 04 06 17 21 21 01 77 74 61 62 6c 65 66 B)U...!!.wtablef
| 3760: 74 5f 63 6f 6e 74 65 6e 74 66 74 5f 63 6f 6e 74 t_contentft_cont
| 3776: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
| 3792: 20 27 66 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 'ft_content'(id
| 3808: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
| 3824: 20 4b 45 59 2c 20 63 30 29 69 03 07 17 19 19 01 KEY, c0)i......
| 3840: 81 2d 74 61 62 6c 65 66 74 5f 69 64 78 66 74 5f .-tableft_idxft_
| 3856: 69 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 idx.CREATE TABLE
| 3872: 20 27 66 74 5f 69 64 78 27 28 73 65 67 69 64 2c 'ft_idx'(segid,
| 3888: 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 term, pgno, PRI
| 3904: 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 MARY KEY(segid,
| 3920: 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 term)) WITHOUT R
| 3936: 4f 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 OWIDU........tab
| 3952: 6c 65 66 74 5f 64 61 74 61 66 74 5f 64 61 74 61 left_dataft_data
| 3968: 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 66 .CREATE TABLE 'f
| 3984: 74 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 t_data'(id INTEG
| 4000: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
| 4016: 62 6c 6f 63 6b 20 42 4c 4f 42 29 43 01 06 17 11 block BLOB)C....
| 4032: 11 08 75 74 61 62 6c 65 66 74 66 74 43 52 45 41 ..utableftftCREA
| 4048: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE
| 4064: 20 66 74 20 55 53 49 4e 47 20 66 74 73 35 28 61 ft USING fts5(a
| 4080: 2c 20 64 65 74 61 69 6c 3d 63 6f 6c 75 6d 6e 29 , detail=column)
| page 2 offset 4096
| 0: 0d 00 00 00 03 0f 7f 00 0f e8 0f ef 0f 7f 00 00 ................
| 3952: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 62 ...............b
| 3968: 84 80 80 80 80 01 04 00 81 48 00 00 00 54 04 30 .........H...T.0
| 3984: 61 61 61 01 81 02 02 02 02 02 02 02 02 02 02 02 aaa.............
| 4000: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 4016: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 4032: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
| 4048: 02 02 02 02 02 02 02 03 6a 6a 6a 01 02 02 04 08 ........jjj.....
| 4064: 08 08 08 08 08 08 08 08 05 01 03 00 10 01 0a 0f ................
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 01 0f d4 00 0f d4 00 00 00 00 00 00 ................
| 4048: 00 00 00 00 2a 01 03 00 5b 61 61 61 20 62 62 62 ....*...[aaa bbb
| 4064: 20 63 63 63 20 64 64 64 20 65 65 65 20 66 66 66 ccc ddd eee fff
| 4080: 20 67 67 67 20 68 68 68 20 69 69 69 20 6a 6a 6a ggg hhh iii jjj
| page 5 offset 16384
| 0: 0d 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 04 01 03 00 0e 0a ................
| page 6 offset 20480
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| end p.db
}]} {}
do_catchsql_test 12.1 {
SELECT rowid FROM ft('a:aaa')
} {0 1}
#-------------------------------------------------------------------------
reset_db
do_test 13.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename vuln_001.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 03 00 00 00 06 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 ................
| 96: 00 2e 76 89 0d 00 00 00 06 0e 09 00 0f ca 0f 77 ..v............w
| 112: 0f 0f 0e b7 0e 5e 0e 09 00 00 00 00 00 00 00 00 .....^..........
| 3584: 00 00 00 00 00 00 00 00 00 53 06 06 17 1d 1d 01 .........S......
| 3600: 7b 74 61 62 6c 65 74 5f 63 6f 6e 66 69 67 74 5f .tablet_configt_
| 3616: 63 6f 6e 66 69 67 06 43 52 45 41 54 45 20 54 41 config.CREATE TA
| 3632: 42 4c 45 20 27 74 5f 63 6f 6e 66 69 67 27 28 6b BLE 't_config'(k
| 3648: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
| 3664: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 57 05 WITHOUT ROWIDW.
| 3680: 06 17 1f 1f 01 7f 74 61 62 6c 65 74 5f 64 6f 63 ......tablet_doc
| 3696: 73 69 7a 65 74 5f 64 6f 63 73 69 7a 65 05 43 52 sizet_docsize.CR
| 3712: 45 41 54 45 20 54 41 42 4c 45 20 27 74 5f 64 6f EATE TABLE 't_do
| 3728: 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 45 csize'(id INTEGE
| 3744: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 R PRIMARY KEY, s
| 3760: 7a 20 42 4c 4f 42 29 56 04 06 17 1f 1f 01 7d 74 z BLOB)V.......t
| 3776: 61 62 6c 65 74 5f 63 6f 6e 74 65 6e 74 74 5f 63 ablet_contentt_c
| 3792: 6f 6e 74 65 6e 74 04 43 52 45 41 54 45 20 54 41 ontent.CREATE TA
| 3808: 42 4c 45 20 27 74 5f 63 6f 6e 74 65 6e 74 27 28 BLE 't_content'(
| 3824: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 id INTEGER PRIMA
| 3840: 52 59 20 4b 45 59 2c 20 63 30 2c 20 63 31 29 66 RY KEY, c0, c1)f
| 3856: 03 07 17 17 17 01 81 2b 74 61 62 6c 65 74 5f 69 .......+tablet_i
| 3872: 64 78 74 5f 69 64 78 03 43 52 45 41 54 45 20 54 dxt_idx.CREATE T
| 3888: 41 42 4c 45 20 27 74 5f 69 64 78 27 28 73 65 67 ABLE 't_idx'(seg
| 3904: 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 id, term, pgno,
| 3920: 50 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 PRIMARY KEY(segi
| 3936: 64 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 d, term)) WITHOU
| 3952: 54 20 52 4f 57 49 44 51 02 06 17 19 19 01 7f 74 T ROWIDQ.......t
| 3968: 61 62 6c 65 74 5f 64 61 74 61 74 5f 64 61 74 61 ablet_datat_data
| 3984: 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
| 4000: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE
| 4016: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b
| 4032: 6c 6f 63 6b 20 42 4c 4f 42 29 34 01 06 17 0f 0f lock BLOB)4.....
| 4048: 08 5b 74 61 62 6c 65 74 74 43 52 45 41 54 45 20 .[tablettCREATE
| 4064: 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 20 VIRTUAL TABLE t
| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 USING fts5(a, b)
| page 2 offset 4096
| 0: 0d 00 00 00 04 0b da 00 0f e7 0f ef 0f ce 0b da ................
| 3024: 00 00 00 00 00 00 00 00 00 00 87 6c 84 80 80 80 ...........l....
| 3040: 80 02 04 00 8f 5c 00 00 03 e8 80 80 80 80 80 80 ................
| 3056: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3072: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3088: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3104: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3120: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3136: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3152: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3168: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3184: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3200: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3216: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3232: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3248: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3264: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3280: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3296: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3312: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3328: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3344: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3360: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3376: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3392: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3408: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3424: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3440: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3456: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3472: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3488: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3504: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3520: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3536: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3552: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3568: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3584: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3600: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3616: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3632: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3648: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3664: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3680: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3696: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3712: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3728: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3744: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3760: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3776: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3792: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3808: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3824: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3840: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3856: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3872: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3888: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3904: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3920: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3936: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3952: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3968: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 3984: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 4000: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 4016: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
| 4032: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 12 84 ................
| 4048: 80 80 80 80 01 03 00 2a 00 0b 00 0e 06 30 68 65 .......*.....0he
| 4064: 6c 6c 6f 01 04 04 04 06 01 03 00 12 01 02 02 0f llo.............
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 02 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 01 0f e8 00 0f e8 00 00 00 00 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 16 01 04 00 23 1b 68 65 ............#.he
| 4080: 6c 6c 6f 20 77 6f 72 6c 64 66 6f 6f 20 62 61 72 llo worldfoo bar
| page 5 offset 16384
| 0: 0d 00 00 00 01 0f f9 00 0f f9 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 05 01 03 00 10 02 02 ................
| page 6 offset 20480
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| end vuln_001.db
}]} {}
do_catchsql_test 13.1 {
SELECT * FROM t('a:hello')
} {0 {{hello world} {foo bar}}}
sqlite3_fts5_may_be_corrupt 0
finish_test
+36
View File
@@ -125,4 +125,40 @@ do_catchsql_test 2.3 {
DELETE FROM t1 WHERE rowid = 1
} {/.*fts5: corrupt.*/}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
PRAGMA page_size=4096;
PRAGMA journal_mode=DELETE;
CREATE VIRTUAL TABLE t USING fts5(x, detail=none);
WITH s(i) AS (
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<5000
)
INSERT INTO t(rowid, x) SELECT i, 'vulnerabilitytest' FROM s;
INSERT INTO t(t) VALUES('optimize');
INSERT INTO t(t, rank) VALUES('secure-delete', 1);
} {delete}
do_test 3.1 {
db eval { SELECT rowid AS rowid, block FROM t_data ORDER BY rowid } {
if {$rowid>=10 && [string length $block]>=4} {
binary scan $block Su first_rowid_off
set pgno [expr ($rowid & 0x7FFFFFFF)]
if {$pgno>=2 && $first_rowid_off>0} break
}
}
set bad [binary format a*a* "\xFF\xFF" [string range $block 2 end]]
db eval {
UPDATE t_data SET block = $bad WHERE rowid=$rowid
}
} {}
do_catchsql_test 3.2 {
DELETE FROM t WHERE rowid=4500;
} {1 {fts5: corruption in table "t"}}
finish_test
+128
View File
@@ -0,0 +1,128 @@
# 2026 May 11
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5corruptA
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
sqlite3_fts5_may_be_corrupt 1
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t USING fts5(x, detail='full');
INSERT INTO t(t, rank) VALUES('pgsz', 32);
}
set big [string repeat "a " 200]
do_execsql_test 1.1 {
INSERT INTO t(rowid, x) VALUES(1, $big)
}
do_test 1.2 {
db eval {
SELECT min(rowid) AS base_rowid, count(*) AS page_count FROM t_data
WHERE rowid>1000
} {}
} {}
do_test 1.3 {
for {set ii 0} {$ii < 5} {incr ii} {
db eval {
INSERT INTO t_data(rowid, block)
VALUES( $base_rowid + $page_count + $ii, zeroblob(4) );
}
}
db eval {
INSERT INTO t_data(rowid, block)
VALUES( $base_rowid + $page_count + 5,
unhex('00000080' || 'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC') );
}
set {} {}
} {}
db close
do_test 1.4 {
set hex [hexio_read test.db 0 [file size test.db]]
set off [string first "023061018310" $hex]
set hex [string replace $hex $off [expr $off+11] 023061018370]
hexio_write test.db 0 $hex
} {6144}
sqlite3 db test.db
do_catchsql_test 1.5 {
SELECT rowid FROM t WHERE t MATCH 'a'
} {1 {fts5: corruption found reading blob 137438953481 from table "t"}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a);
BEGIN;
INSERT INTO t1(rowid, a) VALUES(1, 'aaaa');
INSERT INTO t1(rowid, a) VALUES(2, 'bbbb');
INSERT INTO t1(rowid, a) VALUES(3, 'cccc');
COMMIT;
}
db close
do_test 2.1 {
set hex [hexio_read test.db 0 [file size test.db]]
set off [string first "010463636363" $hex]
set hex [string replace $hex $off [expr $off+11] 017F63636363]
hexio_write test.db 0 $hex
set {} {}
} {}
sqlite3 db test.db
do_catchsql_test 2.2 {
SELECT rowid FROM t1('cccccccccccccccccccccccccccccccccccccccccccccccc');
} {1 {fts5: corruption on page 1, segment 1, table "t1"}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
INSERT INTO t1 VALUES(
'hello',
'alpha bravo charlie delta echo foxtrot golf hotel india juliet kilo lima mike november oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu',
'ant bear cat dog elephant fox gorilla hippo iguana jaguar kangaroo lion monkey newt octopus panda quail rabbit snake turtle unicorn vulture walrus xerus yak zebra'
);
UPDATE t1_data SET block = unhex(
-- Preserve bytes 0-168: header through hello's nSz field
hex(substr(block, 1, 169))
-- Inject 448 bytes of 0xFF: corrupted poslist + subsequent term data
|| replace(hex(zeroblob(448)), '00', 'FF')
-- Preserve 16 bytes of page index needed for hello lookup
|| hex(substr(block, 618, 16))
-- Corrupt remaining 37 footer bytes (not needed for hello lookup)
|| replace(hex(zeroblob(37)), '00', 'FF')
)
WHERE id = 137438953473;
}
do_test 3.1 {
execsql { SELECT * FROM t1 WHERE t1 MATCH '{a b}: hello' }
set {} {}
} {}
sqlite3_fts5_may_be_corrupt 0
finish_test
+10
View File
@@ -371,4 +371,14 @@ do_execsql_test 10.10 {
a 2 2 b 2 2 c 2 2 d 1 1 e 1 1 f 1 1
}
# Bug report 2026-05-18T05:19:01Z
#
set manyporters {porter Porter}
for {set i 0} {$i<18} {incr i} {
set manyporters "$manyporters $manyporters"
}
do_execsql_test 11.1 "
CREATE VIRTUAL TABLE t11 USING fts5(a,b,tokenize=\"$manyporters\");
" {}
finish_test
+4 -4
View File
@@ -362,7 +362,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
const UChar *zInput; /* Pointer to input string */
UChar *zOutput = 0; /* Pointer to output buffer */
int nInput; /* Size of utf-16 input string in bytes */
int nOut; /* Size of output buffer in bytes */
sqlite3_int64 nOut; /* Size of output buffer in bytes */
int cnt;
int bToUpper; /* True for toupper(), false for tolower() */
UErrorCode status;
@@ -385,7 +385,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
}
for(cnt=0; cnt<2; cnt++){
UChar *zNew = sqlite3_realloc(zOutput, nOut);
UChar *zNew = sqlite3_realloc64(zOutput, nOut);
if( zNew==0 ){
sqlite3_free(zOutput);
sqlite3_result_error_nomem(p);
@@ -394,9 +394,9 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
zOutput = zNew;
status = U_ZERO_ERROR;
if( bToUpper ){
nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
nOut = 2LL*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
}else{
nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
nOut = 2LL*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
}
if( U_SUCCESS(status) ){
+8
View File
@@ -60,6 +60,10 @@ static void compressFunc(
nIn = sqlite3_value_bytes(argv[0]);
nOut = 13 + nIn + (nIn+999)/1000;
pOut = sqlite3_malloc64( nOut+5 );
if( pOut==0 ){
sqlite3_result_error_nomem(context);
return;
}
for(i=4; i>=0; i--){
x[i] = (nIn >> (7*(4-i)))&0x7f;
}
@@ -99,6 +103,10 @@ static void uncompressFunc(
if( (pIn[i]&0x80)!=0 ){ i++; break; }
}
pOut = sqlite3_malloc64( nOut+1 );
if( pOut==0 ){
sqlite3_result_error_nomem(context);
return;
}
rc = uncompress(pOut, &nOut, &pIn[i], nIn-i);
if( rc==Z_OK ){
sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
+37 -37
View File
@@ -340,45 +340,45 @@ static void percentSort(double *a, unsigned int n){
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
int i; /* Loop counter */
double rPivot; /* The pivot value */
assert( n>=2 );
if( a[0]>a[n-1] ){
SWAP_DOUBLE(a[0],a[n-1])
}
if( n==2 ) return;
iGt = n-1;
i = n/2;
if( a[0]>a[i] ){
SWAP_DOUBLE(a[0],a[i])
}else if( a[i]>a[iGt] ){
SWAP_DOUBLE(a[i],a[iGt])
}
if( n==3 ) return;
rPivot = a[i];
iLt = i = 1;
do{
if( a[i]<rPivot ){
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
iLt++;
i++;
}else if( a[i]>rPivot ){
do{
iGt--;
}while( iGt>i && a[iGt]>rPivot );
SWAP_DOUBLE(a[i],a[iGt])
}else{
i++;
while( n>=2 ){
if( a[0]>a[n-1] ){
SWAP_DOUBLE(a[0],a[n-1])
}
if( n==2 ) return;
iGt = n-1;
i = n/2;
if( a[0]>a[i] ){
SWAP_DOUBLE(a[0],a[i])
}else if( a[i]>a[iGt] ){
SWAP_DOUBLE(a[i],a[iGt])
}
if( n==3 ) return;
rPivot = a[i];
iLt = i = 1;
do{
if( a[i]<rPivot ){
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
iLt++;
i++;
}else if( a[i]>rPivot ){
do{
iGt--;
}while( iGt>i && a[iGt]>rPivot );
SWAP_DOUBLE(a[i],a[iGt])
}else{
i++;
}
}while( i<iGt );
if( iLt>n/2 ){
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
n = iLt;
}else{
if( iLt>=2 ) percentSort(a, iLt);
a += iGt;
n -= iGt;
}
}while( i<iGt );
if( iLt>=2 ) percentSort(a, iLt);
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
/* Uncomment for testing */
#if 0
for(i=0; i<n-1; i++){
assert( a[i]<=a[i+1] );
}
#endif
}
+5 -1
View File
@@ -289,10 +289,14 @@ static void prefixLengthFunc(
int nL = sqlite3_value_bytes(apVal[0]);
int nR = sqlite3_value_bytes(apVal[1]);
int i;
if( zL==0 || zR==0 ){
sqlite3_result_int(ctx, 0);
return;
}
nByte = (nL > nR ? nL : nR);
for(i=0; i<nByte; i++){
if( zL[i]!=zR[i] ) break;
if( zL[i]==0 || zL[i]!=zR[i] ) break;
if( (zL[i] & 0xC0)!=0x80 ) nRet++;
}
-610
View File
@@ -1,610 +0,0 @@
/*
** 2016-05-05
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file implements a utility function (and a utility program) that
** makes a copy of an SQLite database while simultaneously zeroing out all
** deleted content.
**
** Normally (when PRAGMA secure_delete=OFF, which is the default) when SQLite
** deletes content, it does not overwrite the deleted content but rather marks
** the region of the file that held that content as being reusable. This can
** cause deleted content to recoverable from the database file. This stale
** content is removed by the VACUUM command, but VACUUM can be expensive for
** large databases. When in PRAGMA secure_delete=ON mode, the deleted content
** is zeroed, but secure_delete=ON has overhead as well.
**
** This utility attempts to make a copy of a complete SQLite database where
** all of the deleted content is zeroed out in the copy, and it attempts to
** do so while being faster than running VACUUM.
**
** Usage:
**
** int sqlite3_scrub_backup(
** const char *zSourceFile, // Source database filename
** const char *zDestFile, // Destination database filename
** char **pzErrMsg // Write error message here
** );
**
** Simply call the API above specifying the filename of the source database
** and the name of the backup copy. The source database must already exist
** and can be in active use. (A read lock is held during the backup.) The
** destination file should not previously exist. If the pzErrMsg parameter
** is non-NULL and if an error occurs, then an error message might be written
** into memory obtained from sqlite3_malloc() and *pzErrMsg made to point to
** that error message. But if the error is an OOM, the error might not be
** reported. The routine always returns non-zero if there is an error.
**
** If compiled with -DSCRUB_STANDALONE then a main() procedure is added and
** this file becomes a standalone program that can be run as follows:
**
** ./sqlite3scrub SOURCE DEST
*/
#include "sqlite3.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
typedef struct ScrubState ScrubState;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
/* State information for a scrub-and-backup operation */
struct ScrubState {
const char *zSrcFile; /* Name of the source file */
const char *zDestFile; /* Name of the destination file */
int rcErr; /* Error code */
char *zErr; /* Error message text */
sqlite3 *dbSrc; /* Source database connection */
sqlite3_file *pSrc; /* Source file handle */
sqlite3 *dbDest; /* Destination database connection */
sqlite3_file *pDest; /* Destination file handle */
u32 szPage; /* Page size */
u32 szUsable; /* Usable bytes on each page */
u32 nPage; /* Number of pages */
u32 iLastPage; /* Page number of last page written so far*/
u8 *page1; /* Content of page 1 */
};
/* Store an error message */
static void scrubBackupErr(ScrubState *p, const char *zFormat, ...){
va_list ap;
sqlite3_free(p->zErr);
va_start(ap, zFormat);
p->zErr = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( p->rcErr==0 ) p->rcErr = SQLITE_ERROR;
}
/* Allocate memory to hold a single page of content */
static u8 *scrubBackupAllocPage(ScrubState *p){
u8 *pPage;
if( p->rcErr ) return 0;
pPage = sqlite3_malloc64( p->szPage );
if( pPage==0 ) p->rcErr = SQLITE_NOMEM;
return pPage;
}
/* Read a page from the source database into memory. Use the memory
** provided by pBuf if not NULL or allocate a new page if pBuf==NULL.
*/
static u8 *scrubBackupRead(ScrubState *p, int pgno, u8 *pBuf){
int rc;
sqlite3_int64 iOff;
u8 *pOut = pBuf;
if( p->rcErr ) return 0;
if( pOut==0 ){
pOut = scrubBackupAllocPage(p);
if( pOut==0 ) return 0;
}
iOff = (pgno-1)*(sqlite3_int64)p->szPage;
rc = p->pSrc->pMethods->xRead(p->pSrc, pOut, p->szPage, iOff);
if( rc!=SQLITE_OK ){
if( pBuf==0 ) sqlite3_free(pOut);
pOut = 0;
scrubBackupErr(p, "read failed for page %d", pgno);
p->rcErr = SQLITE_IOERR;
}
return pOut;
}
/* Write a page to the destination database */
static void scrubBackupWrite(ScrubState *p, int pgno, const u8 *pData){
int rc;
sqlite3_int64 iOff;
if( p->rcErr ) return;
iOff = (pgno-1)*(sqlite3_int64)p->szPage;
rc = p->pDest->pMethods->xWrite(p->pDest, pData, p->szPage, iOff);
if( rc!=SQLITE_OK ){
scrubBackupErr(p, "write failed for page %d", pgno);
p->rcErr = SQLITE_IOERR;
}
if( (u32)pgno>p->iLastPage ) p->iLastPage = pgno;
}
/* Prepare a statement against the "db" database. */
static sqlite3_stmt *scrubBackupPrepare(
ScrubState *p, /* Backup context */
sqlite3 *db, /* Database to prepare against */
const char *zSql /* SQL statement */
){
sqlite3_stmt *pStmt;
if( p->rcErr ) return 0;
p->rcErr = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( p->rcErr ){
scrubBackupErr(p, "SQL error \"%s\" on \"%s\"",
sqlite3_errmsg(db), zSql);
sqlite3_finalize(pStmt);
return 0;
}
return pStmt;
}
/* Open the source database file */
static void scrubBackupOpenSrc(ScrubState *p){
sqlite3_stmt *pStmt;
int rc;
/* Open the source database file */
p->rcErr = sqlite3_open_v2(p->zSrcFile, &p->dbSrc,
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
if( p->rcErr ){
scrubBackupErr(p, "cannot open source database: %s",
sqlite3_errmsg(p->dbSrc));
return;
}
p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_schema; BEGIN;",
0, 0, 0);
if( p->rcErr ){
scrubBackupErr(p,
"cannot start a read transaction on the source database: %s",
sqlite3_errmsg(p->dbSrc));
return;
}
rc = sqlite3_wal_checkpoint_v2(p->dbSrc, "main", SQLITE_CHECKPOINT_FULL,
0, 0);
if( rc ){
scrubBackupErr(p, "cannot checkpoint the source database");
return;
}
pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_size");
if( pStmt==0 ) return;
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
p->szPage = sqlite3_column_int(pStmt, 0);
}else{
scrubBackupErr(p, "unable to determine the page size");
}
sqlite3_finalize(pStmt);
if( p->rcErr ) return;
pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_count");
if( pStmt==0 ) return;
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
p->nPage = sqlite3_column_int(pStmt, 0);
}else{
scrubBackupErr(p, "unable to determine the size of the source database");
}
sqlite3_finalize(pStmt);
sqlite3_file_control(p->dbSrc, "main", SQLITE_FCNTL_FILE_POINTER, &p->pSrc);
if( p->pSrc==0 || p->pSrc->pMethods==0 ){
scrubBackupErr(p, "cannot get the source file handle");
p->rcErr = SQLITE_ERROR;
}
}
/* Create and open the destination file */
static void scrubBackupOpenDest(ScrubState *p){
sqlite3_stmt *pStmt;
int rc;
char *zSql;
if( p->rcErr ) return;
p->rcErr = sqlite3_open_v2(p->zDestFile, &p->dbDest,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
if( p->rcErr ){
scrubBackupErr(p, "cannot open destination database: %s",
sqlite3_errmsg(p->dbDest));
return;
}
zSql = sqlite3_mprintf("PRAGMA page_size(%u);", p->szPage);
if( zSql==0 ){
p->rcErr = SQLITE_NOMEM;
return;
}
p->rcErr = sqlite3_exec(p->dbDest, zSql, 0, 0, 0);
sqlite3_free(zSql);
if( p->rcErr ){
scrubBackupErr(p,
"cannot set the page size on the destination database: %s",
sqlite3_errmsg(p->dbDest));
return;
}
sqlite3_exec(p->dbDest, "PRAGMA journal_mode=OFF;", 0, 0, 0);
p->rcErr = sqlite3_exec(p->dbDest, "BEGIN EXCLUSIVE;", 0, 0, 0);
if( p->rcErr ){
scrubBackupErr(p,
"cannot start a write transaction on the destination database: %s",
sqlite3_errmsg(p->dbDest));
return;
}
pStmt = scrubBackupPrepare(p, p->dbDest, "PRAGMA page_count;");
if( pStmt==0 ) return;
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ){
scrubBackupErr(p, "cannot measure the size of the destination");
}else if( sqlite3_column_int(pStmt, 0)>1 ){
scrubBackupErr(p, "destination database is not empty - holds %d pages",
sqlite3_column_int(pStmt, 0));
}
sqlite3_finalize(pStmt);
sqlite3_file_control(p->dbDest, "main", SQLITE_FCNTL_FILE_POINTER, &p->pDest);
if( p->pDest==0 || p->pDest->pMethods==0 ){
scrubBackupErr(p, "cannot get the destination file handle");
p->rcErr = SQLITE_ERROR;
}
}
/* Read a 32-bit big-endian integer */
static u32 scrubBackupInt32(const u8 *a){
u32 v = a[3];
v += ((u32)a[2])<<8;
v += ((u32)a[1])<<16;
v += ((u32)a[0])<<24;
return v;
}
/* Read a 16-bit big-endian integer */
static u32 scrubBackupInt16(const u8 *a){
return (a[0]<<8) + a[1];
}
/*
** Read a varint. Put the value in *pVal and return the number of bytes.
*/
static int scrubBackupVarint(const u8 *z, sqlite3_int64 *pVal){
sqlite3_int64 v = 0;
int i;
for(i=0; i<8; i++){
v = (v<<7) + (z[i]&0x7f);
if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
}
v = (v<<8) + (z[i]&0xff);
*pVal = v;
return 9;
}
/*
** Return the number of bytes in a varint.
*/
static int scrubBackupVarintSize(const u8 *z){
int i;
for(i=0; i<8; i++){
if( (z[i]&0x80)==0 ){ return i+1; }
}
return 9;
}
/*
** Copy the freelist trunk page given, and all its descendents,
** zeroing out as much as possible in the process.
*/
static void scrubBackupFreelist(ScrubState *p, int pgno, u32 nFree){
u8 *a, *aBuf;
u32 n, mx;
if( p->rcErr ) return;
aBuf = scrubBackupAllocPage(p);
if( aBuf==0 ) return;
while( pgno && nFree){
a = scrubBackupRead(p, pgno, aBuf);
if( a==0 ) break;
n = scrubBackupInt32(&a[4]);
mx = p->szUsable/4 - 2;
if( n<mx ){
memset(&a[n*4+8], 0, 4*(mx-n));
}
scrubBackupWrite(p, pgno, a);
pgno = scrubBackupInt32(a);
#if 0
/* There is really no point in copying the freelist leaf pages.
** Simply leave them uninitialized in the destination database. The
** OS filesystem should zero those pages for us automatically.
*/
for(i=0; i<n && nFree; i++){
u32 iLeaf = scrubBackupInt32(&a[i*4+8]);
if( aZero==0 ){
aZero = scrubBackupAllocPage(p);
if( aZero==0 ){ pgno = 0; break; }
memset(aZero, 0, p->szPage);
}
scrubBackupWrite(p, iLeaf, aZero);
nFree--;
}
#endif
}
sqlite3_free(aBuf);
}
/*
** Copy an overflow chain from source to destination. Zero out any
** unused tail at the end of the overflow chain.
*/
static void scrubBackupOverflow(ScrubState *p, int pgno, u32 nByte){
u8 *a, *aBuf;
aBuf = scrubBackupAllocPage(p);
if( aBuf==0 ) return;
while( nByte>0 && pgno!=0 ){
a = scrubBackupRead(p, pgno, aBuf);
if( a==0 ) break;
if( nByte >= (p->szUsable)-4 ){
nByte -= (p->szUsable) - 4;
}else{
u32 x = (p->szUsable - 4) - nByte;
u32 i = p->szUsable - x;
memset(&a[i], 0, x);
nByte = 0;
}
scrubBackupWrite(p, pgno, a);
pgno = scrubBackupInt32(a);
}
sqlite3_free(aBuf);
}
/*
** Copy B-Tree page pgno, and all of its children, from source to destination.
** Zero out deleted content during the copy.
*/
static void scrubBackupBtree(ScrubState *p, int pgno, int iDepth){
u8 *a;
u32 i, n, pc;
u32 nCell;
u32 nPrefix;
u32 szHdr;
u32 iChild;
u8 *aTop;
u8 *aCell;
u32 x, y;
int ln = 0;
if( p->rcErr ) return;
if( iDepth>50 ){
scrubBackupErr(p, "corrupt: b-tree too deep at page %d", pgno);
return;
}
if( pgno==1 ){
a = p->page1;
}else{
a = scrubBackupRead(p, pgno, 0);
if( a==0 ) return;
}
nPrefix = pgno==1 ? 100 : 0;
aTop = &a[nPrefix];
szHdr = 8 + 4*(aTop[0]==0x02 || aTop[0]==0x05);
aCell = aTop + szHdr;
nCell = scrubBackupInt16(&aTop[3]);
/* Zero out the gap between the cell index and the start of the
** cell content area */
x = scrubBackupInt16(&aTop[5]); /* First byte of cell content area */
if( x>p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
y = szHdr + nPrefix + nCell*2;
if( y>x ){ ln=__LINE__; goto btree_corrupt; }
if( y<x ) memset(a+y, 0, x-y); /* Zero the gap */
/* Zero out all the free blocks */
pc = scrubBackupInt16(&aTop[1]);
if( pc>0 && pc<x ){ ln=__LINE__; goto btree_corrupt; }
while( pc ){
if( pc>(p->szUsable)-4 ){ ln=__LINE__; goto btree_corrupt; }
n = scrubBackupInt16(&a[pc+2]);
if( pc+n>(p->szUsable) ){ ln=__LINE__; goto btree_corrupt; }
if( n>4 ) memset(&a[pc+4], 0, n-4);
x = scrubBackupInt16(&a[pc]);
if( x<pc+4 && x>0 ){ ln=__LINE__; goto btree_corrupt; }
pc = x;
}
/* Write this one page */
scrubBackupWrite(p, pgno, a);
/* Walk the tree and process child pages */
for(i=0; i<nCell; i++){
u32 X, M, K, nLocal;
sqlite3_int64 P;
pc = scrubBackupInt16(&aCell[i*2]);
if( pc <= szHdr ){ ln=__LINE__; goto btree_corrupt; }
if( pc > p->szUsable-3 ){ ln=__LINE__; goto btree_corrupt; }
if( aTop[0]==0x05 || aTop[0]==0x02 ){
if( pc+4 > p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
iChild = scrubBackupInt32(&a[pc]);
pc += 4;
scrubBackupBtree(p, iChild, iDepth+1);
if( aTop[0]==0x05 ) continue;
}
pc += scrubBackupVarint(&a[pc], &P);
if( pc >= p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
if( aTop[0]==0x0d ){
X = p->szUsable - 35;
}else{
X = ((p->szUsable - 12)*64/255) - 23;
}
if( P<=X ){
/* All content is local. No overflow */
continue;
}
M = ((p->szUsable - 12)*32/255)-23;
K = M + ((P-M)%(p->szUsable-4));
if( aTop[0]==0x0d ){
pc += scrubBackupVarintSize(&a[pc]);
if( pc > (p->szUsable-4) ){ ln=__LINE__; goto btree_corrupt; }
}
nLocal = K<=X ? K : M;
if( pc+nLocal > p->szUsable-4 ){ ln=__LINE__; goto btree_corrupt; }
iChild = scrubBackupInt32(&a[pc+nLocal]);
scrubBackupOverflow(p, iChild, (u32)(P-nLocal));
}
/* Walk the right-most tree */
if( aTop[0]==0x05 || aTop[0]==0x02 ){
iChild = scrubBackupInt32(&aTop[8]);
scrubBackupBtree(p, iChild, iDepth+1);
}
/* All done */
if( pgno>1 ) sqlite3_free(a);
return;
btree_corrupt:
scrubBackupErr(p, "corruption on page %d of source database (errid=%d)",
pgno, ln);
if( pgno>1 ) sqlite3_free(a);
}
/*
** Copy all ptrmap pages from source to destination.
** This routine is only called if the source database is in autovacuum
** or incremental vacuum mode.
*/
static void scrubBackupPtrmap(ScrubState *p){
u32 pgno = 2;
u32 J = p->szUsable/5;
u32 iLock = (1073742335/p->szPage)+1;
u8 *a, *pBuf;
if( p->rcErr ) return;
pBuf = scrubBackupAllocPage(p);
if( pBuf==0 ) return;
while( pgno<=p->nPage ){
a = scrubBackupRead(p, pgno, pBuf);
if( a==0 ) break;
scrubBackupWrite(p, pgno, a);
pgno += J+1;
if( pgno==iLock ) pgno++;
}
sqlite3_free(pBuf);
}
int sqlite3_scrub_backup(
const char *zSrcFile, /* Source file */
const char *zDestFile, /* Destination file */
char **pzErr /* Write error here if non-NULL */
){
ScrubState s;
u32 n, i;
sqlite3_stmt *pStmt;
memset(&s, 0, sizeof(s));
s.zSrcFile = zSrcFile;
s.zDestFile = zDestFile;
/* Open both source and destination databases */
scrubBackupOpenSrc(&s);
scrubBackupOpenDest(&s);
/* Read in page 1 */
s.page1 = scrubBackupRead(&s, 1, 0);
if( s.page1==0 ) goto scrub_abort;
s.szUsable = s.szPage - s.page1[20];
/* Copy the freelist */
n = scrubBackupInt32(&s.page1[36]);
i = scrubBackupInt32(&s.page1[32]);
if( n ) scrubBackupFreelist(&s, i, n);
/* Copy ptrmap pages */
n = scrubBackupInt32(&s.page1[52]);
if( n ) scrubBackupPtrmap(&s);
/* Copy all of the btrees */
scrubBackupBtree(&s, 1, 0);
pStmt = scrubBackupPrepare(&s, s.dbSrc,
"SELECT rootpage FROM sqlite_schema WHERE coalesce(rootpage,0)>0");
if( pStmt==0 ) goto scrub_abort;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
i = (u32)sqlite3_column_int(pStmt, 0);
scrubBackupBtree(&s, i, 0);
}
sqlite3_finalize(pStmt);
/* If the last page of the input db file is a free-list leaf, then the
** backup file on disk is still smaller than the size indicated within
** the database header. In this case, write a page of zeroes to the
** last page of the backup database so that SQLite does not mistakenly
** think the db is corrupt. */
if( s.iLastPage<s.nPage ){
u8 *aZero = scrubBackupAllocPage(&s);
if( aZero ){
memset(aZero, 0, s.szPage);
scrubBackupWrite(&s, s.nPage, aZero);
sqlite3_free(aZero);
}
}
scrub_abort:
/* Close the destination database without closing the transaction. If we
** commit, page zero will be overwritten. */
sqlite3_close(s.dbDest);
/* But do close out the read-transaction on the source database */
sqlite3_exec(s.dbSrc, "COMMIT;", 0, 0, 0);
sqlite3_close(s.dbSrc);
sqlite3_free(s.page1);
if( pzErr ){
*pzErr = s.zErr;
}else{
sqlite3_free(s.zErr);
}
return s.rcErr;
}
#ifdef SCRUB_STANDALONE
/* Error and warning log */
static void errorLogCallback(void *pNotUsed, int iErr, const char *zMsg){
const char *zType;
switch( iErr&0xff ){
case SQLITE_WARNING: zType = "WARNING"; break;
case SQLITE_NOTICE: zType = "NOTICE"; break;
default: zType = "ERROR"; break;
}
fprintf(stderr, "%s: %s\n", zType, zMsg);
}
/* The main() routine when this utility is run as a stand-alone program */
int main(int argc, char **argv){
char *zErr = 0;
int rc;
if( argc!=3 ){
fprintf(stderr,"Usage: %s SOURCE DESTINATION\n", argv[0]);
exit(1);
}
sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, 0);
rc = sqlite3_scrub_backup(argv[1], argv[2], &zErr);
if( rc==SQLITE_NOMEM ){
fprintf(stderr, "%s: out of memory\n", argv[0]);
exit(1);
}
if( zErr ){
fprintf(stderr, "%s: %s\n", argv[0], zErr);
sqlite3_free(zErr);
exit(1);
}
return 0;
}
#endif
+2 -2
View File
@@ -536,7 +536,7 @@ static int seriesFilter(
if( r<(double)SMALLEST_INT64 ){
iMin = SMALLEST_INT64;
}else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
iMin = (sqlite3_int64)seriesCeil(r+1.0);
iMin = (sqlite3_int64)seriesCeil(r)+1;
}else{
iMin = (sqlite3_int64)seriesCeil(r);
}
@@ -557,7 +557,7 @@ static int seriesFilter(
if( r>(double)LARGEST_INT64 ){
iMax = LARGEST_INT64;
}else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
iMax = (sqlite3_int64)(r-1.0);
iMax = ((sqlite3_int64)r)-1;
}else{
iMax = (sqlite3_int64)seriesFloor(r);
}
+21 -11
View File
@@ -32,6 +32,7 @@ SQLITE_EXTENSION_INIT1
# define NEVER(X) 0
typedef unsigned char u8;
typedef unsigned short u16;
typedef sqlite3_int64 i64;
#endif
#include <ctype.h>
@@ -192,7 +193,7 @@ static const unsigned char className[] = ".ABCDHLRMY9 ?";
** Return NULL if memory allocation fails.
*/
static unsigned char *phoneticHash(const unsigned char *zIn, int nIn){
unsigned char *zOut = sqlite3_malloc64( nIn + 1 );
unsigned char *zOut = sqlite3_malloc64( (i64)nIn + 1 );
int i;
int nOut = 0;
char cPrev = 0x77;
@@ -352,6 +353,7 @@ static int substituteCost(char cPrev, char cFrom, char cTo){
** -1 One of the inputs is NULL
** -2 Non-ASCII characters on input
** -3 Unable to allocate memory
** -4 Inputs too large
**
** If pnMatch is not NULL, then *pnMatch is set to the number of bytes
** of zB that matched the pattern in zA. If zA does not end with a '*',
@@ -390,9 +392,11 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
for(nA=0; zA[nA]; nA++){
if( zA[nA]&0x80 ) return -2;
}
if( nA>=100000 ) return -4;
for(nB=0; zB[nB]; nB++){
if( zB[nB]&0x80 ) return -2;
}
if( nB>=100000 ) return -4;
/* Special processing if either string is empty */
if( nA==0 ){
@@ -419,7 +423,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
if( nB<(sizeof(mStack)*4)/(sizeof(mStack[0])*5) ){
m = mStack;
}else{
m = toFree = sqlite3_malloc64( (nB+1)*5*sizeof(m[0])/4 );
m = toFree = sqlite3_malloc64( ((i64)nB+1)*5LL*sizeof(m[0])/4 );
if( m==0 ) return -3;
}
cx = (char*)&m[nB+1];
@@ -527,6 +531,8 @@ static void editdistSqlFunc(
if( res<0 ){
if( res==(-3) ){
sqlite3_result_error_nomem(context);
}else if( res==(-4) ){
sqlite3_result_error_toobig(context);
}else if( res==(-2) ){
sqlite3_result_error(context, "non-ASCII input to editdist()", -1);
}else{
@@ -767,7 +773,7 @@ static int editDist3ConfigLoad(
if( iCost>=10000 ) continue; /* Costs above 10K are considered infinite */
if( pLang==0 || iLang!=iLangPrev ){
EditDist3Lang *pNew;
pNew = sqlite3_realloc64(p->a, (p->nLang+1)*sizeof(p->a[0]));
pNew = sqlite3_realloc64(p->a, ((i64)p->nLang+1)*sizeof(p->a[0]));
if( pNew==0 ){ rc = SQLITE_NOMEM; break; }
p->a = pNew;
pLang = &p->a[p->nLang];
@@ -901,7 +907,7 @@ static EditDist3FromString *editDist3FromStringNew(
if( z==0 ) return 0;
if( n<0 ) n = (int)strlen(z);
pStr = sqlite3_malloc64( sizeof(*pStr) + sizeof(pStr->a[0])*n + n + 1 );
pStr = sqlite3_malloc64( sizeof(*pStr) + sizeof(pStr->a[0])*n + (i64)n + 1 );
if( pStr==0 ) return 0;
pStr->a = (EditDist3From*)&pStr[1];
memset(pStr->a, 0, sizeof(pStr->a[0])*n);
@@ -927,13 +933,13 @@ static EditDist3FromString *editDist3FromStringNew(
if( matchFrom(p, z+i, n-i)==0 ) continue;
if( p->nTo==0 ){
apNew = sqlite3_realloc64(pFrom->apDel,
sizeof(*apNew)*(pFrom->nDel+1));
sizeof(*apNew)*((i64)pFrom->nDel+1));
if( apNew==0 ) break;
pFrom->apDel = apNew;
apNew[pFrom->nDel++] = p;
}else{
apNew = sqlite3_realloc64(pFrom->apSubst,
sizeof(*apNew)*(pFrom->nSubst+1));
sizeof(*apNew)*((i64)pFrom->nSubst+1));
if( apNew==0 ) break;
pFrom->apSubst = apNew;
apNew[pFrom->nSubst++] = p;
@@ -1008,6 +1014,8 @@ static int editDist3Core(
unsigned int stackSpace[SQLITE_SPELLFIX_STACKALLOC_SZ/sizeof(unsigned int)];
/* allocate the Wagner matrix and the aTo[] array for the TO string */
if( n2>10000 ) return -2;
if( f.n>10000 ) return -2;
n = (f.n+1)*(n2+1);
n = (n+1)&~1;
nByte = n*sizeof(m[0]) + sizeof(a2[0])*n2;
@@ -1198,6 +1206,8 @@ static void editDist3SqlFunc(
editDist3FromStringDelete(pFrom);
if( dist==(-1) ){
sqlite3_result_error_nomem(context);
}else if( dist==(-2) ){
sqlite3_result_error_toobig(context);
}else{
sqlite3_result_int(context, dist);
}
@@ -1712,9 +1722,9 @@ static const Transliteration *spellfixFindTranslit(int c, int *pxTop){
*/
static unsigned char *transliterate(const unsigned char *zIn, int nIn){
#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
unsigned char *zOut = sqlite3_malloc64( nIn*5 + 1 );
unsigned char *zOut = sqlite3_malloc64( (i64)nIn*5 + 1 );
#else
unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 );
unsigned char *zOut = sqlite3_malloc64( (i64)nIn*4 + 1 );
#endif
int c, sz, nOut;
if( zOut==0 ) return 0;
@@ -2057,7 +2067,7 @@ static int spellfix1Init(
int i;
nDbName = (int)strlen(zDbName);
pNew = sqlite3_malloc64( sizeof(*pNew) + nDbName + 1);
pNew = sqlite3_malloc64( sizeof(*pNew) + (i64)nDbName + 1);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -2461,7 +2471,7 @@ static void spellfix1RunQuery(MatchQuery *p, const char *zQuery, int nQuery){
iDist = editdist1(p->zPattern, zK1, 0);
}
if( iDist<0 ){
p->rc = SQLITE_NOMEM;
p->rc = iDist==(-4) ? SQLITE_TOOBIG : SQLITE_NOMEM;
break;
}
pCur->nSearch++;
@@ -2773,7 +2783,7 @@ static int spellfix1Column(
if( !zTranslit ) return SQLITE_NOMEM;
res = editdist1(pCur->zPattern, zTranslit, &iMatchlen);
sqlite3_free(zTranslit);
if( res<0 ) return SQLITE_NOMEM;
if( res<0 ) return res==(-4) ? SQLITE_TOOBIG : SQLITE_NOMEM;
iMatchlen = translen_to_charlen(zWord, nWord, iMatchlen);
}else{
iMatchlen = utf8Charlen(zWord, nWord);
+11 -4
View File
@@ -488,6 +488,7 @@ static void zipfileResetCursor(ZipfileCsr *pCsr){
pNext = p->pNext;
zipfileEntryFree(p);
}
pCsr->pFreeEntry = 0;
}
/*
@@ -890,7 +891,13 @@ static int zipfileGetEntry(
if( rc==SQLITE_OK ){
u32 *pt = &pNew->mUnixTime;
pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
/* aRead[0..nFile-1] might contain embedded \000 characters
** See Bug 2026-05-31T11:43:05Z */
pNew->cds.zFile = sqlite3_malloc64(nFile+1);
if( pNew->cds.zFile!=0 ){
memcpy(pNew->cds.zFile, aRead, nFile);
pNew->cds.zFile[nFile] = 0;
}
pNew->aExtra = (u8*)&pNew[1];
memcpy(pNew->aExtra, &aRead[nFile], nExtra);
if( pNew->cds.zFile==0 ){
@@ -1994,10 +2001,10 @@ struct ZipfileCtx {
};
static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
if( pBuf->n+nByte>pBuf->nAlloc ){
if( (pBuf->nAlloc-pBuf->n)<nByte ){
u8 *aNew;
sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
int nReq = pBuf->n + nByte;
i64 nNew = pBuf->n ? (i64)pBuf->n*2 : 512;
i64 nReq = pBuf->n + nByte;
while( nNew<nReq ) nNew = nNew*2;
aNew = sqlite3_realloc64(pBuf->a, nNew);
+2 -2
View File
@@ -911,7 +911,7 @@ static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){
sqlite3_str_append(pOut, (const char*)z, i);
}
switch( z[i] ){
case '>': sqlite3_str_append(pOut, "&lt;", 4); break;
case '>': sqlite3_str_append(pOut, "&gt;", 4); break;
case '&': sqlite3_str_append(pOut, "&amp;", 5); break;
case '<': sqlite3_str_append(pOut, "&lt;", 4); break;
case '"': sqlite3_str_append(pOut, "&quot;", 6); break;
@@ -1391,7 +1391,7 @@ static void qrfWrapLine(
for(k=i-1; k>=i/2; k--){
if( qrfSpace(z[k]) ) break;
}
if( k<i/2 ){
if( k<i/2 && i/2>0 ){
for(k=i; k>=i/2; k--){
if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
}
+40 -16
View File
@@ -532,18 +532,39 @@ static void recoverFinalize(sqlite3_recover *p, sqlite3_stmt *pStmt){
}
}
/*
** Run a single SQL statement in zSql. If zSql contains two or more
** SQL statements separated by ';', only the first is run.
**
** Return the sqlite3_finalizer() or sqlite3_prepare() result code
** from running the zSql statement.
*/
static int recoverOneStmt(sqlite3 *db, const char *zSql){
sqlite3_stmt *pStmt = 0;
int rc;
if( zSql==0 ) return SQLITE_OK;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ){
sqlite3_finalize(pStmt);
return rc;
}
while( SQLITE_ROW==sqlite3_step(pStmt) ){}
return sqlite3_finalize(pStmt);
}
/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). A copy of p->errCode is returned in this
** case.
**
** Otherwise, execute SQL script zSql. If successful, return SQLITE_OK.
** Or, if an error occurs, leave an error code and message in the recover
** handle and return a copy of the error code.
** Otherwise, execute a single SQL statment in zSql. Even if zSql contains
** two or more SQL statements separated by ';', only execute the first one.
** If successful, return SQLITE_OK. Or, if an error occurs, leave an error
** code and message in the recover handle and return a copy of the error code.
*/
static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
if( p->errCode==SQLITE_OK ){
int rc = sqlite3_exec(db, zSql, 0, 0, 0);
int rc = recoverOneStmt(db, zSql);
if( rc ){
recoverDbError(p, db);
}
@@ -943,7 +964,8 @@ static void recoverTransferSettings(sqlite3_recover *p){
}
recoverFinalize(p, p1);
}
recoverExec(p, db2, "CREATE TABLE t1(a); DROP TABLE t1;");
recoverExec(p, db2, "CREATE TABLE t1(a)");
recoverExec(p, db2, "DROP TABLE t1");
if( p->errCode==SQLITE_OK ){
sqlite3 *db = p->dbOut;
@@ -1025,12 +1047,12 @@ static int recoverOpenOutput(sqlite3_recover *p){
static void recoverOpenRecovery(sqlite3_recover *p){
char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
recoverExec(p, p->dbOut, zSql);
recoverExec(p, p->dbOut,
"PRAGMA writable_schema = 1;"
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT);"
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
);
sqlite3_free(zSql);
recoverExec(p, p->dbOut, "PRAGMA writable_schema = 1");
recoverExec(p, p->dbOut,
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT)");
recoverExec(p, p->dbOut,
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql)");
}
@@ -1170,7 +1192,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
")"
"SELECT rootpage, tbl, isVirtual, name, sql"
" FROM dbschema "
" WHERE tbl OR isIndex"
" WHERE (tbl OR isIndex) AND sql GLOB 'CREATE *'"
" ORDER BY tbl DESC, name=='sqlite_sequence' DESC"
);
@@ -1196,7 +1218,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
zName, zName, zSql
));
}
rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
rc = recoverOneStmt(p->dbOut, zSql);
if( rc==SQLITE_OK ){
recoverSqlCallback(p, zSql);
if( bTable && !bVirtual ){
@@ -1238,15 +1260,17 @@ static int recoverWriteSchema2(sqlite3_recover *p){
p->bSlowIndexes ?
"SELECT rootpage, sql FROM recovery.schema "
" WHERE type!='table' AND type!='index'"
" AND sql GLOB 'CREATE *'"
:
"SELECT rootpage, sql FROM recovery.schema "
" WHERE type!='table' AND (type!='index' OR sql NOT LIKE '%unique%')"
" AND sql GLOB 'CREATE *'"
);
if( pSelect ){
while( sqlite3_step(pSelect)==SQLITE_ROW ){
const char *zSql = (const char*)sqlite3_column_text(pSelect, 1);
int rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
int rc = recoverOneStmt(p->dbOut, zSql);
if( rc==SQLITE_OK ){
recoverSqlCallback(p, zSql);
}else if( rc!=SQLITE_ERROR ){
@@ -2624,7 +2648,7 @@ static void recoverStep(sqlite3_recover *p){
if( bUseWrapper ) recoverUninstallWrapper(p);
}while( p->errCode==SQLITE_NOTADB
&& (bUseWrapper--)
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
&& SQLITE_OK==recoverOneStmt(p->dbIn, "ROLLBACK")
);
}
@@ -2689,7 +2713,7 @@ static void recoverStep(sqlite3_recover *p){
** database. Regardless of whether or not an error has occurred, make
** an attempt to end the read transaction on the input database. */
recoverExec(p, p->dbOut, "COMMIT");
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
rc = recoverOneStmt(p->dbIn, "END");
if( p->errCode==SQLITE_OK ) p->errCode = rc;
recoverSqlCallback(p, "PRAGMA writable_schema = off");
@@ -2885,7 +2909,7 @@ int sqlite3_recover_finish(sqlite3_recover *p){
}else{
recoverFinalCleanup(p);
if( p->bCloseTransaction && sqlite3_get_autocommit(p->dbIn)==0 ){
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
rc = recoverOneStmt(p->dbIn, "END");
if( p->errCode==SQLITE_OK ) p->errCode = rc;
}
rc = p->errCode;
+5
View File
@@ -1251,6 +1251,11 @@ static int geopolyInit(
int ii;
(void)pAux;
if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
*pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
return SQLITE_ERROR;
}
sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
+7 -4
View File
@@ -166,7 +166,7 @@ struct Rtree {
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
u8 nBytesPerCell; /* Bytes consumed per cell */
u8 inWrTrans; /* True if inside write transaction */
u8 nAux; /* # of auxiliary columns in %_rowid */
u16 nAux; /* # of auxiliary columns in %_rowid */
#ifdef SQLITE_ENABLE_GEOPOLY
u8 nAuxNotNull; /* Number of initial not-null aux columns */
#endif
@@ -1402,7 +1402,7 @@ static int nodeRowidIndex(
){
int ii;
int nCell = NCELL(pNode);
assert( nCell<200 );
assert( nCell<65536 && nCell>=0 );
for(ii=0; ii<nCell; ii++){
if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
*piIndex = ii;
@@ -1664,7 +1664,10 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
if( rc ) return rc;
nCell = NCELL(pNode);
assert( nCell<200 );
if( nCell>RTREE_MAXCELLS ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
while( p->iCell<nCell ){
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
@@ -3641,7 +3644,7 @@ static int rtreeInit(
"Auxiliary rtree columns must be last" /* 4 */
};
assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
assert( RTREE_MAX_AUX_COLUMN<256 );
if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
return SQLITE_ERROR;
+29
View File
@@ -18,6 +18,7 @@ if {![info exists testdir]} {
}
source $testdir/tester.tcl
ifcapable !rtree { finish_test ; return }
set testprefix rtreeA
proc create_t1 {} {
db close
@@ -258,5 +259,33 @@ do_test rtreeA-7.120 {
sqlite3_extended_errcode db
} {SQLITE_CORRUPT_VTAB}
#-------------------------------------------------------------------------
reset_db
set N 300
set rec [binary format SS 0 $N]
for {set ii 1} {$ii<=$N} {incr ii} {
set cell [binary format Wff $ii $ii [expr $ii+1]]
set rec [binary format a*a* $rec $cell]
}
do_execsql_test 8.1 {
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
INSERT INTO rt VALUES(1, 0.0, 1.0);
UPDATE rt_node SET data = $rec WHERE nodeno = 1;
DELETE FROM rt_rowid;
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300
)
INSERT INTO rt_rowid SELECT i, 1 FROM s;
DELETE FROM rt_parent;
}
db close
sqlite3 db test.db
do_execsql_test 8.2 {
SELECT count(*) FROM rt WHERE id = 1
} {1}
finish_test
+42
View File
@@ -324,5 +324,47 @@ do_test 6.3.2 { sqlite3_errcode db2 } {SQLITE_ERROR}
do_test 6.4 {
catchsql { INSERT INTO c1 VALUES(100, 200) } db2
} {1 {no such table: main.p1}}
db2 close
#-------------------------------------------------------------------------
reset_db
do_execsql_test 7.0 {
PRAGMA trusted_schema=OFF;
PRAGMA foreign_keys=ON;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
CREATE TABLE t2(e TEXT PRIMARY KEY NOT NULL, f, g);
CREATE TABLE t3(w REAL PRIMARY KEY NOT NULL, x, y);
CREATE TABLE t4(z PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE tc(a INTEGER, b INTEGER, c BLOB, d TEXT, PRIMARY KEY(a,b));
CREATE TABLE wr(a TEXT, b INT, c, PRIMARY KEY(a,b)) WITHOUT ROWID;
CREATE TABLE child(x INTEGER PRIMARY KEY, y INTEGER REFERENCES t1(a) ON DELETE CASCADE, z TEXT);
INSERT INTO t1 VALUES(1,2,3,4),(2,3.5,'four',x'556677'),(3,NULL,'xyz',15),(4,'bubba',2147483648,0.0);
INSERT INTO t1 SELECT a+4,c,d,b FROM t1;
INSERT INTO t2 VALUES('x1y',2,3),('x2y','four',x'556677'),('x3y',NULL,'xyz');
INSERT INTO t3 VALUES(1.1,'a','b'),(2.2,x'00ff','c');
INSERT INTO t4 VALUES('alpha'),('beta'),('gamma');
INSERT INTO tc VALUES(1,1,x'0102','one'),(1,2,x'0304','two'),(2,1,x'0506','three');
INSERT INTO wr VALUES('a',1,'wa'),('b',2,'wb');
INSERT INTO child VALUES(1,1,'c1'),(2,2,'c2');
}
set C [db one "SELECT unhex('
54 0401 0200 0074 6300 1700 0100 0000
0000 0000 0101 0000 0000 0069 0001 0402
0102 0303 6f6e 6500 0004 2008 40a1 4c0b
0d3f 3730 5d92 3f18 f2c9 66a6 4220 a873
04cc 5281 ce5c d9d4 dc8b 7003 056f 6e65
2d75 1700 0100 0002 5004 0100 0000 6d69
7800 1700 0302 6b31 0409 1100
', ' \n')"]
proc conflict_handler {args} {
return "OMIT"
}
do_test 7.1 {
list [catch {sqlite3changeset_apply_v2 db $::C conflict_handler} msg] $msg
} {1 SQLITE_CORRUPT}
finish_test
+13 -1
View File
@@ -259,6 +259,18 @@ foreach {tn type C2hex C3hex} {
} {1 SQLITE_CORRUPT}
}
#-------------------------------------------------------------------------
#
reset_db
set CSD 5402010074000900010000000000000001030441414141
set CSI 5402010074001200010000000000000001063258585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858
do_test 7.0 {
sqlite3changegroup grp
grp add [db one {SELECT unhex($CSD)}]
list [catch { grp add [db one {SELECT unhex($CSI)}] } msg] $msg
} {1 SQLITE_CORRUPT}
grp delete
finish_test
+4 -1
View File
@@ -82,6 +82,9 @@ do_test 2.2.1 {
# It is not possible to apply the changeset generated by the following
# SQL, as none of the three updated rows may be updated as part of the
# first pass.
#
# UPDATE 19/05/2026 - it is now possible to apply such an update.
#
do_then_apply_sql -ignorenoop {
UPDATE t1 SET b=0 WHERE a=1;
UPDATE t1 SET b=1 WHERE a=2;
@@ -89,7 +92,7 @@ do_test 2.2.1 {
UPDATE t1 SET b=3 WHERE a=1;
}
db2 eval { SELECT a, b FROM t1 }
} {1 1 2 2 3 3}
} {1 3 2 1 3 2}
do_test 2.2.2 { db eval { SELECT a, b FROM t1 } } {1 3 2 1 3 2}
#-------------------------------------------------------------------------
+298
View File
@@ -0,0 +1,298 @@
# 2026 May 18
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionconflict2
forcedelete test.db2
sqlite3 db2 test.db2
do_test 1.0 {
do_common_sql {
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
INSERT INTO t1 VALUES(1, 1, 1);
INSERT INTO t1 VALUES(2, 2, 2);
INSERT INTO t1 VALUES(3, 3, 3);
}
} {}
do_test 1.1 {
do_then_apply_sql {
UPDATE t1 SET c=NULL WHERE a=1;
UPDATE t1 SET c=1 WHERE a=3;
UPDATE t1 SET c=3 WHERE a=1;
}
} {}
do_execsql_test -db db 1.2 {
SELECT rowid, * FROM t1
} {
1 1 1 3
2 2 2 2
3 3 3 1
}
do_execsql_test -db db2 1.3 {
SELECT rowid, * FROM t1
} {
1 1 1 3
2 2 2 2
3 3 3 1
}
#--------------------------------------------------------------------------
reset_db
db2 close
forcedelete test.db2
sqlite3 db2 test.db2
do_test 2.0 {
do_common_sql {
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE) WITHOUT ROWID;
INSERT INTO t1 VALUES(1, 1, 1);
INSERT INTO t1 VALUES(2, 2, 2);
INSERT INTO t1 VALUES(3, 3, 3);
}
} {}
do_test 2.1 {
do_then_apply_sql {
UPDATE t1 SET c=NULL WHERE a=1;
UPDATE t1 SET c=1 WHERE a=3;
UPDATE t1 SET c=3 WHERE a=1;
}
} {}
do_execsql_test -db db 2.2 {
SELECT * FROM t1
} {
1 1 3
2 2 2
3 3 1
}
do_execsql_test -db db2 2.3 {
SELECT * FROM t1
} {
1 1 3
2 2 2
3 3 1
}
#--------------------------------------------------------------------------
reset_db
db2 close
forcedelete test.db2
sqlite3 db2 test.db2
do_test 3.0 {
do_common_sql {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE);
INSERT INTO t1 VALUES(1, 1, 1);
INSERT INTO t1 VALUES(2, 2, 2);
INSERT INTO t1 VALUES(3, 3, 3);
}
} {}
do_test 3.1 {
do_then_apply_sql {
UPDATE t1 SET c=NULL WHERE a=1;
UPDATE t1 SET c=1 WHERE a=3;
UPDATE t1 SET c=3 WHERE a=1;
}
} {}
do_execsql_test -db db 3.2 {
SELECT rowid, * FROM t1
} {
1 1 1 3
2 2 2 2
3 3 3 1
}
do_execsql_test -db db2 3.3 {
SELECT rowid, * FROM t1
} {
1 1 1 3
2 2 2 2
3 3 3 1
}
#-------------------------------------------------------------------------
db2 close
reset_db
forcedelete test.db2
sqlite3 db2 test.db2
set ::conflict_list [list]
proc xConflict {args} {
lappend ::conflict_list $args
return "OMIT"
}
proc do_conflict_test {tn bNoUpdateLoop script clist} {
uplevel [list do_test $tn.1 [subst -nocommands {
sqlite3session S db "main"
S attach *
eval {$script}
set ::changeset [S changeset]
S delete
}] {}]
if {$bNoUpdateLoop} {
uplevel [list do_test $tn.2.no {
set ::conflict_list [list]
sqlite3changeset_apply_v2 -noupdateloop db2 $::changeset xConflict
set ::conflict_list
} [list {*}$clist]]
} else {
uplevel [list do_test $tn.2 {
set ::conflict_list [list]
sqlite3changeset_apply_v2 db2 $::changeset xConflict
set ::conflict_list
} [list {*}$clist]]
}
}
do_test 4.0 {
do_common_sql {
CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE, d UNIQUE);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10
)
INSERT INTO t1 SELECT i, i, i, i FROM s;
}
} {}
proc swap {tbl pkcol valcol pk1 pk2} {
set val1 [db one "SELECT $valcol FROM $tbl WHERE $pkcol = \$pk1"]
set val2 [db one "SELECT $valcol FROM $tbl WHERE $pkcol = \$pk2"]
db eval "
UPDATE $tbl SET $valcol = NULL WHERE $pkcol IN (\$pk1, \$pk2);
UPDATE $tbl SET $valcol = \$val2 WHERE $pkcol = \$pk1;
UPDATE $tbl SET $valcol = \$val1 WHERE $pkcol = \$pk2;
"
}
do_conflict_test 4.1.1 0 {
swap t1 a c 4 5
swap t1 a c 2 3
swap t1 a c 8 1
} {
}
do_execsql_test -db db 4.1.2 {
SELECT a, c FROM t1
} {
1 8 2 3 3 2 4 5 5 4 6 6 7 7 8 1 9 9 10 10
}
do_execsql_test -db db2 4.1.3 {
SELECT a, c FROM t1
} {
1 8 2 3 3 2 4 5 5 4 6 6 7 7 8 1 9 9 10 10
}
do_conflict_test 4.2.1 0 {
swap t1 a d 10 9
swap t1 a d 8 7
swap t1 a d 7 6
swap t1 a d 5 4
swap t1 a d 4 8
} {
}
do_execsql_test -db db 4.2.2 {
SELECT a, d FROM t1
} {
1 1 2 2 3 3 4 7 5 4 6 8 7 6 8 5 9 10 10 9
}
do_execsql_test -db db2 4.2.3 {
SELECT a, d FROM t1
} {
1 1 2 2 3 3 4 7 5 4 6 8 7 6 8 5 9 10 10 9
}
do_execsql_test -db db2 4.3 {
INSERT INTO t1(a, b, c, d) VALUES(11, 11, 11, 11);
}
do_conflict_test 4.3.1 0 {
swap t1 a c 3 6
db eval { UPDATE t1 SET d=11 WHERE a=10; }
swap t1 a d 4 8
} {
{UPDATE t1 CONSTRAINT {i 10 {} {} {} {} i 9} {{} {} {} {} {} {} i 11}}
}
do_conflict_test 4.3.2 0 {
swap t1 a c 1 2
swap t1 a c 3 4
db eval { UPDATE t1 SET c=11 WHERE a=10; }
swap t1 a d 5 6
swap t1 a d 4 5
} {
{UPDATE t1 CONSTRAINT {i 10 {} {} i 10 {} {}} {{} {} {} {} i 11 {} {}}}
}
do_conflict_test 4.3.3 0 {
swap t1 a c 1 2
swap t1 a c 2 3
swap t1 a c 3 4
swap t1 a c 4 1
} {
}
db2 close
#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
sqlite3 db2 test.db2
do_test 5.0 {
do_common_sql {
CREATE TABLE t1(a INT PRIMARY KEY, b UNIQUE);
INSERT INTO t1 VALUES('one', 'one');
INSERT INTO t1 VALUES('two', 'two');
INSERT INTO t1 VALUES('three', 'three');
INSERT INTO t1 VALUES('four', 'four');
INSERT INTO t1 VALUES('five', 'five');
}
} {}
do_conflict_test 5.1 1 {
} {
}
do_conflict_test 5.2 1 {
swap t1 a b one two
} {
{UPDATE t1 CONSTRAINT {t two t two} {{} {} t one}}
{UPDATE t1 CONSTRAINT {t one t one} {{} {} t two}}
}
do_conflict_test 5.2 0 {
swap t1 a b four five
} {
}
finish_test
+41
View File
@@ -94,4 +94,45 @@ do_faultsim_test 2 -faults oom-t* -prep {
catch { S delete }
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(3, 'three');
INSERT INTO t1 VALUES(4, 'four');
INSERT INTO t1 VALUES(5, 'five');
}
faultsim_save_and_close
faultsim_restore_and_reopen
set C [changeset_from_sql {
UPDATE t1 SET b=NULL WHERE a IN (1, 3, 5);
UPDATE t1 SET b='three' WHERE a=1;
UPDATE t1 SET b='five' WHERE a=3;
UPDATE t1 SET b='one' WHERE a=5;
}]
do_execsql_test 3.1 {
SELECT * FROM t1
} {
1 three 2 two 3 five 4 four 5 one
}
proc xConflict {args} {
lappend ::conflict_list $args
return "OMIT"
}
do_faultsim_test 3 -faults oom* -prep {
faultsim_restore_and_reopen
db eval {SELECT * FROM sqlite_schema}
} -body {
sqlite3changeset_apply_v2 db $::C xConflict
set {} {}
} -test {
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
}
finish_test
+6
View File
@@ -181,5 +181,11 @@ do_invert_test 4.1 {
{UPDATE t1 0 X. {i 4 t three} {{} {} t four}}
}
#-------------------------------------------------------------------------
#
do_test 5.0 {
set C [db one {SELECT unhex('54000009')}]
list [catch { sqlite3changeset_invert $C } msg] $msg
} {1 SQLITE_CORRUPT}
finish_test
+25
View File
@@ -228,5 +228,30 @@ do_execsql_test 3.8 {
SELECT * FROM c1;
} {two}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c INTEGER);
ATTACH ':memory:' AS aux;
CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b TEXT, c INTEGER);
}
do_test 4.1 {
sqlite3session S db main
S diff aux t1
} {}
do_test 4.2 {
sqlite3changeset_apply_v2 -ignorenoop -noaction db "" conflict
} {}
breakpoint
do_test 4.3 {
S diff aux t1
} {}
S delete
finish_test
+384 -47
View File
@@ -638,10 +638,11 @@ static int sessionSerialLen(const u8 *a){
int n;
assert( a!=0 );
e = *a;
if( e==0 || e==0xFF ) return 1;
if( e==SQLITE_NULL ) return 1;
if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
return sessionVarintGet(&a[1], &n) + 1 + n;
if( e==SQLITE_TEXT || e==SQLITE_BLOB ){
return sessionVarintGet(&a[1], &n) + 1 + n;
}
return 1;
}
/*
@@ -664,17 +665,17 @@ static unsigned int sessionChangeHash(
u8 *a = aRecord; /* Used to iterate through change record */
for(i=0; i<pTab->nCol; i++){
int eType = *a;
int isPK = pTab->abPK[i];
if( bPkOnly && isPK==0 ) continue;
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|| eType==SQLITE_NULL || eType==0
);
if( isPK ){
a++;
int eType = *a++;
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|| eType==SQLITE_NULL || eType==0
);
h = sessionHashAppendType(h, eType);
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
h = sessionHashAppendI64(h, sessionGetI64(a));
@@ -1544,6 +1545,16 @@ static int sessionPrepareDfltStmt(
return rc;
}
/*
** Finalize statement pStmt. If (*pRc) is SQLITE_OK when this function is
** called, set it to the results of the sqlite3_finalize() call. Or, if
** it is already set to an error code, leave it as is.
*/
static void sessionFinalizeStmt(sqlite3_stmt *pStmt, int *pRc){
int rc = sqlite3_finalize(pStmt);
if( *pRc==SQLITE_OK ) *pRc = rc;
}
/*
** Table pTab has one or more existing change-records with old.* records
** with fewer than pTab->nCol columns. This function updates all such
@@ -1566,9 +1577,8 @@ static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){
}
}
sessionFinalizeStmt(pStmt, &rc);
pSession->rc = rc;
rc = sqlite3_finalize(pStmt);
if( pSession->rc==SQLITE_OK ) pSession->rc = rc;
return pSession->rc;
}
@@ -2136,7 +2146,7 @@ static int sessionDiffFindNew(
rc = SQLITE_NOMEM;
}else{
sqlite3_stmt *pStmt;
rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
pDiffCtx->pStmt = pStmt;
@@ -2199,7 +2209,7 @@ static int sessionDiffFindModified(
rc = SQLITE_NOMEM;
}else{
sqlite3_stmt *pStmt;
rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
@@ -2894,11 +2904,11 @@ static int sessionSelectStmt(
);
sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
}else{
#if 0
#if 0
if( bRowid ){
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
}
#endif
#endif
for(i=0; i<nCol; i++){
if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
sessionAppendIdent(&cols, azCol[i], &rc);
@@ -3702,9 +3712,11 @@ static int sessionChangesetBufferRecord(
rc = sessionInputBuffer(pIn, nByte);
}else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
nByte += 8;
}else if( eType!=0 && eType!=SQLITE_NULL ){
rc = SQLITE_CORRUPT_BKPT;
}
}
if( (pIn->iNext+nByte)>pIn->nData ){
if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
rc = SQLITE_CORRUPT_BKPT;
}
}
@@ -4150,7 +4162,13 @@ static int sessionChangesetInvert(
/* Test for EOF. */
if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert;
if( pInput->iNext>=pInput->nData ) break;
if( pInput->iNext+1>=pInput->nData ){
if( pInput->iNext!=pInput->nData ){
rc = SQLITE_CORRUPT_BKPT;
goto finished_invert;
}
break;
}
eType = pInput->aData[pInput->iNext];
switch( eType ){
@@ -4346,6 +4364,7 @@ struct SessionApplyCtx {
u8 bRebaseStarted; /* If table header is already in rebase */
u8 bRebase; /* True to collect rebase information */
u8 bIgnoreNoop; /* True to ignore no-op conflicts */
u8 bNoUpdateLoop; /* No update-loop processing */
int bRowid;
char *zErr; /* Error message, if any */
};
@@ -4919,7 +4938,7 @@ static int sessionConflictHandler(
u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
int nBlob = pIter->in.iNext - pIter->in.iCurrent;
sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
return SQLITE_OK;
return rc;
}else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
|| eType==SQLITE_CHANGESET_CONFLICT
){
@@ -5041,7 +5060,7 @@ static int sessionApplyOneOp(
for(i=0; rc==SQLITE_OK && i<nCol; i++){
sqlite3_value *pOld = sessionChangesetOld(pIter, i);
sqlite3_value *pNew = sessionChangesetNew(pIter, i);
if( p->abPK[i] || (bPatchset==0 && pOld) ){
if( pOld && (p->abPK[i] || bPatchset==0) ){
rc = sessionBindValue(pUp, i*2+2, pOld);
}
if( rc==SQLITE_OK && pNew ){
@@ -5167,7 +5186,264 @@ static int sessionApplyOneWithRetry(
}
/*
** Retry the changes accumulated in the pApply->constraints buffer.
** Create an iterator to iterate through the retry buffer pRetry.
*/
static int sessionRetryIterInit(
SessionBuffer *pRetry, /* Buffer to iterate through */
int bPatchset, /* True for patchset, false for changeset */
const char *zTab, /* Table name */
SessionApplyCtx *pApply, /* Session apply context */
sqlite3_changeset_iter **ppIter /* OUT: New iterator */
){
sqlite3_changeset_iter *pRet = 0;
int rc = SQLITE_OK;
rc = sessionChangesetStart(
&pRet, 0, 0, pRetry->nBuf, pRetry->aBuf, pApply->bInvertConstraints, 1
);
if( rc==SQLITE_OK ){
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
pRet->bPatchset = bPatchset;
pRet->zTab = (char*)zTab;
pRet->nCol = pApply->nCol;
pRet->abPK = pApply->abPK;
sessionBufferGrow(&pRet->tblhdr, nByte, &rc);
pRet->apValue = (sqlite3_value**)pRet->tblhdr.aBuf;
if( rc==SQLITE_OK ){
memset(pRet->apValue, 0, nByte);
}else{
sqlite3changeset_finalize(pRet);
pRet = 0;
}
}
*ppIter = pRet;
return rc;
}
/*
** Attempt to apply all the changes in retry buffer pRetry to the database.
** Except, if parameter iSkip is greater than or equal to 0, skip change
** iSkip.
*/
static int sessionApplyRetryBuffer(
SessionBuffer *pRetry, /* Buffer to apply changes from */
int iSkip, /* If >=0, index of change to omit */
sqlite3 *db, /* Database handle */
int bPatchset, /* True for patchset, false for changeset */
const char *zTab, /* Name of table to write to */
SessionApplyCtx *pApply, /* Apply context */
int(*xConflict)(void*, int, sqlite3_changeset_iter*),
void *pCtx /* First argument passed to xConflict */
){
int rc = SQLITE_OK;
int rc2 = SQLITE_OK;
int ii = 0;
sqlite3_changeset_iter *pIter = 0;
assert( pApply->constraints.nBuf==0 );
rc = sessionRetryIterInit(pRetry, bPatchset, zTab, pApply, &pIter);
for(ii=0; rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter); ii++){
if( ii!=iSkip ){
rc = sessionApplyOneWithRetry(db, pIter, pApply, xConflict, pCtx);
}
}
rc2 = sqlite3changeset_finalize(pIter);
if( rc==SQLITE_OK ) rc = rc2;
assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
return rc;
}
/*
** Check if table zTab in the "main" database of db is a WITHOUT ROWID
** table.
**
** If no error occurs, return SQLITE_OK and set output variable (*pbWR) to
** true if zTab is a WITHOUT ROWID table, or false otherwise. Or, if an
** error does occur, return an SQLite error code. The final value of (*pbWR)
** is undefined in this case.
*/
static int sessionTableIsWithoutRowid(sqlite3 *db, const char *zTab, int *pbWR){
sqlite3_stmt *pList = 0;
char *zSql = 0;
int rc = SQLITE_OK;
zSql = sqlite3_mprintf("PRAGMA table_list = %Q", zTab);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(db, zSql, -1, &pList, 0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ){
sqlite3_step(pList);
*pbWR = sqlite3_column_int(pList, 4);
rc = sqlite3_finalize(pList);
}
return rc;
}
/*
** Iterator pUp points to an UPDATE change. This function deletes the
** affected row from the database and creates an INSERT statement that
** may be used to reinsert the row as it is after the UPDATE change
** has been applied.
**
** If successful, SQLITE_OK is returned and output variable (*ppInsert)
** is left pointing to a prepared INSERT statement. It is the responsibility
** of the caller to eventually free this statement using sqlite3_finalize().
** Or, if an error occurs, an SQLite error code is returned and (*ppInsert)
** set to NULL. pApply->zErr may be set to an error message in this case.
*/
static int sessionUpdateToDeleteInsert(
sqlite3 *db, /* Database to write to */
const char *zTab, /* Table name */
SessionApplyCtx *pApply, /* Apply context */
sqlite3_changeset_iter *pUp, /* Iterator pointing to UPDATE change */
sqlite3_stmt **ppInsert /* OUT: INSERT statement */
){
sqlite3_stmt *pRet = 0; /* The INSERT statement */
sqlite3_stmt *pSelect = 0; /* SELECT to read current values of row */
int rc = SQLITE_OK;
int bWR = 0;
rc = sessionTableIsWithoutRowid(db, zTab, &bWR);
if( rc==SQLITE_OK ){
char *zSelect = 0;
char *zInsert = 0;
SessionBuffer cols = {0, 0, 0};
SessionBuffer insbind = {0, 0, 0};
SessionBuffer pkcols = {0, 0, 0};
SessionBuffer selbind = {0, 0, 0};
const char *zComma = "";
const char *zComma2 = "";
int ii;
for(ii=0; ii<pApply->nCol; ii++){
sessionAppendStr(&cols, zComma, &rc);
sessionAppendIdent(&cols, pApply->azCol[ii], &rc);
sessionAppendStr(&insbind, zComma, &rc);
sessionAppendStr(&insbind, "?", &rc);
zComma = ", ";
if( pApply->abPK[ii] ){
sessionAppendStr(&pkcols, zComma2, &rc);
sessionAppendIdent(&pkcols, pApply->azCol[ii], &rc);
sessionAppendStr(&selbind, zComma2, &rc);
sessionAppendPrintf(&selbind, &rc, "?%d", ii+1);
zComma2 = ", ";
}
}
if( bWR==0 ){
sessionAppendStr(&cols, zComma, &rc);
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
sessionAppendStr(&insbind, zComma, &rc);
sessionAppendStr(&insbind, "?", &rc);
}
if( rc==SQLITE_OK ){
zSelect = sqlite3_mprintf("SELECT %s FROM %Q WHERE (%s) IS (%s)",
cols.aBuf, zTab, pkcols.aBuf, selbind.aBuf
);
if( zSelect==0 ) rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
zInsert = sqlite3_mprintf("INSERT INTO %Q(%s) VALUES(%s)",
zTab, cols.aBuf, insbind.aBuf
);
if( zInsert==0 ) rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
rc = sessionPrepare(db, &pSelect, &pApply->zErr, zSelect);
}
if( rc==SQLITE_OK ){
rc = sessionPrepare(db, &pRet, &pApply->zErr, zInsert);
}
sqlite3_free(zSelect);
sqlite3_free(zInsert);
sqlite3_free(cols.aBuf);
sqlite3_free(insbind.aBuf);
sqlite3_free(pkcols.aBuf);
sqlite3_free(selbind.aBuf);
}
if( rc==SQLITE_OK ){
rc = sessionBindRow(
pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pSelect
);
}
if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
int iCol;
for(iCol=0; iCol<pApply->nCol; iCol++){
sqlite3_value *pVal = pUp->apValue[iCol+pApply->nCol];
if( pVal==0 ){
pVal = sqlite3_column_value(pSelect, iCol);
}
rc = sqlite3_bind_value(pRet, iCol+1, pVal);
}
if( bWR==0 ){
sqlite3_bind_int64(pRet, iCol+1, sqlite3_column_int64(pSelect, iCol));
}
}
sessionFinalizeStmt(pSelect, &rc);
/* Delete the row from the database. */
if( rc==SQLITE_OK ){
rc = sessionBindRow(
pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pApply->pDelete
);
sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
}
if( rc==SQLITE_OK ){
sqlite3_step(pApply->pDelete);
rc = sqlite3_reset(pApply->pDelete);
}
if( rc!=SQLITE_OK ){
sqlite3_finalize(pRet);
pRet = 0;
}
*ppInsert = pRet;
return rc;
}
/*
** Retry the changes accumulated in the pApply->constraints buffer. The
** pApply->constraints buffer contains all changes to table zTab that
** could not be applied due to SQLITE_CONSTRAINT errors. This function
** attempts to apply them as follows:
**
** 1) It runs through the buffer and attempts to retry each change,
** removing any that are successfully applied from the buffer. This
** is repeated until no further progress can be made.
**
** 2) For each UPDATE change in the buffer, try the following in a
** savepoint transaction:
**
** a) DELETE the affected row,
** b) Attempt step (1) with remaining changes,
** c) Attempt to INSERT a row equivalent to the one that would be
** created by applying this UPDATE change.
**
** If the INSERT in (c) succeeds, the savepoint is committed and all
** successfully applied changes are removed from the buffer. Step (2)
** is then repeated.
**
** 3) Once step (2) has been attempted for each UPDATE in the change,
** a final attempt is made to apply each remaining change. This time,
** if an SQLITE_CONSTRAINT error is encountered, the conflict handler
** is invoked and the user has to decide whether to omit the change
** or rollback the entire _apply() operation.
*/
static int sessionRetryConstraints(
sqlite3 *db,
@@ -5178,41 +5454,101 @@ static int sessionRetryConstraints(
void *pCtx /* First argument passed to xConflict */
){
int rc = SQLITE_OK;
int iUpdate = 0;
/* Step (1) */
while( pApply->constraints.nBuf ){
sqlite3_changeset_iter *pIter2 = 0;
SessionBuffer cons = pApply->constraints;
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
rc = sessionChangesetStart(
&pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
rc = sessionApplyRetryBuffer(
&cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
);
if( rc==SQLITE_OK ){
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
int rc2;
pIter2->bPatchset = bPatchset;
pIter2->zTab = (char*)zTab;
pIter2->nCol = pApply->nCol;
pIter2->abPK = pApply->abPK;
sessionBufferGrow(&pIter2->tblhdr, nByte, &rc);
pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf;
if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){
rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx);
}
rc2 = sqlite3changeset_finalize(pIter2);
if( rc==SQLITE_OK ) rc = rc2;
}
assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
sqlite3_free(cons.aBuf);
if( rc!=SQLITE_OK ) break;
if( pApply->constraints.nBuf>=cons.nBuf ){
/* No progress was made on the last round. */
pApply->bDeferConstraints = 0;
/* If no progress has been made this round, break out of the loop. */
if( pApply->constraints.nBuf>=cons.nBuf ) break;
}
/* Step (2) */
while( rc==SQLITE_OK && pApply->constraints.nBuf && !pApply->bNoUpdateLoop ){
SessionBuffer cons = {0, 0, 0};
sqlite3_changeset_iter *pUp = 0;
sqlite3_stmt *pInsert = 0;
int iSkip = 0;
rc = sessionRetryIterInit(
&pApply->constraints, bPatchset, zTab, pApply, &pUp
);
if( rc==SQLITE_OK ){
int iThis = -1;
while( SQLITE_ROW==sqlite3changeset_next(pUp) ){
if( pUp->op==SQLITE_UPDATE ) iThis++;
if( iThis==iUpdate ) break;
iSkip++;
}
if( iThis==iUpdate ){
rc = sqlite3_exec(db, "SAVEPOINT update_op", 0, 0, 0);
if( rc==SQLITE_OK ){
rc = sessionUpdateToDeleteInsert(db, zTab, pApply, pUp, &pInsert);
}
}
sqlite3changeset_finalize(pUp);
if( iThis!=iUpdate ) break;
}
if( rc==SQLITE_OK ){
cons = pApply->constraints;
while( rc==SQLITE_OK && pApply->constraints.nBuf>0 ){
SessionBuffer app = pApply->constraints;
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
rc = sessionApplyRetryBuffer(
&app, iSkip, db, bPatchset, zTab, pApply, xConflict, pCtx
);
if( app.aBuf!=cons.aBuf ){
sqlite3_free(app.aBuf);
}
if( pApply->constraints.nBuf>=app.nBuf ){
break;
}
iSkip = -1;
}
}
iUpdate++;
if( rc==SQLITE_OK ){
sqlite3_step(pInsert);
rc = sqlite3_finalize(pInsert);
if( rc==SQLITE_CONSTRAINT ){
rc = sqlite3_exec(db, "ROLLBACK TO update_op", 0, 0, 0);
sqlite3_free(pApply->constraints.aBuf);
pApply->constraints = cons;
memset(&cons, 0, sizeof(cons));
}else if( rc==SQLITE_OK ){
iUpdate = 0;
}
if( rc==SQLITE_OK ){
rc = sqlite3_exec(db, "RELEASE update_op", 0, 0, 0);
}
}else{
sqlite3_finalize(pInsert);
}
sqlite3_free(cons.aBuf);
}
/* Step (3) */
if( rc==SQLITE_OK && pApply->constraints.nBuf ){
SessionBuffer cons = pApply->constraints;
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
pApply->bDeferConstraints = 0;
rc = sessionApplyRetryBuffer(
&cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
);
sqlite3_free(cons.aBuf);
}
return rc;
@@ -5266,6 +5602,7 @@ static int sessionChangesetApply(
sApply.bRebase = (ppRebase && pnRebase);
sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
sApply.bNoUpdateLoop = !!(flags & SQLITE_CHANGESETAPPLY_NOUPDATELOOP);
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
}
@@ -7077,7 +7414,7 @@ int sqlite3changegroup_change_blob(
const void *pVal,
int nVal
){
sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + nVal;
sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + (i64)nVal;
int rc = SQLITE_OK;
SessionBuffer *pBuf = 0;
+12
View File
@@ -1366,11 +1366,23 @@ int sqlite3changeset_apply_v3(
** database behave as if they were declared with "ON UPDATE NO ACTION ON
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
** or SET DEFAULT.
**
** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
** Sometimes, a changeset contains two or more update statements such that
** although after applying all updates the database will contain no
** constraint violations, no single update can be applied before the others.
** The simplest example of this is a pair of UPDATEs that have "swapped"
** two column values with a UNIQUE constraint.
** <p>
** Usually, sqlite3changeset_apply() and similar functions work hard to try
** to find a way to apply such a changeset. However, if this flag is set,
** then all such updates are considered CONSTRAINT conflicts.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
/*
** CAPI3REF: Constants Passed To The Conflict Handler
+5 -1
View File
@@ -914,6 +914,9 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
}
else if( n>2 && n<=11 && 0==sqlite3_strnicmp("-ignorenoop", z1, n) ){
flags |= SQLITE_CHANGESETAPPLY_IGNORENOOP;
}
else if( n>3 && n<=13 && 0==sqlite3_strnicmp("-noupdateloop", z1, n) ){
flags |= SQLITE_CHANGESETAPPLY_NOUPDATELOOP;
}else{
break;
}
@@ -1095,7 +1098,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_invert(
memset(&sIn, 0, sizeof(sIn));
memset(&sOut, 0, sizeof(sOut));
sIn.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
sIn.aData = Tcl_GetByteArrayFromObj(objv[1], &nn);
sIn.aData = testGetByteArrayFromObj(objv[1], &nn);
sIn.nData = (int)nn;
if( sIn.nStream ){
@@ -1112,6 +1115,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_invert(
Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n));
}
sqlite3_free(sOut.p);
free(sIn.aData);
return rc;
}
+8 -7
View File
@@ -1099,20 +1099,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return promiseResolve_(sqlite3);
};
const options = opfsUtil.options;
let proxyUri = options.proxyUri +(
//#if not target:es6-bundler-friendly
const proxyUri = options.proxyUri +(
(options.proxyUri.indexOf('?')<0) ? '?' : '&'
)+'vfs='+vfsName;
//sqlite3.config.error("proxyUri",options.proxyUri, (new Error()));
//#/if
const W = opfsVfs.worker =
//#if target:es6-bundler-friendly
(()=>{
/* _Sigh_... */
switch(vfsName){
case 'opfs':
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs", import.meta.url));
case 'opfs-wl':
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs-wl", import.meta.url));
}
/* Discussion explaining this formulation:
https://github.com/sqlite/sqlite-wasm/pull/159 */
const url = new URL('sqlite3-opfs-async-proxy.js', import.meta.url);
url.searchParams.set('vfs', vfsName);
return new Worker(url.toString());
})();
//#elif target:es6-module
new Worker(new URL(proxyUri, import.meta.url));
+4 -4
View File
@@ -1559,18 +1559,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
only argument. On success, returns the result of the
callback. Throws on error.
Note that transactions may not be nested, so this will throw if
it is called recursively. For nested transactions, use the
Transactions may not be nested, so this will throw if it is
called recursively. For nested transactions, use the
savepoint() method or manually manage SAVEPOINTs using exec().
If called with 2 arguments, the first must be a keyword which
is legal immediately after a BEGIN statement, e.g. one of
"DEFERRED", "IMMEDIATE", or "EXCLUSIVE". Though the exact list
"DEFERRED", "IMMEDIATE", or "EXCLUSIVE", though the exact list
of supported keywords is not hard-coded here, in order to be
future-compatible, if the argument does not look like a single
keyword then an exception is triggered with a description of
the problem.
*/
*/
transaction: function(/* [beginQualifier,] */callback){
let opener = 'BEGIN';
if(arguments.length>1){
+7 -6
View File
@@ -1949,8 +1949,6 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
}/*changeset/preupdate additions*/
/**
EXPERIMENTAL. For tentative addition in 3.53.0.
sqlite3_js_retry_busy(maxTimes,callback[,beforeRetry])
Calls the given _synchronous_ callback function. If that function
@@ -1971,11 +1969,14 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
(so it starts with 2, not 1). If it throws, the exception is
handled as described above. Its result value is ignored.
To effectively retry "forever", pass a negative maxTimes value,
with the caveat that there is no recovery from that unless the
beforeRetry() can figure out when to throw.
To effectively retry "forever", pass a huge maxTimes value such
as Number.MAX_SAFE_INTEGER, with the caveat that there is no
recovery from that unless the beforeRetry() can figure out when
to throw.
TODO: an async variant of this.
Added in 3.53.0.
TODO?: an async variant of this.
*/
capi.sqlite3_js_retry_busy = function(maxTimes, callback, beforeRetry){
for(let n = 1; n <= maxTimes; ++n){
+5 -1
View File
@@ -1021,11 +1021,15 @@ static void mk_fiddle(void){
pf("\t@$(call b.call.wasm-strip,%s)\n", zBuildName);
pf("\t@$(call b.strip-js-emcc-bindings,$(logtag.%s))\n",
zBuildName);
pf("\t@$(call b.cp,%s,$(dir.dout)/sqlite3-opfs-async-proxy.js,"
"$(dir $@)"
")\n", zBuildName);
if( isDebug ){
pf("\t@$(call b.cp,%s,"
"$(dir.fiddle)/index.html "
"$(dir.fiddle)/fiddle.js "
"$(dir.fiddle)/fiddle-worker.js,"
"$(dir.fiddle)/fiddle-worker.js "
"$(dir.fiddle)/sqlite3-opfs-async-proxy.js,"
"$(dir $@)"
")\n",
zBuildName);
+2 -2
View File
@@ -386,7 +386,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
This function initializes the db described by ctorOptFunc(...),
writes some secret info into it, and re-opens it twice to
confirmi that it can be read with an SEE key and cannot be read
confirm that it can be read with an SEE key and cannot be read
without one.
*/
T.seeBaseCheck = function(ctor, ctorOptFunc, dbUnlink){
@@ -3940,7 +3940,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
//#/query
////////////////////////////////////////////////////////////////////////
T.g('OPFS SyncAccessHandle Pool VFS',
(sqlite3)=>(!!sqlite3.installOpfsSAHPoolVfs || "requires OPFS SAH Pool APIs"))
(sqlite3)=>(isWorker() && !!sqlite3.installOpfsSAHPoolVfs || "requires OPFS SAH Pool APIs"))
.t({
name: 'SAH sanity checks',
test: async function(sqlite3){
+6 -8
View File
@@ -1678,7 +1678,8 @@ tclsqlite3.c: sqlite3.c tclsqlite-ex.c
#
# $(CFLAGS.tclextension) = CFLAGS for the tclextension* targets.
#
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAGS) $(OPTS)
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) \
$(OPT_FEATURE_FLAGS) $(OPTS) $(CFLAGS.icu)
#
# Build the SQLite TCL extension in a way that make it compatible
# with whatever version of TCL is running as $TCLSH_CMD, possibly defined
@@ -1686,7 +1687,8 @@ CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAG
#
tclextension: tclsqlite3.c
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only \
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
#
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
@@ -1694,7 +1696,8 @@ tclextension: tclsqlite3.c
#
tclextension-install: tclsqlite3.c
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" \
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
#
# Uninstall the SQLite TCL extension that is used by $TCLSH_CMD.
@@ -2232,11 +2235,6 @@ install: install-man1
install-pc: sqlite3.pc $(install-dir.pkgconfig)
$(INSTALL.noexec) sqlite3.pc "$(install-dir.pkgconfig)"
scrub$(T.exe): $(TOP)/ext/misc/scrub.c sqlite3.o
$(T.link) -o $@ -I. -DSCRUB_STANDALONE \
$(TOP)/ext/misc/scrub.c sqlite3.o $(LDFLAGS.libsqlite3)
xbin: scrub$(T.exe)
srcck1$(B.exe): $(TOP)/tool/srcck1.c
$(B.cc) -o srcck1$(B.exe) $(TOP)/tool/srcck1.c
xbin: srcck1$(B.exe)
+101 -100
View File
@@ -1,14 +1,14 @@
C Version\s3.53.0
D 2026-04-09T11:41:38.498
C Version\s3.53.2
D 2026-06-03T19:12:13.350
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
F Makefile.in 5fda086f33b144da08119255da1d2557f983d0764a13707f05acf0159fd89ba5
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 92391304cf70f4c178b127aa83b88637abd28d1b83ede451616144037ea1d3dd
F Makefile.msc 1d6098faf066e14bc181f9460b002285248eee32cfaaa7babcb37f4381928408
F README.md f49fbd826941842e348242f3ab62f240c985ceafdf8fbe576abf4eb75317468c
F VERSION 31435e19ded2aae3c1c67dacf06a995a37fd1b253baec5899b78d64cd29db4f7
F VERSION 7441adea0de9103e8e0541375ba322afed1a5d614a39bffcdbda09b69619bba7
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
@@ -47,7 +47,7 @@ F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1
F autosetup/jimsh0.c 916bbdf8023fbda9937afae57d81a853d8c2ea00f2320aa27becbc33574f963d
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
F autosetup/proj.tcl ce301197f364f7ce2acabbbd84b43d19e917ec73653157ca134a06f32d322712
F autosetup/sqlite-config.tcl 8fecce2838b7e7d990d161d08998034f3e3b0b2ddf4d7a99dbfafba9c902e302
F autosetup/sqlite-config.tcl 7ff8dad28d6ea2ad95f0288c61274042e6594145511b58ec4d42daacbee15f0d
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
F autosetup/teaish/core.tcl e014dd95900c7f9a34e8e0f460f47e94841059827bce8b4c49668b0c7ae3f1a0
@@ -79,16 +79,16 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
F ext/fts3/README.syntax b72477722e9b4fe43f8403227d790a1c94221bfad15c27863a4b36d1052e892b
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 6cc7bbc307f27e7b6ee2e1d5ff63ffff4df3b42529dfe00eb34ddded417961b3
F ext/fts3/fts3.c 1716994c40715223431d98e5132c40a3c1a00c011c5bde2270bad1bd06be3ccd
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 277f32f304e82f4397fc2a74793c0a95318b7abb9670b519e4805a00946cbd9b
F ext/fts3/fts3_aux.c 37ba1b10bbd163ddc6b05dbc3a306a0d5d68aee3d30f33b4dc5794955cc50887
F ext/fts3/fts3_expr.c 5c13796638d8192c388777166075cdc8bc4b6712024cd5b72c31acdbefce5984
F ext/fts3/fts3_aux.c bbb614abcc995bf748cba4717e9fd8de67898e33c80f60379f6feb2358189b4b
F ext/fts3/fts3_expr.c 907dd64deb881c0586d5ecbabc96cfebdbe2ff9e7a052d379fd3b606edfa21ea
F ext/fts3/fts3_hash.c d9dba473741445789330c7513d4f65737c92df23c3212784312931641814672a
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c 024417020c57dd1ab39816f5fe6cf45222a857b78a1f6412f040ada1ceabd4ff
F ext/fts3/fts3_snippet.c abe3b2998e7cb6d1ab6019f87f021758a0df3ee4010fe144a174a524cff96fe6
F ext/fts3/fts3_snippet.c 65e178107b59ad4724a11339a645f2e3789f3cf59b2f4e29c90efd864e53c5b4
F ext/fts3/fts3_term.c 6a96027ad364001432545fe43322b6af04ed28bb5619ec51af1f59d0710d6d69
F ext/fts3/fts3_test.c cc329471e573f95a6ea9fbca87e89dcfa1d355591c80172ffcd759ac521d25d8
F ext/fts3/fts3_tokenize_vtab.c 66eba6c2baa04b2b15e80d68341b8fd0b4d3831f6b2edb33916a2906ff2d4389
@@ -113,13 +113,13 @@ F ext/fts5/fts5_buffer.c dcc3f0352339fe79c9d8abbc1c2009bc3469206467880bf43558447
F ext/fts5/fts5_config.c bfba970fe1e4eed18ee57c8d51458e226db9a960ddf775c5e50e3d76603a667e
F ext/fts5/fts5_expr.c 71d48e8cf0358deace4949276647d317ff7665db6db09f40b81e2e7fe6664c7c
F ext/fts5/fts5_hash.c d5871df92ce3fa210a650cf419ee916b87c29977e86084d06612edf772bff6f5
F ext/fts5/fts5_index.c f8cfa37bb7397e5ede20242e4c9cb030bc8b4584ce3f23a5e2495038c0ae64bd
F ext/fts5/fts5_index.c 1627d9c184dec6be913647ba1e31a906e825b8460c9575e1c367ee27fe847f0c
F ext/fts5/fts5_main.c b0fed47b3b4420ba6810373480a75bc28a9c0b7d16478d19a396436fb3ff17d7
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
F ext/fts5/fts5_tokenize.c cfc16dde905552fe238c0403670852e75c0330ba508a9fb4836c1f596618561d
F ext/fts5/fts5_tokenize.c 21078ea9f496ba9b0c4dd15ac2404933251df8bebab9907f6a5a47d4321c77fd
F ext/fts5/fts5_unicode2.c 536a6dae41d16edadd6a6b58c56e2ebbb133f0dfe757562a2edbcdc9b8362e50
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
F ext/fts5/fts5_vocab.c bebee4aabcd056a44b3731166433cfdecf17ece750c08cb58733216222bd39e2
@@ -162,13 +162,14 @@ F ext/fts5/test/fts5contentless4.test ec34dc69ef474ca9997dae6d91e072906e0e9a5a4b
F ext/fts5/test/fts5contentless5.test 38cd0392c730dc7090c550321ce3c24ba4c392bc97308b51a4180e9959dca7b5
F ext/fts5/test/fts5corrupt.test 237fce1c3261bb3a5bec333b0f0dbf5b105ec32627ef14cccbda3cfe13833193
F ext/fts5/test/fts5corrupt2.test 4a03a158c2cb617c9f76d26b35c1ef2534124bc0bbddcea38dfd5b170ebea27b
F ext/fts5/test/fts5corrupt3.test e489b51b6c4ded2a808e0f78bdbe126f6d369de41a59ac2717878e37fc3db0e8
F ext/fts5/test/fts5corrupt3.test 121a8a7622dfe1be1bc55cbe70eddd6a3416f76a837dc8c06a11a32e781595a4
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
F ext/fts5/test/fts5corrupt5.test 73985d4fe6d8f0d5d5c7bcf79ae7c6522c376cd6ad710a0ff2f26e0c2e222abe
F ext/fts5/test/fts5corrupt5.test b9085599389721b38f080f501660c931cd608f8ecbc93c23644344f74ef7aa21
F ext/fts5/test/fts5corrupt6.test 2d72db743db7b5d9c9a6d0cfef24d799ed1aa5e8192b66c40e871a37ed9eed06
F ext/fts5/test/fts5corrupt7.test 814aab492d7a09abb5bfdd81cc66fc206d7f3868f9a3bae91876e02efc466fb3
F ext/fts5/test/fts5corrupt7.test 9664c15360e8b649ad76f457a0bbf5a7271b8eff1a8ee141ea039bc63240c934
F ext/fts5/test/fts5corrupt8.test 0b10750caf8aa23fa1c379ca4caf6130d41454505e4d5315590f4061eedcbe44
F ext/fts5/test/fts5corrupt9.test 4253b9b59f33effac8b67da72ec34309c738aca2d5e8e2656bfbbd6a489a1dfe
F ext/fts5/test/fts5corruptA.test 7b31551444569420903d34ae50a55a1227d16969264f0b50de2dc812bc0b3414
F ext/fts5/test/fts5corruptbig.test 9f95b40fa36e292feceab02b2ef06e21878bfa1ac7afefa138aae05518b51774
F ext/fts5/test/fts5delete.test 2a5008f8b1174ef41d1974e606928c20e4f9da77d9f8347aed818994d89cced4
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
@@ -253,7 +254,7 @@ F ext/fts5/test/fts5synonym2.test 58f357b997cf2fedeeb9d0de4db9f880fa96fa2fe27a74
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokendata.test 7cad79af82e8e81b7a36b450087233d2fca051bb0d584421afc375d6dd26d6f6
F ext/fts5/test/fts5tokenizer.test 7937cec672b148223fff8746d21d3e7ed0965fd7caf35ccdc888a005bb452f98
F ext/fts5/test/fts5tokenizer.test 738e9c3e1b338028e202d0fcd33aa39f1bd3f8444d14f9a408e8a617b1361d3f
F ext/fts5/test/fts5tokenizer2.test ddb8b10fbe4b84b2a75812671f127774c1d2e3e2bf82d2e0e4f0bb1cd8a2b2d6
F ext/fts5/test/fts5tokenizer3.test eea778f7bb7024c3e904e28915f9d53286141671b138722148be22a9c758bdc3
F ext/fts5/test/fts5trigram.test a55fde7065ae69a0f82c5a7a5bf5286a97de11ae4bff6537fd3e27ca9a01416f
@@ -278,7 +279,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl 135b9e160f8e10211c10c5873d5e8c3eaebd3da9ec56a12ae4db157d4738ffe4
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt 1f8d76e10d2385fc77914a14ccd99acfbaf68111dfcf26a360ad9063787f57fb
F ext/icu/icu.c 9837f4611915baad1edbe38222f3ee7d1b5e118ab16fec9ba603720f72c78b2a
F ext/icu/icu.c 535d0d61f109e760a56e1afc450414ebfb0e2d594e2233b30315b815e3433ac2
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/intck/intck1.test 53d885075abeb45aeb1eeffeaa8560b329060835ade4af5c44cf5fcb581c1e63
F ext/intck/intck2.test a29343a8e65c5c3400e10747f394924f3df95a5b2de94f46e9b5c9b97f5e7339
@@ -368,7 +369,7 @@ F ext/misc/btreeinfo.c 13bc9e9f1c13cde370d0e4a6a2683e9f1926a4cead7fb72c71871b11a
F ext/misc/cksumvfs.c 9d7d0cf1a8893ac5d48922bfe9f3f217b4a61a6265f559263a02bb2001259913
F ext/misc/closure.c c983987a8d7846c3e52b1885ed3e20af7d4ca52a81a8f94ec6d1cd68f93acc86
F ext/misc/completion.c 3f5db28e88c3313103b2dd86d910a2944fd500c46754e473493968ce81e994a4
F ext/misc/compress.c 8191118b9b73e7796c961790db62d35d9b0fb724b045e005a5713dc9e0795565
F ext/misc/compress.c 5cc142aa82d1589a31c384657d0418c0eb0871348a2201e5dca32d24a0dd6654
F ext/misc/csv.c 5e9d4dd749e762c144104c0f01db5bf4458735b19081ebe481a64e589a66687a
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
F ext/misc/decimal.c 23698283d9365ce66d54b5bb97c01e69b4aa7ac804f226f9117a0d42efd15a65
@@ -385,19 +386,18 @@ F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
F ext/misc/normalize.c fbb144a861809686ff2b5b6eee8bb2e1207f9bf13ce7376e5273c700a1eafbd5
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
F ext/misc/percentile.c 72e05a21db20a2fa85264b99515941f00ae698824c9db82d7edfbb16cea8ec80
F ext/misc/prefixes.c aa15fd268e7d1336d1a1d4bc79265860d1d2ad68bba4cbcab61f83e4989dc68c
F ext/misc/percentile.c b6b9c740f0dc42838efd776eec0f68a93bc5ac86524c71337a70950860bf6c4d
F ext/misc/prefixes.c e7d3e7a39174db412c5f77c266fa221c2dc3cb2621a9422835a607ad08805eb2
F ext/misc/qpvtab.c 470a5fffba005c8e1994209e59c1848122351e19522de71beb68d666c4fa39a5
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
F ext/misc/regexp.c 9dada9e9aa91f0cc23e35429e5d1111f110cc201b4c8dcc49aa6d2fc4b2a865d
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c df54e202887e480bf9cd73168c9ac829e3b0211381b68b9809e0cb5bc1bdc2cf
F ext/misc/series.c 9454c7ef27d3729432496f31caabc892aeee1c21377d403f681126d93c09d6e9
F ext/misc/series.c 496f43bac9bad2ee2cea63fb5212036f30ad3003b4cd317d5c2d6f3ad7c7d264
F ext/misc/sha1.c 8bf60344c11a525384c2efd1ae77f160b06be336db679effaadf292d4b41451c
F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 693c8fd3293087fa821322967a97e59dfa24051e5d2ca7fa85790a4034db6fa4
F ext/misc/spellfix.c e9e951f9712b6c302e4ee84f5db5a7b18daab87aa229867c66f34684d2dfbb40
F ext/misc/sqlar.c 97c100b010159c08a7a9acd8eb1ea510a5522e64741aaafcd7b6c629de682edc
F ext/misc/sqlite3_stdio.c b43a0f530c6f0fb3d41d9af8c0b40f3f71198a1db55ab8ffffbef5c8cc329d22
F ext/misc/sqlite3_stdio.h 27a4ecea47e61bc9574ccdf2806f468afe23af2f95028c9b689bfa08ab1ce99f
@@ -417,11 +417,11 @@ F ext/misc/vtablog.c 6c0c11c4822ab6c1a205718ea7c6d1bb561d96b27104b9c1fe84d01aa62
F ext/misc/vtshim.c f5ab480d1e33fa46a0b138359bedc9979e32798d72348e04bbe6093f9ae95c7b
F ext/misc/wholenumber.c aa5e6d786fe8d79bc100ea0e852249c026a91ae65a5c1bcb2b869cd1a7cdd6d5
F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
F ext/misc/zipfile.c 5a583b5e72b4d777dc9f845529e6bd185d58024b633aafc93588679c78719700
F ext/misc/zipfile.c 58d535e6f177709c3f3607e19aa8e1b4c3c57c1f2c78bd4cdfac15e0b2f53e5a
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
F ext/qrf/README.md 9e644615d7d7b77ef7e9db798765679e50c5ed12eda48bce21c9ef9eb4715e9d
F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
F ext/qrf/qrf.c 9bef1f01e0c33a8693a9a7c1b666b8dee1aa60b8bc880d562eb4dfff551a6009
F ext/qrf/qrf.c b82987a8b9bc24710e44e5f0120ee6be8d55f270688f0ddad2baa331d20ba7a5
F ext/qrf/qrf.h fbb223ff5789b324b3e9c22e787e4c1f53e217cff7cc5a243164d4b2e8410f4b
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
@@ -486,12 +486,12 @@ F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
F ext/recover/recoverslowidx.test c90d59c46bb8924a973ac6fbc38f3163cee38cc240256addcab1cf1a322c37dc
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
F ext/recover/sqlite3recover.c dfbfca5a8e4909333e5aa3749bcffb5dd7e396de9541c338f8cc843b2e20217e
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c 3d0fb1df7823f5bc22a0b93955034d16a2dfa2eb1e443e9a0123a77f120599a3
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
F ext/rtree/geopoly.c bd1971479184d559499ff3087c37f2823977d7b0ec80916141ae66f70345c88d
F ext/rtree/rtree.c 44abdd5df278ca1901daf29c82cce6785f0ee82ce59e28160ee988c17a9a185b
F ext/rtree/geopoly.c 77bad24162b6ae84a2fd6de3f1f8ad0b255a4ceb572f50f8771d1ac9d4d986d8
F ext/rtree/rtree.c e350bb1c7adefab45cd4ce77e11393c7f3a9ee21c27345a684b6e1c04fae1a12
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -502,7 +502,7 @@ F ext/rtree/rtree6.test 2f5ffc69670395c1a84fad7924e2d49e82a25460c5293fb1e54e1aa9
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
F ext/rtree/rtree8.test 4da84c7f328bbdca15052fa13da6e8b8d426433347bf75fc85574c2f5a411a02
F ext/rtree/rtree9.test fd3c9384ef8aabbc127b3878764070398f136eebc551cd20484b570f2cc1956a
F ext/rtree/rtreeA.test 14e67fccc5b41efbad7ea99d21d11aaa66d2067da7d5b296ee86e4de64391d82
F ext/rtree/rtreeA.test c90dd34792aeb7e15909530b5e0e91a8ad69f4d4b7bb52c14c4ef5c60050cace
F ext/rtree/rtreeB.test ab93136c45cf25af78d22665c2a6d75068eef6bf3a710356e4ba8d5f37bed364
F ext/rtree/rtreeC.test 2978b194d09b13e106bdb0e1c5b408b9d42eb338c1082bf43c87ef43bd626147
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
@@ -537,14 +537,14 @@ F ext/session/session4.test ad0ddaaddb9a99dac433d83fc6674aae2af072b8f57e63a6b3f2
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
F ext/session/session6.test 35279f2ec45448cd2e24a61688219dc6cf7871757716063acf4a8b5455e1e926
F ext/session/session8.test 326f3273abf9d5d2d7d559eee8f5994c4ea74a5d935562454605e6607ee29904
F ext/session/session9.test 0c4a8fbe7a5031f50855f020f3408e1f07fd7859f1daa1629eadcec3422072d6
F ext/session/session9.test ce2b898aa4caf0e492b57c29cb707224e0a33479e4f019785a81828273143ba5
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c
F ext/session/sessionC.test 2bd42225efdf5f5b1a20f75b672665bcd4f67e2a6d7ddf7420fe7bf523ba41f8
F ext/session/sessionC.test de98b5e173fd86c79af0d0541534398d2ea75dc0d5d74a00103eb26151b76959
F ext/session/sessionD.test 470ff917dc849e2eb78142ade63aaabd729d773833cff0ff01bca0eda68a21ce
F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
F ext/session/sessionG.test 3efe388282d641b65485b5462e67851002cd91a282dc95b685d085eb8efdad0a
F ext/session/sessionG.test 64c2b69531aebdb36d5977a5f832d77e4c8bda0c746a6c630adf23660bb1c7c2
F ext/session/sessionH.test 71bbff6b1abb2c4ac62b84dee53273c37e0b21e5fde3aed80929403e091ef859
F ext/session/sessionI.test 11e7b6729fc942982a5104a40132f70a2e964d64d60dc5809b8206465af74822
F ext/session/session_common.tcl a31f537a929a695a852d241c9434f2847cadf329856401921139fbb03a5a7697
@@ -557,13 +557,14 @@ F ext/session/sessionblob.test 87faf667870b72f08e91969abd9f52a383ab7b514506ee194
F ext/session/sessionchange.test 6618cb1c1338a4b6df173b6ac42d09623fb71269962abf23ebb7617fe9f45a50
F ext/session/sessionchange2.test 6b5b7e3d1cc4ede43817f7fb68e3771aac4aa6500adb21a458b3e5a9fd841f83
F ext/session/sessionconflict.test 19e4a53795c4c930bfec49e809311e09b2a9e202d9446e56d7a8b139046a0c07 x
F ext/session/sessionconflict2.test d7f4caf59360dbca8a4698b9a3a322adf6f547f810ad41d131cacb730e02dd5e x
F ext/session/sessiondiff.test e89f7aedcdd89e5ebac3a455224eb553a171e9586fc3e1e6a7b3388d2648ba8d
F ext/session/sessionfault.test c2b43d01213b389a3f518e90775fca2120812ba51e50444c4066962263e45c11
F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
F ext/session/sessionfault3.test 9397819ec25b0960c5bc03c78613f9cb5cacc970f83e817aec1775c2a839a787
F ext/session/sessioninvert.test 9018f6a7387ac745084b6374c5e1aa14d648b372e6e1181cfab3df632b662d26 x
F ext/session/sessionfault3.test aea5331fa6dbe5ca4e19826605e624c0e1767545411479f27c5ef82b41046925
F ext/session/sessioninvert.test 7ccb7609a2c11e4e13e606df439bf3d484ba8e455d0bd3aa8d4828a940e1a242 x
F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
F ext/session/sessionnoact.test 4c7ae5c7d351cb5323bca62b6b095592ad24bd90a6713c178b62ab0063d23e19
F ext/session/sessionnoact.test 2cf060c12a7a23e663f0ec796561e58638c5c10a846653d37be886414b06ddc9
F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
F ext/session/sessionnoop2.test 2d8146321785bdc7cee8966d984560184cfca83fd46da2ff81ea883d6e977b36
F ext/session/sessionrebase.test 702378bdcb5062f1106e74457beca8797d09c113a81768734a58b197b5b334e2
@@ -571,9 +572,9 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3session.c d5c91d5b07d2b8e860f2782ae23f7b44ce929280e00645418ee84a0fd14525b2
F ext/session/sqlite3session.h 063e7bf7be2fff874456f452a224b5b3013b25682d108933b0351c93a1279b9c
F ext/session/test_session.c 2a02a68b522e2f3d4a64b2a4733af54b0f3e500769aeccd5bcbdd440103db069
F ext/session/sqlite3session.c 1010718d9d88eeb1efd1bf3d6bcbc85e598e9d5bb094c2d202515622d2233481
F ext/session/sqlite3session.h ca7c4422c1514a95056cc8d333217df6b1829d39058126b1de85d10cd62d7a9c
F ext/session/test_session.c 95fbf8fc721fdb1a0d00268f930d6763c5299ed766b317f9dd3cf9ca5262e337
F ext/wasm/GNUmakefile 68c750f173106d9d63f12c1edf1256c6f4bad9894b155da5db64322f4912de4b
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
F ext/wasm/README.md 2e87804e12c98f1d194b7a06162a88441d33bb443efcfe00dc6565a780d2f259
@@ -587,13 +588,13 @@ F ext/wasm/api/README.md a905d5c6bfc3e2df875bd391d6d6b7b48d41b43bdee02ad115b4724
F ext/wasm/api/extern-post-js.c-pp.js 80accc53cc6ea1e61c721595f42ba95baa7c7ea636807d9507e69403301f8c54
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
F ext/wasm/api/opfs-common-inline.c-pp.js 496ca858af09b7fef2efaece467960611d35f57254078424bcdeac42ded9e85d
F ext/wasm/api/opfs-common-shared.c-pp.js d0bff21d34fa05a7eb975c4ee608165f96387332101cb05e976953c77434374d
F ext/wasm/api/opfs-common-shared.c-pp.js 5b5880ced26977931a4fb33aafc6c71206fbee519e82abf9614898d8fa5ec241
F ext/wasm/api/post-js-footer.js a50c1a2c4d008aede7b2aa1f18891a7ee71437c2f415b8aeb3db237ddce2935b
F ext/wasm/api/post-js-header.js f35d2dcf1ab7f22a93d565f8e0b622a2934fc4e743edf3b708e4dd8140eeff55
F ext/wasm/api/pre-js.c-pp.js d6bf82f83f60caa2904bddb95a29cb738b310f672d2796cdc5fe54463ab0d6cd
F ext/wasm/api/sqlite3-api-glue.c-pp.js 31a721ada7225838a61310a9f3f797fa5275353f8e9b0ae769d85b437be061f5
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 5f203f5bb5d48a9e43ec51e791dc411c24dca825842bfb6a2d979d871bf8cfaf
F ext/wasm/api/sqlite3-api-prologue.js 4336f02ac24ba58e68e355adb9da2804a1eef15a4aee961fa813c7d812a56b54
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 35e4727010f15fd72ead0dd1eb4e3c2c9bb1cc60e51544cbdff1f7c14f209de2
F ext/wasm/api/sqlite3-api-prologue.js 29ca376ff5d5f189714cf10b2b93b136e91b06ec8616579b53b2af9dfb4796bf
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1fa34e9b0e3b90a8898e4f700d7125e44c81877f182627bb8564b97989bc6e78
F ext/wasm/api/sqlite3-license-version-header.js 98d90255a12d02214db634e041c8e7f2f133d9361a8ebf000ba9c9af4c6761cc
F ext/wasm/api/sqlite3-opfs-async-proxy.c-pp.js 25e31482b04293a33d7599f1459eb552b3eb36ca10c02c816122d3308bf80cb2
@@ -630,7 +631,7 @@ F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b
F ext/wasm/jaccwabyt/jaccwabyt.md 6aa90fa1a973d0ad10d077088bea163b241d8470c75eafdef87620a1de1dea41
F ext/wasm/libcmpp.c 0e2cec7de7c9cbe7941e6a4dc0c123cec736578a3eeae7828ac18706acd3cea6
F ext/wasm/mkdist.sh f8883b077a2ca47cf92e6f0ce305fbf72ca648c3501810125056c4b09c2d5554 x
F ext/wasm/mkwasmbuilds.c d4479af2774a43104b819d9286961b7c09793ca39440e20191e693ceff21f911
F ext/wasm/mkwasmbuilds.c 60706fb66db7f1e24d876e3cb2493484cfb27e7b103c7741c384505dd678769c
F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
@@ -646,7 +647,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.c-pp.html 7171022e7f4da8f46e5f50ea81dd6ce840b9235c47653a5deeb3764ccc2fe472
F ext/wasm/tester1.c-pp.html bd927ccf51ddd65e924660a0487add99e1b044afe03950e49d87ccf44efdddb6
F ext/wasm/tester1.c-pp.js 581be6f3228351bc77512ba743912d1ad52f40dde1fef1a943fd568b0cfc51b1
F ext/wasm/tester1.c-pp.js 54ce4a08d3752cb52cf60926d7da47a21ae63d620f90679770dd9c04002722b4
F ext/wasm/tests/opfs/concurrency/index.html 706eab6308343c04ac2360aba6001af4ffaf46d8f33a0ccd02c64d93e3216a43
F ext/wasm/tests/opfs/concurrency/test.js 6919778fceaac1b7cc78caf41d796f545d2c4433b31188aa9689f05b5ad28828
F ext/wasm/tests/opfs/concurrency/worker.js 704d82c5e287e47f612349e027765943a58ad967dcf178fb5a1c3a8eaafb09af
@@ -656,7 +657,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk bf77c630aeef4ed4b9270e1fd52c35147b529412c00b74ed6eb8aca3466763f6
F main.mk 582cb3ab67cb5b8887c087265e700f7a132dace4316e1656419e8e4c049ba683
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -667,14 +668,14 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
F src/alter.c fc36b19273ffe364aeb4d00ba04bda8798ad7a67fec7a035ee8ee56272e1bdbe
F src/alter.c d7cbe4332a7a2c3a21ab58ee2609efade493f6ae78254613ada0759898629ee3
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
F src/attach.c 7cf07d4fa42b9fc8662237c60c40b730326c30aa90ae5fffc0b18b2d726ebf61
F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338
F src/auth.c ebec42df26b34a62b6750d30d9c2c03554a1c522020182476f7729a439fef04f
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c fb350c445316c1cc0529703c0b76450770a1de0ab0440641a56b19f05d6fefbe
F src/btree.c 377b98fbe170ae38298a3fcea5355ec88404f63238f80741992cda765ac91aeb
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c 8581de0af3b6c448f5d64e2d18a91ac1e7057b3bcb8b8827e1240f80d87486a4
@@ -682,20 +683,20 @@ F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804a
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
F src/dbpage.c 98c716bc5c0c70af4e7934bfcddd707f14e78b5d4cf1e0602a07b485e1af2e74
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 1f2268d6fe3c78fc1bf794ba65d7026498b78e2342ffaf85825dedae546e6fde
F src/expr.c 51e9c77ff5d9a21439e611fe6571a3cd50387e526e13c5614fd407e5b8571930
F src/expr.c 8a458928fe502526d4ce90fa4e084a6e1a4dceb6da747381973b5b0086b1492c
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
F src/func.c 706ac012bf87d8ad7416a56a1d2b1f19e5dea03506a4606a01aa9d3bacf392c7
F src/func.c 6f6abe78831fba92ebb5c3d347273f37656ae357f5902e1fb48aa297d57fbcc6
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
F src/json.c 5027b856cd9b621dc9ba66b211e21a440ccdc63cefdefb44c51e7d3ac550d1a4
F src/json.c 82b685636c9ff9d677734682e170f637fbfef3a14febf8cb274c4b7e7a272dcc
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
F src/main.c 387bb9d0216d6d35b221481ba8e661d94ad043060cd89581b6422c269ce680a0
@@ -705,7 +706,7 @@ F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
F src/memdb.c a3feb427cdd4036ea2db0ba56d152f14c8212ca760ccb05fb7aa49ff6b897df3
F src/memdb.c 0a0e827311cec57fdea2ed3142d6684704a1b90e7995b286f74fd7d1a6c5a62c
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
F src/mutex.c 00b8cee206a67fd764d001f3a148494331d8d0b3b9c3974ecd69ff29bb444462
@@ -719,27 +720,27 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
F src/os_unix.c fa5e09b4df35ad845440cad67b86908cfe1fd4c28c51915f82e23633d1992bf4
F src/os_win.c 0d553b6e8b92c8eb85e7f1b4a8036fe8638c8b32c9ad8d9d72a861c10f81b4c5
F src/os_unix.c 92a1773139e0c6206a927c7e1648b06287583570b6e253210a06ee3886739d39
F src/os_win.c 938805c15e855819cb0874aea560c3a7250175d311a5494b47a4f8b69dcd59c0
F src/os_win.h 5e168adf482484327195d10f9c3bce3520f598e04e07ffe62c9c5a8067c1037b
F src/pager.c fe34fd22ec251436985d7b6ebdd05bf238a17901c2cb23d3d28974dd2361a912
F src/pager.c 5e98a67fad5e33c9588460c42063859d22aca8d3140865fd411056dd360b26c2
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y 3b784d6083380a950e3b1b32ce5ddd303e8c7c209d8ab788df2c62aaf9ee8eb3
F src/parse.y d5a3c5b0277a441c38b35071c05e2b61ff5fc918a63309c809f4b6706179c320
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
F src/printf.c 41fb76fcb5ed7e16aaddc659d3b23891abebea45549fe125fc2e6ec380cc7175
F src/printf.c ed43bcd6b551b590e47b905115aa1c35504267f532680590102e79894230a06b
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
F src/resolve.c f5a780a7b604d43b78bca290cace7479bca0c7d8ef9ce855830d9498b975baec
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
F src/shell.c.in a3288615aba1b375f7dca9801874c806e8d0d047dfe4e9253a944f4b47c7459e
F src/select.c 5c3a5e3c1e6c3f8ccabeb414e18dce64e6f3e797de225ee93034f2c9e76f289c
F src/shell.c.in cbb7ae029cea6d8789924d9009574081b4f3c0619ce736ed36e8c7564ef13547
F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
F src/sqliteInt.h bc1cbc0c23dba35b324ae85a7dbb5fb182321bbd30857fb21f3d0cba049001a5
F src/sqliteInt.h 9f152ad54b9ce85040365b96eb6d2a985146dc760bb295cc645f48d38100ad85
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -799,7 +800,7 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 4f0abc15f63829e12cdfeeb490faf25ac65894b0bcc20d660e3f3757b8e2360b
F src/util.c 2053344769bc602b2c23ce193f4d24f89777ab67fa768b80fa197d3876dc3017
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
@@ -816,10 +817,10 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
F src/wal.c 7340d4f9bb827bd349127cac6b2cf0cb7f76b9fda645f7b9b0bf7a6e0b1e2e7c
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c bffca5e4ef20d0bfbdc24f1dc13fd3f955284225a8ad25a4454635f6be39aad0
F src/where.c a1caeb656f74e58de7e7310ee91c6dfb40e975c7dd9b18e61a965aea46a610f2
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
F src/wherecode.c 676cb6cb02878643e817d9917a2d3522b83a3736b2cedd3dc8a01d7bb92af6c2
F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
F src/wherecode.c bc39ccbe3648f01157038b16cc55bdbff128590972b7185521b5526dc2815765
F src/whereexpr.c 61b1c9d98d39f6bcd79fcb4ebb4c9478effb259fefac4c7d3e78e4957f97f75a
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
@@ -837,8 +838,8 @@ F test/alter4.test 37cafe164067a6590a0ee4cec780bddbbaa33dc50b11542dcfbe0e6562649
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
F test/alterauth2.test 4b74fa8f184f4736497317feb587b65759eb87d87acfe3a8ef433d4d18bb002b
F test/altercol.test 3661c432aacb42bc2198dd4611bbb9c3b09fc73251b59edda046109103b8ac00
F test/altercons.test ea18def4a0f26b9066da56095c9c480df705df4d02e4ae151708fae76f7e3884
F test/altercons2.test 3c1f58312817df43aeada3b1827fdc3ce3fc50c6f49a95ef62cf4cbbae8583a0
F test/altercons.test 9b036a956268eccd64761a6af3ab6f7b313c738392c7460b747d8aacd32589a2
F test/altercons2.test 4933eadb035fc0ccfc34ed879f69a09051c53907f9dae9c3d36d25f93519ccc7
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
@@ -914,7 +915,7 @@ F test/bestindex8.test 4d8b1e8f30a7f405988ce4dbcc2b95c0775f0bed9ec08e0291a07e2f3
F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
F test/bestindexB.test 14db2f66ec9cc5064a74996033b74e5eec0fd2f3a327fbe34ff18de67e9d2671
F test/bestindexC.test 95b4a527b1a5d07951d731604a6d4cf7e5a806b39cea0e7819d4c9667e11c3fc
F test/bestindexC.test f44eb3d77359e9487222a2dde27f8ecf11a8e4932803c0dd9477f75e114f1c55
F test/bestindexD.test 6a8f6f84990bcf17dfa59652a1f935beddb7afd96f8302830fbc86b0a13df3c3
F test/bestindexE.test 297f3ea8500a8f3c17d6f78e55bdfee089064c6144ee84a110bd005a03338f49
F test/bestindexF.test 4e53d606cbde40a2254aa016d500c5b71766a4065b8541202d195a3d9fe11b1c
@@ -943,6 +944,7 @@ F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1
F test/btreefault.test a82a23b0578bc587afbf9a622c8f54a54f63762f062ba8a35613cfee38ab42f9
F test/busy.test caff7164c16ce06a53af51f9e4c2753d4cc64250e00790a5e48b9c4f4be37597
F test/busy2.test 20823a5d7c42fb257d9f108c66312d90b1bb4ec3d80ba6b4e371073727560f98
F test/c/changeblob1.c c2f51ff87ed628634badfe635d987c21ffcc6a03554a29bff7f68607e6deb9ab
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
@@ -952,7 +954,7 @@ F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test 31d3a6778f2d06f2d9222bd7660c41a516d1518a059b069e96ebbeadb5a490f7
F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/carray01.test 17c1cf8287862b15dda949dba626fd5fee5c58471dcc1cae0341471c2ae7da01
F test/carray01.test 4a77d9f5711212bd209598913405d36dd48cc4f5f643e78cf589daa4d3047c54
F test/carray02.test 9d070b54f24a34d1f3b3c552ba34db0375a9d1c4219067416fb07d1595987c9d
F test/carrayfault.test 108a7d83904fc267c448e27c13b2a857c700bd6ddaa2f1e2518be718b159cb6b
F test/cast.test a2a3b32df86e3c0601ffa2e9f028a18796305d251801efea807092dbf374a040
@@ -1039,7 +1041,7 @@ F test/dbfuzz001.test 6c9a4622029d69dc38926f115864b055cb2f39badd25ec22cbfb130c8b
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
F test/dblwidth-a.sql 59dd59aa78ce8fd8ab631a3816516831f4e947b143039257e6fe132c3cea4171
F test/dbpage.test 63fab1eb026bada121107e53436fa749bbf83281dc9dea17af422f7a5c0f289f
F test/dbpage.test 2e3a50548edea551ef974b8f121f975852de9c5b16cb3284ac4bf2c9f2ed5a62
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test a36518c0f0951d8fd5a3dc36f99948ad1af93fb7fc0d2e03e5bb5a643186cf52
@@ -1097,7 +1099,7 @@ F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650
F test/exclusive2.test cd70b1d9c6fffd336f9795b711dcc5d9ceba133ad3f7001da3fda63615bdc91e
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/existsexpr.test 75c1c13cda18b53f68c135fe644afc034d72a6de5b0774b0219ca4a6dc4b96b0
F test/existsexpr.test 1ce70ac41fb6d52525774388aa23e982428e883a850f9d56d49776d234865552
F test/existsexpr2.test dc23e76389eff3d29f6488ff733012a3560cd67ec8cfaecbecd52cced5d5af11
F test/existsfault.test ff41c11f3052c1bbd4f8dd557802310026253d67d7c4e3a180c16d2f0862973e
F test/expr.test db981f8a85520e99ae20aab7ad2e9b5b0437ed09159b57ced434c672075d2e61
@@ -1164,7 +1166,7 @@ F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cd
F test/fts3corrupt4.test c7f414fe29b97a478d15c90382c4ae077a2bbd2283bf8c63bf66dadaaed3edb8
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
F test/fts3corrupt6.test f417c910254f32c0bc9ead7affa991a1d5aec35b3b32a183ffb05eea78289525
F test/fts3corrupt7.test 1da31776e24bb91d3c028e663456b61280b121a74496ccf2fef3fe33790ad2b0
F test/fts3corrupt7.test 93622a4336b161a733accbd66311d93749660243cdda268fd647c21e1e680770
F test/fts3cov.test 1e5ecea0e4c1394cea97adcfb9fd3d2d5998fd563dacf465f413e6c7fa5cffb3
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
@@ -1316,7 +1318,7 @@ F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
F test/intck01.sql f2d88bf41cdd64f2ed8c3d4f357cf520f017aa2986999ab9a62eb6506ef18106
F test/interrupt.test ac1ef50ec9ab8e4f0e17c47629f82539d4b22558904e321ed5abea2e6187da7a
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
F test/interrupt2.test 7eaa40a975d950826cd56e6c37f0f0629adfa2d1a8d3333aff0ff7cf86069963
F test/intpkey.test 7d54711acf553cdd641a40e9c6cfc2bf1a76070074940c1b126442517054320f
F test/intreal.test 68829a8bb073ee1610ca3f8f9e0f99b0371fb36e0fa64862dd5ced4ef03c2343
F test/io.test d267fdc8915444a45e19841489033ebe70bb69f6db605b00df70be16b2a80f59
@@ -1343,7 +1345,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test 1d2fc3190be68525fd9ce749b9468c40ba2930181e52fb5ee6f836051b38effb
F test/joinI.test a4d37143fcc39e915d9feb08e614a13f88dfe332d77152a3c526a2370ddb9a70
F test/joinI.test f5e8613c3262f056c56249cc98255bf5fa1a764d7667b8ceb9fe08b4c965f061
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
@@ -1355,7 +1357,7 @@ F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd286
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
F test/json/json-speed-check.sh 45862b216f1f8bbf16d74e2ad6ea20c773ee77774b299a7e0f76a22eb98e91f1 x
F test/json/jsonb-q1.txt 1e180fe6491efab307e318b22879e3a736ac9a96539bbde7911a13ee5b33abc7
F test/json101.test cf53254f0f0c1399a01b21fc58fee0e63a12a556be91b9ee9faccdb8b82c083c
F test/json101.test 34109fe1bfa384774ceea2a174de00e0b77e8a7b586bf30bdc9a60d7377ed15b
F test/json102.test ea5c9811e408e115c8fc539548deef431fda4924c23cacd79dd4b783f4449f07
F test/json103.test e626d109cd0bdb8282ec9bf755af3befa50e3e03a255362fc53433d31e1d66d4
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
@@ -1420,7 +1422,7 @@ F test/malloctraceviewer.tcl 3e3ddf11e30d2b20f53aa16aa6615082fb24a100bea61cca721
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
F test/memdb1.test c737ac9aa5895092332b1dde24fae7ae494b7fcbcd346d22d600891096a3836d
F test/memdb1.test 916093ae5ad097660a742890a9986d1f217a620ac95efb64884041ee4c408603
F test/memdb2.test 4ba1fc09e2f51df80d148a540e4a3fa66d0462e91167b27497084de4d1f6b5b4
F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c
F test/memjournal2.test dbc2c5cb5f7b38950f4f6dc3e73fcecf0fcbed3fc32c7ce913bba164d288da1e
@@ -1441,7 +1443,7 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test d595599972ec0b436985f0f02f243b68500ffc977b9b3194ec66c0866cfddcab
F test/misc8.test 08d2380bc435486b12161521f225043ac2be26f02471c2c1ea4cac0b1548edbd
F test/misuse.test 859f37014d9824ca66bd90c36372c08c80c51c9593a7cfa8a31d4f92cd4d5b7f
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mjournal.test 3570ca4241b0d19ca1f47616f5293722f7c2fc9f2d359fc7933d67ef51dc2137
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
F test/mmap2.test dba452dc7db91e9df10f70bdd73dc4190c7b8ee7b5133b4684f04277ada0b9ac
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
@@ -1449,7 +1451,7 @@ F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
F test/mmapcorrupt.test 470fb44fe92e99c1d23701d156f8c17865f5b027063c9119dcfdb842791f4465
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
F test/modeA.sql fc64f646b0a1d0806af122fad6db2c89de63c51106655c09d44a652052a14d05
F test/modeA.sql 859e608297646e2d573e431507f38e465bc1513fa5862916ec8fb20a1d6314a4
F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
F test/multiplex3.test fac575e0b1b852025575a6a8357701d80933e98b5d2fe6d35ddaa68f92f6a1f7
@@ -1467,7 +1469,7 @@ F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed
F test/notnull2.test c2c7b670fb8fa6ffe5f9cc08af88864fbb8237e28b56ad528e8dee921019c5fe
F test/notnullfault.test fc4bb7845582a2b3db376001ef49118393b1b11abe0d24adb03db057ee2b73d5
F test/null.test b7ff206a1c60fe01aa2abd33ef9ea83c93727d993ca8a613de86e925c9f2bc6f
F test/nulls1.test 7a5e4346ee4285034100b4cd20e6784f16a9d6c927e44ecdf10034086bbee9c9
F test/nulls1.test 8fc70d75ab363b0f2ce9151669c2cb897def5064e2e30f7d9322970480bf6e87
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
F test/offset1.test c21e67d2d5ae8ed310243fbe84fc2f0dca49e9ffed3ea89110c0d5914c0de620
@@ -1503,7 +1505,7 @@ F test/parser1.test 131f4733472252d53d8ed681115257866f55740ab697fa05900d76604934
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
F test/percentile.test eaee1ff3e35d5fe933ac98d927c9a7d2f4f1a1a19ee22e7d45e97a6d9ee32077
F test/percentile.test fd78896fa882fa4fbf693640097859721f3629926c2ccf804af5bcb7001fd35b
F test/permutations.test e6de4f5777f7785737ac3d1d964b8656e5477a134665b2fe8a91884ab9b685b3
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 7d07b7bb76e273215d6a20c4f83c3062cc28976c737ccb70a686025801e86c8f
@@ -1513,13 +1515,13 @@ F test/pragma4.test 396ef9bff1fb966d41721545ad4b12bfc26aae315f5fe51d9b917828d49e
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
F test/prefixes.test fe52bb0c2fee10fb9b918a095d443ebf31dd48e5e2c7a1b21feba594fe7ff2d0
F test/printf.test bcb093ef5cbd17e2d94d93d62045ee61ed0f465c1ca123f284774e474e73a9ea
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/pushdown.test 46a626ef1c0ca79b85296ff2e078b9da20a50e9b804b38f441590c3987580ddd
F test/qrf01.test 09caa00e6b4deea5fcd8958b4062233fcef5ef1b354312ec956ec4bc3a09572a
F test/qrf01.test 0b5095dfc841eaa12806fe20fc0ede72573885390b3152edc0edb66378fb55f7
F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92
F test/qrf03.test e7efe46d204671726b4707585126cd78d107368de4a7d0c7b8d5157cdd8624ed
F test/qrf04.test 0894692c998d2401dcc33449c02051b503ecce0c94217be54fb007c82d2d1379
@@ -1554,7 +1556,7 @@ F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190c
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test d27191b5ce794c05bf61081e8b2c546a1844c1641321dcaf7fb785234256cc8e
F test/rowvalue.test 93474d8e1c496e970bdcc3a7f54ac835adda667d2fd971957b4bce0c0b11707b
F test/rowvalue.test ba43ff378f78c81579dd0f9f2b1e92876d29fb767f090acb7d4cbc6ff4a3c42c
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 103e9a224ca0548dd0d67e439f39c5dd16de4200221a333927372408c025324c
F test/rowvalue4.test 6e160977d44ee715e142f63ec0e339586c61f12bbbffacee369b1cdc0b7390f0
@@ -1563,7 +1565,7 @@ F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
F test/rowvalue7.test 06ec0aca725bf683313d03793aa2943bc7f45a901848c7056a9665b769c8fc38
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
F test/rowvalue9.test 7499a8fd7ca3a3f0e19d94e135355439aa2b596f86b775ca8de79672da2ca378
F test/rowvalueA.test 7d28bf6c2f8a2af8adbba2c4eda9136a4dd36250b8966ba05b34c0954f78efd7
F test/rowvalueA.test 5849865659f27ec50ba3185b2e18928a92077ceddf121ee6b95bf32300d44c91
F test/rowvaluefault.test 963ae9cdaed30a85a29668dd514e639f3556cae903ee9f172ea972d511c54fff
F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
@@ -1669,7 +1671,7 @@ F test/speedtest1.c 6c01252e66f46de0b6b8d5316e03521e2151782104f3608c10262aa5dce8
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
F test/spellfix4.test 7c56a09de68b95051ef0627fe235e514efbba2aa816dc2a9c5c670d98877e632
F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb
F test/sqllimits1.test 408131e4975d61868711c83f101a56d4602313cc5cae88d3eee81c1da364fd89
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
@@ -1687,7 +1689,7 @@ F test/subquery.test 23087f9b1c15ab9cc5231d04946bdebc51db527c95eb9d7434a2222127e
F test/subquery2.test ab96ff3fa9c4e3dce0d699f74e61c50250ed4335bc8f400e127707d552a8999e
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
F test/subtype1.test 96fd2a59bfc845c955b5f339d23b37ef4d50de5f8a04acd1450a68605fa2e3e7
F test/subtype1.test 1ca002dbda34c342c2dee7cffac220b77d67edfbffd43124978956747f534a96
F test/superlock.test 85256830339a6871ce36a2ef591c3f67716a701b5497788fb2068b90159c2442
F test/swarmvtab.test 250231404fcac88f61a6c147bb0e3a118ed879278cd3ccb0ae2d3a729e1e8e26
F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
@@ -1699,7 +1701,7 @@ F test/sync.test a619e407ede58a7b6e3e44375328628559fc9695a9c24c47cb5690a866b0031
F test/sync2.test 06152269ed73128782c450c355988fe8dd794d305833af75e1a5e79edd4dae47
F test/syscall.test a067468b43b8cb2305e9f9fe414e5f40c875bb5d2cba5f00b8154396e95fcf37
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test cfa96a9a235c39fb0cae69928b989b28bfec108f62d2533486f76e32dcedfdfb
F test/tabfunc01.test 7827c2dfd57a094125b059f51a2200eaf04d417af6b1e720c34a8cbf54e8a14f
F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1714,7 +1716,7 @@ F test/temptrigfault.tes fc5918e64f3867156fefe7cfca9d8e1f495134a5229b2b511b0dc11
F test/temptrigger.test a00f258ed8d21a0e8fd4f322f15e8cfb5cef2e43655670e07a753e3fb4769d61
F test/tester.tcl 2d943f60200e0a36bcd3f1f0baf181a751cd3604ef6b6bd4c8dc39b4e8a53116
F test/testloadext.c 862b848783eaed9985fbce46c65cd214664376b549fae252b364d5d1ef350a27
F test/testrunner.tcl 6b232f0d4825dec8b967754503080fc9609fad077f582d02f86bd2d95bec4110 x
F test/testrunner.tcl 8d92cacf9989aefdf33229c414adac56d389b5b6d9d31d9ebed34d5ab4e13833 x
F test/testrunner_data.tcl 48c8a230fcada37f4809f95c2ba49e44bc3d520b6165c09173249c6e65b01cc1
F test/testrunner_estwork.tcl 81e2ae10238f50540f42fbf2d94913052a99bfb494b69e546506323f195dcff9
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
@@ -1884,7 +1886,7 @@ F test/trace3.test 2deeac66359c9f007f0fc9fb6336994a5d68fc1a65129f322a9e9546fd537
F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
F test/transitive1.test f8ee983600b33d167da1885657f064aec404e1c0d0bc8765fdf163f4c749237a
F test/transitive1.test d6252d06ddc104d13372fce0da93af501546bf5d75cb4d2a1f83b8c27238997a
F test/trigger1.test 141bd2bbfa82fa91aed7391f50517373c9823ff8f55af35e56313dbc75112ca1
F test/trigger2.test 30fcb3a6aa6782020d47968735ee6086ed795f73a7affa9406c8d5a36e7b5265
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
@@ -1922,7 +1924,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d2366ef2d3d95249314307861d748924d9ab4f24305541159a08be61ccd4a9ee
F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2
F test/update.test 258dcf26d401177d3cb7fdf0beab14d671dbe72e8ff6e0435fd85a08fcd57bd9
F test/update.test 93fba5f7505f7a7b25d66135d98d9b055b7f1bd627a7e514dbba1ea6213f0c41
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
@@ -2026,7 +2028,7 @@ F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9
F test/walthread.test d562f51a61191ccfab64940df7aa1cef87c902fa5ab742590ef7f859dfe6a44b
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
F test/where.test 5087c72d26fd075a1644c8512be9fe18de9bf2d2b0754f7fd9b74a1c6540c4fc
F test/where2.test 1dbff4ab847068a52b927a0c1a7cf7faed4c8cae081fbcdac9b052a3a209aefa
F test/where2.test b73f8ee8f94b850764c429efe2d48171090628737dcc3df64a9f2214da02089f
F test/where3.test 4ccb156ae33de86414a52775a6f590a9d60ba2cbc7a93a24fa331b7bcf5b6030
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
@@ -2073,10 +2075,10 @@ F test/window8.tcl c57364e64d816f6e26df60437e1202e2c1031c7b818a1a67535d1006862a0
F test/window8.test 3d931e58802b8ab8063da00f0cf30aa3351640238a952c0efb5a129e2349a4bb
F test/window9.test 7b98a7916dd87763ea35f56ea023e3b29e99744582204ccf2937a3bac411cd4d
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf
F test/windowB.test bba3bee77c1d3321077ff8951d543161d74f08f78633d84433ced7d6261dc2c2
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b
F test/windowE.test d045a5fbaaf50ecac9483e1249dd317ba4f9d189c405a730ba6effdefb87b94f
F test/windowE.test a82a4213c7b923220de5e457cb76c537a5d10d5e94641e3055ba21b79870a7fb
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
@@ -2100,7 +2102,7 @@ F test/writecrash.test 13520af28f376bfc8c0bcd130efc1fff20bb165198e8b94cf153f1f75
F test/zeroblob.test 7b74cefc7b281dfa2b07cd237987fbe94b4a2037a7771e9e83f2d5f608b1d99e
F test/zeroblobfault.test 861d8191a0d944dfebb3cb4d2c5b4e46a5a119eaec5a63dd996c2389f8063441
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
F test/zipfile.test a3fcfc43115e4226fdddadd43bdf31c8ca805ad08dad435634f1633d8f5840d9
F test/zipfile.test 7b5c2f43ce9f7c882237e74822a331d94f4f83891e7a64c503519b434d06a5bf
F test/zipfile2.test 21afaffcf4f7769df38bf16e4a9c4dfa6ba1b0f5b695f844ec61fafb92db0db7
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
@@ -2108,7 +2110,7 @@ F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e045
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/build-all-msvc.bat 1ee9dbadcc07fc23268025854e97b392bcbad72376b47aee7b22f3797a4f2c87 x
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
F tool/buildtclext.tcl d09b753d7858314104eeaf5f4def85d35784470279809e47a633f142226f2b3f
F tool/buildtclext.tcl b58df93e772fec8b2ae44ee1a82d13378e13edb1e94c4ab2f7ee3440a9523bff
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca
@@ -2178,7 +2180,7 @@ F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
F tool/sqldiff.c 847edc1e0d1e1feb652d3d6128e504456deaf254ab9ad3e7cebd4317d2037182
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
F tool/sqlite3_rsync.c f510a8b230e1c5b0f62842acd0e94ff15d2f77a00ae782f7d20f9e39919fa19b
F tool/sqlite3_rsync.c d9ce999e5b3aa9f36de44b321755622e52258774889bd804ba56f00eca01af50
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F tool/src-verify.c 6c655d9a8d6b30f3648fc78a79bf3838ed68f8543869d380c43ea9f17b3b8501
@@ -2197,11 +2199,10 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P cda5dd9bcbef2135bb9855139a11d0e22a092f9498d82eb18e7d4401264b6eb8
R 78f8c181262c6bdd7ab10b5492ff03ea
T +sym-major-release *
P ac00a18dcf132180295d41299f31fbc68087a27b61782d00b9633dd9661ded2b
R 58c568d42a018658d9c21e84f3d9ab9d
T +sym-release *
T +sym-version-3.53.0 *
T +sym-version-3.53.2 *
U drh
Z 5cc2d306947f7e965f5f798b08602c26
Z a64dcb64a02448f95d399730d70f1fe2
# Remove this line to create a well-formed Fossil manifest.
+3 -4
View File
@@ -1,5 +1,4 @@
branch trunk
tag trunk
branch branch-3.53
tag release
tag major-release
tag version-3.53.0
tag branch-3.53
tag version-3.53.2
+1 -1
View File
@@ -1 +1 @@
4525003a53a7fc63ca75c59b22c79608659ca12f0131f52c18637f829977f20b
d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24
+19 -5
View File
@@ -2798,7 +2798,9 @@ void sqlite3AlterDropConstraint(
if( !pTab ) return;
if( pCons ){
zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z);
char *z = sqlite3NameFromToken(db, pCons);
zArg = sqlite3MPrintf(db, "%Q", z);
sqlite3DbFree(db, z);
}else{
int iCol;
if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
@@ -2985,19 +2987,31 @@ void sqlite3AlterAddConstraint(
SrcList *pSrc, /* Table to add constraint to */
Token *pFirst, /* First token of new constraint */
Token *pName, /* Name of new constraint. NULL if name omitted. */
const char *pExpr, /* Text of CHECK expression */
int nExpr /* Size of pExpr in bytes */
const char *zExpr, /* Text of CHECK expression */
int nExpr, /* Size of pExpr in bytes */
Expr *pExpr /* The parsed CHECK expression */
){
Table *pTab = 0; /* Table identified by pSrc */
int iDb = 0; /* Which schema does pTab live in */
const char *zDb = 0; /* Name of the schema in which pTab lives */
const char *pCons = 0; /* Text of the constraint */
int nCons; /* Bytes of text to use from pCons[] */
int rc; /* Result from error checking pExpr */
/* Look up the table being altered. */
assert( pSrc->nSrc==1 );
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
if( !pTab ) return;
if( !pTab ){
sqlite3ExprDelete(pParse->db, pExpr);
return;
}
/* Verify that the new CHECK constraint does not contain any
** internal-use-only function. Forum post 2026-05-10T01:11:28Z
*/
rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0);
sqlite3ExprDelete(pParse->db, pExpr);
if( rc ) return;
/* If this new constraint has a name, check that it is not a duplicate of
** an existing constraint. It is an error if it is. */
@@ -3018,7 +3032,7 @@ void sqlite3AlterAddConstraint(
sqlite3NestedParse(pParse,
"SELECT sqlite_fail('constraint failed', %d) "
"FROM %Q.%Q WHERE (%.*s) IS NOT TRUE",
SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr
SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr
);
/* Edit the SQL for the named table. */
+11 -2
View File
@@ -106,6 +106,16 @@ static void attachFunc(
** from sqlite3_deserialize() to close database db->init.iDb and
** reopen it as a MemDB */
Btree *pNewBt = 0;
pNew = &db->aDb[db->init.iDb];
assert( pNew->pBt!=0 );
if( sqlite3BtreeTxnState(pNew->pBt)!=SQLITE_TXN_NONE
|| sqlite3BtreeIsInBackup(pNew->pBt)
){
rc = SQLITE_BUSY;
goto attach_error;
}
pVfs = sqlite3_vfs_find("memdb");
if( pVfs==0 ) return;
rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB);
@@ -115,8 +125,7 @@ static void attachFunc(
/* Both the Btree and the new Schema were allocated successfully.
** Close the old db and update the aDb[] slot with the new memdb
** values. */
pNew = &db->aDb[db->init.iDb];
if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt);
sqlite3BtreeClose(pNew->pBt);
pNew->pBt = pNewBt;
pNew->pSchema = pNewSchema;
}else{
+9 -1
View File
@@ -5185,7 +5185,9 @@ static int accessPayload(
** means "not yet known" (the cache is lazily populated).
*/
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
i64 nOvfl = pCur->info.nPayload;
testcase( nOvfl - pCur->info.nLocal + ovflSize - 1 > 0xffffffffU );
nOvfl = (nOvfl - pCur->info.nLocal + ovflSize-1)/ovflSize;
if( pCur->aOverflow==0
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
){
@@ -5290,6 +5292,12 @@ static int accessPayload(
(eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
if( eOp!=0
&& (sqlite3PagerPageRefcount(pDbPage)!=1
|| NEVER(((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit)) ){
sqlite3PagerUnref(pDbPage);
return SQLITE_CORRUPT_PAGE(pPage);
}
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
+3 -2
View File
@@ -259,12 +259,13 @@ static int dbpageFilter(
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
if( idxNum & 1 ){
i64 iPg = sqlite3_value_int64(argv[idxNum>>1]);
assert( argc>(idxNum>>1) );
pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
if( iPg<1 || iPg>pCsr->mxPgno ){
pCsr->pgno = 1;
pCsr->mxPgno = 0;
}else{
pCsr->pgno = (Pgno)iPg;
pCsr->mxPgno = pCsr->pgno;
}
}else{
+34 -14
View File
@@ -4262,7 +4262,16 @@ static void sqlite3ExprCodeIN(
CollSeq *pColl;
int r3 = sqlite3GetTempReg(pParse);
p = sqlite3VectorFieldSubexpr(pLeft, i);
pColl = sqlite3ExprCollSeq(pParse, p);
if( ExprUseXSelect(pExpr) ){
Expr *pRhs = pExpr->x.pSelect->pEList->a[i].pExpr;
pColl = sqlite3BinaryCompareCollSeq(pParse, p, pRhs);
}else{
/* If the RHS of the IN(...) expression are scalar expressions, do
** not consider their collation sequences. The documentation says
** "The collating sequence used for expressions of the form "x IN (y, z,
** ...)" is the collating sequence of x.". */
pColl = sqlite3ExprCollSeq(pParse, p);
}
sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
(void*)pColl, P4_COLLSEQ);
@@ -4685,26 +4694,37 @@ static int exprCodeInlineFunction(
}
/*
** Expression Node callback for sqlite3ExprCanReturnSubtype().
** Expression Node callback for sqlite3ExprCanReturnSubtype(). If
** pExpr is able to return a subtype, set pWalker->eCode and abort
** the search. If pExpr can never return a subtype, prune search.
**
** Only a function call is able to return a subtype. So if the node
** is not a function call, return WRC_Prune immediately.
** The only expressions that can return a subtype are:
**
** A function call is able to return a subtype if it has the
** SQLITE_RESULT_SUBTYPE property.
** 1. A function
** 2. The no-op "+" operator
** 3. A CASE...END expression
** 4. A CAST() expression
** 5. A "expr COLLATE colseq" expression.
**
** Assume that every function is able to pass-through a subtype from
** one of its argument (using sqlite3_result_value()). Most functions
** are not this way, but we don't have a mechanism to distinguish those
** that are from those that are not, so assume they all work this way.
** That means that if one of its arguments is another function and that
** other function is able to return a subtype, then this function is
** able to return a subtype.
** For any other kind of expression, prune the search.
**
** For case 1, the expression can yield a subtype if the function has
** the SQLITE_RESULT_SUBTYPE property. Functions can also return
** a subtype (via sqlite3_result_value()) if any of the arguments can
** return a subtype.
**
** In all cases 1 through 5, the expression might also return a subtype
** if any operand can return a subtype.
*/
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
int n;
FuncDef *pDef;
sqlite3 *db;
if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS
|| pExpr->op==TK_COLLATE || pExpr->op==TK_CAST
){
return WRC_Continue;
}
if( pExpr->op!=TK_FUNCTION ){
return WRC_Prune;
}
@@ -4714,7 +4734,7 @@ static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
pWalker->eCode = 1;
return WRC_Prune;
return WRC_Abort;
}
return WRC_Continue;
}
+60 -47
View File
@@ -326,9 +326,18 @@ static void printfFunc(
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
str.printfFlags = SQLITE_PRINTF_SQLFUNC;
sqlite3_str_appendf(&str, zFormat, &x);
n = str.nChar;
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
SQLITE_DYNAMIC);
if( str.accError==SQLITE_OK ){
n = str.nChar;
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
SQLITE_DYNAMIC);
}else{
if( str.accError==SQLITE_NOMEM ){
sqlite3_result_error_nomem(context);
}else{
sqlite3_result_error_toobig(context);
}
sqlite3_str_reset(&str);
}
}
}
@@ -1966,11 +1975,16 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
assert( p->cnt>0 );
p->cnt--;
if( !p->approx ){
if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
p->ovrfl = 1;
p->approx = 1;
i64 x = p->iSum;
if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
p->iSum = x;
return;
}
}else if( type==SQLITE_INTEGER ){
p->ovrfl = 1;
p->approx = 1;
kahanBabuskaNeumaierInit(p, p->iSum);
}
if( type==SQLITE_INTEGER ){
i64 iVal = sqlite3_value_int64(argv[0]);
if( iVal!=SMALLEST_INT64 ){
kahanBabuskaNeumaierStepInt64(p, -iVal);
@@ -2942,47 +2956,46 @@ static void percentSort(double *a, unsigned int n){
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
int i; /* Loop counter */
double rPivot; /* The pivot value */
assert( n>=2 );
if( a[0]>a[n-1] ){
SWAP_DOUBLE(a[0],a[n-1])
}
if( n==2 ) return;
iGt = n-1;
i = n/2;
if( a[0]>a[i] ){
SWAP_DOUBLE(a[0],a[i])
}else if( a[i]>a[iGt] ){
SWAP_DOUBLE(a[i],a[iGt])
}
if( n==3 ) return;
rPivot = a[i];
iLt = i = 1;
do{
if( a[i]<rPivot ){
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
iLt++;
i++;
}else if( a[i]>rPivot ){
do{
iGt--;
}while( iGt>i && a[iGt]>rPivot );
SWAP_DOUBLE(a[i],a[iGt])
}else{
i++;
}
}while( i<iGt );
if( iLt>=2 ) percentSort(a, iLt);
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
/* Uncomment for testing */
#if 0
for(i=0; i<n-1; i++){
assert( a[i]<=a[i+1] );
}
#endif
}
while( n>=2 ){
if( a[0]>a[n-1] ){
SWAP_DOUBLE(a[0],a[n-1])
}
if( n==2 ) return;
iGt = n-1;
i = n/2;
if( a[0]>a[i] ){
SWAP_DOUBLE(a[0],a[i])
}else if( a[i]>a[iGt] ){
SWAP_DOUBLE(a[i],a[iGt])
}
if( n==3 ) return;
rPivot = a[i];
iLt = i = 1;
do{
if( a[i]<rPivot ){
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
iLt++;
i++;
}else if( a[i]>rPivot ){
do{
iGt--;
}while( iGt>i && a[iGt]>rPivot );
SWAP_DOUBLE(a[i],a[iGt])
}else{
i++;
}
}while( i<iGt );
if( iLt>n/2 ){
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
n = iLt;
}else{
if( iLt>=2 ) percentSort(a, iLt);
a += iGt;
n -= iGt;
}
}
}
/*
** The "inverse" function for percentile(Y,P) is called to remove a
+67 -13
View File
@@ -810,7 +810,7 @@ static void jsonAppendSqlValue(
break;
}
case SQLITE_FLOAT: {
jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue));
jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
break;
}
case SQLITE_INTEGER: {
@@ -2124,9 +2124,10 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
u8 x;
u32 sz;
u32 n;
assert( i<=pParse->nBlob );
x = pParse->aBlob[i]>>4;
if( x<=11 ){
if( i>=pParse->nBlob ){
*pSz = 0;
return 0;
}else if( (x = pParse->aBlob[i]>>4)<=11 ){
sz = x;
n = 1;
}else if( x==12 ){
@@ -4909,11 +4910,9 @@ static void jsonGroupInverse(
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
#ifdef NEVER
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
** always have been called to initialize it */
if( NEVER(!pStr) ) return;
#endif
z = pStr->zBuf;
for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
if( c=='"' ){
@@ -4942,6 +4941,13 @@ static void jsonGroupInverse(
** json_group_obj(NAME,VALUE)
**
** Return a JSON object composed of all names and values in the aggregate.
**
** Rows for which NAME is NULL do not result in a new entry. However, we
** do initially insert a "@" entry into the growing string for each null entry
** and change the first character of the string to "@" to signal that the
** string contains null entries. The "@" markers are needed in order to
** correctly process xInverse() requests. The initial "@" is converted
** back into "{" and the "@" null values are removed by jsonObjectCompute().
*/
static void jsonObjectStep(
sqlite3_context *ctx,
@@ -4959,7 +4965,7 @@ static void jsonObjectStep(
if( pStr->zBuf==0 ){
jsonStringInit(pStr, ctx);
jsonAppendChar(pStr, '{');
}else if( pStr->nUsed>1 && z!=0 ){
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
@@ -4967,6 +4973,9 @@ static void jsonObjectStep(
jsonAppendString(pStr, z, n);
jsonAppendChar(pStr, ':');
jsonAppendSqlValue(pStr, argv[1]);
}else{
pStr->zBuf[0] = '@';
jsonAppendRawNZ(pStr, "@", 1);
}
}
}
@@ -4975,20 +4984,64 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
if( pStr ){
jsonAppendRawNZ(pStr, "}", 2);
jsonStringTrimOneChar(pStr);
JsonString *pOgStr = pStr;
JsonString tmpStr;
jsonAppendRawNZ(pOgStr, "}", 2); /* Ensure it is zero-terminated */
jsonStringTrimOneChar(pOgStr); /* Remove the zero terminator */
pStr->pCtx = ctx;
if( pStr->eErr ){
jsonReturnString(pStr, 0, 0);
return;
}else if( flags & JSON_BLOB ){
}
if( pStr->zBuf[0]!='{' ){
/* The string contains null entries that need to be removed */
u64 i, j;
int inStr = 0;
if( !isFinal ){
/* Work with a temporary copy of the string if this is not the
** final result */
jsonStringInit(&tmpStr, ctx);
jsonAppendRawNZ(&tmpStr, pStr->zBuf, pStr->nUsed+1);
pStr = &tmpStr;
if( pStr->eErr ){
jsonReturnString(pStr, 0, 0);
return;
}
jsonStringTrimOneChar(pStr); /* Remove zero terminator */
}
/* Fix up the string by changing the initial "@" flag back to
** to "{" and removing all subsequence "@" entries, with their
** associated comma delimeters. */
pStr->zBuf[0] = '{';
for(i=j=1; i<pStr->nUsed; i++){
char c = pStr->zBuf[i];
if( c=='"' ){
inStr = !inStr;
pStr->zBuf[j++] = '"';
}else if( c=='\\' ){
pStr->zBuf[j++] = '\\';
pStr->zBuf[j++] = pStr->zBuf[++i];
}else if( c=='@' && !inStr ){
assert( i+1<pStr->nUsed );
if( pStr->zBuf[i+1]==',' ){
i++;
}else if( pStr->zBuf[j-1]==',' ){
j--;
}
}else{
pStr->zBuf[j++] = c;
}
}
pStr->zBuf[j] = 0; /* Restore zero terminator */
pStr->nUsed = j; /* Truncate the string */
}
if( flags & JSON_BLOB ){
jsonReturnStringAsBlob(pStr);
if( isFinal ){
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
}else{
jsonStringTrimOneChar(pStr);
jsonStringTrimOneChar(pOgStr);
}
return;
}else if( isFinal ){
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
pStr->bStatic ? SQLITE_TRANSIENT :
@@ -4996,8 +5049,9 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
pStr->bStatic = 1;
}else{
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
jsonStringTrimOneChar(pStr);
jsonStringTrimOneChar(pOgStr);
}
if( pStr!=pOgStr ) jsonStringReset(pStr);
}else if( flags & JSON_BLOB ){
static const unsigned char emptyObject = 0x0c;
sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
+3 -4
View File
@@ -876,10 +876,10 @@ int sqlite3_deserialize(
if( rc ) goto end_deserialize;
db->init.iDb = (u8)iDb;
db->init.reopenMemdb = 1;
rc = sqlite3_step(pStmt);
sqlite3_step(pStmt);
db->init.reopenMemdb = 0;
if( rc!=SQLITE_DONE ){
rc = SQLITE_ERROR;
rc = sqlite3_finalize(pStmt);
if( rc!=SQLITE_OK ){
goto end_deserialize;
}
p = memdbFromDbSchema(db, zSchema);
@@ -900,7 +900,6 @@ int sqlite3_deserialize(
}
end_deserialize:
sqlite3_finalize(pStmt);
if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
sqlite3_free(pData);
}
+6 -6
View File
@@ -5140,9 +5140,9 @@ static int unixShmMap(
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
if( pShmNode->nRegion<nReqRegion ){
char **apNew; /* New apRegion[] array */
int nByte = nReqRegion*szRegion; /* Minimum required file size */
struct stat sStat; /* Used by fstat() */
char **apNew; /* New apRegion[] array */
i64 nByte = nReqRegion*(i64)szRegion; /* Minimum required file size */
struct stat sStat; /* Used by fstat() */
pShmNode->szRegion = szRegion;
@@ -5173,7 +5173,7 @@ static int unixShmMap(
*/
else{
static const int pgsz = 4096;
int iPg;
i64 iPg;
/* Write to the last byte of each newly allocated or extended page */
assert( (nByte % pgsz)==0 );
@@ -5199,8 +5199,8 @@ static int unixShmMap(
}
pShmNode->apRegion = apNew;
while( pShmNode->nRegion<nReqRegion ){
int nMap = szRegion*nShmPerMap;
int i;
i64 nMap = (i64)szRegion*(i64)nShmPerMap;
i64 i;
void *pMem;
if( pShmNode->hShm>=0 ){
pMem = osMmap(0, nMap,
+6 -7
View File
@@ -4582,7 +4582,7 @@ static int winShmMap(
if( pShmNode->nRegion<=iRegion ){
HANDLE hShared = pShmNode->hSharedShm;
struct ShmRegion *apNew; /* New aRegion[] array */
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */
sqlite3_int64 sz; /* Current size of wal-index file */
pShmNode->szRegion = szRegion;
@@ -4613,7 +4613,7 @@ static int winShmMap(
/* Map the requested memory region into this processes address space. */
apNew = (struct ShmRegion*)sqlite3_realloc64(
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
rc = SQLITE_IOERR_NOMEM_BKPT;
@@ -4635,15 +4635,14 @@ static int winShmMap(
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
#endif
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n",
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
hMap ? "ok" : "failed"));
if( hMap ){
int iOffset = pShmNode->nRegion*szRegion;
i64 iOffset = pShmNode->nRegion*szRegion;
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
pMap = osMapViewOfFile(hMap, flags,
0, iOffset - iOffsetShift, szRegion + iOffsetShift
0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
);
OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
@@ -4665,7 +4664,7 @@ static int winShmMap(
shmpage_out:
if( pShmNode->nRegion>iRegion ){
int iOffset = iRegion*szRegion;
i64 iOffset = (i64)iRegion*(i64)szRegion;
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
char *p = (char *)pShmNode->aRegion[iRegion].pMap;
*pp = (void *)&p[iOffsetShift];
+4 -4
View File
@@ -2566,7 +2566,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
if( rc!=SQLITE_OK ) goto delsuper_out;
nSuperPtr = 1 + (i64)pVfs->mxPathname;
assert( nSuperJournal>=0 && nSuperPtr>0 );
zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
zFree = sqlite3Malloc(4 + nSuperJournal + 2 + nSuperPtr + 2);
if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
@@ -2827,10 +2827,10 @@ static int pager_playback(Pager *pPager, int isHot){
**
** TODO: Technically the following is an error because it assumes that
** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
** ((pPager->pageSize+8) >= pPager->pVfs->mxPathname+1). Using os_unix.c,
** mxPathname is 512, which is the same as the minimum allowable value
** for pageSize.
*/
** for pageSize, and so this assumption holds. But it might not for some
** custom VFS. */
zSuper = pPager->pTmpSpace;
rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
if( rc==SQLITE_OK && zSuper[0] ){
+9 -6
View File
@@ -1334,9 +1334,11 @@ expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
ExprList *pList = sqlite3ExprListAppend(pParse, X, Y);
A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
if( A ){
int i;
A->x.pList = pList;
if( ALWAYS(pList->nExpr) ){
A->flags |= pList->a[0].pExpr->flags & EP_Propagate;
for(i=0; i<pList->nExpr; i++){
assert( pList->a[i].pExpr!=0 );
A->flags |= pList->a[i].pExpr->flags & EP_Propagate;
}
}else{
sqlite3ExprListDelete(pParse->db, pList);
@@ -1476,6 +1478,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0);
if( A ){
A->x.pList = pList;
sqlite3ExprSetHeightAndFlags(pParse, A);
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
@@ -1909,11 +1912,11 @@ cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) DROP NOT NULL. {
cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) SET NOT(Z) NULL onconf. {
sqlite3AlterSetNotNull(pParse, X, &Y, &Z);
}
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT(Y) nm(Z) CHECK LP(A) expr RP(B) onconf. {
sqlite3AlterAddConstraint(pParse, X, &Y, &Z, A.z+1, (B.z-A.z-1));
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT(Y) nm(Z) CHECK LP(A) expr(E) RP(B) onconf. {
sqlite3AlterAddConstraint(pParse, X, &Y, &Z, A.z+1, (B.z-A.z-1), E);
}
cmd ::= ALTER TABLE fullname(X) ADD CHECK(Y) LP(A) expr RP(B) onconf. {
sqlite3AlterAddConstraint(pParse, X, &Y, 0, A.z+1, (B.z-A.z-1));
cmd ::= ALTER TABLE fullname(X) ADD CHECK(Y) LP(A) expr(E) RP(B) onconf. {
sqlite3AlterAddConstraint(pParse, X, &Y, 0, A.z+1, (B.z-A.z-1), E);
}
kwcolumn_opt ::= .
+40 -16
View File
@@ -165,7 +165,7 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
return 0;
}
z = sqlite3DbMallocRaw(pAccum->db, n);
z = sqlite3_malloc(n);
if( z==0 ){
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
}
@@ -623,11 +623,27 @@ void sqlite3_str_vappendf(
szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+10;
if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;
if( sqlite3StrAccumEnlargeIfNeeded(pAccum, szBufNeeded) ){
width = length = 0;
break;
if( szBufNeeded + pAccum->nChar >= pAccum->nAlloc ){
if( pAccum->mxAlloc==0 && pAccum->accError==0 ){
/* Unable to allocate space in pAccum, perhaps because it
** is coming from sqlite3_snprintf() or similar. We'll have
** to render into temporary space and the memcpy() it over. */
bufpt = sqlite3_malloc(szBufNeeded);
if( bufpt==0 ){
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
return;
}
zExtra = bufpt;
}else if( sqlite3StrAccumEnlarge(pAccum, szBufNeeded)<szBufNeeded ){
width = length = 0;
break;
}else{
bufpt = pAccum->zText + pAccum->nChar;
}
}else{
bufpt = pAccum->zText + pAccum->nChar;
}
bufpt = zOut = pAccum->zText + pAccum->nChar;
zOut = bufpt;
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
@@ -728,14 +744,22 @@ void sqlite3_str_vappendf(
}
length = width;
}
pAccum->nChar += length;
zOut[length] = 0;
/* Floating point conversions render directly into the output
** buffer. Hence, don't just break out of the switch(). Bypass the
** output buffer writing that occurs after the switch() by continuing
** to the next character in the format string. */
continue;
if( zExtra==0 ){
/* The result is being rendered directory into pAccum. This
** is the command and fast case */
pAccum->nChar += length;
zOut[length] = 0;
continue;
}else{
/* We were unable to render directly into pAccum because we
** couldn't allocate sufficient memory. We need to memcpy()
** the rendering (or some prefix thereof) into the output
** buffer. */
bufpt[0] = 0;
bufpt = zExtra;
break;
}
}
case etSIZE:
if( !bArgList ){
@@ -782,7 +806,7 @@ void sqlite3_str_vappendf(
if( sqlite3StrAccumEnlargeIfNeeded(pAccum, nCopyBytes) ){
break;
}
sqlite3_str_append(pAccum,
sqlite3_str_append(pAccum,
&pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);
precision -= nPrior;
nPrior *= 2;
@@ -885,8 +909,8 @@ void sqlite3_str_vappendf(
** all control characters, and for backslash itself.
** For %#Q, do the same but only if there is at least
** one control character. */
u32 nBack = 0;
u32 nCtrl = 0;
i64 nBack = 0;
i64 nCtrl = 0;
for(k=0; k<i; k++){
if( escarg[k]=='\\' ){
nBack++;
@@ -1298,7 +1322,7 @@ void sqlite3_str_reset(StrAccum *p){
** of its content, all in one call.
*/
void sqlite3_str_free(sqlite3_str *p){
if( p ){
if( p!=0 && p!=&sqlite3OomStr ){
sqlite3_str_reset(p);
sqlite3_free(p);
}
+22 -4
View File
@@ -774,6 +774,7 @@ static int lookupName(
pExpr->op = TK_FUNCTION;
pExpr->u.zToken = "coalesce";
pExpr->x.pList = pFJMatch;
pExpr->affExpr = SQLITE_AFF_DEFER;
cnt = 1;
goto lookupname_end;
}else{
@@ -942,6 +943,26 @@ static int exprProbability(Expr *p){
return (int)(r*134217728.0);
}
/*
** Set the EP_SubtArg property on every expression inside of
** pList. If any subexpression is actually a subquery, then
** also set the EP_SubtArg property on the first result-set
** column of that subquery.
*/
static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
int nn, ii;
nn = pList ? pList->nExpr : 0;
for(ii=0; ii<nn; ii++){
Expr *pExpr = pList->a[ii].pExpr;
ExprSetProperty(pExpr, EP_SubtArg);
if( pExpr->op==TK_SELECT ){
assert( ExprUseXSelect(pExpr) );
assert( pExpr->x.pSelect!=0 );
resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
}
}
}
/*
** This routine is callback for sqlite3WalkExpr().
**
@@ -1186,10 +1207,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( (pDef->funcFlags & SQLITE_SUBTYPE)
|| ExprHasProperty(pExpr, EP_SubtArg)
){
int ii;
for(ii=0; ii<n; ii++){
ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
}
resolveSetExprSubtypeArg(pList);
}
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
+5 -2
View File
@@ -7324,6 +7324,7 @@ static SQLITE_NOINLINE void existsToJoin(
&& !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
&& ALWAYS(p->pSrc!=0)
&& p->pSrc->nSrc<BMS
&& (p->pLimit==0 || p->pLimit->pRight==0)
){
if( pWhere->op==TK_AND ){
Expr *pRight = pWhere->pRight;
@@ -7371,7 +7372,6 @@ static SQLITE_NOINLINE void existsToJoin(
sqlite3TreeViewSelect(0, p, 0);
}
#endif
existsToJoin(pParse, p, pSubWhere);
}
}
}
@@ -7432,8 +7432,11 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
** does not refer to a table to the right of CheckOnCtx.iJoin. */
do {
SrcList *pSrc = pCtx->pSrc;
int nSrc = pSrc->nSrc;
int iTab = pExpr->iTable;
if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
int ii;
for(ii=0; ii<nSrc && pSrc->a[ii].iCursor!=iTab; ii++){}
if( ii<nSrc ){
if( pCtx->iJoin && iTab>pCtx->iJoin ){
sqlite3ErrorMsg(pWalker->pParse,
"%s references tables to its right",
+10 -5
View File
@@ -3787,7 +3787,7 @@ static const char *(azHelp[]) = {
" --schema SCHEMA Use SCHEMA instead of \"main\"",
" --help Show CMD details",
".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
",headers on|off Turn display of headers on or off",
".headers on|off Turn display of headers on or off",
".help ?-all? ?PATTERN? Show help text for PATTERN",
#ifndef SQLITE_SHELL_FIDDLE
".import FILE TABLE Import data from FILE into TABLE",
@@ -8570,8 +8570,7 @@ static int dotCmdOutput(ShellState *p){
zBom = zBomUtf8;
}else if( cli_strcmp(z,"-plain")==0 ){
bPlain = 1;
}else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
&& (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
}else if( c=='o' && sqlite3_strglob("-[ewx]",z)==0 ){
if( bKeep || eMode ){
dotCmdError(p, i, "incompatible with prior options",0);
goto dotCmdOutput_error;
@@ -12316,7 +12315,9 @@ static int runOneSqlLine(
rc = shell_exec(p, zSql, &zErrMsg);
END_TIMER(p);
if( rc || zErrMsg ){
char zPrefix[100];
char zPrefix[2048
/* must be relatively large:
** https://sqlite.org/forum/forumpost/205f73db1b2806f5 */];
const char *zErrorTail;
const char *zErrorType;
if( zErrMsg==0 ){
@@ -13288,7 +13289,7 @@ int SQLITE_CDECL main(int argc, char **argv){
#ifndef SQLITE_SHELL_FIDDLE
sqlite3_appendvfs_init(0,0,0);
#ifdef SQLITE_DEBUG
sqlite3_auto_extension( (void (*)())auto_ext_leak_tester );
sqlite3_auto_extension( (void (*)(void))auto_ext_leak_tester );
#endif
#endif
modeDefault(&data);
@@ -13555,6 +13556,10 @@ int SQLITE_CDECL main(int argc, char **argv){
modePop(&data);
data.nPopMode = 0;
}
if( rc ){
goto shell_main_exit;
}
}
if( data.nPopOutput && azCmd[i][0]!='.' ){
output_reset(&data);
+9 -1
View File
@@ -5453,7 +5453,15 @@ void sqlite3AlterFunctions(void);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int);
void sqlite3AlterAddConstraint(
Parse *pParse, /* Parse context */
SrcList *pSrc, /* Table to add constraint to */
Token *pFirst, /* First token of new constraint */
Token *pName, /* Name of new constraint. NULL if name omitted. */
const char *zExpr, /* Text of CHECK expression */
int nExpr, /* Size of pExpr in bytes */
Expr *pExpr /* The parsed CHECK expression */
);
void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
i64 sqlite3GetToken(const unsigned char *, int *);
void sqlite3NestedParse(Parse*, const char*, ...);
+11 -6
View File
@@ -458,15 +458,20 @@ u8 sqlite3StrIHash(const char *z){
return h;
}
#if !defined(SQLITE_DISABLE_INTRINSIC) \
&& (defined(__GNUC__) || defined(__clang__)) \
&& (defined(__x86_64__) || defined(__aarch64__) || \
(defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen>32)))
#define SQLITE_USE_UINT128
#endif
/*
** Two inputs are multiplied to get a 128-bit result. Write the
** lower 64-bits of the result into *pLo, and return the high-order
** 64 bits.
*/
static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
#if (defined(__GNUC__) || defined(__clang__)) \
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
&& !defined(SQLITE_DISABLE_INTRINSIC)
#if defined(SQLITE_USE_UINT128)
__uint128_t r = (__uint128_t)a * b;
*pLo = (u64)r;
return (u64)(r>>64);
@@ -500,9 +505,7 @@ static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
** The lower 64 bits of A*B are discarded.
*/
static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
#if (defined(__GNUC__) || defined(__clang__)) \
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
&& !defined(SQLITE_DISABLE_INTRINSIC)
#if defined(SQLITE_USE_UINT128)
__uint128_t r = (__uint128_t)a * b;
r += ((__uint128_t)aLo * b) >> 32;
*pLo = (r>>32)&0xffffffff;
@@ -540,6 +543,8 @@ static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
#endif
}
#undef SQLITE_USE_UINT128
/*
** Return a u64 with the N-th bit set.
*/
+7 -22
View File
@@ -3187,7 +3187,8 @@ static int whereRangeVectorLen(
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
if( aff!=idxaff ) break;
pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
if( ExprHasProperty(pTerm->pExpr, EP_Commuted) ) SWAP(Expr*, pRhs, pLhs);
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
if( pColl==0 ) break;
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
}
@@ -7583,27 +7584,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
}
if( pTabList->a[pLevel->iFrom].fg.fromExists
&& (i==pWInfo->nLevel-1
|| pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
){
/* This is an EXISTS-to-JOIN optimization which is either the
** inner-most loop, or the inner-most of a group of nested
** EXISTS-to-JOIN optimization loops. If this loop sees a successful
** row, it should break out of itself as well as other EXISTS-to-JOIN
** loops in which is is directly nested. */
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
while( nOuter<i ){
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
nOuter++;
}
testcase( nOuter>0 );
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
if( nOuter ){
VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
}else{
VdbeComment((v, "EXISTS break %d", i));
}
if( pTabList->a[pLevel->iFrom].fg.fromExists ){
/* This is an EXISTS-to-JOIN optimization loop. If this loop sees a
** successful row, it should break out of itself. */
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
VdbeComment((v, "EXISTS break %d", i));
}
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
+10 -2
View File
@@ -2297,7 +2297,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
*/
if( pWInfo->nLevel>1 ){
if( pWInfo->nLevel>1 || pTabItem->fg.fromExists ){
int nNotReady; /* The number of notReady tables */
SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
@@ -2310,6 +2310,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
for(k=1; k<=nNotReady; k++){
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
}
/* Clear the fromExists flag on the OR-optimized table entry so that
** the calls to sqlite3WhereEnd() do not code early-exits after the
** first row is visited. The early exit applies to this table's
** overall loop - including the multiple OR branches and any WHERE
** conditions not passed to the sub-loops - not to the sub-loops. */
pOrTab->a[0].fg.fromExists = 0;
}else{
pOrTab = pWInfo->pTabList;
}
@@ -2553,7 +2560,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
assert( pLevel->op==OP_Return );
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
if( pWInfo->pTabList!=pOrTab ){ sqlite3DbFreeNN(db, pOrTab); }
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
@@ -2710,6 +2717,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
if( ExprHasProperty(pAlt->pExpr, EP_Collate) ) continue;
if( (pAlt->eOperator & WO_IN)
&& ExprUseXSelect(pAlt->pExpr)
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
+5 -9
View File
@@ -954,8 +954,8 @@ static void exprAnalyzeOrTerm(
** 3. Not originating in the ON clause of an OUTER JOIN
** 4. The operator is not IS or else the query does not contain RIGHT JOIN
** 5. The affinities of A and B must be compatible
** 6a. Both operands use the same collating sequence OR
** 6b. The overall collating sequence is BINARY
** 6. Both operands use the same collating sequence, and they must not
** use explicit COLLATE clauses.
** If this routine returns TRUE, that means that the RHS can be substituted
** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
** This is an optimization. No harm comes from returning 0. But if 1 is
@@ -963,10 +963,9 @@ static void exprAnalyzeOrTerm(
*/
static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
char aff1, aff2;
CollSeq *pColl;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
if( ExprHasProperty(pExpr, EP_OuterON|EP_Collate) ) return 0; /* (3) */
assert( pSrc!=0 );
if( pExpr->op==TK_IS
&& pSrc->nSrc>=2
@@ -981,10 +980,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
){
return 0; /* (5) */
}
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
if( !sqlite3IsBinary(pColl)
&& !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
){
if( !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){
return 0; /* (6) */
}
return 1;
@@ -1316,7 +1312,7 @@ static void exprAnalyze(
/* Analyze a term that is composed of two or more subterms connected by
** an OR operator.
*/
else if( pExpr->op==TK_OR ){
else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){
assert( pWC->op==TK_AND );
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
pTerm = &pWC->a[idxTerm];
+15 -1
View File
@@ -438,5 +438,19 @@ do_execsql_test 9.2.5 {
SELECT sql FROM aux.sqlite_schema WHERE name='t2';
} {{CREATE TABLE t2(x, y, z)}}
finish_test
# Cannot add constraints the use internal functions.
# Forum post 2026-05-10T01:11:28Z
#
reset_db
do_execsql_test 10.1 {
CREATE TABLE t1(x,y,z);
INSERT INTO t1 VALUES(1,'two',x'3333');
}
do_catchsql_test 10.2 {
ALTER TABLE t1 ADD CONSTRAINT c1 CHECK( sqlite_drop_column(22,'CREATE TABLE a(b,c)', 0));
} {1 {no such function: sqlite_drop_column}}
do_catchsql_test 10.3 {
ALTER TABLE t1 ADD CONSTRAINT c1 CHECK( x>#2 );
} {1 {near "#2": syntax error}}
finish_test
+48
View File
@@ -243,5 +243,53 @@ do_execsql_test 11.2.3 {
do_execsql_test 11.2.2 {ALTER TABLE t2 ALTER b SET NOT NULL --new cons
;
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 12.0 {
CREATE TABLE "Test" (
"IsActive" INTEGER,
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
);
}
do_execsql_test 12.1 {
ALTER TABLE Test DROP CONSTRAINT BooleanZeroOrOne
}
do_execsql_test 12.2 {
SELECT sql FROM sqlite_schema
} {
{CREATE TABLE "Test" (
"IsActive" INTEGER)}
}
do_execsql_test 12.3 {
DROP TABLE Test;
CREATE TABLE "Test" (
"IsActive" INTEGER,
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
);
}
do_execsql_test 12.4 {
ALTER TABLE Test DROP CONSTRAINT "BooleanZeroOrOne"
}
do_execsql_test 12.5 {
SELECT sql FROM sqlite_schema
} {
{CREATE TABLE "Test" (
"IsActive" INTEGER)}
}
do_execsql_test 12.6 {
CREATE TABLE t1(a, b CONSTRAINT "a""b" CHECK (b IS NOT NULL));
}
do_execsql_test 12.7 {
ALTER TABLE t1 DROP CONSTRAINT "a""b"
}
finish_test
+32 -15
View File
@@ -333,20 +333,39 @@ do_execsql_test 5.7 {
INSERT INTO t1(rowid, a, b, c, d) VALUES(7, 'X', 'Y', 'z', 'seven');
}
do_execsql_test 5.8 {
SELECT d FROM x1
WHERE a='x' AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
} {
zero two three
}
do_execsql_test 5.9 {
SELECT d FROM x1
WHERE a='x' COLLATE nocase
AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
} {
zero four two
three six seven
if {1} {
# Since 2026-05-18, SQLite does not attempt the OR-optimization on
# conjuncts that contain COLLATE operators, due to
# bug report 2026-05-17T11:46:40Z.
do_catchsql_test 5.8 {
SELECT d FROM x1
WHERE a='x' AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
} {1 {no query solution}}
do_catchsql_test 5.9 {
SELECT d FROM x1
WHERE a='x' COLLATE nocase
AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
} {1 {no query solution}}
} else {
# This case would work if SQLite knew how to deal with conjuncts that
# contain COLLATE operators.
do_execsql_test 5.8 {
SELECT d FROM x1
WHERE a='x' AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
} {
zero two three
}
do_execsql_test 5.9 {
SELECT d FROM x1
WHERE a='x' COLLATE nocase
AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
} {
zero four two
three six seven
}
}
#--------------------------------------------------------------------------
@@ -422,5 +441,3 @@ do_execsql_test 6.6 {
} {555}
finish_test
+35
View File
@@ -0,0 +1,35 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
int main(void){
#ifdef SQLITE_ENABLE_SESSION
sqlite3 *db;
sqlite3_changegroup *pGrp;
char *zErr = 0;
char *buf = malloc(64);
int rc = SQLITE_OK;
sqlite3_open(":memory:", &db);
sqlite3_exec(db, "CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);", 0, 0, 0);
sqlite3changegroup_new(&pGrp);
sqlite3changegroup_schema(pGrp, db, "main");
sqlite3changegroup_change_begin(pGrp, SQLITE_INSERT, "t1", 0, &zErr);
sqlite3changegroup_change_int64(pGrp, 1, 0, 42);
memset(buf, 'X', 64);
/* This should return an OOM error: */
rc = sqlite3changegroup_change_blob(pGrp, 1, 1, buf, 2147483647);
free(buf);
sqlite3changegroup_delete(pGrp);
sqlite3_close(db);
return (rc==7) ? 0 : -1;
#else
return 0;
#endif
}
+14
View File
@@ -164,4 +164,18 @@ do_test 300 {
sqlite3_finalize $STMT
sqlite3_finalize $STMT2
# 2026-05-31 dbsqlfuzz case 55c60cf7eb9e0f14c811b7c9227b8d2a0c32f022
# 2026-06-01 dbsqlfuzz case 78e187a0fb61b19ff2e0cb76d4e8609df5248302
# Probably also Bug 2026-06-01T07:23:11Z
do_catchsql_test 400 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INT PRIMARY KEY, b INT) WITHOUT ROWID;
WITH c(x) AS (
VALUES(1)
UNION
SELECT x+1 FROM (carray NATURAL FULL JOIN carray(t1.b)), t1, c
)
SELECT * FROM c;
} {1 {table-function argument references tables to its right}}
finish_test
+14
View File
@@ -251,5 +251,19 @@ do_execsql_test 720 {
PRAGMA integrity_check
} {ok}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 800 {
CREATE TABLE x1(x);
}
do_execsql_test 810 {
SELECT pgno FROM sqlite_dbpage WHERE pgno=555
} {}
do_execsql_test 820 {
SELECT pgno FROM sqlite_dbpage WHERE pgno=4294967297
} {}
finish_test
+115
View File
@@ -476,6 +476,29 @@ catch { optimization_control db exists-to-join 0 }
db cache flush
do_execsql_test 9.6 $Q {{big string value}}
#-------------------------------------------------------------------------
# Forum post 2026-04-21T10:57:09Z
do_execsql_test 9.7.1 {
DROP TABLE t3;
CREATE TABLE t3(x INT, y INT);
CREATE TABLE t4(z INT);
INSERT INTO t3 VALUES (1,0),(2,2),(3,3);
INSERT INTO t4 VALUES (4),(5);
}
set Q {
SELECT x FROM t3
WHERE EXISTS(SELECT 1 FROM t4 WHERE z>y)
LIMIT 1 OFFSET 1
}
catch { optimization_control db all 1 }
db cache flush
do_execsql_test 9.7.2 $Q {2}
catch { optimization_control db exists-to-join 0 }
db cache flush
do_execsql_test 9.7.3 $Q {2}
catch { optimization_control db all 1 }
db cache flush
#-------------------------------------------------------------------------
reset_db
@@ -514,4 +537,96 @@ do_execsql_test 11.1 {
GROUP BY id;
} {1 p1}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 12.0 {
CREATE TABLE t2(id INT, data INT);
CREATE TABLE t3(amount INT);
INSERT INTO t2 VALUES (1,0),(2,0);
INSERT INTO t3 VALUES (1),(1);
}
do_execsql_test 12.1 {
SELECT * FROM t2
WHERE EXISTS (SELECT 1 FROM t3 WHERE t3.amount > t2.data)
} {
1 0
2 0
}
do_execsql_test 12.2 {
SELECT * FROM t2
WHERE EXISTS (SELECT 1 FROM t3 WHERE t3.amount > t2.data)
LIMIT 2 OFFSET 3
} {}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 13.0 {
CREATE TABLE t1(b,c);
CREATE TABLE t2(x,y);
CREATE TABLE t3(p,q);
INSERT INTO t1 VALUES(7,10);
INSERT INTO t2 VALUES(1,1), (4,7);
INSERT INTO t3 VALUES(4,7);
PRAGMA automatic_index = 0;
}
do_execsql_test 13.1 {
SELECT * FROM t1 WHERE EXISTS (
SELECT 1 FROM t2
WHERE EXISTS (
SELECT 1 FROM t3 WHERE t3.p=t2.x AND t3.q=t1.b
)
)
} {7 10}
#-------------------------------------------------------------------------
# Forum post https://sqlite.org/forum/forumpost/c8b205720c
#
reset_db
do_execsql_test 14.1.0 {
CREATE TABLE t(n INTEGER, parent INTEGER);
CREATE INDEX idx ON t(parent);
INSERT INTO t VALUES (1, NULL);
INSERT INTO t VALUES (10, NULL);
}
do_execsql_test 14.1.1 {
SELECT count(*) FROM t b
WHERE (b.parent IS NULL OR b.parent = 99)
AND 5 <= +b.n
} 1
do_execsql_test 14.1.2 {
SELECT 'match' WHERE EXISTS (
SELECT 1 FROM t b
WHERE (b.parent IS NULL OR b.parent = 99)
AND 5 <= +b.n
)
} {match}
do_execsql_test 14.2.1 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(20, 20);
CREATE TABLE t2(c, d);
CREATE INDEX t2c ON t2(c);
CREATE INDEX t2d ON t2(d);
INSERT INTO t2 VALUES(20, -1);
INSERT INTO t2 VALUES(20, 0);
}
do_execsql_test 14.2.2 {
SELECT * FROM t1 WHERE EXISTS (
SELECT 1 FROM t2 WHERE (c=a OR d=a) AND (d+1)>0
)
} {20 20}
finish_test
+68
View File
@@ -277,4 +277,72 @@ do_catchsql_test 2.1 {
SELECT 0 FROM t1 WHERE t1 MATCH 'rtree NEAR rtree"json1 enable"';
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
set DEPTH 40000
proc fts3_put_varint {v} {
set l [list]
while {$v >= 0x80} {
lappend l [expr ($v & 0x7F) | 0x80]
set v [expr $v >> 7]
}
lappend l [expr $v & 0x7F]
binary format cu* $l
}
proc make_interior_node {height child_blockid} {
binary format a*a* [fts3_put_varint $height] [fts3_put_varint $child_blockid]
}
db func make_interior_node make_interior_node
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE fts USING fts3(content TEXT);
INSERT INTO fts(content) VALUES ('hello world');
DELETE FROM fts_segdir;
INSERT INTO fts_segdir
(level, idx, start_block, leaves_end_block, end_block, root) VALUES
(0, 0, 100, 100 + $DEPTH, 100 + $DEPTH, make_interior_node($DEPTH+1, 100));
}
do_test 3.1 {
execsql BEGIN
for {set ii 0} {$ii<$DEPTH} {incr ii} {
execsql {
INSERT INTO fts_segments(blockid, block)
VALUES($ii+100, make_interior_node($DEPTH-$ii, 101+$ii))
}
}
execsql COMMIT
} {}
do_catchsql_test 3.2 {
SELECT * FROM fts WHERE fts MATCH 'x';
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.1 {
CREATE VIRTUAL TABLE t1 USING fts4(content);
DELETE FROM t1_segments;
DELETE FROM t1_segdir;
}
do_execsql_test 4.2 {
INSERT INTO t1_segdir
(level, idx, start_block, leaves_end_block, end_block, root)
VALUES(0, 0, 0, 0, 0, X'000568656C6C6F08010201FFFFFF7F00');
}
do_execsql_test 4.3 {
CREATE VIRTUAL TABLE t1_terms USING fts4aux(t1);
}
do_catchsql_test 4.4 {
SELECT * FROM t1_terms;
} {1 {database disk image is malformed}}
finish_test
+17 -1
View File
@@ -30,12 +30,19 @@ tvfs filter xWrite
tvfs script write_cb
set ::trigger_interrupt 0
set ::dbpointer ""
proc write_cb {method args} {
set filename [lindex $args 0]
if {[file tail $filename]=="test.db" && $::trigger_interrupt} {
if {$::trigger_interrupt} {
incr ::trigger_interrupt -1
if {$::trigger_interrupt==0} { sqlite3_interrupt db }
if {$::trigger_interrupt==0} {
if {$::dbpointer!=""} {
sqlite3_interrupt $::dbpointer
} else {
sqlite3_interrupt db
}
}
}
}
return 0
@@ -110,8 +117,17 @@ db_save_and_close
db_restore_and_reopen
do_test 3.1.1 {
set ::trigger_interrupt 10
# Set dbpointer here so that the write-callback can use the (sqlite3*)
# pointer with sqlite3_interrupt() directly instead of looking up the
# command. On at least some versions of Tcl9, looking up a command from
# within Tcl_DeleteCommand apparently returns a bad pointer.
#
set ::dbpointer [sqlite3_connection_pointer db]
db eval { SELECT * FROM sqlite_master }
db close
set ::dbpointer ""
set {} {}
} {}
do_test 3.1.2 {
+37 -1
View File
@@ -211,5 +211,41 @@ do_execsql_test 7.3 {
);
} {1}
finish_test
#--------------------------------------------------------------------------
# Forum post 2026-05-15T11:23:01Z
#
reset_db
do_execsql_test 8.0 {
CREATE TABLE t1(x REAL);
CREATE TABLE t2(x REAL);
INSERT INTO t1 VALUES(2.5);
INSERT INTO t2 VALUES(2.5);
SELECT x FROM t1 JOIN t2 USING(x) WHERE x='2.5';
} 2.5
do_execsql_test 8.1 {
SELECT x FROM t1 LEFT JOIN t2 USING(x) WHERE x='2.5';
} 2.5
do_execsql_test 8.2 {
SELECT x FROM t1 RIGHT JOIN t2 USING(x) WHERE x='2.5';
} 2.5
do_execsql_test 8.3 {
SELECT x FROM t1 FULL JOIN t2 USING(x) WHERE x='2.5';
} 2.5
do_execsql_test 8.10 {
CREATE TABLE t3(x TEXT COLLATE nocase);
CREATE TABLE t4(x TEXT COLLATE nocase);
INSERT INTO t3 VALUES('abc');
INSERT INTO t4 VALUES('ABC');
SELECT lower(x) FROM t3 JOIN t4 USING(x) WHERE x='Abc';
} abc
do_execsql_test 8.11 {
SELECT lower(x) FROM t3 LEFT JOIN t4 USING(x) WHERE x='Abc';
} abc
do_execsql_test 8.12 {
SELECT lower(x) FROM t3 RIGHT JOIN t4 USING(x) WHERE x='Abc';
} abc
do_execsql_test 8.13 {
SELECT lower(x) FROM t3 FULL JOIN t4 USING(x) WHERE x='Abc';
} abc
finish_test
+7
View File
@@ -1178,4 +1178,11 @@ foreach {id start path ins set repl} {
} [list [tx $repl]]
}
# 2026-05-29
# JSON floating point precision
#
do_execsql_test json101-25.1 {
SELECT json_array(0.1234567890123456789)->>0 = 0.1234567890123456789;
} 1
finish_test
+37
View File
@@ -280,4 +280,41 @@ do_test 900 {
} 1
dbempty close
#-------------------------------------------------------------------------
# Make sure a database cannot be overwritten by deserialize() if
# there is an open transaction on it.
#
do_execsql_test 1000 {
CREATE TABLE t(x);
INSERT INTO t VALUES(1),(2);
}
set blob [db serialize main]
do_test 1010 {
set seen 0
list [catch {
db eval {SELECT x FROM t} {
incr seen
if {$seen == 1} {
db deserialize main $blob
}
}
} msg] $msg
} {1 {unable to set MEMDB content}}
forcedelete test.db2
sqlite3 db2 test.db2
do_test 1020 {
set seen 0
sqlite3_backup B db2 main db main
B step 2
set res [list [catch {
db deserialize main $blob
} msg] $msg]
B finish
set res
} {1 {unable to set MEMDB content}}
finish_test
+56
View File
@@ -159,4 +159,60 @@ do_hasmj_test 2.3 {
COMMIT;
} {0}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
PRAGMA synchronous = OFF;
CREATE TABLE t1(x, y);
}
do_execsql_test 3.1 {
BEGIN;
INSERT INTO t1 VALUES(100, 200);
}
db_save
db close
db_restore
do_test 3.2 {
# Append super-journal name to test.db-journal
#
set mjname [file join [pwd] test.db-super]
binary scan $mjname c* bytes
set cksum 0
foreach b $bytes { incr cksum $b }
set fd [open test.db-journal a+]
fconfigure $fd -translation binary -encoding iso8859-1
puts -nonewline $fd $mjname
puts -nonewline $fd [binary format I [string length $mjname]]
puts -nonewline $fd [binary format I $cksum]
puts -nonewline $fd [binary decode hex "d9d505f920a163d7"]
close $fd
# Create super-journal
#
set fd [open test.db-super w]
fconfigure $fd -translation binary -encoding iso8859-1
puts -nonewline $fd "test2.db-journal\0test.db-journal\0"
close $fd
# Create corrupt child journal
#
set fd [open test2.db-journal w]
fconfigure $fd -translation binary -encoding iso8859-1
puts -nonewline $fd [binary decode hex "00200001[string repeat 41 512]"]
puts -nonewline $fd [binary decode hex "0000020000008200d9d505f920a163d7"]
close $fd
} {}
sqlite3 db test.db
do_execsql_test 3.3 {
SELECT type, name, tbl_name, sql FROM sqlite_schema
} {table t1 t1 {CREATE TABLE t1(x, y)}}
finish_test
+16
View File
@@ -79,7 +79,23 @@ SELECT * FROM t2;
Quoted" │ │ │
END
.testcase 121
.mode tty --wrap 1 --limits off
SELECT 'xyz123' AS a, 2 AS b;
.check <<END
a b
x 2
y
z
1
2
3
END
.testcase 130
.mode tty -wrap 10
.mode
.check <<END
.mode qbox --limits on --quote relaxed --sw auto --textjsonb on
+28
View File
@@ -336,6 +336,34 @@ do_execsql_test 10.51 {
ORDER BY +d NULLS LAST, +c NULLS LAST;
} {X 3 X | X 4 X | X 5 X | X 7 X | X {} X | {} {} {} | Y {} {} |}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.1 {
CREATE TABLE t1(a TEXT COLLATE NOCASE, b TEXT);
INSERT INTO t1 VALUES('Hello', 'world');
}
foreach {tn sql res} {
0 "SELECT null" NULL
1 "SELECT ('hello', NULL) IN (SELECT a, b FROM t1)" NULL
2 "SELECT NOT ('hello', NULL) IN (SELECT a, b FROM t1)" NULL
3 "SELECT ('Hello', NULL) IN (SELECT a, b FROM t1)" NULL
4 "SELECT ('Hello' COLLATE NOCASE, NULL) IN (SELECT a, b FROM t1)" NULL
5 "SELECT ('hello', 'world') IN (SELECT a, b FROM t1)" 1
6 "SELECT ('hi', NULL) IN (SELECT a, b FROM t1)" 0
7 "SELECT ('hello', NULL) IN ((a, b), (3, 4), (5, 6)) FROM t1" 0
8 "SELECT (a, b) IN (('hello', NULL), (3, 4), (5, 6)) FROM t1" NULL
9 "SELECT ('Hello', NULL) IN ((a, b), (3, 4), (5, 6)) FROM t1" NULL
} {
db nullvalue NULL
do_execsql_test 11.2.$tn $sql $res
}
+11
View File
@@ -592,4 +592,15 @@ do_execsql_test percentile-6.0 {
SELECT median(iif(n%2,0.1,1.0)) FROM c;
} 0.55
# Bug 2026-06-03T07:26:42Z
# Use tail recursion in percentSort() to prevent stack overflow
#
do_execsql_test percentile-7.0 {
WITH RECURSIVE t1(n,x) AS (
VALUES(1,1.0)
UNION ALL
SELECT n+1, if(n%2,n*2.0,999998.0-2.0*n) FROM t1 WHERE n<1000000
) SELECT median(x) FROM t1;
} 499998.0
finish_test
+13 -1
View File
@@ -14,7 +14,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix unionvtab
set testprefix prefixes
ifcapable !vtab {
finish_test
@@ -85,4 +85,16 @@ foreach {tn INPUT expected} {
} $expected
}
do_execsql_test 3.1 {
SELECT prefix_length(null,'abc');
} 0
do_execsql_test 3.2 {
SELECT prefix_length('abc',null);
} 0
# Bug 2026-06-03T07:42:00Z
do_execsql_test 3.3 {
SELECT prefix_length(zeroblob(15000),zeroblob(5000));
} 0
finish_test
+14
View File
@@ -239,6 +239,20 @@ do_test 1.71 {
<TD>Ἀμήν
</TR>
}
do_test 1.72 {
set result "\n[db format -style html {
SELECT 'ab<cd' AS a, 'ab&cd' as b,
'ab>cd' AS c, 'ab"cd' AS d,
'xy''z' AS e}]"
} {
<TR>
<TD>ab&lt;cd
<TD>ab&amp;cd
<TD>ab&gt;cd
<TD>ab&quot;cd
<TD>xy&#39;z
</TR>
}
do_test 1.80 {
set result "\n[db format -style insert {SELECT * FROM t1}]"
+14
View File
@@ -854,5 +854,19 @@ do_execsql_test 35.1 {
SELECT (1, 'a') IN (SELECT c2, c1 from t1);
} 1
# Forum post 2026-05-09T07:55:45Z
#
do_execsql_test 36.0 {
DROP TABLE t1;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1),(2),(3);
SELECT (1,2,3,max(x)) IN () FROM t1;
} 0
do_execsql_test 36.1 {
SELECT (1,2,max(x),3) IN () FROM t1;
} 0
do_execsql_test 36.2 {
SELECT (max(x),1,23) IN () FROM t1;
} 0
finish_test
+20
View File
@@ -121,5 +121,25 @@ do_execsql_test 4.3 {
SELECT * FROM t0, t1 WHERE (t1.c1, t1.c0) <= (t0.c0, t0.c0);
} {True a 1 True a True}
#-------------------------------------------------------------------------
# Bug report https://sqlite.org/bugs/info/2026-05-17T11:59:19Z
#
do_execsql_test 5.1 {
DROP TABLE t1;
CREATE TABLE t1(a TEXT, b TEXT);
CREATE INDEX t1_ab ON t1(a COLLATE NOCASE, b COLLATE NOCASE);
INSERT INTO t1 VALUES('a',null),('b', 'ABCD');
}
db null NULL
do_execsql_test 5.2 {
SELECT * FROM t1
WHERE ('B' COLLATE nocase,'abc')>(a,b)
ORDER BY +a;
} {a NULL b ABCD}
do_execsql_test 5.3 {
SELECT * FROM t1 NOT INDEXED
WHERE ('B' COLLATE nocase,'abc')>(a,b)
ORDER BY +a;
} {a NULL b ABCD}
finish_test
+10
View File
@@ -350,4 +350,14 @@ do_execsql_test 320 {
)
} {69d0a31872203a775e19325ea98cd053}
do_catchsql_test 400 {
SELECT editdist3(format('%.10001c','x'),'abc');
} {1 {string or blob too big}}
do_catchsql_test 401 {
SELECT editdist3('xxxabc',format('%.10001c','x'));
} {1 {string or blob too big}}
do_catchsql_test 410 {
SELECT editdist3(format('abc%.9997c','x'),format('abc%.9997c','x'));
} {0 0}
finish_test
+29
View File
@@ -84,4 +84,33 @@ do_execsql_test subtype1-400 {
SELECT id, subtype(if(json_valid(j,6),j->'a')) FROM t400;
} {1 74 2 0}
#-------------------------------------------------------------------------
# Test that indexes on expressions do not alter subtypes.
#
reset_db
do_execsql_test subtype1-500 {
CREATE TABLE t1(id, j);
INSERT INTO t1 VALUES (1,'{a:{x:1,y:2},b:{x:3,y:4}}'), (2,'not json');
}
foreach {tn expr st} {
510 "(CASE WHEN json_valid(j, 6) THEN j->'a' ELSE j END)" 74
520 "+(CASE WHEN json_valid(j, 6) THEN j->'a' ELSE j END)" 74
530 "-(CASE WHEN json_valid(j, 6) THEN j->'a' ELSE j END)" 0
540 "if( json_valid(j, 6), j->'a' ) " 74
550 "if( json_valid(j, 6), j->'a' ) COLLATE nocase" 74
560 "CAST( if( json_valid(j, 6), j->'a' ) AS TEXT )" 74
} {
do_execsql_test subtype1-$tn.1 "
SELECT id, subtype( $expr ) FROM t1;
" [list 1 $st 2 0]
do_execsql_test subtype1-$tn.2 "
DROP INDEX IF EXISTS i1;
CREATE INDEX i1 ON t1( $expr );
SELECT id, subtype( $expr ) FROM t1 INDEXED BY i1 ORDER BY id;
" [list 1 $st 2 0]
}
finish_test
+33
View File
@@ -668,6 +668,39 @@ do_execsql_test 1370 {
SELECT * FROM generate_series(0,0,0);
} {}
# Forum post 2026-05-09T07:41:32Z
set subtest 1
foreach bound {
9007199254740991.0
9007199254740991.1
9007199254740991.5
9007199254740991.9
9007199254740992.0
9007199254740992.1
9007199254740992.5
9007199254740992.9
9007199254740993.0
9007199254740993.1
9007199254740993.5
} {
foreach {range boundsign} {
(+9007199254740990,+9007199254740995) +
(-9007199254740995,-9007199254740990) -
} {
set bx $boundsign$bound
foreach op {< > <= >=} {
do_execsql_test 1380.$subtest "
SELECT 'value $op $bx' WHERE (
SELECT group_concat(value) FROM generate_series $range
WHERE value $op $bx)<>(
SELECT group_concat(value) FROM generate_series $range
WHERE +value $op $bx);
" {}
incr subtest
}
}
}
reset_db
load_static_extension db series
do_execsql_test 1400 {
+8
View File
@@ -127,6 +127,7 @@ Special values for PERMUTATION include:
mdevtest - tests recommended prior to normal development check-ins.
devtest - alias for "mdevtest"
release - full release test with various builds.
c - tests in test/c directory only.
sdevtest - like mdevtest but using ASAN and UBSAN.
all - all tcl test scripts, plus a subset of test scripts rerun
with various permutations.
@@ -1514,6 +1515,13 @@ proc add_jobs_from_cmdline {patternlist} {
}
}
c {
set patternlist [lrange $patternlist 1 end]
foreach b [trd_builds $TRG(platform)] {
add_c_jobs $b $patternlist
}
}
list {
set allperm [array names ::testspec]
lappend allperm all devtest mdevtest sdevtest release list
+98 -1
View File
@@ -14,6 +14,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix transitive1
do_execsql_test transitive1-100 {
CREATE TABLE t1(a TEXT, b TEXT, c TEXT COLLATE NOCASE);
@@ -351,7 +352,7 @@ do_execsql_test transitive1-570 {
do_execsql_test transitive1-570eqp {
EXPLAIN QUERY PLAN
SELECT * FROM c1 WHERE x=y AND z=y AND z='abc';
} {/SEARCH c1 USING INDEX c1x/}
} {/SCAN c1/}
# 2021-05-04 forum https://sqlite.org/forum/forumpost/eb8613976a
reset_db
@@ -426,4 +427,100 @@ do_execsql_test transitive1-813 {
SELECT * FROM t3 WHERE a=b AND a='5x';
} {}
# Bug 2026-05-21T03:39:28Z
#
reset_db
do_execsql_test transitive1-900 {
CREATE TABLE t1(a TEXT);
CREATE TABLE t2(b TEXT COLLATE NOCASE);
INSERT INTO t1 VALUES('abc');
INSERT INTO t2 VALUES('abc');
SELECT * FROM t1 CROSS JOIN t2 WHERE a=b AND b='ABC';
} {abc abc}
#-------------------------------------------------------------------------
reset_db
db cache size 0
do_execsql_test 1000 {
PRAGMA automatic_index = 0;
CREATE TABLE t1(a TEXT);
CREATE TABLE t2(b TEXT);
INSERT INTO t1 VALUES ('hello');
INSERT INTO t1 VALUES ('Hello');
INSERT INTO t1 VALUES ('HELLO');
INSERT INTO t1 VALUES ('HeLLo');
INSERT INTO t2 VALUES ('hello');
INSERT INTO t2 VALUES ('Hello');
INSERT INTO t2 VALUES ('HELLO');
INSERT INTO t2 VALUES ('HeLLo');
}
optimization_control db transitive 1
do_execsql_test 1010 {
SELECT t1.a, t2.b
FROM t1 CROSS JOIN t2
WHERE t1.a = t2.b
AND t2.b COLLATE NOCASE = 'Hello';
} {
hello hello
Hello Hello
HELLO HELLO
HeLLo HeLLo
}
optimization_control db transitive 0
do_execsql_test 1020 {
SELECT t1.a, t2.b
FROM t1 CROSS JOIN t2
WHERE t1.a = t2.b
AND t2.b COLLATE NOCASE = 'Hello';
} {
hello hello
Hello Hello
HELLO HELLO
HeLLo HeLLo
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 1100 {
PRAGMA automatic_index = 0;
CREATE TABLE t1(x);
CREATE TABLE t2(y);
INSERT INTO t1 VALUES('ABC');
INSERT INTO t2 VALUES('abc');
}
do_execsql_test 1110 {
SELECT * FROM t1 CROSS JOIN t2
WHERE (t1.x COLLATE nocase) = (t2.y COLLATE nocase)
AND (t2.y = 'ABC')
} {}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 1200 {
PRAGMA automatic_index = 0;
CREATE TABLE t1(x);
CREATE TABLE t2(y);
INSERT INTO t1 VALUES('ABC');
INSERT INTO t2 VALUES('ABC');
}
do_execsql_test 1210 {
SELECT * FROM t1 CROSS JOIN t2
WHERE t1.x = t2.y
AND (t1.x COLLATE nocase = 'abc')
} {ABC ABC}
finish_test
+10
View File
@@ -787,4 +787,14 @@ do_eqp_test update-21.12 {
`--SEARCH t3 USING AUTOMATIC COVERING INDEX (x=?)
}
# /forumpost/2026-04-21T19:10:55Z
do_execsql_test update-22.0 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(x INT, y INT);
INSERT INTO t1(x) VALUES(1),(2),(3),(4),(5);
UPDATE t1 SET x=x+100, y=x<=(SELECT min(x) FROM t1)
WHERE x<3 OR (1 BETWEEN 0 AND x<=(SELECT min(x)+2 FROM t1));
SELECT x FROM t1 WHERE x<100 ORDER BY x;
} {4 5}
finish_test
+12 -2
View File
@@ -828,7 +828,17 @@ do_execsql_test where2-16.2 {
AND t1.a=t4.h;
} {~/.* t[34] .* t1 .*/}
# 2026-05-18 bug report 2026-05-17T11:46:40Z
#
do_execsql_test where2-17.0 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a TEXT);
INSERT INTO t1 VALUES('A'),('b');
SELECT * FROM t1 WHERE (a='a' COLLATE nocase) OR a='b' ORDER BY +a;
} {A b}
do_execsql_test where2-17.1 {
CREATE INDEX t1_a ON t1(a);
SELECT * FROM t1 WHERE (a='a' COLLATE nocase) OR a='b' ORDER BY +a;
} {A b}
finish_test
+122 -1
View File
@@ -201,6 +201,128 @@ ifcapable json1 {
{{"a":{"a":1,"e":9}}}
{{"c":{"c":3,"e":9}}}
}
#-----------------------------------------------------------------------
# Bug report 2026-05-18T12:34:42Z
#
# The xInverse() method used by json_group_object() should correctly
# account for NULL entries.
#
do_execsql_test 3.8 {
CREATE TABLE t1(id INT, k TEXT, v INT);
INSERT INTO t1 VALUES
(1, 'a', 1),
(2, 'b', 2),
(3, 'c', 3),
(4, 'd', 4),
(5, 'f', 5),
(6, 'g', 6),
(7, 'h', 7);
}
do_execsql_test 3.9 {
SELECT id, json_group_object(if(id<>1,k),v) OVER
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
FROM t1;
} {
1 {{"b":2}}
2 {{"b":2,"c":3}}
3 {{"b":2,"c":3,"d":4}}
4 {{"c":3,"d":4,"f":5}}
5 {{"d":4,"f":5,"g":6}}
6 {{"f":5,"g":6,"h":7}}
7 {{"g":6,"h":7}}
}
do_execsql_test 3.10 {
SELECT id, json_group_object(if(id>4,k),v) OVER
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
FROM t1;
} {
1 {{}}
2 {{}}
3 {{}}
4 {{"f":5}}
5 {{"f":5,"g":6}}
6 {{"f":5,"g":6,"h":7}}
7 {{"g":6,"h":7}}
}
do_execsql_test 3.11 {
SELECT id, json_group_object(if(id>4,k||'@'),v) OVER
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
FROM t1;
} {
1 {{}}
2 {{}}
3 {{}}
4 {{"f@":5}}
5 {{"f@":5,"g@":6}}
6 {{"f@":5,"g@":6,"h@":7}}
7 {{"g@":6,"h@":7}}
}
do_execsql_test 3.12 {
SELECT id, json_group_object(k,v) OVER
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
FROM t1;
} {
1 {{"a":1,"b":2}}
2 {{"a":1,"b":2,"c":3}}
3 {{"b":2,"c":3,"d":4}}
4 {{"c":3,"d":4,"f":5}}
5 {{"d":4,"f":5,"g":6}}
6 {{"f":5,"g":6,"h":7}}
7 {{"g":6,"h":7}}
}
do_execsql_test 3.13 {
SELECT id, json_group_object(if(id>1 AND id<7,k),v) OVER
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
FROM t1;
} {
1 {{"b":2}}
2 {{"b":2,"c":3}}
3 {{"b":2,"c":3,"d":4}}
4 {{"c":3,"d":4,"f":5}}
5 {{"d":4,"f":5,"g":6}}
6 {{"f":5,"g":6}}
7 {{"g":6}}
}
do_execsql_test 3.14 {
SELECT id, json_group_object(if(id>2 AND id<6,k),v) OVER
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
FROM t1;
} {
1 {{}}
2 {{"c":3}}
3 {{"c":3,"d":4}}
4 {{"c":3,"d":4,"f":5}}
5 {{"d":4,"f":5}}
6 {{"f":5}}
7 {{}}
}
do_execsql_test 3.15 {
SELECT id, json_group_object(if(id<2 OR id>6,k),v) OVER
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
FROM t1;
} {
1 {{"a":1}}
2 {{"a":1}}
3 {{}}
4 {{}}
5 {{}}
6 {{"h":7}}
7 {{"h":7}}
}
do_execsql_test 3.16 {
SELECT id, json_group_object(if(id<3 OR id>5,k),v) OVER
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
FROM t1;
} {
1 {{"a":1,"b":2}}
2 {{"a":1,"b":2}}
3 {{"b":2}}
4 {{}}
5 {{"g":6}}
6 {{"g":6,"h":7}}
7 {{"g":6,"h":7}}
}
}
#-------------------------------------------------------------------------
@@ -483,4 +605,3 @@ if {[permutation]!="no_optimization"} {
}}
finish_test
+58 -1
View File
@@ -62,7 +62,6 @@ do_execsql_test 2.0 {
sqlite3_create_aggregate db
breakpoint
do_catchsql_test 2.1 {
SELECT min(x) OVER w1 FROM t1
WINDOW w1 AS (PARTITION BY x_count(x) OVER w1);
@@ -105,6 +104,64 @@ do_execsql_test 3.1 {
537 1.0 538 1.0 539 1.0 540 1.0 543 1.0 544 1.0
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t1 VALUES(2, 9223372036854775807);
INSERT INTO t1 VALUES(3, 3);
INSERT INTO t1 VALUES(4, 4);
}
do_execsql_test 4.1 {
SELECT a,
total(b) OVER (ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
FROM t1;
} {
1 9.22337203685478e+18 2 9.22337203685478e+18 3 7.0 4 4.0
}
do_execsql_test 4.2 {
SELECT a,
total(b) OVER (ORDER BY a ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
FROM t1;
} {
1 9.22337203685478e+18 2 9.22337203685478e+18 3 7.0 4 4.0
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
CREATE TABLE t(id, x);
INSERT INTO t VALUES(1, -1);
INSERT INTO t VALUES(2, 9223372036854775807);
INSERT INTO t VALUES(3, 1);
INSERT INTO t VALUES(4, 0.5);
}
do_execsql_test 5.1 {
SELECT id,
sum(id) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
FROM t t1
} {
1 6
2 9
3 7
4 4
}
breakpoint
do_execsql_test 5.2 {
SELECT id,
sum(x) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
FROM t t1
} {
1 9223372036854775807
2 9.22337203685478e+18
3 1.5
4 0.5
}
finish_test
+27
View File
@@ -914,4 +914,31 @@ do_catchsql_test 21.0 {
SELECT * FROM zipfile(X'504B03040A0000000000000000000000000000000000000000000100000078504B010200000A0000000000000000000000000000000000000000000100000000000000000000000000E2FFFFFF78504B050600000000010001002F0000001F0000000000');
} {1 {failed to read LFH at offset -30}}
#--------------------------------------------------------------------------
reset_db
load_static_extension db zipfile
# This test requires a non-default SQLITE_MAX_LENGTH value to run.
#
if {[catch {db one {SELECT length( zeroblob(1200000000) )}}]==0} {
do_catchsql_test 23.0 {
SELECT length(zipfile(name,0,0,data,0)) FROM (
SELECT 'a' AS name, zeroblob(1000000000) AS data
UNION ALL SELECT 'b', zeroblob(1200000000)
);
} {1 {out of memory}}
}
# Bug 2026-06-03T10:58:51Z
do_catchsql_test 25.0 {
WITH t(v) AS (
SELECT unhex(
'504B03041400000000000000000000000000000000000000000001000000
61504B01021E031400000000000000000000000000000000000000000001
000000000000000000000000000000000061504B05060000000001000100
2F0000001F0000000000',char(10,13,32))
UNION ALL SELECT 'x'
) SELECT z.name FROM t, zipfile(t.v) AS z;
} {1 {cannot open file: x}}
finish_test
+10 -5
View File
@@ -17,7 +17,8 @@ Options:
--uninstall Uninstall the extension
--version-check Check extension version against this source tree
--destdir DIR Installation root (used by "make install DESTDIR=...")
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
--extlibs LDFLAGS required for external libs, e.g. ICU.
Other options are retained and passed through into the compiler.}
@@ -29,8 +30,9 @@ set infoonly 0
set versioncheck 0
set CC {}
set OPTS {}
set DESTDIR ""; # --destdir "$(DESTDIR)"
set DESTDIR "" ; # --destdir "$(DESTDIR)"
set tclConfigSh ""; # --tclConfig.sh FILE
set LIBS {} ; # --extlibs "-lx -ly ..."
for {set ii 0} {$ii<[llength $argv]} {incr ii} {
set a0 [lindex $argv $ii]
if {$a0=="--install-only"} {
@@ -61,6 +63,9 @@ for {set ii 0} {$ii<[llength $argv]} {incr ii} {
} elseif {$a0=="--tclConfig.sh" && $ii+1<[llength $argv]} {
incr ii
set tclConfigSh [lindex $argv $ii]
} elseif {$a0=="--extlibs" && $ii+1<[llength $argv]} {
incr ii
lappend LIBS [lindex $argv $ii]
} elseif {[string match -* $a0]} {
append OPTS " $a0"
} else {
@@ -152,8 +157,8 @@ if {$tcl_platform(platform) eq "windows"} {
}
set CFLAGS -fPIC
regexp {TCL_SHLIB_CFLAGS='([^']+)'} $tclConfig all CFLAGS
set LIBS {}
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBS
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBSTUB
lappend LIBS $LIBSTUB
set INC "-I$srcdir/src"
set inc {}
regexp {TCL_INCLUDE_SPEC='([^']+)'} $tclConfig all inc
@@ -312,7 +317,7 @@ package ifneeded sqlite3 $VERSION \\
# Generate and execute the command with which to do the compilation.
#
set cmd "$CMD -DUSE_TCL_STUBS tclsqlite3.c -o $OUT $LIBS"
set cmd "$CMD -DUSE_TCL_STUBS tclsqlite3.c -o $OUT [join $LIBS { }]"
puts $cmd
file delete -force $OUT
catch {exec {*}$cmd} errmsg
+3 -3
View File
@@ -2193,7 +2193,7 @@ int main(int argc, char const * const *argv){
printf("%s\n", sqlite3_str_value(pStr));
return 0;
}
if( z[i]=='-' ){
if( z[0]=='-' ){
fprintf(stderr,
"unknown option: \"%s\". Use --help for more detail.\n", z);
return 1;
@@ -2262,7 +2262,7 @@ int main(int argc, char const * const *argv){
append_escaped_arg(pStr, zSsh, 1);
if( iPort>0 ) sqlite3_str_appendf(pStr, " -p %d", iPort);
sqlite3_str_appendf(pStr, " -e none");
append_escaped_arg(pStr, ctx.zOrigin, 0);
append_escaped_arg(pStr, ctx.zOrigin, 1);
if( iRetry ) add_path_argument(pStr);
append_escaped_arg(pStr, zExe, 1);
append_escaped_arg(pStr, "--origin", 0);
@@ -2311,7 +2311,7 @@ int main(int argc, char const * const *argv){
append_escaped_arg(pStr, zSsh, 1);
if( iPort>0 ) sqlite3_str_appendf(pStr, " -p %d", iPort);
sqlite3_str_appendf(pStr, " -e none");
append_escaped_arg(pStr, ctx.zReplica, 0);
append_escaped_arg(pStr, ctx.zReplica, 1);
if( iRetry==1 ) add_path_argument(pStr);
append_escaped_arg(pStr, zExe, 1);
append_escaped_arg(pStr, "--replica", 0);