Compare commits

...

78 Commits

Author SHA1 Message Date
stephan 6e1c2f0483 proj.tcl portability fixes and cleanups suggested in [forum:7b218c3c9f|forum post 7b218c3c9f]. Branching so that it can be tested on msys/cygwin/haiku before committing to it.
FossilOrigin-Name: 89552e9137b7ebba9600443720e936e8dc4f7ab021d2ac3f0bb01b74071e130c
2025-06-17 14:37:31 +00:00
drh 86d9c2d9f3 Fix an issue going back to version 3.39.0 with transitive IS constraints
in queries that make use of RIGHT JOIN.  Problem reported by
[forum:/forumpost/68f29a2005|forum post 68f29a2005].

FossilOrigin-Name: 9441fff52cc4e19c44df1a77ffe474f409d519b270c7166ce17f99e6ea48fc1e
2025-06-16 17:36:11 +00:00
drh d3a13f7d25 Improved debugging output for the transitive constraint optimization.
FossilOrigin-Name: 94b53c20e9bc8687c44272419aa7a93076eebdeae9a4f50b95b96a49993f9c0d
2025-06-16 16:07:14 +00:00
drh 6ed5aa4b9b Make the show-%p-az-zero hack of the previous check-in configurable at
run-time using the 0x100000 bit of either .treetrace or .wheretrace.
As before, this is all a no-op except for debugging builds.

FossilOrigin-Name: a29627d7e7f8344d9a099cc133bda85250b02dc5ee5f358ba59691e0816b5b2d
2025-06-16 15:34:26 +00:00
drh 67f708298f Add an "#if 0" that can be changed to "1" to cause all %p output to render
as 0, thus making comparisons of .treetrace and .wheretrace output easier.

FossilOrigin-Name: 65e2704c0bc329f3dd248548a2d4edb7d3ace8ceaf0b82b8618b9b1b764884cd
2025-06-16 13:51:09 +00:00
dan 792d1d1b6d Have sqlite3_setlk_timeout() take the database handle mutex. This fixes an assert() failure that could occur if sqlite3_setlk_timeout() were called on a threadsafe handle.
FossilOrigin-Name: a95d126e1330e1b83f42b51f97c4c216622cf38062f3b5d72ccb76313187e850
2025-06-12 07:35:38 +00:00
dan 6a5e74cbf0 Fix a problem with UPDATEs on fts5 tables that contain blob values.
FossilOrigin-Name: badf3014bd1620fd3d4b8013f641fd820b249649fb93cc75b7b8df9dfd6f32a6
2025-06-11 15:03:53 +00:00
drh 23e59b34e9 Fix the concat_ws() SQL function so that it includes empty strings in the
concatenation.  [forum:/forumpost/52503ac21d|Forum post 52503ac21d].

FossilOrigin-Name: 80a78987da484d435a8242c05c48d546d430920df713b24a9d9d9fff7ba1113d
2025-06-11 00:01:42 +00:00
drh a09a4fbac9 Improved selection of the divisor when subdividing nested Bitvec objects.
This fixes a potential stack overflow that can occur when the database size
is within 60 pages of the maximum allowed by the file format.

FossilOrigin-Name: f7ab764ed9df6d7a4a96cb0933d291f00174f33fed3d9951785078fe225adcb7
2025-06-10 19:52:21 +00:00
drh 6a23ff5a07 Minor corrections to the new Bitvec testing logic.
FossilOrigin-Name: 77b79ca1277419b91589aff2c601d4abdd7107d48019a58f7f7c85d96c2a538e
2025-06-10 18:26:09 +00:00
drh 5706b316c3 Enhancements to sqlite3BitvecBuiltinTest() that allow testing code to
create very large Bitvec objects that do not use the linear array cross-check.

FossilOrigin-Name: c5680672cae23f65637eebf66f3bb983a2864be03ea70378832034f3c89ef728
2025-06-10 17:22:53 +00:00
drh 90ba0d4995 Improved diagnostics for Bitvec: Add the sqlite3ShowBitvec() routine that
can be called from a debugger (only available with SQLITE_DEBUG).  Add new
output opcodes for sqlite3BitvecBuiltinTest().

FossilOrigin-Name: dea1e37fa67ada6efc1533b449d9eb22338d9e58eec8f89b48c38319c212c8f4
2025-06-10 16:02:29 +00:00
drh f091f423ad Adjustments to ext/misc/fileio.c in an attempt to get it to build using mingw.
FossilOrigin-Name: 96b14a3f1193de8f30e9fa704f87558dab8027a218868d32e47688cd5df497b7
2025-06-09 22:38:34 +00:00
drh 4c323ba4be Remove unnecessary whitespace and otherwise improve comments in the
wherecode.c module.  No coding changes.

FossilOrigin-Name: 2eb4e9bf0f2df50324a62fb272a92bbd931b8b4e4b35bac0c05b676c97b61339
2025-06-06 23:10:18 +00:00
drh 368c549044 Update the "msort" function in Lemon so that it works with lists of any
length, and also so that the sort is stable.  This patch was motivated by
[forum:/forumpost/63750d717c9ed961|forum post 63750d717c] but was
independently developed, then tested by temporarily setting LISTSIZE to 2.

FossilOrigin-Name: aba5c3135edf7de2798ad808fa0ff176fdba3f4a9b101f1f4210b441cba8e75d
2025-06-06 23:02:03 +00:00
drh b1929b7117 Remove the clunky test_windirent.h and test_windirent.c files from src/
and replace them with a much cleaner and more compact ext/misc/windirent.h.

FossilOrigin-Name: acc978df52ec41ffdb5c27764f30d53efa1f25a314b7d98983dc0d211a36b570
2025-06-05 20:12:41 +00:00
drh 6facd9566d Enhance the FSDIR virtual table with a new "level" column. The query planner
knows how to optimize to avoid search deeper than the maximum requested level.

FossilOrigin-Name: 1ddc0f9e79c33957961bc1443ccb74d756a02cbd20850052079782e76aef2706
2025-06-05 18:28:54 +00:00
stephan 26370358b6 tea build: add an info-exists check after a 'scan' call, as scan does not create its target vars on error. Problem reported at [forum:fde857fb8101a4be | forum post fde857fb8101a4be] and triggers when the 'vsatisfies' test for the host's Tcl version fails (so the build would fail anyway, but will fail more informatively with this fix).
FossilOrigin-Name: 4f21874d5d20aef2e2d67a59e4fa03d98aa6514b16e4d956acfc817142cfbdb6
2025-06-04 18:34:20 +00:00
stephan a29b138692 Apply the duplicate 'export default' workaround to the (untested and unsupported) node-specific build rules in mkwasmbuilds.c to resolve a problem reported off-list by Thomas Steiner.
FossilOrigin-Name: 2f8a1b79533879e4975b405c46fea496ba8bffbef065e7dd0ad29fd4aa8f8f92
2025-06-03 18:10:59 +00:00
drh 1d151e6d25 Enhance sqlite3_rsync so that it works even if the replica database is
initially malformed.

FossilOrigin-Name: ea1754f7d8a770477a1b19b606b27724fdc0b733e51fef32c1ef834f972c3cc5
2025-06-03 10:49:51 +00:00
drh df724c893a Fix an off-by-one error in sqlite3_rsync, reported in
[forum:/forumpost/b6d78f60fc|forum post b6d78f60fc].

FossilOrigin-Name: 27d9e8e79b921c4a86916556f3bf56b94684a7e3d40166c0fdaaf750d4011de0
2025-06-03 10:28:47 +00:00
drh 140748f949 Fix harmless compiler warning introduced by the setlk-snapshot-fix merge.
FossilOrigin-Name: c1f20f89d9eb3e1dd1018c0e0efe5d3043a592f078e235ad04b960334c7186c2
2025-06-03 10:18:54 +00:00
drh 2bd9f69d40 Fix JSONB edit so that when it is trying to reduce the size of an element
it understands 0xf0 (8-byte) sizes.

FossilOrigin-Name: 5b3de6e8ab6b228bf6c0e0c31b50ca29d8b7852b460eaaca6c6ecf5a3c083cab
2025-06-02 23:34:42 +00:00
drh 333b07b18d Increase the version number to 3.51.0
FossilOrigin-Name: ed69d4432712603bea2161e0ca0c99e59480fb000e1cbf1aa1401d924544e351
2025-06-02 18:58:42 +00:00
dan 9269b212bf Fixes to ensure SQLITE_ENABLE_SETLK_TIMEOUT builds use a blocking lock and do not call xSleep() when (a) opening a snapshot transaction, and (b) when blocked by another process running recovery.
FossilOrigin-Name: 7f9c0cdd0630a41db359b188b226a1ad6a3bae1663c27169acfe25edc7fb171b
2025-06-02 18:48:36 +00:00
dan 69ce758efa Fix os_win.c so that SQLITE_ENABLE_SETLK_TIMEOUT=2 builds work on windows.
FossilOrigin-Name: 8efb95e0d4670b9c5dbd8cf34512334f47951a8dff8fdadc8645f75076acd91f
2025-06-02 18:37:32 +00:00
drh 342ef63e63 Improve the accuracy of affinity and collating sequence analysis for
NATURAL JOINs to the left of RIGHT JOINs where source tables are views
or subqueries.  Initial problem report in
[forum:/forumpost/829306db47|forum post 829306db47].

FossilOrigin-Name: f184d1d236e47962658a4639d9533f67a525b74cfe0f06c93e9b85fdcd02a15f
2025-06-02 18:34:17 +00:00
dan cfee69fbe4 Updates to new test cases to run with SQLITE_ENABLE_SETLK_TIMEOUT=2 builds.
FossilOrigin-Name: c6d3e3542fdf6a3428d3a2ec20c699c169ed53341dc782d81f7fe5944f769748
2025-06-02 18:09:46 +00:00
dan eb9a145711 Merge trunk changes into this branch.
FossilOrigin-Name: 7d27451804e525190f8e67da75aaeb3bf2de677021f7566c6681398e60a88c72
2025-06-02 17:44:10 +00:00
stephan d84bbac8be Slight modernization of the TEA README.txt.
FossilOrigin-Name: bf7be67e3fb7b75fc281997f7bf9aa69eaf4da6bdf2fefe359b12d25ec95f512
2025-06-02 15:17:59 +00:00
stephan a3fcd7c79e TEA: remove the stale man page and references to the MSC makefiles from the README.txt. Based on discussion at [forum:87e6660191a472c5 | forum post 87e6660191a472c5]. A couple of weeks ago we internally discussed pulling in the MSC makefiles from the 3.49 tree but they are stale and possibly unused, so opted against it for the time being.
FossilOrigin-Name: c9888a409565e6c8891a3dafa56962df364fb729a61df2701dc0bb282e36fb75
2025-06-02 15:10:41 +00:00
drh 8658a8df59 Remove an unnecessary parameter from sqlite3VdbeRecordUnpack(). Improved
comments and assert()s on KeyInfo.

FossilOrigin-Name: 387f4c4d98b8fb83f6ae406e4143dabda7766e8752b7f6ca104655e51330c978
2025-06-02 13:54:33 +00:00
drh 7590bfd7fc Fix stale comments related to KeyInfo. Add new assert()s associated with
memory management of KeyInfo.

FossilOrigin-Name: abd805bc76f14ede7359b029908179b7ca57e929c5918acae1403ef73ae0bd47
2025-06-02 09:49:07 +00:00
drh d4c224b833 Fix an off-by-one error in the size computation of a vdbe-sorter.
[forum:/forumpost/c1cc8b057a|Forum post c1cc8b057a].
Problem introduced by checkin [d4307a0d43f42e96].

FossilOrigin-Name: 8b7a7fcf62e5c2742c243808fa482472954f2b4aae0bc7ae513bc07065c93737
2025-06-01 21:38:35 +00:00
drh f18bf8997b Fix VACUUM so that it works even when ATTACH_WRITE is disabled.
FossilOrigin-Name: 42494f85acb303919d3f1f2202f8b95fbd657652da4b8dc00451c10ea6c496e0
2025-06-01 16:10:25 +00:00
drh c0190101d1 Enhance "box" and "column" mode formatting in the CLI to better deal with
double-wide characters.

FossilOrigin-Name: b0de22ed0abf2ea5d269f191c884d7b2be167a2ed27018c25aaa0ea238cd621a
2025-05-31 20:51:42 +00:00
dan 977b0f8813 Update a few test scripts so that they run on windows.
FossilOrigin-Name: 14a18f4e3a3f35e636262a253364ab1e8054ed38c0c7fd482633522cbcf5ffc4
2025-05-31 19:55:07 +00:00
drh 0d3e5ca28e New makefile target "xdevtest" works like "releasetest" except that it
omits the "verify-source" dependency so that it can be run with uncommitted
changes in the source tree.

FossilOrigin-Name: 1afb1ac3e9f0a122f1374799c09b60a0dd5443434d4567d94385096ada91bf12
2025-05-31 18:26:37 +00:00
dan 51e3f855b8 Fix an affinity problem caused by a USING or NATURAL JOIN on the LHS of a FULL JOIN. [forum:/forumpost/5028c785b6|Forum post 5028c785b6].
FossilOrigin-Name: 8d393ca07fe09f48d77adb517e2e4baaa58a9251422de62a0504999205d3ea1d
2025-05-31 18:16:21 +00:00
drh 5248693924 Relax query flattener constraint (3b) and thereby allow flattening the RHS of
a LEFT JOIN even if the RHS contains a virtual table.  This was previously
disallowed by [9dbae1df75219e2a] as a performance optimization.  It
turns out that the constraint causes performance issues, and we do not have
a record of any performance issue that it solves.

FossilOrigin-Name: 1ddaa92057e550ea281d45d9860eafe69399224725548a93dd91c47a34e52152
2025-05-31 16:17:14 +00:00
dan 420233e375 Fix assert() statements in os_unix.c and os_win.c. Allow walsetlk_recover.test to run in non-SQLITE_ENABLE_SNAPSHOT builds.
FossilOrigin-Name: 9f521ecda2b8d2f383cc84e308b3a4adfcf1bd6339eb834c8fa76c8704c861b7
2025-05-31 15:10:41 +00:00
stephan 1ff4233f90 Move a mis-located makefile comment block.
FossilOrigin-Name: 7d884386bec11f47c2c18002dd8c573c9b5cb6f7cdf2307a96cccead05b6abf2
2025-05-31 11:08:06 +00:00
stephan 10206572b6 tcl extension: UDFs may now 'break' to return an SQL NULL. Add the (eval -asdict) flag to use a dict, instead of an array, for the eval row data.
FossilOrigin-Name: 413a626b5c7902c1810142536c36e4ea8ee7c616ea82dfe1114199f9319091f7
2025-05-31 11:02:06 +00:00
stephan b504aab848 Add some missing UNUSED_PARAMETER() annotations to squelch downstream build warnings when using -Wextra -pedantic.
FossilOrigin-Name: a98a2f49355ec39c56e571c70d377675b1bd99a6d43cf9217b0eb1e081895d8e
2025-05-31 09:44:00 +00:00
drh d930d7ef14 Follow-up to the previous: The same optimization suppression needs to
happen if the left-hand side is coming from a LEFT JOIN.

FossilOrigin-Name: cf5b37b3a39013d8ca9de92da2289346caf52b56daff59e19b140cc586a3421f
2025-05-30 22:58:09 +00:00
dan ded1959120 If blocking locks are enabled, avoid using the busy handler when blocked by another process running recovery.
FossilOrigin-Name: a35236757ab57c4c9b34e47c5dbc10d8f1220f8152955f5303cf9c3902ee169b
2025-05-30 20:52:18 +00:00
drh dd16539e71 When synthesizing an ON constraint from a USING or NATURAL, if the left-hand
side is coming from a RIGHT JOIN, be sure to set the EP_CanBeNull flag so that
the optimizer knows to check for NULL even if the column has a NOT NULL
constraint.  Fix for the problem reported by
[forum:/forumpost/4fc70203b61c7e12|forum post 4fc70203b61]

FossilOrigin-Name: 60adc78a22956429d34ccc4e2c193c5994c11c3b3cff7901d47fad7d92dba935
2025-05-30 19:55:46 +00:00
dan 88ed38ca6d Avoid invoking the busy-handler if a blocking lock times out while attempting to open a snapshot transaction.
FossilOrigin-Name: fe11f85fd3283bb7002f43bd8b796e9e7b67f6d1a92eb676be06b46d1458fc1d
2025-05-30 18:23:03 +00:00
stephan f42ceb9075 Configure-related fixes and additions, most notably integration of self-tests for proj.tcl's APIs. Teaish make-install fixes based on the discussion in [forum:87e6660191a472c5 | forum thread 87e6660191a472c5].
FossilOrigin-Name: 2e486f8fd011d28fdd7e59ff34f7f04374019932eb160a8c4de56a5ce01e5782
2025-05-30 16:08:31 +00:00
stephan 7ac10ec8b5 Random typo fixes in JNI docs.
FossilOrigin-Name: f63608a3847469b130e029cc569fe6f03a9053352ec43c10d69849cbab4f61c5
2025-05-30 15:46:52 +00:00
drh 8ae57fab64 Use a more robust backup definition for offsetof().
FossilOrigin-Name: 22441955e03df07903b98832a60c05c53721cd67c667f6c83d5e97fcc62735ee
2025-05-30 15:43:04 +00:00
dan b65326f51a Add "include <stddef.h>" to fts5 and rtree to ensure that they use the system version of the offsetof() macro when it is available, as the built-in version triggers ubsan errors with clang.
FossilOrigin-Name: 838deb7f3423df84061a043928ed34e1d74e2e7d57ef1a9519bb32fea82e4352
2025-05-30 11:14:11 +00:00
stephan 0148820fd7 Squelch an interesting but harmless struct initialization warning emitted after an emsdk update. Fix JS breakage introduced by changes in Emscripten 4.0.7: manually export the HEAPxyz symbols which used to be exposed by default.
FossilOrigin-Name: 10d0897cc9a5998fe1344cfbb242a78b59012e29aa3b1993895dfac26721b053
2025-05-30 10:18:09 +00:00
stephan d2b230a488 Fix the missing -lm link flag for the sqlite3 shell when building the autoconf bundle with --disable-static-shell, as reported in [forum:5adf1c932a | forum post 5adf1c932a].
FossilOrigin-Name: f6318c4a6b5a133657741c066ef2c76a71880dbc98cfff1fdd632637daf002dc
2025-05-29 20:29:13 +00:00
drh f429845a60 Extend the fix for ticket [623eff57e76d45f6] so that it covers RIGHT JOIN
in addition to LEFT JOIN.  Problem reported by 
[forum:/forumpost/7dee41d32506c4ae|forum post 2025-05-29T15:10:14Z].

FossilOrigin-Name: 29b1e1b97619d03a97ef562a5707929e241d019179b4ff1d0bc2a8c008441431
2025-05-29 18:44:41 +00:00
drh b163f66de0 Fix a goofy hash function in Lemon. No changes to SQLite itself.
FossilOrigin-Name: d6cbabe23d3919d5bde6a83421cdae92125caec09d5c39a648d0305878c6a1dc
2025-05-29 17:46:34 +00:00
drh 3f52361352 Version 3.50.0
FossilOrigin-Name: dfc790f998f450d9c35e3ba1c8c89c17466cb559f87b0239e4aab9d34e28f742
2025-05-29 14:26:00 +00:00
drh b3c1884b65 Do not use a partial index unless the WHERE clause uses one or more columns
from the table being indexed.  This resolves the issue reported by
[forum:/forumpost/a8704b30f3|forum post 2025-05-28T13:03:40Z]. Test cases
are in TH3.

FossilOrigin-Name: f037ca064daeb81cb386da2a372d8e2d2dce55a3a13bc7bea4968ca51bf2843a
2025-05-28 16:56:23 +00:00
drh b3bcf489a4 Do not use a partial index if the truth of the WHERE clause does not depend
on at least one column from the table being indexed.

FossilOrigin-Name: cbe2a392e45d40778570656d2ef2db43e58ad6453bd9d4b936fecfd963e22736
2025-05-28 14:59:42 +00:00
drh f08f71a21d Slight change to tool/split-sqlite3c.tcl to make it compatible with jimsh
FossilOrigin-Name: fe670ddda933007386eb10facf4048ee88671f74b1fd41dfc3120beb717b8c9e
2025-05-26 23:20:23 +00:00
drh f96d44e5de Fix a bug in the speedtest.tcl testing script that was introduced by
[7e9845433ff26bdc]

FossilOrigin-Name: e4ffa86aa6ca82a42933281f6cbfca7bad702797eb8d6e684a1992e68dc1cfb7
2025-05-26 17:29:13 +00:00
stephan 209894c2f5 In the TEA build, enable USE_TCL_STUBS on Mac platforms.
FossilOrigin-Name: 0b5415151c9bf558378f83b1a60df3d3760f1aa311895af04e1fb79a8fb29e79
2025-05-26 16:59:49 +00:00
dan 93394ebc27 On OpenBSD, do not test fuzzcheck with ubsan as part of "make devtest".
FossilOrigin-Name: a3dabd599c3d3143b67258b307d352968e5f5d4ea0456940d16ae678de8c95eb
2025-05-26 16:17:06 +00:00
drh 8f06aed1df Avoid calls to sprintf() in Lemon, since OpenBSD hates sprintf().
FossilOrigin-Name: ed17858ddf833b6b9c2164f31ee9138a998d28ec1564d09e20deb102eefedbc8
2025-05-26 15:36:43 +00:00
stephan 3f01048954 When detecting TCLLIBDIR, skip over //zipfs paths, as the (file isdirectory) command will actually return true for those, but they're useless for installation purposes. This resolves the tea build's inability to install on stock openbsd.
FossilOrigin-Name: 5b29724a3287c9a910f303faf056d0706b66c3e6ba23f9746c11d775c631f374
2025-05-26 15:20:57 +00:00
stephan 45fa2347fe tclsqlite.c doc typo fix.
FossilOrigin-Name: de0dfac1e5ca9d2661674c20664095386f60c77378311507fcba08111df52b38
2025-05-26 07:15:20 +00:00
drh a01b7adb13 Change json_group_object() so that it ignores entries where the label
is NULL.  [forum:/forumpost/e5bd251fb5|Forum post e5bd251fb5].

FossilOrigin-Name: 28215d131cd970a2756338579fb6b6091ab155be8f419505cae8ac918956165c
2025-05-24 20:20:20 +00:00
stephan c5031b578b vtablog.c doc fixes reported in [forum:416d1e37b2|forum post 416d1e37b2].
FossilOrigin-Name: 5d25f62bcd2d754134f608162778b49b0e71c29bd5a6f2461a07caca3d76c7de
2025-05-24 16:01:50 +00:00
drh 81a2f7ba8f Amend the previous: Set SQLITE_JSON_MAX_DEPTH to 500 on *all* builds
of fuzzcheck.

FossilOrigin-Name: c266e38c5b61f47b920027aad418b641ab32cb8a3360dbcfd9f9f29b14fd5375
2025-05-24 01:34:41 +00:00
drh 85f37eba16 Limit JSON recursion depth to 500 when running ASAN in fuzzcheck, to prevent
stack overflow on ARM64.

FossilOrigin-Name: 5e96e177a040b46aa55492037ce5dc71ab49d66b45659d739f2ee6c3042f16ef
2025-05-23 20:50:49 +00:00
drh c1ea1a6d4d Add the --osmalloc option to the test/speedtest.tcl testing script.
Adjust ./configure so that it does not check for malloc_usable_size().

FossilOrigin-Name: 7e9845433ff26bdc5fe8654281d584394b77e3b206d09669b4468e0271c6eb37
2025-05-23 14:52:23 +00:00
dan 96e16194b8 Fix a problem with using streaming iterators with sqlite3changegroup_add_change().
FossilOrigin-Name: 3dbde727146d28c316df47c7b5116be7f2476a0a0c893207c2a4ca3ab285cb5e
2025-05-22 18:04:48 +00:00
drh 4a0b7a332f Clarify some malloc size computations to simplify the proof that they
are safe.  Remove some code associated with cygwin that is marked "#if 0".

FossilOrigin-Name: ba8184d132a935aa1980fbfb61ff308b93d433d559db4968f9014f7653ac9c6e
2025-05-19 14:50:36 +00:00
drh 79c792d5d9 Make the new sqlite3_setlk_timeout() interface accessible to loadable
extensions.

FossilOrigin-Name: 8819b7285b71932327f47d29fa575cfb338e2fccd3f7c2023faf0575bfdb0079
2025-05-19 14:04:48 +00:00
drh 890de76cf5 Remove stray tab characters from source files.
FossilOrigin-Name: 298ff5a1dc5dbccaf6acd91731044f478a5ce522745332801708ceee996b01e6
2025-05-19 12:46:08 +00:00
drh a58208a214 Fix a harmless comment typo
FossilOrigin-Name: c4d25acec3c1e28e5a4664a74c263cc0d00e118a6db4b26b51cb0d42d0f2b26f
2025-05-19 12:34:11 +00:00
drh acf95a3217 Adjust the tool/warnings.sh script so that it works on the latest versions
of clang on Mac.

FossilOrigin-Name: 05a3dd9a179193d00968329152c8ffe6532f0cbdad7d19b47af32aebc0cd0d9e
2025-05-19 11:08:30 +00:00
stephan 953e450e8e Latest teaish pieces, most significantly for tcl portability fixes. Move autoconf/teaish/autosetup/... to autosetup/teaish/. to simplify maintenance and deployment via the autoconf bundle.
FossilOrigin-Name: 381d3e82e831bedee56108fb585880d802c4d7d50b0804d909a33ff15a3be185
2025-05-17 11:06:02 +00:00
86 changed files with 2195 additions and 1152 deletions
+11 -6
View File
@@ -1623,7 +1623,6 @@ TESTSRC = \
$(TOP)\src\test_thread.c \
$(TOP)\src\test_vdbecov.c \
$(TOP)\src\test_vfs.c \
$(TOP)\src\test_windirent.c \
$(TOP)\src\test_window.c \
$(TOP)\src\test_wsd.c \
$(TOP)\ext\fts3\fts3_term.c \
@@ -2395,12 +2394,11 @@ SHELL_DEP = \
$(TOP)\ext\misc\sqlite3_stdio.h \
$(TOP)\ext\misc\uint.c \
$(TOP)\ext\misc\vfstrace.c \
$(TOP)\ext\misc\windirent.h \
$(TOP)\ext\misc\zipfile.c \
$(TOP)\ext\recover\dbdata.c \
$(TOP)\ext\recover\sqlite3recover.c \
$(TOP)\ext\recover\sqlite3recover.h \
$(TOP)\src\test_windirent.c \
$(TOP)\src\test_windirent.h
$(TOP)\ext\recover\sqlite3recover.h
# If use of zlib is enabled, add the "zipfile.c" source file.
#
@@ -2585,7 +2583,7 @@ sqlite_tcl.h:
testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
-DBUILD_sqlite -I$(TCLINCDIR) \
-DBUILD_sqlite -I$(TCLINCDIR) -I$(TOP)\ext\misc \
$(TESTFIXTURE_SRC) \
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
@@ -2674,7 +2672,14 @@ srctree-check: $(TOP)\tool\srctree-check.tcl
# Testing for a release
#
releasetest:
releasetest: verify-source
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
# xdevtest is like releasetest, except that it skips the
# dependency on verify-source so that xdevtest can be run from
# a modified source tree.
#
xdevtest:
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
+1 -1
View File
@@ -1 +1 @@
3.50.0
3.51.0
+1 -1
View File
@@ -224,7 +224,7 @@ install: install-lib
#
ENABLE_STATIC_SHELL = @ENABLE_STATIC_SHELL@
sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS.libsqlite3)
sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib)
sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib) $(LDFLAGS.math)
sqlite3-shell-deps.1 = $(TOP)/sqlite3.c
sqlite3-shell-deps.0 = $(libsqlite3.DLL)
#
+51 -28
View File
@@ -146,7 +146,7 @@ LDFLAGS.shlib = @SH_LDFLAGS@
# sources passed to [teaish-src-add], but may also be appended to by
# teaish.make.
#
tx.src =@TEAISH_EXT_SRC@
tx.src = @TEAISH_EXT_SRC@
#
# tx.CFLAGS is typically set by teaish.make, whereas TEAISH_CFLAGS
@@ -167,6 +167,11 @@ tx.LDFLAGS =
#
tx.dist.files = @TEAISH_DIST_FILES@
#
# The base name for a distribution tar/zip file.
#
tx.dist.basename = $(tx.name.dist)-$(tx.version)
# List of deps which may trigger an auto-reconfigure.
#
teaish__autogen.deps = \
@@ -199,9 +204,14 @@ $(teaish.makefile): $(teaish__auto.def) $(teaish.makefile.in) \
@AUTODEPS@
@if TEAISH_TESTER_TCL_IN
@TEAISH_TESTER_TCL_IN@:
@TEAISH_TESTER_TCL@: @TEAISH_TESTER_TCL_IN@
config.log: @TEAISH_TESTER_TCL@
@TEAISH_TESTER_TCL_IN@: $(teaish__autogen.deps)
config.log: @TEAISH_TESTER_TCL_IN@
@TEAISH_TESTER_TCL@: @TEAISH_TESTER_TCL_IN@
@endif
@if TEAISH_TEST_TCL_IN
@TEAISH_TEST_TCL_IN@: $(teaish__autogen.deps)
config.log: @TEAISH_TEST_TCL_IN@
@TEAISH_TEST_TCL@: @TEAISH_TEST_TCL_IN@
@endif
#
@@ -217,7 +227,7 @@ CC.tcl = \
#
CC.dll = \
$(CC.tcl) $(tx.src) $(LDFLAGS.shlib) \
$(LDFLAGS.configure) $(LDFLAGS) $(tx.LDFLAGS) $(TCL_STUB_LIB_SPEC)
$(tx.LDFLAGS) $(LDFLAGS.configure) $(LDFLAGS) $(TCL_STUB_LIB_SPEC)
@if TEAISH_ENABLE_DLL
#
@@ -248,16 +258,25 @@ test-extension: # this name is reserved for use by teaish.make[.in]
test-prepre: $(tx.dll)
@endif
@if TEAISH_TESTER_TCL
test-core.args = @TEAISH_TESTER_TCL@
teaish.tester.tcl = @TEAISH_TESTER_TCL@
test-core.args = $(teaish.tester.tcl)
@if TEAISH_ENABLE_DLL
test-core.args += '$(tx.dll)' '$(tx.loadPrefix)'
@else
test-core.args += '' ''
@endif
test-core.args += @TEAISH_TESTUTIL_TCL@
# Clients may pass additional args via test.args=...
# and ::argv will be rewritten before the test script loads, to
# remove $(test-core.args)
test.args ?=
test-core: test-pre
$(TCLSH) $(test-core.args)
test-prepre: @TEAISH_TESTER_TCL@
$(TCLSH) $(test-core.args) $(test.args)
test-gdb: $(teaish.tester.tcl)
gdb --args $(TCLSH) $(test-core.args) $(test.args)
test-vg.flags ?= --leak-check=full -v --show-reachable=yes --track-origins=yes
test-vg: $(teaish.tester.tcl)
valgrind $(test-vg.flags) $(TCLSH) $(test-core.args) $(test.args)
@else # !TEAISH_TESTER_TCL
test-prepre:
@endif # TEAISH_TESTER_TCL
@@ -288,7 +307,7 @@ distclean-core: distclean-pre
@endif
@endif
@if TEAISH_TESTER_TCL_IN
rm -f @TEAISH_TESTER_TCL@
rm -f $(teaish.tester.tcl)
@endif
@if TEAISH_PKGINDEX_TCL_IN
rm -f @TEAISH_PKGINDEX_TCL@
@@ -355,10 +374,15 @@ install-core: install-pre
@endif
install-test: install-core
@echo "Post-install test of [package require $(tx.name.pkg) $(tx.version)]..."; \
set xtra=""; \
if [ x != "x$(DESTDIR)" ]; then \
xtra='set ::auto_path [linsert $$::auto_path 0 [file normalize $(DESTDIR)$(TCLLIBDIR)/..]];'; \
fi; \
if echo \
'set c 0; ' \
'set c 0; ' $$xtra \
'@TEAISH_POSTINST_PREREQUIRE@' \
'if {[catch {package require $(tx.name.pkg) $(tx.version)}]} {incr c};' \
'if {[catch {package require $(tx.name.pkg) $(tx.version)} xc]} {incr c};' \
'if {$$c && "" ne $$xc} {puts $$xc; puts "auto_path=$$::auto_path"};' \
'exit $$c' \
| $(TCLSH) ; then \
echo "passed"; \
@@ -406,7 +430,7 @@ config.log: $(teaish.makefile.in)
# recognized when running in --teaish-install mode, causing
# the sub-configure to fail.
dist.flags = --with-tclsh=$(TCLSH)
dist.reconfig = $(teaish.dir)/configure $(dist.flags)
dist.reconfig = $(teaish.dir)/configure $(tx.dist.reconfig-flags) $(dist.flags)
# Temp dir for dist.zip. Must be different than dist.tgz or else
# parallel builds may hose the dist.
@@ -414,24 +438,23 @@ teaish__dist.tmp.zip = teaish__dist_zip
#
# Make a distribution zip file...
#
dist.basename = $(tx.name.dist)-$(tx.version)
dist.zip = $(dist.basename).zip
dist.zip = $(tx.dist.basename).zip
.PHONY: dist.zip dist.zip-core dist.zip-post
#dist.zip-pre:
# We apparently can't add a pre-hook here, else "make dist" rebuilds
# the archive each time it's run.
$(dist.zip): $(tx.dist.files)
@rm -fr $(teaish__dist.tmp.zip)
@mkdir -p $(teaish__dist.tmp.zip)/$(dist.basename)
@mkdir -p $(teaish__dist.tmp.zip)/$(tx.dist.basename)
@tar cf $(teaish__dist.tmp.zip)/tmp.tar $(tx.dist.files)
@tar xf $(teaish__dist.tmp.zip)/tmp.tar -C $(teaish__dist.tmp.zip)/$(dist.basename)
@tar xf $(teaish__dist.tmp.zip)/tmp.tar -C $(teaish__dist.tmp.zip)/$(tx.dist.basename)
@if TEAISH_DIST_FULL
@$(dist.reconfig) \
--teaish-install=$(teaish__dist.tmp.zip)/$(dist.basename) \
--t-e-d=$(teaish__dist.tmp.zip)/$(dist.basename) >/dev/null
--teaish-install=$(teaish__dist.tmp.zip)/$(tx.dist.basename) \
--t-e-d=$(teaish__dist.tmp.zip)/$(tx.dist.basename) >/dev/null
@endif
@rm -f $(dist.basename)/tmp.tar $(dist.zip)
@cd $(teaish__dist.tmp.zip) && zip -q -r ../$(dist.zip) $(dist.basename)
@rm -f $(tx.dist.basename)/tmp.tar $(dist.zip)
@cd $(teaish__dist.tmp.zip) && zip -q -r ../$(dist.zip) $(tx.dist.basename)
@rm -fr $(teaish__dist.tmp.zip)
@ls -la $(dist.zip)
dist.zip-core: $(dist.zip)
@@ -447,23 +470,23 @@ undist: undist-zip
# Make a distribution tarball...
#
teaish__dist.tmp.tgz = teaish__dist_tgz
dist.tgz = $(dist.basename).tar.gz
dist.tgz = $(tx.dist.basename).tar.gz
.PHONY: dist.tgz dist.tgz-core dist.tgz-post
# dist.tgz-pre:
# see notes in dist.zip
$(dist.tgz): $(tx.dist.files)
@rm -fr $(teaish__dist.tmp.tgz)
@mkdir -p $(teaish__dist.tmp.tgz)/$(dist.basename)
@mkdir -p $(teaish__dist.tmp.tgz)/$(tx.dist.basename)
@tar cf $(teaish__dist.tmp.tgz)/tmp.tar $(tx.dist.files)
@tar xf $(teaish__dist.tmp.tgz)/tmp.tar -C $(teaish__dist.tmp.tgz)/$(dist.basename)
@tar xf $(teaish__dist.tmp.tgz)/tmp.tar -C $(teaish__dist.tmp.tgz)/$(tx.dist.basename)
@if TEAISH_DIST_FULL
@rm -f $(teaish__dist.tmp.tgz)/$(dist.basename)/pkgIndex.tcl.in; # kludge
@rm -f $(teaish__dist.tmp.tgz)/$(tx.dist.basename)/pkgIndex.tcl.in; # kludge
@$(dist.reconfig) \
--teaish-install=$(teaish__dist.tmp.tgz)/$(dist.basename) \
--t-e-d=$(teaish__dist.tmp.zip)/$(dist.basename) >/dev/null
--teaish-install=$(teaish__dist.tmp.tgz)/$(tx.dist.basename) \
--t-e-d=$(teaish__dist.tmp.zip)/$(tx.dist.basename) >/dev/null
@endif
@rm -f $(dist.basename)/tmp.tar $(dist.tgz)
@cd $(teaish__dist.tmp.tgz) && tar czf ../$(dist.tgz) $(dist.basename)
@rm -f $(tx.dist.basename)/tmp.tar $(dist.tgz)
@cd $(teaish__dist.tmp.tgz) && tar czf ../$(dist.tgz) $(tx.dist.basename)
@rm -fr $(teaish__dist.tmp.tgz)
@ls -la $(dist.tgz)
dist.tgz-core: $(dist.tgz)
+28 -33
View File
@@ -41,24 +41,32 @@ step-by-step instructions at the links below for more information:
https://sqlite.org/src/doc/trunk/doc/compile-for-unix.md
https://sqlite.org/src/doc/trunk/doc/compile-for-windows.md
The whole point of the amalgamation-autoconf tarball (in which this
README.txt file is embedded) is to provide a means of compiling
SQLite that does not require first installing TCL and/or "tclsh".
The canonical Makefile in the SQLite source tree provides more
capabilities (such as the the ability to run test cases to ensure
that the build worked) and is better maintained. The only
downside of the canonical Makefile is that it requires a TCL
installation. But if you are wanting to build the TCL extension for
SQLite, then presumably you already have a TCL installation. So why
not just use the more-capable and better-maintained canoncal Makefile?
And info about the extension's Tcl interface can be found at:
This TEA builder is derived from code found at
https://sqlite.org/tclsqlite.html
The whole point of the amalgamation-autoconf tarball (in which this
README.txt file is embedded) is to provide a means of compiling SQLite
that does not require first installing TCL and/or "tclsh". The
canonical Makefile in the SQLite source tree provides more
capabilities (such as the the ability to run test cases to ensure that
the build worked) and is better maintained. The only downside of the
canonical Makefile is that it requires a TCL installation. But if you
are wanting to build the TCL extension for SQLite, then presumably you
already have a TCL installation. So why not just use the more-capable
and better-maintained canoncal Makefile?
As of version 3.50.0, this build process uses "teaish":
https://fossil.wanderinghorse.net/r/teaish
which is conceptually derived from the pre-3.50 toolchain, TEA:
http://core.tcl-lang.org/tclconfig
http://core.tcl-lang.org/sampleextension
The SQLite developers do not understand how it works. It seems to
work for us. It might also work for you. But we cannot promise that.
It to works for us. It might also work for you. But we cannot
promise that.
If you want to use this TEA builder and it works for you, that's fine.
But if you have trouble, the first thing you should do is go back
@@ -70,30 +78,17 @@ to using the canonical Makefile in the SQLite source tree.
UNIX BUILD
==========
Building under most UNIX systems is easy, just run the configure script
and then run make. For more information about the build process, see
the tcl/unix/README file in the Tcl src dist. The following minimal
example will install the extension in the /opt/tcl directory.
Building under most UNIX systems is easy, just run the configure
script and then run make. For example:
$ cd sqlite-*-tea
$ ./configure --prefix=/opt/tcl
$ make
$ ./configure --with-tcl=/path/to/tcl/install/root
$ make test
$ make install
WINDOWS BUILD
=============
The recommended method to build extensions under windows is to use the
Msys + Mingw build process. This provides a Unix-style build while
generating native Windows binaries. Using the Msys + Mingw build tools
means that you can use the same configure script as per the Unix build
to create a Makefile. See the tcl/win/README file for the URL of
the Msys + Mingw download.
If you have VC++ then you may wish to use the files in the win
subdirectory and build the extension using just VC++. These files have
been designed to be as generic as possible but will require some
additional maintenance by the project developer to synchronise with
the TEA configure.in and Makefile.in files. Instructions for using the
VC++ makefile are written in the first part of the Makefile.vc
file.
On Windows this build is known to work on Cygwin and some Msys2
environments. We do not currently support Microsoft makefiles for
native Windows builds.
+2 -1
View File
@@ -21,7 +21,8 @@ if {[llength [lindex $::argv 0]] > 0} {
# ----^^^^^^^ needed on Haiku when argv 0 is just a filename, else
# load cannot find the file.
}
source -encoding utf-8 [lindex $::argv 2]; # teaish/tester.tcl
set ::argv [lassign $argv - -]
source -encoding utf-8 [lindex $::argv 0]; # teaish/tester.tcl
@if TEAISH_PKGINIT_TCL
apply {{file} {
set dir [file dirname $::argv0]
-15
View File
@@ -1,15 +0,0 @@
.TH sqlite3 n 4.1 "Tcl-Extensions"
.HS sqlite3 tcl
.BS
.SH NAME
sqlite3 \- an interface to the SQLite3 database engine
.SH SYNOPSIS
\fBsqlite3\fI command_name ?filename?\fR
.br
.SH DESCRIPTION
SQLite3 is a self-contains, zero-configuration, transactional SQL database
engine. This extension provides an easy to use interface for accessing
SQLite database files from Tcl.
.PP
For full documentation see \fIhttps://sqlite.org/\fR and
in particular \fIhttps://sqlite.org/tclsqlite.html\fR.
+1 -2
View File
@@ -67,6 +67,7 @@ apply {{dir} {
-vsatisfies 8.6-
-libDir sqlite$version
-pragmas $pragmas
-src generic/tclsqlite3.c
}
}} [teaish-get -dir]
@@ -119,8 +120,6 @@ proc teaish-options {} {
proc teaish-configure {} {
use teaish/feature
teaish-src-add -dist -dir generic/tclsqlite3.c
if {[proj-opt-was-provided override-sqlite-version]} {
teaish-pkginfo-set -version [opt-val override-sqlite-version]
proj-warn "overriding sqlite version number:" [teaish-pkginfo-get -version]
+387 -123
View File
@@ -60,10 +60,11 @@
# $proj__Config is an internal-use-only array for storing whatever generic
# internal stuff we need stored.
#
array set ::proj__Config {
self-tests 1
}
array set ::proj__Config [subst {
self-tests [get-env proj.self-tests 0]
verbose-assert [get-env proj.assert-verbose 0]
isatty [isatty? stdout]
}]
#
# List of dot-in files to filter in the final stages of
@@ -75,7 +76,6 @@ array set ::proj__Config {
# See: proj-dot-ins-append and proj-dot-ins-process
#
set ::proj__Config(dot-in-files) [list]
set ::proj__Config(isatty) [isatty? stdout]
#
# @proj-warn msg
@@ -85,28 +85,29 @@ set ::proj__Config(isatty) [isatty? stdout]
#
proc proj-warn {args} {
show-notices
puts stderr [join [list "WARNING: \[[proj-scope 1]\]: " {*}$args] " "]
puts stderr [join [list "WARNING:" \[ [proj-scope 1] \]: {*}$args] " "]
}
#
# Internal impl of [proj-fatal] and [proj-error]. It must be called
# using tailcall.
proc proj__faterr {failMode argv} {
#
proc proj__faterr {failMode args} {
show-notices
set lvl 1
while {"-up" eq [lindex $argv 0]} {
set argv [lassign $argv -]
while {"-up" eq [lindex $args 0]} {
set args [lassign $args -]
incr lvl
}
if {$failMode} {
puts stderr [join [list "FATAL: \[[proj-scope $lvl]]: " {*}$argv]]
puts stderr [join [list "FATAL:" \[ [proj-scope $lvl] \]: {*}$args]]
exit 1
} else {
error [join [list "\[[proj-scope $lvl]]:" {*}$argv]]
error [join [list in \[ [proj-scope $lvl] \]: {*}$args]]
}
}
#
# @proj-fatal ?-up...? msg...
#
@@ -118,7 +119,7 @@ proc proj__faterr {failMode argv} {
# additional level.
#
proc proj-fatal {args} {
tailcall proj__faterr 1 $args
tailcall proj__faterr 1 {*}$args
}
#
@@ -127,10 +128,9 @@ proc proj-fatal {args} {
# Works like proj-fatal but uses [error] intead of [exit].
#
proc proj-error {args} {
tailcall proj__faterr 0 $args
tailcall proj__faterr 0 {*}$args
}
set ::proj__Config(verbose-assert) [get-env proj-assert-verbose 0]
#
# @proj-assert script ?message?
#
@@ -147,7 +147,7 @@ proc proj-assert {script {msg ""}} {
if {"" eq $msg} {
set msg $script
}
proj-fatal "Assertion failed in \[[proj-scope 1]\]: $msg"
tailcall proj__faterr 1 "Assertion failed:" $msg
}
}
@@ -885,7 +885,9 @@ proc proj-looks-like-windows {{key host}} {
#
proc proj-looks-like-mac {{key host}} {
switch -glob -- [get-define $key] {
*apple* {
*-*-darwin {
# https://sqlite.org/forum/forumpost/7b218c3c9f207646
# There's at least one Linux out there which matches *apple*.
return 1
}
default {
@@ -927,17 +929,13 @@ proc proj-exe-extension {} {
#
proc proj-dll-extension {} {
set inner {{key} {
switch -glob -- [get-define $key] {
*apple* {
return ".dylib"
}
*-*-ming* - *-*-cygwin - *-*-msys {
return ".dll"
}
default {
return ".so"
}
if {[proj-looks-like-mac $key]} {
return ".dylib"
}
if {[proj-looks-like-windows $key]} {
return ".dll"
}
return ".so"
}}
define BUILD_DLLEXT [apply $inner build]
define TARGET_DLLEXT [apply $inner host]
@@ -1665,7 +1663,7 @@ proc proj-dot-ins-append {fileIn args} {
proj-fatal "Too many arguments: $fileIn $args"
}
}
#puts "******* [proj-scope]: adding $fileIn"
#puts "******* [proj-scope]: adding [llength $fileIn]-length item: $fileIn"
lappend ::proj__Config(dot-in-files) $fileIn
}
@@ -1703,17 +1701,18 @@ proc proj-dot-ins-list {} {
# makes proj-dot-ins-append available for re-use.
#
proc proj-dot-ins-process {args} {
proj-parse-simple-flags args flags {
proj-parse-flags args flags {
-touch "" {return "-touch"}
-clear 0 {expr 1}
-validate 0 {expr 1}
}
#puts "args=$args"; parray flags
if {[llength $args] > 0} {
error "Invalid argument to [proj-scope]: $args"
}
foreach f $::proj__Config(dot-in-files) {
proj-assert {3==[llength $f]} \
"Expecting proj-dot-ins-list to be stored in 3-entry lists"
"Expecting proj-dot-ins-list to be stored in 3-entry lists. Got: $f"
lassign $f fIn fOut fScript
#puts "DOING $fIn ==> $fOut"
proj-make-from-dot-in {*}$flags(-touch) $fIn $fOut
@@ -1753,7 +1752,7 @@ proc proj-validate-no-unresolved-ats {args} {
set isMake [string match {*[Mm]ake*} $f]
foreach line [proj-file-content-list $f] {
if {!$isMake || ![string match "#*" [string trimleft $line]]} {
if {[regexp {(@[A-Za-z0-9_]+@)} $line match]} {
if {[regexp {(@[A-Za-z0-9_\.]+@)} $line match]} {
error "Unresolved reference to $match at line $lnno of $f"
}
}
@@ -1893,7 +1892,7 @@ proc proj-define-amend {args} {
#
proc proj-define-to-cflag {args} {
set rv {}
proj-parse-simple-flags args flags {
proj-parse-flags args flags {
-list 0 {expr 1}
-quote 0 {expr 1}
-zero-undef 0 {expr 1}
@@ -2001,7 +2000,7 @@ proc proj-cache-key {arg {addLevel 0}} {
# See proj-cache-key for -key's and -level's semantics, noting that
# this function adds one to -level for purposes of that call.
proc proj-cache-set {args} {
proj-parse-simple-flags args flags {
proj-parse-flags args flags {
-key => 0
-level => 0
}
@@ -2037,7 +2036,7 @@ proc proj-cache-remove {{key 0} {addLevel 0}} {
# See proj-cache-key for $key's and $addLevel's semantics, noting that
# this function adds one to $addLevel for purposes of that call.
proc proj-cache-check {args} {
proj-parse-simple-flags args flags {
proj-parse-flags args flags {
-key => 0
-level => 0
}
@@ -2070,147 +2069,316 @@ proc proj-coalesce {args} {
}
#
# @proj-parse-simple-flags ...
# @proj-parse-flags argvListName targetArrayName {prototype}
#
# A helper to parse flags from proc argument lists.
#
# Expects a list of arguments to parse, an array name to store any
# -flag values to, and a prototype object which declares the flags.
# The first argument is the name of a var holding the args to
# parse. It will be overwritten, possibly with a smaller list.
#
# The prototype must be a list in one of the following forms:
# The second argument is the name of an array variable to create in
# the caller's scope.
#
# -flag defaultValue {script}
# The third argument, $prototype, is a description of how to handle
# the flags. Each entry in that list must be in one of the
# following forms:
#
# -flag => defaultValue
# -----^--^ (with spaces there!)
# -flag defaultValue ?-literal|-call|-apply?
# script|number|incr|proc-name|{apply $aLambda}
#
# Repeated for each flag.
# -flag* ...as above...
#
# The first form represents a basic flag with no associated
# following argument. The second form extracts its value
# from the following argument in $argvName.
# -flag => defaultValue ?-call proc-name-and-args|-apply lambdaExpr?
#
# The first argument to this function is the name of a var holding the
# args to parse. It will be overwritten, possibly with a smaller list.
# -flag* => ...as above...
#
# The second argument the name of an array variable to create in the
# caller's scope. (Pneumonic: => points to the next argument.)
# :PRAGMA
#
# For the first form of flag, $script is run in the caller's scope if
# $argv contains -flag, and the result of that script is the new value
# for $tgtArrayName(-flag). This function intercepts [return $val]
# from $script. Any empty script will result in the flag having ""
# assigned to it.
# The first two forms represents a basic flag with no associated
# following argument. The third and fourth forms, called arg-consuming
# flags, extract the value from the following argument in $argvName
# (pneumonic: => points to the next argument.). The :PRAGMA form
# offers a way to configure certain aspects of this call.
#
# The args list is only inspected until the first argument which is
# not described by $prototype. i.e. the first "non-flag" (not counting
# values consumed for flags defined like --flag=>default).
# If $argv contains any given flag from $prototype, its default value
# is overridden depending on several factors:
#
# - If the -literal flag is used, or the flag's script is a number,
# value is used verbatim.
#
# - Else if the -call flag is used, the argument must be a proc name
# and any leading arguments, e.g. {apply $myLambda}. The proc is passed
# the (flag, value) as arguments (non-consuming flags will get
# passed the flag's current/starting value and consuming flags will
# get the next argument). Its result becomes the result of the
# flag.
#
# - Else if -apply X is used, it's effectively shorthand for -call
# {apply X}. Its argument may either be a $lambaRef or a {{f v}
# {body}} construct.
#
# - Else if $script is one of the following values, it is treated as
# the result of...
#
# - incr: increments the current value of the flag.
#
# - Else $script is eval'd to get its result value. That result
# becomes the new flag value for $tgtArrayName(-flag). This
# function intercepts [return $val] from eval'ing $script. Any
# empty script will result in the flag having "" assigned to it.
#
# Unless the -flag has a trailing asterisk, e.g. -flag*, this function
# assumes that each flag is unique, and using a flag more than once
# causes an error to be triggered. the -flag* forms works similarly
# except that may appear in $argv any number of times:
#
# - For non-arg-consuming flags, each invocation of -flag causes the
# result of $script to overwrite the previous value. e.g. so
# {-flag* {x} {incr foo}} has a default value of x, but passing in
# -flag twice would change it to the result of incrementing foo
# twice. This form can be used to implement, e.g., increasing
# verbosity levels by passing -verbose multiple times.
#
# - For arg-consuming flags, the given flag starts with value X, but
# if the flag is provided in $argv, the default is cleared, then
# each instance of -flag causes its value to be appended to the
# result, so {-flag* => {a b c}} defaults to {a b c}, but passing
# in -flag y -flag z would change it to {y z}, not {a b c y z}..
#
# By default, the args list is only inspected until the first argument
# which is not described by $prototype. i.e. the first "non-flag" (not
# counting values consumed for flags defined like -flag => default).
# The :all-flags pragma (see below) can modify this behavior.
#
# If a "--" flag is encountered, no more arguments are inspected as
# flags. If "--" is the first non-flag argument, the "--" flag is
# removed from the results but all remaining arguments are passed
# through. If "--" appears after the first non-flag, it is retained.
# flags unless the :all-flags pragma (see below) is in effect. The
# first instance of "--" is removed from the target result list but
# all remaining instances of "--" are are passed through.
#
# This function assumes that each flag is unique, and using a flag
# more than once behaves in a last-one-wins fashion.
# Any argvName entries not described in $prototype are considered to
# be "non-flags" for purposes of this function, even if they
# ostensibly look like flags.
#
# Any argvName entries not described in $prototype are not treated as
# flags.
#
# Returns the number of flags it processed in $argvName.
# Returns the number of flags it processed in $argvName, not counting
# "--".
#
# Example:
#
# set args [list -foo -bar {blah} 8 9 10 -theEnd]
# proj-parse-simple-flags args flags {
# -foo 0 {expr 1}
# -bar => 0
# -no-baz 2 {return 0}
# }
## set args [list -foo -bar {blah} -z 8 9 10 -theEnd]
## proj-parse-flags args flags {
## -foo 0 {expr 1}
## -bar => 0
## -no-baz 1 {return 0}
## -z 0 2
## }
#
# After that $flags would contain {-foo 1 -bar {blah} -no-baz 2}
# After that $flags would contain {-foo 1 -bar {blah} -no-baz 1 -z 2}
# and $args would be {8 9 10 -theEnd}.
#
# Potential TODOs: consider using lappend instead of set so that any
# given flag can be used more than once. Or add a syntax to indicate
# that multiples are allowed. Also consider searching the whole
# argv list, rather than stopping at the first non-flag
# Pragmas:
#
proc proj-parse-simple-flags {argvName tgtArrayName prototype} {
# Passing :PRAGMAS to this function may modify how it works. The
# following pragmas are supported (note the leading ":"):
#
# :all-flags indicates that the whole input list should be scanned,
# not stopping at the first non-flag or "--".
#
proc proj-parse-flags {argvName tgtArrayName prototype} {
upvar $argvName argv
upvar $tgtArrayName tgt
array set dflt {}
array set scripts {}
array set consuming {}
upvar $tgtArrayName outFlags
array set flags {}; # staging area
array set blob {}; # holds markers for various per-key state and options
set incrSkip 1; # 1 if we stop at the first non-flag, else 0
# Parse $prototype for flag definitions...
set n [llength $prototype]
# Figure out what our flags are...
set checkProtoFlag {
#puts "**** checkProtoFlag #$i of $n k=$k fv=$fv"
switch -exact -- $fv {
-literal {
proj-assert {![info exists blob(${k}.consumes)]}
set blob(${k}.script) [list expr [lindex $prototype [incr i]]]
}
-apply {
set fv [lindex $prototype [incr i]]
if {2 == [llength $fv]} {
# Treat this as a lambda literal
set fv [list $fv]
}
lappend blob(${k}.call) "apply $fv"
}
-call {
# arg is either a proc name or {apply $aLambda}
set fv [lindex $prototype [incr i]]
lappend blob(${k}.call) $fv
}
default {
proj-assert {![info exists blob(${k}.consumes)]}
set blob(${k}.script) $fv
}
}
if {$i >= $n} {
proj-error -up "[proj-scope]: Missing argument for $k flag"
}
}
for {set i 0} {$i < $n} {incr i} {
set k [lindex $prototype $i]
#puts "**** #$i of $n k=$k"
proj-assert {[string match -* $k]} \
"Invalid flag value: $k"
set v ""
set s ""
switch -exact -- [lindex $prototype [expr {$i + 1}]] {
=> {
incr i 2
if {$i >= $n} {
proj-error "Missing argument for $k => flag"
}
set consuming($k) 1
set v [lindex $prototype $i]
}
default {
set v [lindex $prototype [incr i]]
set s [lindex $prototype [incr i]]
set scripts($k) $s
# Check for :PRAGMA...
switch -exact -- $k {
:all-flags {
set incrSkip 0
continue
}
}
#puts "**** #$i of $n k=$k v=$v s=$s"
set dflt($k) $v
proj-assert {[string match -* $k]} \
"Invalid argument: $k"
if {[string match {*\*} $k]} {
# Re-map -foo* to -foo and flag -foo as a repeatable flag
set k [string map {* ""} $k]
incr blob(${k}.multi)
}
if {[info exists flags($k)]} {
proj-error -up "[proj-scope]: Duplicated prototype for flag $k"
}
switch -exact -- [lindex $prototype [expr {$i + 1}]] {
=> {
# -flag => DFLT ?-subflag arg?
incr i 2
if {$i >= $n} {
proj-error -up "[proj-scope]: Missing argument for $k => flag"
}
incr blob(${k}.consumes)
set vi [lindex $prototype $i]
if {$vi in {-apply -call}} {
proj-error -up "[proj-scope]: Missing default value for $k flag"
} else {
set fv [lindex $prototype [expr {$i + 1}]]
if {$fv in {-apply -call}} {
incr i
eval $checkProtoFlag
}
}
}
default {
# -flag VALUE ?flag? SCRIPT
set vi [lindex $prototype [incr i]]
set fv [lindex $prototype [incr i]]
eval $checkProtoFlag
}
}
#puts "**** #$i of $n k=$k vi=$vi"
set flags($k) $vi
}
# Now look for those flags in the source list
array set tgt [array get dflt]
unset dflt
#puts "-- flags"; parray flags
#puts "-- blob"; parray blob
set rc 0
set rv {}
set rv {}; # staging area for the target argv value
set skipMode 0
set n [llength $argv]
# Now look for those flags in $argv...
for {set i 0} {$i < $n} {incr i} {
set arg [lindex $argv $i]
#puts "-- [proj-scope] arg=$arg"
if {$skipMode} {
lappend rv $arg
} elseif {"--" eq $arg} {
incr skipMode
} elseif {[info exists tgt($arg)]} {
if {[info exists consuming($arg)]} {
if {$i + 1 >= $n} {
proj-assert 0 {Cannot happen - bounds already checked}
# "--" is the conventional way to end processing of args
if {[incr blob(--)] > 1} {
# Elide only the first one
lappend rv $arg
}
incr skipMode $incrSkip
} elseif {[info exists flags($arg)]} {
# A known flag...
set isMulti [info exists blob(${arg}.multi)]
incr blob(${arg}.seen)
if {1 < $blob(${arg}.seen) && !$isMulti} {
proj-error -up [proj-scope] "$arg flag was used multiple times"
}
set vMode 0; # 0=as-is, 1=eval, 2=call
set isConsuming [info exists blob(${arg}.consumes)]
if {$isConsuming} {
incr i
if {$i >= $n} {
proj-error -up [proj-scope] "is missing argument for $arg flag"
}
set tgt($arg) [lindex $argv [incr i]]
} elseif {"" eq $scripts($arg)} {
set tgt($arg) ""
set vv [lindex $argv $i]
} elseif {[info exists blob(${arg}.script)]} {
set vMode 1
set vv $blob(${arg}.script)
} else {
#puts "**** running scripts($arg) $scripts($arg)"
set code [catch {uplevel 1 $scripts($arg)} xrc xopt]
#puts "**** tgt($arg)=$scripts($arg) code=$code rc=$rc"
if {$code in {0 2}} {
set tgt($arg) $xrc
} else {
return {*}$xopt $xrc
set vv $flags($arg)
}
if {[info exists blob(${arg}.call)]} {
set vMode 2
set vv [concat {*}$blob(${arg}.call) $arg $vv]
} elseif {$isConsuming} {
proj-assert {!$vMode}
# fall through
} elseif {"" eq $vv || [string is double -strict $vv]} {
set vMode 0
} elseif {$vv in {incr}} {
set vMode 0
switch -exact $vv {
incr {
set xx $flags($k); incr xx; set vv $xx; unset xx
}
default {
proj-error "Unhandled \$vv value $vv"
}
}
} else {
set vv [list eval $vv]
set vMode 1
}
if {$vMode} {
set code [catch [list uplevel 1 $vv] vv xopt]
if {$code ni {0 2}} {
return {*}$xopt $vv
}
}
if {$isConsuming && $isMulti} {
if {1 == $blob(${arg}.seen)} {
# On the first hit, overwrite the default with a new list.
set flags($arg) [list $vv]
} else {
# On subsequent hits, append to the list.
lappend flags($arg) $vv
}
} else {
set flags($arg) $vv
}
incr rc
} else {
incr skipMode
# Non-flag
incr skipMode $incrSkip
lappend rv $arg
}
}
set argv $rv
array set outFlags [array get flags]
#puts "-- rv=$rv argv=$argv flags="; parray flags
return $rc
}; # proj-parse-flags
#
# Older (deprecated) name of proj-parse-flags.
#
proc proj-parse-simple-flags {args} {
tailcall proj-parse-flags {*}$args
}
if {$::proj__Config(self-tests)} {
set __ova $::proj__Config(verbose-assert);
set ::proj__Config(verbose-assert) 1
puts "Running [info script] self-tests..."
# proj-cache...
apply {{} {
#proj-warn "Test code for proj-cache"
proj-assert {![proj-cache-check -key here check]}
@@ -2233,4 +2401,100 @@ if {$::proj__Config(self-tests)} {
proj-assert {"" eq [proj-cache-remove]}
proj-assert {"" eq $check}
}}
}
# proj-parse-flags ...
apply {{} {
set foo 3
set argv {-a "hi - world" -b -b -b -- -a {bye bye} -- -d -D c -a "" --}
proj-parse-flags argv flags {
:all-flags
-a* => "gets overwritten"
-b* 7 {incr foo}
-d 1 0
-D 0 1
}
#puts "-- argv = $argv"; parray flags;
proj-assert {"-- c --" eq $argv}
proj-assert {$flags(-a) eq "{hi - world} {bye bye} {}"}
proj-assert {$foo == 6}
proj-assert {$flags(-b) eq $foo}
proj-assert {$flags(-d) == 0}
proj-assert {$flags(-D) == 1}
set foo 0
foreach x $flags(-a) {
proj-assert {$x in {{hi - world} {bye bye} {}}}
incr foo
}
proj-assert {3 == $foo}
set argv {-a {hi world} -b -maybe -- -a {bye bye} -- -b c --}
set foo 0
proj-parse-flags argv flags {
-a => "aaa"
-b 0 {incr foo}
-maybe no -literal yes
}
#parray flags; puts "--- argv = $argv"
proj-assert {"-a {bye bye} -- -b c --" eq $argv}
proj-assert {$flags(-a) eq "hi world"}
proj-assert {1 == $flags(-b)}
proj-assert {"yes" eq $flags(-maybe)}
set argv {-f -g -a aaa -M -M -M -L -H -A AAA a b c}
set foo 0
set myLambda {{flag val} {
proj-assert {$flag in {-f -g -M}}
#puts "myLambda flag=$flag val=$val"
incr val
}}
proc myNonLambda {flag val} {
proj-assert {$flag in {-A -a}}
#puts "myNonLambda flag=$flag val=$val"
concat $val $val
}
proj-parse-flags argv flags {
-f 0 -call {apply $myLambda}
-g 2 -apply $myLambda
-h 3 -apply $myLambda
-H 30 33
-a => aAAAa -apply {{f v} {
set v
}}
-A => AaaaA -call myNonLambda
-B => 17 -call myNonLambda
-M* 0 -apply $myLambda
-L "" -literal $myLambda
}
rename myNonLambda ""
#puts "--- argv = $argv"; parray flags
proj-assert {$flags(-f) == 1}
proj-assert {$flags(-g) == 3}
proj-assert {$flags(-h) == 3}
proj-assert {$flags(-H) == 33}
proj-assert {$flags(-a) == {aaa}}
proj-assert {$flags(-A) eq "AAA AAA"}
proj-assert {$flags(-B) == 17}
proj-assert {$flags(-M) == 3}
proj-assert {$flags(-L) eq $myLambda}
set argv {-touch -validate}
proj-parse-flags argv flags {
-touch "" {return "-touch"}
-validate 0 1
}
#puts "----- argv = $argv"; parray flags
proj-assert {$flags(-touch) eq "-touch"}
proj-assert {$flags(-validate) == 1}
proj-assert {$argv eq {}}
set argv {-i -i -i}
proj-parse-flags argv flags {
-i* 0 incr
}
proj-assert {3 == $flags(-i)}
}}
set ::proj__Config(verbose-assert) $__ova
unset __ova
puts "Done running [info script] self-tests."
}; # proj- API self-tests
+1 -1
View File
@@ -616,7 +616,7 @@ proc sqlite-check-common-system-deps {} {
# Check for needed/wanted functions
cc-check-functions gmtime_r isnan localtime_r localtime_s \
malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64
strchrnul usleep utime pread pread64 pwrite pwrite64
apply {{} {
set ldrt ""
+79 -56
View File
@@ -92,6 +92,7 @@ array set teaish__Config [proj-strip-hash-comments {
-tm.tcl.in TEAISH_TM_TCL_IN
-options {}
-pragmas {}
-src {}
}
#
@@ -331,29 +332,33 @@ proc teaish-configure-core {} {
-url - -v ""
-tm.tcl - -v ""
-tm.tcl.in - -v ""
-src - -v ""
} {
#proj-assert 0 {Just testing}
set isPIFlag [expr {"-" ne $pflag}]
if {$isPIFlag} {
if {[info exists ::teaish__PkgInfo($pflag)]} {
# Was already set - skip it.
continue;
}
proj-assert {{-} eq $key}
proj-assert {{-} eq $key};# "Unexpected pflag=$pflag key=$key type=$type val=$val"
set key $f2d($pflag)
}
proj-assert {"" ne $key}
set got [get-define $key "<nope>"]
if {"<nope>" ne $got} {
# Was already set - skip it.
continue
if {"" ne $key} {
if {"<nope>" ne [get-define $key "<nope>"]} {
# Was already set - skip it.
continue
}
}
switch -exact -- $type {
-v {}
-e { set val [eval $val] }
default { proj-error "Invalid type flag: $type" }
}
#puts "***** defining default $pflag $key {$val} isPIFlag=$isPIFlag got=$got"
define $key $val
#puts "***** defining default $pflag $key {$val} isPIFlag=$isPIFlag"
if {$key ne ""} {
define $key $val
}
if {$isPIFlag} {
set ::teaish__PkgInfo($pflag) $val
}
@@ -522,7 +527,7 @@ proc teaish__configure_phase1 {} {
set vputs "puts \[ $vsat \]"
#puts "*** vputs = $vputs"
scan [exec echo $vputs | $tclsh] %d vvcheck
if {0 == $vvcheck} {
if {![info exists vvcheck] || 0 == $vvcheck} {
proj-fatal -up $tclsh "check failed:" $vsat
}
}
@@ -585,7 +590,8 @@ proc teaish__configure_phase1 {} {
#
if {0x0f & $::teaish__Config(pkginit-policy)} {
file delete -force -- [get-define TEAISH_PKGINIT_TCL]
proj-dot-ins-append [get-define TEAISH_PKGINIT_TCL_IN]
proj-dot-ins-append [get-define TEAISH_PKGINIT_TCL_IN] \
[get-define TEAISH_PKGINIT_TCL]
}
if {0x0f & $::teaish__Config(tm-policy)} {
file delete -force -- [get-define TEAISH_TM_TCL]
@@ -595,17 +601,20 @@ proc teaish__configure_phase1 {} {
apply {{} {
# Queue up any remaining dot-in files
set dotIns [list]
foreach d {
TEAISH_TESTER_TCL_IN
TEAISH_TEST_TCL_IN
TEAISH_MAKEFILE_IN
foreach {dIn => dOut} {
TEAISH_TESTER_TCL_IN => TEAISH_TESTER_TCL
TEAISH_TEST_TCL_IN => TEAISH_TEST_TCL
TEAISH_MAKEFILE_IN => TEAISH_MAKEFILE
} {
lappend dotIns [get-define $d ""]
lappend dotIns [get-define $dIn ""] [get-define $dOut ""]
}
lappend dotIns $::autosetup(srcdir)/Makefile.in; # must be after TEAISH_MAKEFILE_IN
foreach f $dotIns {
if {"" ne $f} {
proj-dot-ins-append $f
lappend dotIns $::autosetup(srcdir)/Makefile.in Makefile; # must be after TEAISH_MAKEFILE_IN.
# Much later: probably because of timestamps for deps purposes :-?
#puts "dotIns=$dotIns"
foreach {i o} $dotIns {
if {"" ne $i && "" ne $o} {
#puts " pre-dot-ins-append: \[$i\] -> \[$o\]"
proj-dot-ins-append $i $o
}
}
}}
@@ -640,10 +649,10 @@ proc teaish__configure_phase1 {} {
#
# NO [define]s after this point!
#
proj-dot-ins-process -validate
proj-if-opt-truthy teaish-dump-defines {
proj-file-write config.defines.txt $tdefs
}
proj-dot-ins-process -validate
}; # teaish__configure_phase1
@@ -817,7 +826,9 @@ proc teaish__check_tcl {} {
if {"" ne $withSh &&
[catch {exec echo "puts stdout \$auto_path" | "$withSh"} result] == 0} {
foreach i $result {
if {[file isdirectory $i]} {
if {![string match //zip* $i] && [file isdirectory $i]} {
# isdirectory actually passes on //zipfs:/..., but those are
# useless for our purposes
set tcllibdir $i/$extDirName
break
}
@@ -1066,7 +1077,7 @@ If you are attempting an out-of-tree build, use
]]} {
if {[string match *.in $extM]} {
define TEAISH_MAKEFILE_IN $extM
define TEAISH_MAKEFILE [file rootname [file tail $extM]]
define TEAISH_MAKEFILE _[file rootname [file tail $extM]]
} else {
define TEAISH_MAKEFILE_IN ""
define TEAISH_MAKEFILE $extM
@@ -1134,8 +1145,8 @@ If you are attempting an out-of-tree build, use
set flist [list $dirExt/teaish.test.tcl.in $dirExt/teaish.test.tcl]
if {[proj-first-file-found ttt $flist]} {
if {[string match *.in $ttt]} {
# Generate teaish.test.tcl from $ttt
set xt [file rootname [file tail $ttt]]
# Generate _teaish.test.tcl from $ttt
set xt _[file rootname [file tail $ttt]]
file delete -force -- $xt; # ensure no stale copy is used
define TEAISH_TEST_TCL $xt
define TEAISH_TEST_TCL_IN $ttt
@@ -1302,7 +1313,6 @@ proc teaish-ldflags-prepend {args} {
# object files (which are typically in the build tree)).
#
proc teaish-src-add {args} {
set i 0
proj-parse-simple-flags args flags {
-dist 0 {expr 1}
-dir 0 {expr 1}
@@ -1387,7 +1397,7 @@ proc teaish__cleanup_rule {{tgt clean}} {
return ${tgt}-_${x}_
}
# @teaish-make-obj objfile srcfile ?...args?
# @teaish-make-obj ?flags? ?...args?
#
# Uses teaish-make-add to inject makefile rules for $objfile from
# $srcfile, which is assumed to be C code which uses libtcl. Unless
@@ -1401,43 +1411,45 @@ proc teaish__cleanup_rule {{tgt clean}} {
# Any arguments after the 2nd may be flags described below or, if no
# -recipe is provided, flags for the compiler call.
#
# -obj obj-filename.o
#
# -src src-filename.c
#
# -recipe {...}
# Uses the trimmed value of {...} as the recipe, prefixing it with
# a single hard-tab character.
#
# -deps {...}
# List of extra files to list as dependencies of $o. Good luck
# escaping non-trivial cases properly.
# List of extra files to list as dependencies of $o.
#
# -clean
# Generate cleanup rules as well.
proc teaish-make-obj {o src args} {
set consume 0
set clean 0
set flag ""
array set flags {}
set xargs {}
foreach arg $args {
if {$consume} {
set consume 0
set flags($flag) $arg
continue
}
switch -exact -- $arg {
-clean {incr clean}
-recipe -
-deps {
set flag $arg
incr consume
}
default {
lappend xargs $arg
}
proc teaish-make-obj {args} {
proj-parse-simple-flags args flags {
-clean 0 {expr 1}
-recipe => {}
-deps => {}
-obj => {}
-src => {}
}
#parray flags
if {"" eq $flags(-obj)} {
set args [lassign $args flags(-obj)]
if {"" eq $flags(-obj)} {
proj-error "Missing -obj flag."
}
}
foreach f {-deps -src} {
set flags($f) [string trim [string map {\n " "} $flags($f)]]
}
foreach f {-deps -src} {
set flags($f) [string trim $flags($f)]
}
#parray flags
#puts "-- args=$args"
teaish-make-add \
"# [proj-scope 1] -> [proj-scope] $o $src" -nl \
"$o: $src $::teaish__Config(teaish.tcl)"
"# [proj-scope 1] -> [proj-scope] $flags(-obj) $flags(-src)" -nl \
"$flags(-obj): $flags(-src) $::teaish__Config(teaish.tcl)"
if {[info exists flags(-deps)]} {
teaish-make-add " " [join $flags(-deps)]
}
@@ -1445,12 +1457,12 @@ proc teaish-make-obj {o src args} {
if {[info exists flags(-recipe)]} {
teaish-make-add [string trim $flags(-recipe)] -nl
} else {
teaish-make-add [join [list \$(CC.tcl) -c $src {*}$xargs]] -nl
teaish-make-add [join [list \$(CC.tcl) -c $flags(-src) {*}$args]] -nl
}
if {$clean} {
if {$flags(-clean)} {
set rule [teaish__cleanup_rule]
teaish-make-add \
"clean: $rule\n$rule:\n\trm -f \"$o\"\n"
"clean: $rule\n$rule:\n\trm -f \"$flags(-obj)\"\n"
}
}
@@ -2078,6 +2090,17 @@ proc teaish-pkginfo-set {args} {
set v $x
}
-src {
set d $::teaish__Config(extension-dir)
foreach f $v {
lappend ::teaish__Config(dist-files) $f
lappend ::teaish__Config(extension-src) $d/$f
lappend ::teaish__PkgInfo(-src) $f
# ^^^ so that default-value initialization in
# teaish-configure-core recognizes that it's been set.
}
}
-tm.tcl -
-tm.tcl.in {
if {0x30 & $::teaish__Config(pkgindex-policy)} {
@@ -2515,7 +2538,7 @@ proc teaish__install {{dDest ""}} {
] {
teaish__verbose 1 msg-result "Copying files to $destDir..."
file mkdir $destDir
foreach f [glob -directory $srcDir *] {
foreach f [glob -nocomplain -directory $srcDir *] {
if {[string match {*~} $f] || [string match "#*#" [file tail $f]]} {
# Editor-generated backups and emacs lock files
continue
+68 -3
View File
@@ -99,7 +99,7 @@ proc test__affert {failMode args} {
lassign $args script msg
}
incr ::test__Counters($what)
if {![uplevel 1 [concat expr [list $script]]]} {
if {![uplevel 1 expr [list $script]]} {
if {"" eq $msg} {
set msg $script
}
@@ -136,6 +136,40 @@ proc assert {args} {
tailcall test__affert 1 {*}$args
}
#
# @assert-matches ?-e? pattern ?-e? rhs ?msg?
#
# Equivalent to assert {[string match $pattern $rhs]} except that
# if either of those are prefixed with an -e flag, they are eval'd
# and their results are used.
#
proc assert-matches {args} {
set evalLhs 0
set evalRhs 0
if {"-e" eq [lindex $args 0]} {
incr evalLhs
set args [lassign $args -]
}
set args [lassign $args pattern]
if {"-e" eq [lindex $args 0]} {
incr evalRhs
set args [lassign $args -]
}
set args [lassign $args rhs msg]
if {$evalLhs} {
set pattern [uplevel 1 $pattern]
}
if {$evalRhs} {
set rhs [uplevel 1 $rhs]
}
#puts "***pattern=$pattern\n***rhs=$rhs"
tailcall test__affert 1 \
[join [list \[ string match [list $pattern] [list $rhs] \]]] $msg
# why does this not work? [list \[ string match [list $pattern] [list $rhs] \]] $msg
# "\[string match [list $pattern] [list $rhs]\]"
}
#
# @test-assert testId script ?msg?
#
@@ -157,7 +191,7 @@ proc test-expect {testId script result} {
puts "test $testId"
set x [string trim [uplevel 1 $script]]
set result [string trim $result]
tailcall test__affert 0 [list $x eq $result] \
tailcall test__affert 0 [list "{$x}" eq "{$result}"] \
"\nEXPECTED: <<$result>>\nGOT: <<$x>>"
}
@@ -169,7 +203,7 @@ proc test-expect {testId script result} {
#
proc test-catch {cmd args} {
if {[catch {
$cmd {*}$args
uplevel 1 $cmd {*}$args
} rc xopts]} {
puts "[test-current-scope] ignoring failure of: $cmd [lindex $args 0]: $rc"
return 1
@@ -177,6 +211,37 @@ proc test-catch {cmd args} {
return 0
}
#
# @test-catch-matching pattern (script|cmd args...)
#
# Works like test-catch, but it expects its argument(s) to to throw an
# error matching the given string (checked with [string match]). If
# they do not throw, or the error does not match $pattern, this
# function throws, else it returns 1.
#
# If there is no second argument, the $cmd is assumed to be a script,
# and will be eval'd in the caller's scope.
#
# TODO: add -glob and -regex flags to control matching flavor.
#
proc test-catch-matching {pattern cmd args} {
if {[catch {
#puts "**** catch-matching cmd=$cmd args=$args"
if {0 == [llength $args]} {
uplevel 1 $cmd {*}$args
} else {
$cmd {*}$args
}
} rc xopts]} {
if {[string match $pattern $rc]} {
return 1
} else {
error "[test-current-scope] exception does not match {$pattern}: {$rc}"
}
}
error "[test-current-scope] expecting to see an error matching {$pattern}"
}
if {![array exists ::teaish__BuildFlags]} {
array set ::teaish__BuildFlags {}
}
+1 -1
View File
@@ -213,7 +213,7 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
** Macros needed to provide flexible arrays in a portable way
*/
#ifndef offsetof
# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define FLEXARRAY
+2 -1
View File
@@ -20,6 +20,7 @@ SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>
#include <stddef.h>
#ifndef SQLITE_AMALGAMATION
@@ -79,7 +80,7 @@ typedef sqlite3_uint64 u64;
** Macros needed to provide flexible arrays in a portable way
*/
#ifndef offsetof
# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define FLEXARRAY
+18 -5
View File
@@ -539,6 +539,7 @@ static int fts5StorageDeleteFromIndex(
for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
if( pConfig->abUnindexed[iCol-1]==0 ){
sqlite3_value *pVal = 0;
sqlite3_value *pFree = 0;
const char *pText = 0;
int nText = 0;
const char *pLoc = 0;
@@ -555,11 +556,22 @@ static int fts5StorageDeleteFromIndex(
if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
}else{
pText = (const char*)sqlite3_value_text(pVal);
nText = sqlite3_value_bytes(pVal);
if( pConfig->bLocale && pSeek ){
pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol);
nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
if( sqlite3_value_type(pVal)!=SQLITE_TEXT ){
/* Make a copy of the value to work with. This is because the call
** to sqlite3_value_text() below forces the type of the value to
** SQLITE_TEXT, and we may need to use it again later. */
pFree = pVal = sqlite3_value_dup(pVal);
if( pVal==0 ){
rc = SQLITE_NOMEM;
}
}
if( rc==SQLITE_OK ){
pText = (const char*)sqlite3_value_text(pVal);
nText = sqlite3_value_bytes(pVal);
if( pConfig->bLocale && pSeek ){
pLoc = (const char*)sqlite3_column_text(pSeek, iCol+pConfig->nCol);
nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
}
}
}
@@ -575,6 +587,7 @@ static int fts5StorageDeleteFromIndex(
}
sqlite3Fts5ClearLocale(pConfig);
}
sqlite3_value_free(pFree);
}
}
if( rc==SQLITE_OK && p->nTotalRow<1 ){
+20
View File
@@ -325,5 +325,25 @@ ifcapable foreignkey {
}
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 13.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b);
INSERT INTO t1 VALUES('abc def', X'123456');
}
faultsim_save_and_close
do_faultsim_test 13 -faults oom* -prep {
faultsim_restore_and_reopen
} -body {
execsql {
UPDATE t1 SET a='def abc'
}
} -test {
faultsim_test_result {0 {}}
}
finish_test
+30
View File
@@ -28,4 +28,34 @@ do_execsql_test 1.1 {
INSERT INTO sss VALUES('まりや');
}
foreach {tn enc tok} {
1 utf-8 ascii
2 utf-16 ascii
3 utf-8 unicode61
4 utf-16 unicode61
} {
reset_db
do_execsql_test 1.$tn.0 "
PRAGMA encoding = '$enc';
CREATE VIRTUAL TABLE vt2 USING fts5(c0, c1, tokenize=$tok);
"
do_execsql_test 1.$tn.1 {
INSERT INTO vt2(c0, c1) VALUES ('bhal', x'17db');
}
do_execsql_test 1.$tn.2 {
UPDATE vt2 SET c0='bhal';
}
do_execsql_test 1.$tn.3 {
INSERT INTO vt2(vt2) VALUES('integrity-check')
}
do_execsql_test 1.$tn.4 {
SELECT quote(c1) FROM vt2
} {X'17DB'}
}
finish_test
@@ -120,7 +120,7 @@ public abstract class AggregateFunction<T> implements SQLFunction {
argument, the context is set to the given initial value. On all other
calls, the 2nd argument is ignored.
@see SQLFunction.PerContextState#getAggregateState
@see AggregateFunction.PerContextState#getAggregateState
*/
protected final ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
return map.getAggregateState(cx, initialValue);
@@ -130,7 +130,7 @@ public abstract class AggregateFunction<T> implements SQLFunction {
To be called from the implementation's xFinal() method to fetch
the final state of the UDF and remove its mapping.
see SQLFunction.PerContextState#takeAggregateState
see AggregateFunction.PerContextState#takeAggregateState
*/
protected final T takeAggregateState(sqlite3_context cx){
return map.takeAggregateState(cx);
+100 -47
View File
@@ -67,6 +67,7 @@
** data: For a regular file, a blob containing the file data. For a
** symlink, a text value containing the text of the link. For a
** directory, NULL.
** level: Directory hierarchy level. Topmost is 1.
**
** If a non-NULL value is specified for the optional $dir parameter and
** $path is a relative path, then $path is interpreted relative to $dir.
@@ -92,13 +93,11 @@ SQLITE_EXTENSION_INIT1
# include <dirent.h>
# include <utime.h>
# include <sys/time.h>
# define STRUCT_STAT struct stat
#else
# include "windows.h"
# include <io.h>
# include "windirent.h"
# include <direct.h>
# include "test_windirent.h"
# define dirent DIRENT
# define stat _stat
# define STRUCT_STAT struct _stat
# define chmod(path,mode) fileio_chmod(path,mode)
# define mkdir(path,mode) fileio_mkdir(path)
#endif
@@ -116,14 +115,16 @@ SQLITE_EXTENSION_INIT1
/*
** Structure of the fsdir() table-valued function
*/
/* 0 1 2 3 4 5 */
#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
/* 0 1 2 3 4 5 6 */
#define FSDIR_SCHEMA "(name,mode,mtime,data,level,path HIDDEN,dir HIDDEN)"
#define FSDIR_COLUMN_NAME 0 /* Name of the file */
#define FSDIR_COLUMN_MODE 1 /* Access mode */
#define FSDIR_COLUMN_MTIME 2 /* Last modification time */
#define FSDIR_COLUMN_DATA 3 /* File content */
#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
#define FSDIR_COLUMN_LEVEL 4 /* Level. Topmost is 1 */
#define FSDIR_COLUMN_PATH 5 /* Path to top of search */
#define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
/*
** UTF8 chmod() function for Windows
@@ -289,7 +290,7 @@ LPWSTR utf8_to_utf16(const char *z){
*/
static void statTimesToUtc(
const char *zPath,
struct stat *pStatBuf
STRUCT_STAT *pStatBuf
){
HANDLE hFindFile;
WIN32_FIND_DATAW fd;
@@ -317,7 +318,7 @@ static void statTimesToUtc(
*/
static int fileStat(
const char *zPath,
struct stat *pStatBuf
STRUCT_STAT *pStatBuf
){
#if defined(_WIN32)
sqlite3_int64 sz = strlen(zPath);
@@ -341,7 +342,7 @@ static int fileStat(
*/
static int fileLinkStat(
const char *zPath,
struct stat *pStatBuf
STRUCT_STAT *pStatBuf
){
#if defined(_WIN32)
return fileStat(zPath, pStatBuf);
@@ -374,7 +375,7 @@ static int makeDirectory(
int i = 1;
while( rc==SQLITE_OK ){
struct stat sStat;
STRUCT_STAT sStat;
int rc2;
for(; zCopy[i]!='/' && i<nCopy; i++);
@@ -424,7 +425,7 @@ static int writeFile(
** be an error though - if there is already a directory at the same
** path and either the permissions already match or can be changed
** to do so using chmod(), it is not an error. */
struct stat sStat;
STRUCT_STAT sStat;
if( errno!=EEXIST
|| 0!=fileStat(zFile, &sStat)
|| !S_ISDIR(sStat.st_mode)
@@ -620,13 +621,14 @@ struct fsdir_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
int nLvl; /* Number of entries in aLvl[] array */
int mxLvl; /* Maximum level */
int iLvl; /* Index of current entry */
FsdirLevel *aLvl; /* Hierarchy of directories being traversed */
const char *zBase;
int nBase;
struct stat sStat; /* Current lstat() results */
STRUCT_STAT sStat; /* Current lstat() results */
char *zPath; /* Path to current entry */
sqlite3_int64 iRowid; /* Current rowid */
};
@@ -738,7 +740,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
mode_t m = pCur->sStat.st_mode;
pCur->iRowid++;
if( S_ISDIR(m) ){
if( S_ISDIR(m) && pCur->iLvl+3<pCur->mxLvl ){
/* Descend into this directory */
int iNew = pCur->iLvl + 1;
FsdirLevel *pLvl;
@@ -846,7 +848,11 @@ static int fsdirColumn(
}else{
readFileContents(ctx, pCur->zPath);
}
break;
}
case FSDIR_COLUMN_LEVEL:
sqlite3_result_int(ctx, pCur->iLvl+2);
break;
case FSDIR_COLUMN_PATH:
default: {
/* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
@@ -880,8 +886,11 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){
/*
** xFilter callback.
**
** idxNum==1 PATH parameter only
** idxNum==2 Both PATH and DIR supplied
** idxNum bit Meaning
** 0x01 PATH=N
** 0x02 DIR=N
** 0x04 LEVEL<N
** 0x08 LEVEL<=N
*/
static int fsdirFilter(
sqlite3_vtab_cursor *cur,
@@ -892,20 +901,31 @@ static int fsdirFilter(
fsdir_cursor *pCur = (fsdir_cursor*)cur;
(void)idxStr;
fsdirResetCursor(pCur);
int i;
if( idxNum==0 ){
fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
return SQLITE_ERROR;
}
assert( argc==idxNum && (argc==1 || argc==2) );
assert( (idxNum & 0x01)!=0 && argc>0 );
zDir = (const char*)sqlite3_value_text(argv[0]);
if( zDir==0 ){
fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
return SQLITE_ERROR;
}
if( argc==2 ){
pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
i = 1;
if( (idxNum & 0x02)!=0 ){
assert( argc>i );
pCur->zBase = (const char*)sqlite3_value_text(argv[i++]);
}
if( (idxNum & 0x0c)!=0 ){
assert( argc>i );
pCur->mxLvl = sqlite3_value_int(argv[i++]);
if( idxNum & 0x08 ) pCur->mxLvl++;
if( pCur->mxLvl<=0 ) pCur->mxLvl = 1000000000;
}else{
pCur->mxLvl = 1000000000;
}
if( pCur->zBase ){
pCur->nBase = (int)strlen(pCur->zBase)+1;
@@ -934,10 +954,11 @@ static int fsdirFilter(
** In this implementation idxNum is used to represent the
** query plan. idxStr is unused.
**
** The query plan is represented by values of idxNum:
** The query plan is represented by bits in idxNum:
**
** (1) The path value is supplied by argv[0]
** (2) Path is in argv[0] and dir is in argv[1]
** 0x01 The path value is supplied by argv[0]
** 0x02 dir is in argv[1]
** 0x04 maxdepth is in argv[1] or [2]
*/
static int fsdirBestIndex(
sqlite3_vtab *tab,
@@ -946,6 +967,9 @@ static int fsdirBestIndex(
int i; /* Loop over constraints */
int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
int idxLevel = -1; /* Index in pIdxInfo->aConstraint of LEVEL< or <= */
int idxLevelEQ = 0; /* 0x08 for LEVEL<= or LEVEL=. 0x04 for LEVEL< */
int omitLevel = 0; /* omit the LEVEL constraint */
int seenPath = 0; /* True if an unusable PATH= constraint is seen */
int seenDir = 0; /* True if an unusable DIR= constraint is seen */
const struct sqlite3_index_constraint *pConstraint;
@@ -953,25 +977,48 @@ static int fsdirBestIndex(
(void)tab;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
switch( pConstraint->iColumn ){
case FSDIR_COLUMN_PATH: {
if( pConstraint->usable ){
idxPath = i;
seenPath = 0;
}else if( idxPath<0 ){
seenPath = 1;
if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
switch( pConstraint->iColumn ){
case FSDIR_COLUMN_PATH: {
if( pConstraint->usable ){
idxPath = i;
seenPath = 0;
}else if( idxPath<0 ){
seenPath = 1;
}
break;
}
case FSDIR_COLUMN_DIR: {
if( pConstraint->usable ){
idxDir = i;
seenDir = 0;
}else if( idxDir<0 ){
seenDir = 1;
}
break;
}
case FSDIR_COLUMN_LEVEL: {
if( pConstraint->usable && idxLevel<0 ){
idxLevel = i;
idxLevelEQ = 0x08;
omitLevel = 0;
}
break;
}
break;
}
case FSDIR_COLUMN_DIR: {
if( pConstraint->usable ){
idxDir = i;
seenDir = 0;
}else if( idxDir<0 ){
seenDir = 1;
}
break;
}else
if( pConstraint->iColumn==FSDIR_COLUMN_LEVEL
&& pConstraint->usable
&& idxLevel<0
){
if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){
idxLevel = i;
idxLevelEQ = 0x08;
omitLevel = 1;
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){
idxLevel = i;
idxLevelEQ = 0x04;
omitLevel = 1;
}
}
}
@@ -988,14 +1035,20 @@ static int fsdirBestIndex(
}else{
pIdxInfo->aConstraintUsage[idxPath].omit = 1;
pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
pIdxInfo->idxNum = 0x01;
pIdxInfo->estimatedCost = 1.0e9;
i = 2;
if( idxDir>=0 ){
pIdxInfo->aConstraintUsage[idxDir].omit = 1;
pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
pIdxInfo->idxNum = 2;
pIdxInfo->estimatedCost = 10.0;
}else{
pIdxInfo->idxNum = 1;
pIdxInfo->estimatedCost = 100.0;
pIdxInfo->aConstraintUsage[idxDir].argvIndex = i++;
pIdxInfo->idxNum |= 0x02;
pIdxInfo->estimatedCost /= 1.0e4;
}
if( idxLevel>=0 ){
pIdxInfo->aConstraintUsage[idxLevel].omit = omitLevel;
pIdxInfo->aConstraintUsage[idxLevel].argvIndex = i++;
pIdxInfo->idxNum |= idxLevelEQ;
pIdxInfo->estimatedCost /= 1.0e4;
}
}
+2 -2
View File
@@ -240,7 +240,7 @@ static int vtablogConnect(
/*
** This method is the destructor for vtablog_cursor objects.
** This method is the destructor for vtablog_vtab objects.
*/
static int vtablogDisconnect(sqlite3_vtab *pVtab){
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
@@ -252,7 +252,7 @@ static int vtablogDisconnect(sqlite3_vtab *pVtab){
}
/*
** This method is the destructor for vtablog_cursor objects.
** This method is (also) the destructor for vtablog_vtab objects.
*/
static int vtablogDestroy(sqlite3_vtab *pVtab){
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
+163
View File
@@ -0,0 +1,163 @@
/*
** 2025-06-05
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** An implementation of opendir(), readdir(), and closedir() for Windows,
** based on the FindFirstFile(), FindNextFile(), and FindClose() APIs
** of Win32.
**
** #include this file inside any C-code module that needs to use
** opendir()/readdir()/closedir(). This file is a no-op on non-Windows
** machines. On Windows, static functions are defined that implement
** those standard interfaces.
*/
#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
#define SQLITE_WINDIRENT_H
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#ifndef FILENAME_MAX
# define FILENAME_MAX (260)
#endif
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISLNK
#define S_ISLNK(m) (0)
#endif
typedef unsigned short mode_t;
/* The dirent object for Windows is abbreviated. The only field really
** usable by applications is d_name[].
*/
struct dirent {
int d_ino; /* Inode number (synthesized) */
unsigned d_attributes; /* File attributes */
char d_name[FILENAME_MAX]; /* Null-terminated filename */
};
/* The internals of DIR are opaque according to standards. So it
** does not matter what we put here. */
typedef struct DIR DIR;
struct DIR {
intptr_t d_handle; /* Handle for findfirst()/findnext() */
struct dirent cur; /* Current entry */
};
/* Ignore hidden and system files */
#define WindowsFileToIgnore(a) \
((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
/*
** Close a previously opened directory
*/
static int closedir(DIR *pDir){
int rc = 0;
if( pDir==0 ){
return EINVAL;
}
if( pDir->d_handle!=0 && pDir->d_handle!=(-1) ){
rc = _findclose(pDir->d_handle);
}
sqlite3_free(pDir);
return rc;
}
/*
** Open a new directory. The directory name should be UTF-8 encoded.
** appropriate translations happen automatically.
*/
static DIR *opendir(const char *zDirName){
DIR *pDir;
wchar_t *b1;
sqlite3_int64 sz;
struct _wfinddata_t data;
pDir = sqlite3_malloc64( sizeof(DIR) );
if( pDir==0 ) return 0;
memset(pDir, 0, sizeof(DIR));
memset(&data, 0, sizeof(data));
sz = strlen(zDirName);
b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
if( b1==0 ){
closedir(pDir);
return NULL;
}
sz = MultiByteToWideChar(CP_UTF8, 0, zDirName, sz, b1, sz);
b1[sz++] = '\\';
b1[sz++] = '*';
b1[sz] = 0;
if( sz+1>sizeof(data.name)/sizeof(data.name[0]) ){
closedir(pDir);
sqlite3_free(b1);
return NULL;
}
memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
sqlite3_free(b1);
pDir->d_handle = _wfindfirst(data.name, &data);
if( pDir->d_handle<0 ){
closedir(pDir);
return NULL;
}
while( WindowsFileToIgnore(data) ){
memset(&data, 0, sizeof(data));
if( _wfindnext(pDir->d_handle, &data)==-1 ){
closedir(pDir);
return NULL;
}
}
pDir->cur.d_ino = 0;
pDir->cur.d_attributes = data.attrib;
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
pDir->cur.d_name, FILENAME_MAX, 0, 0);
return pDir;
}
/*
** Read the next entry from a directory.
**
** The returned struct-dirent object is managed by DIR. It is only
** valid until the next readdir() or closedir() call. Only the
** d_name[] field is meaningful. The d_name[] value has been
** translated into UTF8.
*/
static struct dirent *readdir(DIR *pDir){
struct _wfinddata_t data;
if( pDir==0 ) return 0;
if( (pDir->cur.d_ino++)==0 ){
return &pDir->cur;
}
do{
memset(&data, 0, sizeof(data));
if( _wfindnext(pDir->d_handle, &data)==-1 ){
return NULL;
}
}while( WindowsFileToIgnore(data) );
pDir->cur.d_attributes = data.attrib;
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
pDir->cur.d_name, FILENAME_MAX, 0, 0);
return &pDir->cur;
}
#endif /* defined(_WIN32) && defined(_MSC_VER) */
+4 -2
View File
@@ -64,6 +64,8 @@
#endif
int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
#include <stddef.h>
/*
** If building separately, we will need some setup that is normally
** found in sqliteInt.h
@@ -95,7 +97,7 @@ typedef unsigned int u32;
# define NEVER(X) (X)
#endif
#ifndef offsetof
#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define FLEXARRAY
@@ -2848,7 +2850,7 @@ static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){
return rc;
}
/*
** Insert cell pCell into node pNode. Node pNode is the head of a
** subtree iHeight high (leaf nodes have iHeight==0).
+16
View File
@@ -96,6 +96,22 @@ do_test 1.5 {
$iter finalize
grp delete
do_test 1.6 {
set C [changeset_from_sql {
INSERT INTO t1 VALUES(1001, hex(randomblob(10000)), hex(randomblob(10000)));
INSERT INTO t1 VALUES(2001, hex(randomblob(10000)), hex(randomblob(10000)));
INSERT INTO t1 VALUES(3001, hex(randomblob(10000)), hex(randomblob(10000)));
}]
sqlite3changegroup grp
set iter [sqlite3changeset_start $C]
while {[$iter next]=="SQLITE_ROW"} {
grp add_change $iter
}
$iter finalize
} SQLITE_OK
grp delete
finish_test
+14 -8
View File
@@ -3396,14 +3396,15 @@ int sqlite3changeset_start_v2_strm(
** object and the buffer is full, discard some data to free up space.
*/
static void sessionDiscardData(SessionInput *pIn){
if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){
int nMove = pIn->buf.nBuf - pIn->iNext;
if( pIn->xInput && pIn->iCurrent>=sessions_strm_chunk_size ){
int nMove = pIn->buf.nBuf - pIn->iCurrent;
assert( nMove>=0 );
if( nMove>0 ){
memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove);
memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iCurrent], nMove);
}
pIn->buf.nBuf -= pIn->iNext;
pIn->iNext = 0;
pIn->buf.nBuf -= pIn->iCurrent;
pIn->iNext -= pIn->iCurrent;
pIn->iCurrent = 0;
pIn->nData = pIn->buf.nBuf;
}
}
@@ -3757,8 +3758,8 @@ static int sessionChangesetNextOne(
p->rc = sessionInputBuffer(&p->in, 2);
if( p->rc!=SQLITE_OK ) return p->rc;
sessionDiscardData(&p->in);
p->in.iCurrent = p->in.iNext;
sessionDiscardData(&p->in);
/* If the iterator is already at the end of the changeset, return DONE. */
if( p->in.iNext>=p->in.nData ){
@@ -6117,14 +6118,19 @@ int sqlite3changegroup_add_change(
sqlite3_changegroup *pGrp,
sqlite3_changeset_iter *pIter
){
int rc = SQLITE_OK;
if( pIter->in.iCurrent==pIter->in.iNext
|| pIter->rc!=SQLITE_OK
|| pIter->bInvert
){
/* Iterator does not point to any valid entry or is an INVERT iterator. */
return SQLITE_ERROR;
rc = SQLITE_ERROR;
}else{
pIter->in.bNoDiscard = 1;
rc = sessionOneChangeToHash(pGrp, pIter, 0);
}
return sessionOneChangeToHash(pGrp, pIter, 0);
return rc;
}
/*
+26 -4
View File
@@ -1459,6 +1459,9 @@ struct TestChangegroup {
typedef struct TestChangeIter TestChangeIter;
struct TestChangeIter {
sqlite3_changeset_iter *pIter;
/* If this iter uses streaming. */
TestStreamInput in;
};
@@ -1681,6 +1684,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_start(
sqlite3_changeset_iter *pIter = 0;
int flags = 0;
int rc = SQLITE_OK;
int nAlloc = 0; /* Bytes of space to allocate */
static int iCmd = 1;
char zCmd[64];
@@ -1696,18 +1700,36 @@ static int SQLITE_TCLAPI test_sqlite3changeset_start(
return TCL_ERROR;
}
flags = isInvert ? SQLITE_CHANGESETSTART_INVERT : 0;
pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[objc-1], &nChangeset);
rc = sqlite3changeset_start_v2(&pIter, (int)nChangeset, pChangeset, flags);
flags = isInvert ? SQLITE_CHANGESETSTART_INVERT : 0;
nAlloc = sizeof(TestChangeIter);
if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
nAlloc += nChangeset;
}
pNew = (TestChangeIter*)ckalloc(nAlloc);
memset(pNew, 0, nAlloc);
if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
pNew->in.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
pNew->in.nData = nChangeset;
pNew->in.aData = (unsigned char*)&pNew[1];
memcpy(pNew->in.aData, pChangeset, nChangeset);
}
if( pNew->in.nStream ){
void *pCtx = (void*)&pNew->in;
rc = sqlite3changeset_start_v2_strm(&pIter, testStreamInput, pCtx, flags);
}else{
rc = sqlite3changeset_start_v2(&pIter, (int)nChangeset, pChangeset, flags);
}
if( rc!=SQLITE_OK ){
char *zErr = sqlite3_mprintf(
"error in sqlite3changeset_start_v2() - %d", rc
);
Tcl_AppendResult(interp, zErr, (char*)0);
ckfree(pNew);
return TCL_ERROR;
}
pNew = (TestChangeIter*)ckalloc(sizeof(TestChangeIter));
pNew->pIter = pIter;
sprintf(zCmd, "csiter%d", iCmd++);
+5 -3
View File
@@ -410,7 +410,7 @@ DISTCLEAN_FILES += $(bin.stripccomments)
# -D... flags which should be included in all invocations should be
# appended to $(SQLITE.CALL.C-PP.FILTER.global).
bin.c-pp := ./c-pp
$(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
$(bin.c-pp): c-pp.c $(sqlite3.c) # $(MAKEFILE)
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \
-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
@@ -597,6 +597,7 @@ emcc.flags += -v
# -v is _very_ loud but also informative about what it's doing
endif
########################################################################
# emcc flags for .c/.o.
emcc.cflags :=
@@ -615,8 +616,9 @@ emcc.jsflags += -sDYNAMIC_EXECUTION=0
emcc.jsflags += -sNO_POLYFILL
emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api)
emcc.exportedRuntimeMethods := \
-sEXPORTED_RUNTIME_METHODS=wasmMemory
# wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY
-sEXPORTED_RUNTIME_METHODS=wasmMemory,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAP64,HEAPU64
# wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY
# Emscripten 4.0.7 (2025-04-15) stops exporting HEAP* by default
emcc.jsflags += $(emcc.exportedRuntimeMethods)
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
emcc.jsflags += -sIMPORTED_MEMORY
+1 -1
View File
@@ -1157,7 +1157,7 @@ const char * sqlite3__wasm_enum_json(void){
{ /* Validate that the above struct sizeof()s match
** expectations. We could improve upon this by
** checking the offsetof() for each member. */
const sqlite3_index_info siiCheck;
const sqlite3_index_info siiCheck = {0};
#define IndexSzCheck(T,M) \
(sizeof(T) == sizeof(*siiCheck.M))
if(!IndexSzCheck(sqlite3_index_constraint,aConstraint)
+1 -1
View File
@@ -328,7 +328,7 @@ static void mk_lib_mode(const char *zName /* build name */,
pf("\t\t$(cflags.common) $(SQLITE_OPT) \\\n"
"\t\t$(cflags.%s) $(cflags.%s.%s) \\\n"
"\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", zName, zNM);
if( LIBMODE_ESM & flags ){
if( (LIBMODE_ESM & flags) || (LIBMODE_NODEJS & flags) ){
/* TODO? Replace this $(call) with the corresponding makefile
** code. OTOH, we also use this $(call) in the speedtest1-wasmfs
** build, which is not part of the rules emitted by this
+10 -4
View File
@@ -772,7 +772,6 @@ TESTSRC = \
$(TOP)/src/test_thread.c \
$(TOP)/src/test_vdbecov.c \
$(TOP)/src/test_vfs.c \
$(TOP)/src/test_windirent.c \
$(TOP)/src/test_window.c \
$(TOP)/src/test_wsd.c \
$(TOP)/ext/fts3/fts3_term.c \
@@ -996,6 +995,7 @@ FUZZCHECK_OPT += \
-DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
-DSQLITE_ENABLE_STAT4 \
-DSQLITE_ENABLE_STMT_SCANSTATUS \
-DSQLITE_JSON_MAX_DEPTH=500 \
-DSQLITE_MAX_MEMORY=50000000 \
-DSQLITE_MAX_MMAP_SIZE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
@@ -1834,6 +1834,12 @@ mdevtest: srctree-check has_tclsh85
sdevtest: has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest $(TSTRNNR_OPTS)
# Like releasetest, except it omits srctree-check and verify-source so
# that it can be used on a modified source tree.
#
xdevtest: has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
#
# Validate that various generated files in the source tree
# are up-to-date.
@@ -2323,12 +2329,12 @@ SHELL_DEP = \
$(TOP)/ext/misc/sqlar.c \
$(TOP)/ext/misc/uint.c \
$(TOP)/ext/misc/vfstrace.c \
$(TOP)/ext/misc/windirent.h \
$(TOP)/ext/misc/zipfile.c \
$(TOP)/ext/recover/dbdata.c \
$(TOP)/ext/recover/sqlite3recover.c \
$(TOP)/ext/recover/sqlite3recover.h \
$(TOP)/src/test_windirent.c \
$(TOP)/src/test_windirent.h
$(TOP)/ext/recover/sqlite3recover.h
shell.c: $(SHELL_DEP) $(TOP)/tool/mkshellc.tcl $(B.tclsh)
$(B.tclsh) $(TOP)/tool/mkshellc.tcl shell.c
+89 -85
View File
@@ -1,14 +1,14 @@
C Minor\stcl\sdoc\supdate.
D 2025-05-17T10:35:11.233
C proj.tcl\sportability\sfixes\sand\scleanups\ssuggested\sin\s[forum:7b218c3c9f|forum\spost\s7b218c3c9f].\sBranching\sso\sthat\sit\scan\sbe\stested\son\smsys/cygwin/haiku\sbefore\scommitting\sto\sit.
D 2025-06-17T14:37:31.325
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
F Makefile.in c3e414df4dc8dfb12f1f6baf129fcb6d18cd0ebd3c9109370fb3fceeeef9a37a
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 0206f28988bb6634c7e8aff05bf6cfa65d6dfe1d2b6bd95160dd99290a83dfc7
F Makefile.msc ec2011bbdfc917d6a1c7c173dabb29c14ead0dd8e2e0b67278a00ae4ba576a77
F README.md e28077cfbef795e99c9c75ed95aa7257a1166709b562076441a8506ac421b7c1
F VERSION 001dea55eb8304ec9130b6b44a32d3fc349f279d45a7e224fc0730c3cb8e2372
F VERSION 16eddb43056a79c1977427ab7a05f3457c373fa159dcdced8754eb89ce7e06b8
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
@@ -17,20 +17,19 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F art/sqlite370.svg 40b7e2fe8aac3add5d56dd86ab8d427a4eca5bcb3fe4f8946cb3794e1821d531
F auto.def 82c32443a91c1062f7a48beec37dbb2d8d03447b1286bce8df5ebb6d8d353f8a
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.in 36516827bb5d2309422bbcbf53e873fa22ef179f5c25b1d3dc6a7255e63270b7
F autoconf/Makefile.in d0926d2309e563b5ebdfd711e5c218533acab79829a05eef4e97c3a92e17bf42
F autoconf/Makefile.msc f15ad424ca2820df8e39d9157965710af0a64d87773706706a12ea4f96e3a0d8
F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
F autoconf/README.txt b749816b8452b3af994dc6d607394bef3df1736d7e09359f1087de8439a52807
F autoconf/auto.def 3d994f3a9cc9b712dbce92a5708570ddcf3b988141b6eb738f2ed16127a9f0ac
F autoconf/tea/Makefile.in 14c6a79ce87e10d8a35398f2d0e04e1d83a88eb52ee16ebf0eeaccf005ff84b3
F autoconf/tea/README.txt 656d4686c509d375f5988ff3deda94f65fe6cd8358cd55d1f1dcc7b6e2ff73aa
F autoconf/tea/_teaish.tester.tcl.in ed5445512e91c12afbbb99771efb68a23be4a046d52d61213fb5b6f010118129
F autoconf/tea/Makefile.in bf6b43eafcd18766d81a8f0085cfc9cb051d8abae9031a8e7c3f5f1246e8f166
F autoconf/tea/README.txt 23475876343498ef2b514cc7510e8f1559a17e8e03fbc7a41c1c8a3b89e7b7e3
F autoconf/tea/_teaish.tester.tcl.in 8253b44be88e2e3f21de95a65d3a90c2be8e70b7bdd08a5b80e337ba7402f8f1
F autoconf/tea/auto.def ce95b9450e2fa4ba5dc857e208fe10f4e6f2d737796ac3278aee6079db417529
F autoconf/tea/configure d0b12b984edca6030d1976375b80157ac78b5b90a5b4f0dcee39357f63f4a80b x
F autoconf/tea/doc/sqlite3.n 9a97f4f717ceab73004ea412af7960625c1cb24b5c25e4ae4c8b5d8fa4300f4e
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in e07da6b94561f4aa382bab65b1ccceb04701b97bf59d007c1d1f20a222b22d07
F autoconf/tea/teaish.tcl 81571a9f9ae5c70735595b05586cb2de9d2aea7e32aad10417c4982f2e2f01c8
F autoconf/tea/teaish.tcl a2224762a039ed30c45cc1ce4b2fde5667fb0aa2569bb56590f5cb5d45d7410b
F autoconf/tea/teaish.test.tcl cfe94e1fb79dd078f650295be59843d470125e0cc3a17a1414c1fb8d77f4aea6
F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4
F autosetup/README.autosetup a78ff8c4a3d2636a4268736672a74bf14a82f42687fcf0631a70c516075c031e
@@ -47,13 +46,13 @@ F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e
F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1821baf61bc86a7e
F autosetup/jimsh0.c 563b966c137a4ce3c9333e5196723b7ac0919140a9d7989eb440463cd855c367
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
F autosetup/proj.tcl c4a77735b57f3c016a185bff048212a197b77723f9bea6cfafe396e4b542c666
F autosetup/sqlite-config.tcl 7ff986f6c3951f3aec5608522cbf772d8d04a0d26cc894289e2ca4836e018719
F autosetup/proj.tcl d2428ea25745d25a090b938647737818accd5b802511776a186c9f1bcce53420
F autosetup/sqlite-config.tcl ccda82e43e377b832aae72a1678b1dc17dcaff36ed0ebbd8f0cfc88612ae8de3
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
F autosetup/teaish/core.tcl 1ebbe849d8e716424a3ffe9384c7e8b352b3e1194d3d4a153b125cc5176b3715
F autosetup/teaish/core.tcl aee092fc71986d1272b835ea7492bb55ffc213a289502e4f14da80cf67b7e3c3
F autosetup/teaish/feature.tcl 18194fb79a24d30e5bbdeab40999616f39278b53a27525349ded033af2fd73be
F autosetup/teaish/tester.tcl 091745984473faea6985254b9986c6dfd0cce06f68bc515ba4afc1e6b3742fa8
F autosetup/teaish/tester.tcl 1799514c2652db49561b3386c5242b94534d1663f2cfac861a955e071895fdd0
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
F contrib/sqlitecon.tcl eb4c6578e08dd353263958da0dc620f8400b869a50d06e271ab0be85a51a08d3
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
@@ -82,7 +81,7 @@ F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 4f02858ab845a97bedf06e6cc1fba49a81fe5e00a26df68d0ad0f00a5814fa70
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 53f00a0d037c81174af1089ad7776563dcbccb5ed4697405256d3d4260d9fccc
F ext/fts3/fts3Int.h d0f70d602be987501cf6eff86a06a0b5d0389929c6abe24972d59594e6f4cb03
F ext/fts3/fts3_aux.c 7eab82a9cf0830f6551ba3abfdbe73ed39e322a4d3940ee82fbf723674ecd9f3
F ext/fts3/fts3_expr.c 5c13796638d8192c388777166075cdc8bc4b6712024cd5b72c31acdbefce5984
F ext/fts3/fts3_hash.c d9dba473741445789330c7513d4f65737c92df23c3212784312931641814672a
@@ -108,7 +107,7 @@ F ext/fts3/unicode/mkunicode.tcl cbf5f7b5c8ce8014bad731f246f2e520eece908465de477
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
F ext/fts5/fts5.h ff5d3cc88b29e41612bfb29eb723e29e38973de62ca75ba3e8f94ccb67f5b5f2
F ext/fts5/fts5Int.h bffbd0acdcdf509899681f4e1cfeef1c955030acd9fe15ff9082410f80c3bead
F ext/fts5/fts5Int.h cc1e6ed28e1fbde71e4427ba6d15b0c73a4f8f119adeb4f7bcc97e3336fbbeac
F ext/fts5/fts5_aux.c da4a7a9a11ec15c6df0699d908915a209bcde48f0b04101461316b59f71abffb
F ext/fts5/fts5_buffer.c f1e6d0324d7c55329d340673befc26681a372a4d36086caa8d1ec7d7c53066c7
F ext/fts5/fts5_config.c e7d8dd062b44a66cd77e5a0f74f23a2354cd1f3f8575afb967b2773c3384f7f8
@@ -116,7 +115,7 @@ F ext/fts5/fts5_expr.c be9e5f7f11d87e7bd3680832c93c13050fe351994b5052b0215c2ef40
F ext/fts5/fts5_hash.c a6266cedd801ab7964fa9e74ebcdda6d30ec6a96107fa24148ec6b7b5b80f6e0
F ext/fts5/fts5_index.c d171f2a507abccb3d524bf461b01f0d3971a9bf221be622ac7c671a991cb62ee
F ext/fts5/fts5_main.c 57933c18efe1058d8871199875c7a59744dabc3904f3aefbf9ff4a4e11fc79e2
F ext/fts5/fts5_storage.c 1ad05dab4830a4e2eaf2900bb143477f93bc17437093582f36f4b818809e88d8
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
@@ -193,7 +192,7 @@ F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e
F ext/fts5/test/fts5faultF.test 4abef99f86e99d9f0c6460dd68c586a766b6b9f1f660ada55bf2e8266bd1bbc1
F ext/fts5/test/fts5faultG.test 0544411ffcb3e19b42866f757a8a5e0fb8fef3a62c06f61d14deebc571bb7ea9
F ext/fts5/test/fts5faultH.test 2b2b5b8cb1b3fd7679f488c06e22af44107fbc6137eaf45b3e771dc7b149312d
F ext/fts5/test/fts5faultI.test 9b33d664bccee4bbde0f275a48b2df3ea2f05d41f6d1d171aa2e844382cba621
F ext/fts5/test/fts5faultI.test 4e3d5a9d3e3b3f17d5e5087ee069414632667719dcfccafd715bc87c72838c72
F ext/fts5/test/fts5first.test bfd685b96905bf541d99d8644e0a7219d1d833455a08ab64e344071a613b6ba9
F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affcf7e979df59547b
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
@@ -261,7 +260,7 @@ F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d059264
F ext/fts5/test/fts5unicode.test 41898f7e476e6515cd4b737c02a442cda5a580a74509788aa9072a2074948e0e
F ext/fts5/test/fts5unicode2.test 3bbd30152f9f760bf13886e5b1e5ec23ff62f56758ddda5d9c775a6082fb4c7c
F ext/fts5/test/fts5unicode3.test f4891a3dac3b49c3d7c0fdb29566e9eb0ecff35263370c89f9661b1952b20818
F ext/fts5/test/fts5unicode4.test 728c8f0caafb05567f524ad313d9f8b780fa45987b8a8df04eff87923c74b4d0
F ext/fts5/test/fts5unicode4.test 6d70dbe56e5179bb1990cfb22e62fdf2aae9458e443ade856e598ce95832fe9b
F ext/fts5/test/fts5unindexed.test 168838d2c385e131120bbf5b516d2432a5fabc4caa2259c932e1d49ae209a4ae
F ext/fts5/test/fts5unindexed2.test 516236eceaac05ace322290a0d3705b4c4ffe4760d8eb9d014d9d27d56dfcc02
F ext/fts5/test/fts5update.test b8affd796e45c94a4d19ad5c26606ea06065a0f162a9562d9f005b5a80ccf0bc
@@ -296,7 +295,7 @@ F ext/jni/src/org/sqlite/jni/annotation/NotNull.java be6cc3e8e114485822331630097
F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 56e3dee1f3f703a545dfdeddc1c3d64d1581172b1ad01ffcae95c18547fafd90
F ext/jni/src/org/sqlite/jni/annotation/package-info.java 977b374aed9d5853cbf3438ba3b0940abfa2ea4574f702a2448ee143b98ac3ca
F ext/jni/src/org/sqlite/jni/capi/AbstractCollationCallback.java 1afa90d3f236f79cc7fcd2497e111992644f7596fbc8e8bcf7f1908ae00acd6c
F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0b72cdff61533b564d65b63418129656daa9a9f30e7e7be982bd5ab394b1dbd0
F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0e28a0df51368c7127e505f1e9acd92a7e66e035bcd6288463aa691cb300c9af
F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java c045a5b47e02bb5f1af91973814a905f12048c428a3504fbc5266d1c1be3de5a
F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759
F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca
@@ -418,7 +417,7 @@ F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f82
F ext/misc/decimal.c 228d47e9ef4de60daf5851da19e3ac9ac1eda9e94432816914469501db6a1129
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
F ext/misc/fileio.c 34993b810514c58ff99d7b4254d4a388d844a4774ea77bec68a1dafe8de5ce41
F ext/misc/fileio.c 5e1aff478ea12455a76be25dff321e1e9517b189fffb1d547a019625c49c1880
F ext/misc/fossildelta.c 0aeb099e9627eea693cf21ae47826ecd1e0319b93143bed23090838b2ef0c162
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
F ext/misc/ieee754.c c9dd9d77c8e8e18e0a5706f8ffcccf4ccb6562073709f7453d4d73f5122f4362
@@ -457,9 +456,10 @@ F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
F ext/misc/vfsstat.c 0b23c0a69a2b63dc0ef0af44f9c1fc977300c480a1f7a9814500369d8211f56e
F ext/misc/vfstrace.c 0e4b8b17ac0675ea90f6d168d8214687e06ca3efbc0060aad4814994d82b41fb
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
F ext/misc/vtablog.c a197addbbd1e267a5476274b74953e1b6f050e28516f0a5fe7d6382753165ee6
F ext/misc/vtshim.c e5bce24ab8c532f4fdc600148718fe1802cb6ed57417f1c1032d8961f72b0e8f
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
F ext/misc/zipfile.c b62147ac4985eaac4e368d529b1f4f43ad6bc9ac13d6805d907fff3afdac64d3
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
@@ -539,7 +539,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
F ext/rtree/geopoly.c f0573d5109fdc658a180db0db6eec86ab2a1cf5ce58ec66cbf3356167ea757eb
F ext/rtree/rtree.c 99dade93b5ca1c1fa4a5ba1381140d88b27a52573a92897827d9eb2a8059a460
F ext/rtree/rtree.c a1f04a2013bc8f982307760615d1cee591355ac4723c74c3761c128d5c6954ab
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -601,7 +601,7 @@ F ext/session/sessionalter.test e852acb3d2357aac7d0b920a2109da758c4331bfdf85b41d
F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
F ext/session/sessionblob.test 87faf667870b72f08e91969abd9f52a383ab7b514506ee194d64a39d8faff00a
F ext/session/sessionchange.test 77c4702050f24270b58070e2cf01c95c3d232a3ef164b70f31974b386ce69903
F ext/session/sessionchange.test 6618cb1c1338a4b6df173b6ac42d09623fb71269962abf23ebb7617fe9f45a50
F ext/session/sessionconflict.test 19e4a53795c4c930bfec49e809311e09b2a9e202d9446e56d7a8b139046a0c07 x
F ext/session/sessiondiff.test e89f7aedcdd89e5ebac3a455224eb553a171e9586fc3e1e6a7b3388d2648ba8d
F ext/session/sessionfault.test c2b43d01213b389a3f518e90775fca2120812ba51e50444c4066962263e45c11
@@ -617,11 +617,11 @@ 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 7a8816d56940c464c74706dfb02f18129b290655df1ccb8648228a7d436141f2
F ext/session/sqlite3session.c 6b0877fe1ab832aa4b85eaca72606dfd1630a1363a1be7af10ee1042a5ec719e
F ext/session/sqlite3session.h 9bb1a6687b467764b35178dc29bbd2c57ab8cd3acdc8a62f088c34ad17e4fe2b
F ext/session/test_session.c af162108e8dc40cb9fe0e876e0155cecabcb49e82e5939677d21451e36160283
F ext/session/test_session.c 2ddff73ea368d827028c32851b291416e1008845832feb27b751d15e57e13cc3
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile 24d7e6f446528fa67f5ade6c3c7d7e46e1ac52649d6264cbe24539c1dab608e1
F ext/wasm/GNUmakefile e315b903c33b28ca074367041849de9dd2681c96d1437c11a5e9596abc265012
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
F ext/wasm/README.md b89605f65661cf35bf034ff6d43e448cc169b8017fc105d498e33b81218b482c
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -650,7 +650,7 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 0f68a64e508598910e7c01214ae27d603dfc8baec6a184506fafac603a901931
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4ab0704ee198de7d1059eccedc7703c931510b588d10af0ee36ea5b3ebbac284
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
F ext/wasm/api/sqlite3-wasm.c 6a4cd40267eaf08400895c5b9de39c56976c3b97b3c1bbe53fc2e80fa074e9c7
F ext/wasm/api/sqlite3-wasm.c 7ea3d4a286a2241f6fcc65c9ff10fc04ee5590f80f40763a57001dd5e93aa4c4
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc65debfe43b81fc39fb25c40ad0cc1946bd82580fbf644351107b544d6177ee
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
@@ -682,7 +682,7 @@ F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf1
F ext/wasm/index.html bcaa00eca521b372a6a62c7e7b17a870b0fcdf3e418a5921df1fd61e5344080d
F ext/wasm/jaccwabyt/jaccwabyt.js 6e4f26d0edb5c2e7d381b7eff1924832a040a12274afab2d1e1789027e9f6c5c
F ext/wasm/jaccwabyt/jaccwabyt.md 1128e3563e7eff90b5a373395251fc76cb32386fad1fea6075b0f34a8f1b9bdf
F ext/wasm/mkwasmbuilds.c 6e0b22002bc520b7af053681571a96d30049a51f7f1389e81c524e8d420f5d40
F ext/wasm/mkwasmbuilds.c 5b096a3c9fdf6e67eb20329dc685f995e820248a67fa970633c2c8f49bf472ad
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
@@ -709,7 +709,7 @@ F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F ext/wasm/wasmfs.make 68999f5bd8c489239592d59a420f8c627c99169bbd6fa16a404751f757b9f702
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk a41fa9e96ef139452d21a9ca5db4561ce053363e04d07da803f5e1cefb44c65e
F main.mk 17744293e7af7c39936c3f220ebb8eaff4f0ad1be1e186efb584dbc34bbea2c1
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -719,37 +719,37 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
F sqlite3.pc.in 0977c03a4da7c4204bd60e784a0efb8d51a190448aba78a4e973fe7192bdaf03
F src/alter.c 6a21a487290ed0990a0fac9db6b0b09c63de4b1cdaa6ba3fa3872e6f26b87768
F src/alter.c fc7bbbeb9e89c7124bf5772ce474b333b7bdc18d6e080763211a40fde69fb1da
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
F src/attach.c 9af61b63b10ee702b1594ecd24fb8cea0839cfdb6addee52fba26fa879f5db9d
F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 782cc29b42b47e7ec6348eb0aaf9ffe60063f498387e7249f458d445af4b53e9
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c 00fcee37947641f48d4b529d96143e74d056b7afa8f26d61292c90ee59c056b2
F src/btree.c 53a9c7b243e94c992853d90f1dac0959028433b4b0d27e04409cee04e001b508
F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c 67c1db4c5e89a8519fe9b6dafc287f6bc3627696b5b8536dc5e06db570d8c05f
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
F src/dbpage.c fcb1aafe00872a8aff9a7aa0ef7ff1b01e5817ec7bbd521f8f3e1e674ac8d609
F src/dbpage.c b3e218f8ed74fcbb7fa805df8ca669a3718d397617b3d8a8aac3307dc315c4d6
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
F src/expr.c 6f184da1f36576ad1ecc48a03f14774235373c64f88d462c710834930ee6c145
F src/expr.c f16fa5cbd849991462edf1d31bb7def5b970bb9611afcb4ea21c77e88e52a220
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c 7686ea382b20e8bfe2ab9de76150c99ee7b6e83523561f3c7787e0f68cb435c2
F src/func.c de47a8295503aa130baae5e6d9868ecf4f7c4dbffa65d83ad1f70bdbac0ee2d6
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c d05934dfab2c5c0c480fc6fd2038f11215661de08ea6ff38d2563216bd555c1b
F src/json.c 2406a6b0dd849ee0fd107d5cfef9fec2cdc2fbe631ece3183c31d6f85e0ec988
F src/json.c cb87977b1ee25ee7d27505d65a9261b687395bf895342c8ba566b7c01aee2047
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
F src/main.c 07f78d917ffcdf327982840cfd8e855fd000527a2ea5ace372ce4febcbd0bf97
F src/loadext.c d7edd8e671237539d795d30daaf888908a2c82e99bade4c78f3be021e8b7d655
F src/main.c eb46066bf2f0bec2dd89229572de5a9c479c47da134e2422e7a0056e9510cbee
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -770,10 +770,10 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c 410185df4900817c218c0efdb8064b3481af88cb3f7cea7392f820b6eebc7889
F src/os_win.c caab8bc13f1d64a2ba6b8af35d660ffe25083df3493d9082d7a461a5e9950a50
F src/os_unix.c 04e054ab86d86a7be99ebe5265922687791a40df5afc781d059beb47f4a40acd
F src/os_win.c b8d3cfdf2f40e2f9715b7d8df64f3c0c7ee18743a2dd0c4fc70c1d57fa1aadc7
F src/os_win.h 4c247cdb6d407c75186c94a1e84d5a22cbae4adcec93fcae8d2bc1f956fd1f19
F src/pager.c 9fbb541b46125dfa8914827575e6bb4d15048caa008073b1709112d495d7983b
F src/pager.c 23c0f17deb892da6b32fef1f465507df7ab5cd01d774288cb43695658a649259
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y e426d7323311554c75b0aebc426d0fe3c88d9777ffefed236f343ad9e661dc4c
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
@@ -781,22 +781,22 @@ F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
F src/pragma.c 30b535d0a66348df844ee36f890617b4cf45e9a22dcbc47ec3ca92909c50aaf1
F src/prepare.c 1832be043fce7d489959aae6f994c452d023914714c4d5457beaed51c0f3d126
F src/printf.c 3b91c334f528359145f4dde0dedd945bbb21044d0825ea064934d7222d61662c
F src/printf.c 71b6d3a0093bf23f473e25480ca0024e8962681506c75f4ffd3d343a3f0ab113
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c d40fe18d7c2fd0339f5846ffcf7d6809866e380acdf14c76fb2af87e9fe13f64
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c ee072fe20566119a195a5a3df454479bb6e944de7aef7006ff0b4d4612f9cb86
F src/shell.c.in ba53a52dafb167ac6320703da741386c34fbcabe8c078a188bb9f89808e3ef8f
F src/select.c 882d739e0d5e6c7a8b46a3cca3ada37fe1a56301f1360d6b141312c666bbe482
F src/shell.c.in 4ae9ff8e8b23d9a309e50d5b5ef2768b9bb18f748ece2acc2641a3c23b71e2b9
F src/sqlite.h.in 22882ddd3a70751aa8864c81993ee4562ed54c2c508b6270f75e223ffee38e1b
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h ded2e1527c84603d9d91adccb63dda460d96a2e2f98111d0438a479aa0dbe4e3
F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e
F src/sqliteInt.h 493202a7dec31d58ac246252b7f03645160e3709102255a79136b4aa8f863e74
F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 767a11d470b031e85f51b8924a0e8929b2362ff1975aee3474a10eba3c2e0d36
F src/tclsqlite.c 3c604c49e6cf4211960a9ddb9505280fd22cde32175f40884c641c0f5a286036
F src/tclsqlite.h 65e2c761446e1c9fa0342b7d2612a703483643c8b6a316d12a65b745a4727395
F src/test1.c 9b54135e5f1352f06b1d23d7c183f124c1f33de6ea8997cd801f0f215c43591d
F src/test1.c 13cc07851f989141b29f7ca3c6c90f6d18f90081ab423c66716c8cb29d277d1f
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
@@ -813,7 +813,7 @@ F src/test_config.c 7f412406592794636d6226268e26d413850a9f799bc5f3c01afc2820b165
F src/test_delete.c d0e8f6dc55cfc98a7c27c057fb88d512260564bf0b611482656c68b8f7f401ed
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
F src/test_fs.c 6711fd4c6c05914b613cfc99918a24978452f999ce03fc8f89c9794c03b20a5b
F src/test_fs.c a946408c81231feff4b6a2c18068f20aefe254dc82288687128af8b7520d32cb
F src/test_func.c 858d4dddb7acf88222ebcba7cffb585f6dde83e4a15b838c0d05ccdf8d5219b9
F src/test_hexio.c a90baa0a8ab5e7cfe2216a61c9a31cfd1f8378353a3d23e25fa94c09aa755bb0
F src/test_init.c 1649e02448f536e53172f6b1ff873254fe9a0c6c8a4502a2d25c0cc7b11945ea
@@ -841,8 +841,6 @@ F src/test_tclvar.c ae873248a0188459b1c16ca7cc431265dacce524399e8b46725c2b3b7e04
F src/test_thread.c 3edb4a5b5aeb1a6e9a275dccc848ac95acab7f496b3e9230f6d2d04953a2b862
F src/test_vdbecov.c 5c426d9cd2b351f5f9ceb30cabf8c64a63bfcad644c507e0bd9ce2f6ae1a3bf3
F src/test_vfs.c b4135c1308516adf0dfd494e6d6c33114e03732be899eace0502919b674586b5
F src/test_windirent.c cbee2b9a118b56b5a26b99c895adcbc861587bc66d24b88d1ad6e4c1d09dad7b
F src/test_windirent.h f8245d8002aa0d4322192d35b0f8bbfc757479e90d60fd0beb386d3913f72cdd
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
@@ -851,28 +849,28 @@ F src/treeview.c d85ce76e6d1498d781957c07cb234da6d77ce0ed2d196480d516f54dabc6227
F src/trigger.c 3ffb8ed6b64dbcc0ccae6e82435d01be3bf547e13b814e2d46f7df9bef84748e
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 3a20cbae9688af4c1e3754cc2520189d00762e37f60c2deb0b303360d166bba6
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
F src/vacuum.c d580ceb395c1ae3d59da41cbfea60683ff7dd2b94ddf4d0f5657620159e2eeb7
F src/vdbe.c 0feab5781141acca67bd5de84172fff902304274ec5cfe58609f005b8d160050
F src/vdbe.h 31eddcffc1d14c76c2a20fe4e137e1ee43d44f370896fae14a067052801a3625
F src/vdbeInt.h 5446f60e89b2aa7cdf3ab0ec4e7b01b8732cd9d52d9092a0b8b1bf700768f784
F src/vdbeapi.c 28fab30ed0acc981aecfdcaab0a421503609078e29850eb28494816682baf0a7
F src/vdbeaux.c 948c379976885a073b54cc7d8ffda087dc1a1095d1f5bb8df218796f8c933ac3
F src/vacuum.c 1bacdd0a81d2b5dc1c508fbf0d938c89fa78dd8d5b46ec92686d44030d4f4789
F src/vdbe.c 714fab7aa7c516edbcf5e4f653ae8f548a3e24c0ed19086d7383bb5851983992
F src/vdbe.h 93761ed7c6b8bc19524912fd9b9b587d41bf4f1d0ade650a00dadc10518d8958
F src/vdbeInt.h 0bc581a9763be385e3af715e8c0a503ba8422c2b7074922faf4bb0d6ae31b15e
F src/vdbeapi.c 613a6f29efacd6ed83e886b6e52db0fe52ba80a596b0a137608db1948bad90a9
F src/vdbeaux.c fd2c6b19a8892c31a2adc719f156f313560f9cc490cdbd04ff08fdae5d7aedb7
F src/vdbeblob.c b1b4032cac46b41e44b957c4d00aee9851f862dfd85ecb68116ba49884b03dfd
F src/vdbemem.c e67d9c6484d868c879d20c70d00bf4a9058082f1d4058607ca15d50eb3aebc21
F src/vdbesort.c 49e366d0216c782eba287bf602384e4330d2526a22f1275492d2785ce103c79b
F src/vdbesort.c cb6f472e83ca12c46aa7de0ac0a9d11458b357986f2617a1c90dfb19a542ecbe
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c bcf40795a09b699ad7e42624dd6282b13335164fbabcd5a98a717758cebef451
F src/wal.c b0f848cfba8dd057f77073493cdd542f9125b4cf87941f53e9d0db21604155c8
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 1d06561f7310af61bef8a046fa95d463ad88f855be9036fec9091f984520afc5
F src/whereInt.h ecdbfb5551cf394f04ec7f0bc7ad963146d80eee3071405ac29aa84950128b8e
F src/wherecode.c d67fadf5430c2647773b5f702a47b82eb4af50a317f8978c0c82363cc1a5107f
F src/whereexpr.c 2415c8eee5ff89a8b709d7d83d71c1ff986cd720d0520057e1d8a5371339012a
F src/where.c a99fa3061a0155d2cb0e2c91df76dbf834750272a8d79ec5e2dce3ed4e6abad6
F src/whereInt.h 02b646ea41a8342815b3628f8064c32618ea2e0f20b83216ea08cad11f0ac5aa
F src/wherecode.c 9710e62379c000189476404f923d4d1b192d0def222fdd287b820cc085a0d555
F src/whereexpr.c cf86bb36c5c4560aa13f81853bc8a345da441a0cce5cccbb634a80ea517f6cc0
F src/window.c d01227141f622f24fbe36ca105fbe6ef023f9fd98f1ccd65da95f88886565db5
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
@@ -1084,6 +1082,7 @@ F test/dbfuzz.c fc566102f72c8af84ae8077b4faf7f056c571e6fa7a32e98b66e42b7505f47b6
F test/dbfuzz001.test 6c9a4622029d69dc38926f115864b055cb2f39badd25ec22cbfb130c8ba8e9c3
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
F test/dblwidth-a.sql eb4141518610e52f931a55a984310075e98dc31eee5a28ae806b1e35377be85a
F test/dbpage.test 63fab1eb026bada121107e53436fa749bbf83281dc9dea17af422f7a5c0f289f
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
@@ -1222,7 +1221,7 @@ F test/fts3fault3.test ccdd2292dd2d4e21e30fc5f4c8e064f79e516087eec5ff57ab6bc4f6a
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3fuzz001.test c78afcd8ad712ea0b8d2ed50851a8aab3bc9dc52c64a536291e07112f519357c
F test/fts3integrity.test 0c6fe7353d7b24d78862f4272ee9df4da2f32b3ff30fa3396945cda8119580a8
F test/fts3join.test 1a4d786539b2b79a41c28ef2ac22cacd92a8ee830249b68a7dee4a020848e3bb
F test/fts3join.test de31d304ba479043a7d33d2f201c514b3e1da809da6797d7a58704d00e8da2e6
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
F test/fts3matchinfo2.test 00144e841704b8debfcdf6097969cd9f2a1cf759e2203cda42583648f2e6bf58
@@ -1274,7 +1273,7 @@ F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d8
F test/func6.test 3bc89ec0f2605736d3a118f43d25ef58115a7db4dba8ae939a363917d815c0bb
F test/func7.test 7e009275f52c52954c8c028fdb62f8bc16cc47276fcc8753c1d2b22c6e074598
F test/func8.test c4e2ecacf9f16e47a245e7a25fbabcc7e78f9c7c41a80f158527cdfdc6dd299d
F test/func9.test 62750dbbbcc9a2d241918b5f999f59e2126084d5f81904f9e1d8ee466666a19d
F test/func9.test d56aa5b0f7d0e4fec01cb19b797671221dece2b00714bb71679588666be7530d
F test/fuzz-oss1.test 514dcabb24687818ea949fa6760229eaacad74ca70157743ef36d35bbe01ffb0
F test/fuzz.test 819ea7e483bcee91209aacbe6f9eaf3287baa1841479ee5f639f57c5e7c42b86
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
@@ -1361,7 +1360,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 5984da7bf74b6540aa356f2ab0c6ae68a6d12039a3d798a9ac6a100abc17d520
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
F test/join.test 0cc86e5fd579780b98cc01c9d6fc5b69f6ecc777f1c4daa501a14d1a74f56a6b
F test/join.test 2fcfd84640cfd9ff48f31b4b0d370c4d5498c355ae4384544668ca54d37ae186
F test/join2.test f59d63264fb24784ae9c3bc9d867eb569cd6d442da5660f8852effe5c1938c27
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -1376,7 +1375,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test 55f69e64da74d4eca2235237f3acb657aef181e22e45daa228e35bba865e0255
F test/joinH.test fd76024ff104baec16417db5cafc0894ad4e0863e70803e63c1bba0322706339
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
@@ -1388,7 +1387,7 @@ F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd286
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
F test/json/json-speed-check.sh 7d5898808ce7542762318306ae6075a30f5e7ee115c4a409f487e123afe91d88 x
F test/json/jsonb-q1.txt 1e180fe6491efab307e318b22879e3a736ac9a96539bbde7911a13ee5b33abc7
F test/json101.test 11024e20fe298f7214878947b8f85a2dbe593593e04b4173c14a5857afbb986c
F test/json101.test 8237a484c256965eab1678fd950a32ac56325bb7d0dadbd095a46b0ddd95d62b
F test/json102.test 9b2e5ada10845ff84853b3feaae2ce51ce7145ae458f74c6a6cecc6ef6ee3ae1
F test/json103.test 355746a6b66aa438f214b4fae454b13068fad2444b5f693e0d538ad1c059b264
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
@@ -1664,7 +1663,7 @@ F test/skipscan5.test 0672103fd2c8f96bd114133f356192b35ece45c794fe3677e1d9e5e310
F test/skipscan6.test e2b256cf5d538a605beb97dc97ca5e2836dfc24c5e1d9b7a09e13c069a3b8b49
F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
F test/snapshot3.test 41350216abc6c7da37113ad462259c070786e5ad70bdc8709daaed148b1b3a2c
F test/snapshot3.test 2e0328ba019aa981848e10aded4d7dcd6094ec1f9c6290a34ab18415be0c44eb
F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
F test/snapshot_fault.test 129234ceb9b26a0e1000e8563a16e790f5c1412354e70749cbd78c3d5d07d60a
F test/snapshot_up.test 77dc7853bfb2b4fa249f76e1714cfa1e596826165d9ef22c06ac3a0b7b778d9a
@@ -1686,7 +1685,7 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
F test/speedtest.md ee958457ae1b729d9715ae33c0320600000bf1d9ddea1a88dcf79f56729d6fad
F test/speedtest.tcl 926d1e168f4a14e6fb68c5dc174de743536b547f365264bd5bac533b3621a4a0 x
F test/speedtest.tcl 405411356fbc54af15987b7ffeec330a49138f71584220fb8fe1948b2f7ac907 x
F test/speedtest1.c 64b8804b053a796eab22f8b23fb181000f05d7b3e2aa44f022117ea543bc5a2a
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
@@ -1725,7 +1724,7 @@ F test/tabfunc01.test 8a484fe8b19fc24844f72ca1ceb7c9ae8c9a6bca000a5c6ccab5d89f5c
F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test ad0bbd92edabe64cc91d990a0748142fe5ab962d74ac71fa3bfa94d50d2f4c87
F test/tclsqlite.test 3f697424cfc1cdc9c076ec0cadb0e700f059400a3e3ce134b7d856fc9f880e1c
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
@@ -1735,7 +1734,7 @@ F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 463ae33b8bf75ac77451df19bd65e7c415c2e9891227c7c9e657d0a2d8e1074a
F test/testrunner.tcl 614c4a28f7f730acd7bec53e17d76602fb480e0d538b6ec548169e03a093f92d x
F test/testrunner_data.tcl 8d5fa3851c48bc94e26db0be325202e44f6ca4ed838272b8d5b10c23817621e6
F test/testrunner_data.tcl 02dd645b647d907c959fbf232b7ff7d869c2ae430d5117443fc1e16a0d32243a
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1959,7 +1958,7 @@ F test/uri.test 1250724af9beeed2d6c3716f5b990c483200c54f408d3c0ec9543a3c7961f8fc
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
F test/vacuum-into.test 5a489714feecfdabfc7b293be4111564a173dee92c0d6818dd0207f3ade65783
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum.test f3b2257a4fcd659513c866a5d9e5f70999cc58fd5d74e979290385fa350b79ee
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
F test/vacuum3.test d9d9a04ee58c485b94694fd4f68cffaba49c32234fdefe1ac1a622c5e17d4ce3
F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7c010
@@ -2034,8 +2033,10 @@ F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
F test/walseh1.test bae700eb99519b6d5cd3f893c04759accc5a59c391d4189fe4dd6995a533442b
F test/walsetlk.test 9079cd8ef82570b8cf0067f31e049a72bec353fb2d5f0cc88f1736dc42ba9704
F test/walsetlk2.test 9097083633cdf55bf1098b694fb8651d0356d38fef28b869481d18029d7ceaf4
F test/walsetlk2.test 4a67823b1e759ac5a4fe78a83c1f857c3c5761bf8d755421c8b55907957f23dd
F test/walsetlk3.test 1b82bd92dea7e58f498b4399b0b3d26773dd8ac5c74205ce4a23c207cb8e85fe
F test/walsetlk_recover.test adccbffc59e365063a4efd2da6b661ae2fcf15d775b6719fe46acd87face08ff
F test/walsetlk_snapshot.test 86d5588380f9927d8fcbbd75133b0a34fddf959378d6823c6f164a390123f70a
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9aa23
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
@@ -2143,7 +2144,7 @@ F tool/genfkey.README e550911fa984c8255ebed2ef97824125d83806eb5232582700de949edf
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
F tool/lemon.c f51a488369046cd4f4212d755a214a57673ded400cbeb01e298cbf63539e1d8c
F tool/lemon.c 8f6c122e5727cb0e5f302b8efc91489b1947a8d98206d7a1b1cfc0ed685b6e7c
F tool/lempar.c bdffd3b233a4e4e78056c9c01fadd2bb3fe902435abde3bce3d769fdf0d5cca2
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
@@ -2160,7 +2161,7 @@ F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl 3801ce32f8c55fe63a3b279f231fb26c2c1a2ea9a09d2dd599239d87a609acec
F tool/mkshellc.tcl 9ce74de0fa904a2c56a96f8d8b5261246bacb0eaa8d7e184f9e18ff94145ebbc
F tool/mkshellc.tcl bab0a72a68384181a5706712dfdf6815f6526446d4e8aacace2de5e80cda91b2
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mksqlite3c-noext.tcl 351c55256213154cabb051a3c870ef9f4487de905015141ae50dc7578a901b84
F tool/mksqlite3c.tcl f11b63445c4840509248bd4aa151a81aea25d5415fef71943c8d436eba4f3b3c
@@ -2186,13 +2187,13 @@ F tool/showwal.c 11eca547980a066b081f512636151233350ac679f29ecf4ebfce7f4530230b3
F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdaddf
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 07e18a1d8cc3f6b3a4a1f3528e63c9b29a5c8a7bca0b8d394b231da464ce1247
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
F tool/sqldiff.c 134be7866be19f8beb32043d5aea5657f01aaeae2df8d33d758ff722c78666b9
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
F tool/sqlite3_rsync.c e8659970e839d71d2ef04b96d48ad65f1d4298a41636affaf93c32ed71f3f879
F tool/sqlite3_rsync.c c1e1a737ebb458a4ccbbaa21e5eaa878448fef1aaa71b879b9a685785e28987f
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F tool/src-verify.c d00f93263aa2fa6ba0cba0106d95458e6effb94fdb5fc634f56834f90c05bbb4
F tool/src-verify.c 6c655d9a8d6b30f3648fc78a79bf3838ed68f8543869d380c43ea9f17b3b8501
F tool/srcck1.c 559e703c6cca1d70398bdba1d7f91036c1a71adf718a1aaa6401a562ccaed154
F tool/srctree-check.tcl fa4d82dd3e8a38d5cbce7d6ade8abef2f42b9eca0394484d521dc8d086739460
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
@@ -2205,10 +2206,13 @@ F tool/vdbe-compress.tcl fa2f37ab39b2a0087fafb6a7f3ce19503e25e624ffa8ed9951717ab
F tool/vdbe_profile.tcl 3ac5a4a9449f4baf77059358ea050db3e34395ccf59c5464d29b91746d5b961e
F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 15bd9e581a6d6ebe281b091adc04dca4d1c7fa9bbb582bcbab8c401b4f976753
R 39ca8780111060790d2845d7852fde6d
P 9441fff52cc4e19c44df1a77ffe474f409d519b270c7166ce17f99e6ea48fc1e
R 521cd36fd533b38f39517faf822f8bdc
T *branch * linux-named-apple
T *sym-linux-named-apple *
T -sym-trunk * Cancelled\sby\sbranch.
U stephan
Z f2bd0f683f4792863565410791d20518
Z 5f5e8471bf9be6c3059712dd72eeed12
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
43259e8c3fab13b4597cdd1c670df00ec756a6fefdeb7d4ba2e0644e4ad47113
89552e9137b7ebba9600443720e936e8dc4f7ab021d2ac3f0bb01b74071e130c
+2 -2
View File
@@ -1223,10 +1223,10 @@ static int renameEditSql(
}
assert( nQuot>=nNew && nSql>=0 && nNew>=0 );
zOut = sqlite3DbMallocZero(db, (u64)(nSql + pRename->nList*nQuot + 1));
zOut = sqlite3DbMallocZero(db, (u64)nSql + pRename->nList*(u64)nQuot + 1);
}else{
assert( nSql>0 );
zOut = (char*)sqlite3DbMallocZero(db, (u64)(nSql*2+1) * 3);
zOut = (char*)sqlite3DbMallocZero(db, (2*(u64)nSql + 1) * 3);
if( zOut ){
zBuf1 = &zOut[nSql*2+1];
zBuf2 = &zOut[nSql*4+2];
+99 -15
View File
@@ -107,6 +107,7 @@ struct Bitvec {
} u;
};
/*
** Create a new bitmap object able to handle bits between 0 and iSize,
** inclusive. Return a pointer to the new object. Return NULL if
@@ -216,7 +217,9 @@ bitvec_set_rehash:
}else{
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
memset(p->u.apSub, 0, sizeof(p->u.apSub));
p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
p->iDivisor = p->iSize/BITVEC_NPTR;
if( (p->iSize%BITVEC_NPTR)!=0 ) p->iDivisor++;
if( p->iDivisor<BITVEC_NBIT ) p->iDivisor = BITVEC_NBIT;
rc = sqlite3BitvecSet(p, i);
for(j=0; j<BITVEC_NINT; j++){
if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
@@ -293,6 +296,52 @@ u32 sqlite3BitvecSize(Bitvec *p){
return p->iSize;
}
#ifdef SQLITE_DEBUG
/*
** Show the content of a Bitvec option and its children. Indent
** everything by n spaces. Add x to each bitvec value.
**
** From a debugger such as gdb, one can type:
**
** call sqlite3ShowBitvec(p)
**
** For some Bitvec p and see a recursive view of the Bitvec's content.
*/
static void showBitvec(Bitvec *p, int n, unsigned x){
int i;
if( p==0 ){
printf("NULL\n");
return;
}
printf("Bitvec 0x%p iSize=%u", p, p->iSize);
if( p->iSize<=BITVEC_NBIT ){
printf(" bitmap\n");
printf("%*s bits:", n, "");
for(i=1; i<=BITVEC_NBIT; i++){
if( sqlite3BitvecTest(p,i) ) printf(" %u", x+(unsigned)i);
}
printf("\n");
}else if( p->iDivisor==0 ){
printf(" hash with %u entries\n", p->nSet);
printf("%*s bits:", n, "");
for(i=0; i<BITVEC_NINT; i++){
if( p->u.aHash[i] ) printf(" %u", x+(unsigned)p->u.aHash[i]);
}
printf("\n");
}else{
printf(" sub-bitvec with iDivisor=%u\n", p->iDivisor);
for(i=0; i<BITVEC_NPTR; i++){
if( p->u.apSub[i]==0 ) continue;
printf("%*s apSub[%d]=", n, "", i);
showBitvec(p->u.apSub[i], n+4, i*p->iDivisor);
}
}
}
void sqlite3ShowBitvec(Bitvec *p){
showBitvec(p, 0, 0);
}
#endif
#ifndef SQLITE_UNTESTABLE
/*
** Let V[] be an array of unsigned characters sufficient to hold
@@ -304,6 +353,7 @@ u32 sqlite3BitvecSize(Bitvec *p){
#define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7))
#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
/*
** This routine runs an extensive test of the Bitvec code.
**
@@ -312,7 +362,7 @@ u32 sqlite3BitvecSize(Bitvec *p){
** by 0, 1, or 3 operands, depending on the opcode. Another
** opcode follows immediately after the last operand.
**
** There are 6 opcodes numbered from 0 through 5. 0 is the
** There are opcodes numbered starting with 0. 0 is the
** "halt" opcode and causes the test to end.
**
** 0 Halt and return the number of errors
@@ -321,18 +371,25 @@ u32 sqlite3BitvecSize(Bitvec *p){
** 3 N Set N randomly chosen bits
** 4 N Clear N randomly chosen bits
** 5 N S X Set N bits from S increment X in array only, not in bitvec
** 6 Invoice sqlite3ShowBitvec() on the Bitvec object so far
** 7 X Show compile-time parameters and the hash of X
**
** The opcodes 1 through 4 perform set and clear operations are performed
** on both a Bitvec object and on a linear array of bits obtained from malloc.
** Opcode 5 works on the linear array only, not on the Bitvec.
** Opcode 5 is used to deliberately induce a fault in order to
** confirm that error detection works.
** confirm that error detection works. Opcodes 6 and greater are
** state output opcodes. Opcodes 6 and greater are no-ops unless
** SQLite has been compiled with SQLITE_DEBUG.
**
** At the conclusion of the test the linear array is compared
** against the Bitvec object. If there are any differences,
** an error is returned. If they are the same, zero is returned.
**
** If a memory allocation error occurs, return -1.
**
** sz is the size of the Bitvec. Or if sz is negative, make the size
** 2*(unsigned)(-sz) and disabled the linear vector check.
*/
int sqlite3BitvecBuiltinTest(int sz, int *aOp){
Bitvec *pBitvec = 0;
@@ -343,10 +400,15 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
/* Allocate the Bitvec to be tested and a linear array of
** bits to act as the reference */
pBitvec = sqlite3BitvecCreate( sz );
pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 );
if( sz<=0 ){
pBitvec = sqlite3BitvecCreate( 2*(unsigned)(-sz) );
pV = 0;
}else{
pBitvec = sqlite3BitvecCreate( sz );
pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 );
}
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
if( pBitvec==0 || pTmpSpace==0 || (pV==0 && sz>0) ) goto bitvec_end;
/* NULL pBitvec tests */
sqlite3BitvecSet(0, 1);
@@ -355,6 +417,24 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
/* Run the program */
pc = i = 0;
while( (op = aOp[pc])!=0 ){
if( op>=6 ){
#ifdef SQLITE_DEBUG
if( op==6 ){
sqlite3ShowBitvec(pBitvec);
}else if( op==7 ){
printf("BITVEC_SZ = %d (%d by sizeof)\n",
BITVEC_SZ, (int)sizeof(Bitvec));
printf("BITVEC_USIZE = %d\n", (int)BITVEC_USIZE);
printf("BITVEC_NELEM = %d\n", (int)BITVEC_NELEM);
printf("BITVEC_NBIT = %d\n", (int)BITVEC_NBIT);
printf("BITVEC_NINT = %d\n", (int)BITVEC_NINT);
printf("BITVEC_MXHASH = %d\n", (int)BITVEC_MXHASH);
printf("BITVEC_NPTR = %d\n", (int)BITVEC_NPTR);
}
#endif
pc++;
continue;
}
switch( op ){
case 1:
case 2:
@@ -376,12 +456,12 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
pc += nx;
i = (i & 0x7fffffff)%sz;
if( (op & 1)!=0 ){
SETBIT(pV, (i+1));
if( pV ) SETBIT(pV, (i+1));
if( op!=5 ){
if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
}
}else{
CLEARBIT(pV, (i+1));
if( pV ) CLEARBIT(pV, (i+1));
sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
}
}
@@ -391,14 +471,18 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
** match (rc==0). Change rc to non-zero if a discrepancy
** is found.
*/
rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+ sqlite3BitvecTest(pBitvec, 0)
+ (sqlite3BitvecSize(pBitvec) - sz);
for(i=1; i<=sz; i++){
if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
rc = i;
break;
if( pV ){
rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+ sqlite3BitvecTest(pBitvec, 0)
+ (sqlite3BitvecSize(pBitvec) - sz);
for(i=1; i<=sz; i++){
if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
rc = i;
break;
}
}
}else{
rc = 0;
}
/* Free allocated structure */
+10 -1
View File
@@ -872,7 +872,7 @@ static int btreeMoveto(
assert( nKey==(i64)(int)nKey );
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
sqlite3VdbeRecordUnpack((int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
}else{
@@ -2856,6 +2856,7 @@ static int removeFromSharingList(BtShared *pBt){
sqlite3_mutex_leave(pMainMtx);
return removed;
#else
UNUSED_PARAMETER( pBt );
return 1;
#endif
}
@@ -3697,6 +3698,13 @@ static SQLITE_NOINLINE int btreeBeginTrans(
(void)sqlite3PagerWalWriteLock(pPager, 0);
unlockBtreeIfUnused(pBt);
}
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT)
if( rc==SQLITE_BUSY_TIMEOUT ){
/* If a blocking lock timed out, break out of the loop here so that
** the busy-handler is not invoked. */
break;
}
#endif
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
btreeInvokeBusyHandler(pBt) );
sqlite3PagerWalDb(pPager, 0);
@@ -11317,6 +11325,7 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
*/
int sqlite3BtreeSchemaLocked(Btree *p){
int rc;
UNUSED_PARAMETER(p); /* only used in DEBUG builds */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
+7 -6
View File
@@ -227,7 +227,7 @@ static int dbpageEof(sqlite3_vtab_cursor *pCursor){
** idxStr is not used
*/
static int dbpageFilter(
sqlite3_vtab_cursor *pCursor,
sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
@@ -237,10 +237,11 @@ static int dbpageFilter(
sqlite3 *db = pTab->db;
Btree *pBt;
(void)idxStr;
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(argc);
/* Default setting is no rows of result */
pCsr->pgno = 1;
pCsr->pgno = 1;
pCsr->mxPgno = 0;
if( idxNum & 2 ){
@@ -275,8 +276,8 @@ static int dbpageFilter(
}
static int dbpageColumn(
sqlite3_vtab_cursor *pCursor,
sqlite3_context *ctx,
sqlite3_vtab_cursor *pCursor,
sqlite3_context *ctx,
int i
){
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
+6 -2
View File
@@ -73,7 +73,9 @@ char sqlite3ExprAffinity(const Expr *pExpr){
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
if( op==TK_VECTOR ){
if( op==TK_VECTOR
|| (op==TK_FUNCTION && pExpr->affExpr==SQLITE_AFF_DEFER)
){
assert( ExprUseXList(pExpr) );
return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
}
@@ -266,7 +268,9 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
p = p->pLeft;
continue;
}
if( op==TK_VECTOR ){
if( op==TK_VECTOR
|| (op==TK_FUNCTION && p->affExpr==SQLITE_AFF_DEFER)
){
assert( ExprUseXList(p) );
p = p->x.pList->a[0].pExpr;
continue;
+3 -3
View File
@@ -1667,7 +1667,7 @@ static void concatFuncCore(
int nSep,
const char *zSep
){
i64 j, k, n = 0;
i64 j, n = 0;
int i;
char *z;
for(i=0; i<argc; i++){
@@ -1681,8 +1681,8 @@ static void concatFuncCore(
}
j = 0;
for(i=0; i<argc; i++){
k = sqlite3_value_bytes(argv[i]);
if( k>0 ){
if( sqlite3_value_type(argv[i])!=SQLITE_NULL ){
int k = sqlite3_value_bytes(argv[i]);
const char *v = (const char*)sqlite3_value_text(argv[i]);
if( v!=0 ){
if( j>0 && nSep>0 ){
+11 -7
View File
@@ -1285,8 +1285,10 @@ static int jsonBlobChangePayloadSize(
nExtra = 1;
}else if( szType==13 ){
nExtra = 2;
}else{
}else if( szType==14 ){
nExtra = 4;
}else{
nExtra = 8;
}
if( szPayload<=11 ){
nNeeded = 0;
@@ -4850,18 +4852,20 @@ static void jsonObjectStep(
UNUSED_PARAMETER(argc);
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
z = (const char*)sqlite3_value_text(argv[0]);
n = sqlite3Strlen30(z);
if( pStr->zBuf==0 ){
jsonStringInit(pStr, ctx);
jsonAppendChar(pStr, '{');
}else if( pStr->nUsed>1 ){
}else if( pStr->nUsed>1 && z!=0 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
z = (const char*)sqlite3_value_text(argv[0]);
n = sqlite3Strlen30(z);
jsonAppendString(pStr, z, n);
jsonAppendChar(pStr, ':');
jsonAppendSqlValue(pStr, argv[1]);
if( z!=0 ){
jsonAppendString(pStr, z, n);
jsonAppendChar(pStr, ':');
jsonAppendSqlValue(pStr, argv[1]);
}
}
}
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
+3 -1
View File
@@ -517,7 +517,9 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_stmt_explain,
/* Version 3.44.0 and later */
sqlite3_get_clientdata,
sqlite3_set_clientdata
sqlite3_set_clientdata,
/* Version 3.50.0 and later */
sqlite3_setlk_timeout
};
/* True if x is the directory separator character
+2
View File
@@ -1861,6 +1861,7 @@ int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){
#endif
if( ms<-1 ) return SQLITE_RANGE;
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
sqlite3_mutex_enter(db->mutex);
db->setlkTimeout = ms;
db->setlkFlags = flags;
sqlite3BtreeEnterAll(db);
@@ -1872,6 +1873,7 @@ int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){
}
}
sqlite3BtreeLeaveAll(db);
sqlite3_mutex_leave(db->mutex);
#endif
#if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
UNUSED_PARAMETER(db);
+5 -6
View File
@@ -5035,21 +5035,20 @@ static int unixShmLock(
/* Check that, if this to be a blocking lock, no locks that occur later
** in the following list than the lock being obtained are already held:
**
** 1. Checkpointer lock (ofst==1).
** 2. Write lock (ofst==0).
** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
** 1. Recovery lock (ofst==2).
** 2. Checkpointer lock (ofst==1).
** 3. Write lock (ofst==0).
** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
**
** In other words, if this is a blocking lock, none of the locks that
** occur later in the above list than the lock being obtained may be
** held.
**
** It is not permitted to block on the RECOVER lock.
*/
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG)
{
u16 lockMask = (p->exclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
(ofst!=2) /* not RECOVER */
(ofst!=2 || lockMask==0)
&& (ofst!=1 || lockMask==0 || lockMask==2)
&& (ofst!=0 || lockMask<3)
&& (ofst<3 || lockMask<(1<<ofst))
+12 -113
View File
@@ -2722,7 +2722,11 @@ static int winHandleLockTimeout(
if( res==WAIT_OBJECT_0 ){
ret = TRUE;
}else if( res==WAIT_TIMEOUT ){
#if SQLITE_ENABLE_SETLK_TIMEOUT==1
rc = SQLITE_BUSY_TIMEOUT;
#else
rc = SQLITE_BUSY;
#endif
}else{
/* Some other error has occurred */
rc = SQLITE_IOERR_LOCK;
@@ -4208,13 +4212,13 @@ static void *winConvertFromUtf8Filename(const char *zFilename){
if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename)
&& winIsDirSep(zFilename[2])) ){
int nByte;
i64 nByte;
int convertflag = CCP_POSIX_TO_WIN_W;
if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE;
nByte = (int)osCygwin_conv_path(convertflag,
nByte = (i64)osCygwin_conv_path(convertflag,
zFilename, 0, 0);
if( nByte>0 ){
zConverted = sqlite3MallocZero(nByte+12);
zConverted = sqlite3MallocZero(12+(u64)nByte);
if ( zConverted==0 ){
return zConverted;
}
@@ -4533,21 +4537,20 @@ static int winShmLock(
/* Check that, if this to be a blocking lock, no locks that occur later
** in the following list than the lock being obtained are already held:
**
** 1. Checkpointer lock (ofst==1).
** 2. Write lock (ofst==0).
** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
** 1. Recovery lock (ofst==2).
** 2. Checkpointer lock (ofst==1).
** 3. Write lock (ofst==0).
** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
**
** In other words, if this is a blocking lock, none of the locks that
** occur later in the above list than the lock being obtained may be
** held.
**
** It is not permitted to block on the RECOVER lock.
*/
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG)
{
u16 lockMask = (p->exclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
(ofst!=2) /* not RECOVER */
(ofst!=2 || lockMask==0)
&& (ofst!=1 || lockMask==0 || lockMask==2)
&& (ofst!=0 || lockMask<3)
&& (ofst<3 || lockMask<(1<<ofst))
@@ -5097,27 +5100,6 @@ static winVfsAppData winNolockAppData = {
** sqlite3_vfs object.
*/
#if 0 /* No longer necessary */
/*
** Convert a filename from whatever the underlying operating system
** supports for filenames into UTF-8. Space to hold the result is
** obtained from malloc and must be freed by the calling function.
*/
static char *winConvertToUtf8Filename(const void *zFilename){
char *zConverted = 0;
if( osIsNT() ){
zConverted = winUnicodeToUtf8(zFilename);
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
}
#endif
/* caller will handle out of memory */
return zConverted;
}
#endif
/*
** This function returns non-zero if the specified UTF-8 string buffer
** ends with a directory separator character or one was successfully
@@ -5257,42 +5239,6 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
break;
}
sqlite3_free(zConverted);
#if 0 /* No longer necessary */
}else{
zConverted = sqlite3MallocZero( nMax+1 );
if( !zConverted ){
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM_BKPT;
}
if( osCygwin_conv_path(
CCP_POSIX_TO_WIN_W, zDir,
zConverted, nMax+1)<0 ){
sqlite3_free(zConverted);
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
"winGetTempname2", zDir);
}
if( winIsDir(zConverted) ){
/* At this point, we know the candidate directory exists and should
** be used. However, we may need to convert the string containing
** its name into UTF-8 (i.e. if it is UTF-16 right now).
*/
char *zUtf8 = winConvertToUtf8Filename(zConverted);
if( !zUtf8 ){
sqlite3_free(zConverted);
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM_BKPT;
}
sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
sqlite3_free(zUtf8);
sqlite3_free(zConverted);
break;
}
sqlite3_free(zConverted);
#endif /* No longer necessary */
}
}
}
@@ -6191,34 +6137,6 @@ static int winFullPathnameNoMutex(
}
}
#endif /* __CYGWIN__ */
#if 0 /* This doesn't work correctly at all! See:
<https://marc.info/?l=sqlite-users&m=139299149416314&w=2>
*/
SimulateIOError( return SQLITE_ERROR );
UNUSED_PARAMETER(nFull);
assert( nFull>=pVfs->mxPathname );
char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
if( !zOut ){
return SQLITE_IOERR_NOMEM_BKPT;
}
if( osCygwin_conv_path(
CCP_POSIX_TO_WIN_W,
zRelative, zOut, pVfs->mxPathname+1)<0 ){
sqlite3_free(zOut);
return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
"winFullPathname2", zRelative);
}else{
char *zUtf8 = winConvertToUtf8Filename(zOut);
if( !zUtf8 ){
sqlite3_free(zOut);
return SQLITE_IOERR_NOMEM_BKPT;
}
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
sqlite3_free(zUtf8);
sqlite3_free(zOut);
}
return SQLITE_OK;
#endif
#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32)
SimulateIOError( return SQLITE_ERROR );
@@ -6364,27 +6282,8 @@ static int winFullPathname(
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
#if 0 /* This doesn't work correctly at all! See:
<https://marc.info/?l=sqlite-users&m=139299149416314&w=2>
*/
int nFull = pVfs->mxPathname+1;
char *zFull = sqlite3MallocZero( nFull );
void *zConverted = 0;
if( zFull==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
}
if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
sqlite3_free(zFull);
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
}
zConverted = winConvertFromUtf8Filename(zFull);
sqlite3_free(zFull);
#else
void *zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
#endif
if( zConverted==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
+9
View File
@@ -700,6 +700,9 @@ struct Pager {
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
char *zWal; /* File name for write-ahead log */
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
sqlite3 *dbWal;
#endif
};
/*
@@ -7581,6 +7584,11 @@ static int pagerOpenWal(Pager *pPager){
pPager->fd, pPager->zWal, pPager->exclusiveMode,
pPager->journalSizeLimit, &pPager->pWal
);
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
if( rc==SQLITE_OK ){
sqlite3WalDb(pPager->pWal, pPager->dbWal);
}
#endif
}
pagerFixMaplimit(pPager);
@@ -7700,6 +7708,7 @@ int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
** blocking locks are required.
*/
void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
pPager->dbWal = db;
if( pagerUseWal(pPager) ){
sqlite3WalDb(pPager->pWal, db);
}
+8
View File
@@ -416,6 +416,14 @@ void sqlite3_str_vappendf(
}
prefix = 0;
}
#if WHERETRACE_ENABLED
if( xtype==etPOINTER && sqlite3WhereTrace & 0x100000 ) longvalue = 0;
#endif
#if TREETRACE_ENABLED
if( xtype==etPOINTER && sqlite3TreeTrace & 0x100000 ) longvalue = 0;
#endif
if( longvalue==0 ) flag_alternateform = 0;
if( flag_zeropad && precision<width-(prefix!=0) ){
precision = width-(prefix!=0);
+17 -5
View File
@@ -596,7 +596,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
}
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 && pParse->nErr==0 ){
/* This branch runs if the query contains one or more RIGHT or FULL
** JOINs. If only a single table on the left side of this join
** contains the zName column, then this branch is a no-op.
@@ -612,6 +612,8 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
*/
ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */
static const Token tkCoalesce = { "coalesce", 8 };
assert( pE1!=0 );
ExprSetProperty(pE1, EP_CanBeNull);
while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol,
pRight->fg.isSynthUsing)!=0 ){
if( pSrc->a[iLeft].fg.isUsing==0
@@ -628,7 +630,13 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
if( pFuncArgs ){
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0);
if( pE1 ){
pE1->affExpr = SQLITE_AFF_DEFER;
}
}
}else if( (pSrc->a[i+1].fg.jointype & JT_LEFT)!=0 && pParse->nErr==0 ){
assert( pE1!=0 );
ExprSetProperty(pE1, EP_CanBeNull);
}
pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
sqlite3SrcItemColumnUsed(pRight, iRightCol);
@@ -2105,6 +2113,10 @@ static void generateColumnTypes(
#endif
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
}
#else
UNUSED_PARAMETER(pParse);
UNUSED_PARAMETER(pTabList);
UNUSED_PARAMETER(pEList);
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
}
@@ -4236,9 +4248,9 @@ static int compoundHasDifferentAffinities(Select *p){
** from 2015-02-09.)
**
** (3) If the subquery is the right operand of a LEFT JOIN then
** (3a) the subquery may not be a join and
** (3b) the FROM clause of the subquery may not contain a virtual
** table and
** (3a) the subquery may not be a join
** (**) Was (3b): "the FROM clause of the subquery may not contain
** a virtual table"
** (**) Was: "The outer query may not have a GROUP BY." This case
** is now managed correctly
** (3d) the outer query may not be DISTINCT.
@@ -4454,7 +4466,7 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
if( pSubSrc->nSrc>1 /* (3a) */
|| IsVirtual(pSubSrc->a[0].pSTab) /* (3b) */
/**** || IsVirtual(pSubSrc->a[0].pSTab) (3b)-omitted */
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){
+56 -8
View File
@@ -887,12 +887,21 @@ static int strlen30(const char *z){
/*
** Return the length of a string in characters. Multibyte UTF8 characters
** count as a single character.
** count as a single character for single-width characters, or as two
** characters for double-width characters.
*/
static int strlenChar(const char *z){
int n = 0;
while( *z ){
if( (0xc0&*(z++))!=0x80 ) n++;
if( (0x80&z[0])==0 ){
n++;
z++;
}else{
int u = 0;
int len = decodeUtf8((const u8*)z, &u);
z += len;
n += cli_wcwidth(u);
}
}
return n;
}
@@ -1325,11 +1334,7 @@ static void shellAddSchemaName(
#define SQLITE_EXTENSION_INIT1
#define SQLITE_EXTENSION_INIT2(X) (void)(X)
#if defined(_WIN32) && defined(_MSC_VER)
INCLUDE test_windirent.h
INCLUDE test_windirent.c
#define dirent DIRENT
#endif
INCLUDE ../ext/misc/windirent.h
INCLUDE ../ext/misc/memtrace.c
INCLUDE ../ext/misc/pcachetrace.c
INCLUDE ../ext/misc/shathree.c
@@ -11585,7 +11590,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{"always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
{"assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
/*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
/*{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "SIZE INT-ARRAY"},
{"byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
{"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
{"fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"args..." },
@@ -11923,6 +11928,49 @@ static int do_meta_command(char *zLine, ShellState *p){
}
sqlite3_test_control(testctrl, &rc2);
break;
case SQLITE_TESTCTRL_BITVEC_TEST: {
/* Examples:
** .testctrl bitvec_test 100 6,1 -- Show BITVEC constants
** .testctrl bitvec_test 1000 1,12,7,3 -- Simple test
** ---- --------
** size of Bitvec -----^ ^--- aOp array. 0 added at end.
**
** See comments on sqlite3BitvecBuiltinTest() for more information
** about the aOp[] array.
*/
int iSize;
const char *zTestArg;
int nOp;
int ii, jj, x;
int *aOp;
if( nArg!=4 ){
sqlite3_fprintf(stderr,
"ERROR - should be: \".testctrl bitvec_test SIZE INT-ARRAY\"\n"
);
rc = 1;
goto meta_command_exit;
}
isOk = 3;
iSize = (int)integerValue(azArg[2]);
zTestArg = azArg[3];
nOp = (int)strlen(zTestArg)+1;
aOp = malloc( sizeof(int)*(nOp+1) );
shell_check_oom(aOp);
memset(aOp, 0, sizeof(int)*(nOp+1) );
for(ii = jj = x = 0; zTestArg[ii]!=0; ii++){
if( IsDigit(zTestArg[ii]) ){
x = x*10 + zTestArg[ii] - '0';
}else{
aOp[jj++] = x;
x = 0;
}
}
aOp[jj] = x;
x = sqlite3_test_control(testctrl, iSize, aOp);
sqlite3_fprintf(p->out, "result: %d\n", x);
free(aOp);
break;
}
case SQLITE_TESTCTRL_FAULT_INSTALL: {
int kk;
int bShowHelp = nArg<=2;
+4
View File
@@ -366,6 +366,8 @@ struct sqlite3_api_routines {
/* Version 3.44.0 and later */
void *(*get_clientdata)(sqlite3*,const char*);
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
/* Version 3.50.0 and later */
int (*setlk_timeout)(sqlite3*,int,int);
};
/*
@@ -699,6 +701,8 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
/* Version 3.50.0 and later */
#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+29 -11
View File
@@ -765,7 +765,7 @@
** ourselves.
*/
#ifndef offsetof
#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
/*
@@ -1153,6 +1153,7 @@ extern u32 sqlite3TreeTrace;
** 0x00020000 Transform DISTINCT into GROUP BY
** 0x00040000 SELECT tree dump after all code has been generated
** 0x00080000 NOT NULL strength reduction
** 0x00100000 Pointers are all shown as zero
*/
/*
@@ -1197,6 +1198,7 @@ extern u32 sqlite3WhereTrace;
** 0x00020000 Show WHERE terms returned from whereScanNext()
** 0x00040000 Solver overview messages
** 0x00080000 Star-query heuristic
** 0x00100000 Pointers are all shown as zero
*/
@@ -2329,6 +2331,7 @@ struct CollSeq {
#define SQLITE_AFF_INTEGER 0x44 /* 'D' */
#define SQLITE_AFF_REAL 0x45 /* 'E' */
#define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */
#define SQLITE_AFF_DEFER 0x58 /* 'X' - defer computation until later */
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
@@ -2644,9 +2647,15 @@ struct FKey {
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
**
** Note that aSortOrder[] and aColl[] have nField+1 slots. There
** are nField slots for the columns of an index then one extra slot
** for the rowid at the end.
** The aSortOrder[] and aColl[] arrays have nAllField slots each. There
** are nKeyField slots for the columns of an index then extra slots
** for the rowid or key at the end. The aSortOrder array is located after
** the aColl[] array.
**
** If SQLITE_ENABLE_PREUPDATE_HOOK is defined, then aSortFlags might be NULL
** to indicate that this object is for use by a preupdate hook. When aSortFlags
** is NULL, then nAllField is uninitialized and no space is allocated for
** aColl[], so those fields may not be used.
*/
struct KeyInfo {
u32 nRef; /* Number of references to this KeyInfo object */
@@ -2658,9 +2667,18 @@ struct KeyInfo {
CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
};
/* The size (in bytes) of a KeyInfo object with up to N fields */
/* The size (in bytes) of a KeyInfo object with up to N fields. This includes
** the main body of the KeyInfo object and the aColl[] array of N elements,
** but does not count the memory used to hold aSortFlags[]. */
#define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*))
/* The size of a bare KeyInfo with no aColl[] entries */
#if FLEXARRAY+1 > 1
# define SZ_KEYINFO_0 offsetof(KeyInfo,aColl)
#else
# define SZ_KEYINFO_0 sizeof(KeyInfo)
#endif
/*
** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
*/
@@ -2679,9 +2697,8 @@ struct KeyInfo {
**
** An instance of this object serves as a "key" for doing a search on
** an index b+tree. The goal of the search is to find the entry that
** is closed to the key described by this object. This object might hold
** just a prefix of the key. The number of fields is given by
** pKeyInfo->nField.
** is closest to the key described by this object. This object might hold
** just a prefix of the key. The number of fields is given by nField.
**
** The r1 and r2 fields are the values to return if this key is less than
** or greater than a key in the btree, respectively. These are normally
@@ -2691,7 +2708,7 @@ struct KeyInfo {
** The key comparison functions actually return default_rc when they find
** an equals comparison. default_rc can be -1, 0, or +1. If there are
** multiple entries in the b-tree with the same key (when only looking
** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to
** at the first nField elements) then default_rc can be set to -1 to
** cause the search to find the last match, or +1 to cause the search to
** find the first match.
**
@@ -2703,8 +2720,8 @@ struct KeyInfo {
** b-tree.
*/
struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
Mem *aMem; /* Values */
KeyInfo *pKeyInfo; /* Comparison info for the index that is unpacked */
Mem *aMem; /* Values for columns of the index */
union {
char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */
i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */
@@ -4879,6 +4896,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
void sqlite3ShowWindow(const Window*);
void sqlite3ShowWinFunc(const Window*);
#endif
void sqlite3ShowBitvec(Bitvec*);
#endif
void sqlite3SetString(char **, sqlite3*, const char*);
+99 -43
View File
@@ -49,6 +49,10 @@
# define CONST const
#elif !defined(Tcl_Size)
typedef int Tcl_Size;
# ifndef Tcl_BounceRefCount
# define Tcl_BounceRefCount(X) Tcl_IncrRefCount(X); Tcl_DecrRefCount(X)
/* https://www.tcl-lang.org/man/tcl9.0/TclLib/Object.html */
# endif
#endif
/**** End copy of tclsqlite.h ****/
@@ -1084,7 +1088,9 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
Tcl_DecrRefCount(pCmd);
}
if( rc && rc!=TCL_RETURN ){
if( TCL_BREAK==rc ){
sqlite3_result_null(context);
}else if( rc && rc!=TCL_RETURN ){
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
}else{
Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
@@ -1102,7 +1108,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
}else if( (c=='b' && pVar->bytes==0 && strcmp(zType,"boolean")==0 )
|| (c=='b' && pVar->bytes==0 && strcmp(zType,"booleanString")==0 )
|| (c=='w' && strcmp(zType,"wideInt")==0)
|| (c=='i' && strcmp(zType,"int")==0)
|| (c=='i' && strcmp(zType,"int")==0)
){
eType = SQLITE_INTEGER;
}else if( c=='d' && strcmp(zType,"double")==0 ){
@@ -1616,11 +1622,12 @@ struct DbEvalContext {
SqlPreparedStmt *pPreStmt; /* Current statement */
int nCol; /* Number of columns returned by pStmt */
int evalFlags; /* Flags used */
Tcl_Obj *pArray; /* Name of array variable */
Tcl_Obj *pVarName; /* Name of target array/dict variable */
Tcl_Obj **apColName; /* Array of column names */
};
#define SQLITE_EVAL_WITHOUTNULLS 0x00001 /* Unset array(*) for NULL */
#define SQLITE_EVAL_ASDICT 0x00002 /* Use dict instead of array */
/*
** Release any cache of column names currently held as part of
@@ -1641,20 +1648,20 @@ static void dbReleaseColumnNames(DbEvalContext *p){
/*
** Initialize a DbEvalContext structure.
**
** If pArray is not NULL, then it contains the name of a Tcl array
** If pVarName is not NULL, then it contains the name of a Tcl array
** variable. The "*" member of this array is set to a list containing
** the names of the columns returned by the statement as part of each
** call to dbEvalStep(), in order from left to right. e.g. if the names
** of the returned columns are a, b and c, it does the equivalent of the
** tcl command:
**
** set ${pArray}(*) {a b c}
** set ${pVarName}(*) {a b c}
*/
static void dbEvalInit(
DbEvalContext *p, /* Pointer to structure to initialize */
SqliteDb *pDb, /* Database handle */
Tcl_Obj *pSql, /* Object containing SQL script */
Tcl_Obj *pArray, /* Name of Tcl array to set (*) element of */
Tcl_Obj *pVarName, /* Name of Tcl array to set (*) element of */
int evalFlags /* Flags controlling evaluation */
){
memset(p, 0, sizeof(DbEvalContext));
@@ -1662,9 +1669,9 @@ static void dbEvalInit(
p->zSql = Tcl_GetString(pSql);
p->pSql = pSql;
Tcl_IncrRefCount(pSql);
if( pArray ){
p->pArray = pArray;
Tcl_IncrRefCount(pArray);
if( pVarName ){
p->pVarName = pVarName;
Tcl_IncrRefCount(pVarName);
}
p->evalFlags = evalFlags;
addDatabaseRef(p->pDb);
@@ -1687,7 +1694,7 @@ static void dbEvalRowInfo(
Tcl_Obj **apColName = 0; /* Array of column names */
p->nCol = nCol = sqlite3_column_count(pStmt);
if( nCol>0 && (papColName || p->pArray) ){
if( nCol>0 && (papColName || p->pVarName) ){
apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
for(i=0; i<nCol; i++){
apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
@@ -1696,20 +1703,35 @@ static void dbEvalRowInfo(
p->apColName = apColName;
}
/* If results are being stored in an array variable, then create
** the array(*) entry for that array
/* If results are being stored in a variable then create the
** array(*) or dict(*) entry for that variable.
*/
if( p->pArray ){
if( p->pVarName ){
Tcl_Interp *interp = p->pDb->interp;
Tcl_Obj *pColList = Tcl_NewObj();
Tcl_Obj *pStar = Tcl_NewStringObj("*", -1);
Tcl_IncrRefCount(pColList);
Tcl_IncrRefCount(pStar);
for(i=0; i<nCol; i++){
Tcl_ListObjAppendElement(interp, pColList, apColName[i]);
}
Tcl_IncrRefCount(pStar);
Tcl_ObjSetVar2(interp, p->pArray, pStar, pColList, 0);
if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
Tcl_ObjSetVar2(interp, p->pVarName, pStar, pColList, 0);
}else{
Tcl_Obj * pDict = Tcl_ObjGetVar2(interp, p->pVarName, NULL, 0);
if( !pDict ){
pDict = Tcl_NewDictObj();
}else if( Tcl_IsShared(pDict) ){
pDict = Tcl_DuplicateObj(pDict);
}
if( Tcl_DictObjPut(interp, pDict, pStar, pColList)==TCL_OK ){
Tcl_ObjSetVar2(interp, p->pVarName, NULL, pDict, 0);
}
Tcl_BounceRefCount(pDict);
}
Tcl_DecrRefCount(pStar);
Tcl_DecrRefCount(pColList);
}
}
@@ -1751,7 +1773,7 @@ static int dbEvalStep(DbEvalContext *p){
if( rcs==SQLITE_ROW ){
return TCL_OK;
}
if( p->pArray ){
if( p->pVarName ){
dbEvalRowInfo(p, 0, 0);
}
rcs = sqlite3_reset(pStmt);
@@ -1802,9 +1824,9 @@ static void dbEvalFinalize(DbEvalContext *p){
dbReleaseStmt(p->pDb, p->pPreStmt, 0);
p->pPreStmt = 0;
}
if( p->pArray ){
Tcl_DecrRefCount(p->pArray);
p->pArray = 0;
if( p->pVarName ){
Tcl_DecrRefCount(p->pVarName);
p->pVarName = 0;
}
Tcl_DecrRefCount(p->pSql);
dbReleaseColumnNames(p);
@@ -1879,7 +1901,7 @@ static int DbUseNre(void){
/*
** This function is part of the implementation of the command:
**
** $db eval SQL ?ARRAYNAME? SCRIPT
** $db eval SQL ?TGT-NAME? SCRIPT
*/
static int SQLITE_TCLAPI DbEvalNextCmd(
ClientData data[], /* data[0] is the (DbEvalContext*) */
@@ -1893,8 +1915,8 @@ static int SQLITE_TCLAPI DbEvalNextCmd(
** is a pointer to a Tcl_Obj containing the script to run for each row
** returned by the queries encapsulated in data[0]. */
DbEvalContext *p = (DbEvalContext *)data[0];
Tcl_Obj *pScript = (Tcl_Obj *)data[1];
Tcl_Obj *pArray = p->pArray;
Tcl_Obj * const pScript = (Tcl_Obj *)data[1];
Tcl_Obj * const pVarName = p->pVarName;
while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){
int i;
@@ -1902,15 +1924,46 @@ static int SQLITE_TCLAPI DbEvalNextCmd(
Tcl_Obj **apColName;
dbEvalRowInfo(p, &nCol, &apColName);
for(i=0; i<nCol; i++){
if( pArray==0 ){
if( pVarName==0 ){
Tcl_ObjSetVar2(interp, apColName[i], 0, dbEvalColumnValue(p,i), 0);
}else if( (p->evalFlags & SQLITE_EVAL_WITHOUTNULLS)!=0
&& sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL
&& sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL
){
Tcl_UnsetVar2(interp, Tcl_GetString(pArray),
Tcl_GetString(apColName[i]), 0);
/* Remove NULL-containing column from the target container... */
if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
/* Target is an array */
Tcl_UnsetVar2(interp, Tcl_GetString(pVarName),
Tcl_GetString(apColName[i]), 0);
}else{
/* Target is a dict */
Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0);
if( pDict ){
if( Tcl_IsShared(pDict) ){
pDict = Tcl_DuplicateObj(pDict);
}
if( Tcl_DictObjRemove(interp, pDict, apColName[i])==TCL_OK ){
Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0);
}
Tcl_BounceRefCount(pDict);
}
}
}else if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
/* Target is an array: set target(colName) = colValue */
Tcl_ObjSetVar2(interp, pVarName, apColName[i],
dbEvalColumnValue(p,i), 0);
}else{
Tcl_ObjSetVar2(interp, pArray, apColName[i], dbEvalColumnValue(p,i), 0);
/* Target is a dict: set target(colName) = colValue */
Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0);
if( !pDict ){
pDict = Tcl_NewDictObj();
}else if( Tcl_IsShared(pDict) ){
pDict = Tcl_DuplicateObj(pDict);
}
if( Tcl_DictObjPut(interp, pDict, apColName[i],
dbEvalColumnValue(p,i))==TCL_OK ){
Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0);
}
Tcl_BounceRefCount(pDict);
}
}
@@ -2019,7 +2072,7 @@ static int SQLITE_TCLAPI DbObjCmd(
"timeout", "total_changes", "trace",
"trace_v2", "transaction", "unlock_notify",
"update_hook", "version", "wal_hook",
0
0
};
enum DB_enum {
DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
@@ -2853,13 +2906,15 @@ deserialize_error:
}
/*
** $db eval ?options? $sql ?array? ?{ ...code... }?
** $db eval ?options? $sql ?varName? ?{ ...code... }?
**
** The SQL statement in $sql is evaluated. For each row, the values are
** placed in elements of the array named "array" and ...code... is executed.
** If "array" and "code" are omitted, then no callback is every invoked.
** If "array" is an empty string, then the values are placed in variables
** that have the same name as the fields extracted by the query.
** The SQL statement in $sql is evaluated. For each row, the values
** are placed in elements of the array or dict named $varName and
** ...code... is executed. If $varName and $code are omitted, then
** no callback is ever invoked. If $varName is an empty string,
** then the values are placed in variables that have the same name
** as the fields extracted by the query, and those variables are
** accessible during the eval of $code.
*/
case DB_EVAL: {
int evalFlags = 0;
@@ -2867,8 +2922,9 @@ deserialize_error:
while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){
if( strcmp(zOpt, "-withoutnulls")==0 ){
evalFlags |= SQLITE_EVAL_WITHOUTNULLS;
}
else{
}else if( strcmp(zOpt, "-asdict")==0 ){
evalFlags |= SQLITE_EVAL_ASDICT;
}else{
Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0);
return TCL_ERROR;
}
@@ -2876,8 +2932,8 @@ deserialize_error:
objv++;
}
if( objc<3 || objc>5 ){
Tcl_WrongNumArgs(interp, 2, objv,
"?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?");
Tcl_WrongNumArgs(interp, 2, objv,
"?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?");
return TCL_ERROR;
}
@@ -2903,17 +2959,17 @@ deserialize_error:
}else{
ClientData cd2[2];
DbEvalContext *p;
Tcl_Obj *pArray = 0;
Tcl_Obj *pVarName = 0;
Tcl_Obj *pScript;
if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){
pArray = objv[3];
pVarName = objv[3];
}
pScript = objv[objc-1];
Tcl_IncrRefCount(pScript);
p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
dbEvalInit(p, pDb, objv[2], pArray, evalFlags);
dbEvalInit(p, pDb, objv[2], pVarName, evalFlags);
cd2[0] = (void *)p;
cd2[1] = (void *)pScript;
@@ -4044,8 +4100,8 @@ EXTERN int sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
#if defined(TCLSH)
/* This is the main routine for an ordinary TCL shell. If there are
** are arguments, run the first argument as a script. Otherwise,
** read TCL commands from standard input
** arguments, run the first argument as a script. Otherwise, read TCL
** commands from standard input
*/
static const char *tclsh_main_loop(void){
static const char zMainloop[] =
+5
View File
@@ -8458,7 +8458,12 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
{ "DQS_DML", SQLITE_DBCONFIG_DQS_DML },
{ "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL },
{ "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
{ "TRUSTED_SCHEMA", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
{ "STMT_SCANSTATUS", SQLITE_DBCONFIG_STMT_SCANSTATUS },
{ "REVERSE_SCANORDER", SQLITE_DBCONFIG_REVERSE_SCANORDER },
{ "ATTACH_CREATE", SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE },
{ "ATTACH_WRITE", SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE },
{ "COMMENTS", SQLITE_DBCONFIG_ENABLE_COMMENTS },
};
int i;
int v = 0;
+4 -8
View File
@@ -72,12 +72,8 @@
#if !defined(_WIN32) || defined(__MSVCRT__)
# include <unistd.h>
# include <dirent.h>
# ifndef DIRENT
# define DIRENT dirent
# endif
#else
# include <io.h>
# include "test_windirent.h"
# include "windirent.h"
# ifndef S_ISREG
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
# endif
@@ -121,7 +117,7 @@ struct FsdirCsr {
char *zDir; /* Buffer containing directory scanned */
DIR *pDir; /* Open directory */
sqlite3_int64 iRowid;
struct DIRENT *pEntry;
struct dirent *pEntry;
};
/*
@@ -483,9 +479,9 @@ static int fstreeFilter(
char aWild[2] = { '\0', '\0' };
#ifdef _WIN32
const char *zDrive = windirent_getenv("fstreeDrive");
const char *zDrive = getenv("fstreeDrive");
if( zDrive==0 ){
zDrive = windirent_getenv("SystemDrive");
zDrive = getenv("SystemDrive");
}
zRoot = sqlite3_mprintf("%s%c", zDrive, '/');
nRoot = sqlite3Strlen30(zRoot);
-162
View File
@@ -1,162 +0,0 @@
/*
** 2015 November 30
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement most of the opendir() family of
** POSIX functions on Win32 using the MSVCRT.
*/
#if defined(_WIN32) && defined(_MSC_VER)
#include "test_windirent.h"
/*
** Implementation of the POSIX getenv() function using the Win32 API.
** This function is not thread-safe.
*/
const char *windirent_getenv(
const char *name
){
static char value[32768]; /* Maximum length, per MSDN */
DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
memset(value, 0, sizeof(value));
dwRet = GetEnvironmentVariableA(name, value, dwSize);
if( dwRet==0 || dwRet>dwSize ){
/*
** The function call to GetEnvironmentVariableA() failed -OR-
** the buffer is not large enough. Either way, return NULL.
*/
return 0;
}else{
/*
** The function call to GetEnvironmentVariableA() succeeded
** -AND- the buffer contains the entire value.
*/
return value;
}
}
/*
** Implementation of the POSIX opendir() function using the MSVCRT.
*/
LPDIR opendir(
const char *dirname /* Directory name, UTF8 encoding */
){
struct _wfinddata_t data;
LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
wchar_t *b1;
sqlite3_int64 sz;
if( dirp==NULL ) return NULL;
memset(dirp, 0, sizeof(DIR));
/* TODO: Remove this if Unix-style root paths are not used. */
if( sqlite3_stricmp(dirname, "/")==0 ){
dirname = windirent_getenv("SystemDrive");
}
memset(&data, 0, sizeof(data));
sz = strlen(dirname);
b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
if( b1==0 ){
closedir(dirp);
return NULL;
}
sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz);
b1[sz++] = '\\';
b1[sz++] = '*';
b1[sz] = 0;
if( sz+1>(sqlite3_int64)namesize ){
closedir(dirp);
sqlite3_free(b1);
return NULL;
}
memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
sqlite3_free(b1);
dirp->d_handle = _wfindfirst(data.name, &data);
if( dirp->d_handle==BAD_INTPTR_T ){
closedir(dirp);
return NULL;
}
/* TODO: Remove this block to allow hidden and/or system files. */
if( is_filtered(data) ){
next:
memset(&data, 0, sizeof(data));
if( _wfindnext(dirp->d_handle, &data)==-1 ){
closedir(dirp);
return NULL;
}
/* TODO: Remove this block to allow hidden and/or system files. */
if( is_filtered(data) ) goto next;
}
dirp->d_first.d_attributes = data.attrib;
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0);
return dirp;
}
/*
** Implementation of the POSIX readdir() function using the MSVCRT.
*/
LPDIRENT readdir(
LPDIR dirp
){
struct _wfinddata_t data;
if( dirp==NULL ) return NULL;
if( dirp->d_first.d_ino==0 ){
dirp->d_first.d_ino++;
dirp->d_next.d_ino++;
return &dirp->d_first;
}
next:
memset(&data, 0, sizeof(data));
if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL;
/* TODO: Remove this block to allow hidden and/or system files. */
if( is_filtered(data) ) goto next;
dirp->d_next.d_ino++;
dirp->d_next.d_attributes = data.attrib;
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0);
return &dirp->d_next;
}
/*
** Implementation of the POSIX closedir() function using the MSVCRT.
*/
INT closedir(
LPDIR dirp
){
INT result = 0;
if( dirp==NULL ) return EINVAL;
if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
result = _findclose(dirp->d_handle);
}
sqlite3_free(dirp);
return result;
}
#endif /* defined(WIN32) && defined(_MSC_VER) */
-158
View File
@@ -1,158 +0,0 @@
/*
** 2015 November 30
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains declarations for most of the opendir() family of
** POSIX functions on Win32 using the MSVCRT.
*/
#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
#define SQLITE_WINDIRENT_H
/*
** We need several data types from the Windows SDK header.
*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include "windows.h"
/*
** We need several support functions from the SQLite core.
*/
#include "sqlite3.h"
/*
** We need several things from the ANSI and MSVCRT headers.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <io.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
/*
** We may need several defines that should have been in "sys/stat.h".
*/
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (0)
#endif
/*
** We may need to provide the "mode_t" type.
*/
#ifndef MODE_T_DEFINED
#define MODE_T_DEFINED
typedef unsigned short mode_t;
#endif
/*
** We may need to provide the "ino_t" type.
*/
#ifndef INO_T_DEFINED
#define INO_T_DEFINED
typedef unsigned short ino_t;
#endif
/*
** We need to define "NAME_MAX" if it was not present in "limits.h".
*/
#ifndef NAME_MAX
# ifdef FILENAME_MAX
# define NAME_MAX (FILENAME_MAX)
# else
# define NAME_MAX (260)
# endif
# define DIRENT_NAME_MAX (NAME_MAX)
#endif
/*
** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
*/
#ifndef NULL_INTPTR_T
# define NULL_INTPTR_T ((intptr_t)(0))
#endif
#ifndef BAD_INTPTR_T
# define BAD_INTPTR_T ((intptr_t)(-1))
#endif
/*
** We need to provide the necessary structures and related types.
*/
#ifndef DIRENT_DEFINED
#define DIRENT_DEFINED
typedef struct DIRENT DIRENT;
typedef DIRENT *LPDIRENT;
struct DIRENT {
ino_t d_ino; /* Sequence number, do not use. */
unsigned d_attributes; /* Win32 file attributes. */
char d_name[NAME_MAX + 1]; /* Name within the directory. */
};
#endif
#ifndef DIR_DEFINED
#define DIR_DEFINED
typedef struct DIR DIR;
typedef DIR *LPDIR;
struct DIR {
intptr_t d_handle; /* Value returned by "_findfirst". */
DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
DIRENT d_next; /* DIRENT constructed based on "_findnext". */
};
#endif
/*
** Provide a macro, for use by the implementation, to determine if a
** particular directory entry should be skipped over when searching for
** the next directory entry that should be returned by the readdir().
*/
#ifndef is_filtered
# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
#endif
/*
** Provide the function prototype for the POSIX compatible getenv()
** function. This function is not thread-safe.
*/
extern const char *windirent_getenv(const char *name);
/*
** Finally, we can provide the function prototypes for the opendir(),
** readdir(), and closedir() POSIX functions.
*/
extern LPDIR opendir(const char *dirname);
extern LPDIRENT readdir(LPDIR dirp);
extern INT closedir(LPDIR dirp);
#endif /* defined(WIN32) && defined(_MSC_VER) */
+1 -1
View File
@@ -108,7 +108,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
/*
** Write a single UTF8 character whose value is v into the
** buffer starting at zOut. zOut must be sized to hold at
** least for bytes. Return the number of bytes needed
** least four bytes. Return the number of bytes needed
** to encode the new character.
*/
int sqlite3AppendOneUtf8Character(char *zOut, u32 v){
+2 -1
View File
@@ -195,7 +195,8 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments
| SQLITE_AttachCreate | SQLITE_AttachWrite;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);
+2 -1
View File
@@ -2476,6 +2476,7 @@ case OP_Compare: {
pKeyInfo = pOp->p4.pKeyInfo;
assert( n>0 );
assert( pKeyInfo!=0 );
assert( pKeyInfo->aSortFlags!=0 );
p1 = pOp->p1;
p2 = pOp->p2;
#ifdef SQLITE_DEBUG
@@ -5349,7 +5350,7 @@ case OP_Found: { /* jump, in3, ncycle */
if( rc ) goto no_mem;
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
if( pIdxKey==0 ) goto no_mem;
sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey);
sqlite3VdbeRecordUnpack(r.aMem->n, r.aMem->z, pIdxKey);
pIdxKey->default_rc = 0;
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
sqlite3DbFreeNN(db, pIdxKey);
+1 -1
View File
@@ -301,7 +301,7 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3BlobCompare(const Mem*, const Mem*);
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
void sqlite3VdbeRecordUnpack(int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
+1 -1
View File
@@ -557,7 +557,7 @@ struct PreUpdate {
Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
sqlite3_value **apDflt; /* Array of default values, if required */
u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */
u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */
};
/*
+1 -1
View File
@@ -2163,7 +2163,7 @@ static UnpackedRecord *vdbeUnpackRecord(
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
sqlite3VdbeRecordUnpack(nKey, pKey, pRet);
}
return pRet;
}
+10 -16
View File
@@ -4202,30 +4202,22 @@ void sqlite3VdbeSerialGet(
return;
}
/*
** This routine is used to allocate sufficient space for an UnpackedRecord
** structure large enough to be used with sqlite3VdbeRecordUnpack() if
** the first argument is a pointer to KeyInfo structure pKeyInfo.
** Allocate sufficient space for an UnpackedRecord structure large enough
** to hold a decoded index record for pKeyInfo.
**
** The space is either allocated using sqlite3DbMallocRaw() or from within
** the unaligned buffer passed via the second and third arguments (presumably
** stack space). If the former, then *ppFree is set to a pointer that should
** be eventually freed by the caller using sqlite3DbFree(). Or, if the
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
** before returning.
**
** If an OOM error occurs, NULL is returned.
** The space is allocated using sqlite3DbMallocRaw(). If an OOM error
** occurs, NULL is returned.
*/
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
int nByte; /* Number of bytes required for *p */
u64 nByte; /* Number of bytes required for *p */
assert( sizeof(UnpackedRecord) + sizeof(Mem)*65536 < 0x7fffffff );
nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortFlags!=0 );
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nKeyField + 1;
return p;
@@ -4237,7 +4229,6 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
** contents of the decoded record.
*/
void sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
const void *pKey, /* The binary record */
UnpackedRecord *p /* Populate this structure before returning. */
@@ -4248,6 +4239,7 @@ void sqlite3VdbeRecordUnpack(
u16 u; /* Unsigned loop counter */
u32 szHdr;
Mem *pMem = p->aMem;
KeyInfo *pKeyInfo = p->pKeyInfo;
p->default_rc = 0;
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -4275,6 +4267,8 @@ void sqlite3VdbeRecordUnpack(
** warnings from MSAN. */
sqlite3VdbeMemSetNull(pMem-1);
}
testcase( u == pKeyInfo->nKeyField + 1 );
testcase( u < pKeyInfo->nKeyField + 1 );
assert( u<=pKeyInfo->nKeyField + 1 );
p->nField = u;
}
@@ -5134,6 +5128,7 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
** The easiest way to enforce this limit is to consider only records with
** 13 fields or less. If the first field is an integer, the maximum legal
** header size is (12*5 + 1 + 1) bytes. */
assert( p->pKeyInfo->aSortFlags!=0 );
if( p->pKeyInfo->nAllField<=13 ){
int flags = p->aMem[0].flags;
if( p->pKeyInfo->aSortFlags[0] ){
@@ -5492,7 +5487,6 @@ void sqlite3VdbePreUpdateHook(
i64 iKey2;
PreUpdate preupdate;
const char *zTbl = pTab->zName;
static const u8 fakeSortOrder = 0;
#ifdef SQLITE_DEBUG
int nRealCol;
if( pTab->tabFlags & TF_WithoutRowid ){
@@ -5531,7 +5525,7 @@ void sqlite3VdbePreUpdateHook(
preupdate.pKeyinfo->db = db;
preupdate.pKeyinfo->enc = ENC(db);
preupdate.pKeyinfo->nKeyField = pTab->nCol;
preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder;
preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
+12 -4
View File
@@ -766,7 +766,7 @@ static int vdbeSorterCompareTail(
){
UnpackedRecord *r2 = pTask->pUnpacked;
if( *pbKey2Cached==0 ){
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
*pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
@@ -793,7 +793,7 @@ static int vdbeSorterCompare(
){
UnpackedRecord *r2 = pTask->pUnpacked;
if( !*pbKey2Cached ){
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
*pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
@@ -833,6 +833,7 @@ static int vdbeSorterCompareText(
);
}
}else{
assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
res = res * -1;
@@ -896,6 +897,7 @@ static int vdbeSorterCompareInt(
}
}
assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
if( res==0 ){
if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
@@ -969,7 +971,8 @@ int sqlite3VdbeSorterInit(
assert( pCsr->eCurType==CURTYPE_SORTER );
assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
< 0x7fffffff );
szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField+1);
assert( pCsr->pKeyInfo->nKeyField<=pCsr->pKeyInfo->nAllField );
szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nAllField);
sz = SZ_VDBESORTER(nWorker+1);
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
@@ -983,7 +986,12 @@ int sqlite3VdbeSorterInit(
pKeyInfo->db = 0;
if( nField && nWorker==0 ){
pKeyInfo->nKeyField = nField;
assert( nField<=pCsr->pKeyInfo->nAllField );
}
/* It is OK that pKeyInfo reuses the aSortFlags field from pCsr->pKeyInfo,
** since the pCsr->pKeyInfo->aSortFlags[] array is invariant and lives
** longer that pSorter. */
assert( pKeyInfo->aSortFlags==pCsr->pKeyInfo->aSortFlags );
sqlite3BtreeEnter(pBt);
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt);
sqlite3BtreeLeave(pBt);
@@ -2763,7 +2771,7 @@ int sqlite3VdbeSorterCompare(
assert( r2->nField==nKeyCol );
pKey = vdbeSorterRowkey(pSorter, &nKey);
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2);
sqlite3VdbeRecordUnpack(nKey, pKey, r2);
for(i=0; i<nKeyCol; i++){
if( r2->aMem[i].flags & MEM_Null ){
*pRes = -1;
+2 -1
View File
@@ -3062,7 +3062,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = walIndexReadHdr(pWal, pChanged);
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
walDisableBlocking(pWal);
if( rc==SQLITE_BUSY_TIMEOUT ){
rc = SQLITE_BUSY;
*pCnt |= WAL_RETRY_BLOCKED_MASK;
@@ -3077,6 +3076,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
** WAL_RETRY this routine will be called again and will probably be
** right on the second iteration.
*/
(void)walEnableBlocking(pWal);
if( pWal->apWiData[0]==0 ){
/* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
** We assume this is a transient condition, so return WAL_RETRY. The
@@ -3093,6 +3093,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = SQLITE_BUSY_RECOVERY;
}
}
walDisableBlocking(pWal);
if( rc!=SQLITE_OK ){
return rc;
}
+6 -4
View File
@@ -426,11 +426,11 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
pScan->pWC = pWC;
pScan->k = k+1;
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x20000 ){
if( (sqlite3WhereTrace & 0x20000)!=0 && pScan->nEquiv>1 ){
int ii;
sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
pTerm, pScan->nEquiv);
for(ii=0; ii<pScan->nEquiv; ii++){
sqlite3DebugPrintf("EQUIVALENT TO {%d:%d} (due to TERM-%d):",
pScan->aiCur[0], pScan->aiColumn[0], pTerm->iTerm);
for(ii=1; ii<pScan->nEquiv; ii++){
sqlite3DebugPrintf(" {%d:%d}",
pScan->aiCur[ii], pScan->aiColumn[ii]);
}
@@ -2385,6 +2385,7 @@ void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
}else{
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
}
iTerm = pTerm->iTerm = MAX(iTerm,pTerm->iTerm);
sqlite3DebugPrintf(
"TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x",
iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags);
@@ -3602,6 +3603,7 @@ static int whereUsablePartialIndex(
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
&& !sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, -1)
&& (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
+3
View File
@@ -280,6 +280,9 @@ struct WhereTerm {
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
int iParent; /* Disable pWC->a[iParent] when this term disabled */
int leftCursor; /* Cursor number of X in "X <op> <expr>" */
#ifdef SQLITE_DEBUG
int iTerm; /* Which WhereTerm is this, for debug purposes */
#endif
union {
struct {
int leftColumn; /* Column number of X in "X <op> <expr>" */
+43 -42
View File
@@ -110,7 +110,7 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
}
/*
** This function sets the P4 value of an existing OP_Explain opcode to
** This function sets the P4 value of an existing OP_Explain opcode to
** text describing the loop in pLevel. If the OP_Explain opcode already has
** a P4 value, it is freed before it is overwritten.
*/
@@ -600,7 +600,7 @@ static Expr *removeUnindexableInClauseTerms(
iField = pLoop->aLTerm[i]->u.x.iField - 1;
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
pOrigRhs->a[iField].pExpr = 0;
if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
if( pOrigLhs ){
assert( pOrigLhs->a[iField].pExpr!=0 );
@@ -948,7 +948,7 @@ static int codeAllEqualityTerms(
testcase( pIdx->aiColumn[j]==XN_EXPR );
VdbeComment((v, "%s", explainIndexColumnName(pIdx, j)));
}
}
}
/* Evaluate the equality constraints
*/
@@ -1289,7 +1289,7 @@ static void codeDeferredSeek(
assert( iIdxCur>0 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
pWInfo->bDeferredSeek = 1;
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
@@ -1443,14 +1443,14 @@ static SQLITE_NOINLINE void filterPullDown(
}
/*
** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
** operator. Return true if level pLoop is guaranteed to visit only one
** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
** operator. Return true if level pLoop is guaranteed to visit only one
** row for each key generated for the index.
*/
static int whereLoopIsOneRow(WhereLoop *pLoop){
if( pLoop->u.btree.pIndex->onError
&& pLoop->nSkip==0
&& pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
if( pLoop->u.btree.pIndex->onError
&& pLoop->nSkip==0
&& pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
){
int ii;
for(ii=0; ii<pLoop->u.btree.nEq; ii++){
@@ -1831,37 +1831,37 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
}
}else if( pLoop->wsFlags & WHERE_INDEXED ){
/* Case 4: A scan using an index.
/* Case 4: Search using an index.
**
** The WHERE clause may contain zero or more equality
** terms ("==" or "IN" operators) that refer to the N
** left-most columns of the index. It may also contain
** inequality constraints (>, <, >= or <=) on the indexed
** column that immediately follows the N equalities. Only
** the right-most column can be an inequality - the rest must
** use the "==" and "IN" operators. For example, if the
** index is on (x,y,z), then the following clauses are all
** optimized:
** The WHERE clause may contain zero or more equality
** terms ("==" or "IN" or "IS" operators) that refer to the N
** left-most columns of the index. It may also contain
** inequality constraints (>, <, >= or <=) on the indexed
** column that immediately follows the N equalities. Only
** the right-most column can be an inequality - the rest must
** use the "==", "IN", or "IS" operators. For example, if the
** index is on (x,y,z), then the following clauses are all
** optimized:
**
** x=5
** x=5 AND y=10
** x=5 AND y<10
** x=5 AND y>5 AND y<10
** x=5 AND y=5 AND z<=10
** x=5
** x=5 AND y=10
** x=5 AND y<10
** x=5 AND y>5 AND y<10
** x=5 AND y=5 AND z<=10
**
** The z<10 term of the following cannot be used, only
** the x=5 term:
** The z<10 term of the following cannot be used, only
** the x=5 term:
**
** x=5 AND z<10
** x=5 AND z<10
**
** N may be zero if there are inequality constraints.
** If there are no inequality constraints, then N is at
** least one.
** N may be zero if there are inequality constraints.
** If there are no inequality constraints, then N is at
** least one.
**
** This case is also used when there are no WHERE clause
** constraints but an index is selected anyway, in order
** to force the output order to conform to an ORDER BY.
*/
** This case is also used when there are no WHERE clause
** constraints but an index is selected anyway, in order
** to force the output order to conform to an ORDER BY.
*/
static const u8 aStartOp[] = {
0,
0,
@@ -2015,7 +2015,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
if( zStartAff ){
updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
}
}
nConstraint += nBtm;
testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
if( sqlite3ExprIsVector(pRight)==0 ){
@@ -2201,12 +2201,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( pLevel->iLeftJoin==0 ){
/* If a partial index is driving the loop, try to eliminate WHERE clause
** terms from the query that must be true due to the WHERE clause of
** the partial index.
** the partial index. This optimization does not work on an outer join,
** as shown by:
**
** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
** for a LEFT JOIN.
** 2019-11-02 ticket 623eff57e76d45f6 (LEFT JOIN)
** 2025-05-29 forum post 7dee41d32506c4ae (RIGHT JOIN)
*/
if( pIdx->pPartIdxWhere ){
if( pIdx->pPartIdxWhere && pLevel->pRJ==0 ){
whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
}
}else{
@@ -2216,7 +2217,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** a LEFT JOIN: */
assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
}
/* Record the instruction used to terminate the loop. */
if( (pLoop->wsFlags & WHERE_ONEROW)
|| (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop))
@@ -2605,7 +2606,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
**
** iLoop==1: Code only expressions that are entirely covered by pIdx.
** iLoop==2: Code remaining expressions that do not contain correlated
** sub-queries.
** sub-queries.
** iLoop==3: Code all remaining expressions.
**
** An effort is made to skip unnecessary iterations of the loop.
@@ -2876,7 +2877,7 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
pSubq = pRight->u4.pSubq;
assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 );
sqlite3VdbeAddOp3(
v, OP_Null, 0, pSubq->regResult,
v, OP_Null, 0, pSubq->regResult,
pSubq->regResult + pSubq->pSelect->pEList->nExpr-1
);
}
+23 -12
View File
@@ -931,30 +931,38 @@ static void exprAnalyzeOrTerm(
** 1. The SQLITE_Transitive optimization must be enabled
** 2. Must be either an == or an IS operator
** 3. Not originating in the ON clause of an OUTER JOIN
** 4. The affinities of A and B must be compatible
** 5a. Both operands use the same collating sequence OR
** 5b. The overall collating sequence is BINARY
** 4. The operator is not IS or else the query does not contain RIGHT JOIN
** 5. The affinities of A and B must be compatible
** 6a. Both operands use the same collating sequence OR
** 6b. The overall collating sequence is BINARY
** If this routine returns TRUE, that means that the RHS can be substituted
** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
** This is an optimization. No harm comes from returning 0. But if 1 is
** returned when it should not be, then incorrect answers might result.
*/
static int termIsEquivalence(Parse *pParse, Expr *pExpr){
static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
char aff1, aff2;
CollSeq *pColl;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
if( pExpr->op==TK_IS && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
return 0; /* (4) */
}
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlite3ExprAffinity(pExpr->pRight);
if( aff1!=aff2
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
){
return 0;
return 0; /* (5) */
}
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
if( sqlite3IsBinary(pColl) ) return 1;
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
if( !sqlite3IsBinary(pColl)
&& !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
){
return 0; /* (6) */
}
return 1;
}
/*
@@ -1112,6 +1120,9 @@ static void exprAnalyze(
}
assert( pWC->nTerm > idxTerm );
pTerm = &pWC->a[idxTerm];
#ifdef SQLITE_DEBUG
pTerm->iTerm = idxTerm;
#endif
pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr;
assert( pExpr!=0 ); /* Because malloc() has not failed */
@@ -1219,8 +1230,8 @@ static void exprAnalyze(
if( op==TK_IS ) pNew->wtFlags |= TERM_IS;
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_COPIED;
if( termIsEquivalence(pParse, pDup) ){
assert( pWInfo->pTabList!=0 );
if( termIsEquivalence(pParse, pDup, pWInfo->pTabList) ){
pTerm->eOperator |= WO_EQUIV;
eExtraOp = WO_EQUIV;
}
+20
View File
@@ -0,0 +1,20 @@
/*
** Run this script using "sqlite3" to confirm that the command-line
** shell properly handles the output of double-width characters.
**
** https://sqlite.org/forum/forumpost/008ac80276
*/
.mode box
CREATE TABLE data(word TEXT, description TEXT);
INSERT INTO data VALUES('〈οὐκέτι〉','Greek without dblwidth <...>');
.print .mode box
SELECT * FROM data;
.mode table
.print .mode table
SELECT * FROM data;
.mode qbox
.print .mode qbox
SELECT * FROM data;
.mode column
.print .mode column
SELECT * FROM data;
+1 -4
View File
@@ -97,11 +97,8 @@ do_eqp_test 4.2 {
WHERE t4.y = ?;
} {
QUERY PLAN
|--MATERIALIZE rr
| `--SCAN ft4 VIRTUAL TABLE INDEX 3:
|--SCAN t4
|--BLOOM FILTER ON rr (docid=?)
`--SEARCH rr USING AUTOMATIC COVERING INDEX (docid=?) LEFT-JOIN
`--SCAN ft4 VIRTUAL TABLE INDEX 3: LEFT-JOIN
}
finish_test
+3
View File
@@ -26,6 +26,9 @@ do_catchsql_test func9-120 {
do_execsql_test func9-130 {
SELECT concat_ws(',',1,2,3,4,5,6,7,8,NULL,9,10,11,12);
} {1,2,3,4,5,6,7,8,9,10,11,12}
do_execsql_test func9-131 {
SELECT concat_ws(',',1,2,3,4,'',6,7,8,NULL,9,10,11,12);
} {1,2,3,4,,6,7,8,9,10,11,12}
do_execsql_test func9-140 {
SELECT concat_ws(NULL,1,2,3,4,5,6,7,8,NULL,9,10,11,12);
} {{}}
+80
View File
@@ -1002,6 +1002,21 @@ do_execsql_test join-20.2 {
SELECT * FROM t0 LEFT JOIN t1 WHERE NULL IN (c1);
} {}
# 2025-05-29 forum post 7dee41d32506c4ae
# The complaint in the forum post appears to be the same as for the
# ticket on 2019-11-02, only for RIGHT JOIN instead of LEFT JOIN. Note
# that RIGHT JOIN did not yet exist in SQLite when the ticket was
# written and fixed.
#
do_execsql_test join-20.3 {
DROP TABLE t1;
CREATE TABLE t1(x INT); INSERT INTO t1(x) VALUES(1);
CREATE TABLE t2(y BOOLEAN); INSERT INTO t2(y) VALUES(false);
CREATE TABLE t3(z INT); INSERT INTO t3(z) VALUES(3);
CREATE INDEX t2y ON t2(y) WHERE y;
SELECT quote(z) FROM t1 RIGHT JOIN t2 ON y LEFT JOIN t3 ON y;
} {NULL}
# 2019-11-30 ticket 7f39060a24b47353
# Do not allow a WHERE clause term to qualify a partial index on the
# right table of a LEFT JOIN.
@@ -1289,4 +1304,69 @@ do_execsql_test join-30.3 {
WHERE x <= y;
} {}
# 2025-05-30 https://sqlite.org/forum/forumpost/4fc70203b61c7e12
#
# When converting a USING(x) or NATURAL into the constraint expression
# t1.x==t2.x, mark the t1.x term as EP_CanBeNull if it is the left table
# of a RIGHT JOIN.
#
reset_db
db null NULL
do_execsql_test join-31.1 {
CREATE TABLE t1(c0 INT , c1 INT); INSERT INTO t1(c0, c1) VALUES(NULL,11);
CREATE TABLE t2(c0 INT NOT NULL);
CREATE TABLE t2n(c0 INT);
CREATE TABLE t3(x INT); INSERT INTO t3(x) VALUES(3);
CREATE TABLE t4(y INT); INSERT INTO t4(y) VALUES(4);
CREATE TABLE t5(c0 INT, x INT); INSERT INTO t5 VALUES(NULL, 5);
}
do_execsql_test join-31.2 {
SELECT * FROM t2 RIGHT JOIN t3 ON true LEFT JOIN t1 USING(c0);
} {NULL 3 NULL}
do_execsql_test join-31.3 {
SELECT * FROM t2 RIGHT JOIN t3 ON true NATURAL LEFT JOIN t1;
} {NULL 3 NULL}
do_execsql_test join-31.4 {
SELECT * FROM t2n RIGHT JOIN t3 ON true LEFT JOIN t1 USING(c0);
} {NULL 3 NULL}
do_execsql_test join-31.5 {
SELECT * FROM t5 LEFT JOIN t1 USING(c0);
} {NULL 5 NULL}
do_execsql_test join-31.6 {
SELECT * FROM t3 LEFT JOIN t2 ON true LEFT JOIN t1 USING(c0);
} {3 NULL NULL}
do_execsql_test join-31.7 {
SELECT * FROM t3 LEFT JOIN t2 ON true NATURAL LEFT JOIN t1;
} {3 NULL NULL}
do_execsql_test join-31.8 {
SELECT * FROM t3 LEFT JOIN t2 ON true JOIN t4 ON true NATURAL LEFT JOIN t1;
} {3 NULL 4 NULL}
# 2025-06-16 https://sqlite.org/forum/forumpost/68f29a2005
#
# The transitive-constraint optimization was not working for RIGHT JOIN.
#
reset_db
db null NULL
do_execsql_test join-32.1 {
CREATE TABLE t0(w INT);
CREATE TABLE t1(x INT);
CREATE TABLE t2(y INT UNIQUE);
CREATE VIEW v0(z) AS SELECT CAST(x AS INT) FROM t1 LEFT JOIN t2 ON true;
INSERT INTO t1(x) VALUES(123);
INSERT INTO t2(y) VALUES(NULL);
}
do_execsql_test join-32.2 {
SELECT *
FROM t0 JOIN v0 ON w=z
RIGHT JOIN t1 ON true
INNER JOIN t2 ON y IS z;
} {NULL NULL 123 NULL}
do_execsql_test join-32.3 {
SELECT *
FROM t0 JOIN v0 ON w=z
RIGHT JOIN t1 ON true
INNER JOIN t2 ON +y IS z;
} {NULL NULL 123 NULL}
finish_test
+70
View File
@@ -341,4 +341,74 @@ do_execsql_test 13.4 {
GROUP BY a1.a ORDER BY 1;
} {-1480 240 480}
#-------------------------------------------------------------------------
# 2025-05-30
# https://sqlite.org/forum/forumpost/5028c785b6
#
reset_db
do_execsql_test 14.0 {
CREATE TABLE t1(c0 INT);
CREATE TABLE t2(c0 BLOB);
CREATE TABLE t3(c0 BLOB);
CREATE TABLE t4(c4 BLOB);
INSERT INTO t1(c0) VALUES(0);
INSERT INTO t3(c0) VALUES('0');
}
do_execsql_test 14.1.1 {
SELECT * FROM t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3;
} {0}
do_execsql_test 14.1.2 {
SELECT * FROM t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3 FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.1.3 {
SELECT * FROM (t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3) FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.1.4 {
SELECT *
FROM (t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3) AS qq FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.2.1 {
SELECT * FROM t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1;
} {0}
do_execsql_test 14.2.2 {
SELECT * FROM t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1 FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.2.3 {
SELECT * FROM (t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1) FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.2.4 {
SELECT *
FROM (t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1) AS qq FULL JOIN t4 ON true;
} {0 {}}
# 2025-06-01
#
reset_db
do_execsql_test 15.1 {
CREATE TABLE t0(c0);
CREATE TABLE t1(c0);
CREATE TABLE t2(c0);
INSERT INTO t0 VALUES ('1.0');
INSERT INTO t2(c0) VALUES (9);
SELECT t0.c0,t2.c0 FROM (SELECT CAST(t0.c0 as REAL) AS c0 FROM t0) as subquery NATURAL LEFT JOIN t1 NATURAL JOIN t0 RIGHT JOIN t2 ON 1;
} {1.0 9}
do_execsql_test 15.2 {
CREATE TABLE x1(x COLLATE nocase);
CREATE TABLE x2(x);
CREATE TABLE x3(x);
CREATE TABLE t4(y);
INSERT INTO x1 VALUES('ABC');
INSERT INTO x3 VALUES('abc');
SELECT lower(x), quote(y) FROM x1 LEFT JOIN x2 USING (x) JOIN x3 USING (x) FULL JOIN t4;
} {abc NULL}
finish_test
+1 -1
View File
@@ -1113,7 +1113,7 @@ do_execsql_test json101-21.26 {
do_execsql_test json101-21.27 {
WITH c(x,y) AS (VALUES('a',1),('b',2.0),('c',NULL),(NULL,'three'),('e','four'))
SELECT json_group_object(x,y) FROM c;
} {{{"a":1,"b":2.0,"c":null,:"three","e":"four"}}}
} {{{"a":1,"b":2.0,"c":null,"e":"four"}}}
# 2023-10-09 https://sqlite.org/forum/forumpost/b25edc1d46
# UAF due to JSON cache overflow
+3
View File
@@ -96,6 +96,9 @@ do_test 1.8 {
list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg
} {1 SQLITE_ERROR_SNAPSHOT}
db3 close
db2 close
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
+12 -3
View File
@@ -25,6 +25,7 @@ Other options include:
--help Show this help screen.
--lean "Lean" mode.
--lookaside N SZ Lookahead uses N slots of SZ bytes each.
--osmalloc Use the OS native malloc() instead of MEMSYS5
--pagesize N Use N as the page size.
--quiet | -q "Quite". Put results in file but don't pop up editor
--size N Change the test size. 100 means 100%. Default: 5.
@@ -40,7 +41,8 @@ set cc gcc
set testset mix1
set dryrun 0
set quiet 0
set speedtestflags {--shrink-memory --reprepare --stats --heap 40000000 64}
set osmalloc 0
set speedtestflags {--shrink-memory --reprepare --stats}
lappend speedtestflags --journal wal --size 5
for {set i 0} {$i<[llength $argv]} {incr i} {
@@ -92,6 +94,10 @@ for {set i 0} {$i<[llength $argv]} {incr i} {
--dryrun {
set dryrun 1
}
-osmalloc -
--osmalloc {
set osmalloc 1
}
-? -
-help -
--help {
@@ -139,10 +145,13 @@ for {set i 0} {$i<[llength $argv]} {incr i} {
if {[lsearch -glob $cflags -O*]<0} {
lappend cflags -Os
}
if {[lsearch -glob $cflags -DSQLITE_ENABLE_MEMSYS*]<0} {
if {!$osmalloc} {
append speedtestflags { --heap 40000000 64}
}
if {!$osmalloc && [lsearch -glob $cflags {-DSQLITE_ENABLE_MEMSYS*}]<0} {
lappend cflags -DSQLITE_ENABLE_MEMSYS5
}
if {[lsearch -glob $cflags -DSQLITE_ENABLE_RTREE*]<0} {
if {[lsearch -glob $cflags {-DSQLITE_ENABLE_RTREE*}]<0} {
lappend cflags -DSQLITE_ENABLE_RTREE
}
if {$srcfile==""} {
+108 -45
View File
@@ -9,7 +9,7 @@
#
#***********************************************************************
# This file implements regression tests for TCL interface to the
# SQLite library.
# SQLite library.
#
# Actually, all tests are based on the TCL interface, so the main
# interface is pretty well tested. This file contains some addition
@@ -121,7 +121,7 @@ ifcapable {complete} {
do_test tcl-1.14 {
set v [catch {db eval} msg]
lappend v $msg
} {1 {wrong # args: should be "db eval ?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?"}}
} {1 {wrong # args: should be "db eval ?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?"}}
do_test tcl-1.15 {
set v [catch {db function} msg]
lappend v $msg
@@ -359,6 +359,19 @@ do_test tcl-9.3 {
execsql {SELECT typeof(ret_int())}
} {integer}
proc breakAsNullUdf args {
if {"1" eq [lindex $args 0]} {return -code break}
}
do_test tcl-9.4 {
db function banu breakAsNullUdf
execsql {SELECT typeof(banu()), typeof(banu(1))}
} {text null}
do_test tcl-9.5 {
db nullvalue banunull
db eval {SELECT banu(), banu(1)}
} {{} banunull}
# Recursive calls to the same user-defined function
#
ifcapable tclvar {
@@ -465,7 +478,7 @@ do_test tcl-10.13 {
db eval {SELECT * FROM t4}
} {1 2 5 6 7}
# Now test that [db transaction] commands may be nested with
# Now test that [db transaction] commands may be nested with
# the expected results.
#
do_test tcl-10.14 {
@@ -475,7 +488,7 @@ do_test tcl-10.14 {
INSERT INTO t4 VALUES('one');
}
catch {
catch {
db transaction {
db eval { INSERT INTO t4 VALUES('two') }
db transaction {
@@ -674,11 +687,11 @@ do_test tcl-15.5 {
} {0}
# 2017-06-26: The --withoutnulls flag to "db eval".
# 2017-06-26: The -withoutnulls flag to "db eval".
#
# In the "db eval --withoutnulls SQL ARRAY" form, NULL results cause the
# corresponding array entry to be unset. The default behavior (without
# the -withoutnulls flags) is for the corresponding array value to get
# In the "db eval -withoutnulls SQL TARGET" form, NULL results cause the
# corresponding target entry to be unset. The default behavior (without
# the -withoutnulls flags) is for the corresponding target value to get
# the [db nullvalue] string.
#
catch {db close}
@@ -720,64 +733,64 @@ reset_db
proc add {a b} { return [expr $a + $b] }
proc ret {a} { return $a }
db function add_i -returntype integer add
db function add_i -returntype integer add
db function add_r -ret real add
db function add_t -return text add
db function add_b -returntype blob add
db function add_a -returntype any add
db function add_t -return text add
db function add_b -returntype blob add
db function add_a -returntype any add
db function ret_i -returntype int ret
db function ret_i -returntype int ret
db function ret_r -returntype real ret
db function ret_t -returntype text ret
db function ret_b -returntype blob ret
db function ret_a -r any ret
db function ret_t -returntype text ret
db function ret_b -returntype blob ret
db function ret_a -r any ret
do_execsql_test 17.0 {
SELECT quote( add_i(2, 3) );
SELECT quote( add_r(2, 3) );
SELECT quote( add_t(2, 3) );
SELECT quote( add_b(2, 3) );
SELECT quote( add_a(2, 3) );
SELECT quote( add_r(2, 3) );
SELECT quote( add_t(2, 3) );
SELECT quote( add_b(2, 3) );
SELECT quote( add_a(2, 3) );
} {5 5.0 '5' X'35' 5}
do_execsql_test 17.1 {
SELECT quote( add_i(2.2, 3.3) );
SELECT quote( add_r(2.2, 3.3) );
SELECT quote( add_t(2.2, 3.3) );
SELECT quote( add_b(2.2, 3.3) );
SELECT quote( add_a(2.2, 3.3) );
SELECT quote( add_r(2.2, 3.3) );
SELECT quote( add_t(2.2, 3.3) );
SELECT quote( add_b(2.2, 3.3) );
SELECT quote( add_a(2.2, 3.3) );
} {5.5 5.5 '5.5' X'352E35' 5.5}
do_execsql_test 17.2 {
SELECT quote( ret_i(2.5) );
SELECT quote( ret_r(2.5) );
SELECT quote( ret_t(2.5) );
SELECT quote( ret_b(2.5) );
SELECT quote( ret_a(2.5) );
SELECT quote( ret_r(2.5) );
SELECT quote( ret_t(2.5) );
SELECT quote( ret_b(2.5) );
SELECT quote( ret_a(2.5) );
} {2.5 2.5 '2.5' X'322E35' 2.5}
do_execsql_test 17.3 {
SELECT quote( ret_i('2.5') );
SELECT quote( ret_r('2.5') );
SELECT quote( ret_t('2.5') );
SELECT quote( ret_b('2.5') );
SELECT quote( ret_a('2.5') );
SELECT quote( ret_r('2.5') );
SELECT quote( ret_t('2.5') );
SELECT quote( ret_b('2.5') );
SELECT quote( ret_a('2.5') );
} {2.5 2.5 '2.5' X'322E35' '2.5'}
do_execsql_test 17.4 {
SELECT quote( ret_i('abc') );
SELECT quote( ret_r('abc') );
SELECT quote( ret_t('abc') );
SELECT quote( ret_b('abc') );
SELECT quote( ret_a('abc') );
SELECT quote( ret_r('abc') );
SELECT quote( ret_t('abc') );
SELECT quote( ret_b('abc') );
SELECT quote( ret_a('abc') );
} {'abc' 'abc' 'abc' X'616263' 'abc'}
do_execsql_test 17.5 {
SELECT quote( ret_i(X'616263') );
SELECT quote( ret_r(X'616263') );
SELECT quote( ret_t(X'616263') );
SELECT quote( ret_b(X'616263') );
SELECT quote( ret_a(X'616263') );
SELECT quote( ret_r(X'616263') );
SELECT quote( ret_t(X'616263') );
SELECT quote( ret_b(X'616263') );
SELECT quote( ret_a(X'616263') );
} {'abc' 'abc' 'abc' X'616263' X'616263'}
do_test 17.6.1 {
@@ -848,21 +861,70 @@ do_catchsql_test 19.911 {
} {1 {invalid command name "bind_fallback_does_not_exist"}}
db bind_fallback {}
#-------------------------------------------------------------------------
# 2025-05-05: the -asdict eval flag
#
do_test 20.0 {
execsql {CREATE TABLE tad(a,b)}
execsql {INSERT INTO tad(a,b) VALUES('aa','bb'),('AA','BB')}
db eval -asdict {
SELECT a, b FROM tad WHERE 0
} D {}
set D
} {* {a b}}
do_test 20.1 {
unset D
set i 0
set res {}
set colNames {}
db eval -asdict {
SELECT a, b FROM tad ORDER BY a
} D {
dict set D i [incr i]
lappend res $i [dict get $D a] [dict get $D b]
if {1 == $i} {
set colNames [dict get $D *]
}
}
lappend res $colNames
unset D
set res
} {1 AA BB 2 aa bb {a b}}
do_test 20.2 {
set res {}
db eval -asdict -withoutnulls {
SELECT n, a, b FROM (
SELECT 1 as n, 'aa' as a, NULL as b
UNION ALL
SELECT 2 as n, NULL as a, 'bb' as b
)
ORDER BY n
} D {
dict unset D *
lappend res [dict values $D]
}
unset D
execsql {DROP TABLE tad}
set res
} {{1 aa} {2 bb}}
#-------------------------------------------------------------------------
do_test 21.0 {
db transaction {
db close
}
} {}
do_test 20.1 {
do_test 21.1 {
sqlite3 db test.db
set rc [catch {
db eval {SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3} { db close }
} msg]
list $rc $msg
} {1 {invalid command name "db"}}
proc closedb {} {
db close
@@ -874,7 +936,7 @@ sqlite3 db test.db
db func closedb closedb
db func func1 func1
do_test 20.2 {
do_test 21.2 {
set rc [catch {
db eval {
SELECT closedb(),func1() UNION ALL SELECT 20,30 UNION ALL SELECT 30,40
@@ -884,9 +946,10 @@ do_test 20.2 {
} {0 {10 1 20 30 30 40}}
sqlite3 db :memory:
do_test 21.1 {
do_test 22.1 {
catch {db eval {SELECT 1 2 3;}} msg
db erroroffset
} {9}
finish_test
+9 -8
View File
@@ -458,16 +458,17 @@ proc trd_fuzztest_data {buildname} {
if {$::tcl_platform(platform) eq "windows"} {
return [list fuzzcheck.exe $lFuzzDb]
} elseif {[lsearch $sanBuilds $buildname]>=0} {
return [list [trd_get_bin_name fuzzcheck] $lFuzzDb \
[trd_get_bin_name fuzzcheck-asan] $lFuzzDb \
[trd_get_bin_name fuzzcheck-ubsan] $lFuzzDb \
{sessionfuzz run} $lSessionDb]
} else {
return [list [trd_get_bin_name fuzzcheck] $lFuzzDb \
{sessionfuzz run} $lSessionDb]
set lRet [list [trd_get_bin_name fuzzcheck] $lFuzzDb]
if {[lsearch $sanBuilds $buildname]>=0} {
lappend lRet [trd_get_bin_name fuzzcheck-asan] $lFuzzDb
if {$::tcl_platform(os) ne "OpenBSD"} {
lappend lRet [trd_get_bin_name fuzzcheck-ubsan] $lFuzzDb
}
}
lappend lRet {sessionfuzz run} $lSessionDb
return $lRet
}
}
+21
View File
@@ -401,4 +401,25 @@ do_test vacuum-10.1 {
} {}
do_test vacuum-10.2 { execsql VACUUM } {}
# Verify that VACUUM still works if ATTACH is disabled.
#
do_execsql_test vacuum-11.1 {
PRAGMA page_size=1024;
VACUUM;
PRAGMA page_size;
} {1024}
sqlite3_db_config db ATTACH_CREATE 0
do_execsql_test vacuum-11.2 {
PRAGMA page_size=2048;
VACUUM;
PRAGMA page_size;
} {2048}
sqlite3_db_config db ATTACH_CREATE 1
sqlite3_db_config db ATTACH_WRITE 0
do_execsql_test vacuum-11.3 {
PRAGMA page_size=4096;
VACUUM;
PRAGMA page_size;
} {4096}
finish_test
+2
View File
@@ -90,6 +90,8 @@ tvfs delete
# but other operations do not use the retry mechanism.
#
reset_db
db close
sqlite3 db test.db -fullmutex 1
do_execsql_test 2.0 {
CREATE TABLE t1(a, b);
+104
View File
@@ -0,0 +1,104 @@
# 2025 May 30
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# TESTRUNNER: slow
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix walsetlk_recover
ifcapable !wal {finish_test ; return }
# ifcapable !setlk_timeout {finish_test ; return }
do_execsql_test 1.0 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
} {wal}
db_save_and_close
db_restore
testfixture_nb myvar {
testvfs tvfs -fullshm 1
sqlite3 db test.db -vfs tvfs
tvfs script vfs_callback
tvfs filter xRead
set ::done 0
proc vfs_callback {method file args} {
if {$::done==0 && [string match *wal $file]} {
after 4000
set ::done 1
}
return "SQLITE_OK"
}
db eval {
SELECT * FROM t1
}
db close
}
# Give the [testfixture_nb] command time to start
after 1000 {set xyz 1}
vwait xyz
testvfs tvfs -fullshm 1
sqlite3 db test.db -vfs tvfs
tvfs script sleep_callback
tvfs filter xSleep
set ::sleep_count 0
proc sleep_callback {args} {
incr ::sleep_count
}
sqlite3 db test.db -vfs tvfs
db timeout 500
set tm [lindex [time {
catch {
db eval {SELECT * FROM t1}
} msg
}] 0]
do_test 1.2 { set ::msg } {database is locked}
do_test 1.3.($::tm) { expr $::tm>400000 && $::tm<2000000 } 1
vwait myvar
do_execsql_test 1.4 {
SELECT * FROM t1
} {1 2 3 4 5 6}
db close
tvfs delete
# All SQLite builds should pass the tests above. SQLITE_ENABLE_SETLK_TIMEOUT=1
# builds do so without calling the VFS xSleep method.
if {$::sqlite_options(setlk_timeout)==1} {
do_test 1.5.1 {
set ::sleep_count
} 0
} else {
do_test 1.5.2 {
expr $::sleep_count>0
} 1
}
finish_test
+109
View File
@@ -0,0 +1,109 @@
# 2025 May 30
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# TESTRUNNER: slow
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix walsetlk_snapshot
ifcapable !wal {finish_test ; return }
ifcapable !snapshot {finish_test; return}
db close
testvfs tvfs -fullshm 1
sqlite3 db test.db -vfs tvfs
tvfs script sleep_callback
tvfs filter xSleep
set ::sleep_count 0
proc sleep_callback {args} {
incr ::sleep_count
}
do_execsql_test 1.0 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
} {wal}
do_test 1.1 {
db eval BEGIN
set ::snap [sqlite3_snapshot_get db main]
db eval {
INSERT INTO t1 VALUES(7, 8);
COMMIT;
}
} {}
testfixture_nb myvar {
testvfs tvfs -fullshm 1
sqlite3 db test.db -vfs tvfs
tvfs script vfs_callback
tvfs filter {xWrite}
set ::done 0
proc vfs_callback {args} {
if {$::done==0} {
after 4000
set ::done 1
}
return "SQLITE_OK"
}
db eval {
PRAGMA wal_checkpoint;
}
db close
}
# Give the [testfixture_nb] command time to start
after 1000 {set xyz 1}
vwait xyz
db timeout 500
set tm [lindex [time {
catch {
db eval BEGIN
sqlite3_snapshot_open db main $::snap
} msg
}] 0]
do_test 1.2 { set ::msg } {SQLITE_BUSY}
do_test 1.3.($::tm) { expr $::tm<2000000 } 1
do_execsql_test 1.4 {
SELECT * FROM t1
} {1 2 3 4 5 6 7 8}
sqlite3_snapshot_free $::snap
vwait myvar
# All SQLite builds should pass the tests above. SQLITE_ENABLE_SETLK_TIMEOUT=1
# builds do so without calling the VFS xSleep method.
if {$::sqlite_options(setlk_timeout)==1} {
do_test 1.5.1 {
set ::sleep_count
} 0
} else {
do_test 1.5.2 {
expr $::sleep_count>0
} 1
}
finish_test
+5 -5
View File
@@ -2023,10 +2023,10 @@ static char *msort(
list = NEXT(list);
NEXT(ep) = 0;
for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
ep = merge(ep,set[i],cmp,offset);
ep = merge(set[i],ep,cmp,offset);
set[i] = 0;
}
set[i] = ep;
set[i] = merge(set[i],ep,cmp,offset);
}
ep = 0;
for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset);
@@ -4035,10 +4035,10 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
}
}
if( lhsdirect ){
sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
lemon_sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
}else{
rc = 1;
sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
lemon_sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
}
append_str(0,0,0,0);
@@ -5925,7 +5925,7 @@ struct state **State_arrayof(void)
PRIVATE unsigned confighash(struct config *a)
{
unsigned h=0;
h = h*571 + a->rp->index*37 + a->dot;
h = a->rp->index*37 + a->dot;
return h;
}
+1 -1
View File
@@ -62,7 +62,7 @@ while {1} {
if {[regexp {^# *include "sqlite} $lx]} {
set lx "/* $lx */"
}
if {[regexp {^# *include "test_windirent.h"} $lx]} {
if {[regexp {^# *include "windirent.h"} $lx]} {
set lx "/* $lx */"
}
set lx [string map [list __declspec(dllexport) {}] $lx]
+1 -1
View File
@@ -56,7 +56,7 @@ proc write_one_file {content} {
set label $filecnt
}
set out [open sqlite3-$label.c w]
fconfigure $out -translation lf
fconfigure $out -translation text
puts -nonewline $out $content
close $out
puts $::out1 "#include \"sqlite3-$filecnt.c\""
+2 -1
View File
@@ -1538,7 +1538,7 @@ static void originSide(SQLiteRsync *p){
sqlite3_finalize(pInsHash);
pCkHash = 0;
pInsHash = 0;
if( mxHash<p->nPage ){
if( mxHash<=p->nPage ){
runSql(p, "WITH RECURSIVE c(n) AS"
" (VALUES(%d) UNION ALL SELECT n+1 FROM c WHERE n<%d)"
" INSERT INTO badHash SELECT n, 1 FROM c",
@@ -1797,6 +1797,7 @@ static void replicaSide(SQLiteRsync *p){
closeDb(p);
break;
}
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
runSql(p, "ATTACH %Q AS 'replica'", p->zReplica);
if( p->wrongEncoding ){
p->wrongEncoding = 0;
+1 -1
View File
@@ -752,7 +752,7 @@ void sha1sum_file(const char *zFilename, char *zCksum){
SHA1Final(zResult, &ctx);
DigestToBase16(zResult, zCksum, 20);
}
/*
** Decode a fossilized string in-place.
*/
+9 -9
View File
@@ -10,7 +10,7 @@ if uname | grep -i openbsd ; then
WARNING_ANDROID_OPTS=-Wall
else
# Use these for testing on Linux and Mac OSX:
WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long"
WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -Wno-array-bounds"
gccvers=`gcc -v 2>&1 | grep '^gcc version'`
if test "$gccvers" '<' 'gcc version 6'
then
@@ -22,15 +22,15 @@ fi
rm -f sqlite3.c
make sqlite3.c
echo '********** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***'
echo '********** ' Options: $WARNING_OPTS
echo '**** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***'
echo '****' $WARNING_OPTS
gcc -c $WARNING_OPTS -std=c89 \
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
-DSQLITE_ENABLE_FTS5 \
sqlite3.c
if test x`uname` = 'xLinux'; then
echo '********** Android configuration ******************************'
echo '********** ' Options: $WARNING_ANDROID_OPTS
echo '**** Android configuration ******************************'
echo '****' $WARNING_ANDROID_OPTS
gcc -c \
-DSQLITE_HAVE_ISNAN \
-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \
@@ -52,13 +52,13 @@ gcc -c \
$WARNING_ANDROID_OPTS \
-Os sqlite3.c shell.c
fi
echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
echo '********** ' Options: $WARNING_OPTS
echo '**** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
echo '****' $WARNING_OPTS
gcc -c $WARNING_OPTS -std=c89 \
-ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
sqlite3.c
echo '********** Optimized -O3. Includes FTS4/5, GEOPOLY, JSON1 ******'
echo '********** ' Options: $WARNING_OPTS
echo '**** Optimized -O3. Includes FTS4/5, GEOPOLY, JSON1 ******'
echo '****' $WARNING_OPTS
gcc -O3 -c $WARNING_OPTS -std=c89 \
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
-DSQLITE_ENABLE_FTS5 \