Compare commits

...

99 Commits

Author SHA1 Message Date
dan b4d42c6702 When using the OR-optimization on a loop created by exists-to-join, do the early-exit logic for the whole loop, not for each individual OR branch. Possible fix for forum post [forum:c8b205720c | c8b205720c].
FossilOrigin-Name: 3d197dd03c47a0fb687064131dbf519b8c587a47f9c2bccfdb83d7eae8418336
2026-05-04 17:16:43 +00:00
stephan 3ed7926e2f Add a missing tcl quote which breaks the build on msys2.
FossilOrigin-Name: 9380be51c76392eca9544f1fd56373406d2ce001e77a8d476deb772968f2aacc
2026-05-04 16:18:25 +00:00
drh 8923a68c5f Add the --color and --no-color options to the ".prompt" command of the CLI.
FossilOrigin-Name: 1590b401ff0670b68910504c281e67ecae7ae357ba3ed65f96dabaabd7aaeb7f
2026-05-04 12:58:05 +00:00
drh c94c21d0a6 Honor the NO_COLOR environment variable. If NO_COLOR is set and
SQLITE_PS1 and SQLITE_PS2 are not set, then the default prompt is
monochrome and ANSI escapes are omitted.  Also change the name of
the SQLITE_PS_NOANSI compile-time option to SQLITE_NO_COLOR.

FossilOrigin-Name: 7e4134e3ff1ca8712f5fc78fadae665549450988dc43af27c7fe0c77f10ce3fb
2026-05-04 10:14:13 +00:00
drh fb7c642990 New test cases for the shell prompt
FossilOrigin-Name: 2340cbbd230bdadedbb5d3eb9cfd287fd934e69ce5a2c989e141b0fc87b947aa
2026-05-03 18:31:49 +00:00
drh 2bc658c387 Improvements to the non-printing character delimiter logic in the CLI
prompt, for improved accuracy and for improved testability.

FossilOrigin-Name: f5649795cd8d7a1f270037ef0b212ea605c1665ec05a75a6da0b250f2aeab070
2026-05-03 15:53:52 +00:00
drh f02745088c Change the non-printing character escapes for editline to U+0001 and
U+0002.  Also insert those escapes for readline.  Readline does not
need it (because it can figure them out on its own) but they are needed
when editline is being used in readline-compatibility mode, and we have
no way of distinguishing between editline and readline in that case, so
we might as well include them.

FossilOrigin-Name: b9545b0f0b6fa0a777a064e1410b17f52cb49d853c188f9b8b3a772bd810ece3
2026-05-02 23:40:40 +00:00
drh 596008f078 Attempt to automatically insert U+0001 escape bytes before and after
ANSI X3.64 escape sequences when using editline, to work around the
limitations of editline.

FossilOrigin-Name: 63050bee6e5ed46cead14bd5a02b0cb6a7dbcdcb6a56601b90c10cf1c8d84efc
2026-05-02 23:03:42 +00:00
drh 1c9e8ca88b Fix a harmless compiler warning on some MSVC versions.
FossilOrigin-Name: bb8f6deeff31e9cc9b5a88b17b29dc6cd4fb4515134fa8e9758e33e42bbe89b0
2026-05-02 20:19:31 +00:00
drh c70fbd39f9 Minor optimization to the authorizer.
FossilOrigin-Name: 625f78a630bbf897f945065f1b85a92fe26e426302c8f6edc4d26a817ff62358
2026-05-02 17:30:33 +00:00
drh 9db9f18985 Fix harmless compiler warnings.
FossilOrigin-Name: a0d0b5aff51088699e5ad0a726c350d10744b1779acd9ee54232659fb4c352a4
2026-05-02 15:58:28 +00:00
drh f107c52d4c Close database connections in a timely manner to fix test script problems
on Windows.

FossilOrigin-Name: 068a53865a17d4c2b4ce227fc08a2c019d1dbf31d833842ec08ab5665a3565a3
2026-05-02 11:47:22 +00:00
drh 7509c6351e Fix an SQLITE_MISUSE memory error in check-ini [1f940357f7bb160b].
FossilOrigin-Name: fc64113e8f9aee0161e682db7c244a7849f2db86551a557b276deb1785941476
2026-05-01 17:42:15 +00:00
drh 57e46429fe Harden the recovery extension against SQL injections coming from the
sqlite_schema table of the database being recovered.

FossilOrigin-Name: 9190f1b9b8889e4d80c370db36b916744d5779de0ec51da0369bbe74adb7b931
2026-05-01 16:06:21 +00:00
drh a9c2e08087 Check-in [1786fcd5b4ee6cd9] works great and generates correct code, but it
upset UBSAN.  This check-in fixes the UBSAN complaint.

FossilOrigin-Name: 7cd76847e8c9b683e39c1063a343288f11b4aa5e9302394fe0c4244d361ee4f1
2026-05-01 16:03:51 +00:00
drh 7f1f4c803d The value for /f and other filename substitutions in SQLITE_PS1 is now
"memory" if open on an in-memory database.

FossilOrigin-Name: 4aac1057eeaf6c29a4893e9c080497c780b0963e810c501532d79eba1b457f27
2026-04-30 18:23:58 +00:00
drh bd13573a96 Remove lots of code used to support legacy Windows version (WindowsXP and
before).  Use Slim Reader/Writer Locks on Windows for non-recursive mutexes,
since SRWLs are now available on all supported Windows platforms.

FossilOrigin-Name: 6f7a5ff22db10f889596239aae5f6a1130cbdfe72612ceee68cbeb3b86e40227
2026-04-30 16:52:56 +00:00
drh 0cadeecf6f Fix a harmless compiler warning in src/mutex_w32.c.
FossilOrigin-Name: 8de796ca459f2c996937fe1107838b217572636110c8c09e358343385bf17a1b
2026-04-30 15:41:01 +00:00
drh ad52288e0d Fix the memdb1.test test module so that it runs correctly on Windows.
FossilOrigin-Name: 9012f8ea7454bbb792b4361ed74d778e02b98ef44a443f9a23a27a4222fda747
2026-04-30 15:33:44 +00:00
drh d5f0e01593 Change the CLI warning that appears in the header about opening a
in-memory database, to be more readable.

FossilOrigin-Name: cc64cafdfe0b0965fabaf9d561d9a108c20a3643f71b36e6a6c51fc8f30b82cb
2026-04-30 15:19:09 +00:00
drh 3e663bd8c7 Add the /m escape to the CLI prompt string. Use it to show "memory"
in italic for the default prompt for in-memory databases.

FossilOrigin-Name: 1e3c95393044279997833145cb610b98926fb0c8f53ae4fb35e9fcc6c1ded1a2
2026-04-30 15:07:25 +00:00
dan 97901bbd69 Fix a crash that could occur if the destination database of a backup is
replaced using sqlite3_deserialize() between the call to sqlite3_backup_init()
and the first call to sqlite3_backup_step(). Forum post [forum:15d82885e2 | 15d82885e2].

FossilOrigin-Name: 1f940357f7bb160b583ac5b08ff4e32a9fef353255d032c5a18bcb04416c0f0b
2026-04-29 19:14:54 +00:00
drh c549e28c67 Reduce the number of system calls in the os_win.c thunk from 81 down
to 58, as well as other simplifications.

FossilOrigin-Name: c49521739c961ed5e38424bf26b2e34d8017a85122622ceac5af7398233fe343
2026-04-29 16:09:47 +00:00
drh 90dae0d01d Further simplifications to the interface to the Windows family of OSes.
An incremental check-in.

FossilOrigin-Name: f2aa6b66d2a1b5bb2dc8a44788a061a549a846244354df19b44398839578461e
2026-04-29 15:03:01 +00:00
drh 0a0a52ae93 Simplify the Windows interface by removing support for various WindowsXP
and WindowsCE.  This is a work-in-progress.  More to follow.

FossilOrigin-Name: 4dbc4d19c4f3b58d0bedd766cfba65d9624903a5ab0a340eb83ddeec058607ea
2026-04-29 14:02:23 +00:00
drh e1d4680fdd Updates and simplifications to the mutex implementation on Windows. Uses
Slim Reader/Writer Locks for performance, for non-reentrant mutexes.
Requires WindowsVista or later.

FossilOrigin-Name: a75aa5400f94531b8ffd00be4580b0578d8d81ba9681fd06b1d9d96a6180994c
2026-04-28 20:01:03 +00:00
drh 532e506d18 Attempt to align instances of the sqlite3_mutex object at 128-byte boundaries
to prevent false-sharing in multi-core machines. See the discussion at and
around [forum:/forumpost/2026-03-25T23:15:03Z|forum post 2026-03-25T23:15:03Z].

FossilOrigin-Name: 1786fcd5b4ee6cd9b4780f3687dfaec5b90ef0476e0da266a94e069b98e70514
2026-04-28 15:12:40 +00:00
drh c9bed48c3c Fix comment typo
FossilOrigin-Name: d64a1dbe0fb2d9286806d833a3146b21d5bf1636a650d5a64cf163c7f2356e98
2026-04-28 12:49:10 +00:00
drh 6b4eb6725f Improved detection of when the alternative windows-compatible main() is
needed in the sqldiff.exe utility.

FossilOrigin-Name: e25b849a603cb08ab888641ff324e9aa129391c4792de86a62c55e9caf84c16e
2026-04-27 14:01:23 +00:00
drh 6176034151 Relax arbitrary length restrictions on some error messages in the CLI.
FossilOrigin-Name: 52f5531ded8e0d3da3dc4d5c9b3d14573041b9446e2c45b5093c958b6c74e0de
2026-04-27 12:43:09 +00:00
stephan 7471b5d6c0 Increase a stack-local buffer size to resolve a test regression introduced in [ff084ae341eab5c], in which some tests fail a pattern match check if their absolute file names are too long. Resolves [forum:205f73db1b2806f5|forum post 205f73db1b2806f5].
FossilOrigin-Name: 286fc22c7ca882b0b09de2f1b2a7e0b382af6c498f2f8ad237fe064feaa70d7f
2026-04-27 12:05:56 +00:00
dan 1fc7341ad2 Fix a crash that could occur if sqlite3_deserialize() was used to overwrite a database with an open transaction on it. Bug introduced by [fc42d31d6fca21ab] on 2018-03-07 and first released in version 3.23.0. This is not a vulnerability as an attacker that can exploit this already has the ability to execute arbitrary code. Forum post [forum:39134ba029 | 39134ba029].
FossilOrigin-Name: 77662cce9aa452ba5820e5f1a864a802763bd83b937cdb16e7025219eff7bd08
2026-04-27 11:32:43 +00:00
stephan 6af10b0efd Refactor the uint128 type check to consolidate duplicated rules.
FossilOrigin-Name: 362ef7bc00eea180fb3458bd8887021aed54e321901483edc00ad6b23a33d8e5
2026-04-27 06:48:07 +00:00
stephan 70d1e3e75e Feature detection fix for uint128 on RISCV 32-bit, reported in [forum:f8d1417ce8eb2f22|forum post 2026-04-26T11:41:01Z] and validated by the OP.
FossilOrigin-Name: c4a2c20839ef75534d71d928a03ad276bdc488b0baa76c1505f48dc1ff0bcdd1
2026-04-27 05:55:38 +00:00
drh 74006fdcdb Improvements to temp-file cleanup on close in the CLI.
FossilOrigin-Name: 048c969c34eaaf8c203b996e999a7dbc94c47b4959719af9e6625052520f7135
2026-04-26 18:35:26 +00:00
drh 4b9f9d6794 In the CLI, eliminate the 2-second delay before getting the prompt back
after running a ".www" or ".excel".  Instead, remember the name of the
temporary file that is to be deleted and delete it later.

FossilOrigin-Name: 4e9ee211ca661fe8978b7f676f33ef962ff5c8177bc7c5ad42b19a2fa4482d90
2026-04-25 16:17:23 +00:00
drh 39b2fe7e5b Simplify the modePush()/modePop() implementation in the CLI.
FossilOrigin-Name: 92cad2cd7284d3a969b713336865007da2b0b2a8eef367d4185802174cbd027a
2026-04-25 15:05:46 +00:00
dan 01ec60bb87 Do not run expridx2.test as part of the "journaltest" permutation, as it requires wal mode.
FossilOrigin-Name: 11cfbae735669776c967522294b1606af90b4bd5379e2e1ed722520887b57757
2026-04-25 14:32:05 +00:00
dan e2dbd0a578 Fix a single-byte OOB read that could occur in the session module when concatenating patchsets.
FossilOrigin-Name: 60d7cd625a6160ba1bc60fd00fab2e91e0deff42034c6864107c19330b35ea7a
2026-04-25 14:00:29 +00:00
drh df7b22790e Minor code simplification in the CLI.
FossilOrigin-Name: 59795c71e5745e8a27dc596b9f1fc8f137df58a6ec8d8d0dab2b31cf8562796d
2026-04-25 10:45:17 +00:00
drh 50811f74e0 Fix a problem in the CLI in which the ".www" command followed by
".dbstat" does not restore the mode to its original setting afterwards.

FossilOrigin-Name: 4a5cac1d00e1fa287ab8ce3437c0152a9f362d72bdb9976889c93f6368b3fd66
2026-04-25 00:29:40 +00:00
drh d7bf8233ff Fix test cases due to recent CLI default prompt changes. Make sure ANSI
escape codes are recognized on Windows terminals.

FossilOrigin-Name: 22b791e404f0895b0f343b2ce0e169a7ada8578e46a39a9f4bd3a31f81c9853c
2026-04-24 20:27:42 +00:00
drh 455486bbc4 Improvements to the default prompt for the CLI.
FossilOrigin-Name: 9ab0bb487f78ba5a51cd3b4efcee23b11096e90ebf3add4da18aea657e8de0b6
2026-04-24 09:21:25 +00:00
drh ba9092e228 Improved default prompt in the CLI.
FossilOrigin-Name: 78193b60346dba304485241dd65f0eb6e971714397b76191b3bf7a5fdb44916b
2026-04-23 22:15:18 +00:00
drh 67d4e0226f Fix harmless compiler warnings. Enhance the CLI prompt mechanism to make
it more easily reusable by other projects, and to add the /h, /H, and /u
escape sequences.

FossilOrigin-Name: 354ce4f5e2a86b621b2058a6372495a5919cf3dc88ce1ed3637642f720c48002
2026-04-23 20:13:14 +00:00
drh 323b3fc121 Fix a bug in [dbc1d6f0a3452607] that disrupts the display when running
on a Windows console (not redirecting to a file).

FossilOrigin-Name: 75b5df2b0046827e985712b5725488b59667e2cfd171cde9f1194f2917165205
2026-04-23 20:06:16 +00:00
drh 78279e2550 Improvements to the #define mechanism in the CLI that allows other programs
that incorporate the shell.c source file to customize some of the
prompt expansions.

FossilOrigin-Name: e5f8840d11c1863cfc5c0b4a3d16c9ec9ab6ca6ecb7ff1a3a9a237715eed5d30
2026-04-23 16:40:34 +00:00
dan 4e4962f6b3 Have testrunner.tcl return a non-zero exit status if one or more tests have failed.
FossilOrigin-Name: 50ddc36d32540b6d98990b5c9a465beb5b68cc31ae3f0ed162f6fe07e7c74e2d
2026-04-23 15:54:00 +00:00
drh ed95a9d103 New CLI prompt escape sequences: /r, /A, /v, /V, and /D../D.
FossilOrigin-Name: e7c7acd1a4e5cb0f8e68f119352480c1aa9dd3c2b289c92f88e9e697a2e440e0
2026-04-23 15:05:46 +00:00
drh e791e7c7a0 Fix harmless compiler warning.
FossilOrigin-Name: 706373dcbe43752cf21604f278f96fb3015a36089ad64f069bb3a64bc526d137
2026-04-23 14:49:21 +00:00
stephan 2545d9c201 CLI shell: handle the special case of .prompt "" to not incorrectly report that as an OOM. Reported [https://fossil-scm.org/forum/forumpost/ca277be73a|in the Fossil SCM forum].
FossilOrigin-Name: 3fa0500b964869c45f7b49717680b791049f7cd8c47a06a337dd22351d2002f9
2026-04-23 14:05:36 +00:00
dan 2a07c6de2c When updating indexes on expressions, omit the update if the new indexed values are the same as the old.
FossilOrigin-Name: f0fc4e5ec334da3a1db8b0334e23d1911874c96675690da94210b2afb45f7307
2026-04-22 19:38:04 +00:00
dan 68b07ddd41 Add OOM test for the new code on this branch.
FossilOrigin-Name: 685be705a2a69e79de0d581e5bbe9d942133817342121786a551d95d59a4af6c
2026-04-22 19:25:12 +00:00
drh 4b69e7704b Mark branches that are believed to be unreachable.
FossilOrigin-Name: 18ed9736fbbea762e04b8ad156e83e577e60c5234a5e233540ad8664fe3b379c
2026-04-22 19:12:48 +00:00
dan e17ab401f0 Instead of adding a branch to OP_IdxInsert, use an extra OP_IfNull when updating indexes on expressions.
FossilOrigin-Name: 5112f96cb1428693614b91bcca78326fccf7289e395a920339676ceeba871e3f
2026-04-22 18:19:24 +00:00
dan 57ee077c5e Enable the optimization on this branch for indexes on expressions only.
FossilOrigin-Name: 3576b6930436b3149c5033476f70518e9b4adeaeec2538a68b7dc599eb854c47
2026-04-22 17:50:50 +00:00
dan c7edd22456 Fix P3/P5 confusion in the comment above OP_IdxDelete.
FossilOrigin-Name: 0fb6ca8e22f355838a02223dd24b34c0669a6cc0b7ac80931c721db72cf5c1c8
2026-04-22 17:31:19 +00:00
dan 8606a52934 Detect and omit cases where an index key is being replaced with an identical key.
FossilOrigin-Name: 7a01caf0d0864a462eb81b7643dcf89048f4ae56a29d762f0cfc38066218504f
2026-04-22 16:58:36 +00:00
drh 5c6404aa77 Fix a integer type bug in the previous check-in.
FossilOrigin-Name: 5e1b5ff1c170e94956bf77bd38afcad6369cb9f9333864711212af045281ad0e
2026-04-22 13:41:20 +00:00
drh 429369f4aa QRF and the CLI preserve zero bytes when outputing unformatted BLOB values.
FossilOrigin-Name: dbc1d6f0a3452607e4e92155df0fdb1c5ea4ea5ad1654664f86383faf6c105ef
2026-04-22 12:22:32 +00:00
drh 9529894a29 Fix harmless compiler warning in QRF.
FossilOrigin-Name: dcfb505ac7762f7a3102e1c3853a83dca1d1ef436cc8981949b63c7d7992cc5b
2026-04-21 22:19:38 +00:00
dan c4c47a49a8 Disable optimization of nested EXIST loops. Possible fix for [forum:/forumpost/077c02e8ed | forum post 77c02e8ed].
FossilOrigin-Name: d0d95a39bc211034071746395ee6dbcfbea9d573d27480655391ba9698f7e214
2026-04-21 20:40:22 +00:00
drh ee7f6f29fc Fix the BETWEEN operator so that it propagates the EP_Subquery,
EP_Collate, and EP_HasFunc flags in the expression tree, as it ought.
Fix for the problem reported at
[forum:/forumpost/2026-04-21T19:10:55Z|forum post 2026-04-21T19:10:55Z]
and probably a bunch of other problems too.  This has been incorrect
for a long time.

FossilOrigin-Name: 2d1d2947b28f5dcbf4c66b594e176038c4e71e61948a88db565c1cb1212657ce
2026-04-21 20:28:38 +00:00
dan c3b52dff53 Correctly dequote the constraint name passed to ALTER TABLE DROP CONSTRAINT. This improves upon the partial fix in [7f5afb12f4]. Forum post [forum:/forumpost/a746b08b87 | a746b08b87].
FossilOrigin-Name: 9387238cb0bb2651c64ecb229072df039577d71fd91546a2f0c94ca9755bf25d
2026-04-21 18:07:04 +00:00
dan 30af54043e Disable optimization of nested EXIST loops. Possible fix for [forum:/forumpost/077c02e8ed | forum post 77c02e8ed].
FossilOrigin-Name: 64f0d9eb63a351de12bb9643f1f6390a89f6d95dc81c07f1dc409ee31bae6f83
2026-04-21 16:40:08 +00:00
drh 4ebed2a4e5 Fix an off-by-one buffer size calculation in the decimal.c extension.
FossilOrigin-Name: 24df42104d5fd1cf974f2bf539fa7515808e21e68d64899c39f5fcf3bee49a48
2026-04-21 16:07:15 +00:00
drh 532ed30ab2 Do not unnecessarily delay opening the database file in the CLI.
FossilOrigin-Name: ab6ee76c1266b753d0749c63890f40db875536ceb4dd3252cc7a3386e386a0c1
2026-04-21 14:39:23 +00:00
drh 5e99eeb3d8 Fix another bug in [/info/e33da6d5dc964db8|EXISTS-to-JOIN] - this one
having to do with an OFFSET clause of a LIMIT.  Reported by
[forum:/forumpost/2026-04-21T10:57:09Z|forum post 2026-04-21T10:57:09Z].

FossilOrigin-Name: 1dd3c6a5e50ac3f617683678223e42f48636c17e58905506c5c74cc4bf05845c
2026-04-21 12:59:43 +00:00
stephan d3abfd77f5 Reformulate how the OPFS async proxy Worker is loaded for the bundler-friendly builds to work around a bug in Vite in which it incompatibly rewrites the Worker's URL arguments. Addresses the discussion at [https://github.com/sqlite/sqlite-wasm/pull/159|npm package PR 159] and patch validated by Jure Rotar.
FossilOrigin-Name: ec877a30f5c5db30b9154745140744c5cc80d89673d79e50901d7377599cf2b4
2026-04-21 10:19:38 +00:00
drh 63984b6ab7 Fix the fileio extension for Windows builds so that it does not depend on
the sqlite3_win32_utf8_to_unicode() and sqlite3_win32_unicode_to_utf()
routines that are found in the SQLite core.
[forum:/forumpost/2026-04-20T02:02:56Z|Forum post 2026-04-20T02:02:56Z].

FossilOrigin-Name: fe0414a9a3caf6af67f53a5f3534efd5d4bf4978ebce1c591ef62d6961e55701
2026-04-20 10:28:19 +00:00
drh 93082e5589 Fix a harmless compiler warning in test/speedtest1.c.
FossilOrigin-Name: 13f0fd1daaf787bff6eded4a01c2cf47c79e52cf8812bb344995e28c015a4ed1
2026-04-18 21:51:32 +00:00
drh f6b807a022 Performance improvement in the substr() and length() SQL functions.
Caution: The new code may give different results for malformed UTF8.
I do not consider that to be a problem by the GI/GO principle.

FossilOrigin-Name: 6124d27a33f4562f40777c2c6318d61709f7b481f23f9ade45064d8ad0700752
2026-04-18 12:31:53 +00:00
drh 8c6a6b85db Fix a test case that started failing due to a change in the help text
for the ".prompt" command of the CLI.

FossilOrigin-Name: bfe9df1bf4660ce6bdfd11a4f06d32694c93750c7bc0a6432459d9f1089eace4
2026-04-17 19:12:27 +00:00
dan 9f76fb019e Update interrupt2.test to avoid using Tcl_GetCommandInfo() from within calls to Tcl_DeleteCommand().
FossilOrigin-Name: 1979aa0902a43f20d4e396c5f9b9a49aaf0094d8520bf53ce058bb379a7720ab
2026-04-17 15:09:50 +00:00
drh 29997b4731 Help-text and comment fixes in the CLI. Add the output-redir-test.txt
testing script.

FossilOrigin-Name: ec58a133b4716d4f5a53c38853f8ecdb7a1275b931663ce07c8dc700d845e62e
2026-04-17 11:41:33 +00:00
drh f0c8e27670 Less error-prone parsing of ".once" options. Fix for the problem reported
by [forum:/info/2026-04-17T01:26:56Z|forum post 2026-04-17T01:26:56Z].

FossilOrigin-Name: b235a8093734f457c2731af017c99027510d04e5cd1060f5559afbec5409a472
2026-04-17 01:50:40 +00:00
drh d6c985ad0b Fix testrunner.tcl so that it does not create directories with names
ending in "sqlite3.o" or "sqlite3.lo".  Use "sqlite3obj" for those
directory names instead.  Otherwise "make clean" gets confused.

FossilOrigin-Name: a4bf9289c9cdb12b22bfb24e7e2b0243384e9edece12ae3fed14afbfe9b93260
2026-04-16 19:50:52 +00:00
drh 1696740fdc Improved comments explaining the logic, and improved diagnostic messages
when testrunner.tcl encounters trouble loading the sqlite3 extension.

FossilOrigin-Name: 8d820b0ccfccff94ed5b7297fa587ac27a74e990f233cfe229da7409ab2e3af8
2026-04-16 19:33:04 +00:00
drh 2cefd5954a Minor updates to testrunner documentation.
FossilOrigin-Name: f8507bd5e221783175be2bb7b907c098e0970b1cbcb01817df7217005eab9ab4
2026-04-16 17:07:23 +00:00
dan 8895c50403 Run C-language tests in tests/c/ as part of release test.
FossilOrigin-Name: e6929022b71c6bff7aa9cfbdb8a5e80499ca856b8c06d4211c55311b48704a08
2026-04-16 16:43:32 +00:00
drh a2116f86b0 The sqlite3_str_new() interface never returns NULL, even after an OOM.
Code that uses that interface should invoke sqlite3_str_errcode() to see
if an OOM has occurred.

FossilOrigin-Name: cb910047edc591102dd4ed0d57c863b366981b8aa1d3085d5f95b1fbbabf6c31
2026-04-15 14:41:25 +00:00
drh 1e472f2d32 Bug fix in sqlite3_str_free(): Do not crash if called on an sqlite3_str
object returned from sqlite3_str_new() following an OOM.

FossilOrigin-Name: 92d8ac0c4938e43b00111b43630ecfa91c30e5200ca03937a84f4b50bd1a13b3
2026-04-15 14:17:58 +00:00
drh e3dbf75160 Add support for the analyze() extension function to the fuzzcheck test
program.

FossilOrigin-Name: abd94554d24122f0e0c3b7b36e5846e8c7aa0dddbddd9aae35b3f6ae6ab283c0
2026-04-15 13:05:43 +00:00
drh ade9289540 Improve the analyze() extension so that it returns a simple error message
as text (it does not throw an error) if the database is empty or is "temp"
or does not exist.

FossilOrigin-Name: 35379f60922f14d4f6d231ae627df066ad4e4510208bcc244505b9afb279f2fa
2026-04-15 12:47:37 +00:00
drh dfba4eb34a Fix harmless compiler warnings seen by MSVC in the previous check-in.
Also add ext/misc/analyze.c to the makefile dependencies for the CLI.

FossilOrigin-Name: 5a0ee6e227042e41ac64869c75f961798b252458670c18662175fe5bfa8b87d3
2026-04-15 12:35:23 +00:00
drh b57d2a5a51 Add the analyze() SQL function implemented the ext/misc/analyze.c extension
(but not part of the amalgamation).  Make that function available in the
CLI and add a new ".dbinfo" command to the CLI using that function.

FossilOrigin-Name: 4c4988e56df3c668b8891e2a55887a6618f5b84e9111e562b93059ddb9a662dc
2026-04-15 12:20:11 +00:00
stephan f0baddb205 On platforms which support ./configure --with-icu-config, ensure that 'make tclextension' includes the ICU pieces in the tcl extension. Intended to resolve [forum:92a88de4b88929fe|forum post 92a88de4b88929fe].
FossilOrigin-Name: 404fde8bacc3f05254a2fcdb1531a7f53125a7ad45dc6b68a5065c1d0c73b670
2026-04-15 11:40:13 +00:00
dan ec2ea68d1f Avoid a potentially undefined left-shift in the fts5 porter tokenizer.
FossilOrigin-Name: 46a288e43e4c48fca6610bce6a2db418aaa3c8a1dcb115b7a0bfad2063355e58
2026-04-15 11:23:30 +00:00
dan c71e6dd054 Handle the case where the name of the constraint in an "ALTER TABLE DROP CONSTRAINT" command is quoted. [forum:8bfbaec404 | Forum post 8bfbaec404].
FossilOrigin-Name: 7f5afb12f4a5d35cfe6b95f17d85ce85ce62159515bfe26fb9c67d3ce26b6d4a
2026-04-15 11:07:58 +00:00
stephan afef1f2923 Minor doc typo fixes contributed by BrickViking.
FossilOrigin-Name: c4660ce205919ce0d9262e7fd7879375a72ef65d9e5ac97f19caf5dc36e355aa
2026-04-14 23:53:38 +00:00
dan 846fbd6653 Handle a special case of a corrupt changeset in sqlite3changegroup_add().
FossilOrigin-Name: eba625f917935437e3f366197df1c6717c7120ce0418a0cbac1d2024b2235091
2026-04-14 20:18:54 +00:00
dan 1b14a925dc Have the session module detect some corrupt changesets earlier.
FossilOrigin-Name: 0de91ff0d798cff21289d893cc441b89fc37b051d5cdf611d92d3ae2bc41cdf2
2026-04-14 20:17:41 +00:00
dan 839433d457 Handle a special case of a corrupt changeset in sqlite3changegroup_add().
FossilOrigin-Name: 49b3bac482c831f503c7f90c35959e7ea731950e991baba86b2ab95987d2539b
2026-04-14 20:02:49 +00:00
dan 483f0ef13c Ensure c-tests use the locally built sqlite3.h file, not the system copy.
FossilOrigin-Name: 2d81ee65ffbed30fd98bdda96dc79c1929c73f806cea3c9e4c244b618980b202
2026-04-14 18:12:09 +00:00
stephan 6e93d28950 Pass the ICU-related build flags through the 'tclextension' target, not just 'tclextension-install'.
FossilOrigin-Name: 499c89f8745fac7ee93ff79a340abd69b4f06b07983b4d50057fa5d0893b2f3b
2026-04-14 00:48:34 +00:00
stephan 008395614a Tweak 'make tclextension' to pass on any --with-icu-config build flags so that it can link with the various ICU libs. This works for me but needs testing on a wider selection of systems before being moved to trunk. Intended to resolve [forum:92a88de4b88929fe|forum post 92a88de4b88929fe].
FossilOrigin-Name: a8c022d7946e8a29114400c1321f36f03979a2277253f1dcd769d8f36e944ece
2026-04-14 00:11:23 +00:00
dan dd1e2c39bc Update test/c/snprintf1.c to test the result of the sqlite3_snprintf() call. Also add an SQLITE_OMIT_AUTOINIT configuration and update C tests to account for it.
FossilOrigin-Name: 30b597d797e737a2907b755706a37d63c37c6a06c4e037098a6d9c482bcde887
2026-04-13 11:20:51 +00:00
dan 0523cfda5a Fixes for running C tests on windows.
FossilOrigin-Name: 1fcacdc41ab1bb66a628acdac29412e66decdc2578dd9d084baaffb74679f984
2026-04-11 18:05:49 +00:00
dan bc68ec78de Enhance testrunner.tcl to run individual tests written in C from the test/c/ directory.
FossilOrigin-Name: 6f140f76f47aadb10d3f35358503d91adb43e0c1802326f6e599effe1b08e7aa
2026-04-11 17:03:27 +00:00
61 changed files with 2317 additions and 2191 deletions
+5
View File
@@ -1766,6 +1766,7 @@ 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
@@ -2342,6 +2343,7 @@ 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 \
@@ -2741,6 +2743,9 @@ rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
$(AUXTEST).exe: $(TOP)\test\c\$(AUXTEST).c
$(LTLINK) $(NO_WARN) $(TOP)\test\c\$(AUXTEST).c sqlite3.lo /link $(LDFLAGS) $(LTLINKOPTS)
THREADTEST3_SRC = \
$(TOP)\test\threadtest3.c \
$(TOP)\test\tt3_checkpoint.c \
+1 -1
View File
@@ -2042,7 +2042,7 @@ proc sqlite-check-tcl {} {
}
}
if {![file-isexec $with_tclsh]} {
proj-warn "Cannot find a usable tclsh (tried: $tryThese)
proj-warn "Cannot find a usable tclsh (tried: $tryThese)"
}
}
define TCLSH_CMD $with_tclsh
+6 -1
View File
@@ -33,7 +33,7 @@
The testrunner.tcl program is a Tcl script used to run multiple SQLite
tests in parallel, thus reducing testing time on multi-core machines.
The testrunner.tcl supports running tests that based on `testfixture`,
`sqlite3`, and `fuzzcheck`.
`sqlite3`, `fuzzcheck`, and C programs found in test/c.
<a name="runtr"></a>
## 1.1 Running testrunner.tcl
@@ -59,11 +59,16 @@ up front.
The standard Makefiles for SQLite include targets that invoke
testrunner.tcl. So the following commands also run testrunner.tcl:
* `make test`
* `make devtest`
* `make releasetest`
* `make sdevtest`
* `make testrunner`
Since SQLite 3.53.0, there is a "<tt>make.bat</tt>" script in the root
of the source tree that causes the "make" command to work on Windows.
There is no need to do something different using "nmake" on Windows.
<a name="outputs"></a>
## 1.3 Outputs from testrunner.tcl
+2 -2
View File
@@ -712,9 +712,9 @@ static int fts5Porter_Ostar(char *zStem, int nStem){
for(i=0; i<nStem; i++){
bCons = !fts5PorterIsVowel(zStem[i], bCons);
assert( bCons==0 || bCons==1 );
mask = (mask << 1) + bCons;
mask = ((mask << 1) + bCons) & 0x0007;
}
return ((mask & 0x0007)==0x0005);
return (mask==0x0005);
}
}
+8
View File
@@ -65,5 +65,13 @@ foreach {in out} $test_vocab {
incr i
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE tbl USING fts5(t, tokenize='porter unicode61');
INSERT INTO tbl VALUES(' andeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee');
}
finish_test
+46 -37
View File
@@ -419,7 +419,7 @@ static void analyzeFunc(
int rc;
sqlite3_stmt *pStmt;
int n;
sqlite3_int64 i64;
sqlite3_int64 ii;
sqlite3_int64 pgsz;
sqlite3_int64 nPage;
sqlite3_int64 nPageInUse;
@@ -429,25 +429,29 @@ static void analyzeFunc(
Analysis s;
sqlite3_uint64 r[2];
(void)argc;
memset(&s, 0, sizeof(s));
s.db = sqlite3_context_db_handle(context);
s.context = context;
s.pOut = sqlite3_str_new(0);
if( s.pOut==0 ){ analysisError(&s, 0); return; }
if( sqlite3_str_errcode(s.pOut) ){
analysisError(&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 ){
/* Attempt to analyze "temp" returns NULL */
analysisReset(&s);
sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
return;
}
i64 = 0;
rc = analysisSqlInt(&s,&i64,"SELECT 1 FROM pragma_database_list"
ii = 0;
rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
" WHERE name=%Q COLLATE nocase",s.zSchema);
if( rc || i64==0 ){
/* Return NULL the named schema does not exist */
if( rc || ii==0 ){
analysisReset(&s);
sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
return;
}
sqlite3_randomness(sizeof(r), &r);
@@ -536,18 +540,23 @@ static void analyzeFunc(
);
if( rc ) return;
nPage = 0;
rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
if( rc ) return;
if( nPage<=0 ){
/* Very brief reply for an empty database */
analysisReset(&s);
sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
return;
}
/* Begin generating the report */
analysisTitle(&s, "Database storage utilization report");
pgsz = 0;
rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
if( rc ) return;
analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
nPage = 0;
rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
if( rc ) return;
analysisLine(&s, "Pages in the database", "%lld\n", nPage);
if( nPage<=0 ) nPage = 1;
nPageInUse = 0;
rc = analysisSqlInt(&s, &nPageInUse,
@@ -562,25 +571,25 @@ static void analyzeFunc(
analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
i64 = 0;
rc = analysisSqlInt(&s, &i64, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
ii = 0;
rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
if( rc ) return;
if( i64==0 || nPage<=1 ){
i64 = 0;
if( ii==0 || nPage<=1 ){
ii = 0;
}else{
double rPtrsPerPage = pgsz/5;
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
i64 = (sqlite3_int64)ceil(rAvPage);
ii = (sqlite3_int64)ceil(rAvPage);
}
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", i64);
analysisPercent(&s, (i64*100.0)/(double)nPage);
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
analysisPercent(&s, (ii*100.0)/(double)nPage);
i64 = 0;
rc = analysisSqlInt(&s, &i64,
ii = 0;
rc = analysisSqlInt(&s, &ii,
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
s.zSchema);
if( rc ) return;
analysisLine(&s, "Number of tables", "%lld\n", i64);
analysisLine(&s, "Number of tables", "%lld\n", ii);
nWORowid = 0;
rc = analysisSqlInt(&s, &nWORowid,
"SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
@@ -588,7 +597,7 @@ static void analyzeFunc(
if( rc ) return;
if( nWORowid>0 ){
analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
analysisLine(&s, "Number of rowid tables", "%lld\n", i64 - nWORowid);
analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
}
nIndex = 0;
rc = analysisSqlInt(&s, &nIndex,
@@ -596,23 +605,23 @@ static void analyzeFunc(
s.zSchema);
if( rc ) return;
analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
i64 = 0;
rc = analysisSqlInt(&s, &i64,
ii = 0;
rc = analysisSqlInt(&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 - i64);
analysisLine(&s, "Number of implied indexes", "%lld\n", i64);
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);
i64 = 0;
rc = analysisSqlInt(&s, &i64,
ii = 0;
rc = analysisSqlInt(&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 ", i64);
analysisPercent(&s, i64*100.0/(double)(pgsz*nPage));
analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
analysisTitle(&s, "Page counts for all tables with their indexes");
pStmt = analysisPrepare(&s,
@@ -624,9 +633,9 @@ static void analyzeFunc(
s.zSU);
if( pStmt==0 ) return;
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
sqlite3_int64 n = sqlite3_column_int64(pStmt,1);
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", n);
analysisPercent(&s, (n*100.0)/(double)nPage);
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);
}
if( analysisStmtFinish(&s, rc, pStmt) ) return;
@@ -640,9 +649,9 @@ static void analyzeFunc(
s.zSU);
if( pStmt==0 ) return;
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
sqlite3_int64 n = sqlite3_column_int64(pStmt,1);
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", n);
analysisPercent(&s, (n*100.0)/(double)nPage);
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);
}
if( analysisStmtFinish(&s, rc, pStmt) ) return;
+1 -1
View File
@@ -261,7 +261,7 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
sqlite3_result_null(pCtx);
return;
}
z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 );
z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+8 );
if( z==0 ){
sqlite3_result_error_nomem(pCtx);
return;
+62 -9
View File
@@ -97,8 +97,6 @@ SQLITE_EXTENSION_INIT1
# define STRUCT_STAT struct _stat
# define chmod(path,mode) fileio_chmod(path,mode)
# define mkdir(path,mode) fileio_mkdir(path)
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
#endif
#include <time.h>
#include <errno.h>
@@ -125,13 +123,69 @@ SQLITE_EXTENSION_INIT1
#define FSDIR_COLUMN_PATH 5 /* Path to top of search */
#define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
#ifdef _WIN32
/*
** Convert a UTF-8 string to Microsoft Unicode.
**
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static wchar_t *winUtf8To16(const char *zText){
int nChar;
wchar_t *zWideText;
nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
if( nChar==0 ){
return 0;
}
zWideText = sqlite3_malloc64(nChar*sizeof(WCHAR) );
if( zWideText==0 ){
return 0;
}
nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText,
nChar);
if( nChar==0 ){
sqlite3_free(zWideText);
zWideText = 0;
}
return zWideText;
}
#endif /* _WIN32 */
#ifdef _WIN32
/*
** Convert a Microsoft Unicode string to UTF-8.
**
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static char *winUtf16To8(wchar_t *zWideText){
int nByte;
char *zText;
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
if( nByte == 0 ){
return 0;
}
zText = sqlite3_malloc64( nByte );
if( zText==0 ){
return 0;
}
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte,
0, 0);
if( nByte == 0 ){
sqlite3_free(zText);
zText = 0;
}
return zText;
}
#endif /* _WIN32 */
/*
** UTF8 chmod() function for Windows
*/
#if defined(_WIN32) || defined(WIN32)
static int fileio_chmod(const char *zPath, int pmode){
int rc;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
wchar_t *b1 = winUtf8To16(zPath);
if( b1==0 ) return -1;
rc = _wchmod(b1, pmode);
sqlite3_free(b1);
@@ -145,7 +199,7 @@ static int fileio_chmod(const char *zPath, int pmode){
#if defined(_WIN32) || defined(WIN32)
static int fileio_mkdir(const char *zPath){
int rc;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
wchar_t *b1 = winUtf8To16(zPath);
if( b1==0 ) return -1;
rc = _wmkdir(b1);
sqlite3_free(b1);
@@ -272,7 +326,7 @@ static int fileStat(
){
#if defined(_WIN32)
int rc;
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
wchar_t *b1 = winUtf8To16(zPath);
if( b1==0 ) return 1;
rc = _wstat(b1, pStatBuf);
if( rc==0 ){
@@ -425,14 +479,13 @@ static int writeFile(
LONGLONG intervals;
HANDLE hFile;
LPWSTR zUnicodeName;
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
GetSystemTime(&currentTime);
SystemTimeToFileTime(&currentTime, &lastAccess);
intervals = (mtime*10000000) + 116444736000000000;
lastWrite.dwLowDateTime = (DWORD)intervals;
lastWrite.dwHighDateTime = intervals >> 32;
zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
zUnicodeName = winUtf8To16(zFile);
if( zUnicodeName==0 ){
return 1;
}
@@ -1090,12 +1143,12 @@ static char *portable_realpath(const char *zPath){
if( zPath==0 ) return 0;
zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
zPath16 = winUtf8To16(zPath);
if( zPath16==0 ) return 0;
z = _wfullpath(NULL, zPath16, 0);
sqlite3_free(zPath16);
if( z ){
zOut = sqlite3_win32_unicode_to_utf8(z);
zOut = winUtf16To8(z);
free(z);
}
return zOut;
+31 -19
View File
@@ -428,7 +428,6 @@ static void qrfEqpStats(Qrf *p){
if( nRow>=0 ){
if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
qrfApproxInt64(pStats, nRow);
nSp = 2;
if( p->spec.eStyle==QRF_STYLE_StatsEst ){
sqlite3_str_appendf(pStats, " ");
qrfApproxInt64(pStats, (i64)rEstCum);
@@ -718,19 +717,16 @@ static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){
}
/*
** Escape the input string if it is needed and in accordance with
** eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
** Escape the text starting at byte iStart of pStr, if needed, using the
** escape encoding of eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
** The pStr string is modified appropriately.
**
** Escaping is needed if the string contains any control characters
** other than \t, \n, and \r\n
**
** If no escaping is needed (the common case) then set *ppOut to NULL
** and return 0. If escaping is needed, write the escaped string into
** memory obtained from sqlite3_malloc64() and make *ppOut point to that
** memory and return 0. If an error occurs, return non-zero.
**
** The caller is responsible for freeing *ppFree if it is non-NULL in order
** to reclaim memory.
** If no escaping is needed (the common case) then pStr is unchanged.
** If escaping is required, then pStr is expanded and modified to hold
** an escaped representation of the text.
*/
static void qrfEscape(
int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */
@@ -738,20 +734,22 @@ static void qrfEscape(
int iStart /* Begin escapding on this byte of pStr */
){
sqlite3_int64 i, j; /* Loop counters */
sqlite3_int64 sz; /* Size of the string prior to escaping */
sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
unsigned char *zIn; /* Text to be escaped */
unsigned int nIn; /* Bytes of text to be escaped */
unsigned char c; /* A single character of the text */
unsigned char *zOut; /* Where to write the results */
/* Find the text to be escaped */
zIn = (unsigned char*)sqlite3_str_value(pStr);
nIn = sqlite3_str_length(pStr);
if( zIn==0 ) return;
zIn += iStart;
nIn -= iStart;
/* Count the control characters */
for(i=0; (c = zIn[i])!=0; i++){
if( c<=0x1f
for(i=0; i<nIn; i++){
if( (c = zIn[i])<=0x1f
&& c!='\t'
&& c!='\n'
&& (c!='\r' || zIn[i+1]!='\n')
@@ -763,18 +761,17 @@ static void qrfEscape(
/* Make space to hold the escapes. Copy the original text to the end
** of the available space. */
sz = sqlite3_str_length(pStr) - iStart;
if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
sqlite3_str_appendchar(pStr, nCtrl, ' ');
zOut = (unsigned char*)sqlite3_str_value(pStr);
if( zOut==0 ) return;
zOut += iStart;
zIn = zOut + nCtrl;
memmove(zIn,zOut,sz);
memmove(zIn,zOut,nIn);
/* Convert the control characters */
for(i=j=0; (c = zIn[i])!=0; i++){
if( c>0x1f
for(i=j=0; i<nIn; i++){
if( (c = zIn[i])>0x1f
|| c=='\t'
|| c=='\n'
|| (c=='\r' && zIn[i+1]=='\n')
@@ -786,6 +783,7 @@ static void qrfEscape(
j += i;
}
zIn += i+1;
nIn -= i+1;
i = -1;
if( eEsc==QRF_ESC_Symbol ){
zOut[j++] = 0xe2;
@@ -1188,8 +1186,22 @@ static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){
break;
}
default: {
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
qrfEncodeText(p, pOut, zTxt);
const void *pBlob = sqlite3_column_blob(p->pStmt,iCol);
int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
int rc;
qrfWrite(p);
if( nBlob==0 ){
/* no-op */
}else if( p->spec.eEsc==QRF_ESC_Off ){
rc = p->spec.xWrite(p->spec.pWriteArg,pBlob,nBlob);
if( rc ){
qrfError(p, rc, "Failed to write %d bytes of BLOB output", nBlob);
}
}else{
sqlite3_str_append(pOut, pBlob, nBlob);
qrfEscape(p->spec.eEsc, pOut, 0);
qrfWrite(p);
}
}
}
break;
+40 -16
View File
@@ -532,18 +532,39 @@ static void recoverFinalize(sqlite3_recover *p, sqlite3_stmt *pStmt){
}
}
/*
** Run a single SQL statement in zSql. If zSql contains two or more
** SQL statements separated by ';', only the first is run.
**
** Return the sqlite3_finalizer() or sqlite3_prepare() result code
** from running the zSql statement.
*/
static int recoverOneStmt(sqlite3 *db, const char *zSql){
sqlite3_stmt *pStmt = 0;
int rc;
if( zSql==0 ) return SQLITE_OK;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ){
sqlite3_finalize(pStmt);
return rc;
}
while( SQLITE_ROW==sqlite3_step(pStmt) ){}
return sqlite3_finalize(pStmt);
}
/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). A copy of p->errCode is returned in this
** case.
**
** Otherwise, execute SQL script zSql. If successful, return SQLITE_OK.
** Or, if an error occurs, leave an error code and message in the recover
** handle and return a copy of the error code.
** Otherwise, execute a single SQL statment in zSql. Even if zSql contains
** two or more SQL statements separated by ';', only execute the first one.
** If successful, return SQLITE_OK. Or, if an error occurs, leave an error
** code and message in the recover handle and return a copy of the error code.
*/
static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
if( p->errCode==SQLITE_OK ){
int rc = sqlite3_exec(db, zSql, 0, 0, 0);
int rc = recoverOneStmt(db, zSql);
if( rc ){
recoverDbError(p, db);
}
@@ -943,7 +964,8 @@ static void recoverTransferSettings(sqlite3_recover *p){
}
recoverFinalize(p, p1);
}
recoverExec(p, db2, "CREATE TABLE t1(a); DROP TABLE t1;");
recoverExec(p, db2, "CREATE TABLE t1(a)");
recoverExec(p, db2, "DROP TABLE t1");
if( p->errCode==SQLITE_OK ){
sqlite3 *db = p->dbOut;
@@ -1025,12 +1047,12 @@ static int recoverOpenOutput(sqlite3_recover *p){
static void recoverOpenRecovery(sqlite3_recover *p){
char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
recoverExec(p, p->dbOut, zSql);
recoverExec(p, p->dbOut,
"PRAGMA writable_schema = 1;"
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT);"
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
);
sqlite3_free(zSql);
recoverExec(p, p->dbOut, "PRAGMA writable_schema = 1");
recoverExec(p, p->dbOut,
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT)");
recoverExec(p, p->dbOut,
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql)");
}
@@ -1170,7 +1192,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
")"
"SELECT rootpage, tbl, isVirtual, name, sql"
" FROM dbschema "
" WHERE tbl OR isIndex"
" WHERE (tbl OR isIndex) AND sql GLOB 'CREATE *'"
" ORDER BY tbl DESC, name=='sqlite_sequence' DESC"
);
@@ -1196,7 +1218,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
zName, zName, zSql
));
}
rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
rc = recoverOneStmt(p->dbOut, zSql);
if( rc==SQLITE_OK ){
recoverSqlCallback(p, zSql);
if( bTable && !bVirtual ){
@@ -1238,15 +1260,17 @@ static int recoverWriteSchema2(sqlite3_recover *p){
p->bSlowIndexes ?
"SELECT rootpage, sql FROM recovery.schema "
" WHERE type!='table' AND type!='index'"
" AND sql GLOB 'CREATE *'"
:
"SELECT rootpage, sql FROM recovery.schema "
" WHERE type!='table' AND (type!='index' OR sql NOT LIKE '%unique%')"
" AND sql GLOB 'CREATE *'"
);
if( pSelect ){
while( sqlite3_step(pSelect)==SQLITE_ROW ){
const char *zSql = (const char*)sqlite3_column_text(pSelect, 1);
int rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
int rc = recoverOneStmt(p->dbOut, zSql);
if( rc==SQLITE_OK ){
recoverSqlCallback(p, zSql);
}else if( rc!=SQLITE_ERROR ){
@@ -2624,7 +2648,7 @@ static void recoverStep(sqlite3_recover *p){
if( bUseWrapper ) recoverUninstallWrapper(p);
}while( p->errCode==SQLITE_NOTADB
&& (bUseWrapper--)
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
&& SQLITE_OK==recoverOneStmt(p->dbIn, "ROLLBACK")
);
}
@@ -2689,7 +2713,7 @@ static void recoverStep(sqlite3_recover *p){
** database. Regardless of whether or not an error has occurred, make
** an attempt to end the read transaction on the input database. */
recoverExec(p, p->dbOut, "COMMIT");
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
rc = recoverOneStmt(p->dbIn, "END");
if( p->errCode==SQLITE_OK ) p->errCode = rc;
recoverSqlCallback(p, "PRAGMA writable_schema = off");
@@ -2885,7 +2909,7 @@ int sqlite3_recover_finish(sqlite3_recover *p){
}else{
recoverFinalCleanup(p);
if( p->bCloseTransaction && sqlite3_get_autocommit(p->dbIn)==0 ){
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
rc = recoverOneStmt(p->dbIn, "END");
if( p->errCode==SQLITE_OK ) p->errCode = rc;
}
rc = p->errCode;
+13 -1
View File
@@ -259,6 +259,18 @@ foreach {tn type C2hex C3hex} {
} {1 SQLITE_CORRUPT}
}
#-------------------------------------------------------------------------
#
reset_db
set CSD 5402010074000900010000000000000001030441414141
set CSI 5402010074001200010000000000000001063258585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858
do_test 7.0 {
sqlite3changegroup grp
grp add [db one {SELECT unhex($CSD)}]
list [catch { grp add [db one {SELECT unhex($CSI)}] } msg] $msg
} {1 SQLITE_CORRUPT}
grp delete
finish_test
+15 -12
View File
@@ -638,10 +638,11 @@ static int sessionSerialLen(const u8 *a){
int n;
assert( a!=0 );
e = *a;
if( e==0 || e==0xFF ) return 1;
if( e==SQLITE_NULL ) return 1;
if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
return sessionVarintGet(&a[1], &n) + 1 + n;
if( e==SQLITE_TEXT || e==SQLITE_BLOB ){
return sessionVarintGet(&a[1], &n) + 1 + n;
}
return 1;
}
/*
@@ -664,17 +665,17 @@ static unsigned int sessionChangeHash(
u8 *a = aRecord; /* Used to iterate through change record */
for(i=0; i<pTab->nCol; i++){
int eType = *a;
int isPK = pTab->abPK[i];
if( bPkOnly && isPK==0 ) continue;
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|| eType==SQLITE_NULL || eType==0
);
if( isPK ){
a++;
int eType = *a++;
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|| eType==SQLITE_NULL || eType==0
);
h = sessionHashAppendType(h, eType);
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
h = sessionHashAppendI64(h, sessionGetI64(a));
@@ -3702,9 +3703,11 @@ static int sessionChangesetBufferRecord(
rc = sessionInputBuffer(pIn, nByte);
}else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
nByte += 8;
}else if( eType!=0 && eType!=SQLITE_NULL ){
rc = SQLITE_CORRUPT_BKPT;
}
}
if( (pIn->iNext+nByte)>pIn->nData ){
if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
rc = SQLITE_CORRUPT_BKPT;
}
}
@@ -7050,7 +7053,7 @@ int sqlite3changegroup_change_text(
const char *pVal,
int nVal
){
int nText = nVal>=0 ? nVal : strlen(pVal);
sqlite3_int64 nText = nVal>=0 ? nVal : strlen(pVal);
sqlite3_int64 nByte = 1 + sessionVarintLen(nText) + nText;
int rc = SQLITE_OK;
SessionBuffer *pBuf = 0;
+8 -7
View File
@@ -1099,20 +1099,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return promiseResolve_(sqlite3);
};
const options = opfsUtil.options;
let proxyUri = options.proxyUri +(
//#if not target:es6-bundler-friendly
const proxyUri = options.proxyUri +(
(options.proxyUri.indexOf('?')<0) ? '?' : '&'
)+'vfs='+vfsName;
//sqlite3.config.error("proxyUri",options.proxyUri, (new Error()));
//#/if
const W = opfsVfs.worker =
//#if target:es6-bundler-friendly
(()=>{
/* _Sigh_... */
switch(vfsName){
case 'opfs':
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs", import.meta.url));
case 'opfs-wl':
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs-wl", import.meta.url));
}
/* Discussion explaining this formulation:
https://github.com/sqlite/sqlite-wasm/pull/159 */
const url = new URL('sqlite3-opfs-async-proxy.js', import.meta.url);
url.searchParams.set('vfs', vfsName);
return new Worker(url.toString());
})();
//#elif target:es6-module
new Worker(new URL(proxyUri, import.meta.url));
+12 -3
View File
@@ -982,6 +982,7 @@ 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 \
@@ -1678,7 +1679,8 @@ tclsqlite3.c: sqlite3.c tclsqlite-ex.c
#
# $(CFLAGS.tclextension) = CFLAGS for the tclextension* targets.
#
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAGS) $(OPTS)
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) \
$(OPT_FEATURE_FLAGS) $(OPTS) $(CFLAGS.icu)
#
# Build the SQLite TCL extension in a way that make it compatible
# with whatever version of TCL is running as $TCLSH_CMD, possibly defined
@@ -1686,7 +1688,8 @@ CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAG
#
tclextension: tclsqlite3.c
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only \
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
#
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
@@ -1694,7 +1697,8 @@ tclextension: tclsqlite3.c
#
tclextension-install: tclsqlite3.c
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" \
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
#
# Uninstall the SQLite TCL extension that is used by $TCLSH_CMD.
@@ -2341,6 +2345,7 @@ 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 \
@@ -2422,6 +2427,10 @@ sqlite3session.o: $(TOP)/ext/session/sqlite3session.c $(DEPS_EXT_COMMON)
stmt.o: $(TOP)/ext/misc/stmt.c $(DEPS_EXT_COMMON)
$(T.cc.extension) -c $(TOP)/ext/misc/stmt.c
$(AUXTEST): $(TOP)/test/c/$(AUXTEST).c
$(T.cc.sqlite) -o $@ $(TOP)/test/c/$(AUXTEST).c sqlite3.o $(LDFLAGS.libsqlite3)
#
# Windows section
#
+67 -60
View File
@@ -1,12 +1,12 @@
C Add\sa\smissing\sopen_db()\scall\sin\sthe\snew\s".dbstat"\scommand\sof\sthe\sCLI.
D 2026-04-15T11:58:54.973
C When\susing\sthe\sOR-optimization\son\sa\sloop\screated\sby\sexists-to-join,\sdo\sthe\searly-exit\slogic\sfor\sthe\swhole\sloop,\snot\sfor\seach\sindividual\sOR\sbranch.\sPossible\sfix\sfor\sforum\spost\s[forum:c8b205720c\s|\sc8b205720c].
D 2026-05-04T17:16:43.654
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
F Makefile.in 5fda086f33b144da08119255da1d2557f983d0764a13707f05acf0159fd89ba5
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 06b757f8648f1d9dd9683dbd72350cf0cf20d6fe09168cac455569b81dd97ddc
F Makefile.msc 6f4294982758b5eeeac740c1a263186c3fcb9ba51d1b48261e321bcb37a41dbb
F README.md e4f1a030f813c2fafc898c66d4f10bff2c75eb1a8f504eb9ad9a5ef80e3ff814
F VERSION 99cf3be5f13d091183e4314b7fc2e0c0e69accfbe64608b45a313338bbdd7b62
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -47,7 +47,7 @@ F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1
F autosetup/jimsh0.c 740dc8cbfaedaff1f27b54b32e0015b22fa6c1a439492b9795968d61e56bab75
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
F autosetup/proj.tcl ce301197f364f7ce2acabbbd84b43d19e917ec73653157ca134a06f32d322712
F autosetup/sqlite-config.tcl 8fecce2838b7e7d990d161d08998034f3e3b0b2ddf4d7a99dbfafba9c902e302
F autosetup/sqlite-config.tcl f67b868a320ff9f24af0fa74ba446a9735312dd5e69f8023a529600b08711421
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
F autosetup/teaish/core.tcl e014dd95900c7f9a34e8e0f460f47e94841059827bce8b4c49668b0c7ae3f1a0
@@ -63,7 +63,7 @@ F doc/jsonb.md acd77fc3a709f51242655ad7803510c886aa8304202fa9cf2abc5f5c4e9d7ae5
F doc/lemon.html 2085fda0a90a94fe92159a79dccc5c30d5a2313524887a31659cd66162f17233
F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
F doc/tcl-extension-testing.md b88861804fc1eaf83249f8e206334189b61e150c360e1b80d0dcf91af82354f5
F doc/testrunner.md daffa0ebbbe397a73537ae1b19b3124d489ce5f89dfe570781d1f1ef1809597c
F doc/testrunner.md 3589f7914d36adaff6d108566e09b2c6166887bea00580e5343f8b43615ffe12
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
F doc/vfs-shm.txt 1a55f3f0e7b6745931b117ba5c9df3640d7a0536f532ef0052563100f4416f86
@@ -119,7 +119,7 @@ F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e0
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
F ext/fts5/fts5_tokenize.c cfc16dde905552fe238c0403670852e75c0330ba508a9fb4836c1f596618561d
F ext/fts5/fts5_tokenize.c 03fa928dffcf1445f973f0994c4d2732812e32b264f45c303732aa0e8bb8dea7
F ext/fts5/fts5_unicode2.c 536a6dae41d16edadd6a6b58c56e2ebbb133f0dfe757562a2edbcdc9b8362e50
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
F ext/fts5/fts5_vocab.c bebee4aabcd056a44b3731166433cfdecf17ece750c08cb58733216222bd39e2
@@ -227,7 +227,7 @@ F ext/fts5/test/fts5origintext6.test 09eb1347cb0dceaebbebf3d3e6bd5d24c7c1006efdd
F ext/fts5/test/fts5phrase.test bb2554bb61d15f859678c96dc89a7de415cd5fc3b7b54c29b82a0d0ad138091c
F ext/fts5/test/fts5plan.test f8b0d752a818059a934cdc96c0f77de058a67a0a57bb3a8181d28307ab5b1626
F ext/fts5/test/fts5porter.test 15b514fac8690b58e99c330efe5bf5615bc43f2fae4a3cca3f923dbaff55a0c0
F ext/fts5/test/fts5porter2.test 94f0e4351e2c99b4e74f1fae05a4ddf1cb5b926620a8c14554160d075ddc7a59
F ext/fts5/test/fts5porter2.test 1dab0fe41342ebed32ca36a145de3e50be9093cb71e9f5250f6ebc589207982a
F ext/fts5/test/fts5prefix.test c0b7842f1a2d830c0b146cd438a95ea4c5a25635719ed0d973ffe41907338b83
F ext/fts5/test/fts5prefix2.test a5bb43b8a2687efafa7ac4e5ccff6812015cf8cf18e3086bb0eb3126f30fbbf6
F ext/fts5/test/fts5query.test 0320a7a4b58a6e3e50ec8910b301649da90ace675001f9e0bf6392750ad4591d
@@ -358,7 +358,7 @@ 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 8d237cc014b3736922c26a76a451050d244aa4980c47c531f368f817b1e77b49
F ext/misc/analyze.c c329e7fdd23caebbe5362b25a416a7fda7e1524ddba03be12f1d2e4a903caa02
F ext/misc/analyze.c 77e0f45a44c13d66f30922db553072305521c0fb3a448b920e641fccd2498527
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
F ext/misc/base64.c 1445761667c16356e827fc6418294c869468be934429aaa8315035e76dd58acf
@@ -372,10 +372,10 @@ F ext/misc/completion.c 3f5db28e88c3313103b2dd86d910a2944fd500c46754e473493968ce
F ext/misc/compress.c 8191118b9b73e7796c961790db62d35d9b0fb724b045e005a5713dc9e0795565
F ext/misc/csv.c 5e9d4dd749e762c144104c0f01db5bf4458735b19081ebe481a64e589a66687a
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
F ext/misc/decimal.c 23698283d9365ce66d54b5bb97c01e69b4aa7ac804f226f9117a0d42efd15a65
F ext/misc/decimal.c 432e5b03a0e2a68a1846a9852a565a1b546ca9b295deda834e4653f0f5577daa
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 9670c8ff7b255eea7845abc5123a4958e74016c16990b10497e56380f91704b9
F ext/misc/fileio.c e72033f987894ed821bf324a426ed462743399c274f1290dcb646349b6d7548f
F ext/misc/fileio.c 936c0a7b3382a047d833ad33f62ba59a3847b79ea745bf529797cd344966fbb0
F ext/misc/fossildelta.c 40add35db7f355d29ae856fe09043e66802fceff6f2551baccb28d794cadbc77
F ext/misc/fuzzer.c decaca5a3479dfba69576cd41d4e17161eaf154a5438e12d316bbc5853571802
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
@@ -422,7 +422,7 @@ F ext/misc/zipfile.c 5a583b5e72b4d777dc9f845529e6bd185d58024b633aafc93588679c787
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
F ext/qrf/README.md 9e644615d7d7b77ef7e9db798765679e50c5ed12eda48bce21c9ef9eb4715e9d
F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
F ext/qrf/qrf.c 64203184d9fc6ee75439fb6da70fd51dc7aaf3243600e52aa87d18ea1e4d6e73
F ext/qrf/qrf.c 9bd4ad396e75a7905b1eb956ac53fd93f77942963c5ffac176ae39880368553b
F ext/qrf/qrf.h fbb223ff5789b324b3e9c22e787e4c1f53e217cff7cc5a243164d4b2e8410f4b
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
@@ -487,7 +487,7 @@ F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
F ext/recover/recoverslowidx.test c90d59c46bb8924a973ac6fbc38f3163cee38cc240256addcab1cf1a322c37dc
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
F ext/recover/sqlite3recover.c dfbfca5a8e4909333e5aa3749bcffb5dd7e396de9541c338f8cc843b2e20217e
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c 3d0fb1df7823f5bc22a0b93955034d16a2dfa2eb1e443e9a0123a77f120599a3
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
@@ -541,7 +541,7 @@ F ext/session/session8.test 326f3273abf9d5d2d7d559eee8f5994c4ea74a5d935562454605
F ext/session/session9.test 0c4a8fbe7a5031f50855f020f3408e1f07fd7859f1daa1629eadcec3422072d6
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c
F ext/session/sessionC.test 2bd42225efdf5f5b1a20f75b672665bcd4f67e2a6d7ddf7420fe7bf523ba41f8
F ext/session/sessionC.test de98b5e173fd86c79af0d0541534398d2ea75dc0d5d74a00103eb26151b76959
F ext/session/sessionD.test 470ff917dc849e2eb78142ade63aaabd729d773833cff0ff01bca0eda68a21ce
F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
@@ -572,7 +572,7 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3session.c d5c91d5b07d2b8e860f2782ae23f7b44ce929280e00645418ee84a0fd14525b2
F ext/session/sqlite3session.c a75ef1e361ad857518d75184366936beb752f3c2522895dc529c368642eab5a6
F ext/session/sqlite3session.h 063e7bf7be2fff874456f452a224b5b3013b25682d108933b0351c93a1279b9c
F ext/session/test_session.c 2a02a68b522e2f3d4a64b2a4733af54b0f3e500769aeccd5bcbdd440103db069
F ext/wasm/GNUmakefile 68c750f173106d9d63f12c1edf1256c6f4bad9894b155da5db64322f4912de4b
@@ -588,7 +588,7 @@ F ext/wasm/api/README.md a905d5c6bfc3e2df875bd391d6d6b7b48d41b43bdee02ad115b4724
F ext/wasm/api/extern-post-js.c-pp.js 80accc53cc6ea1e61c721595f42ba95baa7c7ea636807d9507e69403301f8c54
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
F ext/wasm/api/opfs-common-inline.c-pp.js 496ca858af09b7fef2efaece467960611d35f57254078424bcdeac42ded9e85d
F ext/wasm/api/opfs-common-shared.c-pp.js d0bff21d34fa05a7eb975c4ee608165f96387332101cb05e976953c77434374d
F ext/wasm/api/opfs-common-shared.c-pp.js 5b5880ced26977931a4fb33aafc6c71206fbee519e82abf9614898d8fa5ec241
F ext/wasm/api/post-js-footer.js a50c1a2c4d008aede7b2aa1f18891a7ee71437c2f415b8aeb3db237ddce2935b
F ext/wasm/api/post-js-header.js f35d2dcf1ab7f22a93d565f8e0b622a2934fc4e743edf3b708e4dd8140eeff55
F ext/wasm/api/pre-js.c-pp.js d6bf82f83f60caa2904bddb95a29cb738b310f672d2796cdc5fe54463ab0d6cd
@@ -657,7 +657,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk 48f6b3557cefd79e5cfae1f15e32d6a0dffd7b689c582a9a7b3920a4ee18affd
F main.mk d9cbbee974a8cd3999430130378878bd87b8c5754397a69ec322f4c9cc3e4e41
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -668,11 +668,11 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
F src/alter.c fc36b19273ffe364aeb4d00ba04bda8798ad7a67fec7a035ee8ee56272e1bdbe
F src/alter.c 7d7ddbdc189f0e0c686e32ee170abdddc95c11f2089e40df4ffcee88f5334826
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
F src/attach.c 7cf07d4fa42b9fc8662237c60c40b730326c30aa90ae5fffc0b18b2d726ebf61
F src/auth.c ebec42df26b34a62b6750d30d9c2c03554a1c522020182476f7729a439fef04f
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
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 216ffbe197e330118a2999adc7d3f09b0e2eeb163df8746ba9a2b27fed3d4335
@@ -685,17 +685,17 @@ F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 1f2268d6fe3c78fc1bf794ba65d7026498b78e2342ffaf85825dedae546e6fde
F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451
F src/expr.c 68400681c5f6e41231d2c85abf6bb432aeeb2e36c4abdf90eb7b78551a5ce0f3
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
F src/func.c 706ac012bf87d8ad7416a56a1d2b1f19e5dea03506a4606a01aa9d3bacf392c7
F src/func.c e6a68dccc9c3c2f638bbf5d29ee84cadd48ded246fbd6c4cc56ddc957e99305f
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
F src/insert.c 77aa90e7ddbebf131c5de504854b5a61c25b11d53580649fb375b23752793651
F src/json.c 5027b856cd9b621dc9ba66b211e21a440ccdc63cefdefb44c51e7d3ac550d1a4
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 78d5b06f18996ffa1203129b28fea043f63a87a4117539678f1d761c30b4ff65
@@ -706,14 +706,14 @@ F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
F src/memdb.c a3feb427cdd4036ea2db0ba56d152f14c8212ca760ccb05fb7aa49ff6b897df3
F src/memdb.c 0a0e827311cec57fdea2ed3142d6684704a1b90e7995b286f74fd7d1a6c5a62c
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
F src/mutex.c 00b8cee206a67fd764d001f3a148494331d8d0b3b9c3974ecd69ff29bb444462
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1
F src/mutex_w32.c e1d317d29cb623667d43de94714264d1e1871cc4bb39fa67dd17048e8138c739
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.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
@@ -721,26 +721,26 @@ F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
F src/os_unix.c a07dce662f6c4e18098f6faa9f7ec7cf311f56ee9151bed2aad4dcd55852c9e2
F src/os_win.c 0d553b6e8b92c8eb85e7f1b4a8036fe8638c8b32c9ad8d9d72a861c10f81b4c5
F src/os_win.h 5e168adf482484327195d10f9c3bce3520f598e04e07ffe62c9c5a8067c1037b
F src/os_win.c 4786b1123beea22a9cd8f8e9d781cc1b4bf4679c56103edbf60a519ce23a2781
F src/os_win.h c06ccc3a090cf54202ea58981c298817f3309d4c9e4d52ad0a02927346493721
F src/pager.c fbec9063ea139dfa5d94ce540671752b89f8e8dc38f8a1f614bab1aa04a2dd40
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y 3b784d6083380a950e3b1b32ce5ddd303e8c7c209d8ab788df2c62aaf9ee8eb3
F src/parse.y 8c8003a932f6f98ac612fd239d3cdc7ca64480f61ca5f4f680c4fe69b1bc68c9
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
F src/printf.c d442fda86ad11da7923dbb354d3761229b5b51dbe06c5c208fa75e3411c79434
F src/printf.c 50be92de0725e88c8b38978775ab46f9b42d74e21f65045c3423503173eb0566
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
F src/resolve.c fcc406bfb055bee9954ee77c023f4a2a66a24bcdf1573516a72280811a269c20
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
F src/shell.c.in 4279e364fd909db808ab8fc46ed06f25e96aaa28726bf6342a9b74bde58bc813
F src/select.c 4c05cde130f26991b7411d8c6809e0630625e18078742c963a047b4b9cc01d49
F src/shell.c.in 51167ca344ac180efcf6339353c11800981bed97f37c9b8d9e940e659b7d181f
F src/sqlite.h.in 39d2e09114d2bdb7afd998f4a469c8f8cd065f8093835a7d0422f260fc78fb4f
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
F src/sqliteInt.h bc1cbc0c23dba35b324ae85a7dbb5fb182321bbd30857fb21f3d0cba049001a5
F src/sqliteInt.h 5071d64ad787d9922e524d834c3fe7b7a11989d29dc6ea25f7944892a43266f4
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -800,9 +800,9 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 377af5da226519a0f374dc3c6d408c9d303a92943e3ae5986432c7d52e6679a2
F src/util.c 98cf12c8ba65623a76c1eb6e6afa98ff40107c9919bf79af42f4bfc70e654232
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
F src/vdbe.c 1cd55e8171e4e87054de196c3c4747d44b69041b5ec910cf547ae82a85beb3e4
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
@@ -817,9 +817,9 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
F src/wal.c 7340d4f9bb827bd349127cac6b2cf0cb7f76b9fda645f7b9b0bf7a6e0b1e2e7c
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c a00d35adeb2550249ba02f24e50eecfb99cba34c8d7d5299b295a591219a2e73
F src/where.c 7241a71725d8c193ddd9e69a299820fcd755943f3b5ac376a84b2716e2848401
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
F src/wherecode.c 676cb6cb02878643e817d9917a2d3522b83a3736b2cedd3dc8a01d7bb92af6c2
F src/wherecode.c 4d573077652f79780d6b50840ab8cbb72053dbb4eb230780dd2a146ab034475d
F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -839,7 +839,7 @@ F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256b
F test/alterauth2.test 4b74fa8f184f4736497317feb587b65759eb87d87acfe3a8ef433d4d18bb002b
F test/altercol.test 3661c432aacb42bc2198dd4611bbb9c3b09fc73251b59edda046109103b8ac00
F test/altercons.test ea18def4a0f26b9066da56095c9c480df705df4d02e4ae151708fae76f7e3884
F test/altercons2.test 3c1f58312817df43aeada3b1827fdc3ce3fc50c6f49a95ef62cf4cbbae8583a0
F test/altercons2.test 4933eadb035fc0ccfc34ed879f69a09051c53907f9dae9c3d36d25f93519ccc7
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
@@ -900,7 +900,7 @@ F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
F test/badutf.test cff75b714866a4ffa0cdda252eb8fe8765483f5872c0076223c92d52b4fffd1b
F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
F test/basexx1.test 4ae6ddbd92a7ebcabb5d844664c3e755d29fb69c8ddcf0c8d59bbe4e07c23919
F test/bc_common.tcl c70b896d1d4ce72f769d2c7c1fc15b2cb07559eb2093f2736c8ca51664b29ff5
@@ -944,6 +944,8 @@ F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1
F test/btreefault.test a82a23b0578bc587afbf9a622c8f54a54f63762f062ba8a35613cfee38ab42f9
F test/busy.test caff7164c16ce06a53af51f9e4c2753d4cc64250e00790a5e48b9c4f4be37597
F test/busy2.test 20823a5d7c42fb257d9f108c66312d90b1bb4ec3d80ba6b4e371073727560f98
F test/c/malloc1.c 2869384011b5dc1f019ddd94e5248a1f2dfd07db06c6ce854793c91da173b811
F test/c/snprintf1.c a66a1ce1195bd409740a60ebeea008686ce3fbacb445840fc0a45419823b7f3f
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
@@ -1098,14 +1100,15 @@ F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650
F test/exclusive2.test cd70b1d9c6fffd336f9795b711dcc5d9ceba133ad3f7001da3fda63615bdc91e
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/existsexpr.test 75c1c13cda18b53f68c135fe644afc034d72a6de5b0774b0219ca4a6dc4b96b0
F test/existsexpr.test 1ce70ac41fb6d52525774388aa23e982428e883a850f9d56d49776d234865552
F test/existsexpr2.test dc23e76389eff3d29f6488ff733012a3560cd67ec8cfaecbecd52cced5d5af11
F test/existsfault.test ff41c11f3052c1bbd4f8dd557802310026253d67d7c4e3a180c16d2f0862973e
F test/expr.test db981f8a85520e99ae20aab7ad2e9b5b0437ed09159b57ced434c672075d2e61
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
F test/exprfault.test da33606d799718e2f8e34efd0e5858884a1ad87f608774c552a7f5517cc27181
F test/exprfault.test 7475e363c7221847855722e9dd2459cf60088f6b172c0c808dba75f89e1704b8
F test/exprfault2.test c49e84273898969af5dbc4fe6a3f4335f14639799f343590336c9ddf84425965
F test/expridx1.test b464520126e1d781a7800f8540621c82e8bbc526f089ff8b0b57ffc51feea6b7
F test/expridx2.test 13348ed208a5d18d9cef7d0a70f8e17948d3c0b5b46508c0573b7e983456165f
F test/extension01.test 5de412c66276105901c370770175003381fdcb0c4da7054fa43cf4a31e0bfa3a
F test/external_reader.test 6fdec43eeca23eb32faad1e95a4d1abc402bc8b3db70df12d6fc08a637f4a2b5
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
@@ -1246,7 +1249,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 207d3d1c1d578928f16dec20df781c5d13c2fd4694b4d70e72242f4dcb799830
F test/fuzzcheck.c 5048a2426bd6968a1b9a00cef7f3aa37442a261df3b532c9e44a1f829bddbede
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1317,7 +1320,7 @@ F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
F test/intck01.sql f2d88bf41cdd64f2ed8c3d4f357cf520f017aa2986999ab9a62eb6506ef18106
F test/interrupt.test ac1ef50ec9ab8e4f0e17c47629f82539d4b22558904e321ed5abea2e6187da7a
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
F test/interrupt2.test 7eaa40a975d950826cd56e6c37f0f0629adfa2d1a8d3333aff0ff7cf86069963
F test/intpkey.test 7d54711acf553cdd641a40e9c6cfc2bf1a76070074940c1b126442517054320f
F test/intreal.test 68829a8bb073ee1610ca3f8f9e0f99b0371fb36e0fa64862dd5ced4ef03c2343
F test/io.test d267fdc8915444a45e19841489033ebe70bb69f6db605b00df70be16b2a80f59
@@ -1421,7 +1424,7 @@ F test/malloctraceviewer.tcl 3e3ddf11e30d2b20f53aa16aa6615082fb24a100bea61cca721
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
F test/memdb1.test c737ac9aa5895092332b1dde24fae7ae494b7fcbcd346d22d600891096a3836d
F test/memdb1.test 413f845c0c2d20dc9808d4084de9e57d55759070eed2a4cf23cd30335a96c295
F test/memdb2.test 4ba1fc09e2f51df80d148a540e4a3fa66d0462e91167b27497084de4d1f6b5b4
F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c
F test/memjournal2.test dbc2c5cb5f7b38950f4f6dc3e73fcecf0fcbed3fc32c7ce913bba164d288da1e
@@ -1490,6 +1493,7 @@ F test/orderbyB.test 32576c7b138105bc72f7fbf33bd320ca3a7d303641fc939e0e56af6cba8
F test/oserror.test ee3fad06ec8671c4d047c2c92a567fc2e0e8161caaec7edd6d48325c5ac97f30
F test/ossfuzz.c b5d232d9717fc999a121c82c4880ae5b9d7fb3ae55d2d87a8da906bc80020906
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/output-redirect-test.txt aeebac99f766f1e54bb2628b13c2d89a3d77de942138a01210c8a814b54c2bc8
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
F test/pager1.test b083c2d5d89df8e979658d9320bfc0b9d50b4ef8ae1d9e115a692ff0b9768393
F test/pager2.test c0ede15952b607f9a38f653acdfa73c19e657958e9104aab1a71950ea7b71831
@@ -1607,7 +1611,7 @@ F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae
F test/selectH.test 0b54599f1917d99568c9b929df22ec6261ed7b6d2f02a46b5945ef81b7871aac
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
F test/sessionfuzz.c f693b8827034a3bed7616d89c65fb4fe8b7ff3c0f000c6ea6beda69b7f1aced3
F test/sessionfuzz.c 0ec813258fbfd222c62ba6867c6a5a015f098fcaa6d89e7e0ee623ea91145cf0
F test/shared.test 50bd8091735b272732125928c363476a17b5fb264835de7d19e90c72055c888b
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F test/shared3.test cb92d083003ddf0f313166e494ec2fcafa55fdebf648628923ded3169dba8850
@@ -1620,13 +1624,13 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell-prompt.sql 5c18599f2b7566172007005206471aefb7e0be593e8f52d37b9ab03a12aa84a6
F test/shell-prompt.sql b062f7778cf5529ccac2e0c07364b8a050c87397706d28ea2240dc5c43e920ac
F test/shell1.test c84eff209f93ad17ccdf7e1634969fc8231684254edeb21d9b13d67c3179cdb5
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
F test/shell5.test a9cd2c8b62e125049ef500937674f47dd6787f0157ac0515aa554044a4dc3ea9
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
F test/shell5.test a0c43d82a811a463a5d07d6418c5a045ab01a072544db8aa31ae394e93845d8d
F test/shell6.test 596f2eb385a1097d4e9130b4d4f663a24cba294b35f13b774b8f13553dec307d
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192
F test/shell9.test c0e8871061a92151450b3332279a893b516fa73a6c46d4f51a0998407cbf8c89
@@ -1667,7 +1671,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
F test/speedtest.md ea0c85ebe0ecff8b45ba6cdb26e694871f469009a5a29dcfe634b055f05ab241
F test/speedtest.tcl b06f6321ef90bb68f18f7b0e430e25203d9da79b80f8926986a0d5f21ac485fb x
F test/speedtest1.c 6c01252e66f46de0b6b8d5316e03521e2151782104f3608c10262aa5dce85721
F test/speedtest1.c f9f30f35431bfc1d3ee9acc561624e0c0b4614071044bc302169dd27206a0fca
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1716,8 +1720,8 @@ F test/temptrigfault.tes fc5918e64f3867156fefe7cfca9d8e1f495134a5229b2b511b0dc11
F test/temptrigger.test a00f258ed8d21a0e8fd4f322f15e8cfb5cef2e43655670e07a753e3fb4769d61
F test/tester.tcl 2d943f60200e0a36bcd3f1f0baf181a751cd3604ef6b6bd4c8dc39b4e8a53116
F test/testloadext.c 862b848783eaed9985fbce46c65cd214664376b549fae252b364d5d1ef350a27
F test/testrunner.tcl 3b6cbceb4d7f0226d51a7fde247cc5592565953568c18155c8c3a454d93bee71 x
F test/testrunner_data.tcl 48c8a230fcada37f4809f95c2ba49e44bc3d520b6165c09173249c6e65b01cc1
F test/testrunner.tcl 6d13732185c13aef87540ebf9daafb8d9657e66f0ac00eb082d93f4749311d4e x
F test/testrunner_data.tcl dfcf192d274e965845189cc014ac89fff91dde92b6e2ac9e1262897fc21ee2e0
F test/testrunner_estwork.tcl 81e2ae10238f50540f42fbf2d94913052a99bfb494b69e546506323f195dcff9
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
@@ -1924,7 +1928,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d2366ef2d3d95249314307861d748924d9ab4f24305541159a08be61ccd4a9ee
F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2
F test/update.test 258dcf26d401177d3cb7fdf0beab14d671dbe72e8ff6e0435fd85a08fcd57bd9
F test/update.test 93fba5f7505f7a7b25d66135d98d9b055b7f1bd627a7e514dbba1ea6213f0c41
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
@@ -2110,7 +2114,7 @@ F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e045
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/build-all-msvc.bat 1ee9dbadcc07fc23268025854e97b392bcbad72376b47aee7b22f3797a4f2c87 x
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
F tool/buildtclext.tcl d09b753d7858314104eeaf5f4def85d35784470279809e47a633f142226f2b3f
F tool/buildtclext.tcl b58df93e772fec8b2ae44ee1a82d13378e13edb1e94c4ab2f7ee3440a9523bff
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca
@@ -2131,7 +2135,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
F tool/lemon.c 3fdc16b23f1ea0c91c049b518fc3f75c71843dbfe2b447fcb3cd92d9e4f219f8
F tool/lempar.c b57e1780bf8098dd4a9a5bba537f994276ea825a420f6165153e5894dc2dfb07
F tool/lempar.c a8de510526f9cbfb45ff0aca9d16f1c828600246f198c1c7d49c8d5492142ffa
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c 63412f9790e5e8538fbde0b4f6db154aaaf80f7a10a01e3c94d14b773a8dd5a6
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
@@ -2178,7 +2182,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 847edc1e0d1e1feb652d3d6128e504456deaf254ab9ad3e7cebd4317d2037182
F tool/sqldiff.c de59a4eecbc802db8ad053889c10e6f8b8427b6f349199ee79938c92c20860dd
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
F tool/sqlite3_rsync.c f510a8b230e1c5b0f62842acd0e94ff15d2f77a00ae782f7d20f9e39919fa19b
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
@@ -2199,8 +2203,11 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P fdba76df2b3a5b4d56ba79f80fd8b16d5faebca1fb07a266262be2ea635e6f94
R 11ac4a0e6010f18fd1adc28138c24819
U drh
Z 0f53747329f642cf306c269a12fd15f3
P 9380be51c76392eca9544f1fd56373406d2ce001e77a8d476deb772968f2aacc
R b0c5fee1261e3ede23c06abcb314461f
T *branch * exists-or-expr-fix
T *sym-exists-or-expr-fix *
T -sym-trunk *
U dan
Z 9ca98967ce2f5b33bad22608c4948005
# Remove this line to create a well-formed Fossil manifest.
+2 -2
View File
@@ -1,2 +1,2 @@
branch analyze-sql-func
tag analyze-sql-func
branch exists-or-expr-fix
tag exists-or-expr-fix
+1 -1
View File
@@ -1 +1 @@
a138e44a243466f8679e9652421f8c893a4a1bc0addc86736588d9aee51cf090
3d197dd03c47a0fb687064131dbf519b8c587a47f9c2bccfdb83d7eae8418336
+3 -1
View File
@@ -2798,7 +2798,9 @@ void sqlite3AlterDropConstraint(
if( !pTab ) return;
if( pCons ){
zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z);
char *z = sqlite3NameFromToken(db, pCons);
zArg = sqlite3MPrintf(db, "%Q", z);
sqlite3DbFree(db, z);
}else{
int iCol;
if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
+11 -2
View File
@@ -106,6 +106,16 @@ static void attachFunc(
** from sqlite3_deserialize() to close database db->init.iDb and
** reopen it as a MemDB */
Btree *pNewBt = 0;
pNew = &db->aDb[db->init.iDb];
assert( pNew->pBt!=0 );
if( sqlite3BtreeTxnState(pNew->pBt)!=SQLITE_TXN_NONE
|| sqlite3BtreeIsInBackup(pNew->pBt)
){
rc = SQLITE_BUSY;
goto attach_error;
}
pVfs = sqlite3_vfs_find("memdb");
if( pVfs==0 ) return;
rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB);
@@ -115,8 +125,7 @@ static void attachFunc(
/* Both the Btree and the new Schema were allocated successfully.
** Close the old db and update the aDb[] slot with the new memdb
** values. */
pNew = &db->aDb[db->init.iDb];
if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt);
sqlite3BtreeClose(pNew->pBt);
pNew->pBt = pNewBt;
pNew->pSchema = pNewSchema;
}else{
+21 -2
View File
@@ -189,8 +189,14 @@ void sqlite3AuthRead(
** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
** is returned, then the error count and error message in pParse are
** modified appropriately.
**
** Divided into two routines. realAuthCheck() does the work. The
** sqlite3AuthCheck() routine is usually a fast no-op but invokes
** realAuthCheck() (and spends time doing some stack pushes and pops
** as a result) in the uncommon case where an authorization check is
** actually needed.
*/
int sqlite3AuthCheck(
static int SQLITE_NOINLINE realAuthCheck(
Parse *pParse,
int code,
const char *zArg1,
@@ -204,7 +210,7 @@ int sqlite3AuthCheck(
** or if the parser is being invoked from within sqlite3_declare_vtab.
*/
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
if( IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
@@ -229,6 +235,19 @@ int sqlite3AuthCheck(
}
return rc;
}
int sqlite3AuthCheck(
Parse *pParse,
int code,
const char *zArg1,
const char *zArg2,
const char *zArg3
){
if( pParse->db->xAuth!=0 && pParse->db->init.busy==0 ){
return realAuthCheck(pParse,code,zArg1,zArg2,zArg3);
}else{
return SQLITE_OK;
}
}
/*
** Push an authorization context. After this routine is called, the
+66 -54
View File
@@ -20,13 +20,13 @@
*/
struct sqlite3_backup {
sqlite3* pDestDb; /* Destination database handle */
Btree *pDest; /* Destination b-tree file */
Db *pDest; /* Destination db file */
u32 iDestSchema; /* Original schema cookie in destination */
int bDestLocked; /* True once a write-transaction is open on pDest */
Pgno iNext; /* Page number of the next source page to copy */
sqlite3* pSrcDb; /* Source database handle */
Btree *pSrc; /* Source b-tree file */
Db *pSrc; /* Source db file */
int rc; /* Backup process error code */
@@ -79,7 +79,7 @@ struct sqlite3_backup {
** function. If an error occurs while doing so, return 0 and write an
** error message to pErrorDb.
*/
static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
static Db *findDatabase(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
int i = sqlite3FindDbName(pDb, zDb);
if( i==1 ){
@@ -102,7 +102,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
return 0;
}
return pDb->aDb[i].pBt;
return &pDb->aDb[i];
}
/*
@@ -110,9 +110,9 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
** of the source.
*/
static int setDestPgsz(sqlite3_backup *p){
int rc;
rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
return rc;
return sqlite3BtreeSetPageSize(p->pDest->pBt,
sqlite3BtreeGetPageSize(p->pSrc->pBt), 0, 0
);
}
/*
@@ -181,15 +181,15 @@ sqlite3_backup *sqlite3_backup_init(
/* If the allocation succeeded, populate the new object. */
if( p ){
p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
p->pSrc = findDatabase(pDestDb, pSrcDb, zSrcDb);
p->pDest = findDatabase(pDestDb, pDestDb, zDestDb);
p->pDestDb = pDestDb;
p->pSrcDb = pSrcDb;
p->iNext = 1;
p->isAttached = 0;
if( 0==p->pSrc || 0==p->pDest
|| checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
|| checkReadTransaction(pDestDb, p->pDest->pBt)!=SQLITE_OK
){
/* One (or both) of the named databases did not exist or an OOM
** error was hit. Or there is a transaction open on the destination
@@ -201,7 +201,7 @@ sqlite3_backup *sqlite3_backup_init(
}
}
if( p ){
p->pSrc->nBackup++;
p->pSrc->pBt->nBackup++;
}
sqlite3_mutex_leave(pDestDb->mutex);
@@ -229,18 +229,18 @@ static int backupOnePage(
const u8 *zSrcData, /* Source database page data */
int bUpdate /* True for an update, false otherwise */
){
Pager * const pDestPager = sqlite3BtreePager(p->pDest);
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
Pager * const pDestPager = sqlite3BtreePager(p->pDest->pBt);
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc->pBt);
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest->pBt);
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
int rc = SQLITE_OK;
i64 iOff;
assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
assert( sqlite3BtreeGetReserveNoMutex(p->pSrc->pBt)>=0 );
assert( p->bDestLocked );
assert( !isFatalError(p->rc) );
assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt->pBt) );
assert( zSrcData );
assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 );
@@ -251,7 +251,7 @@ static int backupOnePage(
for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
DbPage *pDestPg = 0;
Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt->pBt) ) continue;
if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
&& SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
){
@@ -269,7 +269,7 @@ static int backupOnePage(
memcpy(zOut, zIn, nCopy);
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
if( iOff==0 && bUpdate==0 ){
sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc->pBt));
}
}
sqlite3PagerUnref(pDestPg);
@@ -301,8 +301,8 @@ static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
*/
static void attachBackupObject(sqlite3_backup *p){
sqlite3_backup **pp;
assert( sqlite3BtreeHoldsMutex(p->pSrc) );
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
assert( sqlite3BtreeHoldsMutex(p->pSrc->pBt) );
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc->pBt));
p->pNext = *pp;
*pp = p;
p->isAttached = 1;
@@ -316,20 +316,26 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
int destMode; /* Destination journal mode */
int pgszSrc = 0; /* Source page size */
int pgszDest = 0; /* Destination page size */
Btree *pDest;
Btree *pSrc;
#ifdef SQLITE_ENABLE_API_ARMOR
if( p==0 ) return SQLITE_MISUSE_BKPT;
#endif
assert( p->pDest );
assert( p->pSrc );
pDest = p->pDest->pBt;
pSrc = p->pSrc->pBt;
sqlite3_mutex_enter(p->pSrcDb->mutex);
sqlite3BtreeEnter(p->pSrc);
sqlite3BtreeEnter(pSrc);
if( p->pDestDb ){
sqlite3_mutex_enter(p->pDestDb->mutex);
}
rc = p->rc;
if( !isFatalError(rc) ){
Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
Pager * const pSrcPager = sqlite3BtreePager(pSrc); /* Source pager */
Pager * const pDestPager = sqlite3BtreePager(pDest); /* Dest pager */
int ii; /* Iterator variable */
int nSrcPage = -1; /* Size of source db in pages */
int bCloseTrans = 0; /* True if src db requires unlocking */
@@ -337,7 +343,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* If the source pager is currently in a write-transaction, return
** SQLITE_BUSY immediately.
*/
if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
if( p->pDestDb && pSrc->pBt->inTransaction==TRANS_WRITE ){
rc = SQLITE_BUSY;
}else{
rc = SQLITE_OK;
@@ -347,8 +353,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
*/
if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(pSrc) ){
rc = sqlite3BtreeBeginTrans(pSrc, 0, 0);
bCloseTrans = 1;
}
@@ -364,7 +370,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Lock the destination database, if it is not locked already. */
if( SQLITE_OK==rc && p->bDestLocked==0
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(pDest, 2,
(int*)&p->iDestSchema))
){
p->bDestLocked = 1;
@@ -372,9 +378,9 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Do not allow backup if the destination database is in WAL mode
** and the page sizes are different between source and destination */
pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
pgszDest = sqlite3BtreeGetPageSize(p->pDest);
destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
pgszSrc = sqlite3BtreeGetPageSize(pSrc);
pgszDest = sqlite3BtreeGetPageSize(pDest);
destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(pDest));
if( SQLITE_OK==rc
&& (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
&& pgszSrc!=pgszDest
@@ -385,11 +391,11 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Now that there is a read-lock on the source database, query the
** source pager for the number of pages in the database.
*/
nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
nSrcPage = (int)sqlite3BtreeLastPage(pSrc);
assert( nSrcPage>=0 );
for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
const Pgno iSrcPg = p->iNext; /* Source page number */
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
if( iSrcPg!=PENDING_BYTE_PAGE(pSrc->pBt) ){
DbPage *pSrcPg; /* Source page object */
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY);
if( rc==SQLITE_OK ){
@@ -416,18 +422,18 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
*/
if( rc==SQLITE_DONE ){
if( nSrcPage==0 ){
rc = sqlite3BtreeNewDb(p->pDest);
rc = sqlite3BtreeNewDb(pDest);
nSrcPage = 1;
}
if( rc==SQLITE_OK || rc==SQLITE_DONE ){
rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
rc = sqlite3BtreeUpdateMeta(pDest,1,p->iDestSchema+1);
}
if( rc==SQLITE_OK ){
if( p->pDestDb ){
sqlite3ResetAllSchemasOfConnection(p->pDestDb);
}
if( destMode==PAGER_JOURNALMODE_WAL ){
rc = sqlite3BtreeSetVersion(p->pDest, 2);
rc = sqlite3BtreeSetVersion(pDest, 2);
}
}
if( rc==SQLITE_OK ){
@@ -444,12 +450,12 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** journalled by PagerCommitPhaseOne() before they are destroyed
** by the file truncation.
*/
assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
assert( pgszSrc==sqlite3BtreeGetPageSize(pSrc) );
assert( pgszDest==sqlite3BtreeGetPageSize(pDest) );
if( pgszSrc<pgszDest ){
int ratio = pgszDest/pgszSrc;
nDestTruncate = (nSrcPage+ratio-1)/ratio;
if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
if( nDestTruncate==(int)PENDING_BYTE_PAGE(pDest->pBt) ){
nDestTruncate--;
}
}else{
@@ -477,7 +483,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
assert( pFile );
assert( nDestTruncate==0
|| (i64)nDestTruncate*(i64)pgszDest >= iSize || (
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
nDestTruncate==(int)(PENDING_BYTE_PAGE(pDest->pBt)-1)
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
));
@@ -489,7 +495,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** journal file. */
sqlite3PagerPagecount(pDestPager, &nDstPage);
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
if( iPg!=PENDING_BYTE_PAGE(pDest->pBt) ){
DbPage *pPg;
rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0);
if( rc==SQLITE_OK ){
@@ -533,7 +539,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Finish committing the transaction to the destination database. */
if( SQLITE_OK==rc
&& SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
&& SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(pDest, 0))
){
rc = SQLITE_DONE;
}
@@ -547,8 +553,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
*/
if( bCloseTrans ){
TESTONLY( int rc2 );
TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(pSrc, 0);
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(pSrc, 0);
assert( rc2==SQLITE_OK );
}
@@ -560,7 +566,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
if( p->pDestDb ){
sqlite3_mutex_leave(p->pDestDb->mutex);
}
sqlite3BtreeLeave(p->pSrc);
sqlite3BtreeLeave(pSrc);
sqlite3_mutex_leave(p->pSrcDb->mutex);
return rc;
}
@@ -577,17 +583,17 @@ int sqlite3_backup_finish(sqlite3_backup *p){
if( p==0 ) return SQLITE_OK;
pSrcDb = p->pSrcDb;
sqlite3_mutex_enter(pSrcDb->mutex);
sqlite3BtreeEnter(p->pSrc);
sqlite3BtreeEnter(p->pSrc->pBt);
if( p->pDestDb ){
sqlite3_mutex_enter(p->pDestDb->mutex);
}
/* Detach this backup from the source pager. */
if( p->pDestDb ){
p->pSrc->nBackup--;
p->pSrc->pBt->nBackup--;
}
if( p->isAttached ){
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc->pBt));
assert( pp!=0 );
while( *pp!=p ){
pp = &(*pp)->pNext;
@@ -597,7 +603,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
}
/* If a transaction is still open on the Btree, roll it back. */
sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
sqlite3BtreeRollback(p->pDest->pBt, SQLITE_OK, 0);
/* Set the error code of the destination database handle. */
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
@@ -607,7 +613,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
/* Exit the mutexes and free the backup context structure. */
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
}
sqlite3BtreeLeave(p->pSrc);
sqlite3BtreeLeave(p->pSrc->pBt);
if( p->pDestDb ){
/* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
** call to sqlite3_backup_init() and is destroyed by a call to
@@ -665,7 +671,7 @@ static SQLITE_NOINLINE void backupUpdate(
){
assert( p!=0 );
do{
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
assert( sqlite3_mutex_held(p->pSrc->pBt->pBt->mutex) );
if( !isFatalError(p->rc) && iPage<p->iNext ){
/* The backup process p has already copied page iPage. But now it
** has been modified by a transaction on the source pager. Copy
@@ -701,7 +707,7 @@ void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
void sqlite3BackupRestart(sqlite3_backup *pBackup){
sqlite3_backup *p; /* Iterator variable */
for(p=pBackup; p; p=p->pNext){
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
assert( sqlite3_mutex_held(p->pSrc->pBt->pBt->mutex) );
p->iNext = 1;
}
}
@@ -719,6 +725,8 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
int rc;
sqlite3_file *pFd; /* File descriptor for database pTo */
sqlite3_backup b;
Db dbDest;
Db dbSrc;
sqlite3BtreeEnter(pTo);
sqlite3BtreeEnter(pFrom);
@@ -737,9 +745,13 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
** from this function, not directly by the user.
*/
memset(&b, 0, sizeof(b));
memset(&dbDest, 0, sizeof(dbDest));
memset(&dbSrc, 0, sizeof(dbSrc));
dbDest.pBt = pTo;
dbSrc.pBt = pFrom;
b.pSrcDb = pFrom->db;
b.pSrc = pFrom;
b.pDest = pTo;
b.pSrc = &dbSrc;
b.pDest = &dbDest;
b.iNext = 1;
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
@@ -755,7 +767,7 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
if( rc==SQLITE_OK ){
pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
}else{
sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
sqlite3PagerClearCache(sqlite3BtreePager(pTo));
}
assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
+6 -3
View File
@@ -915,6 +915,7 @@ void sqlite3GenerateRowIndexDelete(
v = pParse->pVdbe;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
int p3 = 0;
assert( iIdxCur+i!=iDataCur || pPk==pIdx );
if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
if( pIdx==pPk ) continue;
@@ -922,10 +923,12 @@ void sqlite3GenerateRowIndexDelete(
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
&iPartIdxLabel, pPrior, r1);
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn
);
if( pIdx->bHasExpr && aRegIdx ){
p3 = aRegIdx[i];
}
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, p3);
sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
sqlite3VdbeChangeP5(v, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
pPrior = pIdx;
}
+29 -12
View File
@@ -130,13 +130,17 @@ static void lengthFunc(
case SQLITE_TEXT: {
const unsigned char *z = sqlite3_value_text(argv[0]);
const unsigned char *z0;
unsigned char c;
if( z==0 ) return;
z0 = z;
while( (c = *z)!=0 ){
z++;
if( c>=0xc0 ){
while( (*z & 0xc0)==0x80 ){ z++; z0++; }
while( 1 /*exit-by-break*/ ){
/* vvvvvv---- See tag-20260418-01 */
if( (u8)(z[0]-1)<(0x80-1) ){
z++;
}else if( z[0]==0 ){
break;
}else{
z++;
while( (z[0]&0xc0)==0x80 ){ z++; z0++; }
}
}
sqlite3_result_int(context, (int)(z-z0));
@@ -415,12 +419,25 @@ static void substrFunc(
}
assert( p1>=0 && p2>=0 );
if( p0type!=SQLITE_BLOB ){
while( *z && p1 ){
SQLITE_SKIP_UTF8(z);
p1--;
for( ; p1>0; p1--){
/* vvvvvv---- See tag-20260418-01 */
if( (u8)(z[0]-1)<(0x80-1) ){
z++;
}else if( z[0]==0 ){
break;
}else{
do{ z++; }while( (z[0]&0xc0)==0x80 );
}
}
for(z2=z; *z2 && p2; p2--){
SQLITE_SKIP_UTF8(z2);
for(z2=z; p2>0; p2--){
/* vvvvvv---- See tag-20260418-01 */
if( (u8)(z2[0]-1)<(0x80-1) ){
z2++;
}else if( z2[0]==0 ){
break;
}else{
do{ z2++; }while( (z2[0]&0xc0)==0x80 );
}
}
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
SQLITE_UTF8);
@@ -3106,7 +3123,7 @@ static void filestatFunc(
assert( pPager!=0 );
fd = sqlite3PagerFile(pPager);
pStr = sqlite3_str_new(db);
if( pStr==0 ){
if( sqlite3_str_errcode(pStr) ){
sqlite3_result_error_nomem(context);
}else{
sqlite3_str_append(pStr, "{\"db\":", 6);
@@ -3209,7 +3226,7 @@ static void parseuriFunc(
flgs = (unsigned int)sqlite3_value_int(argv[1]);
rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
pResult = sqlite3_str_new(0);
if( pResult ){
if( !sqlite3_str_errcode(pResult) ){
int i;
sqlite3_str_appendf(pResult, "rc=%d", rc);
sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
+4 -1
View File
@@ -2809,7 +2809,10 @@ void sqlite3CompleteInsertion(
|| pIdx->pNext==0
|| pIdx->pNext->onError==OE_Replace );
if( aRegIdx[i]==0 ) continue;
if( pIdx->pPartIdxWhere ){
if( pIdx->pPartIdxWhere || (update_flags && pIdx->bHasExpr) ){
/* If this is a partial index, or an UPDATE of an index on an
** expression, then the record register may be set to NULL to indicate
** that no record should be inserted into this index. */
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
}
+3 -4
View File
@@ -876,10 +876,10 @@ int sqlite3_deserialize(
if( rc ) goto end_deserialize;
db->init.iDb = (u8)iDb;
db->init.reopenMemdb = 1;
rc = sqlite3_step(pStmt);
sqlite3_step(pStmt);
db->init.reopenMemdb = 0;
if( rc!=SQLITE_DONE ){
rc = SQLITE_ERROR;
rc = sqlite3_finalize(pStmt);
if( rc!=SQLITE_OK ){
goto end_deserialize;
}
p = memdbFromDbSchema(db, zSchema);
@@ -900,7 +900,6 @@ int sqlite3_deserialize(
}
end_deserialize:
sqlite3_finalize(pStmt);
if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
sqlite3_free(pData);
}
+35 -16
View File
@@ -35,8 +35,15 @@
# define SQLITE_MUTEX_NREF 0
#endif
#if GCC_VERSION>0
# define ALIGN128 __attribute__((aligned(128)))
#else
# define ALIGN128
#endif
/*
** Each recursive mutex is an instance of the following structure.
** Each SQLite mutex is an instance of the following structure.
**
*/
struct sqlite3_mutex {
pthread_mutex_t mutex; /* Mutex controlling the lock */
@@ -151,19 +158,31 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
** the same type number.
*/
static sqlite3_mutex *pthreadMutexAlloc(int iType){
static sqlite3_mutex staticMutexes[] = {
SQLITE3_MUTEX_INITIALIZER(2),
SQLITE3_MUTEX_INITIALIZER(3),
SQLITE3_MUTEX_INITIALIZER(4),
SQLITE3_MUTEX_INITIALIZER(5),
SQLITE3_MUTEX_INITIALIZER(6),
SQLITE3_MUTEX_INITIALIZER(7),
SQLITE3_MUTEX_INITIALIZER(8),
SQLITE3_MUTEX_INITIALIZER(9),
SQLITE3_MUTEX_INITIALIZER(10),
SQLITE3_MUTEX_INITIALIZER(11),
SQLITE3_MUTEX_INITIALIZER(12),
SQLITE3_MUTEX_INITIALIZER(13)
/* Static mutexes - those with IDs of 2 or more...
**
** The ALIGN128 macro attempts to force 128-byte alignment on mutexes,
** so that adjacent mutex objects are always on different cache lines
** in the CPU. This is CPU-dependent, of course, but 128-byte alignment
** seems to work well for all contemporary processors. Experiments show
** that 64 works just as well most of the time, but the internet says
** that 128-byte alignment works better.
*/
static ALIGN128 union staticMutex {
sqlite3_mutex m;
char aSpacer[128];
} aMutex[] = {
{ .m = SQLITE3_MUTEX_INITIALIZER(2) },
{ .m = SQLITE3_MUTEX_INITIALIZER(3) },
{ .m = SQLITE3_MUTEX_INITIALIZER(4) },
{ .m = SQLITE3_MUTEX_INITIALIZER(5) },
{ .m = SQLITE3_MUTEX_INITIALIZER(6) },
{ .m = SQLITE3_MUTEX_INITIALIZER(7) },
{ .m = SQLITE3_MUTEX_INITIALIZER(8) },
{ .m = SQLITE3_MUTEX_INITIALIZER(9) },
{ .m = SQLITE3_MUTEX_INITIALIZER(10) },
{ .m = SQLITE3_MUTEX_INITIALIZER(11) },
{ .m = SQLITE3_MUTEX_INITIALIZER(12) },
{ .m = SQLITE3_MUTEX_INITIALIZER(13) },
};
sqlite3_mutex *p;
switch( iType ){
@@ -200,12 +219,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
}
default: {
#ifdef SQLITE_ENABLE_API_ARMOR
if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){
if( iType-2<0 || iType-2>=ArraySize(aMutex) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
p = &staticMutexes[iType-2];
p = &aMutex[iType-2].m;
break;
}
}
+87 -94
View File
@@ -31,11 +31,29 @@
*/
#ifdef SQLITE_MUTEX_W32
#if MSVC_VERSION>0
# define ALIGN128 __declspec(align(128))
#else
# define ALIGN128
#endif
#pragma warning(push)
#pragma warning(disable: 4324)
/*
** Each recursive mutex is an instance of the following structure.
** Each SQLite mutex is an instance of the following structure.
**
** The ALIGN128 macro attempts to force 128-byte alignment on mutexes,
** so that adjacent mutex objects are always on different cache lines
** in the CPU. This is CPU-dependent, of course, but 128-byte alignment
** seems to work well for all contemporary processors. Experiments show
** that 64 works just as well most of the time, but the internet says
** that 128-byte alignment works better.
*/
struct sqlite3_mutex {
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
struct sqlite3_mutex {
union {
CRITICAL_SECTION cs; /* The CRITICAL_SECTION mutex. id==1 */
SRWLOCK srwl; /* The Slim reader/writer lock. id!=1 */
} u;
int id; /* Mutex type */
#ifdef SQLITE_DEBUG
volatile int nRef; /* Number of entrances */
@@ -43,20 +61,7 @@ struct sqlite3_mutex {
volatile LONG trace; /* True to trace changes */
#endif
};
/*
** These are the initializer values used when declaring a "static" mutex
** on Win32. It should be noted that all mutexes require initialization
** on the Win32 platform.
*/
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
#ifdef SQLITE_DEBUG
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \
0L, (DWORD)0, 0 }
#else
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }
#endif
#pragma warning(pop)
#ifdef SQLITE_DEBUG
/*
@@ -67,13 +72,8 @@ static int winMutexHeld(sqlite3_mutex *p){
return p->nRef!=0 && p->owner==GetCurrentThreadId();
}
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
return p->nRef==0 || p->owner!=tid;
}
static int winMutexNotheld(sqlite3_mutex *p){
DWORD tid = GetCurrentThreadId();
return winMutexNotheld2(p, tid);
return p->nRef==0 || p->owner!=GetCurrentThreadId();
}
#endif
@@ -95,41 +95,42 @@ void sqlite3MemoryBarrier(void){
}
/*
** Initialize and deinitialize the mutex subsystem.
** Static mutexes.
**
** The ALIGN128 macro on the static mutex array forces 128-byte alignment
** on the mutexes so that adjacent mutex objects are always on different
** cache lines in the CPU. This is CPU-dependent, of course, but 128-byte
** alignment seems to work well for all contemporary processors.
** Experiments show that 64 works just as well most of the time, but
** the internet says that 128-byte alignment works better.
*/
static sqlite3_mutex winMutex_staticMutexes[] = {
SQLITE3_MUTEX_INITIALIZER(2),
SQLITE3_MUTEX_INITIALIZER(3),
SQLITE3_MUTEX_INITIALIZER(4),
SQLITE3_MUTEX_INITIALIZER(5),
SQLITE3_MUTEX_INITIALIZER(6),
SQLITE3_MUTEX_INITIALIZER(7),
SQLITE3_MUTEX_INITIALIZER(8),
SQLITE3_MUTEX_INITIALIZER(9),
SQLITE3_MUTEX_INITIALIZER(10),
SQLITE3_MUTEX_INITIALIZER(11),
SQLITE3_MUTEX_INITIALIZER(12),
SQLITE3_MUTEX_INITIALIZER(13)
};
static ALIGN128 union staticMutexes {
sqlite3_mutex m;
char spacer[128];
} aWindowsMutex[12];
static int winMutex_isInit = 0;
static int winMutex_isNt = -1; /* <0 means "need to query" */
/* As the winMutexInit() and winMutexEnd() functions are called as part
** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
** "interlocked" magic used here is probably not strictly necessary.
*/
static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
static LONG volatile winMutex_lock = 0;
int sqlite3_win32_is_nt(void); /* os_win.c */
void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
static int winMutexInit(void){
/* The first to increment to 1 does actual initialization */
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
int i;
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
for(i=0; i<ArraySize(aWindowsMutex); i++){
sqlite3_mutex *p = &aWindowsMutex[i].m;
p->id = i+2;
InitializeSRWLock(&p->u.srwl);
#ifdef SQLITE_DEBUG
p->nRef = 0;
p->owner = 0;
p->trace = 0;
#endif
}
winMutex_isInit = 1;
}else{
@@ -147,10 +148,6 @@ static int winMutexEnd(void){
** (which should be the last to shutdown.) */
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
if( winMutex_isInit==1 ){
int i;
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
}
winMutex_isInit = 0;
}
}
@@ -219,18 +216,22 @@ static sqlite3_mutex *winMutexAlloc(int iType){
p->trace = 1;
#endif
#endif
InitializeCriticalSection(&p->mutex);
if( iType==SQLITE_MUTEX_RECURSIVE ){
InitializeCriticalSection(&p->u.cs);
}else{
InitializeSRWLock(&p->u.srwl);
}
}
break;
}
default: {
#ifdef SQLITE_ENABLE_API_ARMOR
if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
if( iType-2<0 || iType-2>=ArraySize(aWindowsMutex) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
p = &winMutex_staticMutexes[iType-2];
p = &aWindowsMutex[iType-2].m;
#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
InterlockedCompareExchange(&p->trace, 1, 0);
@@ -252,8 +253,10 @@ static sqlite3_mutex *winMutexAlloc(int iType){
static void winMutexFree(sqlite3_mutex *p){
assert( p );
assert( p->nRef==0 && p->owner==0 );
if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
DeleteCriticalSection(&p->mutex);
if( p->id==SQLITE_MUTEX_FAST ){
sqlite3_free(p);
}else if( p->id==SQLITE_MUTEX_RECURSIVE ){
DeleteCriticalSection(&p->u.cs);
sqlite3_free(p);
}else{
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -274,67 +277,56 @@ static void winMutexFree(sqlite3_mutex *p){
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
DWORD tid = GetCurrentThreadId();
#endif
assert( p );
#ifdef SQLITE_DEBUG
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
#else
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
#endif
assert( winMutex_isInit==1 );
EnterCriticalSection(&p->mutex);
if( p->id==SQLITE_MUTEX_RECURSIVE ){
EnterCriticalSection(&p->u.cs);
}else{
AcquireSRWLockExclusive(&p->u.srwl);
}
#ifdef SQLITE_DEBUG
assert( p->nRef>0 || p->owner==0 );
p->owner = tid;
p->owner = GetCurrentThreadId();
p->nRef++;
if( p->trace ){
OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
tid, p->id, p, p->trace, p->nRef));
GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
}
#endif
}
static int winMutexTry(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
DWORD tid = GetCurrentThreadId();
#endif
int rc = SQLITE_BUSY;
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
/*
** The sqlite3_mutex_try() routine is very rarely used, and when it
** is used it is merely an optimization. So it is OK for it to always
** The sqlite3_mutex_try() routine is seldom used, and when it is
** used it is merely an optimization. So it is OK for it to always
** fail.
**
** The TryEnterCriticalSection() interface is only available on WinNT.
** And some windows compilers complain if you try to use it without
** first doing some #defines that prevent SQLite from building on Win98.
** For that reason, we will omit this optimization for now. See
** ticket #2685.
*/
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
assert( winMutex_isInit==1 );
assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
if( winMutex_isNt<0 ){
winMutex_isNt = sqlite3_win32_is_nt();
if( p->id==SQLITE_MUTEX_RECURSIVE ){
rc = TryEnterCriticalSection(&p->u.cs);
}else{
rc = TryAcquireSRWLockExclusive(&p->u.srwl);
}
assert( winMutex_isNt==0 || winMutex_isNt==1 );
if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
if( rc ){
#ifdef SQLITE_DEBUG
p->owner = tid;
p->owner = GetCurrentThreadId();
p->nRef++;
#endif
rc = SQLITE_OK;
}else{
rc = SQLITE_BUSY;
}
#else
UNUSED_PARAMETER(p);
#endif
#ifdef SQLITE_DEBUG
if( p->trace ){
OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
OSTRACE((
"TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
GetCurrentThreadId(), p->id, p, p->trace, p->owner, p->nRef,
sqlite3ErrName(rc)));
}
#endif
return rc;
@@ -347,23 +339,24 @@ static int winMutexTry(sqlite3_mutex *p){
** is not currently allocated. SQLite will never do either.
*/
static void winMutexLeave(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
DWORD tid = GetCurrentThreadId();
#endif
assert( p );
#ifdef SQLITE_DEBUG
assert( p->nRef>0 );
assert( p->owner==tid );
assert( p->owner==GetCurrentThreadId() );
p->nRef--;
if( p->nRef==0 ) p->owner = 0;
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
#endif
assert( winMutex_isInit==1 );
LeaveCriticalSection(&p->mutex);
if( p->id==SQLITE_MUTEX_RECURSIVE ){
LeaveCriticalSection(&p->u.cs);
}else{
ReleaseSRWLockExclusive(&p->u.srwl);
}
#ifdef SQLITE_DEBUG
if( p->trace ){
OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
tid, p->id, p, p->trace, p->nRef));
GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
}
#endif
}
+317 -1553
View File
File diff suppressed because it is too large Load Diff
+1 -43
View File
@@ -27,53 +27,11 @@
# include <errno.h> /* amalgamator: dontcache */
#endif
/*
** Determine if we are dealing with Windows NT.
**
** We ought to be able to determine if we are compiling for Windows 9x or
** Windows NT using the _WIN32_WINNT macro as follows:
**
** #if defined(_WIN32_WINNT)
** # define SQLITE_OS_WINNT 1
** #else
** # define SQLITE_OS_WINNT 0
** #endif
**
** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
** it ought to, so the above test does not work. We'll just assume that
** everything is Windows NT unless the programmer explicitly says otherwise
** by setting SQLITE_OS_WINNT to 0.
*/
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
# define SQLITE_OS_WINNT 1
#endif
/*
** Determine if we are dealing with Windows CE - which has a much reduced
** API.
*/
#if defined(_WIN32_WCE)
# define SQLITE_OS_WINCE 1
#else
# define SQLITE_OS_WINCE 0
#endif
/*
** For WinCE, some API function parameters do not appear to be declared as
** volatile.
*/
#if SQLITE_OS_WINCE
# define SQLITE_WIN32_VOLATILE
#else
# define SQLITE_WIN32_VOLATILE volatile
#endif
/*
** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
** functions are not available (e.g. those not using MSVC, Cygwin, etc).
*/
#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && \
SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
#if SQLITE_OS_WIN && SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
# define SQLITE_OS_WIN_THREADS 1
#else
# define SQLITE_OS_WIN_THREADS 0
+1
View File
@@ -1476,6 +1476,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0);
if( A ){
A->x.pList = pList;
sqlite3ExprSetHeightAndFlags(pParse, A);
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
+1 -1
View File
@@ -1322,7 +1322,7 @@ void sqlite3_str_reset(StrAccum *p){
** of its content, all in one call.
*/
void sqlite3_str_free(sqlite3_str *p){
if( p ){
if( p!=0 && p!=&sqlite3OomStr ){
sqlite3_str_reset(p);
sqlite3_free(p);
}
+1 -3
View File
@@ -836,9 +836,7 @@ lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pParse->db->xAuth
&& (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
){
if( db->xAuth && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) ){
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
}
#endif
+1 -1
View File
@@ -7324,6 +7324,7 @@ static SQLITE_NOINLINE void existsToJoin(
&& !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
&& ALWAYS(p->pSrc!=0)
&& p->pSrc->nSrc<BMS
&& (p->pLimit==0 || p->pLimit->pRight==0)
){
if( pWhere->op==TK_AND ){
Expr *pRight = pWhere->pRight;
@@ -7371,7 +7372,6 @@ static SQLITE_NOINLINE void existsToJoin(
sqlite3TreeViewSelect(0, p, 0);
}
#endif
existsToJoin(pParse, p, pSubWhere);
}
}
}
+544 -130
View File
File diff suppressed because it is too large Load Diff
+52 -1
View File
@@ -202,7 +202,7 @@
#include "sqlite3.h"
/*
** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory.
** Reuse the STATIC_VFS1 for mutex access to sqlite3_temp_directory.
*/
#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1
@@ -4612,6 +4612,57 @@ Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
**
** # Dividing malformed UTF-8 into characters (tag-20260418-01)
**
** If a text input is malformed UTF-8, SQLite does not make any guarantees
** about how the bytes are divided up into characters. The system promises
** to not overflow an array or cause other memory errors when presented
** with malformed UTF-8. And it promises to preserve the specific
** sequence of bytes as long as no conversion occur. But beyond that,
** there are no guarantees. Results can vary from one version to the
** next.
**
** The SQLITE_SKIP_UTF8 macro below is one technique for dividing UTF-8
** into characters. The length() and substr() SQL functions use a
** different technique when searching across multiple characters, a
** technique that exchanges a subtraction for comparison of z and results
** in faster machine code on some compilers and architectures. The code
** in substr() to skip over p1 characters goes something like this:
**
** for( ; p1>0; p1--){
** // vvvv--- tag-20260418-01
** if( (u8)(z[0]-1)<(0x80-1) ){
** z++;
** }else if( z[0]==0 ){
** break;
** }else{
** do{ z++; }while( (z[0]&0xc0)==0x80 );
** }
** }
**
** In valid UTF-8, multibyte characters always begin with a byte with the
** two most significant bits set and that is followed by one or more bytes
** for which the two most significant bits are 10. In other words:
**
** First byte: (BYTE & 0xc0)==0xc0
** Following bytes: (BYTE & 0xc0)==0x80
**
** What to do if the input byte sequence contain a "following byte" that
** is not preceded by a "first byte"? How many characters are in the
** byte sequence: 0x61 0x81 0x82 0x7a? 3 or 4 or something else?
**
** If you use the macro below, the answer will be 4. If you use the code
** snippet demonstrated at tag-20260418-01, then answer is 3. If you
** use a variant of tag-20260418-01 where the constant of comparison is
** 0xc0-1 instead of 0x80-1 then the answer is again 4. The key point is
** that because the input is malformed UTF-8, so is no "correct" answer.
** SQLite is free to use either value.
**
** It turns out that GCC 13.3.0 is able to generate faster code (at least
** on x86-64) if the constant at tag-20260418-01 is (0x80-1). If you make
** that constant (0xc0-1) instead, gcc 13.3.0 generates code that runs slower.
** So the (0x80-1) constant is used for substr() and length().
*/
#define SQLITE_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
+13 -8
View File
@@ -465,15 +465,20 @@ u8 sqlite3StrIHash(const char *z){
return h;
}
#if !defined(SQLITE_DISABLE_INTRINSIC) \
&& (defined(__GNUC__) || defined(__clang__)) \
&& (defined(__x86_64__) || defined(__aarch64__) || \
(defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen>32)))
#define SQLITE_USE_UINT128
#endif
/*
** Two inputs are multiplied to get a 128-bit result. Write the
** lower 64-bits of the result into *pLo, and return the high-order
** 64 bits.
*/
static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
#if (defined(__GNUC__) || defined(__clang__)) \
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
&& !defined(SQLITE_DISABLE_INTRINSIC)
#if defined(SQLITE_USE_UINT128)
__uint128_t r = (__uint128_t)a * b;
*pLo = (u64)r;
return (u64)(r>>64);
@@ -507,9 +512,7 @@ static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
** The lower 64 bits of A*B are discarded.
*/
static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
#if (defined(__GNUC__) || defined(__clang__)) \
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
&& !defined(SQLITE_DISABLE_INTRINSIC)
#if defined(SQLITE_USE_UINT128)
__uint128_t r = (__uint128_t)a * b;
r += ((__uint128_t)aLo * b) >> 32;
*pLo = (r>>32)&0xffffffff;
@@ -547,6 +550,8 @@ static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
#endif
}
#undef SQLITE_USE_UINT128
/*
** Return a u64 with the N-th bit set.
*/
@@ -785,7 +790,7 @@ static double sqlite3Fp10Convert2(u64 d, int p){
u64 pwr10h, x, hi, lo, sticky, u, m;
double r;
if( p<POWERSOF10_FIRST ) return 0.0;
if( p>POWERSOF10_LAST ) return INFINITY;
if( p>POWERSOF10_LAST ) return (double)INFINITY;
b = 64 - countLeadingZeros(d);
lp = pwr10to2(p);
e = 53 - b - lp;
@@ -815,7 +820,7 @@ static double sqlite3Fp10Convert2(u64 d, int p){
e -= adj;
}
m = (u + 1 + ((u>>2)&1)) >> 2;
if( e<=(-972) ) return INFINITY;
if( e<=(-972) ) return (double)INFINITY;
if((m & U64_BIT(52)) != 0){
m = (m & ~U64_BIT(52)) | ((u64)(1075-e)<<52);
}
+52 -7
View File
@@ -708,7 +708,6 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){
return h;
}
/*
** For OP_Column, factor out the case where content is loaded from
** overflow pages, so that the code to implement this case is separate
@@ -794,6 +793,40 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow(
return rc;
}
/*
** Memory cell pMem may contain a blob or a NULL value. Cursor pCsr is
** open on an index. If the current index entry matches the blob value in
** pMem byte-for-byte, set pMem to NULL and return 1. Otherwise, return 0.
**
** If an error occurs, set (*pRc) to an SQLite error code. Return 1 in this
** case as well.
*/
static SQLITE_NOINLINE int vdbeIndexKeyCompare(
BtCursor *pCsr, /* Cursor to compare key to */
Mem *pMem,
int *pRc
){
int ret = 0;
u32 nKey = 0;
assert( pMem->flags & (MEM_Blob|MEM_Null) );
nKey = sqlite3BtreePayloadSize(pCsr);
if( nKey==(u32)pMem->n && ALWAYS((pMem->flags & MEM_Blob)!=0) ){
/* This code could just use sqlite3BtreePayloadFetch(). But calling that
** function here apparently prevents compilers from inlining it in other,
** more performance critical, places. So this code uses
** MemFromBtreeZeroOffset(), which is just as fast in most cases, but also
** handles the case where the index record uses overflow pages. */
Mem m;
memset(&m, 0, sizeof(m));
*pRc = sqlite3VdbeMemFromBtreeZeroOffset(pCsr, nKey, &m);
ret = (*pRc!=SQLITE_OK || 0==memcmp(pMem->z, m.z, nKey));
sqlite3VdbeMemReleaseMalloc(&m);
}
return ret;
}
/*
** Send a "statement aborts" message to the error log.
*/
@@ -6622,15 +6655,20 @@ case OP_SorterInsert: { /* in2 */
break;
}
/* Opcode: IdxDelete P1 P2 P3 P4 *
** Synopsis: key=r[P2@P3]
/* Opcode: IdxDelete P1 P2 P3 P4 P5
** Synopsis: key=r[P2@P5]
**
** The content of P3 registers starting at register P2 form
** The content of P5 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the
** index opened by cursor P1.
**
** P4 is a pointer to an Index structure.
**
** If P3 is non-zero, it is the register number of a register holding
** a record that will be inserted into this index. If that record is
** identical to the one that would be deleted by this instruction,
** skip the delete and set register P3 to NULL.
**
** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
** and not in writable_schema mode.
*/
@@ -6640,8 +6678,8 @@ case OP_IdxDelete: {
int res;
UnpackedRecord r;
assert( pOp->p3>0 );
assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
assert( pOp->p5>0 );
assert( pOp->p2>0 && pOp->p2+pOp->p5<=(p->nMem+1 - p->nCursor)+1 );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
@@ -6650,7 +6688,7 @@ case OP_IdxDelete: {
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p3;
r.nField = pOp->p5;
r.default_rc = 0;
r.aMem = &aMem[pOp->p2];
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
@@ -6669,6 +6707,13 @@ case OP_IdxDelete: {
break;
}
}
if( pOp->p3 && vdbeIndexKeyCompare(pCrsr, &aMem[pOp->p3], &rc) ){
if( rc ) goto abort_due_to_error;
sqlite3VdbeMemSetNull(&aMem[pOp->p3]);
break;
}
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
if( rc ) goto abort_due_to_error;
assert( pC->deferredMoveto==0 );
+5 -21
View File
@@ -7583,27 +7583,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
}
if( pTabList->a[pLevel->iFrom].fg.fromExists
&& (i==pWInfo->nLevel-1
|| pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
){
/* This is an EXISTS-to-JOIN optimization which is either the
** inner-most loop, or the inner-most of a group of nested
** EXISTS-to-JOIN optimization loops. If this loop sees a successful
** row, it should break out of itself as well as other EXISTS-to-JOIN
** loops in which is is directly nested. */
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
while( nOuter<i ){
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
nOuter++;
}
testcase( nOuter>0 );
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
if( nOuter ){
VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
}else{
VdbeComment((v, "EXISTS break %d", i));
}
if( pTabList->a[pLevel->iFrom].fg.fromExists ){
/* This is an EXISTS-to-JOIN optimization loop. If this loop sees a
** successful row, it should break out of itself. */
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
VdbeComment((v, "EXISTS break %d", i));
}
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
+9 -2
View File
@@ -2297,7 +2297,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
*/
if( pWInfo->nLevel>1 ){
if( pWInfo->nLevel>1 || pTabItem->fg.fromExists ){
int nNotReady; /* The number of notReady tables */
SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
@@ -2310,6 +2310,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
for(k=1; k<=nNotReady; k++){
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
}
/* Clear the fromExists flag on the OR-optimized table entry so that
** the calls to sqlite3WhereEnd() do not code early-exits after the
** first row is visited. The early exit applies to this table's
** overall loop - including the multiple OR branches and any WHERE
** conditions not passed to the sub-loops - not to the sub-loops. */
pOrTab->a[0].fg.fromExists = 0;
}else{
pOrTab = pWInfo->pTabList;
}
@@ -2553,7 +2560,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
assert( pLevel->op==OP_Return );
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
if( pWInfo->pTabList!=pOrTab ){ sqlite3DbFreeNN(db, pOrTab); }
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+48
View File
@@ -243,5 +243,53 @@ do_execsql_test 11.2.3 {
do_execsql_test 11.2.2 {ALTER TABLE t2 ALTER b SET NOT NULL --new cons
;
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 12.0 {
CREATE TABLE "Test" (
"IsActive" INTEGER,
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
);
}
do_execsql_test 12.1 {
ALTER TABLE Test DROP CONSTRAINT BooleanZeroOrOne
}
do_execsql_test 12.2 {
SELECT sql FROM sqlite_schema
} {
{CREATE TABLE "Test" (
"IsActive" INTEGER)}
}
do_execsql_test 12.3 {
DROP TABLE Test;
CREATE TABLE "Test" (
"IsActive" INTEGER,
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
);
}
do_execsql_test 12.4 {
ALTER TABLE Test DROP CONSTRAINT "BooleanZeroOrOne"
}
do_execsql_test 12.5 {
SELECT sql FROM sqlite_schema
} {
{CREATE TABLE "Test" (
"IsActive" INTEGER)}
}
do_execsql_test 12.6 {
CREATE TABLE t1(a, b CONSTRAINT "a""b" CHECK (b IS NOT NULL));
}
do_execsql_test 12.7 {
ALTER TABLE t1 DROP CONSTRAINT "a""b"
}
finish_test
+4 -4
View File
@@ -97,7 +97,7 @@ do_test badutf-3.2 {
} {0 {x 3}}
do_test badutf-3.3 {
sqlite3_exec db {SELECT length('%7f%80%81') AS x}
} {0 {x 3}}
} {0 {x 2}}
do_test badutf-3.4 {
sqlite3_exec db {SELECT length('%61%c0') AS x}
} {0 {x 2}}
@@ -109,13 +109,13 @@ do_test badutf-3.6 {
} {0 {x 1}}
do_test badutf-3.7 {
sqlite3_exec db {SELECT length('%80%80%80%80%80%80%80%80%80%80') AS x}
} {0 {x 10}}
} {0 {x 1}}
do_test badutf-3.8 {
sqlite3_exec db {SELECT length('%80%80%80%80%80%f0%80%80%80%80') AS x}
} {0 {x 6}}
} {0 {x 2}}
do_test badutf-3.9 {
sqlite3_exec db {SELECT length('%80%80%80%80%80%f0%80%80%80%ff') AS x}
} {0 {x 7}}
} {0 {x 3}}
do_test badutf-4.1 {
sqlite3_exec db {SELECT hex(trim('%80%80%80%f0%80%80%80%ff','%80%ff')) AS x}
+14
View File
@@ -0,0 +1,14 @@
#include "sqlite3.h"
#include <stdio.h>
int main(void) {
void *p = 0;
#ifdef SQLITE_OMIT_AUTOINIT
sqlite3_initialize();
#endif
p = sqlite3_malloc(32);
if( !p ) return 1;
sqlite3_free(p);
return 0;
}
+18
View File
@@ -0,0 +1,18 @@
#include "sqlite3.h"
#include <stdio.h>
int main(void) {
const char *zExpect = "2023.000";
char szBuffer[32];
double val = 2023.0;
#ifdef SQLITE_OMIT_AUTOINIT
sqlite3_initialize();
#endif
sqlite3_snprintf(17, szBuffer, "%.3f", val);
printf("size 17: '%s'\n", szBuffer);
if( sqlite3_stricmp(zExpect, szBuffer) ) return 1;
sqlite3_snprintf(16, szBuffer, "%.3f", val);
printf("size 16: '%s'\n", szBuffer);
if( sqlite3_stricmp(zExpect, szBuffer) ) return 1;
return 0;
}
+115
View File
@@ -476,6 +476,29 @@ catch { optimization_control db exists-to-join 0 }
db cache flush
do_execsql_test 9.6 $Q {{big string value}}
#-------------------------------------------------------------------------
# Forum post 2026-04-21T10:57:09Z
do_execsql_test 9.7.1 {
DROP TABLE t3;
CREATE TABLE t3(x INT, y INT);
CREATE TABLE t4(z INT);
INSERT INTO t3 VALUES (1,0),(2,2),(3,3);
INSERT INTO t4 VALUES (4),(5);
}
set Q {
SELECT x FROM t3
WHERE EXISTS(SELECT 1 FROM t4 WHERE z>y)
LIMIT 1 OFFSET 1
}
catch { optimization_control db all 1 }
db cache flush
do_execsql_test 9.7.2 $Q {2}
catch { optimization_control db exists-to-join 0 }
db cache flush
do_execsql_test 9.7.3 $Q {2}
catch { optimization_control db all 1 }
db cache flush
#-------------------------------------------------------------------------
reset_db
@@ -514,4 +537,96 @@ do_execsql_test 11.1 {
GROUP BY id;
} {1 p1}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 12.0 {
CREATE TABLE t2(id INT, data INT);
CREATE TABLE t3(amount INT);
INSERT INTO t2 VALUES (1,0),(2,0);
INSERT INTO t3 VALUES (1),(1);
}
do_execsql_test 12.1 {
SELECT * FROM t2
WHERE EXISTS (SELECT 1 FROM t3 WHERE t3.amount > t2.data)
} {
1 0
2 0
}
do_execsql_test 12.2 {
SELECT * FROM t2
WHERE EXISTS (SELECT 1 FROM t3 WHERE t3.amount > t2.data)
LIMIT 2 OFFSET 3
} {}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 13.0 {
CREATE TABLE t1(b,c);
CREATE TABLE t2(x,y);
CREATE TABLE t3(p,q);
INSERT INTO t1 VALUES(7,10);
INSERT INTO t2 VALUES(1,1), (4,7);
INSERT INTO t3 VALUES(4,7);
PRAGMA automatic_index = 0;
}
do_execsql_test 13.1 {
SELECT * FROM t1 WHERE EXISTS (
SELECT 1 FROM t2
WHERE EXISTS (
SELECT 1 FROM t3 WHERE t3.p=t2.x AND t3.q=t1.b
)
)
} {7 10}
#-------------------------------------------------------------------------
# Forum post https://sqlite.org/forum/forumpost/c8b205720c
#
reset_db
do_execsql_test 14.1.0 {
CREATE TABLE t(n INTEGER, parent INTEGER);
CREATE INDEX idx ON t(parent);
INSERT INTO t VALUES (1, NULL);
INSERT INTO t VALUES (10, NULL);
}
do_execsql_test 14.1.1 {
SELECT count(*) FROM t b
WHERE (b.parent IS NULL OR b.parent = 99)
AND 5 <= +b.n
} 1
do_execsql_test 14.1.2 {
SELECT 'match' WHERE EXISTS (
SELECT 1 FROM t b
WHERE (b.parent IS NULL OR b.parent = 99)
AND 5 <= +b.n
)
} {match}
do_execsql_test 14.2.1 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(20, 20);
CREATE TABLE t2(c, d);
CREATE INDEX t2c ON t2(c);
CREATE INDEX t2d ON t2(d);
INSERT INTO t2 VALUES(20, -1);
INSERT INTO t2 VALUES(20, 0);
}
do_execsql_test 14.2.2 {
SELECT * FROM t1 WHERE EXISTS (
SELECT 1 FROM t2 WHERE (c=a OR d=a) AND (d+1)>0
)
} {20 20}
finish_test
+21
View File
@@ -41,5 +41,26 @@ do_faultsim_test 2 -faults oom* -prep {
faultsim_test_result {0 ABCDEF}
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
PRAGMA page_size=1024;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE INDEX i1 ON t1( hex(b) );
INSERT INTO t1 VALUES(10, randomblob(500));
}
faultsim_save_and_close
do_faultsim_test 3 -faults oom* -prep {
faultsim_restore_and_reopen
} -body {
execsql {
UPDATE t1 SET b=randomblob(500);
}
} -test {
faultsim_test_result {0 {}}
}
finish_test
+86
View File
@@ -0,0 +1,86 @@
# 2026-04-23
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests for omitting the update of an index when the new value is the
# same as the old.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix expridx2
# This test requires wal mode, but the journaltest permutation installs
# a custom VFS that does not support wal mode.
if {[permutation]=="journaltest"} {
finish_test
return
}
do_execsql_test 1.0 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
INSERT INTO t1 VALUES(1, '{a: 10, b: 20, c: 30}');
INSERT INTO t1 VALUES(2, '{a: 11, b: 21, c: 31}');
INSERT INTO t1 VALUES(3, '{a: 12, b: 22, c: 32}');
INSERT INTO t1 VALUES(4, '{a: 13, b: 23, c: 33}');
CREATE INDEX t1a ON t1( (b->>'a') );
CREATE INDEX t1b ON t1( (b->>'b') );
CREATE INDEX t1c ON t1( (b->>'c') );
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX t2b ON t2( b );
INSERT INTO t2 VALUES(1, 1, 1);
INSERT INTO t2 VALUES(2, 2, 2);
INSERT INTO t2 VALUES(3, 3, 3);
INSERT INTO t2 VALUES(4, 4, 4);
} {wal}
proc nWrite {sql} {
sqlite3_db_status db CACHE_WRITE 1
execsql $sql
lindex [sqlite3_db_status db CACHE_WRITE 0] 1
}
do_test 1.1 {
nWrite { UPDATE t1 SET b = json_set(b, '$.a', b->>'a' + 1) }
} {2}
do_test 1.2 {
nWrite {
UPDATE t1 SET b = json_set(
json_set(b, '$.a', b->>'a' + 1),
'$.b', b->>'b' + 1
);
}
} {3}
do_test 1.3 {
nWrite {
UPDATE t1 SET b = '{a:1, b:2, c:3}' WHERE rowid=1;
}
} {4}
integrity_check 1.4
do_test 1.5 {
nWrite { UPDATE t2 SET b = b+1, c=c+1 }
} {2}
do_test 1.6 {
nWrite { UPDATE t2 SET b = b, c=c+1 }
} {2}
do_test 1.7 {
nWrite { UPDATE t2 SET c=c+1 }
} {1}
finish_test
+2
View File
@@ -172,6 +172,7 @@ 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*);
@@ -1393,6 +1394,7 @@ 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);
+17 -1
View File
@@ -30,12 +30,19 @@ tvfs filter xWrite
tvfs script write_cb
set ::trigger_interrupt 0
set ::dbpointer ""
proc write_cb {method args} {
set filename [lindex $args 0]
if {[file tail $filename]=="test.db" && $::trigger_interrupt} {
if {$::trigger_interrupt} {
incr ::trigger_interrupt -1
if {$::trigger_interrupt==0} { sqlite3_interrupt db }
if {$::trigger_interrupt==0} {
if {$::dbpointer!=""} {
sqlite3_interrupt $::dbpointer
} else {
sqlite3_interrupt db
}
}
}
}
return 0
@@ -110,8 +117,17 @@ db_save_and_close
db_restore_and_reopen
do_test 3.1.1 {
set ::trigger_interrupt 10
# Set dbpointer here so that the write-callback can use the (sqlite3*)
# pointer with sqlite3_interrupt() directly instead of looking up the
# command. On at least some versions of Tcl9, looking up a command from
# within Tcl_DeleteCommand apparently returns a bad pointer.
#
set ::dbpointer [sqlite3_connection_pointer db]
db eval { SELECT * FROM sqlite_master }
db close
set ::dbpointer ""
set {} {}
} {}
do_test 3.1.2 {
+61
View File
@@ -280,4 +280,65 @@ do_test 900 {
} 1
dbempty close
#-------------------------------------------------------------------------
# Make sure a database cannot be overwritten by deserialize() if
# there is an open transaction on it.
#
do_execsql_test 1000 {
CREATE TABLE t(x);
INSERT INTO t VALUES(1),(2);
}
set blob [db serialize main]
do_test 1010 {
set seen 0
list [catch {
db eval {SELECT x FROM t} {
incr seen
if {$seen == 1} {
db deserialize main $blob
}
}
} msg] $msg
} {1 {unable to set MEMDB content}}
forcedelete test.db2
sqlite3 db2 test.db2
do_test 1020 {
set seen 0
sqlite3_backup B db2 main db main
B step 2
set res [list [catch {
db deserialize main $blob
} msg] $msg]
B finish
set res
} {1 {unable to set MEMDB content}}
db2 close
#-------------------------------------------------------------------------
# Check that things work if the destination database of a backup is
# overwritten using sqlite3_deserialize() between sqlite3_backup_init()
# and the first call to sqlite3_backup_step(). Forum post 15d82885e2.
#
reset_db
do_execsql_test 1100 {
CREATE TABLE t(x);
INSERT INTO t VALUES(1),(2);
}
set blob [db serialize main]
forcedelete test.db2
sqlite3 db2 test.db2
do_test 1110 {
set seen 0
sqlite3_backup B db2 main db main
db2 deserialize main $blob
B step 2
B finish
} {SQLITE_OK}
finish_test
+104
View File
@@ -0,0 +1,104 @@
# This script is used to test certain output redirection commands
# in the CLI, specifically:
#
# .www
# .once -w
# .output -w
# .once -e
# .ooutput -e
# .excel
# .once -x
# .output -x
#
# Because of system interactions it is difficult to test these
# commands automatically. They must be tested manually, with the
# aid of this script.
#
# To run the test:
#
# 1. Be on a console of the machine under test (not on ssh).
# 2. Run "./sqlite3 test/output-redir-test.txt" or similar.
# 3. Verify that all the right pop-ups appear. More information
# on what popups to expect appears on the console output.
#
.print "Expect to see 8 output pop-ups:
.print " * 3 new tabs in your web-browser"
.print " * 2 editor windows"
.print " * 3 spreadsheets"
.print "There is a 2-second pause between tests. Wait until"
.print "prompted to verify results...."
.print ""
.print "Running web-browser tests first..."
.mode box
CREATE TABLE t1(x);
INSERT INTO t1 VALUES
('Web-browser test 1 of 3'),
('Test for the ".www" commmand.');
.www
SELECT * FROM t1;
DELETE FROM t1;
INSERT INTO t1 VALUES
('Web-browser test 2 of 3'),
('Test for the ".once -w" commmand.');
.once -w
SELECT * FROM t1;
DELETE FROM t1;
INSERT INTO t1 VALUES
('Web-browser test 3 of 3'),
('Test for the ".output -w" commmand.'),
('Confirm additional text below.');
.output -w
SELECT * FROM t1;
.print "This test should also appear after the table."
.print "in the web-browser output".
.output
.print "Web-browser tests are done. Starting editor tests."
DELETE FROM t1;
INSERT INTO t1 VALUES
('Editor test 1 of 2'),
('Test for the ".once -e" commmand.');
.once -e
SELECT * FROM t1;
DELETE FROM t1;
INSERT INTO t1 VALUES
('Editor test 2 of 2'),
('Test for the ".output -e" commmand.'),
('Confirm additional text below.');
.output -e
SELECT * FROM t1;
.print "This test should also appear after the table."
.print "in the pop-up editor window.".
.output
.print "Pop-up editor tests are done. Starting spreadsheed tests"
DELETE FROM t1;
INSERT INTO t1 VALUES
('Spreadsheet test 1 of 3'),
('Test for the ".excel" commmand.');
.excel
SELECT * FROM t1;
DELETE FROM t1;
INSERT INTO t1 VALUES
('Spreadsheet test 2 of 3'),
('Test for the ".once -x" commmand.');
.once -x
SELECT * FROM t1;
DELETE FROM t1;
INSERT INTO t1 VALUES
('Spreadsheet test 3 of 3'),
('Test for the ".output -x" commmand.'),
('Confirm additional text below.');
.output -x
SELECT * FROM t1;
.print "This test should also appear after the table."
.print "in the spreadsheet output".
.output
.print "All tests are done. You may now verify the results."
+4
View File
@@ -882,6 +882,10 @@ int main(int argc, char **argv){
int nChgset;
int bVerbose = 0;
#ifdef SQLITE_OMIT_AUTOINIT
sqlite3_initialize();
#endif
if( argc<2 ){
fprintf(stderr, "%s", zHelp);
exit(1);
+137 -31
View File
@@ -28,9 +28,9 @@
.testcase 110
.prompt --show
.check <<END
Main prompt: 'SQLite /f> '
Continuation: '/B.../H> '
.check --glob <<END
Main prompt: '*/A*/f*-> '
Continuation: '/B*/C*-> '
END
.testcase 111
.prompt 'abc> ' '123> ' -show
@@ -47,9 +47,9 @@ Continuation: '--second'
END
.testcase 113
.prompt --reset --show
.check <<END
Main prompt: 'SQLite /f> '
Continuation: '/B.../H> '
.check --glob <<END
Main prompt: '*/A*/f*> '
Continuation: '/B*/C*> '
END
.testcase 120 --error-prefix ERROR:
@@ -64,20 +64,20 @@ END
.check ''
.testcase 122
.prompt --show
.check <<END
.check --glob <<END
Main prompt: 'show'
Continuation: '/B.../H> '
Continuation: '/B*/C*> '
END
.testcase 130
.prompt --reset
.help prompt
.check <<END
.prompt MAIN CONTINUE Replace the standard prompts
--hard-reset Unset SQLITE_PS1/2 and then --reset
--reset Revert to default prompts
--show Show the current prompt strings
-- No more options. Subsequent args are prompts
.prompt MAIN CONTINUE Replace the standard prompts
--hard-reset Unset SQLITE_PS1/2 and then --reset
--reset Revert to default prompts
--show Show the current prompt strings
-- No more options. Subsequent args are prompts
END
.testcase 140 --error-prefix ERROR:
@@ -90,31 +90,32 @@ END
.testcase 1000
SELECT shell_prompt_test(NULL);
.check 'SQLite test.db> ';
.check --glob '*SQLite-3*test.db*-> ';
.testcase 1001
SELECT shell_prompt_test(NULL,'SELECT');
.check ' ...;> ';
.check --glob ' *;*-> ';
.testcase 1002
SELECT shell_prompt_test(NULL,'SELECT ((("');
.check ' ...")));> ';
SELECT shell_prompt_test(NULL,'SELECT ((("',null,2);
.check --glob ' *[ m]")));*-> ';
.testcase 1003
SELECT shell_prompt_test(NULL,'SELECT ((()[');
.check ' ...]));> ';
SELECT shell_prompt_test(NULL,'SELECT ((()[',null,2);
.check --glob ' *[ m]]));*-> ';
.testcase 1004
SELECT shell_prompt_test(NULL,'SELECT ''');
.check " ...';> ";
SELECT shell_prompt_test(NULL,'SELECT ''',null,2);
.check --glob " *[ m]';*-> ";
.testcase 1005
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN');
.check " ...;END;> ";
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN',null,2);
.check --glob " *[ m];END;*-> ";
.testcase 1006
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((([');
.check " ...])));END;> ";
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((([',null,2);
.check --glob " *[ m]])));END;*-> ";
.testcase 1007
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((/*a(((''bc');
.check " ...*/));END;> ";
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((/*a(((''bc',
null,2);
.check --glob " *[ m][*]/));END;*-> ";
.testcase 1008
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT 1;');
.check " ...END;> ";
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT 1;',null,2);
.check --glob " *[ m]END;*-> ";
.testcase 2000
.prompt 'SQLite/x-txn$/:>/; '
@@ -135,6 +136,111 @@ SELECT shell_prompt_test(NULL);
.testcase 2004
.prompt --reset
SELECT shell_prompt_test(NULL);
.check 'SQLite test.db> ';
.check --glob '*SQLite-3.# *test.db*-> ';
.testcase
.testcase 3000
SELECT shell_prompt_test('(/A-/V)');
.check --glob '(SQLite-3.#.#)'
.testcase 3001
SELECT shell_prompt_test('(/A-/v)');
.check --glob '(SQLite-3.#)'
.testcase 3002
SELECT shell_prompt_test('(/A-/D%Y-%m-%dT%H:%M:%S/D)');
.check --glob '(SQLite-20#-#-#T#:#:#)'
.testcase 4000
.mode list -rowsep '' -escape ascii
SELECT shell_prompt_test('</myes/:no/;>',NULL,':memory:');
.check <yes>
.testcase 4001
.mode list -rowsep '' -escape ascii
SELECT shell_prompt_test('</myes/:no/;>',NULL,'t1.db');
.check <no>
.testcase 5000
SELECT shell_prompt_test('abc/e[0mxyz',NULL,NULL,1);
.check abc^A^[[0m^Bxyz
.testcase 5001
SELECT shell_prompt_test('abc/e[0mxyz',NULL,NULL,2);
.check abc^[[0mxyz
.testcase 5002
SELECT shell_prompt_test('/e[0mxyz',NULL,NULL,1);
.check ^A^[[0m^Bxyz
.testcase 5003
SELECT shell_prompt_test('abc/e[0m',NULL,NULL,1);
.check abc^A^[[0m^B
.testcase 5004
SELECT shell_prompt_test('abc/e[1;32m/e[0m/e[/exyz',NULL,NULL,1);
.check abc^A^[[1;32m^[[0m^B^[[^[xyz
.testcase 5005
SELECT shell_prompt_test('abc/e[1,32m/e[0m/e[/exyz',NULL,NULL,1);
.check abc^[[1,32m^A^[[0m^B^[[^[xyz
# Additional tests for octal escapes
#
.testcase 6000
SELECT shell_prompt_test('/7');
.check ^G
.testcase 6001
SELECT shell_prompt_test('/78');
.check ^G8
.testcase 6002
SELECT shell_prompt_test('/7//');
.check ^G/
.testcase 6003
SELECT shell_prompt_test('/7/');
.check ^G
.testcase 6004
SELECT shell_prompt_test('/57');
.check /
.testcase 6005
SELECT shell_prompt_test('/578');
.check /8
.testcase 6006
SELECT shell_prompt_test('/57//');
.check //
.testcase 6007
SELECT shell_prompt_test('/57/');
.check /
.testcase 6008
SELECT shell_prompt_test('/10');
.check ^H
.testcase 6009
SELECT shell_prompt_test('/101');
.check A
.testcase 6010
SELECT shell_prompt_test('/1011');
.check A1
.testcase 6011
SELECT shell_prompt_test('/33[0');
.check ^[[0
# The UNKNOWN() error is shown regardless of whether or not the
# escape is part of an active branch.
.testcase 6012
SELECT shell_prompt_test('/x/z/:/y/;');
.check 'UNKNOWN("/z")UNKNOWN("/y")'
# Additional tests of \001..\002 escapes
#
# Two or more disconneted ANSI escapes
#
.testcase 7000
SELECT shell_prompt_test('a-/e[1m-/e[0m-z',null,null,1);
.check a-^A^[[1m^B-^A^[[0m^B-z
# Empty parameter
.testcase 7001
SELECT shell_prompt_test('a-/e[m-z',null,null,1);
.check a-^A^[[m^B-z
# /e followed by non-[
.testcase 7002
SELECT shell_prompt_test('a-/eX-z',null,null,1);
.check a-^[X-z
.testcase 7003
SELECT shell_prompt_test('a-/eX/e[m-z',null,null,1);
.check a-^[X^A^[[m^B-z
.testcase 7004
SELECT shell_prompt_test('a-/e[m/eX-z',null,null,1);
.check a-^A^[[m^B^[X-z
+1
View File
@@ -311,6 +311,7 @@ do_test shell5-1.9 {
puts $out {"""",11,121}
puts $out {"hello",12,132}
close $out
catch {db close}
forcedelete test.db
catchcmd test.db {.mode csv
CREATE TABLE t1(a,b,c);
+1
View File
@@ -103,6 +103,7 @@ foreach {tn schema output} {
}
} {
catch {db close}
forcedelete test.db
sqlite3 db test.db
execsql $schema
-1
View File
@@ -550,7 +550,6 @@ char *speedtest1_once(const char *zFormat, ...){
char *zSql;
sqlite3_stmt *pStmt;
char *zResult = 0;
int rc;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
+79 -16
View File
@@ -34,7 +34,15 @@ proc find_interpreter {} {
set rc [catch { package require sqlite3 }]
if {$rc} {
if {[file readable pkgIndex.tcl] && [catch {source pkgIndex.tcl}]==0} {
# Since $dir is defined to be the [pwd], if the "source pkgIndex.tcl"
# worked, that should have enabled us to use the locally built
# copy of the TCL extension.
set rc [catch { package require sqlite3 }]
if {!$rc} {
puts "Using the locally built copy of the \"sqlite3\" tcl extension"
} else {
puts "The locally built copy of the \"sqlite3\" tcl extension does work..."
}
}
}
if {$rc} {
@@ -49,7 +57,7 @@ proc find_interpreter {} {
}
}
if {$rc} {
puts "Cannot find tcl package sqlite3: Trying to build it now..."
puts "Cannot find tcl package \"sqlite3\": Trying to build it now..."
if {$::tcl_platform(platform) eq "windows"} {
set bat [open make-tcl-extension.bat w]
puts $bat "nmake /f Makefile.msc tclextension"
@@ -142,25 +150,20 @@ are run. Otherwise, each pattern is interpreted as a glob pattern. Only
those tcl tests for which the final component of the filename matches at
least one specified pattern are run. The glob wildcard '*' is prepended
to the pattern if it does not start with '^' and appended to every
pattern that does not end with '$'. If PATTERN begins with "~", then it
is an anti-pattern that only matches tests that do not match PATTERN.
Tests or only run if they match one or more patterns and match no
anti-patterns.
If no PATTERN arguments are present, then various fuzztest, threadtest
and other tests are run as part of the "release" permutation. These are
omitted if any PATTERN arguments are specified on the command line.
pattern that does not end with '$'. If any PATTERN argument begins with "~",
then it is an anti-pattern. When PATTERN arguments are present, tests are
only run if they match one or more patterns and match no anti-patterns.
If a PERMUTATION is specified and is followed by the path to a Tcl script
instead of a list of patterns, then that single Tcl test script is run
with the specified permutation.
The "status" and "njob" commands are designed to be run from the same
directory as a running testrunner.tcl script that is running tests. The
"status" command prints a report describing the current state and progress
of the tests. Use the "-d N" option to have the status display clear the
screen and repeat every N seconds. The "njob" command may be used to query
or modify the number of sub-processes the test script uses to run tests.
directory as a running testrunner.tcl script. The "status" command prints
a report describing the current state and progress of the tests. Use
the "-d N" option to have the status display clear the screen and repeat
every N seconds. The "njob" command may be used to query or modify the
number of sub-processes the test script uses to run tests.
The "halt" command modifies the database so that all tasks are marked
as complete. Testing will halt when all tests currently running complete.
@@ -180,7 +183,7 @@ shows the jobs that failed. If PATTERN are provided, the error information
is only provided for jobs that match PATTERN.
The "retest" command reruns tests that failed or were never completed
by a prior invocation of testrunner.tcl.
by the previous invocation of testrunner.tcl.
Full documentation here: https://sqlite.org/src/doc/trunk/doc/testrunner.md
}]]
@@ -1277,6 +1280,7 @@ proc add_build_job {buildname target {postcmd ""} {depid ""}} {
set dirname "[string tolower [string map {- _} $buildname]]_$target"
regsub {\.exe$} $dirname {} dirname
regsub {\.l?o$} $dirname {obj} dirname
set dirname "testrun_$dirname"
set cmd "$TRG(makecmd) $target"
@@ -1298,6 +1302,57 @@ proc add_build_job {buildname target {postcmd ""} {depid ""}} {
list $id [file normalize $dirname] $buildname
}
# Add jobs to build and run all the *.c files in $testdir/c/ for build
# configuration $buildname.
#
proc add_c_jobs {buildname} {
global TRG
set dir [file join $::testdir c]
# One job to build the sqlite3.o file for this configuration. Each
# individual "c" job will copy this sqlite3.o into its working directory
# so that it doesn't have to build it separately every time.
#
set obj sqlite3.o
if {$TRG(platform)=="win"} { set obj sqlite3.lo }
set B [add_build_job $buildname $obj]
foreach {bldid blddir dummy} $B {}
# One job for each C file.
#
foreach f [glob -nocomplain $dir/*.c] {
set prg [string range [file tail $f] 0 end-2]
set cmd ""
if {$TRG(platform)=="win"} {
foreach cp {sqlite3.lo *.h *.c} {
append cmd "copy [file nativename [file join $blddir $cp]] .\n"
}
append cmd "SET AUXTEST=$prg\n"
set prg "${prg}.exe"
append cmd "$TRG(makecmd) $prg\n"
append cmd ".\\$prg\n"
} else {
set cmd "set -e\n"
foreach cp {sqlite3.c sqlite3.h sqlite3.o .target_source src-verify} {
append cmd "cp [file join $blddir $cp] .\n"
}
append cmd "AUXTEST=$prg $TRG(makecmd) $prg\n"
append cmd "./$prg\n"
}
set id [add_job \
-displaytype tcl \
-displayname "$prg ($buildname)" \
-build $buildname \
-cmd $cmd \
-depid $bldid \
-priority 3
]
}
}
proc add_shell_build_job {buildname dirname depid} {
global TRG
@@ -1545,6 +1600,8 @@ proc add_jobs_from_cmdline {patternlist} {
UPDATE jobs SET depid=$sbldid WHERE depid='SHELL'
}
}
add_c_jobs $b
}
}
@@ -1912,6 +1969,7 @@ proc run_testset {} {
SELECT DISTINCT substr(svers,1,79) as v1 FROM jobs WHERE svers IS NOT NULL
} {puts $v1}
return [expr {$nErr>0}]
}
# If the argument is "retest", simply rerun all tests from the previous
@@ -1971,6 +2029,7 @@ proc explain_tests {} {
explain_layer "" ""
}
set exit_status 0
sqlite3 trdb $TRG(dbname)
trdb timeout $TRG(timeout)
if {[llength $TRG(patternlist)]==1 && $TRG(patternlist) eq "retest"} {
@@ -1989,6 +2048,10 @@ if {$TRG(explain)} {
puts "built testset in [expr $tm/1000]ms.."
}
handle_buildonly
run_testset
set exit_status [run_testset]
}
trdb close
exit $exit_status
+1
View File
@@ -143,6 +143,7 @@ namespace eval trd {
-DSQLITE_ENABLE_UNLOCK_NOTIFY
-DSQLITE_THREADSAFE
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
-DSQLITE_OMIT_AUTOINIT=1
}
set build(Secure-Delete) {
-O2
+10
View File
@@ -787,4 +787,14 @@ do_eqp_test update-21.12 {
`--SEARCH t3 USING AUTOMATIC COVERING INDEX (x=?)
}
# /forumpost/2026-04-21T19:10:55Z
do_execsql_test update-22.0 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(x INT, y INT);
INSERT INTO t1(x) VALUES(1),(2),(3),(4),(5);
UPDATE t1 SET x=x+100, y=x<=(SELECT min(x) FROM t1)
WHERE x<3 OR (1 BETWEEN 0 AND x<=(SELECT min(x)+2 FROM t1));
SELECT x FROM t1 WHERE x<100 ORDER BY x;
} {4 5}
finish_test
+10 -5
View File
@@ -17,7 +17,8 @@ Options:
--uninstall Uninstall the extension
--version-check Check extension version against this source tree
--destdir DIR Installation root (used by "make install DESTDIR=...")
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
--extlibs LDFLAGS required for external libs, e.g. ICU.
Other options are retained and passed through into the compiler.}
@@ -29,8 +30,9 @@ set infoonly 0
set versioncheck 0
set CC {}
set OPTS {}
set DESTDIR ""; # --destdir "$(DESTDIR)"
set DESTDIR "" ; # --destdir "$(DESTDIR)"
set tclConfigSh ""; # --tclConfig.sh FILE
set LIBS {} ; # --extlibs "-lx -ly ..."
for {set ii 0} {$ii<[llength $argv]} {incr ii} {
set a0 [lindex $argv $ii]
if {$a0=="--install-only"} {
@@ -61,6 +63,9 @@ for {set ii 0} {$ii<[llength $argv]} {incr ii} {
} elseif {$a0=="--tclConfig.sh" && $ii+1<[llength $argv]} {
incr ii
set tclConfigSh [lindex $argv $ii]
} elseif {$a0=="--extlibs" && $ii+1<[llength $argv]} {
incr ii
lappend LIBS [lindex $argv $ii]
} elseif {[string match -* $a0]} {
append OPTS " $a0"
} else {
@@ -152,8 +157,8 @@ if {$tcl_platform(platform) eq "windows"} {
}
set CFLAGS -fPIC
regexp {TCL_SHLIB_CFLAGS='([^']+)'} $tclConfig all CFLAGS
set LIBS {}
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBS
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBSTUB
lappend LIBS $LIBSTUB
set INC "-I$srcdir/src"
set inc {}
regexp {TCL_INCLUDE_SPEC='([^']+)'} $tclConfig all inc
@@ -312,7 +317,7 @@ package ifneeded sqlite3 $VERSION \\
# Generate and execute the command with which to do the compilation.
#
set cmd "$CMD -DUSE_TCL_STUBS tclsqlite3.c -o $OUT $LIBS"
set cmd "$CMD -DUSE_TCL_STUBS tclsqlite3.c -o $OUT [join $LIBS { }]"
puts $cmd
file delete -force $OUT
catch {exec {*}$cmd} errmsg
+1 -1
View File
@@ -16,7 +16,7 @@
** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
** interstitial "-" characters) contained in this template is changed into
** the value of the %name directive from the grammar. Otherwise, the content
** of this template is copied straight through into the generate parser
** of this template is copied straight through into the generated parser
** source file.
**
** The following is the concatenation of all %include directives from the
+1 -1
View File
@@ -1900,7 +1900,7 @@ static void showHelp(void){
}
/* work-around the Microsoft "WorstFit" bug */
#ifdef _WIN32
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(main)
#define main utf8_main
#endif