Compare commits

...

118 Commits

Author SHA1 Message Date
drh 7644162026 Use SQLITE_FINISH in a few places in the core, to help ensure that path is
well tested.

FossilOrigin-Name: 7356bf3a813bcd9082a7fdef5e2cc38c7a0f142f0ef4c948f78e4dafa216c039
2026-06-19 22:57:44 +00:00
drh fa8e52021f Put the sqlite3OomStr singleton in "const" space to ensure that it is
never modified.  Doing so identified a long-standing bug.

FossilOrigin-Name: 2fe53e6d68c3f9f1c4b064fa40fe8efe12025179a973182f0bb256acb9b5d58d
2026-06-19 22:17:09 +00:00
drh ec4f18fed8 Additional changes based on Claude analysis.
FossilOrigin-Name: d4691a0db1e96b646d3094f183b1fc330411a2d2472b09f9b5fe0fb268b5ca09
2026-06-19 21:43:04 +00:00
drh 9487f6d441 Further refinements and uses for sqlite3_result_str().
FossilOrigin-Name: 974253a6058a7120354261b2134ed4803373031996957c7334161370b80bf428
2026-06-19 20:01:47 +00:00
drh 7b386a77ff Prototype implementation for a new sqlite3_result_str() API.
FossilOrigin-Name: cdbc62c36a37ad687589917c6f1e92ded6d99959c54eb8d79eaaef6fa57dacd3
2026-06-19 17:03:21 +00:00
drh 3a697a26de Fix the format() SQL function so that it returns an empty string not a
NULL if the first argument is an empty string.
[bugs:/info/2026-06-19T16:40:04Z|Bug 2026-06-19T16:40:04Z]

FossilOrigin-Name: ece7af98a8bf982567b489cf82a52519f46a1c9360c82a486dbe1cd0664b1555
2026-06-19 16:55:08 +00:00
dan 593b55cb78 Fix a cast in fts3_write so that it is applied as intended. Bug [bugs:/info/2026-06-19T07:56:23Z | 2026-06-19T07:56:23Z].
FossilOrigin-Name: d6a3272e5592bcfeecf8a06dd8330cce57ff6603b24994b533d1fdcd48b5dc66
2026-06-19 11:46:05 +00:00
dan 8c4a4acc02 Fix an fts5 problem causing attempts to create locale=1 tables with more than 115 columns to fail. Bug [bugs:/info/2026-06-19T05:19:08Z | 2026-06-19T05:19:08Z].
FossilOrigin-Name: 979229f720e63d0294be14dae3f9fad68f76e4126a0ad63e32573cdfecd0151e
2026-06-19 11:14:16 +00:00
drh 978b0abe4d Fix a memory size computation error on 32-bit platforms caused by
check-in [9a2a230464e43140].

FossilOrigin-Name: dc4763b14c421710f2a19c19c1cac455c1d0244b27303b6f328c778ac188bb02
2026-06-18 17:09:20 +00:00
drh e070f37183 Small parsing performance improvement by reducing the amount of the
Parse object that needs to be initialized.

FossilOrigin-Name: 0901b7c2dfb87707fa159f24ada5abb0a2914043c6f0571de4ce55c80edb663b
2026-06-17 20:11:26 +00:00
drh b5d0d980be Remove the unnecessary Parse.szOpAlloc field, for small size reduction
and performance improvement.

FossilOrigin-Name: 9a2a230464e4314033e67e602dbd9f554f50ec2eefc7b1a5f05b85249591f7b8
2026-06-17 19:28:17 +00:00
drh 3dbf444538 Small performance boost in the sqlite3VdbeResolveLabel() routine of the
code generator.

FossilOrigin-Name: f786f3643e410e862568777ea021afa47c924348e511a83e7e9000cf14bec534
2026-06-17 18:39:05 +00:00
drh 3f7bf4ef2f Safer conversion from double to 64-bit integer in two places.
FossilOrigin-Name: 17c444382979b70cdca78e51418366e802b2d41d1156774e5e9693b52542b84c
2026-06-17 16:57:19 +00:00
drh c9bffdb35e Additional refinements to the large floating-point handling in
generate_series().  Follow-up to [5aab8c2cde63f9db].

FossilOrigin-Name: 4247c5d9afb162a3e9f334b5121f0df2bfddb916054fa1e6fadb65b1983a7ed8
2026-06-17 14:53:14 +00:00
drh ffc14a20ad Fix CLI CSV test cases so that they suppress the CR on windows and thus
work cross-platform.

FossilOrigin-Name: 7a2c96405e365dd2efb3593e0973536d1f87f7183d5442f3bc98ca23310e5530
2026-06-17 13:52:55 +00:00
drh aa1579de80 Fix the OR-to-IN optimization so that it works in cases where there are
conflicting collation sequences on the equality constraints within the OR.
[bugs:/info/2026-06-17T05:04:48Z|Bug 2026-06-17T05:04:48Z].

FossilOrigin-Name: 984c9b181801c1de06782335eb049f32d1dc1d5739a7fb9c94630c22159a4f8c
2026-06-17 13:31:01 +00:00
drh 8227408b6f Typo fix in a comment used to generate documentation. No changes to code.
[forum:/info/2026-06-16T23:18:50Z|Forum 2026-06-16T23:18:50Z].

FossilOrigin-Name: 7386faef618acb006086d688fcea854a7c555ac1bcfcaa294ea86e964e4ce75f
2026-06-16 23:59:58 +00:00
drh 9fb225190c Limit VIEW recursion depth to SQLITE_LIMIT_EXPR_DEPTH to prevent
static overflow in malicious schemas with tens of thousands of
levels of recursive views.
[bugs:/info/2026-06-16T04:21:51Z|Bug 2026-06-16T04:21:51Z]

FossilOrigin-Name: 3f3fb9b638f59ad982beafb7c117f24ddd3da612e62c862510805fa672ffae06
2026-06-16 13:43:08 +00:00
dan b7c32f2f29 Fix instances of potential buffer overflow caused by loading the contents of a stat4 table with an absurd number of samples in a 32-bit build. Bug [bugs:/info/2026-06-16T11:30:52Z | 2026-06-16T11:30:52Z].
FossilOrigin-Name: 0b72246732fecd7909add28f2d95f1727e1c4dc6c8f3b8e6e3482f6d17c92d34
2026-06-16 11:53:19 +00:00
drh 09c84c70ee Fix a possible call to memcpy() with a NULL source pointer when the size
parameter is zero (which is technically undefined behavior but in practice
is completely harmless) in the sha1_query() extension function.
[bugs:/info/2026-06-16T07:42:23Z|Bug 2026-06-16T07:42:23Z].

FossilOrigin-Name: 2063926473adaf9619ca10fd47b273ef59b1f77136836d575e5db3cfd68987da
2026-06-16 09:53:23 +00:00
drh 9a5801af3a Consistent error messages for excess trigger nesting.
FossilOrigin-Name: 4fb9f2ffb4b45d81c70f561f45cf29a0d5872a612b948882c4a2a14629bcbe28
2026-06-15 17:39:46 +00:00
dan a0dc22438d Speed up SQL aggregate functions percentile() and median() by using quickselect to find the required values instead of fully sorting the array of values with quicksort.
FossilOrigin-Name: 0796d337f6a0ef02a460a24eadda20e33e8fb9ec64b696ae1addee69c1bfddeb
2026-06-15 17:27:05 +00:00
drh f0075cd2e4 New Windows makefile targets for common EXEs that omit the ".exe" suffix, so
that when muscle memory kicks in and we type "make sqlite3" on windows, it
still works.

FossilOrigin-Name: 1152463a66b47eed27b71e87533e8361b6077dc54ff55b8cd2ccde5cfa8199bd
2026-06-15 17:14:12 +00:00
dan b348459070 Improve comments in percentSort().
FossilOrigin-Name: 9b43500f51ae7b43f0e2cc805bb8c93907eddbd8caf21ee5b5a3d2e795962088
2026-06-15 17:13:40 +00:00
drh 458dfb94d0 Enhance SQLITE_LIMIT_TRIGGER_DEPTH so that it also limits a chain of
distinct triggers during code generation.
[bugs:/info/2026-06-15T06:44:07Z|Bug 2026-06-15T06:44:07Z].

FossilOrigin-Name: 0b5378678e3d095ef982bb3b5d5ad05dfb15ce4ee12170b8d0a83fa4b75404c0
2026-06-15 16:45:35 +00:00
stephan 91a3aa3646 Change the PACKAGE_BUGREPORT config option point to /bugs instead of /forum.
FossilOrigin-Name: ca15fedede9873b5f72f29f7cd33cba294cd49593999fc952670e2d5ce7ec86e
2026-06-15 15:48:40 +00:00
dan 1b5bd0edf1 Fix a problem sometimes causing an UPSERT to incorrectly convert an excluded.* column from type REAL to INT in cases where doing so does not cause data loss. Bug [bugs:/info/2026-06-15T09:08:12Z | 2026-06-15T09:08:12Z].
FossilOrigin-Name: 71334f7ec95edc91138b51ef6fe455a4a8c1db130484237eb241956bc549aa5c
2026-06-15 15:38:16 +00:00
drh a2fd301a6a Improvements to handling of inequality constraints on generate_series().value
against very large floating-point values.
[bugs:/info/2026-06-15T04:37:48Z|Bug 2026-06-15T04:37:48Z].

FossilOrigin-Name: 5aab8c2cde63f9db6b2346c86512efd6297937cad4e1306759b0f448815ad2e0
2026-06-15 15:27:26 +00:00
drh 53f419e2c8 Additional tweaks and test cases for generate_series() constraints
using very large floating-point numbers.

FossilOrigin-Name: 50d611404a444f23368c684dfa6dc34b057f8adb45aa058bcf3b2768e908eb3e
2026-06-15 15:24:37 +00:00
drh 0cdc6432f7 Better behavior for generate_series() in cases where constraints involve
floating point number that are near the minimum and maximum 64-bit integer
values.

FossilOrigin-Name: 236ef21789c4ebb67a8cf0a841341fab1477a6fe8e88b575e9f450a8f868e618
2026-06-15 14:16:13 +00:00
dan 667d1b15c1 Avoid a possible buffer overrun in 32-bit builds of fts5 that could occur when processing corrupt records. Bug [bugs:/info/2026-06-14T12:21:15Z | 2026-06-14T12:21:15Z].
FossilOrigin-Name: 0fa3345fe4464804f6846c2598774b9e700df39570e81e020de21e06e2ff044d
2026-06-15 13:39:20 +00:00
stephan b1bbff20a0 Revert the native impl of kvvfs's xOpen() (as distinct from the JS impl which the wasm build uses) to the historical db name restrictions of 'local' or 'session', failing with SQLITE_CANTOPEN if passed another name. [ec866b04d088e53b] overhauled support for kvvfs db names in JS but it turns out that the native impl still relies on those names in order to match journals to databases. Correct a related too-lenient assert() in the WASM pieces.
FossilOrigin-Name: 4b3ec30c63e3824163a2e6cacceb9630301b61f3ffd2b80f8a7b234f09bc251b
2026-06-15 12:36:24 +00:00
dan 23e50585eb Fix a problem that could cause fts5 to return incorrect answers when performing prefix queries on tokens with synonyms. Bug [bugs:/info/2026-06-14T11:11:06Z | 2026-06-14T11:11:06Z].
FossilOrigin-Name: 323d87541a63f0b2c64271c78ad6ebd5d04220da59aebfdfbc07caa691af816a
2026-06-15 11:47:52 +00:00
dan b273dc8de1 Regardless of whether the platform is 32 or 64-bits, Use 64-bit arithmetic to calculate buffer sizes in the fts3_snippet(). Bug [bugs:/info/2026-06-14T09:19:52Z | 2026-06-14T09:19:52Z].
FossilOrigin-Name: 79dc1949b2171c46f6649743ed7dbbf6b83046901ec18ffcbc37a2a47544b100
2026-06-15 11:03:13 +00:00
drh 9c2ac0b6e3 Fix rounding behavior in the decimal extension when all leading digits
are 9 and there is not fractional component.
[bugs:/info/2026-06-15T03:49:42Z|Bug 2026-06-15T03:49:42Z].

FossilOrigin-Name: c6a3b18ee9eb4b8dda57fab94aea9c61aed5e1ffe600f0bcf2c90ca752f2512b
2026-06-15 10:13:31 +00:00
drh a5e5116228 Prevent array overflow when decoding a corrupted value from the
underlying key/value store.
[bugs:/info/2026-06-14T21:58:12Z|Bug 2026-06-14T21:58:12Z]

FossilOrigin-Name: 732c8f81b5a914831c36610ddaed3da15a7f9fdbf54f44872e181b941368d702
2026-06-15 01:24:06 +00:00
drh 5d59375ac8 Remove the unused, untested, experiemental "blobio.c" extension, to
avoid confusing AIs.
[bugs:/info/2026-06-14T15:12:50Z|Bug 2026-06-14T15:12:50Z]

FossilOrigin-Name: 45918d5e97a0c29c6fa03d09ac8e131dcca3bf4268bf4f5c46c221b1f900651a
2026-06-14 22:01:56 +00:00
drh 1b828b8770 Do not allow ridiculous "columns=N" values in the (unused) csv virtual
table in the extensions folder.
[bugs:/info/2026-06-14T15:22:47Z|Bug 2026-06-14T15:22:47Z]

FossilOrigin-Name: ecae4a2ddf103fe575c6864d201e83a9bb084b511685397db41b3349c91b38e6
2026-06-14 20:10:28 +00:00
dan 36e9e015de Speed up SQL aggregate functions percentile() and median() by avoiding a full sort of the array of arguments.
FossilOrigin-Name: 9232b5f21d76dc702ccda5c689d61bcd0057fb1f2a4db6a70c607c25ad03a027
2026-06-13 20:16:54 +00:00
drh d8f6cc7ea4 Make the --header option to the CLI sticky, so that it does not get
turned off by subsequence --csv or similar mode change options.
[bugs:/info/2026-06-13T11:49:18Z|Bug 2026-06-13T11:49:18Z]

FossilOrigin-Name: b19cef1862444ee694eeea2254aa9a8d74d2343da5a8257c22e3068f388aa2fd
2026-06-13 18:04:18 +00:00
dan 2884421c05 When reading a super-journal name from a journal file, allocate a new buffer rather than using Pager.pTmpSpace. This prevents a buffer overrun that could occur when using a VFS with a large sqlite3_vfs.mxPathname value with a database with a small page size.
FossilOrigin-Name: 7f71859841af7cb0806f58e9c8013a990fcca72b807a0513156d7127ce5c7b62
2026-06-12 18:35:24 +00:00
dan 7459c01689 Fix errors in comments on this branch. Also prefer SQLITE_NOMEM_BKPT to SQLITE_NOMEM.
FossilOrigin-Name: ac17669e840dbac5c7c75e9b6014cca2d289aba8de36f9d1d0d61186e8cc6207
2026-06-12 17:32:44 +00:00
dan 053048a40f Fix a memory leak that could follow an OOM error in the new code on this branch.
FossilOrigin-Name: d4774a898730d9ef7564bba0a8531748e31e6517ab29564c2f5a0196c1584451
2026-06-12 17:16:12 +00:00
drh 2ca10782d2 Improved documentation for sqlite3_deserialize().
FossilOrigin-Name: f15d076820f4a0d9e7fa32d99575bce27bde5e987bb415e6cfb69b06f0da7e1e
2026-06-12 16:47:45 +00:00
drh 2429af2e0c Do not use shared locks on SHM files when the filename is a long DOS-device
path.  Only used shared locks for UNC paths.  Do not confuse the
long-DOS-device syntax with UNC paths.

FossilOrigin-Name: a4691489f21bb1645bb8de649268dd457af53c5f613f2a7fd2e5569f029efa87
2026-06-12 16:26:39 +00:00
dan 865a8f3072 Fix a buffer overwrite in fts3 that could occur while processing NEAR queries against corrupt records. Bug [bugs:/info/2026-06-11T23:11:26Z | 2026-06-11T23:11:26Z].
FossilOrigin-Name: b0f773e99eb45cde0953e4870a0a7436c35277c95146fdab3aa06ebbc076c79e
2026-06-12 15:36:26 +00:00
drh 124f449319 When using a read-only WAL/SHM, handle a corrupt page size in the WAL
file correctly.
[bugs:/info/2026-06-11T22:20:03Z|Bug 2026-06-11T22:20:03Z].

FossilOrigin-Name: 09ab0a1bac4eb7de651f78cfd3027b452308da7e04c4ccd7f46c402c82fd6ca5
2026-06-12 12:15:42 +00:00
drh 76ad3be617 Add the --raw option to the dbtotxt command-line tool, for debugging.
FossilOrigin-Name: abfecc08209c9377b6762125b2372e4eb1ab56b4d0399467c8fbe5cfc11c806e
2026-06-12 11:55:39 +00:00
dan 23d0a08176 Fix a signed integer overflow that could occur in fts3 when processing corrupt database records. Bug [bugs:/info/2026-06-11T23:12:25Z | 2026-06-11T23:12:25Z].
FossilOrigin-Name: 978d04f051c06aff798f915b0774da19a0b4f89f9daee124f7e62b12afaaced8
2026-06-12 11:24:30 +00:00
drh b14202f86e Comment improvements on the ".ar -x" command of the CLI. No changes to code.
FossilOrigin-Name: 5b939fb1a284088c4bd46adf517cf598816e2262cd77ee2d9caaab1cef2ce9a1
2026-06-11 23:11:14 +00:00
drh 0b9f4ee89c Fix harmless compiler warnings.
FossilOrigin-Name: dd0c161fcd1619518cd4671d64afb6afeec44c140ec176ccb8616d381a88f42f
2026-06-11 22:48:16 +00:00
drh d1b9001a7f Further improvements to the ".ar" command of the CLI.
FossilOrigin-Name: 6149b938c7a1e95a0fb8600a81557dd0e3efb7b312f3806e2c09d03acf9f4b17
2026-06-11 16:39:41 +00:00
drh d57abdb017 Three-pass algorithm for the ".ar x" command in the CLI, so that symlinks
are created after all regular files are created.

FossilOrigin-Name: 37a80d20fe1948db15ac72432ed7bf3d573c80807fe0a58c58440647e3c34ab8
2026-06-11 14:28:48 +00:00
drh 970b3bc4c4 Add the (undocumented) --debug option to the ".ar" command in the CLI
FossilOrigin-Name: 3a040ffc47fa3e38b36716587c56d9b071d9c69d9daaa9cf0ef6baa654419ab5
2026-06-11 14:14:37 +00:00
drh d688d1551a Improved detection of corrupt node IDs in RTree shadow tables.
Test case in TH3.

FossilOrigin-Name: e01a185a699d0c4ad2341ce2114bc826f02768735cef67179a1127229a073d03
2026-06-11 01:31:19 +00:00
dan dacabb4a33 When reading a super-journal name from a journal file, allocate a new buffer rather than using Pager.pTmpSpace. This prevents a buffer overrun that could occur when using a VFS with a large sqlite3_vfs.mxPathname value with a database with a small page size.
FossilOrigin-Name: 37aa82a50a0a1c5edb4c4f2de1cb00fa009ebbfeb420df3de72231c5d883518a
2026-06-10 20:10:19 +00:00
dan 2bd7ac6716 Fix a signed-integer overflow in fts5 that might occur when dealing with strategicly corrupted records. Bug [bugs:/info/2026-06-10T03:56:42Z | 2026-06-10T03:56:42Z].
FossilOrigin-Name: fc6442ee54795fbeb746539193716238aa653d80170523bc327ae3ce0d945ebf
2026-06-10 16:51:20 +00:00
drh 49edbe2150 Detect an OOM condition in the realpath() function of the fileio.c extension
and cause that function to return NULL.  To Do:  we should go back in and
fix realpath() to raise an SQLITE_NOMEM error on OOM rather than returning
NULL.  But we will delay that, in as much as OOMs are all but impossible
on modern OSes.
[bug:/info/2026-06-10T07:46:32Z|Bug 2026-06-10T07:46:32Z].

FossilOrigin-Name: 8b961dc3d27c5aa62a5dc7c2e44f8b505817e184f8499f3bb903e06b5aec1b72
2026-06-10 10:40:29 +00:00
drh 062016c2fd Fix a possible signed integer overflow in the RBU extension given a
maliciously crafted delta.
[bugs:/info/2026-06-10T06:41:54Z|Bug 2026-06-10T06:41:54Z].

FossilOrigin-Name: 8531c0c3b61771592b055b0c22e903b8301a4161c7bcb7f9fc54d730b080d095
2026-06-10 10:13:11 +00:00
drh 84ead09d94 Harden code that processes Fossil Deltas against OOM and maliciously
malformed delta blobs.
[bugs:/info/2026-06-10T07:01:00Z|Bug 2026-06-10T07:01:00Z] and
[bugs:/info/2026-06-10T07:06:43Z|Bug 2026-06-10T07:06:43Z].

FossilOrigin-Name: 67271c31292bc1bddbb5e144c881c85c9f91b3963a1db4bae1f738adab50f7c0
2026-06-10 09:51:33 +00:00
dan 2cb57d9d4a Avoid a possible integer overflow when fts5 tokenizes a very large document. Only possible with non-standard builds that use large values of SQLITE_MAX_LENGTH. Bug [bugs:/info/2026-06-09T05:27:16Z | 2026-06-09T05:27:16Z].
FossilOrigin-Name: d562e91374e2bebcf75a00776b4def532bb71914a07e37c8507f7a5918db1d3b
2026-06-09 10:43:37 +00:00
drh 2f5d281796 Change loop counter variables from int to i64 to avoid a potential
integer overflow inside an assert() statement when SQLite is compiled 
with SQLITE_DEBUG and an extra-large SQLITE_MAX_LENGTH.  Does not
affect production builds.
[bugs:/info/2026-06-09T08:53:14Z|Bug 2026-06-09T08:53:14Z].

FossilOrigin-Name: 77f615d9833b1f5eaabcb1a6b59af3a6698752abcd16592091f1630beec5969e
2026-06-09 10:16:40 +00:00
drh 6a1efec20a Fix builds on i486 CPUs. [forum:/info/2025-01-25T12:58:44Z|Forum 2025-01-25T12:58:44Z].
FossilOrigin-Name: 4cb349370daab17123770c814c71872a3e4c616a3f984569b3d7f97f9c3f5ea0
2026-06-08 18:15:27 +00:00
dan 082e41f17b Fix another buffer overread in fts5 when processing corrupt records. Bug [bugs:/info/2026-06-08T16:03:39Z | 2026-06-08T16:03:39Z ].
FossilOrigin-Name: 8ba5acabf9a0273ffbc2ba0bacc7f0b000690db91081858e4e563d6cbeeb4e7a
2026-06-08 17:48:00 +00:00
dan 19a2ba1f5b Fix a buffer overread that could occur in fts5 when processing corrupt records. Bug [bugs:/info/2026-06-08T11:15:52Z | 2026-06-08T11:15:52Z]
FossilOrigin-Name: b07441cfc06b8e6b47a4f4a6e0f5c261da580d5afe82444cc7f42a9f39ea7026
2026-06-08 15:20:49 +00:00
dan b677c5afd4 Avoid a potential use-after-free in fts5. Report [bugs:/info/2026-06-08T08:45:27Z | 2026-06-08T08:45:27Z].
FossilOrigin-Name: 9c018b02dbfb071c748d540ad679a4dbdc0fb88a62988e02cb51a3403509febe
2026-06-08 12:03:52 +00:00
dan 7340b032d1 Clamp the nToken parameter to the fts5 snippet() function between 0 and 64. It has always been documented this way, but not previously implemented. Report [bugs:/info/2026-06-08T08:29:00Z | 2026-06-08T08:29:00Z].
FossilOrigin-Name: 4af1d9b3e54a7c42552e61284456bbd7089e525d4aa55e580f7518956d8521bb
2026-06-08 11:24:05 +00:00
dan 2bc3763ec5 Add extra tests to check that non-deterministic functions may not be used in indexes.
FossilOrigin-Name: beeef9dc2b1d778ca628c5e3adc097778646933233ea5ea4f03d2cace0199c17
2026-06-08 10:47:55 +00:00
drh a6812a4242 Improvements to the GCC compiler bug work-around of check-in [7fae321095ebec77].
FossilOrigin-Name: 247894f70d8616cb16468025809513a7db70086d24d2a289b50b4e8d9e073eb4
2026-06-06 18:32:53 +00:00
drh 6bf7825ac5 Minor performance enhancement and improved comments on the quicksort
algorithm used by the median() implementation in func.c.

FossilOrigin-Name: 2800f6a75bbb6ddc86f2e029a7d36ff08febe03812302fb7931eb68da316f74d
2026-06-06 17:20:35 +00:00
drh 192b3a539b A new approach to working around the GCC bug.
FossilOrigin-Name: 2f95186ea568b27d45bd19fca1e03b878afb0b1ea0938875897c7323bdeab8a2
2026-06-05 00:11:56 +00:00
drh 002d33d8c5 Disable the vector-IN-SELECT optimization if the number of columns is so
large that it would cause the WhereTerm.nChild column to wrap.
[bugs:/info/2026-06-04T10:00:49Z|Bug 2026-06-04T10:00:49Z].

FossilOrigin-Name: bb49dfc948048779a30deff9a3d1bb39846f6f72c26a2bdcdd0e386251720fe6
2026-06-04 16:56:11 +00:00
dan ee181f479a Fix a crash that could be caused by configuring the pager-cache with a bulk allocation too small to fit even one page. Bug [bugs:/info/2026-06-04T07:03:12Z | 2026-06-04T07:03:12Z].
FossilOrigin-Name: b4b9dc632b06f932759bc2fceeb6fa1dd6e0de329106ae1d34be874ea1695859
2026-06-04 11:48:18 +00:00
drh 076db92d85 Fix a possible NULL pointer derefence in the (experimental and untested)
uuid.c extension.
[bugs:/info/2026-06-04T09:50:59Z|Bug 2026-06-04T09:50:59Z].

FossilOrigin-Name: fa6374fe3ae1530f0b5ba10b7e6fb703ffe5dd592c532a965e7d50b7d2d70a5f
2026-06-04 11:42:23 +00:00
drh 2dacda40a6 Extra testcase() macros to ensure adequate testing of the previous
check-in.

FossilOrigin-Name: 003013ccabaaa7aea1e78844474ed5032ee9c9824f98c5d36687ac5256a5e128
2026-06-04 11:39:13 +00:00
dan 62a3734e78 Fix problems with expressions like "(?,?,?) IN (SELECT c,b,a FROM ...)" when there is an index on columns "c", "b" and "a", but not in that order. Bug [bugs:/info/2026-06-04T07:02:53Z | 2026-06-04T07:02:53Z].
FossilOrigin-Name: 07667afd0f17b73b58df8ace6a2a5c3a593276f9b7804cb14d4705051258dd75
2026-06-04 11:19:43 +00:00
drh 95d072cc81 Clearly mark the ext/misc/wholenumber.c extension as "testing and
debugging use only".  Fix a potential integer overflow that can occur
if the above warning is ignored.
[bugs:/info/2026-06-04T09:40:28Z|Bug 2026-06-04T09:40:28Z].

FossilOrigin-Name: 44154ea9ae99d532d5c7268d70bd8b32751f7a82c367c7bd1ec0e6948d71d1b8
2026-06-04 11:18:11 +00:00
dan 0120735de1 Update the utf-8 decoder in the ICU extension to treat invalid sequences as codepoint 0xFFFD, matching the core. Report [bugs:/info/2026-06-03T04:04:46Z | 2026-06-03T04:04:46Z].
FossilOrigin-Name: 840be0ee62c0ba34f4916c382e2d07071bebd8ce7bca31deb1616869722bfa4d
2026-06-03 17:21:12 +00:00
dan d80528ad4d Fix a faulty assert() in rtree that could fire when processing an unusually large record. Bug [bugs:/info/2026-06-03T14:44:46Z | 2026-06-03T14:44:46Z].
FossilOrigin-Name: e7335dd377a73fc2b913076ee659ed2b0c4a131b16e04b1b55fae677d6b56e8a
2026-06-03 16:46:15 +00:00
drh c2d29194a8 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.
[bugs:/info/2026-06-03T07:26:42Z|Bug 2026-06-03T07:26:42Z].

FossilOrigin-Name: 7dc987165c030c260ba90a8878291b5ceb037c48c2f437a8fb3f05b6c4f84fde
2026-06-03 16:21:17 +00:00
dan 61523e22f9 Fix an integer overflow problem in fts3 that could lead to a buffer overwrite on platforms where size_t is 32-bits. Bug [bugs:/info/2026-06-03T04:28:51Z | 2026-06-03T04:28:51Z].
FossilOrigin-Name: ef0c66d2a2e0b8f523633efca66a97236bb5a502525eb6a00a28a350ec7c76e6
2026-06-03 15:29:59 +00:00
dan 51b2c3863b Fix another buffer overread in fts5 that could occur when processing corrupt records. Bug [bugs:/info/2026-06-03T03:54:40Z | 2026-06-03T03:54:40Z].
FossilOrigin-Name: b5337c87cc314e6830615e4efe2d4723fa7cedf87ce404f60d6e520aeab77cbc
2026-06-03 14:58:13 +00:00
dan 6feeafc7de Fix another potential buffer overrun that could occur in fts5 when processing corrupt records.
FossilOrigin-Name: 6ee44b199512b8cac604bf062f893a9047af4b5bfc881bb7cb69ae42d0a0adb4
2026-06-03 13:49:33 +00:00
drh a735462db6 Fix a potential UAF bug in the zipfile extension.
[bugs:/info/2026-06-03T10:58:51Z|Bug 2026-06-03T10:58:51Z].

FossilOrigin-Name: 1fb5e9169ace6bea2bdf9013f39002c1ce5dc9ce51d6007bec22d91f456c15f0
2026-06-03 13:12:20 +00:00
drh d2240cc988 Fix negative array index in "testing and debugging uses only" extension
qpvtab.c.
[bugs:/info/2026-06-03T07:26:26Z|Bug 2026-06-03T07:26:26Z].

FossilOrigin-Name: d066699fcacd87496645f3aa3c4049935410ae2451879a033102304c80273deb
2026-06-03 12:43:50 +00:00
dan 942b7c555a Avoid excessive recursion and stack overflow in fts3 when processing a corrupt
database.

FossilOrigin-Name: 21369378769195f20f839231f625582552eaa3f79044ca3e3efb7f9476b515a8
2026-06-03 11:37:45 +00:00
drh 069e5acd63 The prefix_length() function should stop at the first NUL terminator.
[bugs:/info/2026-06-03T07:42:00Z|Bug 2026-06-03T07:42:00Z].

FossilOrigin-Name: a9b8bdea0683bb03015ea1ee38f75636c80c189eed4b786b6d3d654a831cfdfb
2026-06-03 11:07:47 +00:00
drh 1c0a370472 Make the (unused, untested, and unsupported) ext/misc/compress.c routines
responsive to OOM conditions.
[bugs:/info/2026-06-03T08:28:36Z|Bug 2026-06-03T08:28:36Z].

FossilOrigin-Name: e3120e2a4339d51210645b14d075abba27dd97bd6bd6d42f445dd5baf3d337e3
2026-06-03 10:55:08 +00:00
dan 2acb57c1be Fix a case where sqlite3expert could be tricked into executing arbitrary SQL by a corrupt database schema.
FossilOrigin-Name: 8a633070e62bdc83a7cf895fd1a22c04b13579659df7cee9584d95096bfffab1
2026-06-02 15:20:37 +00:00
dan 2a28b15748 Add extra test case to zipfile.test. No code changes.
FossilOrigin-Name: 83fe72bcdf866bdaf3043ae5b0c1eb45a9d50a01b24b7a531858271dd746baab
2026-06-02 11:11:02 +00:00
drh b1637e5408 Fix the CLI so that it works when compiled using STDCALL on
Microsoft x86.  Change should not affect other platforms.
[forum:/info/2026-06-02T09:44:12Z|Forum 2026-06-02T09:44:12Z].

FossilOrigin-Name: 83adece349aed73b8d0a3aec141213ea329150eb529f4fd9774ca157b49d02fc
2026-06-02 10:08:30 +00:00
drh b48ca02d64 Enhance PRAGMA integrity_check so that it better detects incorrect
header sizes at the beginning of cells.

FossilOrigin-Name: 08bb2878e7575ab069f8f132537880a47a4d4543a1ac8bffc55e32488223245c
2026-06-01 20:02:17 +00:00
dan c28f2d22b6 Disable transitive WHERE constraints when there are explicit COLLATE operators. Fix for report [bugs:/info/ffddcd3617 | 2026-05-31T08:33:10Z].
FossilOrigin-Name: 18ee3a17c589cfd34500b6a6547d0cb51aea4dd14b4e1e4b2d0cf0dbfb32378e
2026-06-01 18:01:13 +00:00
dan 48a591fa6b Minor performance improvement for the patch on this branch.
FossilOrigin-Name: 2702fecc5c47704bdae535459e59260b55c571ff3b7d09617541e36829d4cf9c
2026-06-01 17:56:11 +00:00
dan 2c351bbf82 Fix minor problems surrounding transitive WHERE constraints and explicit COLLATE terms.
FossilOrigin-Name: 9500238a1d603a3f08a8fc0954725d5d217aab339720146ea0bc700e47b81c3c
2026-06-01 17:40:23 +00:00
drh ddea119f82 Make sure the authenticator is called for columns that are part of
a USING in a FULL JOIN.
[bugs:/info/2026-05-31T02:00:37Z|Bug 2026-05-31T02:00:37Z].

FossilOrigin-Name: 4ef88a36f9d9669b0d74c58f79ad497803885ff6078e5f9685f13c96eab397cc
2026-06-01 16:49:39 +00:00
dan 03aa9a7b50 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. Bug report [bugs:/info/0785f45e67 | 2026-05-31T02:10:44Z].
FossilOrigin-Name: 04d7a9d788cf0bb811483baceb9142f67d4a2380d4af409d5300a92f7972472e
2026-06-01 16:20:40 +00:00
dan 62d17739bc Better handle a (possibly) potential buffer overrun in fts5. Based on the report in [bugs:/info/38e75aa4f9 | 2026-05-31T09:06:13Z].
FossilOrigin-Name: 9d0e39408075f22dd56ad5fb50ef458c0cd6a4ec234dd43b3a5f5e0ac4447b61
2026-06-01 15:03:53 +00:00
stephan f55434ab30 Remove the data type ANY added to the shell's CSV exports in [aff74e71ea734e1a], as discussed in [forum:2ea4c50f69fc9829|forum post 2026-06-01T12:01:59Z].
FossilOrigin-Name: a6a347aec5ff33b24d877ac0f04018f4e93748361da62ed27b1abec77840963e
2026-06-01 13:14:48 +00:00
drh 0a04687373 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.
This is a replacement for the fix at [3c0a277e6741c722].  Fix
for multiple dbsqlfuzz reports and probably also a fix
for [bugs:/info/b6c6fad96c|Bug 2026-06-01T07:23:11Z].

FossilOrigin-Name: d96271db6a3a44e50d1a977250c4cc14178612a6c838e7c51c5f79fda45ae19f
2026-06-01 12:36:28 +00:00
drh c079bd08a2 Test case to show that the change fixes the original carray problem.
FossilOrigin-Name: 8df6671ae8211b706b7d4f073c5166f0f41f3c11339bc4d28997e8a205a39545
2026-06-01 12:30:13 +00:00
drh 5cae890219 Improvements to sqlite3SelectCheckOnClauses() to be more accurate in
identifying table-valued functions that references tables to the right.

FossilOrigin-Name: e5bae3687dbb470ead7e8d6bf428b1fbb1e9f10c214bc2a91e93e68fb2ae6ff7
2026-06-01 12:19:30 +00:00
drh f3eea1efa4 Back out the recent change to carray. The intent is to fix this problem
in a different way so that it works for all table-valued functions.

FossilOrigin-Name: 43e02dbb0dbe7192304125cd3298b3f4bbac02395d4d03f7f8d5f96b465eb43e
2026-06-01 12:07:21 +00:00
dan 3040da55a8 Fix an integer overflow that could lead to a buffer overrun in the zipfile extension. Bug [bugs:/info/2026-06-01T10:16:47Z | 2026-06-01T10:16:47Z].
FossilOrigin-Name: a8dac6af353c02aed8eaaba5921e036d3f3a6639367ae70e8c75d759c7b4ab52
2026-06-01 11:52:23 +00:00
dan 1a760748a6 Update new test in zipfile.test so that it does not run if SQLITE_MAX_LENGTH is too small.
FossilOrigin-Name: cc86820e198db6ee4e62f455d3dd9877d73873aaccad6ceffd0b34452d35c89c
2026-06-01 11:50:55 +00:00
dan 5481274912 Fix an integer overflow that could lead to a buffer overrun in the zipfile extension. Bug [bugs:/info/2026-06-01T10:16:47Z | 2026-06-01T10:16:47Z].
FossilOrigin-Name: 7c740d2cfd22a89258be2221860ca10985f0fc16dc7a17a99fc282d7105dc38e
2026-06-01 10:56:11 +00:00
drh 6c218ba0ad Extra defenses against integer overflows in the untested, unused, and
unsupported transliterate() SQL extension function found in the
ext/misc/spellfix.c extension.
[bugs:/info/2026-06-01T10:34:57Z|Bug 2026-06-01T10:34:57Z].

FossilOrigin-Name: 2b073519b6080abc8872b0728c64827cc088d1b43f132cd2aeb396f06de3d36f
2026-06-01 10:53:28 +00:00
drh ca8593ce68 Fix the carray virtual table so that it gives no solution if it cannot
find a usable first parameter.  dbsqlfuzz find.

FossilOrigin-Name: 3c0a277e6741c72281e12c44d85902aa6780890a7f59bacc3ac2b35ba27f7211
2026-05-31 19:41:16 +00:00
drh af6fdd2673 Test case to cover the bug fix in the previous check-in.
FossilOrigin-Name: 5b28d49b61d5edc9fef896e685bf227b7e1716c0cc666fd2ebe0d5ea0d11af06
2026-05-31 17:01:44 +00:00
drh 1cd9eb3811 Fix the zipfile extension so that ZIP archives containing files whose names
contain embedded \000 bytes do not cause problems.
[bugs:/info/2026-05-31T11:43:05Z|Bug 2026-05-31T11:43:05Z].

FossilOrigin-Name: c12ff342a90c61a0a82c8e63d2d94fecec10dff498da666873ff6aaa15c23dfd
2026-05-31 15:49:57 +00:00
drh 7437c19a01 Fiddle should default to using NO_COLOR since the JS console does not
support ANSI X3.64.

FossilOrigin-Name: bde6190fdeb530bfb92524ab5542f3f4b64adf31c31de1e00fe4430a8e00411f
2026-05-31 09:38:28 +00:00
drh d076d98ec8 Fix the format() SQL function so that it reports TOOBIG and NOMEM errors.
Fix a possible integer overflow on %#Q formatting.
[bugs:/info/2026-05-31T02:00:07Z|Bug 2026-05-31T02:00:07Z].

FossilOrigin-Name: 3bfe0510aecccf113b9d008c308fca3096e9c45c59b919c0b91bb4703415988f
2026-05-31 09:18:31 +00:00
drh 72f0bd609c Add a test to ensure an application does not try to create a geopoly
virtual table with too many columns.
[bugs:/info/2026-05-30T12:47:27Z|Bug 2026-05-30T12:47:27Z].

FossilOrigin-Name: 2c605bfb1562d7a3609ad6ffd7446def12f1ac7084e41b9c6723e998c156501d
2026-05-30 13:23:25 +00:00
drh 7aad2942c2 Harden the diskused.c extension against NULL pointer deferences that
might have previously occurred when given a corrupt database file.
[bug:/info/2026-05-30T07:08:55Z|Bug 2026-05-30T07:08:55Z].

FossilOrigin-Name: 7487a1c59d3aaea9f8b2569dca76bbccf21948b1e7bd8a1d841e04382db696f4
2026-05-30 10:24:03 +00:00
drh 07ded24fbb 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: 27d67fb175e839f6e7450f54166b52e0a6137c075758511da32fd82c57c310c4
2026-05-30 10:09:33 +00:00
drh 5b98467d28 Be sure to do floating-point to text conversions in JSON to the full
17-digits.

FossilOrigin-Name: 61a776650cdc3fe632bdb1dc39f50f542b00a9e5b468180eb54b69750d0cd70c
2026-05-29 23:14:22 +00:00
drh 3d006d0d00 Rename the ext/misc/analyze.c extension to ext/misc/diskused.c, to avoid
confusion with the src/analyze.c file.  The function is now called
"diskused(X)" instead of "analyze(X)".  The CLI command is renamed
from ".dbstat" to ".diskused".

FossilOrigin-Name: c7839f7a1749b38f8a36c06d93a7b59095e91ce753e8dd020de273ca8f73a239
2026-05-29 14:57:38 +00:00
drh 991cbd78b3 The -csv option to the CLI also sets "-limits off", for legacy
compatibility, and because that seems to make sense.
[forum:/info/2026-05-28T16:23:36Z|Forum thread 2026-05-28T16:23:36Z].

FossilOrigin-Name: d15cd64160192119a5f12afec14dbfbb30fb38a8557cb9dc559b3f061c15687a
2026-05-29 12:23:38 +00:00
113 changed files with 2711 additions and 1600 deletions
+17 -5
View File
@@ -1766,11 +1766,11 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\analyze.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\base64.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\base85.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\completion.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\decimal.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\diskused.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\ieee754.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\regexp.c
@@ -1897,9 +1897,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
@@ -2343,12 +2340,12 @@ SHELL_DEP = \
$(TOP)\ext\expert\sqlite3expert.h \
$(TOP)\ext\intck\sqlite3intck.c \
$(TOP)\ext\intck\sqlite3intck.h \
$(TOP)\ext\misc\analyze.c \
$(TOP)\ext\misc\appendvfs.c \
$(TOP)\ext\misc\base64.c \
$(TOP)\ext\misc\base85.c \
$(TOP)\ext\misc\completion.c \
$(TOP)\ext\misc\decimal.c \
$(TOP)\ext\misc\diskused.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\ieee754.c \
$(TOP)\ext\misc\memtrace.c \
@@ -2757,6 +2754,21 @@ THREADTEST3_SRC = \
threadtest3.exe: $(THREADTEST3_SRC) $(TOP)\src\test_multiplex.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\test\threadtest3.c $(TOP)\src\test_multiplex.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
# Convenienced targets for common executables that omit
# the .exe suffix
#
sqldiff: sqldiff.exe
sqlite3_rsync: sqlite3_rsync.exe
fuzzcheck: fuzzcheck.exe
testfixture: testfixture.exe
sqlite3: $(SQLITE3EXE)
showdb: showdb.exe
LogEst: LogEst.exe
wordcount: wordcount.exe
speedtest1: speedtest1.exe
kvtest: kvtest.exe
jimsh0: jimsh0.exe
# Display key variables that control which version of TCL is to be used.
#
tcl-env:
+1 -1
View File
@@ -466,7 +466,7 @@ proc sqlite-configure {buildMode configScript} {
proc sqlite-configure-phase1 {buildMode} {
define PACKAGE_NAME sqlite
define PACKAGE_URL {https://sqlite.org}
define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum
define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/bugs
define PACKAGE_STRING "[get-define PACKAGE_NAME] [get-define PACKAGE_VERSION]"
proj-xfer-options-aliases {
# Carry values from hidden --flag aliases over to their canonical
+36
View File
@@ -606,4 +606,40 @@ ifcapable fts5 {
}
}
#-------------------------------------------------------------------------
reset_db
set ci {CREATE INDEX i1 ON t1(a COLLATE "binary,sqlite_expert_rem(999,0)");}
do_execsql_test 8.0 {
BEGIN TRANSACTION;
CREATE TABLE t1(a TEXT, b TEXT);
INSERT INTO t1 VALUES('v0','d0');
INSERT INTO t1 VALUES('v1','d1');
INSERT INTO t1 VALUES('v2','d2');
INSERT INTO t1 VALUES('v3','d3');
INSERT INTO t1 VALUES('v4','d4');
INSERT INTO t1 VALUES('v5','d5');
INSERT INTO t1 VALUES('v6','d6');
INSERT INTO t1 VALUES('v7','d7');
INSERT INTO t1 VALUES('v8','d8');
INSERT INTO t1 VALUES('v9','d9');
CREATE INDEX i1 ON t1(a);
COMMIT;
PRAGMA writable_schema = ON;
UPDATE sqlite_schema SET sql = $ci WHERE name = 'i1';
}
db close
sqlite3 db test.db
do_test 8.1 {
set expert [sqlite3_expert_new db]
$expert sql { SELECT 1234 }
list [catch { $expert analyze } msg] $msg
} {1 {no such collation sequence: binary,sqlite_expert_rem(999,0)}}
$expert destroy
finish_test
+2 -2
View File
@@ -1501,7 +1501,7 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
/* The statement the vtab will pass to sqlite3_declare_vtab() */
zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
for(i=0; i<pTab->nCol; i++){
zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %Q",
(i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
);
}
@@ -1701,7 +1701,7 @@ static int idxPopulateOneStat1(
return sqlite3_reset(pIndexXInfo);
}
zCols = idxAppendText(&rc, zCols,
"%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s",
"%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %Q",
zComma, zName, nCol, zName, zColl
);
zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
+18 -3
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 ){
@@ -2063,8 +2073,13 @@ static void fts3PutDeltaVarint(
sqlite3_int64 iVal /* Write this value to the list */
){
assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
*pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
*piPrev = iVal;
if( iVal-(*piPrev)>=0 ){
/* Refuse to write a negative delta integer. This only happens with a
** corrupt db (see the assert above) and can cause buffer overwrites
** in some cases. */
*pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
*piPrev = iVal;
}
}
/*
+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 || iCol>0x3fffffff ){
if( iCol<1 || iCol>(pFts3->nColumn+1) ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
+9 -10
View File
@@ -132,10 +132,9 @@ struct StrBuffer {
/*
** Allocate a two-slot MatchinfoBuffer object.
*/
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
static MatchinfoBuffer *fts3MIBufferNew(i64 nElem, const char *zMatchinfo){
MatchinfoBuffer *pRet;
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
+ SZ_MATCHINFOBUFFER(1);
sqlite3_int64 nByte = sizeof(u32) * (2*(i64)nElem+1) + SZ_MATCHINFOBUFFER(1);
sqlite3_int64 nStr = strlen(zMatchinfo);
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
@@ -1006,8 +1005,8 @@ static int fts3MatchinfoCheck(
return SQLITE_ERROR;
}
static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
size_t nVal; /* Number of integers output by cArg */
static i64 fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
i64 nVal; /* Number of integers output by cArg */
switch( cArg ){
case FTS3_MATCHINFO_NDOC:
@@ -1023,16 +1022,16 @@ static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
break;
case FTS3_MATCHINFO_LHITS:
nVal = (size_t)pInfo->nCol * pInfo->nPhrase;
nVal = (i64)pInfo->nCol * pInfo->nPhrase;
break;
case FTS3_MATCHINFO_LHITS_BM:
nVal = (size_t)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
nVal = (i64)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
break;
default:
assert( cArg==FTS3_MATCHINFO_HITS );
nVal = (size_t)pInfo->nCol * pInfo->nPhrase * 3;
nVal = (i64)pInfo->nCol * pInfo->nPhrase * 3;
break;
}
@@ -1314,7 +1313,7 @@ static int fts3MatchinfoValues(
case FTS3_MATCHINFO_LHITS_BM:
case FTS3_MATCHINFO_LHITS: {
size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
i64 nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
memset(pInfo->aMatchinfo, 0, nZero);
rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
break;
@@ -1383,7 +1382,7 @@ static void fts3GetMatchinfo(
** initialize those elements that are constant for every row.
*/
if( pCsr->pMIBuffer==0 ){
size_t nMatchinfo = 0; /* Number of u32 elements in match-info */
i64 nMatchinfo = 0; /* Number of u32 elements in match-info */
int i; /* Used to iterate through zArg */
/* Determine the number of phrases in the query */
+5 -1
View File
@@ -3129,6 +3129,10 @@ static void fts3ReadEndBlockField(
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
/* This if() clause is just to avoid an integer overflow. The record is
** corrupt in this case. */
if( (i64)iVal==SMALLEST_INT64 ) iMul = 1;
*pnByte = ((i64)iVal * (i64)iMul);
}
}
@@ -4355,7 +4359,7 @@ static int fts3IncrmergeLoad(
return FTS_CORRUPT_VTAB;
}
pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
pWriter->nLeafEst = (int)(((iEnd - iStart)+1)/FTS_MAX_APPENDABLE_HEIGHT);
pWriter->iStart = iStart;
pWriter->iEnd = iEnd;
pWriter->iAbsLevel = iAbsLevel;
+2 -2
View File
@@ -426,7 +426,7 @@ static void fts5SnippetFunction(
int rc = SQLITE_OK; /* Return code */
int iCol; /* 1st argument to snippet() */
const char *zEllips; /* 4th argument to snippet() */
int nToken; /* 5th argument to snippet() */
i64 nToken; /* 5th argument to snippet() */
int nInst = 0; /* Number of instance matches this row */
int i; /* Used to iterate through instances */
int nPhrase; /* Number of phrases in query */
@@ -451,7 +451,7 @@ static void fts5SnippetFunction(
ctx.zClose = fts5ValueToText(apVal[2]);
ctx.iRangeEnd = -1;
zEllips = fts5ValueToText(apVal[3]);
nToken = sqlite3_value_int(apVal[4]);
nToken = (int)(MIN( MAX(sqlite3_value_int64(apVal[4]), 0), 64));
iBestCol = (iCol>=0 ? iCol : 0);
nPhrase = pApi->xPhraseCount(pFts);
+2 -2
View File
@@ -807,7 +807,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
i64 iPos = a[i].reader.iPos;
Fts5PoslistWriter *pWriter = &a[i].writer;
if( a[i].pOut->n==0 || iPos!=pWriter->iPrev ){
sqlite3Fts5PoslistWriterAppend(a[i].pOut, pWriter, iPos);
sqlite3Fts5PoslistSafeAppend(a[i].pOut, &pWriter->iPrev, iPos);
}
}
@@ -1758,10 +1758,10 @@ static int fts5ParseTokenize(
memset(pSyn, 0, (size_t)nByte);
pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
pSyn->nFullTerm = pSyn->nQueryTerm = nToken;
memcpy(pSyn->pTerm, pToken, nToken);
if( pCtx->pConfig->bTokendata ){
pSyn->nQueryTerm = (int)strlen(pSyn->pTerm);
}
memcpy(pSyn->pTerm, pToken, nToken);
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
}
+1 -1
View File
@@ -323,7 +323,7 @@ int sqlite3Fts5HashWrite(
** + 5 bytes for the new position offset (32-bit max).
*/
if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
sqlite3_int64 nNew = p->nAlloc * 2;
sqlite3_int64 nNew = (i64)p->nAlloc * 2;
Fts5HashEntry *pNew;
Fts5HashEntry **pp;
pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew);
+24 -16
View File
@@ -1166,7 +1166,7 @@ static int fts5StructureDecode(
i += fts5GetVarint32(&pData[i], nTotal);
if( nTotal<pLvl->nMerge ) rc = FTS5_CORRUPT;
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
nTotal * sizeof(Fts5StructureSegment)
(i64)nTotal * sizeof(Fts5StructureSegment)
);
nSegment -= nTotal;
}
@@ -1695,6 +1695,7 @@ static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){
pLvl->bEof = 1;
}else{
u8 *a = pLvl->pData->p;
int nn = pLvl->pData->nn;
pLvl->iOff = 0;
fts5DlidxLvlNext(pLvl);
@@ -1703,7 +1704,7 @@ static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){
int ii = pLvl->iOff;
u64 delta = 0;
while( a[ii]==0 ){
while( ii<nn && a[ii]==0 ){
nZero++;
ii++;
}
@@ -2122,7 +2123,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){
Fts5Data *pNew;
pIter->iLeafPgno--;
pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID(
pNew = fts5LeafRead(p, FTS5_SEGMENT_ROWID(
pIter->pSeg->iSegid, pIter->iLeafPgno
));
if( pNew ){
@@ -3556,8 +3557,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);
@@ -5301,6 +5301,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 );
@@ -7986,8 +7991,8 @@ static void fts5IndexTombstoneRebuild(
){
const int MINSLOT = 32;
int nSlotPerPage = MAX(MINSLOT, (p->pConfig->pgsz - 8) / szKey);
int nSlot = 0; /* Number of slots in each output page */
int nOut = 0;
i64 nSlot = 0; /* Number of slots in each output page */
i64 nOut = 0;
/* Figure out how many output pages (nOut) and how many slots per
** page (nSlot). There are three possibilities:
@@ -8012,23 +8017,26 @@ static void fts5IndexTombstoneRebuild(
nSlot = MINSLOT;
}else if( pSeg->nPgTombstone==1 ){
/* Case 2. */
int nElem = (int)fts5GetU32(&pData1->p[4]);
u32 nElem = fts5GetU32(&pData1->p[4]);
assert( pData1 && iPg1==0 );
nOut = 1;
nSlot = MAX(nElem*4, MINSLOT);
if( nSlot>nSlotPerPage ) nOut = 0;
if( nElem>((u32)nSlotPerPage/4) ){
nOut = 0;
}else{
nOut = 1;
nSlot = MAX((i64)nElem*4, MINSLOT);
}
}
if( nOut==0 ){
/* Case 3. */
nOut = (pSeg->nPgTombstone * 2 + 1);
nOut = ((i64)pSeg->nPgTombstone * 2 + 1);
nSlot = nSlotPerPage;
}
/* Allocate the required array and output pages */
while( 1 ){
int res = 0;
int ii = 0;
int szPage = 0;
i64 ii = 0;
i64 szPage = 0;
Fts5Data **apOut = 0;
/* Allocate space for the new hash table */
@@ -8566,7 +8574,7 @@ static void fts5IndexIntegrityCheckSegment(
/* Check any rowid-less pages that occur before the current leaf. */
for(iPg=iPrevLeaf+1; iPg<fts5DlidxIterPgno(pDlidx); iPg++){
iKey = FTS5_SEGMENT_ROWID(iSegid, iPg);
pLeaf = fts5DataRead(p, iKey);
pLeaf = fts5LeafRead(p, iKey);
if( pLeaf ){
if( fts5LeafFirstRowidOff(pLeaf)!=0 ) FTS5_CORRUPT_ROWID(p, iKey);
fts5DataRelease(pLeaf);
@@ -8577,7 +8585,7 @@ static void fts5IndexIntegrityCheckSegment(
/* Check that the leaf page indicated by the iterator really does
** contain the rowid suggested by the same. */
iKey = FTS5_SEGMENT_ROWID(iSegid, iPrevLeaf);
pLeaf = fts5DataRead(p, iKey);
pLeaf = fts5LeafRead(p, iKey);
if( pLeaf ){
i64 iRowid;
int iRowidOff = fts5LeafFirstRowidOff(pLeaf);
+23 -26
View File
@@ -365,34 +365,31 @@ int sqlite3Fts5StorageOpen(
if( pConfig->eContent==FTS5_CONTENT_NORMAL
|| pConfig->eContent==FTS5_CONTENT_UNINDEXED
){
int nDefn = 32 + pConfig->nCol*10;
char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
if( zDefn==0 ){
rc = SQLITE_NOMEM;
}else{
int i;
int iOff;
sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
iOff = (int)strlen(zDefn);
for(i=0; i<pConfig->nCol; i++){
if( pConfig->eContent==FTS5_CONTENT_NORMAL
|| pConfig->abUnindexed[i]
){
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
iOff += (int)strlen(&zDefn[iOff]);
}
int i = 0;
char *zDefn = 0;
sqlite3_str *pDefn = sqlite3_str_new(pConfig->db);
sqlite3_str_appendf(pDefn, "id INTEGER PRIMARY KEY");
for(i=0; i<pConfig->nCol; i++){
if( pConfig->eContent==FTS5_CONTENT_NORMAL || pConfig->abUnindexed[i] ){
sqlite3_str_appendf(pDefn, ", c%d", i);
}
if( pConfig->bLocale ){
for(i=0; i<pConfig->nCol; i++){
if( pConfig->abUnindexed[i]==0 ){
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
iOff += (int)strlen(&zDefn[iOff]);
}
}
}
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
}
sqlite3_free(zDefn);
if( pConfig->bLocale ){
for(i=0; i<pConfig->nCol; i++){
if( pConfig->abUnindexed[i]==0 ){
sqlite3_str_appendf(pDefn, ", l%d", i);
}
}
}
zDefn = sqlite3_str_finish(pDefn);
if( zDefn ){
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
sqlite3_free(zDefn);
}else{
rc = SQLITE_NOMEM;
}
}
if( rc==SQLITE_OK && pConfig->bColumnsize ){
+23
View File
@@ -191,6 +191,29 @@ do_execsql_test 5.6 {
SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ' || x'DB');
} {{[x a a a a a...}}
do_execsql_test 5.7.1 {
SELECT snippet(p1, 0, '[', NULL, '...', -2147483647) FROM p1('x OR ' || x'DB')
} {{[x...}}
do_execsql_test 5.7.2 {
SELECT snippet(p1, 0, '[', NULL, '...', -2147483648) FROM p1('x OR ' || x'DB')
} {{[x...}}
do_execsql_test 5.7.3 {
SELECT snippet(p1, 0, '[', NULL, '...', -2147483649) FROM p1('x OR ' || x'DB')
} {{[x...}}
do_execsql_test 5.7.4 {
SELECT snippet(p1, 0, '[', NULL, '...', 0) FROM p1('x OR ' || x'DB')
} {{[x...}}
do_execsql_test 5.8.1 {
SELECT snippet(p1, 0, '[', NULL, '...', 2147483647) FROM p1('x OR ' || x'DB')
} {{[x a a a a a a a a a a}}
do_execsql_test 5.8.2 {
SELECT snippet(p1, 0, '[', NULL, '...', 2147483648) FROM p1('x OR ' || x'DB')
} {{[x a a a a a a a a a a}}
do_execsql_test 5.8.3 {
SELECT snippet(p1, 0, '[', NULL, '...', 2147483649) FROM p1('x OR ' || x'DB')
} {{[x a a a a a a a a a a}}
} ;# foreach_detail_mode
reset_db
+28
View File
@@ -0,0 +1,28 @@
# 2026 June 19
#
# 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. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5bigtok2
return_if_no_fts5
set big [string repeat a 1080000000]
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t USING fts5(x);
}
do_catchsql_test 1.1 { INSERT INTO t VALUES($big); } {1 {out of memory}}
set big {}
finish_test
+213
View File
@@ -1998,6 +1998,219 @@ 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}}}
#-------------------------------------------------------------------------
reset_db
#-------------------------------------------------------------------------
reset_db
do_test 14.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 0a 00 0f c7 0f 74 ..v............t
| 112: 0f 0c 0e b8 0e 5f 0e 0a 00 00 00 00 00 00 00 00 ....._..........
| 3584: 00 00 00 00 00 00 00 00 00 00 53 06 06 17 1d 1d ..........S.....
| 3600: 01 7b 74 61 62 6c 65 74 5f 63 6f 6e 66 69 67 74 ..tablet_configt
| 3616: 5f 63 6f 6e 66 69 67 06 43 52 45 41 54 45 20 54 _config.CREATE T
| 3632: 41 42 4c 45 20 27 74 5f 63 6f 6e 66 69 67 27 28 ABLE 't_config'(
| 3648: 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 k PRIMARY KEY, v
| 3664: 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 57 ) WITHOUT ROWIDW
| 3680: 05 06 17 1f 1f 01 7f 74 61 62 6c 65 74 5f 64 6f .......tablet_do
| 3696: 63 73 69 7a 65 74 5f 64 6f 63 73 69 7a 65 05 43 csizet_docsize.C
| 3712: 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 5f 64 REATE TABLE 't_d
| 3728: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG
| 3744: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
| 3760: 73 7a 20 42 4c 4f 42 29 52 04 06 17 1f 1f 01 75 sz BLOB)R......u
| 3776: 74 61 62 6c 65 74 5f 63 6f 6e 74 65 6e 74 74 5f tablet_contentt_
| 3792: 63 6f 6e 74 65 6e 74 04 43 52 45 41 54 45 20 54 content.CREATE T
| 3808: 41 42 4c 45 20 27 74 5f 63 6f 6e 74 65 6e 74 27 ABLE 't_content'
| 3824: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
| 3840: 41 52 59 20 4b 45 59 2c 20 63 30 29 66 03 07 17 ARY KEY, c0)f...
| 3856: 17 17 01 81 2b 74 61 62 6c 65 74 5f 69 64 78 74 ....+tablet_idxt
| 3872: 5f 69 64 78 03 43 52 45 41 54 45 20 54 41 42 4c _idx.CREATE TABL
| 3888: 45 20 27 74 5f 69 64 78 27 28 73 65 67 69 64 2c E 't_idx'(segid,
| 3904: 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 term, pgno, PRI
| 3920: 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 MARY KEY(segid,
| 3936: 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 term)) WITHOUT R
| 3952: 4f 57 49 44 51 02 06 17 19 19 01 7f 74 61 62 6c OWIDQ.......tabl
| 3968: 65 74 5f 64 61 74 61 74 5f 64 61 74 61 02 43 52 et_datat_data.CR
| 3984: 45 41 54 45 20 54 41 42 4c 45 20 27 74 5f 64 61 EATE TABLE 't_da
| 4000: 74 61 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 ta'(id INTEGER P
| 4016: 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 RIMARY KEY, bloc
| 4032: 6b 20 42 4c 4f 42 29 37 01 06 17 0f 0f 08 61 74 k BLOB)7......at
| 4048: 61 62 6c 65 74 74 43 52 45 41 54 45 20 56 49 52 ablettCREATE VIR
| 4064: 54 55 41 4c 20 54 41 42 4c 45 20 74 20 55 53 49 TUAL TABLE t USI
| 4080: 4e 47 20 66 74 73 35 28 63 6f 6e 74 65 6e 74 29 NG fts5(content)
| page 2 offset 4096
| 0: 0d 0f ef 00 03 0f ac 00 0f e8 0f ac 0f c4 00 00 ................
| 4000: 00 00 00 00 00 00 00 00 00 00 00 00 16 0a 03 00 ................
| 4016: 32 01 00 00 00 01 01 01 00 d5 aa d5 2b 01 01 01 2...........+...
| 4032: 83 74 01 01 1d 84 80 80 80 80 01 03 00 40 00 00 .t...........@..
| 4048: 00 18 06 30 68 65 6c 6c 6f 01 02 02 01 05 77 6f ...0hello.....wo
| 4064: 72 6c 64 01 02 03 04 0a 05 01 03 00 10 01 02 00 rld.............
| 4080: 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 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 f0 00 0f f0 00 00 00 00 00 00 ................
| 4080: 0e 01 03 00 23 68 65 6c 6c 6f 20 77 6f 72 6c 64 ....#hello world
| 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 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 14.1 {
SELECT * FROM t('hello');
} {1 {out of memory}}
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
+145
View File
@@ -124,5 +124,150 @@ do_test 3.1 {
set {} {}
} {}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE t1 USING fts5(content);
INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
BEGIN;
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<5000
)
INSERT INTO t1(content) SELECT 'xyzterm' FROM s;
COMMIT;
INSERT INTO t1(t1) VALUES('optimize');
}
do_test 4.1 {
db eval {
SELECT rowid AS a, hex(block) AS block FROM t1_data
WHERE ((rowid>>36) & 0x01)==1
AND ((rowid>>31) & 0x1F)==0
} {
set n [string length $block]
set block [string range $block 0 11]
append block [string repeat "00" [expr ($n/2)-7-2]]
append block "8080"
db eval {
UPDATE t1_data SET block = unhex($block) WHERE rowid = $a
}
}
} {}
do_catchsql_test 4.2 {
SELECT count(*) FROM (
SELECT rowid FROM t1 WHERE t1 MATCH 'xyzterm' ORDER BY rowid ASC
)
} {0 5000}
do_catchsql_test 4.3 {
SELECT count(*) FROM (
SELECT rowid FROM t1 WHERE t1 MATCH 'xyzterm' ORDER BY rowid DESC
)
} {0 4987}
do_test 4.4 {
db eval {
SELECT rowid AS a, hex(block) AS block FROM t1_data
WHERE ((rowid>>36) & 0x01)==1
AND ((rowid>>31) & 0x1F)==0
} {
set n [string length $block]
set block [string range $block 0 $n-5]
append block [string repeat "00" 2]
db eval {
UPDATE t1_data SET block = unhex($block) WHERE rowid = $a
}
}
} {}
do_catchsql_test 4.5 {
SELECT count(*) FROM (
SELECT rowid FROM t1 WHERE t1 MATCH 'xyzterm' ORDER BY rowid ASC
)
} {0 5000}
do_catchsql_test 4.6 {
SELECT count(*) FROM (
SELECT rowid FROM t1 WHERE t1 MATCH 'xyzterm' ORDER BY rowid DESC
)
} {0 4879}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE t USING fts5(x);
INSERT INTO t(t,rank) VALUES('pgsz', 64);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<80
)
INSERT INTO t SELECT 'shared word' || (i%10) || ' shared shared' FROM s;
INSERT INTO t(t) VALUES('optimize');
}
set lLeaf [db eval { SELECT id FROM t_data }]
db_save_and_close
foreach leaf $lLeaf {
db_restore_and_reopen
set leaf [expr $leaf]
set hex [db one {
SELECT hex(block) FROM t_data WHERE id=$leaf
}]
# Replace the first 4 bytes of each leaf page with the size of the leaf in
# bytes plus 50 as a 2 byte integer, followed by 0x7FFF.
#
set nn [expr [string length $hex]/2]
set first "[format %.4x [expr $nn+50]]7FFF"
set hex [string replace $hex 0 7 $first]
db eval { UPDATE t_data SET block=unhex($hex) WHERE id=$leaf }
do_test 5.1.$leaf {
catchsql {
SELECT rowid FROM t WHERE t MATCH 'shared' ORDER BY rowid DESC;
}
set {} {}
} {}
do_test 5.1.$leaf.2 {
catchsql {
PRAGMA integrity_check;
}
set {} {}
} {}
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE t USING fts5(x, content='', contentless_delete=1);
INSERT INTO t(rowid,x)
VALUES(1,'a b'), (2,'c d'), (3,'e f'), (4,'g h'), (5,'i j');
INSERT INTO t(t) VALUES('optimize');
DELETE FROM t WHERE rowid=2;
}
do_test 6.1 {
db eval {
SELECT rowid AS rid, hex(block) AS blk
FROM t_data WHERE rowid>1_000_000_000_000
} {}
set blk [string replace $blk 8 15 20000000]
execsql {
UPDATE t_data SET block = unhex($blk) WHERE rowid=$rid
}
} {}
do_execsql_test 6.2 {
DELETE FROM t WHERE rowid=3;
}
sqlite3_fts5_may_be_corrupt 0
finish_test
+13
View File
@@ -743,6 +743,19 @@ do_execsql_test 15.4 {
SELECT c, fts5_columnlocale(ft, 2) FROM ft
} {three {} three loc}
#-------------------------------------------------------------------------
#
set nMaxCol 500
set nStep 20
for {set ii $nStep} {$ii <= $nMaxCol} {incr ii $nStep} {
set C [list]
for {set iCol 0} {$iCol<$ii} {incr iCol} {
lappend C col$iCol
}
set ct "CREATE VIRTUAL TABLE t$ii USING fts5([join $C ,], locale=1)"
do_execsql_test 16.$ii $ct
}
finish_test
+13
View File
@@ -66,5 +66,18 @@ do_near_test 1.23 "a b c d e f g h i" { NEAR(a+b+c+d i b+c, 4) } 0
do_near_test 1.24 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 5) } 1
do_near_test 1.25 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 4) } 0
#-------------------------------------------------------------------------
# Check that https://sqlite.org/bugs/forumpost/16bb36f7e8 is fixed.
#
reset_db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t USING fts5(x, tokenize=trigram);
INSERT INTO t
VALUES('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
}
do_execsql_test 2.1 {
SELECT count(*) FROM t WHERE t MATCH 'NEAR(aaa aaa, 4)';
} {1}
finish_test
+28
View File
@@ -418,6 +418,34 @@ do_execsql_test 7.1.2 {
INSERT INTO t2(t2) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
reset_db
fts5_aux_test_functions db
proc tcl_create {args} { return "tcl_tokenize" }
sqlite3_fts5_create_tokenizer db tcl tcl_create
proc tcl_tokenize {tflags text} {
foreach {w iStart iEnd} [fts5_tokenize_split $text] {
sqlite3_fts5_token $w $iStart $iEnd
if {$w=="usa"} {
sqlite3_fts5_token -colo "united" $iStart $iEnd
}
}
}
do_execsql_test 8.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize='tcl', tokendata=1);
INSERT INTO t1 VALUES('usa is great');
INSERT INTO t1 VALUES('canada is cool');
INSERT INTO t1 VALUES('australia is what matters');
}
do_execsql_test 8.1 {
SELECT * FROM t1 WHERE t1 MATCH 'usa*';
} {{usa is great}}
} ;# foreach_detail_mode
finish_test
+3
View File
@@ -105,6 +105,9 @@ static const unsigned char icuUtf8Trans1[] = {
while( (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
if( c<0x80 \
|| (c&0xFFFFF800)==0xD800 \
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
}
#define SQLITE_ICU_SKIP_UTF8(zIn) \
-152
View File
@@ -1,152 +0,0 @@
/*
** 2019-03-30
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** An SQL function that uses the incremental BLOB I/O mechanism of SQLite
** to read or write part of a blob. This is intended for debugging use
** in the CLI.
**
** readblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,N)
**
** Returns N bytes of the blob starting at OFFSET.
**
** writeblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,NEWDATA)
**
** NEWDATA must be a blob. The content of NEWDATA overwrites the
** existing BLOB data at SCHEMA.TABLE.COLUMN for row ROWID beginning
** at OFFSET bytes into the blob.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
static void readblobFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_blob *pBlob = 0;
const char *zSchema;
const char *zTable;
const char *zColumn;
sqlite3_int64 iRowid;
int iOfst;
unsigned char *aData;
int nData;
sqlite3 *db;
int rc;
zSchema = (const char*)sqlite3_value_text(argv[0]);
zTable = (const char*)sqlite3_value_text(argv[1]);
if( zTable==0 ){
sqlite3_result_error(context, "bad table name", -1);
return;
}
zColumn = (const char*)sqlite3_value_text(argv[2]);
if( zTable==0 ){
sqlite3_result_error(context, "bad column name", -1);
return;
}
iRowid = sqlite3_value_int64(argv[3]);
iOfst = sqlite3_value_int(argv[4]);
nData = sqlite3_value_int(argv[5]);
if( nData<=0 ) return;
aData = sqlite3_malloc64( nData+1 );
if( aData==0 ){
sqlite3_result_error_nomem(context);
return;
}
db = sqlite3_context_db_handle(context);
rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 0, &pBlob);
if( rc ){
sqlite3_free(aData);
sqlite3_result_error(context, "cannot open BLOB pointer", -1);
return;
}
rc = sqlite3_blob_read(pBlob, aData, nData, iOfst);
sqlite3_blob_close(pBlob);
if( rc ){
sqlite3_free(aData);
sqlite3_result_error(context, "BLOB read failed", -1);
}else{
sqlite3_result_blob(context, aData, nData, sqlite3_free);
}
}
static void writeblobFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_blob *pBlob = 0;
const char *zSchema;
const char *zTable;
const char *zColumn;
sqlite3_int64 iRowid;
int iOfst;
unsigned char *aData;
int nData;
sqlite3 *db;
int rc;
zSchema = (const char*)sqlite3_value_text(argv[0]);
zTable = (const char*)sqlite3_value_text(argv[1]);
if( zTable==0 ){
sqlite3_result_error(context, "bad table name", -1);
return;
}
zColumn = (const char*)sqlite3_value_text(argv[2]);
if( zTable==0 ){
sqlite3_result_error(context, "bad column name", -1);
return;
}
iRowid = sqlite3_value_int64(argv[3]);
iOfst = sqlite3_value_int(argv[4]);
if( sqlite3_value_type(argv[5])!=SQLITE_BLOB ){
sqlite3_result_error(context, "6th argument must be a BLOB", -1);
return;
}
nData = sqlite3_value_bytes(argv[5]);
aData = (unsigned char *)sqlite3_value_blob(argv[5]);
db = sqlite3_context_db_handle(context);
rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 1, &pBlob);
if( rc ){
sqlite3_result_error(context, "cannot open BLOB pointer", -1);
return;
}
rc = sqlite3_blob_write(pBlob, aData, nData, iOfst);
sqlite3_blob_close(pBlob);
if( rc ){
sqlite3_result_error(context, "BLOB write failed", -1);
}
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_blobio_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "readblob", 6, SQLITE_UTF8, 0,
readblobFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "writeblob", 6, SQLITE_UTF8, 0,
writeblobFunc, 0, 0);
}
return rc;
}
+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);
+7 -2
View File
@@ -547,6 +547,10 @@ static int csvtabConnect(
if( nCol<=0 ){
csv_errmsg(&sRdr, "column= value must be positive");
goto csvtab_connect_error;
}else if( nCol>sqlite3_limit(db,SQLITE_LIMIT_COLUMN,-1) ){
csv_errmsg(&sRdr, "column= value too big, max %d",
sqlite3_limit(db, SQLITE_LIMIT_COLUMN,-1));
goto csvtab_connect_error;
}
}else
{
@@ -709,8 +713,9 @@ static int csvtabClose(sqlite3_vtab_cursor *cur){
static int csvtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
CsvTable *pTab = (CsvTable*)p;
CsvCursor *pCur;
size_t nByte;
nByte = sizeof(*pCur) + (sizeof(char*)+sizeof(i64))*pTab->nCol;
sqlite3_int64 nByte = pTab->nCol;
assert( pTab->nCol<32768 );
nByte = sizeof(*pCur) + (sizeof(char*)+sizeof(i64))*nByte;
pCur = sqlite3_malloc64( nByte );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, nByte);
+15 -6
View File
@@ -299,28 +299,37 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
sqlite3_result_text(pCtx, z, i, sqlite3_free);
}
/* Forward declaration */
static void decimal_expand(Decimal *p, int nDigit, int nFrac);
/*
** Round a decimal value to N significant digits. N must be positive.
*/
static void decimal_round(Decimal *p, int N){
int i;
int nZero;
int nZero; /* Number of leading zeros */
if( N<1 ) return;
if( p==0 ) return;
if( p->nDigit<=N ) return;
for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
N += nZero;
if( p->nDigit<=N ) return;
if( p->a[N]>4 ){
if( p->a[N]>=5 ){
/* If all leading digits are 9, increase the number of digits
** by adding a new 0 to the front */
for(i=0; i<N && p->a[i]==9; i++){}
if( i==N ){
decimal_expand(p, p->nDigit+1, 0);
if( p->oom ) return;
}
/* Do the rounding */
p->a[N-1]++;
for(i=N-1; i>0 && p->a[i]>9; i--){
p->a[i] = 0;
p->a[i-1]++;
}
if( p->a[0]>9 ){
p->a[0] = 1;
p->nFrac--;
}
assert( p->a[0]<=9 );
}
memset(&p->a[N], 0, p->nDigit - N);
}
+150 -139
View File
@@ -10,8 +10,17 @@
**
******************************************************************************
**
** Partial reimplement of the sqlite3_analyzer utility program as
** loadable SQL function.
** This extension implements an SQL function:
**
** diskused(X)
**
** Where X is the schema name (typically 'main'). The output is text
** that describes how much filesystem space the various tables and indexes
** of the database consume.
**
** This function is a replacement for the (now deprecated)
** "sqlite3_analyzer" utility program. This function is built
** into the CLI and is used to implement the ".diskused" command there.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
@@ -23,8 +32,8 @@ SQLITE_EXTENSION_INIT1
/*
** State information for the analysis
*/
typedef struct Analysis Analysis;
struct Analysis {
typedef struct DiskUsed DiskUsed;
struct DiskUsed {
sqlite3 *db; /* Database connection */
sqlite3_context *context; /* SQL function context */
sqlite3_str *pOut; /* Write output here */
@@ -33,14 +42,14 @@ struct Analysis {
};
/*
** Free all resources that the Analysis object references and
** reset the Analysis object.
** Free all resources that the DiskUsed object references and
** reset the DiskUsed object.
**
** Call this routine multiple times on the same Analysis object
** Call this routine multiple times on the same DiskUsed object
** is a harmless no-op, as long as the memory for the object itself
** has not been freed.
*/
static void analysisReset(Analysis *p){
static void diskusedReset(DiskUsed *p){
if( p->zSU ){
char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
if( zSql ){
@@ -57,7 +66,7 @@ static void analysisReset(Analysis *p){
** Report an error using formatted text. If zFormat==NULL then report
** an OOM error.
*/
static void analysisError(Analysis *p, const char *zFormat, ...){
static void diskusedError(DiskUsed *p, const char *zFormat, ...){
char *zErr;
if( zFormat ){
va_list ap;
@@ -73,34 +82,34 @@ static void analysisError(Analysis *p, const char *zFormat, ...){
sqlite3_result_error(p->context, zErr, -1);
sqlite3_free(zErr);
}
analysisReset(p);
diskusedReset(p);
}
/*
** Prepare and return an SQL statement.
*/
static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
static sqlite3_stmt *diskusedVPrep(DiskUsed *p, const char *zFmt, va_list ap){
char *zSql;
int rc;
sqlite3_stmt *pStmt = 0;
zSql = sqlite3_vmprintf(zFmt, ap);
if( zSql==0 ){ analysisError(p,0); return 0; }
if( zSql==0 ){ diskusedError(p,0); return 0; }
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
if( rc ){
analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
diskusedError(p, "SQL parse error: %s\nOriginal SQL: %s",
sqlite3_errmsg(p->db), zSql);
sqlite3_finalize(pStmt);
analysisReset(p);
diskusedReset(p);
pStmt = 0;
}
sqlite3_free(zSql);
return pStmt;
}
static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
static sqlite3_stmt *diskusedPrepare(DiskUsed *p, const char *zFormat, ...){
va_list ap;
sqlite3_stmt *pStmt = 0;
va_start(ap, zFormat);
pStmt = analysisVPrep(p,zFormat,ap);
pStmt = diskusedVPrep(p,zFormat,ap);
va_end(ap);
return pStmt;
}
@@ -113,14 +122,14 @@ static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
**
** The prepared statement is closed in either case.
*/
static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
static int diskusedStmtFinish(DiskUsed *p, int rc, sqlite3_stmt *pStmt){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
}
if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
analysisReset(p);
diskusedReset(p);
}
sqlite3_finalize(pStmt);
return rc;
@@ -129,21 +138,21 @@ static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
/*
** Run SQL. Return the number of errors.
*/
static int analysisSql(Analysis *p, const char *zFormat, ...){
static int diskusedSql(DiskUsed *p, const char *zFormat, ...){
va_list ap;
int rc;
sqlite3_stmt *pStmt = 0;
va_start(ap, zFormat);
pStmt = analysisVPrep(p,zFormat,ap);
pStmt = diskusedVPrep(p,zFormat,ap);
va_end(ap);
if( pStmt==0 ) return 1;
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
}else{
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
analysisReset(p);
diskusedReset(p);
}
sqlite3_finalize(pStmt);
return rc;
@@ -153,8 +162,8 @@ static int analysisSql(Analysis *p, const char *zFormat, ...){
** Run an SQL query that returns an integer. Write that integer
** into *piRes. Return the number of errors.
*/
static int analysisSqlInt(
Analysis *p,
static int diskusedSqlInt(
DiskUsed *p,
sqlite3_int64 *piRes,
const char *zFormat, ...
){
@@ -162,7 +171,7 @@ static int analysisSqlInt(
int rc;
sqlite3_stmt *pStmt = 0;
va_start(ap, zFormat);
pStmt = analysisVPrep(p,zFormat,ap);
pStmt = diskusedVPrep(p,zFormat,ap);
va_end(ap);
if( pStmt==0 ) return 1;
rc = sqlite3_step(pStmt);
@@ -174,10 +183,10 @@ static int analysisSqlInt(
}else{
if( p->db ){
/* p->db is NULL if there was some prior error */
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
}
analysisReset(p);
diskusedReset(p);
}
sqlite3_finalize(pStmt);
return rc;
@@ -190,7 +199,7 @@ static int analysisSqlInt(
** comment. Otherwise begin with a new-line. Always finish with a
** newline.
*/
static void analysisTitle(Analysis *p, const char *zFormat, ...){
static void diskusedTitle(DiskUsed *p, const char *zFormat, ...){
char *zFirst;
char *zTitle;
size_t nTitle;
@@ -199,7 +208,7 @@ static void analysisTitle(Analysis *p, const char *zFormat, ...){
zTitle = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( zTitle==0 ){
analysisError(p, 0);
diskusedError(p, 0);
return;
}
zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
@@ -218,8 +227,8 @@ static void analysisTitle(Analysis *p, const char *zFormat, ...){
** 50 columns with "." characters, and followed by whatever text is
** described by zFormat.
*/
static void analysisLine(
Analysis *p, /* Analysis context */
static void diskusedLine(
DiskUsed *p, /* DiskUsed context */
const char *zDesc, /* Description */
const char *zFormat, /* Argument to the description */
...
@@ -231,10 +240,10 @@ static void analysisLine(
zTxt = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( zTxt==0 ){
analysisError(p, 0);
diskusedError(p, 0);
return;
}
nDesc = strlen(zDesc);
nDesc = zDesc ? strlen(zDesc) : 0;
if( nDesc>=50 ){
sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
}else{
@@ -248,7 +257,7 @@ static void analysisLine(
** two or three significant digits, with the decimal point being the fourth
** character.
*/
static void analysisPercent(Analysis *p, double r){
static void diskusedPercent(DiskUsed *p, double r){
char zNum[100];
char *zDP;
int nLeadingDigit;
@@ -277,8 +286,8 @@ static void analysisPercent(Analysis *p, double r){
** a boolean expression that can go in the WHERE clause to select
** the relevant rows of the s.zSU table.
*/
static int analysisSubreport(
Analysis *p, /* Analysis context */
static int diskusedSubreport(
DiskUsed *p, /* DiskUsed context */
char *zTitle, /* Title for this subreport */
char *zWhere, /* WHERE clause for this subreport */
sqlite3_int64 pgsz, /* Database page size */
@@ -306,10 +315,10 @@ static int analysisSubreport(
int rc;
if( zTitle==0 || zWhere==0 ){
analysisError(p, 0);
diskusedError(p, 0);
return SQLITE_NOMEM;
}
pStmt = analysisPrepare(p,
pStmt = diskusedPrepare(p,
"SELECT\n"
" sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
" sum(payload),\n" /* 1 */
@@ -330,7 +339,7 @@ static int analysisSubreport(
if( pStmt==0 ) return 1;
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
analysisTitle(p, "%s", zTitle);
diskusedTitle(p, "%s", zTitle);
nentry = sqlite3_column_int64(pStmt, 0);
payload = sqlite3_column_int64(pStmt, 1);
@@ -349,69 +358,69 @@ static int analysisSubreport(
rc = SQLITE_DONE;
total_pages = leaf_pages + int_pages + ovfl_pages;
analysisLine(p, "Percentage of total database", "%.3g%%\n",
diskusedLine(p, "Percentage of total database", "%.3g%%\n",
(total_pages*100.0)/(double)nPage);
analysisLine(p, "Number of entries", "%lld\n", nentry);
diskusedLine(p, "Number of entries", "%lld\n", nentry);
storage = total_pages*pgsz;
analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
analysisLine(p, "Bytes of payload", "%-11lld ", payload);
analysisPercent(p, payload*100.0/(double)storage);
diskusedLine(p, "Bytes of storage consumed", "%lld\n", storage);
diskusedLine(p, "Bytes of payload", "%-11lld ", payload);
diskusedPercent(p, payload*100.0/(double)storage);
if( ovfl_cnt>0 ){
analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
analysisPercent(p, ovfl_payload*100.0/(double)payload);
diskusedLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
diskusedPercent(p, ovfl_payload*100.0/(double)payload);
}
total_unused = leaf_unused + int_unused + ovfl_unused;
total_meta = storage - payload - total_unused;
analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
analysisPercent(p, total_meta*100.0/(double)storage);
diskusedLine(p, "Bytes of metadata","%-11lld ", total_meta);
diskusedPercent(p, total_meta*100.0/(double)storage);
if( cnt==1 ){
analysisLine(p, "B-tree depth", "%lld\n", depth);
diskusedLine(p, "B-tree depth", "%lld\n", depth);
if( int_cell>1 ){
analysisLine(p, "Average fanout", "%.1f\n",
diskusedLine(p, "Average fanout", "%.1f\n",
(double)(int_cell+int_pages)/(double)int_pages);
}
}
if( nentry>0 ){
analysisLine(p, "Average payload per entry", "%.1f\n",
diskusedLine(p, "Average payload per entry", "%.1f\n",
(double)payload/(double)nentry);
analysisLine(p, "Average unused bytes per entry", "%.1f\n",
diskusedLine(p, "Average unused bytes per entry", "%.1f\n",
(double)total_unused/(double)nentry);
analysisLine(p, "Average metadata per entry", "%.1f\n",
diskusedLine(p, "Average metadata per entry", "%.1f\n",
(double)total_meta/(double)nentry);
}
analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
diskusedLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
if( nentry>0 ){
analysisLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
analysisPercent(p, ovfl_cnt*100.0/(double)nentry);
diskusedLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
diskusedPercent(p, ovfl_cnt*100.0/(double)nentry);
}
if( int_pages>0 ){
analysisLine(p, "Index pages used", "%lld\n", int_pages);
diskusedLine(p, "Index pages used", "%lld\n", int_pages);
}
analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
diskusedLine(p, "Primary pages used", "%lld\n", leaf_pages);
if( ovfl_cnt ){
analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
diskusedLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
}
analysisLine(p, "Total pages used", "%lld\n", total_pages);
diskusedLine(p, "Total pages used", "%lld\n", total_pages);
if( int_pages>0 ){
analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
diskusedLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
}
analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
diskusedLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
if( ovfl_cnt ){
analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
diskusedLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
}
analysisLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
analysisPercent(p, total_unused*100.0/(double)storage);
diskusedLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
diskusedPercent(p, total_unused*100.0/(double)storage);
}
return analysisStmtFinish(p, rc, pStmt);
return diskusedStmtFinish(p, rc, pStmt);
}
/*
** SQL Function: analyze(SCHEMA)
** SQL Function: diskused(SCHEMA)
**
** Analyze the database schema named in the argument. Return text
** containing the analysis.
** containing the space utilization stats.
*/
static void analyzeFunc(
static void diskusedFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
@@ -426,7 +435,7 @@ static void analyzeFunc(
sqlite3_int64 nFreeList;
sqlite3_int64 nIndex;
sqlite3_int64 nWORowid;
Analysis s;
DiskUsed s;
sqlite3_uint64 r[2];
(void)argc;
@@ -435,34 +444,34 @@ static void analyzeFunc(
s.context = context;
s.pOut = sqlite3_str_new(0);
if( sqlite3_str_errcode(s.pOut) ){
analysisError(&s, 0);
diskusedError(&s, 0);
return;
}
s.zSchema = (const char*)sqlite3_value_text(argv[0]);
if( s.zSchema==0 ){
s.zSchema = "main";
}else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
analysisReset(&s);
diskusedReset(&s);
sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
return;
}
ii = 0;
rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
rc = diskusedSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
" WHERE name=%Q COLLATE nocase",s.zSchema);
if( rc || ii==0 ){
analysisReset(&s);
diskusedReset(&s);
sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
return;
}
sqlite3_randomness(sizeof(r), &r);
s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
if( s.zSU==0 ){ analysisError(&s, 0); return; }
s.zSU = sqlite3_mprintf("diskused%016llx%016llx", r[0], r[1]);
if( s.zSU==0 ){ diskusedError(&s, 0); return; }
/* The s.zSU table contains the data used for the analysis.
** The table name contains 128-bits of randomness to avoid
** collisions with preexisting tables in temp.
*/
rc = analysisSql(&s,
rc = diskusedSql(&s,
"CREATE TABLE temp.%s(\n"
" name text, -- A table or index\n"
" tblname text, -- Table that owns name\n"
@@ -489,7 +498,7 @@ static void analyzeFunc(
/* Populate the s.zSU table
*/
rc = analysisSql(&s,
rc = diskusedSql(&s,
"WITH\n"
" allidx(idxname) AS (\n"
" SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
@@ -541,38 +550,38 @@ static void analyzeFunc(
if( rc ) return;
nPage = 0;
rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
rc = diskusedSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
if( rc ) return;
if( nPage<=0 ){
/* Very brief reply for an empty database */
analysisReset(&s);
diskusedReset(&s);
sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
return;
}
/* Begin generating the report */
analysisTitle(&s, "Database storage utilization report");
diskusedTitle(&s, "Database storage utilization report");
pgsz = 0;
rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
rc = diskusedSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
if( rc ) return;
analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
analysisLine(&s, "Pages in the database", "%lld\n", nPage);
diskusedLine(&s, "Page size in bytes","%lld\n",pgsz);
diskusedLine(&s, "Pages in the database", "%lld\n", nPage);
nPageInUse = 0;
rc = analysisSqlInt(&s, &nPageInUse,
rc = diskusedSqlInt(&s, &nPageInUse,
"SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
if( rc ) return;
analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
diskusedLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
diskusedPercent(&s, (nPageInUse*100.0)/(double)nPage);
nFreeList = 0;
rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
rc = diskusedSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
if( rc ) return;
analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
diskusedLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
diskusedPercent(&s, (nFreeList*100.0)/(double)nPage);
ii = 0;
rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
rc = diskusedSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
if( rc ) return;
if( ii==0 || nPage<=1 ){
ii = 0;
@@ -581,97 +590,99 @@ static void analyzeFunc(
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
ii = (sqlite3_int64)ceil(rAvPage);
}
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
analysisPercent(&s, (ii*100.0)/(double)nPage);
diskusedLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
diskusedPercent(&s, (ii*100.0)/(double)nPage);
ii = 0;
rc = analysisSqlInt(&s, &ii,
rc = diskusedSqlInt(&s, &ii,
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
s.zSchema);
if( rc ) return;
analysisLine(&s, "Number of tables", "%lld\n", ii);
diskusedLine(&s, "Number of tables", "%lld\n", ii);
nWORowid = 0;
rc = analysisSqlInt(&s, &nWORowid,
rc = diskusedSqlInt(&s, &nWORowid,
"SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
s.zSchema);
if( rc ) return;
if( nWORowid>0 ){
analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
diskusedLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
diskusedLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
}
nIndex = 0;
rc = analysisSqlInt(&s, &nIndex,
rc = diskusedSqlInt(&s, &nIndex,
"SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
s.zSchema);
if( rc ) return;
analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
diskusedLine(&s, "Number of indexes", "%lld\n", nIndex);
ii = 0;
rc = analysisSqlInt(&s, &ii,
rc = diskusedSqlInt(&s, &ii,
"SELECT count(*) FROM \"%w\".sqlite_schema"
" WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
s.zSchema);
if( rc ) return;
analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
diskusedLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
diskusedLine(&s, "Number of implied indexes", "%lld\n", ii);
diskusedLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
ii = 0;
rc = analysisSqlInt(&s, &ii,
rc = diskusedSqlInt(&s, &ii,
"SELECT sum(payload) FROM temp.%s"
" WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
s.zSU);
if( rc ) return;
analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
diskusedLine(&s, "Bytes of payload", "%-11lld ", ii);
diskusedPercent(&s, ii*100.0/(double)(pgsz*nPage));
analysisTitle(&s, "Page counts for all tables with their indexes");
pStmt = analysisPrepare(&s,
diskusedTitle(&s, "Page counts for all tables with their indexes");
pStmt = diskusedPrepare(&s,
"SELECT upper(tblname),\n"
" sum(int_pages+leaf_pages+ovfl_pages)\n"
" FROM temp.%s\n"
" WHERE tblname IS NOT NULL\n"
" GROUP BY 1\n"
" ORDER BY 2 DESC, 1;",
s.zSU);
if( pStmt==0 ) return;
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
analysisPercent(&s, (nn*100.0)/(double)nPage);
diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
diskusedPercent(&s, (nn*100.0)/(double)nPage);
}
if( analysisStmtFinish(&s, rc, pStmt) ) return;
if( diskusedStmtFinish(&s, rc, pStmt) ) return;
analysisTitle(&s, "Page counts for all tables and indexes separately");
pStmt = analysisPrepare(&s,
diskusedTitle(&s, "Page counts for all tables and indexes separately");
pStmt = diskusedPrepare(&s,
"SELECT upper(name),\n"
" sum(int_pages+leaf_pages+ovfl_pages)\n"
" FROM temp.%s\n"
" WHERE name IS NOT NULL\n"
" GROUP BY 1\n"
" ORDER BY 2 DESC, 1;",
s.zSU);
if( pStmt==0 ) return;
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
analysisPercent(&s, (nn*100.0)/(double)nPage);
diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
diskusedPercent(&s, (nn*100.0)/(double)nPage);
}
if( analysisStmtFinish(&s, rc, pStmt) ) return;
if( diskusedStmtFinish(&s, rc, pStmt) ) return;
rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
rc = diskusedSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
if( rc ) return;
rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
rc = diskusedSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
if( rc ) return;
if( nWORowid>0 ){
rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
rc = diskusedSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
pgsz, nPage);
if( rc ) return;
rc = analysisSubreport(&s, "All rowid tables",
rc = diskusedSubreport(&s, "All rowid tables",
"NOT is_without_rowid AND NOT is_index",
pgsz, nPage);
if( rc ) return;
}
rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
rc = diskusedSubreport(&s, "All indexes", "is_index", pgsz, nPage);
if( rc ) return;
pStmt = analysisPrepare(&s,
pStmt = diskusedPrepare(&s,
"SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
" GROUP BY 1 ORDER BY 1",
s.zSU);
@@ -683,7 +694,7 @@ static void analyzeFunc(
if( nSubIndex==0 ){
char *zTitle = sqlite3_mprintf("Table %s", zUpper);
char *zWhere = sqlite3_mprintf("name=%Q", zName);
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
sqlite3_free(zTitle);
sqlite3_free(zWhere);
if( rc ) break;
@@ -691,25 +702,25 @@ static void analyzeFunc(
sqlite3_stmt *pS2;
char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
sqlite3_free(zTitle);
sqlite3_free(zWhere);
if( rc ) break;
zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
zWhere = sqlite3_mprintf("name=%Q", zName);
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
sqlite3_free(zTitle);
sqlite3_free(zWhere);
if( rc ) break;
if( nSubIndex>1 ){
zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
sqlite3_free(zTitle);
sqlite3_free(zWhere);
if( rc ) break;
}
pS2 = analysisPrepare(&s,
pS2 = diskusedPrepare(&s,
"SELECT name, upper(name) FROM temp.%s"
" WHERE is_index AND tblname=%Q",
s.zSU, zName);
@@ -722,21 +733,21 @@ static void analyzeFunc(
const char *zN = (const char*)sqlite3_column_text(pS2, 0);
zTitle = sqlite3_mprintf("Index %s", zU);
zWhere = sqlite3_mprintf("name=%Q", zN);
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
sqlite3_free(zTitle);
sqlite3_free(zWhere);
if( rc ) break;
}
rc = analysisStmtFinish(&s, rc, pS2);
rc = diskusedStmtFinish(&s, rc, pS2);
if( rc ) break;
}
}
if( analysisStmtFinish(&s, rc, pStmt) ) return;
if( diskusedStmtFinish(&s, rc, pStmt) ) return;
/* Append SQL statements that will recreate the raw data used for
** the analysis.
*/
analysisTitle(&s, "Raw data used to generate this report");
diskusedTitle(&s, "Raw data used to generate this report");
sqlite3_str_appendf(s.pOut,
"The following SQL will create a table named \"space_used\" which\n"
"contains most of the information used to generate the report above.\n"
@@ -766,7 +777,7 @@ static void analyzeFunc(
");\n"
"INSERT INTO space_used VALUES\n"
);
pStmt = analysisPrepare(&s,
pStmt = diskusedPrepare(&s,
"SELECT quote(name), quote(tblname),\n" /* 0..1 */
" is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
" depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
@@ -801,7 +812,7 @@ static void analyzeFunc(
sqlite3_column_int64(pStmt, 17));
}
if( rc!=SQLITE_DONE ){
analysisError(&s, "SQL run-time error: %s\nSQL: %s",
diskusedError(&s, "SQL run-time error: %s\nSQL: %s",
sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
sqlite3_finalize(pStmt);
return;
@@ -814,14 +825,14 @@ static void analyzeFunc(
sqlite3_free);
s.pOut = 0;
}
analysisReset(&s);
diskusedReset(&s);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_analyze_init(
int sqlite3_diskused_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
@@ -829,8 +840,8 @@ int sqlite3_analyze_init(
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "analyze", 1,
rc = sqlite3_create_function(db, "diskused", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS,
0, analyzeFunc, 0, 0);
0, diskusedFunc, 0, 0);
return rc;
}
+4
View File
@@ -1165,6 +1165,9 @@ static char *portable_realpath(const char *zPath){
** The file or directory X is not required to exist. The answer is formed
** by calling system realpath() on the prefix of X that does exist and
** appending the tail of X that does not (yet) exist.
**
** FIXME: This routine sometimes returns NULL rather than raising
** an SQLITE_NOMEM error if an OOM is encountered.
*/
static void realpathFunc(
sqlite3_context *context,
@@ -1187,6 +1190,7 @@ static void realpathFunc(
if( zPath==0 ) return;
if( zPath[0]==0 ) zPath = ".";
zCopy = sqlite3_mprintf("%s",zPath);
if( zCopy==0 ) return;
len = strlen(zCopy);
while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
len--;
+23 -10
View File
@@ -179,16 +179,26 @@ static unsigned int deltaGetInt(const char **pz, int *pLen){
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36,
-1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
unsigned int v = 0;
int c;
unsigned char *z = (unsigned char*)*pz;
unsigned char *zStart = z;
while( (c = zValue[0x7f&*(z++)])>=0 ){
v = (v<<6) + c;
unsigned char *zEnd = z + (*pLen);
while( z<zEnd && (c = zValue[*z])>=0 ){
v = (v<<6) + c;
z++;
}
z--;
*pLen -= z - zStart;
*pLen -= (int)(z - (unsigned char*)*pz);
*pz = (char*)z;
return v;
}
@@ -278,7 +288,8 @@ static unsigned int checksum(const char *zIn, size_t N){
** The delta string will be NUL-terminated, but it might also contain
** embedded NUL characters if either the zSrc or zOut files are
** binary. This function returns the length of the delta string
** in bytes, excluding the final NUL terminator character.
** in bytes, excluding the final NUL terminator character. It returns
** 0 if an OOM occurs.
**
** Output Format:
**
@@ -370,6 +381,7 @@ static int delta_create(
*/
nHash = lenSrc/NHASH;
collide = sqlite3_malloc64( (sqlite3_int64)nHash*2*sizeof(int) );
if( collide==0 ) return 0;
memset(collide, -1, nHash*2*sizeof(int));
landmark = &collide[nHash];
for(i=0; i<lenSrc-NHASH; i+=NHASH){
@@ -520,7 +532,7 @@ static int delta_create(
static int delta_output_size(const char *zDelta, int lenDelta){
int size;
size = deltaGetInt(&zDelta, &lenDelta);
if( *zDelta!='\n' ){
if( lenDelta<=0 || *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
@@ -562,7 +574,7 @@ static int delta_apply(
#endif
limit = deltaGetInt(&zDelta, &lenDelta);
if( *zDelta!='\n' ){
if( lenDelta<=0 || *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
@@ -570,6 +582,7 @@ static int delta_apply(
while( *zDelta && lenDelta>0 ){
unsigned int cnt, ofst;
cnt = deltaGetInt(&zDelta, &lenDelta);
if( lenDelta<=0 ) return -1;
switch( zDelta[0] ){
case '@': {
zDelta++; lenDelta--;
@@ -889,7 +902,7 @@ static int deltaparsevtabNext(sqlite3_vtab_cursor *cur){
}
z = pCur->aDelta + pCur->iCursor;
pCur->a1 = deltaGetInt(&z, &i);
switch( z[0] ){
switch( i>0 ? z[0] : 0 ){
case '@': {
z++;
if( pCur->iNext>=pCur->nDelta ){
@@ -1019,7 +1032,7 @@ static int deltaparsevtabFilter(
a = pCur->aDelta;
pCur->eOp = DELTAPARSE_OP_SIZE;
pCur->a1 = deltaGetInt(&a, &i);
if( a[0]!='\n' ){
if( i<=0 || a[0]!='\n' ){
pCur->eOp = DELTAPARSE_OP_ERROR;
pCur->a1 = pCur->a2 = 0;
pCur->iNext = pCur->nDelta;
+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
}
+1 -1
View File
@@ -296,7 +296,7 @@ static void prefixLengthFunc(
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++;
}
+1 -1
View File
@@ -363,7 +363,7 @@ static int qpvtabBestIndex(
}
sqlite3_str_appendf(pStr,"aConstraint,%d,%s,%d,%d,",
i,
azColname[iCol],
iCol>=0 ? azColname[iCol] : "rowid",
op,
pIdxInfo->aConstraint[i].usable);
pVal = 0;
-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
+29 -11
View File
@@ -400,6 +400,16 @@ static double seriesFloor(double r){
}
#endif
/* Convert a floating point value to its closest integer. Do so in
** a way that avoids 'outside the range of representable values' warnings
** from UBSAN.
*/
sqlite3_int64 seriesRealToI64(double r){
if( r<-9223372036854774784.0 ) return SMALLEST_INT64;
if( r>+9223372036854774784.0 ) return LARGEST_INT64;
return (sqlite3_int64)r;
}
/*
** This method is called to "rewind" the series_cursor object back
** to the first row of output. This method is always called at least
@@ -522,7 +532,7 @@ static int seriesFilter(
&& r>=(double)SMALLEST_INT64
&& r<=(double)LARGEST_INT64
){
iMin = iMax = (sqlite3_int64)r;
iMin = iMax = seriesRealToI64(r);
}else{
goto series_no_rows;
}
@@ -530,15 +540,19 @@ static int seriesFilter(
iMin = iMax = sqlite3_value_int64(argv[iArg++]);
}
}else{
if( idxNum & 0x0300 ){ /* value>X or value>=X */
if( idxNum & 0x0300 ){ /* value>X (0x200) or value>=X (0x100) */
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
double r = sqlite3_value_double(argv[iArg++]);
if( r<(double)SMALLEST_INT64 ){
if( r<=(double)SMALLEST_INT64 ){
iMin = SMALLEST_INT64;
}else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
iMin = (sqlite3_int64)seriesCeil(r)+1;
}else if( r>(double)LARGEST_INT64 ){
goto series_no_rows;
}else{
iMin = (sqlite3_int64)seriesCeil(r);
iMin = seriesRealToI64(seriesCeil(r));
if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
if( iMin==LARGEST_INT64 ) goto series_no_rows;
iMin++;
}
}
}else{
iMin = sqlite3_value_int64(argv[iArg++]);
@@ -551,15 +565,19 @@ static int seriesFilter(
}
}
}
if( idxNum & 0x3000 ){ /* value<X or value<=X */
if( idxNum & 0x3000 ){ /* value<X (0x2000) or value<=X (0x1000) */
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
double r = sqlite3_value_double(argv[iArg++]);
if( r>(double)LARGEST_INT64 ){
if( r>=(double)LARGEST_INT64 ){
iMax = LARGEST_INT64;
}else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
iMax = ((sqlite3_int64)r)-1;
}else if( r<=(double)SMALLEST_INT64 ){
goto series_no_rows;
}else{
iMax = (sqlite3_int64)seriesFloor(r);
iMax = seriesRealToI64(seriesFloor(r));
if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
if( iMax==SMALLEST_INT64 ) goto series_no_rows;
iMax--;
}
}
}else{
iMax = sqlite3_value_int64(argv[iArg++]);
+1 -1
View File
@@ -175,7 +175,7 @@ static void hash_step(
}else{
i = 0;
}
(void)memcpy(&p->buffer[j], &data[i], len - i);
if( len-i>0 ) (void)memcpy(&p->buffer[j], &data[i], len - i);
}
/* Compute a string using sqlite3_vsnprintf() and hash it */
+10 -9
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;
@@ -422,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)*5LL*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];
@@ -772,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];
@@ -906,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);
@@ -932,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;
@@ -1721,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;
@@ -2066,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{
+1
View File
@@ -120,6 +120,7 @@ static int sqlite3UuidStrToBlob(
unsigned char *aBlob /* Write results here */
){
int i;
if( zStr==0 ) return 1;
if( zStr[0]=='{' ) zStr++;
for(i=0; i<16; i++){
if( zStr[0]=='-' ) zStr++;
+9 -2
View File
@@ -13,6 +13,11 @@
** This file implements a virtual table that returns the whole numbers
** between 1 and 4294967295, inclusive.
**
** TESTING AND DEBUG USE ONLY -> This is not production code. This is
** not a deliverable. Use the generate_series() virtual table for
** real-world applications instead of this extension. THIS EXTENSION
** MAY CONTAIN BUGS.
**
** Example:
**
** CREATE VIRTUAL TABLE nums USING wholenumber;
@@ -154,12 +159,14 @@ static int wholenumberFilter(
pCur->iValue = 1;
pCur->mxValue = 0xffffffff; /* 4294967295 */
if( idxNum & 3 ){
v = sqlite3_value_int64(argv[0]) + (idxNum&1);
v = sqlite3_value_int64(argv[0]);
if( v<=pCur->mxValue && (idxNum&1)!=0 ) v++;
if( v>pCur->iValue && v<=pCur->mxValue ) pCur->iValue = v;
i++;
}
if( idxNum & 12 ){
v = sqlite3_value_int64(argv[i]) - ((idxNum>>2)&1);
v = sqlite3_value_int64(argv[i]);
if( v>0 && ((idxNum>>2)&1)!=0 ) v--;
if( v>=pCur->iValue && v<pCur->mxValue ) pCur->mxValue = v;
}
return SQLITE_OK;
+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);
+21 -10
View File
@@ -516,16 +516,26 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36,
-1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
unsigned int v = 0;
int c;
unsigned char *z = (unsigned char*)*pz;
unsigned char *zStart = z;
while( (c = zValue[0x7f&*(z++)])>=0 ){
v = (v<<6) + c;
unsigned char *zEnd = z + (*pLen);
while( z<zEnd && (c = zValue[*z])>=0 ){
v = (v<<6) + c;
z++;
}
z--;
*pLen -= (int)(z - zStart);
*pLen -= (int)(z - (unsigned char*)*pz);
*pz = (char*)z;
return v;
}
@@ -601,7 +611,7 @@ static int rbuDeltaApply(
#endif
limit = rbuDeltaGetInt(&zDelta, &lenDelta);
if( *zDelta!='\n' ){
if( lenDelta<=0 || *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
@@ -609,11 +619,12 @@ static int rbuDeltaApply(
while( *zDelta && lenDelta>0 ){
unsigned int cnt, ofst;
cnt = rbuDeltaGetInt(&zDelta, &lenDelta);
if( lenDelta<=0 ) return -1;
switch( zDelta[0] ){
case '@': {
zDelta++; lenDelta--;
ofst = rbuDeltaGetInt(&zDelta, &lenDelta);
if( lenDelta>0 && zDelta[0]!=',' ){
if( lenDelta>0 || zDelta[0]!=',' ){
/* ERROR: copy command not terminated by ',' */
return -1;
}
@@ -638,7 +649,7 @@ static int rbuDeltaApply(
/* ERROR: insert command gives an output larger than predicted */
return -1;
}
if( (int)cnt>lenDelta ){
if( (i64)cnt>(i64)lenDelta ){
/* ERROR: insert count exceeds size of delta */
return -1;
}
@@ -676,7 +687,7 @@ static int rbuDeltaApply(
static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){
int size;
size = rbuDeltaGetInt(&zDelta, &lenDelta);
if( *zDelta!='\n' ){
if( lenDelta<=0 || *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
@@ -724,7 +735,7 @@ static void rbuFossilDeltaFunc(
return;
}
aOut = sqlite3_malloc(nOut+1);
aOut = sqlite3_malloc64((i64)nOut+1);
if( aOut==0 ){
sqlite3_result_error_nomem(context);
}else{
+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);
+6 -3
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
@@ -761,6 +761,9 @@ static int nodeAcquire(
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
}else if( iNode<=0 ){
RTREE_IS_CORRUPT(pRtree);
rc = SQLITE_CORRUPT_VTAB;
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
if( !pNode ){
@@ -1402,7 +1405,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;
@@ -3644,7 +3647,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
+1 -1
View File
@@ -1557,7 +1557,7 @@ SQLITE_WASM_EXPORT2(int,sqlite3__wasm_posix_create_file,
SQLITE_WASM_EXPORT2(const char *,sqlite3__wasm_kvvfsMakeKey,
(const char *zClass, const char *zKeyIn)){
static char buf[SQLITE_KVOS_SZ+1] = {0};
assert(sqlite3KvvfsMethods.nKeySize>24);
assert(sqlite3KvvfsMethods.nKeySize>32);
if( zClass && *zClass ){
kvrecordMakeKey(zClass, zKeyIn, buf);
return buf;
+2 -7
View File
@@ -982,11 +982,11 @@ FUZZCHECK_SRC = sqlite3.c \
$(TOP)/ext/recover/dbdata.c \
$(TOP)/ext/recover/sqlite3recover.c \
$(TOP)/test/vt02.c \
$(TOP)/ext/misc/analyze.c \
$(TOP)/ext/misc/base64.c \
$(TOP)/ext/misc/base85.c \
$(TOP)/ext/misc/completion.c \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/diskused.c \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/randomjson.c \
$(TOP)/ext/misc/regexp.c \
@@ -2236,11 +2236,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)
@@ -2345,12 +2340,12 @@ SHELL_DEP = \
$(TOP)/ext/expert/sqlite3expert.h \
$(TOP)/ext/intck/sqlite3intck.c \
$(TOP)/ext/intck/sqlite3intck.h \
$(TOP)/ext/misc/analyze.c \
$(TOP)/ext/misc/appendvfs.c \
$(TOP)/ext/misc/base64.c \
$(TOP)/ext/misc/base85.c \
$(TOP)/ext/misc/completion.c \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/diskused.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/memtrace.c \
+114 -114
View File
@@ -1,5 +1,5 @@
C Avoid\sa\sresource\sleak\sin\san\serror\spath\sin\sthe\sicu\sextension.
D 2026-05-28T11:29:05.704
C Use\sSQLITE_FINISH\sin\sa\sfew\splaces\sin\sthe\score,\sto\shelp\sensure\sthat\spath\sis\nwell\stested.
D 2026-06-19T22:57:44.085
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -7,7 +7,7 @@ F AGENTS.md 44ddfb38ef23e277888bd70ae378e6cbf5f5cab0e2a4420bd21d89b6caff7a4a
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
F Makefile.in 5fda086f33b144da08119255da1d2557f983d0764a13707f05acf0159fd89ba5
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 6f4294982758b5eeeac740c1a263186c3fcb9ba51d1b48261e321bcb37a41dbb
F Makefile.msc ae6c8f8c39ed9cec7e3fc27390209117a943acd81941b5e81e8cd828b1875d93
F README.md f00091ffb5c6379b783afb57ca5f443a5742e119082f37c407f64a5e16c56346
F VERSION 99cf3be5f13d091183e4314b7fc2e0c0e69accfbe64608b45a313338bbdd7b62
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -48,7 +48,7 @@ F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1
F autosetup/jimsh0.c 740dc8cbfaedaff1f27b54b32e0015b22fa6c1a439492b9795968d61e56bab75
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
F autosetup/proj.tcl 67683f214977a416baafc4c1020f9940ff047a7306b2292c5872d6287460b7d5
F autosetup/sqlite-config.tcl 2205b8bcc193a5d46584ebc1cf44c7a93a977d155e20dc38b18dcce720e58074
F autosetup/sqlite-config.tcl a503f8b418547c2872348dbcb71abb09726f3970088625ec90d8000035b06b32
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
F autosetup/teaish/core.tcl e014dd95900c7f9a34e8e0f460f47e94841059827bce8b4c49668b0c7ae3f1a0
@@ -72,24 +72,24 @@ F doc/wal-lock.md 7db0cd61e2000b545b78ce89b0c2a9a8dd8d64c097839258ac10d7c5c4156e
F ext/README.md 6eb1ac267d917767952ed0ef63f55de003b6a5da433ce1fa389e1a9532e73132
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
F ext/expert/expert1.test d9dfbf7fb527cfd43049e30a6238ef02c94484041fa4461ed41acbc6435425d6
F ext/expert/sqlite3expert.c 546010043fbec93544f762de5161b3d553165859e6bd853c4b85c05f93484260
F ext/expert/expert1.test 5292f9f488ca396fa0973e8ed5d26914bc29a0cdb5979db3d9e05416f30858c3
F ext/expert/sqlite3expert.c 1a5296245bf80c201b2f5fa5947ef54a7d2b7e90428cb86240dd18076242ec1f
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c c395134bd6d4efa594a7d26578a1cb624c4027b79b4b5fcd44736c5ef1f5f725
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
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 4e62e96794ee8a5e73b1357e63d9b7749c30e0f712db3dfe27cd515e50afce9d
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 277f32f304e82f4397fc2a74793c0a95318b7abb9670b519e4805a00946cbd9b
F ext/fts3/fts3_aux.c c105f6502df588f49a383eb22aed953844fb0e31265361a0cc8dd73037b37e39
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 65e178107b59ad4724a11339a645f2e3789f3cf59b2f4e29c90efd864e53c5b4
F ext/fts3/fts3_snippet.c 004923c49dca8c711f83fd31d3abe2e663df174afeae096b1c902cc52fda2097
F ext/fts3/fts3_term.c 6a96027ad364001432545fe43322b6af04ed28bb5619ec51af1f59d0710d6d69
F ext/fts3/fts3_test.c cc329471e573f95a6ea9fbca87e89dcfa1d355591c80172ffcd759ac521d25d8
F ext/fts3/fts3_tokenize_vtab.c 66eba6c2baa04b2b15e80d68341b8fd0b4d3831f6b2edb33916a2906ff2d4389
@@ -98,7 +98,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c c1de4ae28356ad98ccb8b2e3388a7fdcce7607b5523738c9afb6275dab765154
F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
F ext/fts3/fts3_write.c d218b687fb55bce8c9340c6dbb368a10d94647cbe39801d85492d576a4e7da75
F ext/fts3/fts3_write.c 3a78030f52747d53ef8c9bdff8ad137957834ce2ff7367db5de2b0fabdbefb5f
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
@@ -109,14 +109,14 @@ F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a0
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
F ext/fts5/fts5.h ff5d3cc88b29e41612bfb29eb723e29e38973de62ca75ba3e8f94ccb67f5b5f2
F ext/fts5/fts5Int.h 8d98f8e180fe28d6067e240ed45b9011735d29d5cfb5bac194e1e376baa7c708
F ext/fts5/fts5_aux.c 042da27e97d38071312c111cf18f3cb7983b75ba5e724aa1c3164e61e90f428a
F ext/fts5/fts5_aux.c 27af933e1a052d9f12d62a45bc60e0b65023997e0cea8f0476ef3cf66e724599
F ext/fts5/fts5_buffer.c dcc3f0352339fe79c9d8abbc1c2009bc3469206467880bf43558447ef4f846fb
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 87faf9a9ca65ec7be0886e13e9f7571d0d2416ab88e77a06d57bbaf3734bd51f
F ext/fts5/fts5_expr.c b906c59e9e842805cc3eea4e131b822e586bb01260e542f67920c61798dcb53d
F ext/fts5/fts5_hash.c 341a08ad0153b397b819ef3d7a7959c1dc3c84a6988a431d93dece8bd62ae10e
F ext/fts5/fts5_index.c 5a2ab65d170a4b3314a927c5861740ba9070aa5bf326717690de5dd90fbb7b54
F ext/fts5/fts5_main.c b0fed47b3b4420ba6810373480a75bc28a9c0b7d16478d19a396436fb3ff17d7
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
F ext/fts5/fts5_storage.c 46b0024fdd8002fbfba162230e5cc212c8f019ba4075396860354bfaf549a546
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
@@ -132,7 +132,7 @@ F ext/fts5/test/fts5ab.test c7e5c1519afb20366cb40d0179897a3c39d9fc06ba6b9c286d79
F ext/fts5/test/fts5ac.test 4a73626de86f3d17c95738034880c4f0de8d54741fb943d819b528373657e59b
F ext/fts5/test/fts5ad.test 058e616612964e61d19f70295f0e6eaedceb4b29b1fbf4f859615ef7e779dc22
F ext/fts5/test/fts5ae.test 3d49edbd50bb0684199a2e7568aeb30d1d29718f5c0f61751983740fa836d15f
F ext/fts5/test/fts5af.test ae81f08b8da4c5f9b3ec1ef538a4ab6b7c278e92fa9058d6dc5d842c5d9771b9
F ext/fts5/test/fts5af.test 06f05ef35e8c66d8200204379e03d386673cf0c6f052bd67ddc3091dac3d32e9
F ext/fts5/test/fts5ag.test 6667807b5d3fbf460892e756763fbe3d87a2fffe345a06514ba010ca6f6641f7
F ext/fts5/test/fts5ah.test e1f01314b35745a30e1b494b46045b82005d71cae74f1ebd9f1338566b77f9fc
F ext/fts5/test/fts5ai.test cbe26d78030998f535bc103f37915350b137a822c71a9db439a077d7666a3539
@@ -147,6 +147,7 @@ F ext/fts5/test/fts5auxdata.test 372549088ff792655f73e62b9dfaf4863ce74f5e604c06c
F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd
F ext/fts5/test/fts5bigpl.test 8f09858aab866c33593560e6480b2b6975ae7ff29ca32ad7b77e2da61402f8ef
F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
F ext/fts5/test/fts5bigtok2.test d519c0c7c45fcbe75093cb9f4ea47defabbb4e8dd5d44411c8b12da47df538d9
F ext/fts5/test/fts5blob.test 9644a5f917306690e08c5f89a470a3f2489376eaa52026eeca3209d149d6af74
F ext/fts5/test/fts5cat.test bf67dd335f964482ee658287521b81e2b88697b45eb7f73933e15f198ed447cb
F ext/fts5/test/fts5circref.test 0918c69440a73fff429bc9797b07086fc74d018eb3abb1cf9738980390bb2713
@@ -165,12 +166,12 @@ F ext/fts5/test/fts5corrupt.test 237fce1c3261bb3a5bec333b0f0dbf5b105ec32627ef14c
F ext/fts5/test/fts5corrupt2.test 4a03a158c2cb617c9f76d26b35c1ef2534124bc0bbddcea38dfd5b170ebea27b
F ext/fts5/test/fts5corrupt3.test 121a8a7622dfe1be1bc55cbe70eddd6a3416f76a837dc8c06a11a32e781595a4
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
F ext/fts5/test/fts5corrupt5.test bdf6c04a1c9176507c8c0e66842b78b3fbcafccde20a41bb22a1b19896784b54
F ext/fts5/test/fts5corrupt5.test 541dcee99eee8736f6b252d996a1262a778aa9fbe6344c781f9ea2becfae0bf5
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/fts5corruptA.test 43bc56d8ec0ac87f82f6ac1700c16c902d952451f75f5c7dc02292c7b0a1d1b1
F ext/fts5/test/fts5corruptbig.test 9f95b40fa36e292feceab02b2ef06e21878bfa1ac7afefa138aae05518b51774
F ext/fts5/test/fts5delete.test 2a5008f8b1174ef41d1974e606928c20e4f9da77d9f8347aed818994d89cced4
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
@@ -208,14 +209,14 @@ F ext/fts5/test/fts5join.test 3791e30d034050281191cd8141d969849f6c060135f1e3938f
F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1
F ext/fts5/test/fts5leftjoin.test 1c14b51f4d1344a89e488160882f05a2246dd7e70c5cf077c8fb473e03c66338
F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fce79fa43004dff01c
F ext/fts5/test/fts5locale.test 83ba7ee12628b540d3098f39c39c1de0c0440eddff8f7512c8c698d0c4a3ae3c
F ext/fts5/test/fts5locale.test e662cc85b348d27247a7881409d1d1a5f910686c016591094be959d7a1b5a0ba
F ext/fts5/test/fts5matchinfo.test bc9e74157773db7f00aec1e85587f1145956ebdf1672c136f0f04323b2752aa0
F ext/fts5/test/fts5merge.test 088133e135ef7dcd6701753c95b8b10be3c52fa1a99507933e00756d6437489e
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
F ext/fts5/test/fts5misc.test 83d6c5101a092c5db8fb631cfdd69a6482e20528b2750427641ac9050d9d0381
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
F ext/fts5/test/fts5near.test 33d60867581066e5db7016deb5d651628125d7ff4e0233a88175aa5b65874c74
F ext/fts5/test/fts5near.test b173a56a3c45ac9fdd1626db2ddf923c42632489a4ccedfe68a806c1a0734286
F ext/fts5/test/fts5onepass.test b56d4109e841c2bc83555c162515748780ea6e0c455c54cf4afd4bd940d14b84
F ext/fts5/test/fts5optimize.test 264b9101721c17d06d1d174feb743fda3ddc89fad41dee980fef821428258e47
F ext/fts5/test/fts5optimize2.test 795d4ae5f66a7239cf8d5aef4c2ea96aeb8bcd907bd9be0cfe22064fc71a44ed
@@ -250,7 +251,7 @@ F ext/fts5/test/fts5securefault.test c34a28c7cd2f31a8b8907563889e1329a97da975c08
F ext/fts5/test/fts5simple.test 302cdb4f8a3350b091f4f1bccd82d05610428657f6f9e81c17703ba48267ec40
F ext/fts5/test/fts5simple2.test d10d963a357b8ec77b99032e4c816459b4dbdb1f6eee25eada7ef3ed245cb2dc
F ext/fts5/test/fts5simple3.test 4e03b82e669dc07bf9c9a04c306fa493764bc49c93e539896d87d88bd374fece
F ext/fts5/test/fts5synonym.test becc8cea6cfc958a50b30c572c68cbfdf7455971d0fe988202ce67638d2c6cf6
F ext/fts5/test/fts5synonym.test e7facc771e5d00f24df64e169d466cb544b584f5cccc9a346eb30235e6dff82c
F ext/fts5/test/fts5synonym2.test 58f357b997cf2fedeeb9d0de4db9f880fa96fa2fe27a743bfe7d7b96895bdd87
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
@@ -280,7 +281,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 1bc9a5b60e6ec12fc9795aa3a416547e44ee826d954e28a4c36de28eec14d907
F ext/icu/icu.c 4793f95ec022a2f77eade71a7fb2199095756e5b8187b4753ada0e25dbd134b5
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/intck/intck1.test 53d885075abeb45aeb1eeffeaa8560b329060835ade4af5c44cf5fcb581c1e63
F ext/intck/intck2.test a29343a8e65c5c3400e10747f394924f3df95a5b2de94f46e9b5c9b97f5e7339
@@ -360,25 +361,24 @@ F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b6
F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
F ext/misc/README.md 6243cdc4d7eb791c41ef0716f3980b8b5f6aa8c61ff76a3958cbf0031c6ebfa7
F ext/misc/amatch.c 972a250631d481f38736b46740bf7f5c9646a0f2bb53800543299a746ff1bac6
F ext/misc/analyze.c d311ad12179ef4f945f18fbe7917a3a602765afd152e5bd71d358ee9a7c67473
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
F ext/misc/base64.c 1445761667c16356e827fc6418294c869468be934429aaa8315035e76dd58acf
F ext/misc/base85.c c713c7c81b05558c488cbdd8c68d612d5a97f9f0b8adf1167148dd7c89ce3f96
F ext/misc/basexx.c 89ad6b76558efbceb627afd5e2ef1d84b2e96d9aaf9b7ecb20e3d00b51be6fcf
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
F ext/misc/btreeinfo.c 5fe97f798a9ee90e92b3031ed7969ec3f558661bb36b821c3ba045a17cfb951c
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/csv.c 5e9d4dd749e762c144104c0f01db5bf4458735b19081ebe481a64e589a66687a
F ext/misc/compress.c 5cc142aa82d1589a31c384657d0418c0eb0871348a2201e5dca32d24a0dd6654
F ext/misc/csv.c 5ca451b9ce77322c4ce8476766e7ed18160e5c8b19e7cab76e13006d631b9e8f
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
F ext/misc/decimal.c 432e5b03a0e2a68a1846a9852a565a1b546ca9b295deda834e4653f0f5577daa
F ext/misc/decimal.c 75f206e86072bd772041e6731d153517094e298a4b8c763a9f68d73d21b52651
F ext/misc/diskused.c 8acb4f27488fd8b9bdb0a3d300a7bd761b797b6e7858ac8038398263cededc48
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 9670c8ff7b255eea7845abc5123a4958e74016c16990b10497e56380f91704b9
F ext/misc/fileio.c 936c0a7b3382a047d833ad33f62ba59a3847b79ea745bf529797cd344966fbb0
F ext/misc/fossildelta.c 6aa3f15279cd2d796583e3ff654be7d2df745fdbea7987c1640e78ce1fac899e
F ext/misc/fileio.c a8caf3ffb59af6e9870d1a1c739981727ba165cd667bda085fa21ccfc8694059
F ext/misc/fossildelta.c 37b67b2710a0dd2da7b3aeea19388a069471eb0fc04702a0521237770d0d04f1
F ext/misc/fuzzer.c decaca5a3479dfba69576cd41d4e17161eaf154a5438e12d316bbc5853571802
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
F ext/misc/memstat.c 03ab52d2d841eb3f55118105c1964d5225f152b23bd708844c648b48d14ccbcf
@@ -388,19 +388,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 efc261429fd8ab43cedc0d38b94d86d87437af5550651bceb618bd7e84e25125
F ext/misc/qpvtab.c 470a5fffba005c8e1994209e59c1848122351e19522de71beb68d666c4fa39a5
F ext/misc/percentile.c b6b9c740f0dc42838efd776eec0f68a93bc5ac86524c71337a70950860bf6c4d
F ext/misc/prefixes.c e7d3e7a39174db412c5f77c266fa221c2dc3cb2621a9422835a607ad08805eb2
F ext/misc/qpvtab.c eeb04e4fcead64648629d6375077a5d5fd48c0384023edd21defa32730714d5e
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
F ext/misc/regexp.c 378e6e84516952a4b9f3f4df88927f20e6538e2609f55b773ed78899dab8206e
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c df54e202887e480bf9cd73168c9ac829e3b0211381b68b9809e0cb5bc1bdc2cf
F ext/misc/series.c 496f43bac9bad2ee2cea63fb5212036f30ad3003b4cd317d5c2d6f3ad7c7d264
F ext/misc/sha1.c 9a11826db885e8afd997c0a1b28bb799a43e462ef770ac33f19e744887c9c6fa
F ext/misc/series.c ba66183ae4da6875e5cdafc065322118fd7f455a568ea2f22b45eff85f639f42
F ext/misc/sha1.c eed0ad67ad7c69798278183a74523d95623d4864821a3f4dd82b234568e307c1
F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 36b0f4893ff583b6dcc727beca44cc262e7855713aea57a0154766936352cf81
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
@@ -412,15 +411,15 @@ F ext/misc/totype.c ba11aac3c0b52c685bd25aa4e0f80c41c624fb1cc5ab763250e09ddc762b
F ext/misc/uint.c 327afc166058acf566f33a15bf47c869d2d3564612644d9ff81a23efc8b36039
F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
F ext/misc/uuid.c 37297e61935c2d0c425b742100f904d02c866fdeabe0427fe59aed1543e7c0ec
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
F ext/misc/vfsstat.c 2b21efa93062ce814fbe28e6dff2acfafa4073a14b8d02cacfb4da1d604d05a5
F ext/misc/vfstrace.c fc8c393a8316a8c20867b7e6e92908c4f81060c9e1f24d6ad9aefdc91c01dd13
F ext/misc/vtablog.c 6c0c11c4822ab6c1a205718ea7c6d1bb561d96b27104b9c1fe84d01aa62d6c9c
F ext/misc/vtshim.c f5ab480d1e33fa46a0b138359bedc9979e32798d72348e04bbe6093f9ae95c7b
F ext/misc/wholenumber.c aa5e6d786fe8d79bc100ea0e852249c026a91ae65a5c1bcb2b869cd1a7cdd6d5
F ext/misc/wholenumber.c e41953e078894e66a0ff05dd6c76a61f904828c9a4620c7255fac26754f30d3a
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
@@ -470,7 +469,7 @@ F ext/rbu/rbuvacuum.test e3585cfda220038e8186c583e9bd2aaa9eccd0a5c2e40ed861de3c9
F ext/rbu/rbuvacuum2.test 1a9bd41f127be2826de2a65204df9118525a8af8d16e61e6bc63ba3ac0010a23
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
F ext/rbu/sqlite3rbu.c 28246b647831409e84dfb8286fbeda55f1de89e934571509a23a67ada572d0c0
F ext/rbu/sqlite3rbu.c c84dd68888640c56aa4d713e38013a202b10bf1ef2e423f7be2167bd826e69d8
F ext/rbu/sqlite3rbu.h e3a5bf21e09ca93ce4e8740e00d6a853e90a697968ec0ea98f40826938bdb68e
F ext/rbu/test_rbu.c 8b6e64e486c28c41ef29f6f4ea6be7b3091958987812784904f5e903f6b56418
F ext/recover/dbdata.c 10d3c56968a9af6853722a47280805ad1564714d79ea45ac6f7da14bb57fd137
@@ -493,8 +492,8 @@ F ext/recover/sqlite3recover.c dfbfca5a8e4909333e5aa3749bcffb5dd7e396de9541c338f
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 acc098e82686fa278c20973d601b4c2489389f5d580d42efe0f799d2cf8cdf38
F ext/rtree/geopoly.c 77bad24162b6ae84a2fd6de3f1f8ad0b255a4ceb572f50f8771d1ac9d4d986d8
F ext/rtree/rtree.c 0e7e3dd53ef90ab540ed991df3395f4e2e2204e85351a2e6bc3e6ae55c23640c
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -505,7 +504,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
@@ -607,7 +606,7 @@ F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 4325cb9a5ebfbff7cd3060e309b16711
F ext/wasm/api/sqlite3-vfs-opfs-wl.c-pp.js 3dbd918ef037cd8fa9c7b4dccb3c8637b228638654c429e7df6acab5981c75e2
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3da8fe72dc9e76614a9c102b92e777ce03f81d788b607701c828d8fcbac44b06
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 366596d8ff73d4cefb938bbe95bc839d503c3fab6c8335ce4bf52f0d8a7dee81
F ext/wasm/api/sqlite3-wasm.c ddf9d435b2e901eaceb805ff694e9609c2f32b5cf89a4f164e734a6fa303fdd2
F ext/wasm/api/sqlite3-wasm.c 0bcc42b1faff0e4543bba1b595fe9cfde80e0c29e3abc475bce725f2a326a8e5
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 46919740f8176c10f691431a81c769c35657e3b537e2ed2bde691f9017b0ee8a
F ext/wasm/api/sqlite3-worker1.c-pp.js 21b20d3b8d43471d1647123616a7e5435b1e4b6fa447714f91ffc7f950ea01e8
F ext/wasm/common/SqliteTestUtil.js dae753b95e72248c4395d8de8359e0d055cd9928488e8dd84aef89e46d23b32e
@@ -660,7 +659,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 d9cbbee974a8cd3999430130378878bd87b8c5754397a69ec322f4c9cc3e4e41
F main.mk 77e33a16a795abd4a07a55f7eb2e11136326998db597b67c8655d5d2d9b98054
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -671,38 +670,38 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
F src/alter.c d7cbe4332a7a2c3a21ab58ee2609efade493f6ae78254613ada0759898629ee3
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
F src/alter.c ff7f795c602751a574488780cfa1259f24cccbf32ddf2205b6283c0e6998ae50
F src/analyze.c 73162482c656187823217f4c00758c9ee13a420c8745bc542129e0279b792287
F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338
F src/auth.c b5ece4e1edccad082c0332fa0087df225473bae0feea9269f824312201377185
F src/backup.c 6ebe22ccbedfcb92423833992130e8d65824be4e6599c3a03f540ab38fc7d13c
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c 2f74489af68281d143f5c4e9ef8ba280cee86fce67a64b3eff9344bbabc5dadf
F src/btree.c c9b13797b0b68e0c057ec796976b1ab1e8b4e766d1a7c7f919b2d8a1d2193a80
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c 866e584cdf40fbc83f530af9fd4d0991582a6fdbd8a9911b7cdbbea5f26a4a9e
F src/build.c 09946336c3011c2ae2faccdf04e33336e1cd51fd836651be0cd7eb5814f7f6a0
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9a
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
F src/date.c 86d9530729eeb5b3d833e7403de495f4d4b79f3d5f7e74bcc8abda237f5aeafb
F src/dbpage.c c6a9de13b0a01f0bc94a41e16213ab1ecd15ccfe86df7255ced40fda9446257d
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451
F src/expr.c d2188a699ded4522f15cf23d4c82da0ad73dcda09cd943982906824ef019947f
F src/expr.c e97dd9f6ada4c448764e225d8963091bf630b3efb2c92e4d0762571cca2a14e5
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
F src/func.c e8525e6c5493149680b0ebd3352e7f004ee7283181f24809b603329afe911443
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/func.c 7e049176003271095ba560bca90995c8cb7c1e944aee539513daba015b172a18
F src/global.c 7eea537ac0c113ac55cb2dd4d8fc2a6a91ae478be34231b4efaffc46817fee85
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
F src/hwtime.h 5cb15147c8583d0fc4748e1c12ea6f38c9deaeefa147a4d8d379fd9bc81fee9a
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 8dbc22f6ddcc5f0af3abf11daeb89b1978f00059cda15ebc61251fa7724fc7ee
F src/json.c 83122c47ac1c86a3870398e872b1d1afa6439f46fdb92975aa435267771c7ee4
F src/insert.c e6e9b574b4863649e2c433f2260f226183e697df1ab73fcb8da9a85d5abcd390
F src/json.c f058c449acb9fdb1d3d1bb9f7e97b225ba773f5b6fdcec4310d3f49980125ed4
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 78d5b06f18996ffa1203129b28fea043f63a87a4117539678f1d761c30b4ff65
F src/main.c 6180079f53ccdd784df2eddc3751f49ea7153c5959bee792b19ad9f4bdbcf437
F src/loadext.c 5cd4cd7ec6e1a46416806899086363fbf95eecd3bfb9a388b436c9a77243c902
F src/main.c efd782fadd65b8e67952f439d56d7605134582346573018a614a8e082e074bd7
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -718,32 +717,32 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c caec9862aeebad01f6c8997cf709a239abeb0715fcce1895720b87fe7e2ef42f
F src/mutex_w32.c d44e94c064f8ab39e0318fb6fa00171cf7e5645bd4241129b07d655a8ddbd44b
F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
F src/os.c 9566966dd14376099fe8f715e744ab4fef204f55bd89126c5ddd06eb37df9457
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
F src/os_kv.c b9df749ad64c498e8d398d83bb085cfc0ef381b2c103be6c63ac22fc4f2cf680
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
F src/os_unix.c 83759942d1ea8d59daed50901c123016f845fada74caf3496b8a2537c9a08838
F src/os_win.c 8df4b34ec6a08616a7ac33164999524ef773fa359d39ae9ae0e7e1ae4f167440
F src/os_win.c 68b1c31693a5aeeb8126f618c95f7b53fb39e254836f9a95fbf2733461a7e01d
F src/os_win.h c06ccc3a090cf54202ea58981c298817f3309d4c9e4d52ad0a02927346493721
F src/pager.c e0b3b6e39c3a783957d640b28401401d1f3c556803c80695958dd2b9db4ef72d
F src/pager.c f88073a00933c885b167b6d25afc4d1b83c1706943572f5653fb64a7f5bde105
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y d5a3c5b0277a441c38b35071c05e2b61ff5fc918a63309c809f4b6706179c320
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
F src/pcache1.c d7ee0f95992501a65379f620b3de1430b64e52e397769938668a9fd9dd1c8145
F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d
F src/prepare.c 084a037fd3810cb7ffbfc001cd58c0ffac68ba36598a5084b55ea2a090014ebd
F src/printf.c 2bc09ee91d69c709528575bbbee2199e16d6a7e68e1508ac7cf998a7289170ca
F src/prepare.c d055c59c23b917367ed199a52888132316aa9cb9f7653ca71f0c45bd267206fd
F src/printf.c 6916d50913c3271aefe96d3483701ceca8644331ec4c7b23a5aa54a9ba36230f
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 7e936a09405cb59e2b3e51a3ad23753e4803afc5269c5171a54c9bdd70f4fc50
F src/resolve.c d0724113da9f5c0430d2052808ce59519f51ae7c4fbb1f5ef21fe3a832956086
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4c05cde130f26991b7411d8c6809e0630625e18078742c963a047b4b9cc01d49
F src/shell.c.in 691fac6a7f6f6fc72836aa2779d81b8cf67c896a15699c65e810cd1e8c6270f4
F src/sqlite.h.in 749454ec71c875bc130d399ff9a7e47191d143d1b9d8b4af3839b6028df9eda9
F src/select.c 80ea6935f8470b97d1212bc1b759b7fadb28351797877f493d0cf598be1fef5e
F src/shell.c.in a4e83895cfa336065ad7f7a7dea8fc2a19d050f7ce7466621c67208acaac9e44
F src/sqlite.h.in 8c70db561507478176b942a3f88cac396e00993eafb827ed31d48c191f327408
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
F src/sqliteInt.h 5bec8cfdc8346a122b35312452eb6af33fc750a6c901f2c651a2f53eba0b979f
F src/sqlite3ext.h 0efd4723bad9124ea1f581d9f1ea0254ac1c6f3e5fb29e4f3dcf36c72485a456
F src/sqliteInt.h 92563b8edc673513b82d87bf6a8d7aeb554b2c7b7d5e30992fbca04010db79ac
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -799,32 +798,32 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 85d8b9f05f78211c61e3739ab5db761d7118766d1916ae7f2764735106bc4e13
F src/tokenize.c e9d52d9f7374d82dadcd11726bea8a597d43709d6672704f3f0375bf1d726912
F src/treeview.c feaa59f14db4f7b5aacca9c5ad5aeb562c1f98262c1ffd74371f4186ade91fc5
F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
F src/trigger.c 5028874dd1f4fd3085bacd55c30114b5ad651525508656f65af09adf227181d5
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/upsert.c dd9f0fcccbfb4f20e1026a21a7254ba3f2c08e9cfa92affaff5b5ec3b00ea549
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 98cf12c8ba65623a76c1eb6e6afa98ff40107c9919bf79af42f4bfc70e654232
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
F src/vdbe.c 8ed6f274dff8b9fb961d050a9ab933e7f6509221718bec862e85729d171c1606
F src/vdbe.c 39658ee12b9d6bf5fc546e1ede20b307d86d9e988ae709c9b461249a8312513d
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
F src/vdbeaux.c bd3aaf77593a5590f617ce173e8677a21eca18522eadc1c4bc81b53f6d1c7e19
F src/vdbeapi.c 15c55a4be8edc06055502e15f60f444c8fc5cb6134e38b8486742e89670d5e8f
F src/vdbeaux.c a052c43fcf342651f655e6771003c175d49b237a9473c3c4d79d44725f494dae
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
F src/vdbemem.c efacb8f229422d2a4db0ed38e49b7f3897862a98d82b261aa3b43d7a2d98c6da
F src/vdbemem.c 6e7ad67507c9a8e625b46256a9c003929331d6a27b99bbe139b8f0dab636e1f2
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 5437ce986db2f70e639ce8a3fe68dcdfe64b0f1abb14eaebecdabd5e0766cc68
F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
F src/wal.c 7340d4f9bb827bd349127cac6b2cf0cb7f76b9fda645f7b9b0bf7a6e0b1e2e7c
F src/wal.c abfd99239725a258af4f733681b24dd7a9ee298babe389a36d29c197e2443ebf
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 33e4a6558ee69f33d6a4e7069e3a40a55959d14e5653a9a83926e70305d471f3
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
F src/wherecode.c 4d573077652f79780d6b50840ab8cbb72053dbb4eb230780dd2a146ab034475d
F src/whereexpr.c d111a5cb6147253a54010d883474b6aecc0b3009d352c087ee5295d74697bfef
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
F src/wherecode.c bc39ccbe3648f01157038b16cc55bdbff128590972b7185521b5526dc2815765
F src/whereexpr.c 906d30c21470bbafc31bbc2cd07a0753bdd57169caed6ba75b8b4fc0ecb24134
F src/window.c 0d7dacdf2e84c6ee8ff498d5cc881dd245fcb2f14f6c5976e97e112ce96e90dc
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
F test/affinity3.test 9b7d1133e11d5edd7805573c4ab6f3ba73b0b74a1f280d5b130d4bf3506a93ff
@@ -959,7 +958,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
@@ -1030,7 +1029,7 @@ F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test 85cdfdae5c3de331cd888d6c66e1aba575b47c2e3c3cc4a1d6f54140699f5165
F test/cse.test 00b3aea44b16828833c94fbe92475fd6977583fcb064ae0bc590986812b38d0c
F test/csv01.test 2ab5514005fd308995c8910bc313e47f0368b94213b9d6c27f9a2da78796a091
F test/csv01.test 96bc1634961682363a7b4ad5c0e38450e6e9743b38ac626422e1b56cbdc06cd8
F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c4773
F test/cursorhint.test 05cf0febe5c5f8a31f199401fd1c9322249e753950d55f26f9d5aca61408a270
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
@@ -1050,7 +1049,7 @@ F test/dbpage.test 2e3a50548edea551ef974b8f121f975852de9c5b16cb3284ac4bf2c9f2ed5
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test a36518c0f0951d8fd5a3dc36f99948ad1af93fb7fc0d2e03e5bb5a643186cf52
F test/decimal.test a11b87a2c3294eb4c11b55f3168aeac63d683fa8ada35921a6ec1d511eff7648
F test/decimal.test 9e1c40ff2835775a3dae88e1e2f0d81438070e987aafa4d9aeb0a22d60e5bf44
F test/default.test c7124864cded213a3f118bc7e2e26f34b7c36dfa26cf6945cc8b7f5db1191277
F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
@@ -1075,7 +1074,7 @@ F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
F test/e_expr.test 9bdb347b78b9f4eff9153ea97797facc179a821898588471a70808b4471a69b0
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
F test/e_fkey.test 2a4ad815372a4b57dad91cd37932e18e68bf545f6c946e9a4cb3e7bde92b8e84
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
F test/e_reindex.test 027bb13d2c7e9e865886eed6349f126a273f8037899b636bf5fb53c7fc815921
@@ -1171,8 +1170,8 @@ F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c788
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
F test/fts3corrupt4.test c7f414fe29b97a478d15c90382c4ae077a2bbd2283bf8c63bf66dadaaed3edb8
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
F test/fts3corrupt6.test f417c910254f32c0bc9ead7affa991a1d5aec35b3b32a183ffb05eea78289525
F test/fts3corrupt7.test 1da31776e24bb91d3c028e663456b61280b121a74496ccf2fef3fe33790ad2b0
F test/fts3corrupt6.test 9ea944e3cd17a36c64451059022fabff53bd338a43356d1f49264ce8aa9477ad
F test/fts3corrupt7.test 8564d278801a7947d1c74d8819adee7dfed18b81574d0c42f8a1acc6759fc65a
F test/fts3cov.test 1e5ecea0e4c1394cea97adcfb9fd3d2d5998fd563dacf465f413e6c7fa5cffb3
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
@@ -1253,7 +1252,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 5048a2426bd6968a1b9a00cef7f3aa37442a261df3b532c9e44a1f829bddbede
F test/fuzzcheck.c 674d246742da18270abeef9e8510e3cd9e0e14cddca1f1e8131428928e996a6f
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1274,9 +1273,9 @@ F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test 2d89bf9480646feb8093be3a58ea502d6521906779ed960de31dd9c4502c0541
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
F test/icu.test 8da7d52cd9722c82f33b0466ed915460cb03c23a38f18a9a2d3ff97da9a4a8c0
F test/icu.test 3903d97f414741036e48d74af6be904eb69170f5bca7a0031ff3b33925c85582
F test/ieee754.test 0d3ab84ab2069c9994c833a7cd820ee6037f0cf888e206a4a7fc05f735d5790a
F test/import01.sql 11a5f8325b8b04c66fe489d30558d462411432adf750cef1c0f7b06564691a8c
F test/import01.sql d9561059f4ad3f14eff20c269e64b09afd697b1aad00b03a7d5010e167dcba83
F test/imposter1.sql fc5ad0945bb19622688c7a1cd7dfd1cefa4b013bac9e2628c22b03c7309f021f
F test/imposter1.test 5a20b2cdeb53e65fc57cdb10a33750bd4ef6259909eaf1972253b9e79f7a3fb2
F test/in.test edf979bff3244b9e47849e2b43886631354c8213791f42da92216f08012141af
@@ -1308,7 +1307,7 @@ F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a91
F test/index9.test 2ac891806a4136ef3e91280477e23114e67575207dc331e6797fa0ed9379f997
F test/indexA.test 11d84f6995e6e5b9d8315953fb1b6d29772ee7c7803ee9112715e7e4dd3e4974
F test/indexedby.test 444fb04ce0b21a3daf79f84e6735b49e5a5b3396623b37df5431eb09c8b8f557
F test/indexexpr1.test 830fec7ce07102f8e065f9486fa51d733f7443173f66c084d36232fa1628e635
F test/indexexpr1.test e1e6a851d1054fa4fa43b60ad51f350519fabe756e313bc687af430a1efbff6e
F test/indexexpr2.test 1c382e81ef996d8ae8b834a74f2a9013dddf59214c32201d7c8a656d739f999a
F test/indexexpr3.test 47b91bc7999805c9a34d356f672259bc49295ecc797448511cae554a309b47cd
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
@@ -1363,7 +1362,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
@@ -1475,7 +1474,8 @@ 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 642c27ae0792d5fc92969815eb8c4a17636cdcc164cb5b20f3d2b55a1a5d169d
F test/nulls2.test 20356ab1de69f78363faed9c2cd8eb455bb92f805572c405131f1c5d8f2d37fb
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
F test/offset1.test c21e67d2d5ae8ed310243fbe84fc2f0dca49e9ffed3ea89110c0d5914c0de620
@@ -1510,10 +1510,10 @@ F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/parser1.test 131f4733472252d53d8ed681115257866f55740ab697fa05900d766049348f27
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/pcache2.test 8a801d2b8e4b0ebb99701f026a67a9e84634c8aa24799a842c44003b93250da1
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
F test/percentile.test eaee1ff3e35d5fe933ac98d927c9a7d2f4f1a1a19ee22e7d45e97a6d9ee32077
F test/permutations.test e6de4f5777f7785737ac3d1d964b8656e5477a134665b2fe8a91884ab9b685b3
F test/percentile.test fd78896fa882fa4fbf693640097859721f3629926c2ccf804af5bcb7001fd35b
F test/permutations.test 99c5e11130387da85c216a839412b882a779596f3f2e0ecb7e0703c564182cdb
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 7d07b7bb76e273215d6a20c4f83c3062cc28976c737ccb70a686025801e86c8f
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@ -1522,7 +1522,7 @@ F test/pragma4.test 396ef9bff1fb966d41721545ad4b12bfc26aae315f5fe51d9b917828d49e
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
F test/prefixes.test f2c4f30d5d439ca203ec69d72f5e1cc408916104e5310423542faef8003cf013
F test/prefixes.test fe52bb0c2fee10fb9b918a095d443ebf31dd48e5e2c7a1b21feba594fe7ff2d0
F test/printf.test 854ddc19b31e83de41142a6b0c8dbb812fcdbbb127cdcafc0c5efef58b790eee
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
@@ -1629,13 +1629,13 @@ F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell-prompt.sql 8a320a78812d75349bd5e1a95178f7ff1f2194bb4cceee572865d127c51684b3
F test/shell1.test c84eff209f93ad17ccdf7e1634969fc8231684254edeb21d9b13d67c3179cdb5
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
F test/shell1.test 72893bc7957ff6402552ce4e31aa98a94478fa91bf5c4009a458711ad2e6efac
F test/shell2.test e0842ea6a28f86f1ef235e117b3a381d16b999e7bdd9655b1de663026dd8ea27
F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
F test/shell5.test a0c43d82a811a463a5d07d6418c5a045ab01a072544db8aa31ae394e93845d8d
F test/shell6.test 596f2eb385a1097d4e9130b4d4f663a24cba294b35f13b774b8f13553dec307d
F test/shell7.test 4468c1abb7e2708a3aa3f84c8918ca31fbf7909b1c19063853f2abb0a072dfab
F test/shell7.test 6b006d296b569a7ec78b8168af77578b3bde8f58b79c32d9f46cff1eaf763a29
F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192
F test/shell9.test c0e8871061a92151450b3332279a893b516fa73a6c46d4f51a0998407cbf8c89
F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480
@@ -1709,7 +1709,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 7827c2dfd57a094125b059f51a2200eaf04d417af6b1e720c34a8cbf54e8a14f
F test/tabfunc01.test 23d1f92fbbbaaef4cb3a1ee15fd5b44e70bde1f3ee1a6b9df9ce43b05cf0b630
F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1894,7 +1894,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 342b398e4c68deee65a940c5af22a95f44c3090b6539c7a19175afb48ac3fb93
F test/transitive1.test d6252d06ddc104d13372fce0da93af501546bf5d75cb4d2a1f83b8c27238997a
F test/trigger1.test 141bd2bbfa82fa91aed7391f50517373c9823ff8f55af35e56313dbc75112ca1
F test/trigger2.test 30fcb3a6aa6782020d47968735ee6086ed795f73a7affa9406c8d5a36e7b5265
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
@@ -1906,7 +1906,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 1724b595661da3dd3c8d79f0ebae818132a39e65c241bad2049f66952b1dc29d
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51
F test/triggerC.test 1faacf5249a7abe8bdc44aafe170f2141a72cb2abcef300dc91e3d55c4158f41
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
F test/triggerE.test 612969cb57a4ef792059ad6d01af0117e1ae862c283753ffcc9a6428642b22ee
F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad
@@ -1944,7 +1944,7 @@ F test/upsert1.test 77e3cbabd6b5c773056aca39bda7a690901f1dbd08b0a26ee3b5aec9e9e2
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
F test/upsert5.test 9953b180d02d1369cdbb6c73c900834e5fef8cb78e98e07511c8762ec21cc176
F test/upsert5.test 8d0230b358965e0c11f7306b87ba1238970e44b8339e34609f44d0468c4ed458
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
F test/uri.test 1250724af9beeed2d6c3716f5b990c483200c54f408d3c0ec9543a3c7961f8fc
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
@@ -1961,7 +1961,7 @@ F test/values.test 0e037c50789ac2a308746567d07b53b2f6026c1bb3a435d1b099424600e64
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test 3c23d7a068e9e4a0c4e6907498042772adea725f0630c3d9638ffd4e5a08b92b
F test/view.test 79cfd77b29ce49c172fee2ed9ec98d34924e70bebc75c8edb65f6a9bcd80d569
F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456
F test/vt02.c c2faf56d74470d569cd00741acb3f1719ee95d668f84ef58acc3872635789680
@@ -2036,7 +2036,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 b73f8ee8f94b850764c429efe2d48171090628737dcc3df64a9f2214da02089f
F test/where2.test 5d93a8aec78386539aa01cf72926eb39d90de4ce1bfb6d517f56ae9bf704ba8a
F test/where3.test 4ccb156ae33de86414a52775a6f590a9d60ba2cbc7a93a24fa331b7bcf5b6030
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
@@ -2110,7 +2110,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 756af25d30ffd25073b113865f1ebeb12f7edfa5dddd8c37bca70e4c3150ab62
F test/zipfile2.test 21afaffcf4f7769df38bf16e4a9c4dfa6ba1b0f5b695f844ec61fafb92db0db7
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
@@ -2125,7 +2125,7 @@ F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629c
F tool/cp.tcl 9a0d663ad45828de13763ee7ca0200f31f56c6d742cf104a56ae80e027c242d8
F tool/custom.txt 24ed55e71c5edae0067ba159bbf09240d58b160331f7716e95816cd3aa0ba5c4
F tool/dbhash.c 5da0c61032d23d74f2ab84ffc5740f0e8abec94f2c45c0b4306be7eb3ae96df0
F tool/dbtotxt.c cfeb957571735af345f253ba8417256031fa0dddf79468eefad184262d17211e
F tool/dbtotxt.c 88805565e06596f8b2f7143054f74d7aeaf022769b4c3d916f148a1fa17082ef
F tool/dbtotxt.md c9a57af8739957ef36d2cfad5c4b1443ff3688ed33e4901ee200c8b651f43f3c
F tool/emcc.sh.in 41a049468c8155433e37e656ba5bae063a000768b1d627025f277732c4e7c4a4
F tool/enlargedb.c 3e8b2612b985cfa7e3e8800031ee191b43ae80de96abb5abbd5eada62651ee21
@@ -2187,7 +2187,7 @@ F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdadd
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
F tool/sqldiff.c de59a4eecbc802db8ad053889c10e6f8b8427b6f349199ee79938c92c20860dd
F tool/sqldiff.c e581749af18f02a72cd18f56b465df1bef630544aebdf13993e2be55e4158f94
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
F tool/sqlite3_rsync.c d9ce999e5b3aa9f36de44b321755622e52258774889bd804ba56f00eca01af50
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
@@ -2208,8 +2208,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P 646e9b49153ebd7e09e3ef72cc4f64fb685d0cfd8b158ef7d11d37c50c3f0b7e
R 81bf729d8c4142161698f7ae0f57bcc2
U dan
Z a8503d1e8f8b2786c97fea82e248cce7
P 2fe53e6d68c3f9f1c4b064fa40fe8efe12025179a973182f0bb256acb9b5d58d
R 3de030f0b5267bf636ad519cf6229737
U drh
Z e6a5bf5d9c5bcab97848f385d89977e5
# Remove this line to create a well-formed Fossil manifest.
+2 -2
View File
@@ -1,2 +1,2 @@
branch trunk
tag trunk
branch sqlite3-result-str
tag sqlite3-result-str
+1 -1
View File
@@ -1 +1 @@
87c37dab7e53d1bd891f3fed624963b35ab15a785706d0964b5d07ab70421c10
7356bf3a813bcd9082a7fdef5e2cc38c7a0f142f0ef4c948f78e4dafa216c039
+6 -9
View File
@@ -2661,9 +2661,8 @@ static void addConstraintFunc(
int iCol = sqlite3_value_int(argv[2]);
int iOff = 0;
int ii;
char *zNew = 0;
sqlite3_str *pNew;
int t = 0;
sqlite3 *db;
UNUSED_PARAMETER(NotUsed);
if( skipCreateTable(ctx, zSql, &iOff) ) return;
@@ -2683,13 +2682,11 @@ static void addConstraintFunc(
iOff += getWhitespace(&zSql[iOff]);
db = sqlite3_context_db_handle(ctx);
if( iCol<0 ){
zNew = sqlite3MPrintf(db, "%.*s, %s%s", iOff, zSql, zCons, &zSql[iOff]);
}else{
zNew = sqlite3MPrintf(db, "%.*s %s%s", iOff, zSql, zCons, &zSql[iOff]);
}
sqlite3_result_text(ctx, zNew, -1, SQLITE_DYNAMIC);
pNew = sqlite3_str_new(sqlite3_context_db_handle(ctx));
sqlite3_str_append(pNew, zSql, iOff);
if( iCol<0 ) sqlite3_str_append(pNew, ",", 1);
sqlite3_str_appendf(pNew, " %s%s", zCons, &zSql[iOff]);
sqlite3_result_str(ctx, pNew, SQLITE_FINISH);
}
/*
+6 -6
View File
@@ -876,7 +876,7 @@ static void statGet(
assert( p->current.anEq[i] || p->nRow==0 );
#endif
}
sqlite3ResultStrAccum(context, &sStat);
sqlite3_result_str(context, &sStat, SQLITE_XFER);
}
#ifdef SQLITE_ENABLE_STAT4
else if( eCall==STAT_GET_ROWID ){
@@ -913,7 +913,7 @@ static void statGet(
sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]);
}
if( sStat.nChar ) sStat.nChar--;
sqlite3ResultStrAccum(context, &sStat);
sqlite3_result_str(context, &sStat, SQLITE_XFER);
}
#endif /* SQLITE_ENABLE_STAT4 */
#ifndef SQLITE_DEBUG
@@ -1814,9 +1814,9 @@ static int loadStatTbl(
}
pIdx->nSampleCol = nIdxCol;
pIdx->mxSample = nSample;
nByte = ROUND8(sizeof(IndexSample) * nSample);
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
nByte = ROUND8(sizeof64(IndexSample) * nSample);
nByte += sizeof64(tRowcnt) * nIdxCol * 3 * nSample;
nByte += nIdxCol * sizeof64(tRowcnt); /* Space for Index.aAvgEq[] */
pIdx->aSample = sqlite3DbMallocZero(db, nByte);
if( pIdx->aSample==0 ){
@@ -1824,7 +1824,7 @@ static int loadStatTbl(
return SQLITE_NOMEM_BKPT;
}
pPtr = (u8*)pIdx->aSample;
pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
pPtr += ROUND8(nSample*sizeof64(pIdx->aSample[0]));
pSpace = (tRowcnt*)pPtr;
assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
+5
View File
@@ -10984,6 +10984,11 @@ static int checkTreePage(
doCoverageCheck = 0;
continue;
}
if( info.nPayload && info.pPayload[0]<2 ){
checkAppendMsg(pCheck, "Bad cell header size");
doCoverageCheck = 0;
continue;
}
/* Check for integer primary key out of range */
if( pPage->intKey ){
+3 -2
View File
@@ -70,6 +70,7 @@ static SQLITE_NOINLINE void lockTable(
assert( pToplevel->nTableLock < 0x7fff0000 );
nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1);
if( pToplevel->nTableLock==0 ) pToplevel->aTableLock = 0;
pToplevel->aTableLock =
sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
if( pToplevel->aTableLock ){
@@ -236,7 +237,7 @@ void sqlite3FinishCoding(Parse *pParse){
/* Initialize any AUTOINCREMENT data structures required.
*/
if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse);
if( pParse->usesAinc ) sqlite3AutoincrementBegin(pParse);
/* Code constant expressions that were factored out of inner loops.
*/
@@ -269,7 +270,7 @@ void sqlite3FinishCoding(Parse *pParse){
if( pParse->nErr==0 ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
assert( pParse->pAinc==0 || pParse->nTab>0 );
assert( pParse->usesAinc==0 || pParse->nTab>0 );
sqlite3VdbeMakeReady(v, pParse);
pParse->rc = SQLITE_DONE;
}else{
+31 -31
View File
@@ -1416,38 +1416,38 @@ static void strftimeFunc(
size_t i,j;
sqlite3 *db;
const char *zFmt;
sqlite3_str sRes;
sqlite3_str *pRes;
if( argc==0 ) return;
zFmt = (const char*)sqlite3_value_text(argv[0]);
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
db = sqlite3_context_db_handle(context);
sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
pRes = sqlite3_str_new(db);
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
char cf;
if( zFmt[i]!='%' ) continue;
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
if( j<i ) sqlite3_str_append(pRes, zFmt+j, (int)(i-j));
i++;
j = i + 1;
cf = zFmt[i];
switch( cf ){
case 'd': /* Fall thru */
case 'e': {
sqlite3_str_appendf(&sRes, cf=='d' ? "%02d" : "%2d", x.D);
sqlite3_str_appendf(pRes, cf=='d' ? "%02d" : "%2d", x.D);
break;
}
case 'f': { /* Fractional seconds. (Non-standard) */
double s = x.s;
if( NEVER(s>59.999) ) s = 59.999;
sqlite3_str_appendf(&sRes, "%06.3f", s);
sqlite3_str_appendf(pRes, "%06.3f", s);
break;
}
case 'F': {
sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
sqlite3_str_appendf(pRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
break;
}
case 'G': /* Fall thru */
@@ -1459,15 +1459,15 @@ static void strftimeFunc(
y.validYMD = 0;
computeYMD(&y);
if( cf=='g' ){
sqlite3_str_appendf(&sRes, "%02d", y.Y%100);
sqlite3_str_appendf(pRes, "%02d", y.Y%100);
}else{
sqlite3_str_appendf(&sRes, "%04d", y.Y);
sqlite3_str_appendf(pRes, "%04d", y.Y);
}
break;
}
case 'H':
case 'k': {
sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h);
sqlite3_str_appendf(pRes, cf=='H' ? "%02d" : "%2d", x.h);
break;
}
case 'I': /* Fall thru */
@@ -1475,65 +1475,65 @@ static void strftimeFunc(
int h = x.h;
if( h>12 ) h -= 12;
if( h==0 ) h = 12;
sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h);
sqlite3_str_appendf(pRes, cf=='I' ? "%02d" : "%2d", h);
break;
}
case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */
sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1);
sqlite3_str_appendf(pRes,"%03d",daysAfterJan01(&x)+1);
break;
}
case 'J': { /* Julian day number. (Non-standard) */
sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
sqlite3_str_appendf(pRes,"%.16g",x.iJD/86400000.0);
break;
}
case 'm': {
sqlite3_str_appendf(&sRes,"%02d",x.M);
sqlite3_str_appendf(pRes,"%02d",x.M);
break;
}
case 'M': {
sqlite3_str_appendf(&sRes,"%02d",x.m);
sqlite3_str_appendf(pRes,"%02d",x.m);
break;
}
case 'p': /* Fall thru */
case 'P': {
if( x.h>=12 ){
sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2);
sqlite3_str_append(pRes, cf=='p' ? "PM" : "pm", 2);
}else{
sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2);
sqlite3_str_append(pRes, cf=='p' ? "AM" : "am", 2);
}
break;
}
case 'R': {
sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m);
sqlite3_str_appendf(pRes, "%02d:%02d", x.h, x.m);
break;
}
case 's': {
if( x.useSubsec ){
sqlite3_str_appendf(&sRes,"%.3f",
sqlite3_str_appendf(pRes,"%.3f",
(x.iJD - 21086676*(i64)10000000)/1000.0);
}else{
i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
sqlite3_str_appendf(&sRes,"%lld",iS);
sqlite3_str_appendf(pRes,"%lld",iS);
}
break;
}
case 'S': {
sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
sqlite3_str_appendf(pRes,"%02d",(int)x.s);
break;
}
case 'T': {
sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
sqlite3_str_appendf(pRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
break;
}
case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */
case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */
char c = (char)daysAfterSunday(&x) + '0';
if( c=='0' && cf=='u' ) c = '7';
sqlite3_str_appendchar(&sRes, 1, c);
sqlite3_str_appendchar(pRes, 1, c);
break;
}
case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */
sqlite3_str_appendf(&sRes,"%02d",
sqlite3_str_appendf(pRes,"%02d",
(daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7);
break;
}
@@ -1544,30 +1544,30 @@ static void strftimeFunc(
y.iJD += (3 - daysAfterMonday(&x))*86400000;
y.validYMD = 0;
computeYMD(&y);
sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1);
sqlite3_str_appendf(pRes,"%02d", daysAfterJan01(&y)/7+1);
break;
}
case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */
sqlite3_str_appendf(&sRes,"%02d",
sqlite3_str_appendf(pRes,"%02d",
(daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7);
break;
}
case 'Y': {
sqlite3_str_appendf(&sRes,"%04d",x.Y);
sqlite3_str_appendf(pRes,"%04d",x.Y);
break;
}
case '%': {
sqlite3_str_appendchar(&sRes, 1, '%');
sqlite3_str_appendchar(pRes, 1, '%');
break;
}
default: {
sqlite3_str_reset(&sRes);
sqlite3_str_free(pRes);
return;
}
}
}
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
sqlite3ResultStrAccum(context, &sRes);
if( j<i ) sqlite3_str_append(pRes, zFmt+j, (int)(i-j));
sqlite3_result_str(context, pRes, SQLITE_FINISH);
}
/*
@@ -1703,7 +1703,7 @@ static void timediffFunc(
sqlite3StrAccumInit(&sRes, 0, 0, 0, 100);
sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f",
sign, Y, M, d1.D-1, d1.h, d1.m, d1.s);
sqlite3ResultStrAccum(context, &sRes);
sqlite3_result_str(context, &sRes, SQLITE_XFER);
}
+16 -4
View File
@@ -4170,6 +4170,7 @@ static void sqlite3ExprCodeIN(
int rLhsOrig = rLhs;
rLhs = sqlite3GetTempRange(pParse, nVector);
for(i=0; i<nVector; i++){
testcase( aiMap[i]!=i );
sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0);
}
sqlite3ReleaseTempReg(pParse, rLhsOrig);
@@ -4190,7 +4191,8 @@ static void sqlite3ExprCodeIN(
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error;
if( sqlite3ExprCanBeNull(p) ){
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
testcase( aiMap[i]!=i );
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+aiMap[i], destStep2);
VdbeCoverage(v);
}
}
@@ -4264,9 +4266,19 @@ static void sqlite3ExprCodeIN(
CollSeq *pColl;
int r3 = sqlite3GetTempReg(pParse);
p = sqlite3VectorFieldSubexpr(pLeft, i);
pColl = sqlite3ExprCollSeq(pParse, p);
sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
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);
}
testcase( aiMap[i]!=i );
sqlite3VdbeAddOp3(v, OP_Column, iTab, aiMap[i], r3);
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+aiMap[i], destNotNull, r3,
(void*)pColl, P4_COLLSEQ);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r3);
+97 -74
View File
@@ -320,7 +320,6 @@ static void printfFunc(
PrintfArguments x;
StrAccum str;
const char *zFormat;
int n;
sqlite3 *db = sqlite3_context_db_handle(context);
if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
@@ -330,9 +329,7 @@ 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);
sqlite3_result_str(context, &str, SQLITE_XFER);
}
}
@@ -1279,12 +1276,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
UNUSED_PARAMETER(argc);
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
sqlite3QuoteValue(&str,argv[0],SQLITE_PTR_TO_INT(sqlite3_user_data(context)));
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
SQLITE_DYNAMIC);
if( str.accError!=SQLITE_OK ){
sqlite3_result_null(context);
sqlite3_result_error_code(context, str.accError);
}
sqlite3_result_str(context, &str, SQLITE_XFER);
}
/*
@@ -1504,7 +1496,7 @@ static void replaceFunc(
int nRep; /* Size of zRep */
i64 nOut; /* Maximum size of zOut */
int loopLimit; /* Last zStr[] that might match zPattern[] */
int i, j; /* Loop counters */
i64 i, j; /* Loop counters */
unsigned cntExpand; /* Number zOut expansions */
sqlite3 *db = sqlite3_context_db_handle(context);
@@ -2317,7 +2309,7 @@ static void groupConcatFinalize(sqlite3_context *context){
GroupConcatCtx *pGCC
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
if( pGCC ){
sqlite3ResultStrAccum(context, &pGCC->str);
sqlite3_result_str(context, &pGCC->str, SQLITE_XFER);
#ifndef SQLITE_OMIT_WINDOWFUNC
sqlite3_free(pGCC->pnSepLengths);
#endif
@@ -2327,18 +2319,8 @@ static void groupConcatFinalize(sqlite3_context *context){
static void groupConcatValue(sqlite3_context *context){
GroupConcatCtx *pGCC
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
if( pGCC ){
StrAccum *pAccum = &pGCC->str;
if( pAccum->accError==SQLITE_TOOBIG ){
sqlite3_result_error_toobig(context);
}else if( pAccum->accError==SQLITE_NOMEM ){
sqlite3_result_error_nomem(context);
}else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
sqlite3_result_text(context, "", 1, SQLITE_STATIC);
}else{
const char *zText = sqlite3_str_value(pAccum);
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
}
if( pGCC && pGCC->nAccum>0 ){
sqlite3_result_str(context, &pGCC->str, SQLITE_COPY);
}
}
#else
@@ -2958,53 +2940,91 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
** (1) To avoid a dependency on qsort()
** (2) To avoid the function call to the comparison routine for each
** comparison.
**
** If parameter iReq is non-negative, then the caller will only access
** elements a[iReq] and a[iReq+1] (if it exists) of the sorted array and
** so it is not necessary to position any other elements. Or if iReq is
** negative, then the final array must be fully sorted.
*/
static void percentSort(double *a, unsigned int n){
static void percentSort(
double *a, /* Array to sort */
unsigned int n, /* Number of elements in array a[] */
int iReq /* Element caller cares about (or -ve) */
){
int iLt; /* Entries before a[iLt] are less than rPivot */
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
}
assert( n>=2 );
do{
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 );
assert( a[iLt]==rPivot );
assert( iGt>iLt );
if( iReq>=0 ){
/* In this case, the only elements that the caller requires sorted into
** the correct positions are elements a[iReq] and a[iReq+1]. At this
** point we know that element a[iLt] is in the correct position and
** all elements smaller than a[iLt] are in the left-hand partition.
** So if (iReq<iLt), then it is only necessary to sort the left
** partition.
**
** If (iReq>=iLt), then elements iReq and iReq+1 are either in the
** right partition or the equal partition (elements for which
** iLt<=iElem<iGt). Therefore it is always sufficient to sort only
** the right partition in this case. */
if( iReq<iLt ){
n = iLt;
}else{
a += iGt;
n -= iGt;
iReq = MAX(0, iReq-iGt);
}
}else{
/* Recurse on the smaller partition only. The smaller partition
** will hold n/2 or fewer entries, which assures that the stack
** depth will not exceed O(log(n)), even for pathological cases.
** Loop without recursion for the larger partition. */
if( iLt>(int)(n/2) ){
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt, -1);
n = iLt;
}else{
if( iLt>=2 ) percentSort(a, iLt, -1);
a += iGt;
n -= iGt;
}
}
}while( n>=2 );
}
/*
** The "inverse" function for percentile(Y,P) is called to remove a
@@ -3038,7 +3058,7 @@ static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
}
if( p->bSorted==0 ){
assert( p->nUsed>1 );
percentSort(p->a, p->nUsed);
percentSort(p->a, p->nUsed, -1);
p->bSorted = 1;
}
p->bKeepSorted = 1;
@@ -3067,13 +3087,17 @@ static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
if( p==0 ) return;
if( p->a==0 ) return;
if( p->nUsed ){
if( p->bSorted==0 ){
assert( p->nUsed>1 );
percentSort(p->a, p->nUsed);
p->bSorted = 1;
}
ix = p->rPct*(p->nUsed-1);
i1 = (unsigned)ix;
if( p->bSorted==0 ){
/* In cases where bIsFinal is non-zero, setting Percentile.bSorted
** after the percentSort() call here is not technically correct, as
** the array is not fully sorted. But in this case the object will be
** freed below anyway, so it doesn't matter. */
assert( p->nUsed>1 );
percentSort(p->a, p->nUsed, (bIsFinal ? (int)i1 : -1));
p->bSorted = 1;
}
if( settings & 1 ){
vx = p->a[i1];
}else{
@@ -3141,8 +3165,7 @@ static void filestatFunc(
if( rc ) sqlite3_str_append(pStr, "null", 4);
}
sqlite3_str_append(pStr, "}", 1);
sqlite3_result_text(context, sqlite3_str_finish(pStr), -1,
sqlite3_free);
sqlite3_result_str(context, pStr, SQLITE_FINISH);
}
sqlite3BtreeLeave(pBtree);
}else{
@@ -3258,8 +3281,8 @@ static void parseuriFunc(
}
}
}
sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free);
}
sqlite3_result_str(ctx, pResult, SQLITE_FINISH);
sqlite3_free_filename(zFile);
sqlite3_free(zErr);
}
+10
View File
@@ -308,6 +308,16 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
*/
FuncDefHash sqlite3BuiltinFunctions;
/*
** This singleton is an sqlite3_str object that is returned if
** sqlite3_malloc() fails to provide space for a real one. This
** sqlite3_str object accepts no new text and always returns
** an SQLITE_NOMEM error.
*/
const sqlite3_str sqlite3OomStr = {
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
};
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
/*
** Counter used for coverage testing. Does not come into play for
+1 -1
View File
@@ -28,7 +28,7 @@
}
#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && \
(defined(i386) || defined(__i386__) || defined(_M_IX86))
(defined(i586) || defined(__i586__) || defined(_M_IX86))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned int lo, hi;
+7 -1
View File
@@ -433,6 +433,9 @@ static int autoIncBegin(
return 0;
}
if( pToplevel->usesAinc==0 ){
pToplevel->pAinc = 0;
}
pInfo = pToplevel->pAinc;
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
if( pInfo==0 ){
@@ -442,6 +445,7 @@ static int autoIncBegin(
if( pParse->db->mallocFailed ) return 0;
pInfo->pNext = pToplevel->pAinc;
pToplevel->pAinc = pInfo;
pToplevel->usesAinc = 1;
pInfo->pTab = pTab;
pInfo->iDb = iDb;
pToplevel->nMem++; /* Register to hold name of table */
@@ -470,6 +474,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){
assert( sqlite3IsToplevel(pParse) );
assert( v ); /* We failed long ago if this is not so */
assert( pParse->usesAinc );
for(p = pParse->pAinc; p; p = p->pNext){
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList autoInc[] = {
@@ -537,6 +542,7 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
sqlite3 *db = pParse->db;
assert( v );
assert( pParse->usesAinc );
for(p = pParse->pAinc; p; p = p->pNext){
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList autoIncEnd[] = {
@@ -569,7 +575,7 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
}
}
void sqlite3AutoincrementEnd(Parse *pParse){
if( pParse->pAinc ) autoIncrementEnd(pParse);
if( pParse->usesAinc ) autoIncrementEnd(pParse);
}
#else
/*
+1 -1
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: {
+3 -1
View File
@@ -533,7 +533,9 @@ static const sqlite3_api_routines sqlite3Apis = {
0,
0,
#endif
sqlite3_incomplete
/* Version 3.54.0 and later */
sqlite3_incomplete,
sqlite3_result_str
};
/* True if x is the directory separator character
+1 -1
View File
@@ -518,7 +518,7 @@ int sqlite3_config(int op, ...){
break;
}
case SQLITE_CONFIG_SMALL_MALLOC: {
sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int);
sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int)!=0;
break;
}
case SQLITE_CONFIG_PAGECACHE: {
+1 -1
View File
@@ -300,7 +300,7 @@ int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
}else{
double r;
rc = pVfs->xCurrentTime(pVfs, &r);
*pTimeOut = (sqlite3_int64)(r*86400000.0);
*pTimeOut = sqlite3RealToI64(r*86400000.0);
}
return rc;
}
+31 -1
View File
@@ -13,6 +13,22 @@
** This file contains an experimental VFS layer that operates on a
** Key/Value storage engine where both keys and values must be pure
** text.
**
** DEBUG AND TEST
**
** For testing on Unix, compile using:
**
** make clean sqlite3d CFLAGS='-DSQLITE_OS_KV_OPTIONAL'
**
** Then start up a shell using something like:
**
** ./sqlite3d 'file:dbname?vfs=kvvfs'
**
** Each K/V entry is stored in a separate file in the working
** directory that has a name like "kvvfs-dbname-*". Due to limitations
** on the key size, the name of the database must be very short - just
** a few characters. If the database name is too long, the VFS will
** malfunction and you will get SQLITE_CORRUPT errors.
*/
#include <sqliteInt.h>
#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))
@@ -465,12 +481,14 @@ int kvvfsDecode(const char *a, char *aOut, int nOut){
memset(&aOut[j], 0, n);
j += n;
if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
}else{
}else if( j<nOut ){
aOut[j] = c<<4;
c = kvvfsHexValue[aIn[++i]];
if( c<0 ) return -1 /* hex bytes are always in pairs */;
aOut[j++] += c;
i++;
}else{
return -1;
}
}
return j;
@@ -896,6 +914,18 @@ static int kvvfsOpen(
pFile->base.pMethods = &kvvfs_db_io_methods;
}
if( !pFile->zClass ){
#ifdef SQLITE_WASM
if( strlen(zName) >= (KVRECORD_KEY_SZ
- 6 /* "kvvfs-" */
- 11 /* "-##########" */) ){
return SQLITE_CANTOPEN;
}
#else
if( 0!=strcmp(zName, "local") && 0!=strcmp(zName, "session") ){
/* Historical naming restriction which journaling depends on. */
return SQLITE_CANTOPEN;
}
#endif
pFile->zClass = zName;
}
pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ);
+20 -2
View File
@@ -3257,11 +3257,29 @@ int sqlite3_win_test_unc_locking = 0;
/*
** Return true if the string passed as the only argument is likely
** to be a UNC path. In other words, if it starts with "\\".
** to be a UNC path. Return false if note.
**
** Return true if:
**
** (1) The name begins with "\\"
** (2) But does not begin with "\\?\C:\" where C can be any alphabetic
** character.
**
** For testing, also return true in all cases if the global variable
** sqlite3_win_test_unc_locking is true.
*/
static int winIsUNCPath(const char *zFile){
if( zFile[0]=='\\' && zFile[1]=='\\' ){
return 1;
if( zFile[2]=='?'
&& zFile[3]=='\\'
&& sqlite3Isalpha(zFile[4])
&& zFile[5]==':'
&& winIsDirSep(zFile[6])
){
return sqlite3_win_test_unc_locking;
}else{
return 1;
}
}
return sqlite3_win_test_unc_locking;
}
+68 -74
View File
@@ -1272,39 +1272,43 @@ static void checkPage(PgHdr *pPg){
#endif /* SQLITE_CHECK_PAGES */
/*
** When this is called the journal file for pager pPager must be open.
** This function attempts to read a super-journal file name from the
** end of the file and, if successful, copies it into memory supplied
** by the caller. See comments above writeSuperJournal() for the format
** used to store a super-journal file name at the end of a journal file.
**
** zSuper must point to a buffer of at least nSuper bytes allocated by
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
** enough space to write the super-journal name). If the super-journal
** name in the journal is longer than nSuper bytes (including a
** nul-terminator), then this is handled as if no super-journal name
** were present in the journal.
**
** If a super-journal file name is present at the end of the journal
** file, then it is copied into the buffer pointed to by zSuper. A
** nul-terminator byte is appended to the buffer following the
** super-journal file name.
**
** If it is determined that no super-journal file name is present
** zSuper[0] is set to 0 and SQLITE_OK returned.
**
** If an error occurs while reading from the journal file, an SQLite
** error code is returned.
** Free a buffer allocated by the readSuperJournal() function.
*/
static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
static void freeSuperJournal(char *zSuper){
if( zSuper ){
sqlite3_free(&zSuper[-4]);
}
}
/*
** Parameter pJrnl is a file-handle open on a journal file. This function
** attempts to read a super-journal file name from the end of the journal
** file. If successful, it sets output parameter (*pzSuper) to point to a
** buffer containing the super-journal name as a nul-terminated string.
** The caller is responsible for freeing the buffer using freeSuperJournal().
**
** Refer to comments above writeSuperJournal() for the format used to store
** a super-journal file name at the end of a journal file.
**
** Parameter nSuper is passed the maximum allowable size of the super journal
** name in bytes. If the super-journal name in the journal is longer than
** nSuper bytes (including a nul-terminator), then this is handled as if no
** super-journal name were present in the journal.
**
** If there is no super-journal name at the end of pJrnl, (*pzSuper) is
** set to 0 and SQLITE_OK is returned. Or, if an error occurs while reading
** the super-journal name, an SQLite error code is returned and (*pzSuper)
** is set to 0.
*/
static int readSuperJournal(sqlite3_file *pJrnl, u64 nSuper, char **pzSuper){
int rc; /* Return code */
u32 len; /* Length in bytes of super-journal name */
i64 szJ; /* Total size in bytes of journal file pJrnl */
u32 cksum; /* MJ checksum value read from journal */
u32 u; /* Unsigned loop counter */
unsigned char aMagic[8]; /* A buffer to hold the magic header */
zSuper[0] = '\0';
char *zOut = 0;
*pzSuper = 0;
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
@@ -1314,27 +1318,34 @@ static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|| memcmp(aMagic, aJournalMagic, 8)
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
){
return rc;
}
/* See if the checksum matches the super-journal name */
for(u=0; u<len; u++){
cksum -= zSuper[u];
zOut = (char*)sqlite3MallocZero(4 + len + 2);
if( !zOut ){
rc = SQLITE_NOMEM_BKPT;
}else{
zOut = &zOut[4];
if( SQLITE_OK==(rc = sqlite3OsRead(pJrnl, zOut, len, szJ-16-len)) ){
u32 u; /* Unsigned loop counter */
/* See if the checksum matches the super-journal name */
for(u=0; u<len; u++){
cksum -= zOut[u];
}
}
if( rc!=SQLITE_OK || cksum ){
/* If the checksum doesn't add up, then one or more of the disk sectors
** containing the super-journal filename is corrupted. This means
** definitely roll back, so just return SQLITE_OK and report a (nul)
** super-journal filename. */
freeSuperJournal(zOut);
zOut = 0;
}
}
if( cksum ){
/* If the checksum doesn't add up, then one or more of the disk sectors
** containing the super-journal filename is corrupted. This means
** definitely roll back, so just return SQLITE_OK and report a (nul)
** super-journal filename.
*/
len = 0;
}
zSuper[len] = '\0';
zSuper[len+1] = '\0';
return SQLITE_OK;
*pzSuper = zOut;
return rc;
}
/*
@@ -2539,9 +2550,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
char *zSuperJournal = 0; /* Contents of super-journal file */
i64 nSuperJournal; /* Size of super-journal file */
char *zJournal; /* Pointer to one journal within MJ file */
char *zSuperPtr; /* Space to hold super-journal filename */
char *zFree = 0; /* Free this buffer */
i64 nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
/* Allocate space for both the pJournal and pSuper file descriptors.
** If successful, open the super-journal file for reading.
@@ -2564,9 +2573,8 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
*/
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
nSuperPtr = 1 + (i64)pVfs->mxPathname;
assert( nSuperJournal>=0 && nSuperPtr>0 );
zFree = sqlite3Malloc(4 + nSuperJournal + 2 + nSuperPtr + 2);
assert( nSuperJournal>=0 );
zFree = sqlite3Malloc(4 + nSuperJournal + 2);
if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
@@ -2575,7 +2583,6 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
}
zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
zSuperJournal = &zFree[4];
zSuperPtr = &zSuperJournal[nSuperJournal+2];
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
if( rc!=SQLITE_OK ) goto delsuper_out;
zSuperJournal[nSuperJournal] = 0;
@@ -2589,6 +2596,8 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
goto delsuper_out;
}
if( exists ){
char *zSuperPtr = 0;
/* One of the journals pointed to by the super-journal exists.
** Open it and check if it points at the super-journal. If
** so, return without deleting the super-journal file.
@@ -2603,13 +2612,15 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
goto delsuper_out;
}
rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
rc = readSuperJournal(pJournal, 1+(u64)pVfs->mxPathname, &zSuperPtr);
sqlite3OsClose(pJournal);
if( rc!=SQLITE_OK ){
assert( zSuperPtr==0 );
goto delsuper_out;
}
c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
c = zSuperPtr!=0 && strcmp(zSuperPtr, zSuper)==0;
freeSuperJournal(zSuperPtr);
if( c ){
/* We have a match. Do not delete the super-journal file. */
goto delsuper_out;
@@ -2824,19 +2835,11 @@ static int pager_playback(Pager *pPager, int isHot){
** If a super-journal file name is specified, but the file is not
** present on disk, then the journal is not hot and does not need to be
** played back.
**
** 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+8) >= pPager->pVfs->mxPathname+1). Using os_unix.c,
** mxPathname is 512, which is the same as the minimum allowable value
** 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] ){
*/
rc = readSuperJournal(pPager->jfd, 1+(i64)pPager->pVfs->mxPathname, &zSuper);
if( rc==SQLITE_OK && zSuper ){
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
}
zSuper = 0;
if( rc!=SQLITE_OK || !res ){
goto end_playback;
}
@@ -2965,30 +2968,20 @@ end_playback:
*/
pPager->changeCountDone = pPager->tempFile;
if( rc==SQLITE_OK ){
/* Leave 4 bytes of space before the super-journal filename in memory.
** This is because it may end up being passed to sqlite3OsOpen(), in
** which case it requires 4 0x00 bytes in memory immediately before
** the filename. */
zSuper = &pPager->pTmpSpace[4];
rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
rc = sqlite3PagerSync(pPager, 0);
}
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
rc = pager_end_transaction(pPager, zSuper!=0, 0);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK && zSuper[0] && res ){
if( rc==SQLITE_OK && zSuper && res ){
/* If there was a super-journal and this routine will return success,
** see if it is possible to delete the super-journal.
*/
assert( zSuper==&pPager->pTmpSpace[4] );
memset(pPager->pTmpSpace, 0, 4);
assert( memcmp(&zSuper[-4], "\0\0\0\0", 4)==0 );
rc = pager_delsuper(pPager, zSuper);
testcase( rc!=SQLITE_OK );
}
@@ -3001,6 +2994,7 @@ end_playback:
** back a journal created by a process with a different sector size
** value. Reset it to the correct value for this process.
*/
freeSuperJournal(zSuper);
setSectorSize(pPager);
return rc;
}
+18 -16
View File
@@ -309,22 +309,24 @@ static int pcache1InitBulk(PCache1 *pCache){
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
szBulk = pCache->szAlloc*(i64)pCache->nMax;
}
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
sqlite3EndBenignMalloc();
if( zBulk ){
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
do{
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
pX->page.pBuf = zBulk;
pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
pCache->pFree = pX;
zBulk += pCache->szAlloc;
}while( --nBulk );
if( szBulk>=pCache->szAlloc ){
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
sqlite3EndBenignMalloc();
if( zBulk ){
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
do{
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
pX->page.pBuf = zBulk;
pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
pCache->pFree = pX;
zBulk += pCache->szAlloc;
}while( --nBulk );
}
}
return pCache->pFree!=0;
}
+1 -1
View File
@@ -581,7 +581,7 @@ void sqlite3ParseObjectReset(Parse *pParse){
assert( db->pParse==pParse );
assert( pParse->nested==0 );
#ifndef SQLITE_OMIT_SHARED_CACHE
if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
if( pParse->nTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
#endif
while( pParse->pCleanup ){
ParseCleanup *pCleanup = pParse->pCleanup;
+7 -31
View File
@@ -991,8 +991,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++;
@@ -1322,37 +1322,11 @@ char *sqlite3StrAccumFinish(StrAccum *p){
return p->zText;
}
/*
** Use the content of the StrAccum passed as the second argument
** as the result of an SQL function.
*/
void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){
if( p->accError ){
sqlite3_result_error_code(pCtx, p->accError);
sqlite3_str_reset(p);
}else if( isMalloced(p) ){
sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
}else{
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
sqlite3_str_reset(p);
}
}
/*
** This singleton is an sqlite3_str object that is returned if
** sqlite3_malloc() fails to provide space for a real one. This
** sqlite3_str object accepts no new text and always returns
** an SQLITE_NOMEM error.
*/
static sqlite3_str sqlite3OomStr = {
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
};
/* Finalize a string created using sqlite3_str_new().
*/
char *sqlite3_str_finish(sqlite3_str *p){
char *z;
if( p!=0 && p!=&sqlite3OomStr ){
if( p!=0 && p!=(sqlite3_str*)&sqlite3OomStr ){
z = sqlite3StrAccumFinish(p);
sqlite3_free(p);
}else{
@@ -1393,6 +1367,8 @@ void sqlite3_str_reset(StrAccum *p){
if( isMalloced(p) ){
sqlite3DbFree(p->db, p->zText);
p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
}else if( p==(sqlite3_str*)&sqlite3OomStr ){
return;
}
p->nAlloc = 0;
p->nChar = 0;
@@ -1404,7 +1380,7 @@ void sqlite3_str_reset(StrAccum *p){
** of its content, all in one call.
*/
void sqlite3_str_free(sqlite3_str *p){
if( p!=0 && p!=&sqlite3OomStr ){
if( p!=0 && p!=(sqlite3_str*)&sqlite3OomStr ){
sqlite3_str_reset(p);
sqlite3_free(p);
}
@@ -1441,7 +1417,7 @@ sqlite3_str *sqlite3_str_new(sqlite3 *db){
sqlite3StrAccumInit(p, 0, 0, 0,
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
}else{
p = &sqlite3OomStr;
p = (sqlite3_str*)&sqlite3OomStr;
}
return p;
}
+13 -4
View File
@@ -754,7 +754,7 @@ static int lookupName(
** cnt>1 means there were two or more matches.
**
** cnt==0 is always an error. cnt>1 is often an error, but might
** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING.
** be multiple matches for a NATURAL OUTER JOIN or a OUTER JOIN USING.
*/
assert( pFJMatch==0 || cnt>0 );
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
@@ -837,9 +837,18 @@ lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
if( db->xAuth && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) ){
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
}
if( db->xAuth ){
if( pFJMatch ){
assert( pExpr->op==TK_FUNCTION );
assert( sqlite3_stricmp(pExpr->u.zToken,"coalesce")==0 );
assert( pExpr->x.pList==pFJMatch );
assert( pFJMatch->nExpr>0 );
pExpr = pFJMatch->a[0].pExpr;
}
if( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ){
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
}
}
#endif
/* Increment the nRef value on all name contexts from TopNC up to
** the point where the name matched. */
+13 -1
View File
@@ -2441,6 +2441,13 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
sqlite3 *db = pParse->db;
u64 savedFlags;
pParse->nNestSel++;
#if SQLITE_MAX_EXPR_DEPTH>0
if( pParse->nNestSel >= db->aLimit[SQLITE_LIMIT_EXPR_DEPTH] ){
sqlite3ErrorMsg(pParse, "VIEWs and/or subqueries nested too deep");
return 0;
}
#endif
savedFlags = db->flags;
db->flags &= ~(u64)SQLITE_FullColNames;
db->flags |= SQLITE_ShortColNames;
@@ -2462,6 +2469,8 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
sqlite3DeleteTable(db, pTab);
return 0;
}
pParse->nNestSel--;
assert( pParse->nNestSel>=0 );
return pTab;
}
@@ -7432,8 +7441,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",
+123 -64
View File
@@ -301,7 +301,7 @@ INCLUDE ../ext/intck/sqlite3intck.h
INCLUDE ../ext/intck/sqlite3intck.c
INCLUDE ../ext/misc/stmtrand.c
INCLUDE ../ext/misc/vfstrace.c
INCLUDE ../ext/misc/analyze.c
INCLUDE ../ext/misc/diskused.c
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
@@ -934,7 +934,7 @@ static char *local_getline(char *zLine, FILE *in){
** or if the NO_COLOR environment variable exists
*/
static int shellNoColor(void){
#ifdef SQLITE_NO_COLOR
#if defined(SQLITE_NO_COLOR) || defined(SQLITE_SHELL_FIDDLE)
return 1;
#else
return getenv("NO_COLOR")!=0;
@@ -2104,6 +2104,43 @@ static void modeSetStr(char **az, const char *zNew){
}
}
/* Forward reference */
static int pickStr(const char *zArg, char **pzErr, ...);
/*
** Change the limits on the display mode. Return 0 on
** success. Return non-zero if zArg is mis-formatted.
**
** Valid arguments:
**
** "on" Default limits
** "off" All limits turned off
** L,C Line and Characters limits set
** L,C,T Line, Character, and Title limits set
**
** Anything else returns non-zero
*/
static int modeSetLimit(ShellState *p, const char *zArg){
int k = zArg==0 ? 1 : pickStr(zArg,0,"on","off","");
if( k==0 ){
p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
}else if( k==1 ){
p->mode.spec.nLineLimit = 0;
p->mode.spec.nCharLimit = 0;
p->mode.spec.nTitleLimit = 0;
}else{
int L, C, T = 0;
int nNum = sscanf(zArg, "%d,%d,%d", &L, &C, &T);
if( nNum<2 || L<0 || C<0 || T<0) return 1;
p->mode.spec.nLineLimit = L;
p->mode.spec.nCharLimit = C;
if( nNum==3 ) p->mode.spec.nTitleLimit = T;
}
return 0;
}
/*
** Change the mode to eMode
*/
@@ -2140,6 +2177,7 @@ static void modeChange(ShellState *p, unsigned char eMode){
u8 mFlags = p->mode.mFlags;
modeFree(&p->mode);
modeChange(p, MODE_List);
modeSetLimit(p, "off");
p->mode.mFlags = mFlags;
}else if( eMode==MODE_TTY ){
u8 mFlags = p->mode.mFlags;
@@ -4228,8 +4266,8 @@ static const char *(azHelp[]) = {
#if SQLITE_SHELL_HAVE_RECOVER
".dbinfo ?DB? Show status information about the database",
#endif
".dbstat ?SCHEMA? Report database space and size stats",
".dbtotxt Hex dump of the database file",
".diskused ?SCHEMA? Report database space and size stats",
".dump ?OBJECTS? Render database content as SQL",
" Options:",
" --data-only Output only INSERT statements",
@@ -5058,7 +5096,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_regexp_init(p->db, 0, 0);
sqlite3_ieee_init(p->db, 0, 0);
sqlite3_series_init(p->db, 0, 0);
sqlite3_analyze_init(p->db, 0, 0);
sqlite3_diskused_init(p->db, 0, 0);
#ifndef SQLITE_SHELL_FIDDLE
sqlite3_fileio_init(p->db, 0, 0);
sqlite3_completion_init(p->db, 0, 0);
@@ -6864,7 +6902,7 @@ struct ArCommand {
u8 eCmd; /* An AR_CMD_* value */
u8 bVerbose; /* True if --verbose */
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bDryRun; /* 1 for --dry-run, 2 for --debug */
u8 bAppend; /* True if --append */
u8 bGlob; /* True if --glob */
u8 fromCmdLine; /* Run from -A instead of .archive */
@@ -6926,6 +6964,7 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
#define AR_SWITCH_APPEND 11
#define AR_SWITCH_DRYRUN 12
#define AR_SWITCH_GLOB 13
#define AR_SWITCH_DEBUG 14
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
switch( eSwitch ){
@@ -6943,7 +6982,10 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
break;
case AR_SWITCH_DRYRUN:
pAr->bDryRun = 1;
if( pAr->bDryRun<2 ) pAr->bDryRun = 1;
break;
case AR_SWITCH_DEBUG:
pAr->bDryRun = 2;
break;
case AR_SWITCH_GLOB:
pAr->bGlob = 1;
@@ -6994,6 +7036,7 @@ static int arParseCommand(
{ "append", 'a', AR_SWITCH_APPEND, 1 },
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
{ "debug", 0, AR_SWITCH_DEBUG, 0 },
{ "glob", 'g', AR_SWITCH_GLOB, 0 },
};
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
@@ -7294,14 +7337,37 @@ static int arRemoveCommand(ArCommand *pAr){
** Implementation of .ar "eXtract" command.
*/
static int arExtractCommand(ArCommand *pAr){
/* The zSql1[] string is a template for the query that does the
** extraction. Notes:
**
** * $dir is the directory into which the archive is to be extracted
** * $pass is the integer pass number: 0, 1, or 2
** * The dest CTE is created so that realpath($dir) only needs
** to be called once.
*/
const char *zSql1 =
"WITH dest(dpath,dlen) AS (SELECT realpath($dir),length(realpath($dir)))\n"
"SELECT ($dir || name),\n"
" CASE WHEN $dryrun THEN 0\n"
" ELSE writefile($dir||name, %s, mode, mtime) END\n"
"WITH dest(dpath,dlen) AS (\n"
#ifdef _WIN32
" SELECT realpath($dir) || '\\',\n"
#else
" SELECT realpath($dir) || '/',\n"
#endif
" 1+length(realpath($dir))\n"
")\n"
"SELECT\n"
" ($dir || name),\n"
" CASE $dryrun\n" /* vv--- azExtraArg */
" WHEN 0 THEN writefile($dir||name, %s, mode, mtime)\n"
" WHEN 1 THEN 0\n"
" ELSE shell_putsnl(format('writefile(%%Q,%%s,%%0o,%%d)',"
"$dir||name,quote(%s),mode,mtime)) IS NULL\n"
" END\n" /* ^^--- azExtraArg */
" FROM dest CROSS JOIN %s\n"
" WHERE (%s)\n"
" AND (data IS NULL OR $pass==0)\n" /* Dirs both passes */
" WHERE (%s)\n" /* ^^-- pAr->zSrcTable */
/* ^^--- zWhere */
" AND (CASE $pass WHEN 0 THEN (mode&0xf000)<>0xa000\n"
" WHEN 1 THEN (mode&0xf000)=0xa000\n"
" ELSE data IS NULL END)\n"
" AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */
" AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */
@@ -7332,7 +7398,10 @@ static int arExtractCommand(ArCommand *pAr){
}
shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
azExtraArg[pAr->bZip],
azExtraArg[pAr->bZip],
pAr->zSrcTable,
zWhere
);
if( rc==SQLITE_OK ){
@@ -7342,25 +7411,31 @@ static int arExtractCommand(ArCommand *pAr){
sqlite3_bind_int(pSql, j, pAr->bDryRun);
/* Run the SELECT statement twice
** (0) writefile() all files and directories
** (1) writefile() for directory again
** The second pass is so that the timestamps for extracted directories
** (0) writefile() files and directories
** (1) writefile() symlinks
** (2) writefile() for directory again
** The third pass is so that the timestamps for extracted directories
** will be reset to the value in the archive, since populating them
** in the first pass will have changed the timestamp. */
for(i=0; i<2; i++){
for(i=0; i<3; i++){
if( pAr->bDryRun>=2 ){
cli_printf(pAr->out, "*** BEGIN PASS %d ***\n", i+1);
}
j = sqlite3_bind_parameter_index(pSql, "$pass");
sqlite3_bind_int(pSql, j, i);
if( pAr->bDryRun ){
if( pAr->bDryRun && i==0 ){
cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql));
if( pAr->bVerbose==0 ) break;
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
if( i==0 && pAr->bVerbose ){
cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
}
}
if( pAr->bDryRun ) break;
if( pAr->bDryRun==1 ) break;
shellReset(&rc, pSql);
if( pAr->bDryRun>=2 ){
cli_printf(pAr->out, "*** END PASS %d ***\n", i+1);
}
}
shellFinalize(&rc, pSql);
}
@@ -7875,7 +7950,7 @@ SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \
SELECT\
'('||x'0a'\
|| group_concat(\
cname||' ANY',\
cname,\
','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
||')' AS ColsSpec \
FROM (\
@@ -8720,26 +8795,10 @@ static int dotCmdMode(ShellState *p){
dotCmdError(p, i-1, "missing argument", 0);
return 1;
}
k = pickStr(azArg[i],0,"on","off","");
if( k==0 ){
p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
}else if( k==1 ){
p->mode.spec.nLineLimit = 0;
p->mode.spec.nCharLimit = 0;
p->mode.spec.nTitleLimit = 0;
}else{
int L, C, T = 0;
int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T);
if( nNum<2 || L<0 || C<0 || T<0){
dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C"
" and T are unsigned integers");
return 1;
}
p->mode.spec.nLineLimit = L;
p->mode.spec.nCharLimit = C;
if( nNum==3 ) p->mode.spec.nTitleLimit = T;
if( modeSetLimit(p, azArg[i]) ){
dotCmdError(p, i, "bad argument", "Should be \"on\" or \"off\" or "
"\"L,C,T\" where L, C, and T are unsigned integers");
return 1;
}
chng = 1;
}else if( optionMatch(z,"list") ){
@@ -9957,7 +10016,12 @@ static int do_meta_command(const char *zLine, ShellState *p){
}else
#endif /* SQLITE_SHELL_HAVE_RECOVER */
if( c=='d' && n==6 && cli_strncmp(azArg[0], "dbstat", n)==0 ){
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
open_db(p, 0);
rc = shell_dbtotxt_command(p, nArg, azArg);
}else
if( c=='d' && n==8 && cli_strncmp(azArg[0], "diskused", n)==0 ){
const char *zSchema = 0;
int ii;
char *zSql;
@@ -9976,23 +10040,15 @@ static int do_meta_command(const char *zLine, ShellState *p){
}
zSchema = z;
}
zSql = sqlite3_mprintf("SELECT analyze(%Q)", zSchema);
zSql = sqlite3_mprintf("SELECT diskused(%Q)", zSchema);
shell_check_oom(zSql);
modePush(p);
modeChange(p, MODE_BATCH);
p->mode.spec.nLineLimit = 0;
p->mode.spec.nCharLimit = 0;
p->mode.spec.nTitleLimit = 0;
shell_exec(p, zSql, 0);
modePop(p);
sqlite3_free(zSql);
}else
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
open_db(p, 0);
rc = shell_dbtotxt_command(p, nArg, azArg);
}else
if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
char *zLike = 0;
char *zSql;
@@ -13352,13 +13408,13 @@ static const char zOptions[] =
" -A ARGS... run \".archive ARGS\" and exit\n"
#endif
" -append append the database to the end of the file\n"
" -ascii set output mode to 'ascii'\n"
" -ascii set '.mode ascii'\n"
" -bail stop after hitting an error\n"
" -batch force batch I/O\n"
" -box set output mode to 'box'\n"
" -box set '.mode box'\n"
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
" -column set output mode to 'column'\n"
" -csv set output mode to 'csv'\n"
" -column set '.mode column'\n"
" -csv set '.mode csv -limits off'\n"
#if !defined(SQLITE_OMIT_DESERIALIZE)
" -deserialize open the database using sqlite3_deserialize()\n"
#endif
@@ -13370,14 +13426,14 @@ static const char zOptions[] =
" -heap SIZE Size of heap for memsys3 or memsys5\n"
#endif
" -help show this message\n"
" -html set output mode to HTML\n"
" -html set '.mode html'\n"
" -ifexists only open if database already exists\n"
" -interactive force interactive I/O\n"
" -json set output mode to 'json'\n"
" -line set output mode to 'line'\n"
" -list set output mode to 'list'\n"
" -json set '.mode json'\n"
" -line set '.mode line'\n"
" -list set '.mode list'\n"
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
" -markdown set output mode to 'markdown'\n"
" -markdown set '.mode markdown'\n"
#if !defined(SQLITE_OMIT_DESERIALIZE)
" -maxsize N maximum size for a --deserialize database\n"
#endif
@@ -13394,7 +13450,7 @@ static const char zOptions[] =
" -nullvalue TEXT set text string for NULL values. Default ''\n"
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
" -pcachetrace trace all page cache operations\n"
" -quote set output mode to 'quote'\n"
" -quote set '.mode quote'\n"
" -readonly open the database read-only\n"
" -safe enable safe-mode\n"
" -screenwidth N use N as the default screenwidth \n"
@@ -13403,8 +13459,8 @@ static const char zOptions[] =
" -sorterref SIZE sorter references threshold size\n"
#endif
" -stats print memory stats before each finalize\n"
" -table set output mode to 'table'\n"
" -tabs set output mode to 'tabs'\n"
" -table set '.mode table'\n"
" -tabs set '.mode tabs'\n"
" -unsafe-testing allow unsafe commands and modes for testing\n"
" -version show SQLite version\n"
" -vfs NAME use NAME as the default VFS\n"
@@ -13506,7 +13562,7 @@ static char *cmdline_option_value(int argc, char **argv, int i){
/*
** The callback from atexit().
*/
static void abnormalExit(void){
static void SQLITE_CDECL abnormalExit(void){
if( seenInterrupt ) eputz("Program interrupted.\n");
if( globalShellState ){
clearTempFile(globalShellState, 1, 1);
@@ -14006,6 +14062,7 @@ int SQLITE_CDECL main(int argc, char **argv){
modeChange(&data, MODE_Box);
}else if( cli_strcmp(z,"-csv")==0 ){
modeChange(&data, MODE_Csv);
modeSetLimit(&data, "off");
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
/* See similar code at tag-20250224-1 */
const char *zEsc = argv[++i];
@@ -14064,8 +14121,10 @@ int SQLITE_CDECL main(int argc, char **argv){
cmdline_option_value(argc,argv,++i));
}else if( cli_strcmp(z,"-header")==0 ){
data.mode.spec.bTitles = QRF_Yes;
data.mode.mFlags |= MFLG_HDR;
}else if( cli_strcmp(z,"-noheader")==0 ){
data.mode.spec.bTitles = QRF_No;
data.mode.mFlags |= MFLG_HDR;
}else if( cli_strcmp(z,"-echo")==0 ){
data.mode.mFlags |= MFLG_ECHO;
}else if( cli_strcmp(z,"-eqp")==0 ){
+61 -9
View File
@@ -3413,7 +3413,7 @@ void sqlite3_randomness(int N, void *P);
**
** ^The first parameter to the authorizer callback is a copy of the third
** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
** to the callback is an integer [SQLITE_COPY | action code] that specifies
** to the callback is an integer [SQLITE_READ | action code] that specifies
** the particular action to be authorized. ^The third through sixth parameters
** to the callback are either NULL pointers or zero-terminated strings
** that contain additional details about the action to be authorized.
@@ -3545,9 +3545,14 @@ int sqlite3_set_authorizer(
#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
#define SQLITE_FUNCTION 31 /* NULL Function Name */
#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */
#define SQLITE_COPY 0 /* No longer used */
#define SQLITE_RECURSIVE 33 /* NULL NULL */
/*
** Note: The SQLITE_COPY macro (with value 0) used to be one of the
** action codes above. That macro has now been repurposed as a possible
** value to the 3rd argument to sqlite3_result_str().
*/
/*
** CAPI3REF: Deprecated Tracing And Profiling Functions
** DEPRECATED
@@ -4377,7 +4382,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** or in an ORDER BY or GROUP BY clause.</dd>)^
**
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
** <dd>The maximum depth of the parse tree on any expression and
** the maximum nesting depth for subqueries and VIEWs</dd>)^
**
** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(<dt>SQLITE_LIMIT_PARSER_DEPTH</dt>
** <dd>The maximum depth of the LALR(1) parser stack used to analyze
@@ -4408,7 +4414,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
**
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
** <dd>The maximum depth of recursion for triggers.</dd>)^
** <dd>The maximum depth of recursion for triggers, and the maximum
** nesting depth for separate triggers.</dd>)^
**
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
** <dd>The maximum number of auxiliary worker threads that a single
@@ -5285,7 +5292,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** [prepared statement]. ^In the "v2" interface,
** the more specific error code is returned directly by sqlite3_step().
**
** [SQLITE_MISUSE] means that the this routine was called inappropriately.
** [SQLITE_MISUSE] means that this routine was called inappropriately.
** Perhaps it was called on a [prepared statement] that has
** already been [sqlite3_finalize | finalized] or on one that had
** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could
@@ -8796,8 +8803,8 @@ int sqlite3_keyword_check(const char*,int);
** <li> ^The sqlite3_str object is created using [sqlite3_str_new()].
** <li> ^Text is appended to the sqlite3_str object using various
** methods, such as [sqlite3_str_appendf()].
** <li> ^The sqlite3_str object is destroyed and the string it created
** is returned using the [sqlite3_str_finish()] interface.
** <li> The sqlite3_str object is destroyed and the string it created
** is returned using [sqlite3_str_finish()] or [sqlite3_result_str()].
** </ol>
*/
typedef struct sqlite3_str sqlite3_str;
@@ -8849,6 +8856,40 @@ sqlite3_str *sqlite3_str_new(sqlite3*);
char *sqlite3_str_finish(sqlite3_str*);
void sqlite3_str_free(sqlite3_str*);
/*
** CAPI3REF: Return A Dynamic String From an SQL Function
**
** The [sqlite3_result_str(C,S,F)] interface causes the
** [sqlite3_str|dynamic string] S to become the return value for the
** application-defined function or virtual table that uses
** [sqlite3_context] C. The F flag can be one of [SQLITE_COPY]
** or [SQLITE_XFER] or [SQLITE_FINISH].
**
** If the dynamic string is invalid or incomplete due to an out-of-memory
** or string-too-large error, then this routine transfers that error
** over to the SQL function.
**
** If the F argument is SQLITE_COPY, then a copy of the dynamic string
** content is made and the dynamic string object is unchanged.
** If the F argument is SQLITE_XFER, then ownership of the content
** in the dynamic is transferred to the SQL function (via a pointer copy
** rather than a string copy) and the dynamic string is reset to an
** empty string. The SQLITE_FINISH value for F works like SQLITE_RESET
** except that it also invokes the [sqlite3_str_free(S)] destructor
** on the dynamic string object.
*/
void sqlite3_result_str(sqlite3_context*, sqlite3_str*, int);
/*
** CAPI3REF: Control Flags For sqlite3_result_str()
**
** The following integers can be used as the third "F" argument
** to [sqlite3_result_str(C,S,F)].
*/
#define SQLITE_COPY 0 /* Results copied. Dynamic string unchanged */
#define SQLITE_XFER 1 /* Results transfered. Dynamic string reset */
#define SQLITE_FINISH 2 /* Like SQLITE_XFER, plus dynamic string freed */
/*
** CAPI3REF: Add Content To A Dynamic String
** METHOD: sqlite3_str
@@ -11214,8 +11255,19 @@ unsigned char *sqlite3_serialize(
** used. The serialized database P is N bytes in size. M is the size
** of the buffer P, which might be larger than N. If M is larger than
** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then
** SQLite is permitted to add content to the in-memory database as
** long as the total size does not exceed M bytes.
** SQLite is permitted to add content to the in-memory database, in
** page-sized chunks, as long as the total size does not exceed M bytes.
**
** The parameter M must be greater than or equal to N. Ideally, M
** should have a value which is N+(512&times;K)+20 where K determines how
** must extra space is available to hold new content as the database
** grows. K can be 0 if the database is read-only.
**
** If the database content in P is malformed in a malicious way then
** it is possible that SQLite might try to read a few more than N bytes
** from P. If the veracity of the database content P is uncertain,
** then applications are advised to allocate about 20 extra bytes on
** the end of the P buffer to avoid a memory error.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
+2
View File
@@ -378,6 +378,7 @@ struct sqlite3_api_routines {
int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
/* Version 3.54.0 and later */
sqlite3_int64 (*incomplete)(const char*);
void (*result_str)(sqlite3_context*,sqlite3_str*,int);
};
/*
@@ -723,6 +724,7 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
/* Version 3.54.0 and later */
#define sqlite3_incomplete sqlite3_api->incomplete
#define sqlite3_result_str sqlite3_api->result_str
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+17 -4
View File
@@ -767,6 +767,13 @@
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
/*
** sizeof64() is like sizeof(), but always returns a 64-bit value, even
** on 32-bit builds. This can help to avoid overflow by ensuring 64-bit
** arithmetic is used consistently in both 32-bit and 64-bit builds.
*/
#define sizeof64(X) ((sqlite3_int64)sizeof(X))
/*
** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
** to avoid complaints from -fsanitize=strict-bounds.
@@ -3904,14 +3911,15 @@ struct Parse {
bft bHasWith :1; /* True if statement contains WITH */
bft okConstFactor:1; /* OK to factor out constants */
bft checkSchema :1; /* Causes schema cookie check after an error */
bft usesAinc :1; /* True if pAinc is valid */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */
int nNestSel; /* Number of nested SELECT statements and/or VIEWs */
int nLabel; /* The *negative* of the number of labels used */
int nLabelAlloc; /* Number of slots in aLabel */
int *aLabel; /* Space to hold the labels */
@@ -3927,9 +3935,7 @@ struct Parse {
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
@@ -3958,6 +3964,13 @@ struct Parse {
Returning *pReturning; /* The RETURNING clause */
} d;
} u1;
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters. Only
** valid if Parse.usesAinc is true */
#ifndef SQLITE_OMIT_SHARED_CACHE
TableLock *aTableLock; /* Required table locks for shared-cache mode. Only
** valid if Parse.nTableLock>0 */
#endif
/************************************************************************
** Above is constant between recursions. Below is reset before and after
@@ -5491,6 +5504,7 @@ extern const unsigned char *sqlite3aGTb;
extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
extern const sqlite3_str sqlite3OomStr;
#ifndef SQLITE_OMIT_WSD
extern int sqlite3PendingByte;
#endif
@@ -5593,7 +5607,6 @@ int sqlite3StrAccumEnlarge(StrAccum*, i64);
int sqlite3StrAccumEnlargeIfNeeded(StrAccum*, i64);
char *sqlite3StrAccumFinish(StrAccum*);
void sqlite3StrAccumSetError(StrAccum*, u8);
void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*);
void sqlite3SelectDestInit(SelectDest*,int,int);
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
void sqlite3RecordErrorByteOffset(sqlite3*,const char*);
+15 -1
View File
@@ -1234,7 +1234,7 @@ static TriggerPrg *codeRowTrigger(
Table *pTab, /* The table pTrigger is attached to */
int orconf /* ON CONFLICT policy to code trigger program with */
){
Parse *pTop = sqlite3ParseToplevel(pParse);
Parse *pTop; /* Top level Parse object */
sqlite3 *db = pParse->db; /* Database handle */
TriggerPrg *pPrg; /* Value to return */
Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */
@@ -1243,10 +1243,24 @@ static TriggerPrg *codeRowTrigger(
SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
Parse sSubParse; /* Parse context for sub-vdbe */
int nDepth; /* Trigger depth */
/* Ensure that triggers are not chained too deep. This test is linear
** in the chaining depth, but sensible code ought not be chaining
** triggers excessively, so that shouldn't be a problem.
*/
pTop = pParse;
for(nDepth=0; pTop->pOuterParse; pTop = pTop->pOuterParse, nDepth++){}
if( nDepth>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
sqlite3ErrorMsg(pParse, "triggers nested too deep");
return 0;
}
pTop = sqlite3ParseToplevel(pParse);
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTop->pVdbe );
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
** are freed if an error occurs, link them into the Parse.pTriggerPrg
** list of the top-level Parse object sooner rather than later. */
+2 -1
View File
@@ -318,7 +318,8 @@ void sqlite3UpsertDoUpdate(
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
int iStorage = pTop->regData + sqlite3TableColumnToStorage(pTab, i);
sqlite3VdbeAddOp1(v, OP_RealAffinity, iStorage);
}
}
sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
+1 -1
View File
@@ -7560,7 +7560,7 @@ case OP_Program: { /* jump0 */
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
rc = SQLITE_ERROR;
sqlite3VdbeError(p, "too many levels of trigger recursion");
sqlite3VdbeError(p, "triggers nested too deep");
goto abort_due_to_error;
}
+74 -9
View File
@@ -374,15 +374,18 @@ void sqlite3_value_free(sqlite3_value *pOld){
/**************************** sqlite3_result_ *******************************
** The following routines are used by user-defined functions to specify
** the function result.
** The following routines are used by application-defined SQL functions to
** specify the function return value. There are many variations on
** sqlite3_result_xxxx() for different types of return values.
**
** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the
** result as a string or blob. Appropriate errors are set if the string/blob
** is too big or if an OOM occurs.
** The setStrOrError() function is a helper function that invokes
** sqlite3VdbeMemSetStr() to store the result as a string or blob.
** Appropriate errors are set if the string/blob is too big or if
** an OOM occurs.
**
** The invokeValueDestructor(P,X) routine invokes destructor function X()
** on value P if P is not going to be used and need to be destroyed.
** The invokeValueDestructor(P,X) helper function invokes the destructor
** function X() on value P if P is not going to be used and need to
** be destroyed.
*/
static void setResultStrOrError(
sqlite3_context *pCtx, /* Function context */
@@ -695,7 +698,7 @@ void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
}
}
/* Force an SQLITE_TOOBIG error. */
/* Cause the SQL function to raise an SQLITE_TOOBIG error. */
void sqlite3_result_error_toobig(sqlite3_context *pCtx){
#ifdef SQLITE_ENABLE_API_ARMOR
if( pCtx==0 ) return;
@@ -706,7 +709,7 @@ void sqlite3_result_error_toobig(sqlite3_context *pCtx){
SQLITE_UTF8, SQLITE_STATIC);
}
/* An SQLITE_NOMEM error. */
/* Cause the SQL function to raise an SQLITE_NOMEM error. */
void sqlite3_result_error_nomem(sqlite3_context *pCtx){
#ifdef SQLITE_ENABLE_API_ARMOR
if( pCtx==0 ) return;
@@ -717,6 +720,68 @@ void sqlite3_result_error_nomem(sqlite3_context *pCtx){
sqlite3OomFault(pCtx->pOut->db);
}
/* Make the return value of the SQL function or virtual table pCtx
** be the content of the sqlite3_str object pStr. The eOwn flag
** determines ownership of the sqlite3_str object and its content.
**
** eOwn Ownership transfer
** ------------- ------------------------------------------------
**
** SQLITE_COPY The SQL function returns a copy the sqlite3_str
** content and leaves the sqlite3_str object itself
** unchanged.
**
** SQLITE_XFER The content of the sqlite3_str is transferred to
** the SQL function and the SQL function takes
** responsibility for freeing that content when it is
** no longer needed. The sqlite3_str object is reset
** to an empty string.
**
** SQLITE_FINISH Like SQLITE_XFER except that the pStr is also
** freed using sqlite3_str_free().
*/
void sqlite3_result_str(sqlite3_context *pCtx, sqlite3_str *pStr, int eOwn){
#ifdef SQLITE_ENABLE_API_ARMOR
if( pCtx==0 ) return;
if( pStr==0 ) return;
#endif
if( pStr->accError==0 ){
if( pStr->nChar==0 ){
setResultStrOrError(pCtx, "", 0, SQLITE_UTF8_ZT, SQLITE_STATIC);
if( eOwn ) sqlite3_str_reset(pStr);
}else{
const char *zText = sqlite3_str_value(pStr);
/* Only internal code has the ability to capture a pointer to
** an sqlite3_str object that uses static buffer. And none of
** those internal use cases every invoke the sqlite3_result_str()
** interface on a static-buffer sqlite3_str. Should this change
** in the future, the following assert() will let us know. */
assert( isMalloced(pStr) );
if( eOwn==SQLITE_COPY ){
setResultStrOrError(pCtx, zText, pStr->nChar,
SQLITE_UTF8, SQLITE_TRANSIENT);
}else{
setResultStrOrError(pCtx, zText, pStr->nChar,
SQLITE_UTF8_ZT, SQLITE_DYNAMIC);
}
}
}else if( pStr->accError==SQLITE_NOMEM ){
sqlite3_result_error_nomem(pCtx);
}else{
assert( pStr->accError==SQLITE_TOOBIG );
sqlite3_result_error_toobig(pCtx);
}
if( eOwn ){
testcase( pStr==(sqlite3_str*)&sqlite3OomStr );
if( pStr->accError==0 ){
sqlite3StrAccumInit(pStr, pStr->db, 0, 0, pStr->mxAlloc);
}
if( eOwn==SQLITE_FINISH ){
sqlite3_str_free(pStr);
}
}
}
#ifndef SQLITE_UNTESTABLE
/* Force the INT64 value currently stored as the result to be
** a MEM_IntReal value. See the SQLITE_TESTCTRL_RESULT_INTREAL
+3 -5
View File
@@ -41,7 +41,6 @@ Vdbe *sqlite3VdbeCreate(Parse *pParse){
assert( pParse->aLabel==0 );
assert( pParse->nLabel==0 );
assert( p->nOpAlloc==0 );
assert( pParse->szOpAlloc==0 );
sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
return p;
}
@@ -191,8 +190,7 @@ static int growOpArray(Vdbe *v, int nOp){
assert( nNew>=(v->nOpAlloc+nOp) );
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
if( pNew ){
p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
v->nOpAlloc = p->szOpAlloc/sizeof(Op);
v->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
v->aOp = pNew;
}
return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT);
@@ -627,7 +625,7 @@ int sqlite3VdbeMakeLabel(Parse *pParse){
** a prior call to sqlite3VdbeMakeLabel().
*/
static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
int nNewSize = 10 - p->nLabel;
int nNewSize = 25 - p->nLabel;
p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
nNewSize*sizeof(p->aLabel[0]));
if( p->aLabel==0 ){
@@ -2695,7 +2693,7 @@ void sqlite3VdbeMakeReady(
n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
x.nFree = ROUNDDOWN8((p->nOpAlloc-p->nOp)*sizeof(Op)); /* Bytes unused mem */
assert( x.nFree>=0 );
assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
+2 -2
View File
@@ -114,8 +114,8 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659
** The problem appears to be fixed in GCC 15 */
i64 x;
assert( (MEM_Str&~p->flags)*4==sizeof(x) );
memcpy(&x, (char*)&p->u, (MEM_Str&~p->flags)*4);
assert( (sqlite3Config.bSmallMalloc!=0xee)*8==sizeof(x) );
memcpy(&x, (char*)&p->u.i, (sqlite3Config.bSmallMalloc!=0xee)*8);
p->n = sqlite3Int64ToText(x, zBuf);
#else
p->n = sqlite3Int64ToText(p->u.i, zBuf);
+7 -1
View File
@@ -1023,6 +1023,12 @@ static int walDecodeFrame(
return 0;
}
/* Need a valid page size
*/
if( !pWal->szPage ){
return 0;
}
/* A frame is only valid if a checksum of the WAL header,
** all prior frames, the first 16 bytes of this frame-header,
** and the frame-data matches the checksum in the last 8
@@ -2877,7 +2883,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
/* Allocate a buffer to read frames into */
assert( (pWal->szPage & (pWal->szPage-1))==0 );
assert( pWal->szPage>=512 && pWal->szPage<=65536 );
assert( (pWal->szPage>=512 && pWal->szPage<=65536) || pWal->szPage==0 );
szFrame = pWal->szPage + WAL_FRAME_HDRSIZE;
aFrame = (u8 *)sqlite3_malloc64(szFrame);
if( aFrame==0 ){
+1
View File
@@ -2717,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)
+45 -10
View File
@@ -515,7 +515,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
pWC->a[iChild].iParent = iParent;
pWC->a[iChild].truthProb = pWC->a[iParent].truthProb;
assert( pWC->a[iParent].nChild < UMXV(pWC->a[0].nChild) );
pWC->a[iParent].nChild++;
testcase( pWC->a[iParent].nChild == UMXV(pWC->a[0].nChild) );
}
/*
@@ -904,29 +907,56 @@ static void exprAnalyzeOrTerm(
}
}
/* At this point, okToChngToIN is true if original pTerm satisfies
** case 1. In that case, construct a new virtual term that is
** pTerm converted into an IN operator.
/* At this point, okToChngToIN is true if original pTerm is a
** candidate to satisfy case 1, though we are not yet certain that
** the collating sequences are all compatible. Try to construct a
** new virtual term that is pTerm converted from an OR operator
** into an IN operator.
**
** During construction, verify that the collating sequences on all
** subterms of the OR are compatible. Omit the construction of the
** new IN operator if there are any collating sequence mismatches.
*/
if( okToChngToIN ){
Expr *pDup; /* A transient duplicate expression */
ExprList *pList = 0; /* The RHS of the IN operator */
Expr *pLeft = 0; /* The LHS of the IN operator */
CollSeq *pCollSeq = 0; /* Collating sequence to use */
Expr *pNew; /* The complete IN operator */
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
Expr *pThis;
if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.x.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
pThis = pOrTerm->pExpr;
pDup = sqlite3ExprDup(db, pThis->pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
if( pLeft==0 ){
pLeft = pThis->pLeft;
pCollSeq = sqlite3ExprCompareCollSeq(pParse, pThis);
}else{
assert( 0==sqlite3ExprCompare(pParse, pThis->pLeft, pLeft, -1) );
if( pCollSeq!=sqlite3ExprCompareCollSeq(pParse, pThis) ){
pLeft = 0; /* Collating sequence mismatch */
break;
}
}
}
if( pLeft==0 ){
pNew = 0; /* Collating sequence mismatch */
}else{
pDup = sqlite3ExprDup(db, pLeft, 0);
if( sqlite3ExprCollSeq(pParse, pDup)!=pCollSeq
&& ALWAYS(pCollSeq!=0)
){
assert( pCollSeq->zName!=0 );
pDup = sqlite3ExprAddCollateString(pParse, pDup, pCollSeq->zName);
}
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
}
assert( pLeft!=0 );
pDup = sqlite3ExprDup(db, pLeft, 0);
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
@@ -954,7 +984,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
** 6. Both operands use the same collating sequence
** 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
@@ -964,7 +995,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
char aff1, aff2;
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
@@ -1291,6 +1322,7 @@ static void exprAnalyze(
pList = pExpr->x.pList;
assert( pList!=0 );
assert( pList->nExpr==2 );
assert( pWC->a[idxTerm].nChild==0 );
for(i=0; i<2; i++){
Expr *pNewExpr;
int idxNew;
@@ -1501,8 +1533,11 @@ static void exprAnalyze(
&& pExpr->x.pSelect->pWin==0
#endif
&& pWC->op==TK_AND
&& pExpr->x.pSelect->pEList->nExpr <= UMXV(pTerm->nChild)
/* ^-- See bug 2026-06-04T10:00:49Z */
){
int i;
assert( pTerm->nChild==0 );
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
int idxNew;
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE);
+1 -1
View File
@@ -222,7 +222,7 @@ static void nth_valueStepFunc(
break;
case SQLITE_FLOAT: {
double fVal = sqlite3_value_double(apArg[1]);
if( ((i64)fVal)!=fVal ) goto error_out;
if( sqlite3RealToI64(fVal)!=fVal ) goto error_out;
iVal = (i64)fVal;
break;
}
+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
+10
View File
@@ -275,5 +275,15 @@ for {set ii 0} {$ii < 20} {incr ii} {
} [list abcd $T]
}
# Bug 2026-06-14T15:22:47Z
#
reset_db
load_static_extension db csv
do_catchsql_test 8.1 {
CREATE VIRTUAL TABLE abc USING csv(
data='1,2,3,4,5,6',
columns=32768
);
} {1 {column= value too big, max 2000}}
finish_test
+30
View File
@@ -206,6 +206,36 @@ do_execsql_test 6130 {
SELECT printf('%.8e',ieee754_from_blob(x'ffefffffffffffff'));
} {-1.79769313e+308}
# Bug 2026-06-15T03:49:42Z
#
do_execsql_test 7000 {
SELECT decimal('999999999999999', 1);
} {1000000000000000}
# 999999999999999
do_execsql_test 7010 {
SELECT decimal('999999999999999', 2);
} {1000000000000000}
do_execsql_test 7020 {
SELECT decimal('999999999999999', 14);
} {1000000000000000}
do_execsql_test 7030 {
SELECT decimal('999999999999999', 15);
} {999999999999999}
do_execsql_test 7040 {
SELECT decimal('899999999999999', 1);
} {900000000000000}
do_execsql_test 7050 {
SELECT decimal('899999999999999', 14);
} {900000000000000}
do_execsql_test 7060 {
SELECT decimal('899999999999999', 15);
} {899999999999999}
do_execsql_test 7070 {
SELECT decimal('989999999999999', 14);
} {990000000000000}
do_execsql_test 7080 {
SELECT decimal('998999999999999', 14);
} {999000000000000}
+4 -4
View File
@@ -2982,14 +2982,14 @@ if {[clang_sanitize_address]==0} {
} {0 0}
do_test e_fkey-63.1.2 {
test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
} {1 {too many levels of trigger recursion}}
} {1 {triggers nested too deep}}
do_test e_fkey-63.1.3 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
test_on_delete_recursion 5
} {0 0}
do_test e_fkey-63.1.4 {
test_on_delete_recursion 6
} {1 {too many levels of trigger recursion}}
} {1 {triggers nested too deep}}
do_test e_fkey-63.1.5 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
} {5}
@@ -2998,14 +2998,14 @@ if {[clang_sanitize_address]==0} {
} {0 0}
do_test e_fkey-63.2.2 {
test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
} {1 {too many levels of trigger recursion}}
} {1 {triggers nested too deep}}
do_test e_fkey-63.2.3 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
test_on_update_recursion 5
} {0 0}
do_test e_fkey-63.2.4 {
test_on_update_recursion 6
} {1 {too many levels of trigger recursion}}
} {1 {triggers nested too deep}}
do_test e_fkey-63.2.5 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
} {5}
+38 -1
View File
@@ -64,7 +64,6 @@ do_execsql_test 2.1 {
#-------------------------------------------------------------------------
reset_db
breakpoint
do_catchsql_test 3.0 {
CREATE VIRTUAL TABLE main.Table0 USING fts3();
INSERT INTO Table0 VALUES (1), (printf('%8.1280000X') ), (1), (printf('%8.1280000X') ), (1) ;
@@ -75,5 +74,43 @@ do_catchsql_test 3.0 {
INSERT INTO Table0(Table0) VALUES('merge=6,8');
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE t USING fts4(c);
INSERT INTO t(t) VALUES('nodesize=200');
INSERT INTO t VALUES('alpha bravo charlie delta echo foxtrot golf hotel india juliet kilo lima mike november');
INSERT INTO t VALUES('oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu alpha bravo');
INSERT INTO t(t) VALUES('merge=16,4');
UPDATE t_segdir SET end_block = start_block + 2147483647 WHERE level=0;
INSERT OR REPLACE INTO t_segments(blockid,block)
SELECT start_block+2147483647, NULL FROM t_segdir WHERE level=0;
}
do_execsql_test 4.1 {
PRAGMA integrity_check
} {ok}
do_execsql_test 4.2 {
INSERT INTO t VALUES(
'mike november oscar papa quebec romeo
sierra tango uniform victor whiskey xray yankee'
);
INSERT INTO t VALUES(
'charlie delta echo foxtrot golf hotel india
juliet kilo lima mike november oscar papa'
);
INSERT INTO t(t) VALUES('merge=16,4');
SELECT blockid FROM t_segments ORDER BY blockid;
} {
2147483647 2147483648 2147483649 2147483775
}
do_execsql_test 4.3 {
PRAGMA integrity_check
} {ok}
set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
finish_test
+96
View File
@@ -277,4 +277,100 @@ 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}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 7.0 {
CREATE VIRTUAL TABLE t USING fts3(x);
INSERT INTO t_segdir(level,idx,start_block,leaves_end_block,end_block,root)
VALUES(1,0,0,0,'0 -9223372036854775808',x'00');
}
do_execsql_test 7.1 {
INSERT INTO t(x) VALUES('alpha');
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
CREATE VIRTUAL TABLE t USING fts4(x);
INSERT INTO t_content(docid,c0x) VALUES(1,'a b');
DELETE FROM t_segments;
DELETE FROM t_segdir;
INSERT INTO t_segdir(level,idx,start_block,leaves_end_block,end_block,root)
VALUES(0,0,0,0,0,x'000161110150028001500a818080800103038101000001622c010281008101ffffffffffffffffff010204ffffffffffffffffff01ffffffffffffffffff01c80109323200');
}
do_execsql_test 8.1 {
SELECT count(*) FROM t WHERE t MATCH 'a NEAR/100 b';
} {1}
finish_test
+2 -2
View File
@@ -172,11 +172,11 @@ static struct GlobalVars {
extern int sqlite3_vt02_init(sqlite3*,char**,void*);
extern int sqlite3_randomjson_init(sqlite3*,char**,void*);
extern int sqlite3_series_init(sqlite3*,char**,void*);
extern int sqlite3_analyze_init(sqlite3*,char**,void*);
extern int sqlite3_base64_init(sqlite3*,char**,void*);
extern int sqlite3_base85_init(sqlite3*,char**,void*);
extern int sqlite3_completion_init(sqlite3*,char**,void*);
extern int sqlite3_decimal_init(sqlite3*,char**,void*);
extern int sqlite3_diskused_init(sqlite3*,char**,void*);
extern int sqlite3_ieee_init(sqlite3*,char**,void*);
extern int sqlite3_regexp_init(sqlite3*,char**,void*);
extern int sqlite3_shathree_init(sqlite3*,char**,void*);
@@ -1394,11 +1394,11 @@ int runCombinedDbSqlInput(
/* Activate extensions */
sqlite3_randomjson_init(cx.db, 0, 0);
sqlite3_series_init(cx.db, 0, 0);
sqlite3_analyze_init(cx.db, 0, 0);
sqlite3_base64_init(cx.db, 0, 0);
sqlite3_base85_init(cx.db, 0, 0);
sqlite3_completion_init(cx.db, 0, 0);
sqlite3_decimal_init(cx.db, 0, 0);
sqlite3_diskused_init(cx.db, 0, 0);
sqlite3_ieee_init(cx.db, 0, 0);
sqlite3_regexp_init(cx.db, 0, 0);
sqlite3_shathree_init(cx.db, 0, 0);
+18 -1
View File
@@ -141,7 +141,7 @@ ifcapable icu {
do_catchsql_test icu-5.5 {SELECT 'abc' REGEXP } {1 {incomplete input}}
do_catchsql_test icu-5.6 {SELECT 'abc' REGEXP, 1} {1 {near ",": syntax error}}
do_malloc_test icu-6.10 -sqlbody {
do_malloc_test icu-5.10 -sqlbody {
SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04));
}
}
@@ -180,4 +180,21 @@ do_execsql_test icu-7.3 {
SELECT char(0x100)=='a', char(0x100)=='a' COLLATE dflt, char(0x100)=='a' COLLATE prim;
} {0 0 1}
#-------------------------------------------------------------------------
reset_db
do_execsql_test icu-8.1 {
CREATE TABLE t1(x TEXT);
INSERT INTO t1 VALUES('abcdefg');
INSERT INTO t1 VALUES('1234567');
}
do_execsql_test icu-8.2 {
SELECT * FROM t1 WHERE x LIKE CAST(x'C0A5' AS TEXT);
} {}
do_execsql_test icu-8.3 {
SELECT * FROM t1 WHERE x LIKE CAST(x'C19F' AS TEXT) || 'bcdefg';
} {}
finish_test
+7 -7
View File
@@ -119,12 +119,12 @@ END
.testcase 141
SELECT sql FROM sqlite_schema WHERE name='t1';
.check <<END
sql
CREATE TABLE "t1"(
"abc" ANY, "def" ANY, "xy z" ANY)
sql
CREATE TABLE "t1"(
"abc", "def", "xy z")
END
.testcase 150
@@ -138,7 +138,7 @@ SELECT * FROM t1;
.check <<END
Column separator ",", row separator "\n"
CREATE TABLE "main"."t1"(
"abc" ANY, "def" ANY, "xy z" ANY)
"abc", "def", "xy z")
Added 2 rows with 0 errors using 3 lines of input
+20
View File
@@ -686,4 +686,24 @@ do_execsql_test indexexpr1-2300 {
SELECT json_insert('{}', '$.a', json(y)) FROM t1;
} {{{"a":{"b":5}}}}
#-------------------------------------------------------------------------
reset_db
proc addone {n} {
return $n+1
}
db func addone addone
do_execsql_test indexexpr1-2400 {
CREATE TABLE t1(x, y);
}
do_catchsql_test indexexpr1-2310 {
CREATE INDEX i1 ON t1( (addone(x)) );
} {1 {non-deterministic functions prohibited in index expressions}}
do_catchsql_test indexexpr1-2310 {
CREATE INDEX i2 ON t1( ~(addone(x)) );
} {1 {non-deterministic functions prohibited in index expressions}}
do_catchsql_test indexexpr1-2310 {
CREATE INDEX i2 ON t1( ~(addone(DISTINCT x)) );
} {1 {non-deterministic functions prohibited in index expressions}}
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
@@ -336,7 +336,44 @@ 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 {} {} |}
#-------------------------------------------------------------------------
foreach {tn idx} {
1 {}
2 { CREATE INDEX i1 ON t1(a, b) }
3 { CREATE INDEX i1 ON t1(b, a) }
} {
reset_db
do_execsql_test 11.$tn.1 {
CREATE TABLE t1(a TEXT COLLATE NOCASE, b TEXT);
INSERT INTO t1 VALUES('Hello', 'world');
}
do_execsql_test 11.$tn.2 $idx
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.$tn.3.$tn $sql $res
}
}
+74
View File
@@ -0,0 +1,74 @@
# 2026 June 4
#
# 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.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix nulls2
foreach {tn idx} {
1 {}
2 { CREATE INDEX i1 ON t1(a, b, c) }
3 { CREATE INDEX i1 ON t1(b, c, a) }
4 { CREATE INDEX i1 ON t1(c, a, b) }
5 { CREATE INDEX i1 ON t1(c, b, a) }
} {
reset_db
do_execsql_test 1.$tn.0 {
CREATE TABLE t1(a, b, c);
INSERT INTO t1 VALUES(1, 1, NULL);
INSERT INTO t1 VALUES(2, 2, NULL);
CREATE TABLE t2(d NOT NULL, e NOT NULL, f);
INSERT INTO t2 VALUES(1, 1, NULL);
INSERT INTO t2 VALUES(2, 2, NULL);
}
execsql $idx
# This should return zero rows, as "f" is always NULL.
#
do_execsql_test 1.$tn.1 {
SELECT rowid FROM t2 WHERE (d, e, f) IN (
SELECT a, b, c FROM t1
)
}
}
foreach {tn idx} {
1 {}
2 { CREATE INDEX i1 ON t1(a, b, c) }
3 { CREATE INDEX i1 ON t1(b, c, a) }
4 { CREATE INDEX i1 ON t1(c, a, b) }
5 { CREATE INDEX i1 ON t1(c, b, a) }
} {
reset_db
do_execsql_test 2.$tn.0 {
CREATE TABLE t1(a, b, c COLLATE nocase);
INSERT INTO t1 VALUES('one', 'two', 'THREE');
INSERT INTO t1 VALUES('four', 'five', 'SIX');
}
execsql $idx
do_execsql_test 1.$tn.1 {
SELECT (NULL, 'two', 'three') IN (
SELECT a, b, c FROM t1
) IS NULL
} 1
}
finish_test
+19
View File
@@ -71,6 +71,25 @@ do_test pcache2-1.4 {
sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0
} {0 13 13}
# Check that a small (1KB) bulk cache allocation is handled.
#
do_test pcache2-2.1 {
catch {db2 close}
db close
sqlite3_reset_auto_extension
sqlite3_shutdown
sqlite3_config_pagecache 0 -1
sqlite3_config singlethread
sqlite3_initialize
autoinstall_test_functions
} {0}
reset_db
do_execsql_test pcache2-2.2 {
PRAGMA page_size = 4096;
CREATE TABLE t1(x);
}
db close
catch {db2 close}
sqlite3_reset_auto_extension
+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
+1
View File
@@ -142,6 +142,7 @@ set allquicktests [test_set $alltests -exclude {
writecrash.test view3.test
fts5dlidx.test fts5ac.test fts4merge3.test fts5prefix.test
fts5bigtok2.test
sessionB.test
}]
if {[info exists ::env(QUICKTEST_INCLUDE)]} {

Some files were not shown because too many files have changed in this diff Show More